Functions

Functions enable you to create custom code callable using the Airsequel API. Functions are written in TypeScript (executed with Deno) or Python (version 3.10).
Functions generally follow the same basic structure:
Deno:
typescript
export default function(context) { return { data: ... } }
Python:
python
async def main(context): return { 'data': ... }

The Context Argument

The context argument contains many useful pieces of information:
  • functionId contains the id of the functions being called
  • databaseId contains the id of the database the function is attached to
  • db contains an instance of connection to the current database
    • Deno
      Python
  • graphql contains a GraphQL client for the current database
  • method the HTTP method the function got called with
  • headers the HTTP headers the function got called with
  • data the body of the HTTP request the function got called with

Calling Functions

Functions can be called by making requests to its /fns/<function-id> endpoint as shown on the function overview page.

Runtime System

Unlike other FaaS offerings, our functions are not directly handling the HTTP requests and responses. Rather, our runtime system is handling the HTTP request, and your function is called with a simple request JSON object and can then return a response JSON object. This allows you to focus on your business logic, and not worry about the details of the HTTP request or how to implement a HTTP server.

Resource Limits

Number of Functions
Fair-use policy
RAM per Function
256 MB
Maximum Execution Time
10 s
Log Retention
Last 500 function calls (Maximum 100 log entries per function call)

View Function Invocations

Currently there is no GUI for viewing a log of function invocations. However, it can be accessed via our Admin JSON API (using HTTPie here):
shell
http GET \ https://www.airsequel.com/api/dbs/<dbId>/functions/<funcId>/invocations \ Authorization:"Bearer <tokenId>"
Returns:
json
{ "invocations": [ { "createdUtc": "2023-12-19T23:01:26.039Z", "logs": [ { "stream": "stdout", "message": "…", "utc": "…" } ] } ]}
It only stores the last 500 invocations for each function.

A Hands-On Example

We start by creating a simple todos table (via the SQL queries tab):
sql
CREATE TABLE todos ( name TEXT NOT NULL PRIMARY KEY, completed BOOLEAN NOT NULL DEFAULT FALSE )
Functions can than be created from the “functions” tab in the database view.
Image without caption
Let’s create a simple todo-list function:
TypeScript
Python
⚠️
This code is not production ready! Everything is bundled up in a single function, there’s no input validation, etc.
We can start by attempting to call our function. We will use HTTPie for all examples.
bash
$ http GET https://www.airsequel.com/fns/01hbv54akc0zpejb7f59d63qpa { "data": [], "extensions": { "logs": [] } }
There’s nothing there! Let’s change that by creating a todo:
bash
$ http POST https://www.airsequel.com/fns/01hbv54akc0zpejb7f59d63qpa name=hello { "data": "Todo created succesfully", "extensions": { "logs": [] } }
Running the GET method will now yield:
json
{ "data": ["hello"], "extensions": { "logs": []} }
We can run the previous command with different arguments in order to create even more entries:
json
$ http POST http://localhost:4185/fns/01hbv54akc0zpejb7f59d63qpa name=world $ http POST http://localhost:4185/fns/01hbv54akc0zpejb7f59d63qpa name=oops $ http GET http://localhost:4185/fns/01hbv54akc0zpejb7f59d63qpa { "data": ["hello", "world", "oops"], "extensions": { "logs": []} }
Let’s delete the oops todo by using the DELETE method, and complete the hello todo using the PATCH method:
bash
$ http DELETE http://localhost:4185/fns/01hbv54akc0zpejb7f59d63qpa name=oops { "data": "Todo delete succesfully", "extensions": { "logs": [] } } $ http PATCH http://localhost:4185/fns/01hbv54akc0zpejb7f59d63qpa name=hello { "data": "Todo completed succesfully", "extensions": { "logs": [] } }
We can now run the GET method one last time in order to ensure everything is working as expected:
bash
$ http GET http://localhost:4185/fns/01hbv54akc0zpejb7f59d63qpa { "data": ["world"], "extensions": { "logs": [] } }

Available packages

The following common packages are included in the environment:
Python

[Unreleased] Executing GraphQL queries

We can achieve the same functionality by using the provided GraphQL API. For instance, the GET branch of our previous implementation can be rewritten as follows:
Typescript
Python

Troubleshooting

If you get an error like this when making a network request (e.g. with fetch()):
json
error: Uncaught PermissionDenied: Requires net access to "example.com", run again with the --allow-net flag …
Please contact us at support@feram.io and request that the used URL should be allowed. We will then check if the URL is safe and allowlist it if applicable.

Powered by Notaku