From ed0bbeef2baa33d071f80e0e15ed616baa67f0b3 Mon Sep 17 00:00:00 2001 From: jernejfrank Date: Tue, 4 Feb 2025 11:18:37 +0800 Subject: [PATCH] Add persister best_practices docs --- docs/concepts/state-persistence.rst | 69 ++++++++++++++++++++++++++++- docs/reference/persister.rst | 4 +- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/docs/concepts/state-persistence.rst b/docs/concepts/state-persistence.rst index cd24befe..1c0bcd7e 100644 --- a/docs/concepts/state-persistence.rst +++ b/docs/concepts/state-persistence.rst @@ -117,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( @@ -153,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/docs/reference/persister.rst b/docs/reference/persister.rst index 8b610730..e8bd0002 100644 --- a/docs/reference/persister.rst +++ b/docs/reference/persister.rst @@ -2,6 +2,8 @@ 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. @@ -78,8 +80,6 @@ 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: