Sessions
Sessions allow you to create and persist context within your instance seamlessly. Your instance can have many sessions, a one (instance) to many (sessions) relationship. Sessions are created when you want to use a Vonage Cloud Runtime provider from the SDK. Then sessions can be restored on subsequent calls to your instance to access the previous context.
Creating a Session
Sessions can be created by calling the createSession function:
const session = vcr.createSession();
By default, sessions have a TTL of 7 days, but this can be changed by providing a custom TTL in the createSession function.
The new session can be used to access providers and state:
const session = vcr.createSession();
const voice = new Voice(session);
const state = new State(session);
Calling functions on the voice or state object will now be associated with this session. This is done by Vonage Cloud Runtime setting a header on requests with the session ID.
Creating a Session with a Custom TTL
To create a session with a custom TTL, you can provide a TTL in seconds to the createSession function:
const session = vcr.createSession(3600);
The above will create a session which lasts for 1 hour.
The Global Session
The global session is useful for creating providers when you are not preserving context. You can get the global session using the getGlobalSession function:
const session = vcr.getGlobalSession();
Session Restoration
You can store a session for use later, then restore the session from a session ID:
const session = vcr.getSessionById('sessionID');
When you have subsequent incoming requests into your application you can restore an existing session using the getSessionFromRequest function:
app.post('/onMessage', async (req, res, next) => {
const session = vcr.getSessionFromRequest(req);
...
});
getSessionFromRequest will look for a header on the request:
'x-neru-sessionid': '44092039-fa65-41a6-a9ce-97a7d1274b96',
Then using the session ID on the request header, getSessionFromRequest internally will call getSessionById. This allows you to reason about your code in relation to a session and events in a session.
This simplifies state operations since you can be certain that the session's state object is only aware of this session.
Session Restoration Example
To demonstrate, here is an example of a Vonage Cloud Runtime application that carries context between an incoming phone call and text message from the same user:
app.post('/onCall', async (req, res, next) => {
const session = vcr.createSession();
const voice = new Voice(session);
const messages = new Messages(session);
await voice.onVapiEvent({ vapiUUID: req.body.uuid, callback: "onEvent" }).execute();
await messages.onMessage(
'onMessage',
{type: 'sms', number: req.body.from },
vonageNumber
).execute();
res.json([
{
action: 'talk',
text: 'Say some words, then text this number for a transcript',
},
{
"action": "input",
"type": ["speech"]
}
]);
});
The onCall route is called when there is an incoming call to the application. A new session is created which is used to set up a listener for incoming SMS messages from the number calling as well as voice events from the call.
The Vonage Cloud Runtime platform receives incoming RTC, Voice, and Messages webhooks to your Vonage application as configured by vcr app configure. If you have a listener for these webhooks, they will be sent to your application if the incoming webhook satisfies the filters on the listener e.g. the from number.
Since the listeners are set up with a session, any requests that satisfy the filters on the listener will be sent to your application on the route specified with the x-neru-sessionid set.
app.post('/onEvent', async (req, res, next) => {
if (req.body.speech != null) {
const session = vcr.getSessionFromRequest(req);
const state = new State(session);
await state.set('text', req.body.speech.results[0].text);
} else {
console.log(req.body)
}
res.sendStatus(200);
});
In the onEvent route, a session is being restored by using getSessionFromRequest. That session's state is being used to store the speech-to-text results from the phone call. Notice how there was no need to use any form of identifier on the state since the state is local to this session, which is the same session created when the user called.
app.post('/onMessage', async (req, res, next) => {
const session = vcr.getSessionFromRequest(req);
const messages = new Messages(session);
const state = new State(session);
const text = await state.get('text');
await messages.send({
message_type: "text",
to: req.body.from,
from: vonageNumber.number,
channel: vonageNumber.type,
text: text
}).execute();
res.sendStatus(200);
});
Finally, once the user sends an incoming text to request the transcript from their call in onMessage, the original session is restored again, which has the state on it.