-
Notifications
You must be signed in to change notification settings - Fork 5
Building Your Own Plugin
ServiceStack.Webhooks supports the ability to fit within any architecture you may have your services deployed in.
It's as simple as providing your own IEventSink and ISubscriptionStore, and plugging it into your WebhookFeature
.
Developing your own SubscriptionStore plugin (ISubscriptionStore
There is not much to be said about creating your own 'ISubscriptionStore' it is very straightforward to create an adapter to a data store of your choice. It just has a simple CRUD-like interface that you'll need to implement.
public interface ISubscriptionStore
{
/// <summary>
/// Returns the identity of the added subscription
/// </summary>
string Add(WebhookSubscription subscription);
/// <summary>
/// Returns all subscription for the specified userId
/// </summary>
List<WebhookSubscription> Find(string userId);
/// <summary>
/// Gets the subscription for the specified user and eventName
/// </summary>
WebhookSubscription Get(string userId, string eventName);
/// <summary>
/// Gets the specified subscription
/// </summary>
WebhookSubscription Get(string subscriptionId);
/// <summary>
/// Updates the specified subscription
/// </summary>
void Update(string subscriptionId, WebhookSubscription subscription);
/// <summary>
/// Deletes the specified subscription
/// </summary>
void Delete(string subscriptionId);
/// <summary>
/// Returns all subscription configurations for all users for the specified event,
/// and optionally whether they are currently active or not
/// </summary>
List<SubscriptionRelayConfig> Search(string eventName, bool? isActive);
/// <summary>
/// Adds a new delivery result to the subscription
/// </summary>
void Add(string subscriptionId, SubscriptionDeliveryResult result);
/// <summary>
/// Returns the top specified delivery results for the specified subscription (in descending date order)
/// </summary>
List<SubscriptionDeliveryResult> Search(string subscriptionId, int top);
}
Simply:
- Install the nuget package 'Webhooks.Interfaces'.
- Implement the 'ISubscriptionStore' interface.
- See the Installation notes below.
Developing your own EventSink plugin (IEventSink)
However, creating your own 'IEventSink' is not quite so straightforward.
Implementing the interface is a doddle, but the infrastructure you have behind it isn't.
public interface IEventSink
{
/// <summary>
/// Writes a new event with data
/// </summary>
void Write(string eventName, Dictionary<string, string> data);
}
Before you start cutting any code, you will need a plan for your new IEventSink
plugin.
In general the sink plugin is going to need two parts:
- Sink - The first part is generally going to need to use some (asynchronous) and reliable, messaging technology that won't fail, and that 'stores-and-forwards' the raised event
- Relay - the second part picks up the event and delivers it to all registered subscribers (dealing with network latency, availability, network connectivity issues and retries etc.).
There are many ways to do this combo, but commonly a ServiceBus or Queue is used as the 'Sink' part, and then some another compute service (i.e separate elastic process) performs the 'Relay' part.
You can see an example of that in the ServiceStack.Webooks.Azure plugin. But there are many others ways to solve this problem even with Azure.
The choice is entirely yours.
However, please consider the following in your design:
- All events that are raised from your service, will be passed (synchronously) from your service code to the configured Sink
IEventSink
. Therefore, you will want to avoid doing too much processing at this point, otherwise calls to your service will suffer that performance penalty every time. - You will want the Relay process that picks up the events and delivers them to subscribers to do that reliably, otherwise if events are lost subscribers don't get notified, and downstream tool-chains that rely on those webhooks won't be executed. Not a fabulous user experience for your subscribers!
- The 'Relay' component that you choose to sent events to subscribers over HTTP, is likely to be asynchronous, and ideally highly responsive and elastic (scales to demand), and will want to implement some kind of timeout and some kind of retry mechanism, since you don't want to assume that subscribers endpoints are always online all the time, and that their subscription configuration is necessarily valid at the time of delivery.
And just quietly....a reminder about these fallicies just in case your assuming any of them.
Having said all that, there are a bunch of cloud technologies that do all that kind of stuff for you, all you have to do is learn how to wield them, and use them as they are intended to be used.
Once you have all that sorted, create your 'IEventSink'.
- Install the nuget package 'Webhooks.Interfaces'.
- Implement the 'IEventSink' interface.
- See the Installation notes below.
This is the easy part, once you have your plugin installed from either a nuget package, or referenced the same solution as your 'WebhookFeature', then just register it in your AppHost:
public override void Configure(Container container)
{
// Register the ValidationFeature and AuthFeature first
Plugins.Add(new ValidationFeature());
Plugins.Add(new AuthFeature(...));
// Register your own ISubscriptionStore and IEventSink
container.Register<ISubscriptionStore>(new YourDbSubscriptionStore());
container.Register<IEventSink>(new YourEventSink());
Plugins.Add(new WebhookFeature
{
.. any customization for your environment
});
}
Sit back, and start raising events from your service! And let your plugins do all the hard work.
One last thing. Don;t forget to tell us about your neat plugin, so that we can publish it on our Plugins page for other to use. Good luck!