Skip to content
Jezz Santos edited this page Mar 5, 2017 · 33 revisions

Documentation

What are Webhooks?

In general, Webhooks are a common asynchronous means today for listening to key 'events' raised by online systems, typically over HTTPS.

The idea is straightforward:

  1. Register a callback URL to be called when an "event" of a certain type is going to be raised, and the system will POST you notification of that event (along with any data describing that event) to that callback URL when the event is raised.
  2. You first need to register the callback URL with the system for a specific event (which implies a specific DTO of the event data).
  3. Sit back and wait to be called at your callback URL.

Under the covers, Webhooks are a good example of pub/sub architectures, where the consumers of the events are (typically) decoupled from the producer of the events. It is generally an asynchronous eventing system for the web.

How will ServiceStack.Webhooks work?

In this project, we are basing the subscription model of webhooks on that defined by GitHub Webhooks.

Which, defines the subscription service interface, and the wire representations of published events.

The WebhookFeature will be a ServiceStack Plugin that installs the following:

  1. A fully implemented and secured SubscriptionService, that allows any subscriber to register a webhook to any event raised by any service (in the same AppHost).
  2. A singleton service IWebhooks that will be used to raise any event from anywhere in any service in the AppHost.
  3. An extensible framework where the developer can plugin selected technologies that fit their service architecture and runtime environment.

When you register the WebhookFeature in your AppHost, it installs the subscriptions API, and the basic components to support raising events.

By default, the AppHostWebhookEventSink is used as the event sink.

When events are raised to it, the sink queries the ISubscriptionsService.Search(eventName) (in-proc) to fetch all the subscriptions to POST events to. It caches those subscriptions for a TTL (say 60s), to reduce the number of times the query for the same event is made (to avoid chatter as events are raised in your services). Then is dispatches the notification of that event to all registered subscribers (over HTTP). It will retry 3 times before giving up (EventServiceClient.Post).

WARNING: The AppHostWebhookEventSink can work well in testing, but it is going to slow down your service request times, as it has to notify each of the subscribers, and that network latency is added to the call time of your API (since it is done in-proc and on the same thread as that of the web request that raised the event).

  • We recommend only using the AppHostWebhookEventSink in testing and non-production systems.
  • We recommend, configuring a IWebhookEventSink that scales better with your architecture, and decouples the raising of events from the notifying of subscribers.

How do I wire-up ServiceStack.Webhooks to my services?

You add webhooks to your ServiceStack project by simply registering (and customizing) the WebhookFeature in your AppHost.cs.

public override void Configure(Container container)
{
    // Register the ValidationFeature and AuthFeature first
    Plugins.Add(new ValidationFeature());
    Plugins.Add(new AuthFeature(...));

    // Register your own IWebhookSubscriptionStore and IWebhookEventSink
    container.Register<IWebhookSubscriptionStore>(new MyDbSubscriptionStore());
    container.Register<IWebhookEventSink>(new MyAsyncEventSink());

    Plugins.Add(new WebhookFeature
    {
        .. any customization for your environment
    });
}

WARNING: In any production system you are going to need to register a IWebhookSubscriptionStore and IWebhookEventSink, since the built-in ones are really only designed for getting up and running quickly, and for testing.

See Getting Started for more details

How can I extend the WebhookFeature to suit my architecture?

There are several points of extensibility in the WebhookFeature, and each may support their own customization:

Subscription Service

By default the WebHookFeature registers and configures the SubscriptionService to provide an API for subscribers to manage their webhooks.

You can choose to turn this service off, and ship your own, and you can also configure the authorization roles that secure it.

See Subscription Service for more details on how to customize it

Subscription Store

By default, the built-in MemoryWebhookSubscriptionStore uses an MemoryCacheClient store for storing subscriptions.

You should register a different IWebhookSubscriptionStore that will persist subscriptions to some permanent (and perhaps distributed) store in your architecture. These stores are typically provided by extensions to the ServiceStack.Webhooks framework such as those listed in: Plugins

WARNING: The MemoryWebhookSubscriptionStore is not designed for use in production systems. If you do NOT register your own IWebhookSubscriptionStore your subscriptions will be lost when your AppHost restarts!

Event Sink

By default, the built-in AppHostWebhookEventSink will relay events to all subscribers in the same thread that called IWebhooks.Publish<TDto>().

You should register a different IWebhookEventSink that will decouple the raising of events from the relays of events to subscribers, using appropriate components in your architecture. (i.e. muti-threading, queues, async hooks etc.)

These kinds of sinks are typically provided by extensions to the ServiceStack.Webhooks framework such as those listed in: Plugins

WARNING: The AppHostWebhookEventSink is not designed for use in production systems. If you do NOT register your own IWebhookEventSink your services will suffer unacceptable performance penalties.