Event Driven Functions
  • 10 Apr 2024
  • 16 Minutes To Read
  • Dark
    Light
  • PDF

Event Driven Functions

  • Dark
    Light
  • PDF

Article Summary

Event Driven Functions allow you to run a custom code whenever events are happening in the Mambu application. In custom code you can perform actions like calling Mambu APIs or even any other external APIs.

Event Driven Functions integrates with Mambu Streaming API and supports all events types which are supported by the Streaming API: Event Triggers for Notifications - Notifications Different to Streaming APIs, Event Driven Functions do not require any additional infrastructure to process the events and allows you to concentrate on developing custom business logic rather than hosting your own application.

The guide bellow will walk you through the main Event Driven Functions concepts and commands.

Note

Events streaming needs to be enabled for Event Driven functions. If you would like to request early access to this feature, please get in touch with your Mambu Customer Success Manager or contact us through Mambu Support to discuss your requirements.

Warning!

The total size of the input payload (which comprises of data from all the events in a batch) to your custom function should not exceed 6mb. This is a hard limit, and any payload exceeding this size will not be processed.

Workflow to set up Event Driven functions

In order to setup Event Driven function, you need to:

  • Create an event streaming notification template for the target event via admin UI.
  • Generate a sample function using Mambu CLI and then implement the custom business logic.
  • Create secrets necessary for your functions.
  • Build and deploy the function.
  • Create a function Subscription for the target event.
  • Monitor your function to verify that events are being processed as expected.

Create event streaming notification templates

Event streaming notification template defines conditions when the event will be triggered as well as the payload which will be sent to the function. Please follow “Creating event streaming notification templates” section in the Streaming API documentation.

Note down the topic name which will be automatically generated when creating the template.

Note

if you are also using Streaming APIs directly, the events produced by the newly created template will also be visible to Streaming API consumers. If needed, you can filter out such events in your application code based on the template_name field.

Create the project scaffolding for Event Driven Dunction

The Mambu Functions CLI allows you to easily create all the files you need to start working on your new Event Driven Function with the command:

mambu functions generate --functionDirectory=./your-function --functionName=your-function --template=STREAMING_EVENTS
ExampleDescriptionRequired
mambu functions generateThis part of the command is always required.YES
-t or --templateThe templates to use for an extension point. Templates are ready-to-use implementations for an extension point that allow you to start writing code immediately for common processes. For more information, see the Extensions Point page. To create a project for the Event Driven Function, specify STREAMING_EVENTS. NOTE: this parameter is not related to event streaming notification template described above.YES
-d or --functionDirectoryThe local directory to use for your Mambu Function.YES
-n or --functionNameThe name of the Mambu Function. The name can only contain letters, digits, and hyphens - and it can not be the same as a previously used name unless you use the update flag.YES

The command will generate a sample typescript project containing Event Driven Function for the following sample use case: applying a fee for each withdrawal on the deposits account. This can be further extended to other use cases. Please refer to the README file in the function directory for more details how to setup this specific example.

Main project files and directories:

  • README.md - documentation how to configure and deploy the example project
  • mambu-function.json - function’s manifest file. Specifies target file, function name, language etc.
  • package.json - typescript project settings and depencies
  • src/* - directory containing all function typescript source files
  • test/* - directory containing function unit tests
  • src/function.ts - typescript file with the main method which will be invoked by Mambu

After building the project, all function’s files and dependencies will be bundled to dist/bundle.js file. You should never modify this file directly since all the changes will be overwritten during next build.

For more details how to modify this project to suit your business needs, please check Development guidelines section below.

Building and deploying event-driven functions

Event Driven Function can be built and deployed the same way as any other Mambu Function. Please follow the general guide here.

Subscriptions

Similar to Streaming APIs, a Subscription is required for a function to start receiving the events. Subscription is effectively a mapping between a function and an event.

As soon as Subscription is created, Mambu application will start invoking your function when the target event happens and the conditions in the template are met. Each time your function is invoked, it will receive a batch of the events, rather than a single event. Batching behavior can be controlled, see Create Subscriptions and Update Subscriptions.

Important

Subscription is not linked to a specific notification template. When Subscription is active, the function will be receiving one event for each template linked to the same event type. The best practice is to only have a single template per event type.

Create Subscription

To create the Subscription for Mambu Functions, run the command:

mambu functions create-subscription --functionName=your-function --subscriptionName=subscription-name --event=events-name
ExampleDescriptionRequired
mambu functions create-subscriptionThis part of the command is always required.YES
-n or --functionNameThe name of the Mambu Function, which you’ve specified when creating the function.By default reads function name from the mambu-functions.json manifest file in the current directory or in --functionDirectoryNO
-d or --functionDirectoryDirectory where to look for mambu-functions.json manifest file in order to resolve function name. This parameter is only required if --functionName is not specified and manifest file is not in the current directory.Specifying both --functionName and --functionDirectory will result in error.NO
-s or --subscriptionNameArbitrary Subscription name. The name will later be needed to manage the Subscription.NO
--eventTarget event name. Should match the event which you’ve selected when creating streaming notification template in the previous step. List of available events: Event Triggers for Notifications - Notifications E.g. SAVINGS_WITHDRAWALYES
--batchSizeMaximum number of events sent to the function during a single invocation. Defaults to 500.NO
--batchWindowMaximum number of seconds the system will wait for events until invoking the function. The function is invoked as soon as batchWindow seconds is lapsed since the last invocation or if there are at least batch size number of events in the topic, whichever comes first. Defaults to 0 - i.e. no wait, function is invoked as soon as the first event is received in the topic.NO

It might take up a few seconds for Subscription to be created.

Note

Currently you can only create one Subscription per function.
One Subscription can only subscribe your function to one event type.

Get Subscription details and status

To check the configuration and the status of the Subscription, run the command:

mambu functions get-subscription --functionName your-function --subscriptionName subscription-name
ExampleDescriptionRequired
mambu functions get-subscriptionThis part of the command is always required.YES
-n or --functionNameThe name of the Mambu Function, which you’ve specified when creating the functionYES
-s or --subscriptionNameThe name of the Subscription, which you’ve specified when creating the SubscriptionYES

List Subscriptions

To see the Subscription(s) that you have already created for the function, run the command:

mambu functions list-subscriptions --functionName your-function
ExampleDescriptionRequired
mambu functions list-subscriptionsThis part of the command is always required.YES
-n or --functionNameThe name of the Mambu Function, which you’ve specified when creating the functionYES

Update Subscription

To update a Subscription that you have already created to Mambu Functions, run the command:

mambu functions update-subscription --functionName your-function --subscriptionName subscription-name --batchSize <value> --batchWindow <value>
ExampleDescriptionRequired
mambu functions update-subscriptionThis part of the command is always required.YES
-n or --functionNameThe name of the Mambu Function, which you’ve specified when creating the functionYES
-s or --subscriptionNameThe name of the Subscription, which you’ve specified when creating the SubscriptionYES
--batchSizeMaximum number of events sent to the function during a single invocation.YES
--batchWindowMaximum number of seconds the system will wait for events until invoking the function. The function is invoked as soon as batchWindow seconds is lapsed since the last invocation or if there are at least batch size number of events in the topic, whichever comes first.YES
Note

You can not change Subscription’s event type (topic). In order to subscribe function to a different event, delete the existing Subscription and create a new one.

Delete Subscription

To delete a Subscription that you have already deployed to Mambu Functions, run the command:

mambu functions delete-subscription --functionName your-function --subscriptionName subscription-name
ExampleDescriptionRequired
mambu functions delete-subscriptionThis part of the command is always required.YES
-n or --functionNameThe name of the Mambu Function, which you’ve specified when creating the functionYES
-s or --subscriptionNameThe name of the Subscription, which you’ve specified when creating the SubscriptionYES
-y or --yesSkip a confirmation prompt and delete function immediately (we only recommend to use this option if using Mambu cli from automation scripts)NO

After subscription is deleted, there is still a limited amount of time when you can recreate the subscription with the same name and it will pick up events starting from the point when the previous subscription was stopped/deleted.

Disable Subscription

To temporarily stop a Subscription, run the command:

mambu functions disable-subscription --functionName your-function --subscriptionName subscription-name
ExampleDescriptionRequired
mambu functions disable-subscriptionThis part of the command is always required.YES
-n or --functionNameThe name of the Mambu Function, which you’ve specified when creating the functionYES
-s or --subscriptionNameThe name of the Subscription, which you’ve specified when creating the SubscriptionYES

When subscription is stopped, Mambu application will not be sending the events to your function, but all the events will still be queued and sent to the function as soon as the Subscription is reenabled.

Note

Events will only be kept in the queue for 4 days. After that period events will be lost. Hence we do not recommend keeping Subscription disabled for long period of time.

Enable Subscription

To enable a stopped Subscription, run the command:

mambu functions enable-subscription --functionName your-function --subscriptionName subscription-name
ExampleDescriptionRequired
mambu functions enable-subscriptionThis part of the command is always required.YES
-n or --functionNameThe name of the Mambu Function, which you’ve specified when creating the functionYES
-s or --subscriptionNameThe name of the Subscription, which you’ve specified when creating the SubscriptionYES

When Subscription is reenabled, Mambu application will start sending all events, including those which happened while the Subscription was disabled, assuming they did not expire.

Secrets

For most use cases your function will need to have access to secret values like API tokens or passwords. Mambu Functions capability provides a mechanism to securely store your secrets and retrieve them in your function.

In addition, you can also store environment specific parameters as secrets (e.g. Mambu API url). That way you won’t need to change your code at all when deploying to different environments (sandbox, production).

Secrets you create are not linked to a specific function and can be reused in multiple functions.

Important
  • Never hardcode secrets or personally identifiable information (PII) data in your source code - use secrets management functionality instead.
  • Note that there is a separate set of Mambu permissions which need to be enabled for your user to be able to manage secrets. See Permissions page for more details.
  • You can create up to 50 secrets per tenant. Please reach out to Mambu support if you have a use case which requires increasing this (or other) limits.

Create Secret

To create a Secrets, run the command:

mambu functions create-secret --name secret-name --value secret-value
ExampleDescriptionRequired
mambu functions create-secretThis part of the command is always required.YES
--nameSecret name. You will need to use this name in order to retrieve the value in your functionYES
--valueSecret value.YES
Note

If your functions require many secrets which are always used and rotated together, you can use a single secret entry and store all required secret values in a json string.

List Secrets

To see the Secrets that you have already created, run the command:

mambu functions list-secrets
ExampleDescriptionRequired
mambu functions list-secretsThis part of the command is always required.YES

The command will only return secret names and some additional metadata, but not the secret values. For security reasons, it’s not possible to retrieve secret values via CLI or API. Secret values can only be retrieved from inside your function.

Update Secret

To update a Secret that you have already created, run the command:

mambu functions update-secret --name secret-name --value secret-value
ExampleDescriptionRequired
mambu functions update-secretThis part of the command is always required.YES
--nameSecret name.YES
--valueSecret value.YES

Previous value will be overwritten.

Delete Secret

To delete a Secrets that you have already created, run the command:

mambu functions delete-secret --name secret-name
ExampleDescriptionRequired
mambu functions delete-secretThis part of the command is always required.YES
--nameSecret name.YES
Warning

Removal of a secret may cause Denial Of Service for any Mambu Function which uses it. This operation will not verify if there are such usages, so please verify if none of your Mambu Functions use it before deleting the secret (calls to context.getSecret() will start throwing an exception).

Note

For a few minutes after deleting a secret, you won’t be able to create another secret with the same name.

Retrieving Secret in your function

In order to retrieve a secret in your function, a

context.getSecret()

function can be used. context is a second parameter of you handler function. E.g.

export default async function handle(events: StreamingEvent[], context: Context): Promise<void> {
    const secretValue = (await context.getSecret('secret-name')).value
}

context.getSecret() returns a promise with a Secret object. Secret contains two fields:

  1. name: string - secret name
  2. value: string - secret value
Important

context.getSecret() is asynchronous and returns a Promise. In the example above await is used to retrieve Promise result.

Note

Secrets you retrieve will be cached for a period of 5 minutes for optimal performance. When updating internal Mambu API keys we recommend to create a new key before the old one expires as well as to not delete the old one for a period of 5 minutes after updating the secret value. This ensures each function has a chance to pick up the new value.

Retries and Error handling

Event Driven Functions come with a built in retry mechanism.

When your event driven function starts throwing an exception, the following error handling strategy is applied:

  1. The whole batch of events will be retried multiple times. A random delay will be added between retries.
  2. If error rate remains high for a longer period of time, the Subscription of the function will be automatically stopped.
  3. An outbound Salesforce case will be created to notify you about a stopped Subscription. Mambu champions will be added to the case as main contacts.

After Subscription is stopped, you need to identify the underlying issue, resolve it and reenable the Subscription using enable-subscription cli command. In order to identify the issue, please check function logs. More details about logging can be found in Retrieving Function logs section.

Note

Note that you have a limited amount of time to resolve the issue and restart Subscription before events start to expire. See Disable Subscription for more details.

Development guidelines

Function handler

Your function should export a default async method which accepts two arguments and returns nothing (Promise<void>):

export default async function handle(events: StreamingEvent[], context: Context): Promise<void> {
    //process events here
}

First argument is a list of streaming events. StreamingEvent model corresponds to a Mambu Streaming API Event model which is documented in here

Second input parameter is Context which contains the following methods:

MethodDescription
getSecret(secretName: string): Promise<secret>Retrieves a secret value which was previously created via API or Mambu cli. Returned object (Secret) fields are 'name: string - name of the secret' and 'value: string - value of the secret'

Parallel processing

On each invocation your function will receive multiple events (a batch). Depending on your business use case, you will need to iterate over the batch and apply required business logic to each event. To achieve optimal performance, your code should process those events in parallel. Here is an example how parallel execution can be achieved:

export default async function handle(events: StreamingEvent[], context: Context): Promise<void> {
    const promises = events.map((event) => processEvent(event, context));
    await Promise.all(promises);
}

async function processEvent(event: StreamingEvent, context: Context): Promise<void> {
    //Process event.
}

Idempotency

Streaming Mambu Functions ensure at-least-once delivery guarantee. This means your function can be invoked multiple times for the same batch of events. This can happen in case of automatic retry mechanism is engaged. Your code should be able to gracefully handle duplicated events - this property is called idempotency. If your code is calling external APIs, those APIs should also be idempotent.

Streaming event field metadata.eid can be used to identify duplicate events. metadata.eid can also be used directly as Idempotency key when calling Mambu APIs.

Mambu APIs offer two ways to provide an idempotency key:

  • Provide a header Idempotency-Key: string as part of the request, more details can be found here.
  • Provide externalId in the request body. E.g. *Deposits “fee-transactions” API: { "amount": 0, "externalId": "string", "notes": "string", "predefinedFeeKey": "string" } * This is only supported for some of the APIs - please check Mambu API v2 reference.

It is recommended to use both as they cover different cases. Both are demonstrated in the example project (STREAMING_EVENTS template) in src/api.ts.

Example:

export async function applyFee(
    accountId: string,
    feeKey: string,
    feeAmount: Big,
    idempotencyKey: string,
    config: ApiConfiguration
): Promise<unknown> {
    const response = await fetch(`${config.apiUrl}/deposits/${accountId}/fee-transactions`, {
        headers: Object.assign({ 'Idempotency-Key': idempotencyKey }, config.headers),
        method: 'POST',
        body: JSON.stringify({ predefinedFeeKey: feeKey, amount: feeAmount, externalId: idempotencyKey })
    });

    if (!response.ok) {
        const error = await HttpError.fromResponse(response);

        const msg = String(error);
        if (msg.includes('EXTERNAL_ID_ALREADY_EXISTS')) {
            return;
        } else {
            throw error;
        }
    }

    return response.json();
}

Supported Web APIs

Your function should be transpiled to ECMAScript 2020 Language Specification. Only the following web APIs are supported:

APIDescription
fetchExecutes remote HTTP calls
console.log, console.info, console.debug, console.warn, console.errorCreate log entries. Logs can be fetched via Mambu CLI command mambu functions logs -n [function-name]. See Retrieving function logs section for more details.

Memory and time limitations

The following limits apply to Event Driven Functions:

Runtime memory is limited to 2048 MB: The system enforces a memory limit for each Function. A portion of this memory is reserved for the Function's runtime.

Execution timeout is limited to 10 minutes: The system enforces an execution timeout for any Function exceeding this duration.

Events ordering

Order in which events are sent to your function is not guaranteed to be the same as order in which events occurred. Please carefully consider whether this impacts your Event Driven Function use case.

Remote Destination API Inbound IP Address Whitelisting

Mambu Function requests to your endpoints will originate from a fixed set of IP addresses per Mambu region. These IP addresses can be whitelisted in your firewall. Any changes to IP addresses will be announced on our Status Page as well.

If you need to know the sender IP addresses for your environment, please contact us through Mambu Support.


Was this article helpful?