Repository navigation
TS SDK: add the task state store to the task client - #73618
Merged
Merged
Conversation
jason810496
reviewed
Oct 6, 2026
jason810496
left a comment
Member
There was a problem hiding this comment.
Nice, thanks! LGTM overall.
Let's also add a TODO before the serialization to respect the state_store/max_value_storage_bytes that will be passed from the coordinator side.
jason810496
reviewed
Oct 6, 2026
This was referenced Oct 6, 2026
TypeScript task handlers had no way to reach the per-task-instance state store that Python exposes as context["task_state_store"], so a retried TypeScript task could not reattach to an external job it had already submitted. The supervisor and the generated wire types already carried the four state-store messages; only the client surface was missing. The store is reached through client.taskStateStore, with get, set, delete and clear, so it reads like the Python accessor and the Java and Go stores rather than four more flat client methods. It is confined to the caller's own task instance by the Execution API, so the task instance id is bound when the coordinator client is built rather than exposed on TaskContext. Absence handling becomes operation-specific instead of one shared not-found set, because a fourth lookup makes the shared set answer null for codes an operation can never receive. Expiry is resolved on the runtime, as Python does: omitting retentionMs follows AIRFLOW__STATE_STORE__DEFAULT_RETENTION_DAYS, which the coordinator passes from [state_store] default_retention_days, and the write fails when that is absent or malformed rather than retaining the key for a period nobody configured. NEVER_EXPIRE is a symbol, so a retention that reaches Infinity by accident is rejected instead of silently storing a key forever.
The example bundle is what the ts_sdk e2e mode runs, so the new client methods need handlers there before the capability can be claimed. The e2e assertions read the store back through the public REST API rather than the task's own XCom, so they prove the values reached the database and that NEVER_EXPIRE arrives as a null expiry. Clearing lives in its own task because clear removes every key of the task instance that calls it, which would destroy the rows the round-trip test asserts on.
With the client methods in place and exercised end to end, the compatibility matrix can stop listing task-state-store as unsupported. The guide spells out the two places TypeScript deliberately differs from Python so deployment managers are not surprised: the worker-side state_store_backend is not used, and a config value of 0 means never expire while retentionMs: 0 expires the key immediately.
jason810496
force-pushed
the
ts-sdk-task-state-store
branch
from
October 9, 2026 06:57
4e3f4c7 to
481ec48
Compare
jason810496
marked this pull request as ready for review
October 9, 2026 07:03
jason810496
requested review from
amoghrajesh,
ashb,
bugraoz93,
gopidesupavan,
jscheffl and
potiuk
as code owners
October 9, 2026 07:03
jason810496
approved these changes
Oct 9, 2026
jason810496
left a comment
Member
There was a problem hiding this comment.
I just fixed the review comments myself.
Co-Authored-By: Claude <noreply@anthropic.com>
This was referenced Oct 18, 2026
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.
TypeScript task handlers had no access to the per-task-instance state store that Python tasks reach through
context["task_state_store"], so a retried TypeScript task could not reconnect to an external job an earlier attempt had submitted.The supervisor and the generated wire types already carry the four state-store messages. This change exposes them through the TypeScript client, covers them in the example bundle and the
ts_sdke2e mode, and markstask-state-storeas supported in the compatibility matrix.getClient().taskStateStorereturns a store scoped to the running task instance, with the same four operations as the Python accessor and the Java and Go stores:get<T>(key)returns the value, ornullwhen the key is missing.set(key, value, { retentionMs? })stores a value. OmittingretentionMsfollows the deployment's[state_store] default_retention_days, andNEVER_EXPIREstores the key with no expiry.delete(key)removes one key, and resolves when the key does not exist.clear()removes every key for the current task instance.Related: #73420 (Go SDK), #73464 (Java SDK).
Was generative AI tooling used to co-author this PR?
{pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.