The registry is the module that is used for configuration of the service bus. Topics, namespaces and subscriptions are registered with this module, and the registry is accessible for all other modules. There's a separate set of functions just to support the subscriber agent.
Message flow
Topics, namespaces and subscriptions are registered to support the message flow from message intake to message delivery.
Configuration
The order of configuration of the registry is like this:
- Namespace
- Topic
- Subscriber
First the namespace is added. Then a topic is added, and the namespace's ID is used to point the topic to the namespace. Finally a subscriber can be added, this can be done from client agent.
Namespaces are the core of the registry. Topic subscribers are registered in namespaces, and the namespaces are routing messages to subscriber canisters. Namespaces can be used to create collections of topics that are related (by topics or subscribers), and as load balancers if there's a large amount of subscribers.
fn namespace_register(namespace: Namespace)
Register a new namespace.
Parameters
namespace: A record of the type Namespace
Return
Result<String, String>
- Ok: Namespace ID
- Err: "Could not register the namespace"
fn namespace_unregister(namespace_id: String)
Unregister a namespace.
Parameters
namespace_id: The ID string of the namespace to remove
Return
Result<String, String>
- Ok: The removed namespace ID
- Err: "Could not unregister the namespace"
async fn namespace(namespace_id: String)
Get the namespace with a specific ID.
Parameters
namespace_id: The ID string of the namespace to get
Return
Namespaces
- record {
id: text;
name: text;
description: text;
subscribers: vec text;
active: bool;
};
async fn get_subscriptions()
Get all namespaces
Parameters
(none)
Return
Vec<Namespaces>
- vec {
record {
id: text;
name: text;
description: text;
subscribers: vec text;
active: bool;
}
};
fn namespace_register_subscriber(namespace_id: String, subscriber_id: String)
Add a created, unassigned subscriber to a namespace.
Parameters
namespace_id: The ID string of the namespace
subscriber_id: The ID string of the subscriber to add
Return
Result<String, String>
- Ok: The namespace ID
- Err: "Could not add subscriber"
fn namespace_subscriber_size(namespace_id: String)
Get the number of subscribers a specific namespace has
Parameters
namespace_id: The ID string of the namespace
Return
usize
fn namespaces_by_topic(topic_id: String)
Get all namespaces registered for a specific topic
Parameters
topic_id: The ID string of the topic
Return
Vec<Namespaces>
- vec {
record {
id: text;
name: text;
description: text;
subscribers: vec text;
active: bool;
}
};
fn namespace_by_subscriber(subscriber_id: String)
Get the namespace of a specific subscriber is subscribing to
Parameters
subscriber_id: The ID string of the subscriber
Return
Namespaces
- record {
id: text;
name: text;
description: text;
subscribers: vec text;
active: bool;
};
Topics are the data channel the subscribers are subscribing to. The message intake system will forward data messages to topics.
fn topic_register(topic: Topic)
Register a new topic
Parameters
namespace: A record of the type Topic
Return
Result<String, String>
- Ok: Topic ID
- Err: "Could not register the topic"
fn topic_unregister(topic_id: String)
Unregister a topic
Parameters
topic_id: The ID string of the topic to remove
Return
Result<String, String>
- Ok: The removed topic ID
- Err: "Could not unregister topic"
fn topic(topic_id: String)
Get the topic with a specific ID.
Parameters
topic_id: The ID string of the topic to get
Return
Topics
- record {
id: text;
name: text;
description: text;
namespaces: vec text;
active: bool;
};
fn topics()
Get all topics
Parameters
(none)
Return
Vec<Topics>
- vec {
record {
id: text;
name: text;
description: text;
namespaces: vec text;
active: bool;
}
};
fn topic_by_name(topic_name: String)
Get a topic by it's name. Clients are identifying topics by name, and not by ID, which makes this function useful.
Parameters
topic_name: The name of the topic to get
Return
Topics
- record {
id: text;
name: text;
description: text;
namespaces: vec text;
active: bool;
};
Subscribers are the receivers of messages distributed through the service bus. Subscribers can subscribe to topics, and the topic messages are delivered to the callback function specified by the subscriber.
pub async fn subscriber_register(subscriber: Subscribers)
Register a new subscriber
Parameters
subscriber: A record of the type Subscribers
Return
Result<String, String>
- Ok: subscriber ID
- Err: "Could not unregister topic"
fn subscriber_unregister(subscriber_id: String)
Unregister a subscriber
Parameters
subscriber_id: The ID string of the subscriber to remove
Return
Result<String, String>
- Ok: The removed subscriber ID
- Err: "Could not unregister subscriber"
fn subscriber(subscriber_id: String)
Get the subscriber with a specific ID.
Parameters
subscriber_id: The ID string of the subscriber to get
Return
Subscribers
- record {
id: text;
canister_id: text;
callback: text;
name: text;
description: text;
topic: text;
namespaces: vec text;
active: bool;
};
fn subscribers()
Get all topics
Parameters
(none)
Return
Vec<Subscribers>
- vec {
record {
id: text;
canister_id: text;
callback: text;
name: text;
description: text;
topic: text;
namespaces: vec text;
active: bool;
}
};
async fn set_subscription(topic_name: String, callback: String)
Register topic subscription. Messages will be delivered to the callback function.
Parameters
topic_name: The name (string) of the topic to subscribe to
callback: The function the messages will be delivered to
Return
Result<String, String>
- Ok: The subscription ID
- Err: "Could not register the subscriber"
async fn unset_subscription(subscription_id: String)
Unregister topic subscription.
Parameters
subscription_id: The ID string of the subscription to remove
Return
Result<String, String>
- Ok: The removed subscription ID
- Err: "Could not unregister the subscriber"
async fn get_subscription(subscription_id: String)
Get the subscription with a specific ID.
Parameters
(none)
Return
Subscriber
- record {
id: text;
canister_id: text;
callback: text;
name: text;
description: text;
topic: text;
namespace: text;
active: bool;
};
async fn get_subscriptions()
Get all subscriptions registered to this canister.
Parameters
(none)
Return
Vec<Subscribers>
- vec {
record {
id: text;
canister_id: text;
callback: text;
name: text;
description: text;
topic: text;
namespace: text;
active: bool;
}
};
The purpose of the agent functions is to expose a subset of the registry functionality to external agents.
pub async fn agent_subscribe(topic_name: String, callback: String)
Allows an agent to add a subscription, by providing topic and callback information
Parameters
topic_name: The name (string) of the topic to subscribe to
callback: The function the messages will be delivered to
Return
CallStringResponse
- record {
result: text;
};
pub async fn agent_unsubscribe(subscription_id: String)
Unregister topic subscription.
Parameters
subscription_id: The ID string of the subscription to remove
Return
Result<String, String>
- Ok: The removed subscription ID
- Err: "Could not unregister the subscriber"
pub async fn agent_subscriber(subscriber_id: String)
Get the subscription with a specific ID.
Parameters
subscriber_id: The ID string of the subscription to remove
Return
CallSubscriberResponse
- record {
result: Subscribers;
};
pub async fn agent_subscriptions()
Get all subscriptions registered to this canister.
Parameters
(none)
Return
CallSubscribersResponse
- record {
result: Subscribers;
};
To Do
The demo dapp implements the functionality of the registry, and is used for both testing and demonstration of how to implement the agent. This demo dapp is for Rust developers, there will also be a Motoko demo dapp (release TBD).