Event Feeds sample app
This sample application demonstrates how to use Event Feeds to return paginated events from a collection. The application uses Fauna’s Python driver to retrieve the events.
The sample app uses AWS Lambda function to poll for events every 10 minutes. It then sends any fetched events to another service.
Prerequisites
-
Knowledge of Python
-
Knowledge of FQL and Event Feeds
-
Basic understanding of AWS Lambda serverless functions
-
AWS account
-
AWS SAM CLI installed
Overview of Event Feeds
An event source tracks changes to a specific Set of documents or document fields, defined by an FQL query, in the database. Event Feeds are asynchronous requests that poll an event source for paginated events.
Imagine you have a e-commerce operation. Every time a product is low in stock, you want to send a notification to your team. You can use an Event Feed to track the stock levels of your products. When the stock level of a product falls below a certain threshold, the Event Feed sends an event to your warehouse team. Let’s say you check the stock levels every 10 minutes. The Event Feed will return all the events from the previous 10 minutes.
Configure Fauna
Create a Fauna database
Before you start, you need to create a Fauna database and collection. For this sample application, you can use the demo data provided by Fauna.
-
Log in the Fauna Dashboard.
-
In the Dashboard, create a database with the Demo data option enabled. Then navigate to the database in the Dashboard.
-
In the upper left pane of the Dashboard’s Explorer page, click the demo database, and click the Keys tab.
-
Click Create Key.
-
Choose a Role of server.
-
Click Save.
-
Copy the Key Secret. Save the key’s secret. You’ll use it later.
Create a collection to track Event Feed cursors
Each time you poll an Event Feed, you get a top-level page cursor. You can use this cursor to get the next set of events. You can store returned cursors in a collection.
-
Create a collection named
Cursor
.collection Cursor { name: String value: String? index byName { terms [.name] } }
-
Create a document in the
Cursor
collection with the nameProductInventory
.Cursor.create({name: "ProductInventory"})
Create a serverless project
-
Run the following command to create a new serverless project:
sam init
-
Choose the
1
option for theAWS Quick Start Templates
and then choose thepython3.10
runtime. -
Choose the
hello_world
template. -
The folder structure of the project will look like this:
sam-python-function/ ├── README.md ├── events │ └── event.json ├── hello_world │ ├── __init__.py │ ├── app.py # Main Lambda handler file │ └── requirements.txt # Dependencies for your Lambda function ├── template.yaml # SAM template file └── tests └── unit └── test_handler.py
Write code for the serverless function
-
Navigate to the project directory and open the
hello_world/requirements.txt
file. -
Add fauna driver as a dependency:
fauna
-
Navigate inside the Lambda function directory and run the following command to install the dependencies:
cd hello_world pip install -r requirements.txt -t .
-
Next, add the following code to the
hello_world/app.py
file:import json import time from fauna import fql from datetime import datetime, timedelta from fauna.client import Client, FeedOptions def lambda_handler(e, context): client = Client() # Get the previous feed cursor if it exists cursor = None options = None cursor_data = client.query(fql('Cursor.byName("ProductInventory").first()')) cursor = cursor_data.data.value if cursor_data.data.value else None # If no cursor exists, capture all events from previous 10 minutes if cursor is None: # Calculate timestamp for 10 minutes ago ten_minutes_ago = datetime.now() - timedelta(minutes=10) # Convert to microseconds start_ts = int(ten_minutes_ago.timestamp() * 1_000_000) options = FeedOptions( start_ts=start_ts ) feed = client.feed(fql('Product.where(.stock < 25).eventSource()'), options) for page in feed: for event in page: event_type = event['type'] if event_type == 'add': # Do something on add print('Add event: ', event) elif event_type == 'update': # Make an API call to another service on event # (i.e. email or slack notification) print('Update event: ', event) elif event_type == 'remove': # Do something on remove print('Remove event: ', event) # Store the cursor of the last page cursor = page.cursor # Store the cursor in the database cursor_update = client.query(fql(''' Cursor.byName("ProductInventory").first()!.update({ value: ${cursor} }) ''', cursor=cursor)) print(f'Cursor updated: {cursor}') return { "statusCode": 200, "body": json.dumps({ "message": "Event feed processed successfully" }) }
-
Save the file.
-
Open the
template.yaml
file. This file defines the AWS resources that your serverless application will use. -
Add the following code to the
template.yaml
file:AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > sam-python-function Globals: Function: Timeout: 3 Resources: FeedFunction: Type: AWS::Serverless::Function Properties: CodeUri: hello_world/ Handler: app.lambda_handler Runtime: python3.10 Events: # Schedule to run every 10 minutes FeedFunctionSchedule: Type: Schedule Properties: Schedule: rate(10 minutes) # AWS CloudWatch Events schedule Name: "FeedEvery10Minutes" # Optional: Name of the rule Description: "Trigger hello_world Lambda every 10 minutes"
-
Save the file.
-
Change directory to the root of your project and run the following command to deploy the serverless function:
sam deploy --guided
-
Follow the prompts to deploy the function.
-
Once the function is deployed, you can view the logs in the AWS CloudWatch console.
Add Fauna key to the Lambda function environment
Add the Fauna key you generated earlier to the Lambda function environment using the AWS CLI.
-
Run the following command to add the FAUNA_SECRET environment variable to the Lambda function:
aws lambda update-function-configuration \ --function-name <your-function-name> \ --environment Variables="{FAUNA_SECRET=<YOUR_SECRET>}"
Testing
The Lambda function will now automatically trigger every 10 minutes. The function will poll for events that happened in the past 10 minutes. You can verify this in the CloudWatch Logs.
Cleanup
To avoid incurring charges, delete the resources you created in this tutorial.
-
Run the following command to delete the resources:
sam delete
Is this article helpful?
Tell Fauna how the article can be improved:
Visit Fauna's forums
or email docs@fauna.com
Thank you for your feedback!