TL;DR – Multi Client Sessions can be facilitated in a fully serverless fashion. Two players playing Tic Tac Toe or Chess, teams collaborating on a document or diagram, an audience witnessing a presenter’s demonstration – these are just examples where multiple distributed application instances should be kept in synch. This can be done with stand-alone application that have no backend. This article demonstrates a simple set up on Oracle Cloud Infrastructure – using a Serverless Function (that is not truly serverless because an instance and its variables are kept alive for 5-10 minutes after their last execution) and an API Gateway – together with a standalone HTML page running on several distributed computers. Even with this simple setup we can demonstrate a shared, synchronized session state.
For more details on the solution design, please read my earlier article Serverless Distributed Multi User Browser Session Synchronization.
Implementation on OCI
The implementation consists of:
- Serverless Function – handling POST (create new session), PUT (update session state), GET (retrieve session state)
- API Gateway – exposing function, handling requests, dealing with CORS
- Standalone HTML application that allows initiation or joining of session, pushing session state, retrieving session state
Serverless Function Live-Cache
Functions on OCI are created using the Fn Project using the Fn CLI. This can be ran locally of course but also in the OCI Cloud Shell – which is what I have done. An Fn Function is implemented using a configuration file – func.yaml – and the actual implementation in the runtime language specified in the configuration file. Node(JS) in this case. The file cache.js implements the cache functionality (not much more than a simple Map in a global variable that survives individual requests).
Note: the code discussed here is available on GitHub in this repo.
The function is defined in func.js as follows:
- determine the HTTP Method (POST, GET or PUT) and the request url.
- Extract the sessionKey parameter from the request url.
- Depending on the HTTP Method, invoke the corresponding function on the cache module.
- The result from the call to the cache module is returned to the Function caller
The Cache Module does not have any Function (Fn) dependency – it could run anywhere. The global variable cache contains the session context for every multi client session. New session contexts are created from function startNewSession; the key for each session is generated and returned – to be reused in subsequent calls by all clients in the session.
Functions writeToCache and readFromCache are straightforward: they put a value into the cache for the session key and retrieve the session context object from the cache using the session key.
Note: the meta attributes timestamp and version that are stored for the objects stored in the cache offer a stepping stone for fine grained version control to help prevent collision between changes from different clients.
The deployed function on OCI is visualized in the OCI Cloud Console like this:
API Gateway – Expose Function
The Function needs to be exposed outside OCI in order to be usable as the Serverless Multi Client mediator – and it needs to deal with CORS. Exposing a function with the OCI API Gateway is quite straightforward:
- create the API Gateway
- create the API Deployment
- configure p0licies for logging, authentication and CORS
- configure the Route:
- path, methods, back end (Function in this case)
Deploy the API Gateway. Then: get the (public) endpoint – and start invoking.
Stand Alone HTML Application – leveraging the Multi Client Session Cache
The standalone HTML application that I use here to demonstrate the capability to make stand alone clients interact (share a session) is simple and not pretty.
This same application runs on multiple computers at the same time – possibly on very different locations. From each location, the application interacts with the function exposed on the API Gateway, as described above.
The HTML code is quite simple – as you would expect:
Function startSession() calls the POST operation on the backend function; retrieveSessionContext() is invoked from an interval that fires every 5 seconds – it calls the GET operation on the backend function and pushSessionContext() is invoked whenever the user sends a message; this function calls the PUT operation on the API and backend function.
The code details for these functions:
With two cloud resources – API Gateway and Serverless Function – that carry minimal costs (1M API Gateway calls for $3 month and 2M free Function calls per month) we managed to create a multi client session context that is easily shared across multiple remotely distributed clients. This allows stand alone web applications to support advanced behavior such as team collaboration and broadcast like capabilities.
I have demonstrated the implementation on Oracle Cloud Infrastructure. Of course similar implementation can easily be created on Azure, AWS or other public clouds.
My earlier article introducing the idea of serverless client synchronization: https://technology.amis.nl/frontend/serverless-distributed-multi-user-browser-session-synchronization/
Sources for this article on GitHub: https://github.com/lucasjellema/live-cache
Katacoda Scenario introducing Functions on OCI: https://www.katacoda.com/redexpertalliance/courses/oci-course/functions-on-oci
Katacoda Scenario introducing API Gateway on OCI: https://www.katacoda.com/redexpertalliance/courses/oci-course/api-gateway-on-oci