a2aproject / a2aproject/a2a-python

[Feat]: NoSQL (MongoDB) TaskStore / PushNotificationConfigStore backend — production-verified reference implementation available

未关闭
#1,210 2 条评论 0 个 reaction 已指派 1 人 已被 @ishymko 认领 在 GitHub 查看
component: server status: needs review
主要语言
Python
星标
2.1k
派生
496
平均合并
4 天 17 小时
30 天内合并 PR
12

描述

## Summary

The SDK currently ships two `TaskStore` backends: `InMemoryTaskStore` and the SQLAlchemy-based `DatabaseTaskStore` (`a2a-sdk[sql]`). There is no supported path for document/NoSQL databases, even though task records are a natural fit for them. We built and deployed a MongoDB-backed `TaskStore` + `PushNotificationConfigStore` for a production A2A server (FastAPI, multi-replica) and would like to propose upstreaming a generic version — either as an optional extra (e.g. `a2a-sdk[mongodb]`) or as a documented reference implementation.

## Why a document store fits this data

- **Tasks are ephemeral, retention-bound records.** They are written per request, re-read for a bounded window (`GetTask`/`ListTasks`), and then expire. MongoDB TTL indexes handle retention natively (one index on an `updated_at` field); with SQL backends every deployment has to build its own cleanup job (cron / `EVENT` scheduler / partition rotation).
- **Many A2A server deployments already run a document store** for conversation state, and adding a relational database + Alembic migrations solely for task persistence is a heavy dependency for what is a single-collection workload.

## Implementation notes (lessons that may save others time)

We verified these against SDK 1.1.2 semantics; happy to carry them into a PR:

1. **Store the `Task` as serialized proto bytes, not ProtoJSON.** `Task.metadata` is a proto `Struct` with arbitrary client-supplied keys — keys containing `.` or `$` become invalid MongoDB document keys after `MessageToDict`. Storing `task.SerializeToString()` as opaque bytes (plus a handful of extracted top-level fields for querying: owner, `context_id`, `status.state`, `status.timestamp`) is exact, round-trip safe, and resilient to unknown fields across SDK upgrades.
2. **Owner partitioning parity.** All reads/writes are scoped by `owner_resolver(context)` (default `resolve_user_scope`), matching `InMemoryTaskStore` — including refusing cross-owner access on `get`/`delete`.
3. **Pagination matching in-memory semantics.** Sort `(status.timestamp desc — nulls last, id desc)`; the page token (`encode_page_token`) is the id of the first item of the requested page (inclusive anchor), so the store re-resolves the anchor document to build a `(timestamp, id)` cursor filter; unknown tokens raise `InvalidParamsError`. MongoDB's BSON ordering (`Date > Null` under descending sort) reproduces the in-memory null-handling exactly.
4. **`get_info_for_dispatch` must be overridden** on custom `PushNotificationConfigStore` implementations (the base fallback silently drops notifications for authenticated owners — the docstring warns about this, but it is easy to miss). Since streaming turns call it once per emitted event, we front it with a short (5s) in-process memo keyed by `task_id`, invalidated on `set_info`/`delete_info`.

The whole thing is ~200 lines for both stores. Deployed behind a FastAPI JSONRPC server; verified: task survives process restart and is served by a different replica, `ListTasks` cursor pagination over 100+ tasks, push configs dispatching across replicas.

## Questions for maintainers

1. Is there interest in an official NoSQL backend, and if so, would you prefer an optional extra (`a2a-sdk[mongodb]`, pymongo async client) or a documented recipe in the docs/examples?
2. If an extra: should it mirror `DatabaseTaskStore`'s constructor conventions (`create_table` → `ensure_indexes`, `owner_resolver` injection), and should retention (TTL) be part of the contract or left to operators?
3. Would you want the same treatment for `PushNotificationConfigStore` in the same PR?

If maintainers are open to it, we're happy to submit the PR with tests (the store semantics above are covered by a small in-memory fake collection in our suite; we can port those tests).

贡献指南

打开贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。