Streaming Fauna Documents with Python
Tags: fauna, database, python, programming
Published: 2021-07-30 18:44:53

With Fauna’s document streaming feature, you can get real-time updates about changes made to your database. 

In this tutorial, you will learn how to use Fauna’s document streaming feature in a Python application.

> Here for the code alone? Head over to the [implementation section](#h.yqdu04ukzkz1) of this article.

# Introduction

## What is Streaming?

Streaming refers to when a program continuously reads and fetches data from a given source in real-time. For example, while watching a YouTube video or downloading a file from the internet, you stream the data from the origin and process it on your client’s device instantaneously.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s5h55hnzrab1bhowmlxm.png)

Streaming, in some ways, can arguably be a better alternative to polling. Polling refers to when a client periodically makes queries to a data source to get updates. It is more expensive than streaming as the client sends many requests only to get a single update or none at all. Polling is only aware of changes when the query results return.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g1m9etlwcigbalgp4tnn.png)

## What is Fauna?

[Fauna](https://fauna.com/) is a flexible database delivered as a secure data API providing two interfaces: GraphQL and the Fauna Query Language (FQL). It offers functionality to store collections, indexes, and other databases. To learn more about Fauna, visit the [official documentation](https://docs.fauna.com/).

> NOTE: The rest of this article assumes you have a fair understanding of Fauna and Python. Check out my [introductory tutorial](https://dev.to/lordghostx/building-a-telegram-bot-with-python-and-fauna-494i) first if you don't.

# Setting up our Fauna database

## Creating the Fauna database

We need to first create the database to use in Fauna’s dashboard. If you have not created an account on Fauna before now, [do so here](https://dashboard.fauna.com/accounts/register).

In the dashboard, click on the `NEW DATABASE` button, provide a name for the database, then press `SAVE.` We will also be ticking the `Pre-populate` option to get demo data that will be used in this article:

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gsgmiu8a20uhltha7560.png)

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wjyrjch8ws5q4nlnsd2q.png)

## Generate the database security key

Then, we need to create a security key to connect the database to the application. Go to the `Security` tab on the Fauna sidebar (located on the left side of the screen), click the `NEW KEY` button, provide the necessary information, and press `SAVE:`

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/07rfqvz5d6ovfzhts2t4.png)

Fauna will then present you with your `Secret Key.` Copy the key immediately and store it somewhere easily retrievable because it will only be displayed once.

# Implementing document streaming with Python

Fauna features built-in support for document streaming. Whenever changes in a particular document are streamed, all the clients subscribed to it will be notified in real-time.

## Initializing our Fauna client

Let’s write some code to implement this functionality!.

First, we will install the Fauna Python driver, importing the required libraries, and creating a database client.

In the terminal, type:



```
pip install faunadb
```

After that, create a Python script and save the code below in it:

```python
from faunadb import query as q  
from faunadb.objects import Ref  
from faunadb.client import FaunaClient  
  
client = FaunaClient(secret="FAUNA_SECRET_KEY")
```

## Selecting a document to stream

Next, we will fetch the document from the Fauna database collections that we want to stream:

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s1km54sq0hmb8d1rp9un.png)

```python
doc = client.query(
    q.get(
        q.ref(q.collection("customers"), "101")
    )
)
```

## Creating an OnStart function

We will start by defining an `on_start` function, which will be triggered when a document stream starts:

```python
def on_start(event):
    print(f"started stream at {event.txn}")
    data = {
        "firstName": "John",
        "lastName": "Smith",
        "telephone": "719-872-4470"
    }
    client.query(q.update(doc["ref"], {"data": data}))
```

In our `on_start` function, we printed out the current timestamp of the transaction emitting the event (in microseconds) provided by `event.txn.` Then, the streamed document, so Fauna notifies our application in real-time.

## Creating an OnVersion function

Next, we will define an `on_version` function. It will be triggered when there is a change in the streamed document and Fauna has sent a notification to the subscribing application:

```python
def on_version(event):
    print(f"on_version event at {event.txn}")
    print(f"Event action: {event.event['action']}")
    print(f"Changes made: {event.event['diff'].get('data')}")
```

In our `on_version` function, we printed out the current timestamp again (in microseconds), then printed out the event action provided by `event.event['action'].` We then printed out the changes made to the document.

## Creating an OnError function

After that, we will define an `on_error` function. It will be triggered when an error occurs while processing the data in the `on_version:`

```python
def on_error(event):
    print(f"Received error event {event}")
```

In our `on_error` function, we printed out the event that triggered the issue along with its error message.

## Starting the document streaming

We will now begin  document streaming:

```python
options = {"fields": ["document", "diff", "action"]}
stream = client.stream(doc["ref"], options, on_start, on_error, on_version)
stream.start()
```

In the code above, we defined the fields we want in every event update. Then, we passed the `on_start,` `on_error,` and `on_version` functions to the stream object and triggered it with the `start` method. 

You should get an image like the one below when the entire script executes:

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q658zoc9xxgyh4o4og3x.png)

> NOTE: You can stop active streams using the `stream.close()` method.

# A few things to note

At the time of writing, Fauna’s document streaming is still an Early Access feature. Hence there are some limitations to using it, such as:

* You cannot have more than 100 active stream connections to Fauna from a single client device.
* Document streaming is currently not supported in Node.js clients due to an HTTP/2 implementation issue.
* You can only stream Fauna documents. It is not possible to stream collections or any schema document.
* Streams can only report events to the fields and values within a document’s `data` field.
* There is currently no support for GraphQL subscriptions.

# Conclusion

In this article, we learned about Fauna’s document streaming capabilities and how easy it is to integrate Fauna’s document streaming into a Python application.

You can learn more about Fauna document streaming from the [official documentation](https://docs.fauna.com/fauna/current/drivers/streaming.html). If you have any questions, don't hesitate to contact me on Twitter: [@LordGhostX](https://twitter.com/LordGhostX).