Documentation
Feedback
Guides
Learning Center

Learning Center
Learning Center
Events: Handling and receiving events
View in Portuguese
This content was migrated from the VTEX Learning Center and is no longer being actively maintained. For the most accurate and up-to-date information, please check the official documentation.

Introduction

Some interactions on VTEX IO can generate events and they can be used as triggers for actions, like the activity on this step. For now, we will use the events fired by the events-example app.

Events on VTEX IO

On VTEX IO apps, events can be fired and used to trigger actions. For example, an app that listens for order placements and triggers a confirmation e-mail. It is important to highlight that events are workspace and account bound, which means that events are only visible for the account and workspace where they were fired. Events fired on your personal workspace will only be listened to by apps linked on this same workspace.

Listening to events on the app

  1. First, we are starting the event firing on the events-example app. This app will fire an event every X seconds. After running vtex link on the events-example directory, click on the healthcheck route available and a "ok" message should appear on the browser:

    {"base64":"  ","img":{"width":1426,"height":386,"type":"png","mime":"image/png","wUnits":"px","hUnits":"px","length":89920,"url":"https://user-images.githubusercontent.com/43679629/83802091-8c69f380-a680-11ea-82af-a438fb73f40b.png"}}

    This healthcheck route access creates a cache context needed for the VTEX IO to fire events. Without it, the events-example app won't be able to fire the events our app is going to listen to.

  2. We need to add the event handler on the Service declaration to refer to what the app is supposed to do when listening to the event. To do so, on the /node/index.ts file, complement Service declaration:


    _24
    //node/index.ts
    _24
    _24
    + const THREE_SECONDS_MS = 3 * 1000
    _24
    + const CONCURRENCY = 10
    _24
    _24
    export default new Service<Clients, State, ParamsContext>({
    _24
    clients: {
    _24
    implementation: Clients,
    _24
    options: {
    _24
    default: {
    _24
    retries: 2,
    _24
    timeout: 10000,
    _24
    },
    _24
    + events: {
    _24
    + exponentialTimeoutCoefficient: 2,
    _24
    + exponentialBackoffCoefficient: 2,
    _24
    + initialBackoffDelay: 50,
    _24
    + retries: 1,
    _24
    + timeout: THREE_SECONDS_MS,
    _24
    + concurrency: CONCURRENCY,
    _24
    + },
    _24
    + },
    _24
    + },
    _24
    })

    Going by each configuration, we have the following:

    FieldTypeDescription
    exponentialTimeoutCoefficientsecondsthe exponential factor by which the timeout will increase in each retry
    exponentialBackoffCoefficientsecondsthe exponential factor by which the backoff delay will increase in each retry
    initialBackoffDelaysecondsthe time the app will wait until the next retry
    retries-the maximum times the app will retry
    timeoutsecondsthe timeout until consider a failure attempt
    concurrency-the amount of simultaneous processes the event is able to perform

    By adding this code to the Service, we are adding to the Client of this Service, the capability to handle events. At this point, we are not yet using the Client itself when handling the event.

  3. For now, we are only going to create a log when receiving an event. To create this event handler, in the /node/event directory, go to the liveUsersUpdate.ts file and do the following:


    _10
    //node/events/liveUsersUpdate.ts
    _10
    export async function updateLiveUsers() {
    _10
    console.log('EVENT HANDLER: received event')
    _10
    }

  4. Now, we need to declare in the Service the reference to this function. On the /node/index.ts file, add this code:


    _10
    ...
    _10
    + import { updateLiveUsers } from './events/liveUsersUpdate'
    _10
    ...
    _10
    _10
    export default new Service<Clients, State, ParamsContext>({
    _10
    ...
    _10
    + events: {
    _10
    + liveUsersUpdate: updateLiveUsers,
    _10
    + },
    _10
    })

  5. We also need to modify the service.json file. In order to listen to events sent, we need to declare this to give the app's service this capability. You may do so, by modifying service.json file:


    _16
    //node/service.json
    _16
    {
    _16
    "memory": 128,
    _16
    "ttl": 10,
    _16
    "timeout": 10,
    _16
    "minReplicas": 2,
    _16
    "maxReplicas": 10,
    _16
    "workers": 4,
    _16
    + "events": {
    _16
    + "liveUsersUpdate": {
    _16
    + "sender": "vtex.events-example",
    _16
    + "keys": ["send-event"]
    _16
    + }
    _16
    },
    _16
    ...
    _16
    }

    Note that we declare this by using the events resolver and the reference of the app that fires the event (declared as sender) and the event reference key (declared as keys).

  6. At last, run vtex link and wait for the event to be fired by the events-example app. When listened, the log should appear on the console, like this:

    {"base64":"  ","img":{"width":1442,"height":486,"type":"png","mime":"image/png","wUnits":"px","hUnits":"px","length":134467,"url":"https://user-images.githubusercontent.com/43679629/83823425-5f323b00-a6aa-11ea-816a-68525e5800d7.png"}}


Answer sheet

See answer sheet for index.ts
index.ts

_56
// node/index.ts
_56
import {
_56
LRUCache,
_56
Service,
_56
ServiceContext,
_56
ParamsContext,
_56
RecorderState,
_56
method,
_56
} from '@vtex/api'
_56
import { Clients } from './clients'
_56
import { analytics } from './handler/analytics'
_56
import { updateLiveUsers } from './events/liveUsersUpdate'
_56
_56
// Create a LRU memory cache for the Status client.
_56
// The @vtex/api HttpClient respects Cache-Control headers and uses the provided cache.
_56
const memoryCache = new LRUCache<string, any>({ max: 5000 })
_56
metrics.trackCache('status', memoryCache)
_56
_56
const TREE_SECONDS_MS = 3 * 1000
_56
const CONCURRENCY = 10
_56
_56
declare global {
_56
type Context = ServiceContext<Clients, State>
_56
_56
interface State extends RecorderState {
_56
code: number
_56
}
_56
}
_56
_56
export default new Service<Clients, State, ParamsContext>({
_56
clients: {
_56
implementation: Clients,
_56
options: {
_56
default: {
_56
retries: 2,
_56
timeout: 10000,
_56
},
_56
events: {
_56
exponentialTimeoutCoefficient: 2,
_56
exponentialBackoffCoefficient: 2,
_56
initialBackoffDelay: 50,
_56
retries: 1,
_56
timeout: TREE_SECONDS_MS,
_56
concurrency: CONCURRENCY,
_56
},
_56
},
_56
},
_56
routes: {
_56
analytics: method({
_56
GET: [analytics],
_56
}),
_56
},
_56
events: {
_56
liveUsersUpdate: updateLiveUsers,
_56
},
_56
})

See answer sheet for liveUsersUpdate.ts
liveUsersUpdate.ts

_10
//node/event/liveUsersUpdate.ts
_10
export async function updateLiveUsers() {
_10
console.log('EVENT HANDLER: received event')
_10
}

See answer sheet for service.json
service.json

_21
// node/service.json
_21
{
_21
"memory": 128,
_21
"ttl": 10,
_21
"timeout": 10,
_21
"minReplicas": 2,
_21
"maxReplicas": 10,
_21
"workers": 4,
_21
"events": {
_21
"liveUsersUpdate": {
_21
"sender": "vtex.events-example",
_21
"keys": ["send-event"]
_21
}
_21
},
_21
"routes": {
_21
"analytics": {
_21
"path": "/_v/app/analytics/realTime",
_21
"public": true
_21
}
_21
}
_21
}

On this page