# Eventing

{% hint style="warning" %}
The fulfillmenttools eventing mechanism doesn't guarantee event ordering. The same event can be emitted multiple times.
{% endhint %}

Eventing is the mechanism that notifies external systems about business events, such as `Order has been routed` or `pick job has been completed`. Events are phrased in the past tense because they describe actions that have already occurred.

Eventing is available for a callback URL, the [Microsoft Azure Service Bus](https://learn.microsoft.com/en-gb/azure/service-bus-messaging/), and [Google Cloud Pub/Sub](https://docs.cloud.google.com/pubsub/docs/overview).

<figure><img src="https://4170739437-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrrr5jgTsDuR38gNJIrm%2Fuploads%2F21dHoHfqJceCZnmBCOuc%2FEvent%20diagram.png?alt=media&#x26;token=b91c5a79-2eca-4b2b-8ecd-c4789676075c" alt=""><figcaption></figcaption></figure>

## Timing

Events are the primary mechanism for decoupling services within a distributed system. The time from publication on the message bus to delivery to a subscription is typically a few milliseconds to several seconds. In worst-case scenarios, such as when backend services are scaling up, this process can take up to 30 seconds.

The following diagram shows the typical timing of events originating from fulfillmenttools to an external system:

<img src="https://4170739437-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrrr5jgTsDuR38gNJIrm%2Fuploads%2FCSJZIPMK6qycMaD47gu6%2Ffile.excalidraw.svg?alt=media&#x26;token=6f9c6fb8-6e15-4962-81e1-efc21a2804c0" alt="Typical time of event distribution" class="gitbook-drawing">

{% hint style="danger" %}
**Avoid event delivery delays**

In a distributed system, it's expected that parts of the system will fail from time to time. However, when running a service on your own that serves as an endpoint for subscriptions, it's important to properly monitor its availability and return codes to ensure events are delivered on time.

Services returning a `200 OK` response are considered error-free.
{% endhint %}

## Receiving events

For all [available-events](https://docs.fulfillmenttools.com/documentation/getting-started/eventing/available-events "mention"), subscriptions can be created using the eventing API to receive notifications.

{% hint style="success" %}

### Prerequisites

* Access to your company's tenant (`projectId` and credentials)
* Have an authenticated session in Postman
* Have an Administrator role
* Imported the fulfillmenttools Postman collection
  {% endhint %}

{% hint style="warning" %}

### Limitations

For any single event, such as `ORDER_CREATED`, a maximum of five subscriptions can be created.
{% endhint %}

In the below example, we set up a subscription for the order created event.

{% stepper %}
{% step %}
**Set up your preferred provider**

Use the tabs below to select the relevant provider instructions needed for set up

{% tabs %}
{% tab title="Webhook" %}
Visit [webhook.site](https://webhook.site/) to generate a unique URL that can be used for testing and allows the response code to be changed to simulate failing requests.

The following values are then used for the subscription API call in fulfillmenttools:

**GET url** corresponds to `callbackURL`.
{% endtab %}

{% tab title="Microsoft Azure Service Bus" %}
To publish fulfillmenttools messages to Microsoft Azure Service Bus in a target system, a few settings must be configured in the target system:

1. Register an application in **Microsoft Entra ID** and save the **Application (Client) ID** and **Directory (Tenant) ID**.
2. Create a client secret (in **Certificates & secrets**) for the new application and save its **Value**.
3. Create an Azure Service Bus namespace and save the **namespace name**.
4. Configure **Access control (IAM)**, which stands for Identity and Access Management, for the Service Bus. Assign the **Service Bus Sender** role to the application created in step 1.
5. Create a **Queue** or **Topic** within the namespace.

The following values are then used for the subscription API call in fulfillmenttools:

* **Directory (Tenant) ID** corresponds to `tenantId`.
* **Application (Client) ID** corresponds to `clientId`.
* **Value of application secret** corresponds to `clientSecret`.
* **Namespace name** corresponds to `namespace`.
* **Queue or Topic name** corresponds to `queueOrTopicName`.
  {% endtab %}

{% tab title="Google Cloud Pub/Sub" %}
To publish fulfillmenttools messages to Google Cloud Pub/Sub in a target system, the following must be configured:

1. Define the topic where messages will be published.
2. In the topic's permissions, add the `fulfillmenttools` service account `ocff-event-function@{YOUR-TENANT-NAME}.iam.gserviceaccount.com` as a `principal` with the `Pub/Sub Publisher` role.

The following values are then used for the subscription API call in fulfillmenttools:

* **Google Cloud project id** corresponds to `projectId`.
* **Google Cloud Pub/Sub topic id** corresponds to `topicId`.
  {% endtab %}
  {% endtabs %}
  {% endstep %}

{% step %}
**Access the endpoint**

```http
POST https://{projectId}.api.fulfillmenttools.com/api/subscriptions
```

{% hint style="info" %}
In the Postman collection, you can select the relevant provider for this endpoint.
{% endhint %}
{% endstep %}

{% step %}
**Register the event**

Update the parameters in the body for the relevant settings you created in step one for your provider.

{% tabs %}
{% tab title="Webhook" %}

<pre class="language-json" data-title="Body"><code class="lang-json">{
    "name": "Order created (Webhook)",
    "event": "ORDER_CREATED",
    "target": {
        "type": "WEBHOOK",
<strong>        "callbackUrl": "callbackURL",
</strong>        "headers": [
            {
                "key": "header-key",
                "value": "header-value"
            }
        ]
    }
}
</code></pre>

{% endtab %}

{% tab title="Microsoft Azure Service Bus" %}

<pre class="language-json" data-title="Body"><code class="lang-json">{
    "name": "Order created (Microsoft Azure Service Bus)",
    "event": "ORDER_CREATED",
    "target": {
        "type": "MICROSOFT_AZURE_SERVICE_BUS",
        "tenantId": "tenantId",
<strong>        "clientId": "clientId",
</strong><strong>        "clientSecret": "clientSecret",
</strong><strong>        "namespace": "namespace",
</strong><strong>        "queueOrTopicName": "queueOrTopicName"
</strong>    }
}
</code></pre>

{% endtab %}

{% tab title="Google Cloud Pub/Sub" %}

<pre class="language-json" data-title="Body"><code class="lang-json">{
    "name": "Order created (Google Cloud Pub/Sub)",
    "event": "ORDER_CREATED",
    "target": {
        "type": "GOOGLE_CLOUD_PUB_SUB",
<strong>        "projectId": "projectId",
</strong><strong>        "topicId": "topicId"
</strong>    }
}
</code></pre>

{% endtab %}
{% endtabs %}

A successful request returns a `201 Created` status, and the subscription becomes active immediately.
{% endstep %}

{% step %}
**Test the notification**

Create a new test order with the follow endpoint to trigger the `ORDER_CREATED` event:

```http
POST https://{projectId}.api.fulfillmenttools.com/api/order
```

A successful request returns a `201 Created` status, and you should receive a notification on your provider service of the order.
{% endstep %}
{% endstepper %}

### Contexts

For the `INVENTORY_FACILITY_STOCK_CHANGED` event, it's possible to specify contexts to further restrict when a subscription is triggered.

* If contexts are specified, the subscription is triggered only if **all contexts apply**.
* Available context types are `FACILITY` and `FACILITY_GROUP`.
* An event applies if it occurs for a:
  * Facility explicitly listed in the context
  * Facility that belongs to one of the specified facility groups
* If the event is a bulk event containing multiple payloads, the payloads are filtered to include only those relevant to the specified contexts.

```json
"contexts": [
  {
    "type": "FACILITY",
    "values": ["facility-ref-1", "facility-ref-2"]
  },
  {
    "type": "FACILITY_GROUP",
    "values": ["group-ref-1"]
  }
]
```

## Attempts to resend messages that weren't delivered successfully

fulfillmenttools follows the exponential backoff pattern when a configured subscription is unreachable or returns a response code other than `200 OK`. If this happens, fulfillmenttools will automatically initiate a retry. The time between the retries will progressively increase with every retry from 20 seconds until it reaches 600 seconds. This is executed for one hour.

Redelivery attempts continue at this maximum interval until one of the following occurs:

* The subscription endpoint acknowledges the event by returning a `200 OK` response.
* The event's 7-day retention period has expired, at which point it's permanently dropped and deleted.

{% hint style="info" %}
fulfillmenttools can't guarantee how many times or the interval between retries after one hour.
{% endhint %}

See the following diagram that visualizes the approach:

<img src="https://4170739437-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrrr5jgTsDuR38gNJIrm%2Fuploads%2F3jXcmfY2usOCq1iiwjMO%2Ffile.excalidraw.svg?alt=media&#x26;token=03ba7760-c526-4924-bd8e-623cdc8c5d2d" alt="Diagram of an exponential backoff pattern for retrying messages, starting with a 20-second delay and increasing to a maximum of 600 seconds." class="gitbook-drawing">

{% hint style="warning" %}
fulfillmenttools doesn't monitor the health or availability of subscriber endpoints.
{% endhint %}

{% hint style="info" %}
**Monitoring and alerting**

It's recommended to monitor the subscription endpoint and employ an alerting mechanism to detect failures early, preventing events from being dropped after the retention period expires.
{% endhint %}

## Event flow examples

fulfillmenttools communicates relevant changes through events. The flowcharts below provide a brief overview of a subset of processes and the events they trigger.

A comprehensive overview of all events is available in the [Available events article](https://docs.fulfillmenttools.com/documentation/getting-started/eventing/available-events).

{% hint style="info" %}
The flows below are examples of a standard, successful process in fulfillmenttools. The exact sequence of flows and events can differ depending on the specific configuration of modules and processes.
{% endhint %}

{% hint style="warning" %}
The eventing API does not guarantee the order of events.
{% endhint %}

### Order, reservations, and fulfillment

The following diagram depicts the typical events emitted during an exemplary order fulfillment process. This includes order routing, reservations, picking, packing, and handover, as well as a potential return.

<figure><img src="https://4170739437-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrrr5jgTsDuR38gNJIrm%2Fuploads%2Fgit-blob-0318f966da824e8d701f01c2ca3375f41794de24%2Forder%2C_reservations%2C_and_fulfillment.png?alt=media" alt="Flowchart of the order fulfillment process, showing events from order creation and routing through picking, packing, handover, and a potential return."><figcaption></figcaption></figure>

### Inbound process

The following diagram depicts the typical events emitted during an exemplary inbound process, from the creation of a Purchase Order (PO) to the receipt of goods.

<figure><img src="https://4170739437-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrrr5jgTsDuR38gNJIrm%2Fuploads%2Fjb0ELKa2GXBAwteiNabI%2Fimage.png?alt=media&#x26;token=dc4274bb-1234-415f-ad73-ad163074198c" alt="Flowchart of the inbound process, showing events from the creation of a purchase order to the receipt of goods."><figcaption></figcaption></figure>

### Stow jobs

The following diagram depicts the typical events emitted during an exemplary stowing process, from the creation of a `stowJob` to the stowing of the final items and the completion of the job.

<figure><img src="https://4170739437-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLrrr5jgTsDuR38gNJIrm%2Fuploads%2FkOIDvTqvwgfYjzZmd4Lx%2Fimage.png?alt=media&#x26;token=fbd46647-be71-4d4b-af38-ff5abad07b96" alt="Flowchart of the stow job process, showing events from the creation of the stow job to its completion."><figcaption></figcaption></figure>
