Background tasks are a common workload and perfect for serverless environments. They reinforce event-driven architecture and allow you to perform asynchronous work across a distributed system. These functions are well suited for processes that don't require an immediate response or are too resource-intensive for a single function.
OpenJS Architect, https://arc.codes, has three main primitives of background functions:
- @events - A pub/sub service that uses AWS SNS.
- @scheduled - Cron functions that are invoked at a specific rate with Cloudwatch Events.
- @queues - A distributed message queue that uses AWS SQS.
Each type of function enables a reliable way for Lambda functions to call one another while also remaining stateless. This allows your distributed system to process data before it has to be committed to a persistent store. Imagine background tasks as more memory for your main functions to do more work that it doesn't have to deal with right away.
@events example
@events
give your application a pub/sub message bus with AWS Simple Notification Service(SNS). In this tutorial, we will create an event topic, POST JSON data to invoke a subscribed Lambda function. Any @event
function subscribed to the named topic will catch the event object, at least once. The event functions are also good for creating a one-to-many pattern. The same original event object can be sent to any number of functions.
Let's start with a fresh project and install dependencies.
npm init @architect ./arc-event-app
cd arc-event-app
npm install @architect/functions
Open up your arc.app
file and add the @event
pragma along with a POST route.
# app.arc
@app
arc-event-app
@http
get /
post /yolo
@events
yolo
Run the command arc-init
to scaffold the functions that are declared in the app.arc
file.
Now we can write our get-index
handler. This function handler sends an HTML form to the client and allows them to make a POST request to the /yolo
endpoint.
// src/http/get-index/index.js
exports.handler = async function http() {
let form =
`<form action=/yolo method=post>
<button>YOLO</button>
</form>`
let html = `<!doctype html><html><body>${ form }</body></html>`
return {
statusCode: 200,
headers: { 'content-type': 'text/html' },
body: html
}
}
Next, we're going to create a new event function in /src/events/yolo
. This function is automatically subscribed to the topic created from the app.arc
file and will receive a JSON payload published to the event name.
// src/events/yolo/index.js
let arc = require('@architect/functions')
async function yoloEvent(event) {
console.log('got event', JSON.stringify(event, null, 2))
return true
}
exports.handler = arc.events.subscribe(yoloEvent)
The final step is creating a POST endpoint for the client to send JSON data. Good thing we can make another Lambda function, and the @architect/functions
library will handle publishing and service discovery of the SNS topic.
After the library is installed we can now use it for a clean method to interact with the SNS topic. The function accepts a JSON payload with two keys: name
and payload
.
// src/http/post-yolo/index.js
let arc = require('@architect/functions')
async function yolo() {
await arc.events.publish({
// the name of the event
name: 'yolo',
// the JSON payload you want to send
payload: {
message: 'swag',
timestamp: new Date(Date.now()).toISOString()
}
})
return { location: '/' }
}
exports.handler = arc.http.async(yolo)
Test it locally by running npm start
in your terminal from the project root. Architect's Sandbox environment will emulate the same behavior once your project is deployed.
Navigate to http://localhost:3333 and click the "YOLO" button and watch your terminal for the output. You should see Sandbox output the @event
object and log the output of your yolo
event function.
Stay tuned
In the next section we'll look at @scheduled
events!
Top comments (3)
Nice tutorial. I agreee that events would be great for a one-to-many pattern, but I can't work out how arc lets you do that.
/src/events/yolo
defines one lambda function that is subscribed to yolo, but the event is derived from the path. How would you create a second function subscribed to the yolo event?You would still keep a single event mapped to one event function, but in the POST lambda you could publish to multiple event functions. For example, a single POST request would publish in parallel to two different event topics like a newsletter signup service and saving their information to a database. I hope that makes sense.
That makes sense. I was thinking along the lines of a more general "new-user" event, with two subscribers "newsletter signup" and "save to database".