Skip to content

feat: Support for database backend Task Store #259

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Jul 1, 2025
Merged

feat: Support for database backend Task Store #259

merged 22 commits into from
Jul 1, 2025

Conversation

kthota-g
Copy link
Collaborator

@kthota-g kthota-g commented Jun 30, 2025

Release-As: 0.2.11

Add support for database backed TaskStore

Installation

uv add a2a-sdk[postgresql] #postgres driver
or 
uv add a2a-sdk[mysql] #mysql driver
or
uv add a2a-sdk[sqlite] #sqlite driver
or
uv add a2a-sdk[sql]. #install all three sql drivers

Usage

from a2a.server.tasks import DatabaseTaskStore
from sqlalchemy.ext.asyncio import (
        create_async_engine,
    )
...
...
# Postgres - "postgresql+asyncpg://postgres:postgres@localhost:5432/a2a_test"
# Sqlite - "sqlite+aiosqlite:///file::memory:?cache=shared"
# Mysql - "mysql+aiomysql://admin:saysoyeah@localhost:3306/testDB"
engine = create_async_engine(
    "postgresql+asyncpg://postgres:postgres@localhost:5432/a2a_test", echo=False
)
request_handler = DefaultRequestHandler(
    agent_executor=CurrencyAgentExecutor(),
    task_store=DatabaseTaskStore(engine=engine),
    push_notifier=InMemoryPushNotifier(httpx_client),
)

zboyles and others added 6 commits June 2, 2025 11:24
…) (#106)

* feat: postgresql task store

* feat: postgresql task store

* feat: postgresql task store

* feat: postgresql task store

* feat: postgresql task store

* Update check-spelling metadata

* feat: postgresql task store

* Refactor TaskStore to be database-agnostic using SQLAlchemy

This commit replaces the PostgreSQL-specific TaskStore with a generic
`DatabaseTaskStore` that leverages SQLAlchemy for database interactions.
This change allows your A2A server to support multiple database backends,
including SQLite, PostgreSQL, and MySQL.

Key changes include:
- Definition of a SQLAlchemy model `TaskModel` for storing task data.
- Implementation of `DatabaseTaskStore` that uses the `TaskStore` interface
  and SQLAlchemy for CRUD operations.
- Update of example application configurations to use `DatabaseTaskStore`
  when a `DATABASE_URL` environment variable is provided, defaulting to
  `InMemoryTaskStore` otherwise.
- Creation of parameterized unit tests for `DatabaseTaskStore`, designed
  to run against SQLite, PostgreSQL, and MySQL to ensure compatibility.
- Removal of the old `PostgreSQLTaskStore` and its specific tests.
- Addition of necessary dependencies: `sqlalchemy`, `aiosqlite`, `aiomysql`.

The new implementation makes the task persistence layer more flexible
and extensible, allowing you to choose a database backend that best
suits your needs.

* feat: postgresql task store

* feat: postgresql task store

* feat: postgresql task store

* feat: postgresql task store

* feat: postgresql task store

* Update check-spelling metadata

* feat: postgresql task store

* Refactor TaskStore to be database-agnostic using SQLAlchemy

This commit replaces the PostgreSQL-specific TaskStore with a generic
`DatabaseTaskStore` that leverages SQLAlchemy for database interactions.
This change allows your A2A server to support multiple database backends,
including SQLite, PostgreSQL, and MySQL.

Key changes include:
- Definition of a SQLAlchemy model `TaskModel` for storing task data.
- Implementation of `DatabaseTaskStore` that uses the `TaskStore` interface
  and SQLAlchemy for CRUD operations.
- Update of example application configurations to use `DatabaseTaskStore`
  when a `DATABASE_URL` environment variable is provided, defaulting to
  `InMemoryTaskStore` otherwise.
- Creation of parameterized unit tests for `DatabaseTaskStore`, designed
  to run against SQLite, PostgreSQL, and MySQL to ensure compatibility.
- Removal of the old `PostgreSQLTaskStore` and its specific tests.
- Addition of necessary dependencies: `sqlalchemy`, `aiosqlite`, `aiomysql`.

The new implementation makes the task persistence layer more flexible
and extensible, allowing you to choose a database backend that best
suits your needs.

* Refactor project to support multiple database backends

This commit introduces optional dependencies for PostgreSQL, MySQL, and SQLite support in the A2A SDK. Key changes include:
- Addition of optional dependencies in `pyproject.toml` for database drivers.
- Updates to example applications to demonstrate installation and usage with different databases.
- Refactoring of task management to utilize a generic `DatabaseTaskStore` for improved flexibility.
- Enhancements to the README for clearer instructions on database support.

These changes enhance the SDK's versatility, allowing users to choose their preferred database backend.

* Add drivername, aiomysql, and DSNs to the list of expected words in the spelling action

* GitHub Actions installs SQL dependencies for tests and database tests gracefully skip when SQLAlchemy isn't installed locally

* feat(db): refactor database backend to be database-agnostic

This allows users to choose their preferred database backend (PostgreSQL, MySQL, SQLite) while maintaining full compatibility and proper type safety.

- Replace PostgreSQL-specific JSONB with generic JSON type in models
- Implement SQLAlchemy 2.0 best practices with Mapped types and TypeDecorator
- Add configurable table name support via create_task_model() factory
- Updated metadata field mapping between Pydantic and SQLAlchemy using declared_attr
- Add comprehensive tests for metadata field mapping including complex nested data
- Update GitHub Actions to install SQL dependencies for tests
- Add pytest.importorskip to gracefully skip database tests when SQLAlchemy not installed
- Fix test_types.py to use 'id' instead of 'taskId' for JSON-RPC requests
- Add automatic cleanup of SQLite file::memory: files after tests
- Remove examples directory (moved to separate a2a-samples repo)
- Update pyproject.toml to remove workspace members reference and add `nox` for testing

* fix(models): correct variable name in TaskModel repr template

* fix: use typing_extensions for override decorator for Python 3.10 compatibility

The override decorator was added in Python 3.12. For compatibility with Python 3.10,
we import it from typing_extensions when not available in the typing module.

---------

Co-authored-by: MEUNIER Laurent <laurent@breezyai.co>
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: Zac <2215540+zboyles@users.noreply.github.com>
Co-authored-by: kthota-g <kcthota@google.com>
@kthota-g kthota-g requested a review from a team as a code owner June 30, 2025 22:39
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @kthota-g, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the A2A SDK by introducing robust, database-backed persistence for task management. It moves beyond ephemeral in-memory storage, allowing task states, artifacts, and history to be reliably stored and retrieved from various SQL databases. This change provides a foundational improvement for building more resilient and scalable applications.

Highlights

  • New Feature: Database Task Store: I've introduced a new DatabaseTaskStore implementation that allows for persistent storage of task objects using SQLAlchemy. This replaces the previous in-memory storage, enabling tasks to survive application restarts and be shared across instances.
  • Multi-Database Support: The DatabaseTaskStore supports PostgreSQL, MySQL, and SQLite, leveraging SQLAlchemy's async capabilities. Users can select their preferred database by installing the corresponding optional dependencies (e.g., a2a-sdk[postgresql]).
  • Pydantic Model Serialization: Custom SQLAlchemy TypeDecorators (PydanticType and PydanticListType) have been added to automatically serialize and deserialize Pydantic models (like TaskStatus, Artifact, Message) to and from JSON columns in the database, simplifying data handling.
  • Installation & Usage Documentation: The README.md has been updated to include clear instructions for installing the SDK with database support using uv or pip, and the PR description provides Python code examples for initializing the DatabaseTaskStore with different database engines.
  • Development & Testing Infrastructure: A Docker Compose setup for PostgreSQL has been added (docker/postgres/docker-compose.yml, docker/postgres/init.sql) to facilitate local development and testing. Comprehensive asynchronous unit tests for the DatabaseTaskStore have been implemented, covering various CRUD operations and data types across SQLite, PostgreSQL, and MySQL.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a database-backed TaskStore using SQLAlchemy. The code is well-structured, and the addition of comprehensive, parameterized tests is excellent. The feedback focuses on refactoring the save method in DatabaseTaskStore to use session.merge() and cleaning up the database initialization script and test fixtures.

@holtskinner holtskinner changed the title feat: Support for database backed Task Store feat: Support for database backend Task Store Jul 1, 2025
@holtskinner holtskinner requested a review from swapydapy July 1, 2025 18:57
@kthota-g kthota-g merged commit 7c46e70 into main Jul 1, 2025
8 checks passed
@kthota-g kthota-g deleted the sql-support branch July 1, 2025 21:43
swapydapy pushed a commit that referenced this pull request Jul 8, 2025
🤖 I have created a release *beep* *boop*
---


##
[0.2.11](v0.2.10...v0.2.11)
(2025-07-07)


### ⚠ BREAKING CHANGES

* Removes `push_notifier` interface from the SDK and introduces
`push_notification_config_store` and `push_notification_sender` for
supporting push notifications.

### Features

* Add constants for Well-Known URIs
([#271](#271))
([1c8e12e](1c8e12e))
* Adds support for List and Delete push notification configurations.
([f1b576e](f1b576e))
* Adds support for more than one `push_notification_config` per task.
([f1b576e](f1b576e))
* **server:** Add lock to TaskUpdater to prevent race conditions
([#279](#279))
([1022093](1022093))
* Support for database backend Task Store
([#259](#259))
([7c46e70](7c46e70))


### Code Refactoring

* Removes `push_notifier` interface from the SDK and introduces
`push_notification_config_store` and `push_notification_sender` for
supporting push notifications.
([f1b576e](f1b576e))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants