feat(states): add storage-phase config and task-state repository selector - #380
Open
vineetvora-scale wants to merge 2 commits into
Open
feat(states): add storage-phase config and task-state repository selector#380vineetvora-scale wants to merge 2 commits into
vineetvora-scale wants to merge 2 commits into
Conversation
vineetvora-scale
force-pushed
the
vineetvora/task-state-storage-phase-seam
branch
2 times, most recently
from
July 30, 2026 17:12
0be2190 to
c7ec547
Compare
…ctor Introduce TASK_STATE_STORAGE_PHASE and TASK_MESSAGE_STORAGE_PHASE settings (mongodb|postgres, default mongodb) with a derived mongodb_required property, a TaskStateRepositoryProtocol capturing the contract callers rely on through the DTaskStateRepository seam, and a get_task_state_repository() selector that resolves the backend by phase. The DI seam and both Temporal factories (task retention, scheduled agent runs) now construct the repository through the selector, so a phase switch applies to API handlers and workers alike. The postgres phase raises NotImplementedError until the Postgres repository lands, and the mongodb default keeps existing deployments unchanged.
vineetvora-scale
force-pushed
the
vineetvora/task-state-storage-phase-seam
branch
from
July 31, 2026 19:19
c7ec547 to
d28a45c
Compare
vineetvora-scale
marked this pull request as ready for review
July 31, 2026 19:26
An accepted-but-unimplemented phase previously surfaced only on first use: request-time 500s from the API and a crash inside Temporal worker wiring. Fail at process startup instead, with the misconfigured variable named in the error. The selector keeps its NotImplementedError as defense in depth for configs constructed outside refresh().
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
First PR in a short series adding an optional PostgreSQL backend for task state storage, selected per deployment by a config flag. This PR lands the configuration and the selection seam only — no behavior change: the default phase is
mongodb, and existing deployments continue to run exactly as before. Data-migration phases are out of scope for this series; if that effort happens later, it adds its own phase values (additive, not breaking).What's in this PR
1. Storage-phase settings (
src/config/environment_variables.py)TASK_STATE_STORAGE_PHASEandTASK_MESSAGE_STORAGE_PHASE:mongodb | postgres, defaultmongodb.StoragePhaseenum — a typo fails at startup instead of silently routing to a backend the operator didn't choose.postgres, until it lands in a follow-up) are rejected at config refresh — a misconfigured deployment fails at process startup with the variable named, instead of request-time 500s or a Temporal worker crash mid-wiring.mongodb_requiredproperty (true unless every store's phase ispostgres) for later use in conditional Mongo startup/readiness.2.
TaskStateRepositoryProtocol(src/domain/repositories/task_state_repository.py)DTaskStateRepositoryseam — the states use case and authorization shortcuts (create/get/update/delete/list), the retention service (find_by_field/delete_by_field/batch_create), andget_by_task_and_agent.ItemDoesNotExist/DuplicateItemError, the Mongo-shaped$inlist filter). The MongoDB repository satisfies it unchanged.3. Phase selector wired into the seam
get_task_state_repository()resolves the repository for the configured phase;DTaskStateRepositorynow points at it, so every DI consumer follows automatically.mongodbbranch touches a Mongo handle, which is what will allow running without a MongoDB connection once no store needs one.NotImplementedErrorbranch remains as defense in depth; startup validation (above) makes it unreachable through env config.4. Temporal factories routed through the selector (
src/temporal/task_retention_factory.py,src/temporal/scheduled_agent_run_factory.py)TaskStateRepository(mongodb_database)by hand, bypassing DI. Without this change, apostgres-phase deployment's workers would silently keep using MongoDB while the API used Postgres.Plus docker-compose pass-throughs for both variables (defaulting to
mongodb) on the API and worker services.Review focus
find_by_field/delete_by_field/batch_create— these are part of the contract the future Postgres repository must implement.CRUDRepositoryABC): the ABC'slist()takes no filter/pagination arguments and lacks the task-state-specific methods, and a Protocol requires no change to the MongoDB repository's class hierarchy.Testing
mongodb_requiredmatrix; selector resolution for all phases, including a test pinning that non-mongodb branches never touch Mongo wiring; both Temporal factories resolving through the selector.openapi.yamlregenerated with no diff; ruff clean.Follow-ups (separate PRs)
TaskStateORM+ a schema change creating the new (empty)task_statestable — no data is moved.TaskStatePostgresRepository+ repository tests parametrized over both backends; selector'spostgresbranch goes live.Greptile Summary
Adds fail-fast storage-phase configuration while preserving MongoDB as the only currently enabled backend.
Confidence Score: 5/5
The PR appears safe to merge.
No blocking failure remains; unsupported PostgreSQL phases are rejected before the API accepts requests or Temporal workers construct repositories, resolving the previously reported deployment-path failure.
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD E[Process environment] --> R[EnvironmentVariables.refresh] R --> V{Configured phases supported?} V -- No --> F[Fail during process startup] V -- Yes: mongodb --> S[get_task_state_repository] S --> M[TaskStateRepository] M --> A[FastAPI consumers] M --> T[Temporal factories]Reviews (2): Last reviewed commit: "fix(states): reject unimplemented storag..." | Re-trigger Greptile