Serverless Background Tasks with OpenJS Architect - Part 1
Published: 2021-02-22 18:30:31

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.

```bash
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. 

```arc
# 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.

```javascript
// 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. 

```javascript
// 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`. 

```javascript
// 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!