Skip to content

Conversation

@benclarkegithub
Copy link
Contributor

  • Add delete method to TaskStore interface and InMemoryTaskStore
  • Add DatabaseTaskStore for persistent task storage using Drizzle ORM
  • Support SQLite, PostgreSQL, and MySQL databases
  • Export via new entry point @a2a-js/sdk/server/drizzle
  • Add drizzle-orm as optional peer dependency
  • Update README with installation and usage examples

Description

Thank you for opening a Pull Request!
Before submitting your PR, there are a few things you can do to make sure it goes smoothly:

  • Follow the CONTRIBUTING Guide.
  • Make your Pull Request title in the https://www.conventionalcommits.org/ specification.
    • Important Prefixes for release-please:
      • fix: which represents bug fixes, and correlates to a SemVer patch.
      • feat: represents a new feature, and correlates to a SemVer minor.
      • feat!:, or fix!:, refactor!:, etc., which represent a breaking change (indicated by the !) and will result in a SemVer major.
  • Ensure the tests and linter pass
  • Appropriate docs were updated (if necessary)

Fixes #114 🦕

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @benclarkegithub, 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 SDK's task management capabilities by introducing a robust, database-backed solution for task persistence. It allows applications to maintain task state across restarts and scale more effectively by offloading task storage from memory to a relational database. This change provides a critical feature for production deployments, ensuring task data integrity and availability.

Highlights

  • Persistent Task Storage: Introduced DatabaseTaskStore leveraging Drizzle ORM to provide persistent storage for tasks, moving beyond the in-memory default. This supports SQLite, PostgreSQL, and MySQL databases.
  • Drizzle ORM Integration: The new DatabaseTaskStore is built with Drizzle ORM, allowing tasks to be stored and retrieved from relational databases. It includes specific schema definitions and upsert logic for different SQL dialects.
  • New Entry Point: The Drizzle ORM integration is exposed via a new entry point: @a2a-js/sdk/server/drizzle, making it easy for users to import and utilize the new functionality.
  • TaskStore Interface Enhancement: The TaskStore interface now includes a delete method, which has also been implemented in the existing InMemoryTaskStore and the new DatabaseTaskStore.
  • Documentation Updates: The README.md has been updated with comprehensive installation instructions for Drizzle ORM and database drivers, along with detailed setup and usage examples for persistent task storage across supported databases.
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 by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

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 pull request 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 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. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

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.

@benclarkegithub benclarkegithub changed the title feat: addDatabaseTaskStore with Drizzle ORM support feat: add DatabaseTaskStore with Drizzle ORM support Nov 28, 2025
- Add `delete` method to TaskStore interface and InMemoryTaskStore
- Add DatabaseTaskStore for persistent task storage using Drizzle ORM
- Support SQLite, PostgreSQL, and MySQL databases
- Export via new entry point `@a2a-js/sdk/server/drizzle`
- Add drizzle-orm as optional peer dependency
- Update README with installation and usage examples
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 DatabaseTaskStore for persistent task storage using Drizzle ORM, which is a great addition for production environments. The implementation supports SQLite, PostgreSQL, and MySQL, and the new feature is well-documented in the README with clear installation and usage instructions. The changes to the TaskStore interface and InMemoryTaskStore are also correct.

I have a couple of suggestions to improve the implementation in database_task_store.ts regarding a documentation example and improving type safety for better long-term maintainability. Overall, this is a solid contribution.

* const sqlite = new Database('tasks.db');
* const db = drizzle(sqlite);
*
* const taskStore = new DatabaseTaskStore(db, sqliteTasks);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The example usage in the JSDoc for the DatabaseTaskStore constructor is incorrect. The constructor expects a single options object, but the example shows two arguments. Please update the example to match the constructor's signature and the examples in the README.

Suggested change
* const taskStore = new DatabaseTaskStore(db, sqliteTasks);
* const taskStore = new DatabaseTaskStore({ db, table: sqliteTasks, dialect: 'sqlite' });

Comment on lines +31 to +38
export type DrizzleDatabase = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
select: () => SelectQueryBuilder<any>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
insert: <TTable = any>(table: TTable) => InsertQueryBuilder;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
delete: <TTable = any>(table: TTable) => DeleteQueryBuilder;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

While the comment on lines 28-29 explains that this type is intentionally broad, using any throughout the related query builder types (lines 40-63) reduces type safety and leads to runtime checks for properties that could be verified at compile time (e.g., in the save method).

For improved maintainability, consider defining these types more strictly. Even without adding direct dependencies on DB drivers, you could use more specific structural types that better reflect the Drizzle API. This would enhance type safety and developer experience when using or extending this class.

@ishymko
Copy link
Member

ishymko commented Dec 5, 2025

Hi @benclarkegithub, thank you for the PR! Drizzle looks like a reasonable choice to me and overall I agree that providing DB-backed implementation out of the box is important.

However there is one piece missing currently which in my opinion prevents us from developing a reasonable OOTB implementation. Task store has no access to authentication context, so it's not possible to attribute tasks to users started them. Adopting such schema currently is going to cause problems with migrating it later as backfilling won't be possible. Also it doesn't play well with tasks/list method (although it's v1.0) which requires scoping to the identity of a caller.

There is a WIP support of authentication concept started in #195 (not released yet), it may require a few more things to work with DB properly:

  1. A dedicated id field (or renaming userName to id or defining semantics of the userName better).
  2. Passing ServerCallContext to stores.

Also adding a delete method to the TaskStore interface is going to be a breaking change for users who implemented this interface before. And delete method is not invoked from existing task processing lifecycle, so I think we should skip it until we define it properly (probably schedule for 1.0 which should address multi-server deployments better).

I am going to address authentication parts mentioned above and will get back to you so that we can discuss it further.

Thank you!

ishymko added a commit that referenced this pull request Dec 8, 2025
# Description

Pass `ServerCallContext` to `TaskStore` to allow DB-backed stores.
Enhance comments for `User`, stating that `userName` is a unique
identifier.

Re #213
@ishymko
Copy link
Member

ishymko commented Dec 23, 2025

Hi @benclarkegithub, with #235 TaskStore should be able to use user id/name.

A few more high-level questions to clarify:

  1. What do you think about having a column with protocol version (0.3/1.0) to facilitate migration even when there are breaking changes in the data model?
  2. Is there a chance we can omit dialect to make public facing API DB-agnostic? Maybe something can be extracted from pgTasks/sqliteTasks/mysqlTasks at runtime?
  3. What do you think about testing this integration? Seems like it should be integration testing with real DB engines in Docker. a2a-python does this.

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.

[Feat]: Need of persistent task store

2 participants