diff --git a/pull/505/.doctrees/concepts/actions.doctree b/pull/505/.doctrees/concepts/actions.doctree
index fe9af003..4e640559 100644
Binary files a/pull/505/.doctrees/concepts/actions.doctree and b/pull/505/.doctrees/concepts/actions.doctree differ
diff --git a/pull/505/.doctrees/concepts/state-persistence.doctree b/pull/505/.doctrees/concepts/state-persistence.doctree
index 346bb70f..8d484d37 100644
Binary files a/pull/505/.doctrees/concepts/state-persistence.doctree and b/pull/505/.doctrees/concepts/state-persistence.doctree differ
diff --git a/pull/505/.doctrees/environment.pickle b/pull/505/.doctrees/environment.pickle
index 5f422375..ebe86d5d 100644
Binary files a/pull/505/.doctrees/environment.pickle and b/pull/505/.doctrees/environment.pickle differ
diff --git a/pull/505/.doctrees/reference/application.doctree b/pull/505/.doctrees/reference/application.doctree
index 20bf13b6..d48c0bde 100644
Binary files a/pull/505/.doctrees/reference/application.doctree and b/pull/505/.doctrees/reference/application.doctree differ
diff --git a/pull/505/.doctrees/reference/persister.doctree b/pull/505/.doctrees/reference/persister.doctree
index 738cd079..a7cd83e7 100644
Binary files a/pull/505/.doctrees/reference/persister.doctree and b/pull/505/.doctrees/reference/persister.doctree differ
diff --git a/pull/505/_sources/concepts/actions.rst.txt b/pull/505/_sources/concepts/actions.rst.txt
index 90aeb025..541cea83 100644
--- a/pull/505/_sources/concepts/actions.rst.txt
+++ b/pull/505/_sources/concepts/actions.rst.txt
@@ -110,7 +110,7 @@ Will require the inputs to be passed in at runtime. See below for how to do that
This means that the application does not *need* the inputs to be set.
-Note: to access ``app_id`` and ``partition_key`` in your running application, you can have the :py:class:`ApplicationContext `
+Note: to access application-level metadata such as ``app_id``, ``partition_key``, ``sequence_id``, and ``action_name`` in your running application, you can have the :py:class:`ApplicationContext `
injected into your Burr Actions. This is done by adding ``__context`` to the action signature:
.. code-block:: python
@@ -121,6 +121,8 @@ injected into your Burr Actions. This is done by adding ``__context`` to the act
def my_action(state: State, __context: ApplicationContext) -> State:
app_id = __context.app_id
partition_key = __context.partition_key
+ action_name = __context.action_name
+ sequence_id = __context.sequence_id
...
@@ -303,7 +305,9 @@ that have similar capabilities as one, using a variety of :ref:`application `, :py:func:`Application.iterate `, etc.
+APIs.
In all function-based APIs, you can pass in a list of tags with the ``tags`` parameter.
In class-based APIs, you can set the ``tags`` property.
diff --git a/pull/505/_sources/concepts/state-persistence.rst.txt b/pull/505/_sources/concepts/state-persistence.rst.txt
index 8ae5f884..1c0bcd7e 100644
--- a/pull/505/_sources/concepts/state-persistence.rst.txt
+++ b/pull/505/_sources/concepts/state-persistence.rst.txt
@@ -43,7 +43,7 @@ Note that ``partition_key`` can be `None` if this is not relevant. A UUID is alw
You set these values using the :py:meth:`with_identifiers() ` method.
-Note: to access ``app_id`` and ``partition_key`` in your running application, you can have the :py:class:`ApplicationContext `
+Note: to access application-level metadata such as ``app_id``, ``partition_key``, ``sequence_id``, and ``action_name`` in your running application, you can have the :py:class:`ApplicationContext `
injected into your Burr Actions. This is done by adding ``__context`` to the action signature:
.. code-block:: python
@@ -54,6 +54,8 @@ injected into your Burr Actions. This is done by adding ``__context`` to the act
def my_action(state: State, __context: ApplicationContext) -> State:
app_id = __context.app_id
partition_key = __context.partition_key
+ action_name = __context.action_name
+ sequence_id = __context.sequence_id
...
@@ -115,7 +117,7 @@ To make the above more concrete, let's look at a basic chatbot:
.. code-block:: python
- state_persister = SQLLitePersister(db_path=".sqllite.db", table_name="burr_state")
+ state_persister = SQLLitePersister.from_values(db_path=".sqllite.db", table_name="burr_state")
app = (
ApplicationBuilder()
.with_actions(
@@ -151,10 +153,75 @@ See :ref:`available persisters here `.
Note that the tracker also allows reloading from a file, but this is not recommended for production use.
+Persister Usage
+______________________________
+We follow the naming convention ``b_database-dependency-library``, where the ``b_`` is used to avoid name
+clashing with the underlying library. We chose the library name in case we implement the same database
+persister with different dependency libraries to keep the class naming convention.
+
+To initialize the persister we recommend using one of the two class methods: ``.from_config(...)`` or ``.from_values(...)`` that
+establish a connection to the database and return the persister object. In case you already have a database connection
+established (or using a connection pool), you can also initialize the persister directly and pass in the database
+connection as the first argument.
+
+We recommend that you manually handle the database connection cleanup. For now, in the case of
+synchronous persisters, the connection gets closed when the object is deleted. For asynchronous
+persisters this is not possible. Therefore, we suggest that you either use the persister as a context
+manager
+
+.. code-block:: python
+
+ with SQLLitePersister.from_values(
+ db_path=".sqllite.db",
+ table_name="burr_state"
+ ) as state_persister:
+
+ app = (
+ ApplicationBuilder()
+ .with_actions(...)
+ .with_transitions(...)
+ .initialize_from(
+ state_persister, ...
+ )
+ .with_state_persister(state_persister)
+ .with_identifiers(app_id=app_id)
+ .build()
+ )
+
+ *_, state = app.run(...)
+
+or manually close the connection to the database, by using the `.cleanup()` method of the persister
+
+.. code-block:: python
+
+ state_persister = SQLLitePersister.from_values(db_path=".sqllite.db", table_name="burr_state")
+ app = (
+ ApplicationBuilder()
+ .with_actions(...)
+ .with_transitions(...)
+ .initialize_from(
+ state_persister, ...
+ )
+ .with_state_persister(state_persister)
+ .with_identifiers(app_id=app_id)
+ .build()
+ )
+
+ try:
+ *_, state = app.run(...)
+ except Exception as e:
+ ...
+ finally:
+ state_persister.cleanup()
+
+to ensure no database connection leakage.
+
+
Customizing State Persistence
-----------------------------
-Burr exposes the :py:class:`BaseStatePersister ` API for custom state persistence. Implement,
+Burr exposes two APIs :py:class:`BaseStatePersister ` (sync) and
+:py:class:`AsyncBaseStatePersister ` (async) for custom state persistence. Implement,
pass into the above functions, and you can write to whatever database you want! Please contribute back to the community if you do so.
diff --git a/pull/505/_sources/reference/persister.rst.txt b/pull/505/_sources/reference/persister.rst.txt
index e6068023..e8bd0002 100644
--- a/pull/505/_sources/reference/persister.rst.txt
+++ b/pull/505/_sources/reference/persister.rst.txt
@@ -2,11 +2,34 @@
State Persistence
=================
+.. _persistersref:
+
Burr provides a set of tools to make loading and saving state easy. These are functions
that will be used by lifecycle hooks to save and load state.
+We currently support the following database integrations:
+
+.. table:: Burr Implemented Persisters
+ :widths: auto
+
+ +-------------+-----------------------------------------------------------------+---------------------------------------------------------------------+
+ | Database | Sync | Async |
+ +=============+===========+=====================================================+===============+=====================================================+
+ | SQLite | sqlite3 | :ref:`SQLitePersister ` | aiosqlite | :ref:`AsyncSQLitePersister ` |
+ +-------------+-----------+-----------------------------------------------------+---------------+-----------------------------------------------------+
+ | PostgreSQL | psycopg2 | :ref:`PostgreSQLPersister ` | asyncpg | :ref:`AsyncPostgreSQLPersister ` |
+ +-------------+-----------+-----------------------------------------------------+---------------+-----------------------------------------------------+
+ | Redis | redis | :ref:`RedisBasePersister ` | redis.asyncio | :ref:`AsyncRedisBasePersister ` |
+ +-------------+-----------+-----------------------------------------------------+---------------+-----------------------------------------------------+
+ | MongoDB | pymongo | :ref:`MongoDBBasePersister ` | ❌ | ❌ |
+ +-------------+-----------+-----------------------------------------------------+---------------+-----------------------------------------------------+
+
+We follow the naming convention ``b_dependency-library``, where the ``b_`` is used to avoid name
+clashing with the underlying library. We chose the library name in case we implement the same database
+persister with different dependency libraries to keep the class naming convention.
+
If you want to implement your own state persister (to bridge it with a database), you should implement
-the ``BaseStatePersister`` interface.
+the ``BaseStatePersister`` or the ``AsyncBaseStatePersister`` interface.
.. autoclass:: burr.core.persistence.BaseStatePersister
:members:
@@ -57,27 +80,32 @@ Internally, this interface combines the following two interfaces:
Supported Sync Implementations
================================
-.. _persistersref:
-
Currently we support the following, although we highly recommend you contribute your own! We will be adding more shortly.
+.. _syncsqliteref:
+
.. autoclass:: burr.core.persistence.SQLitePersister
:members:
.. automethod:: __init__
+.. _syncpostgresref:
-.. autoclass:: burr.integrations.persisters.postgresql.PostgreSQLPersister
+.. autoclass:: burr.integrations.persisters.b_psycopg2.PostgreSQLPersister
:members:
.. automethod:: __init__
+.. _syncredisref:
+
.. autoclass:: burr.integrations.persisters.b_redis.RedisBasePersister
:members:
.. automethod:: __init__
-.. autoclass:: burr.integrations.persisters.b_mongodb.MongoDBBasePersister
+.. _syncmongoref:
+
+.. autoclass:: burr.integrations.persisters.b_pymongo.MongoDBBasePersister
:members:
.. automethod:: __init__
@@ -90,11 +118,27 @@ although it uses different mechanisms to save state (as it tracks more than just
Supported Async Implementations
================================
+.. _asyncpersistersref:
+
Currently we support the following, although we highly recommend you contribute your own! We will be adding more shortly.
-.. _asyncpersistersref:
+.. _asyncsqliteref:
.. autoclass:: burr.integrations.persisters.b_aiosqlite.AsyncSQLitePersister
:members:
.. automethod:: __init__
+
+.. _asyncpostgresref:
+
+.. autoclass:: burr.integrations.persisters.b_asyncpg.AsyncPostgreSQLPersister
+ :members:
+
+ .. automethod:: __init__
+
+.. _asyncredisref:
+
+.. autoclass:: burr.integrations.persisters.b_redis.AsyncRedisBasePersister
+ :members:
+
+ .. automethod:: __init__
diff --git a/pull/505/concepts/actions/index.html b/pull/505/concepts/actions/index.html
index 4ade348a..1922ec58 100644
--- a/pull/505/concepts/actions/index.html
+++ b/pull/505/concepts/actions/index.html
@@ -457,7 +457,7 @@ Actions
+response_to_display
– referred to as @tag:response_to_display
in the halt_after
or halt_before
parameters
+of Application.run
, Application.iterate
, etc.
+APIs.
In all function-based APIs, you can pass in a list of tags with the tags
parameter.
In class-based APIs, you can set the tags
property.
diff --git a/pull/505/concepts/state-persistence/index.html b/pull/505/concepts/state-persistence/index.html
index 9cca8641..4e62810d 100644
--- a/pull/505/concepts/state-persistence/index.html
+++ b/pull/505/concepts/state-persistence/index.html
@@ -405,7 +405,7 @@ State Keys