Skip to content

feat(runner)!: idempotent run submission via idempotency_key - #450

Draft
agutmanstein-scale wants to merge 1 commit into
mainfrom
claude/idempotent-run-submit
Draft

agutmanstein-scale wants to merge 1 commit into
mainfrom
claude/idempotent-run-submit

Conversation

@agutmanstein-scale

Copy link
Copy Markdown
Collaborator

Requested by Alec Gutmanstein · Slack thread

What and why

Before: every Runner.submit and POST /api/v1/tasks/{id}/run started a new run, so a client that retried after a lost response, or sent the same request twice, got duplicate runs.

After: submit and POST .../run take an optional idempotency_key. A repeat of the same request returns the first run's handle and starts no second run, even if the first failed. The same key with a different request is a 409 (IdempotencyConflict). POST .../runs (run groups) rejects the key with a 422.

How: LocalRunner derives the run id and instance id from sha256 of the key, and compares the stored request (task, version, instance id, parameters) before inserting the run record. The check has no await between it and the insert, so concurrent submits on one event loop cannot both pass. The explorer passes the key only when a request carries one, so a custom Runner without the parameter keeps working until a caller sends a key. The ! in the title is because the plugin-api check reports the new Runner.submit parameter as a break for overrides with the old signature.

The hub-side equivalent is scaleapi/scaleapi PR #171584 (https://github.com/scaleapi/scaleapi/pull/171584), which dedupes via Temporal workflow ids and is independent of this change.

How it was tested

  • pytest tst/unit/runner tst/unit/explorer -q: 161 passed. ruff check .: clean.
  • python .github/scripts/check_plugin_api.py --base origin/main --title "feat(runner)!: ...": reports the Runner.submit break, passes because the title carries !.
  • make unit-test: 12541 passed, 2 failed, 16 skipped. The two failures, test_cli_env.py::test_no_limits_add_no_flags and local_grant_server_test.py::test_the_platform_default_is_served_on_loopback_too_where_a_vm_on_this_machine_reaches_it, fail identically on main without this change.
  • Not run: integration, installer and clean-install tiers. User docs live on the external docs site, so no in-repo doc was changed.

Generated by Claude Code

Runner.submit and POST /api/v1/tasks/{id}/run take an optional
idempotency_key. LocalRunner derives the run and instance ids from the key,
so a repeat of the same request returns the first run's handle without
starting another, and the same key with a different request raises
IdempotencyConflict (HTTP 409 in the explorer). Run groups reject the key.

The explorer passes the key only when a request carries one. A custom Runner
whose submit lacks the new parameter keeps working until a caller sends a
key; the plugin-api check still reports the signature change, hence the !.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QaPoLEaSJECgPbYkBi9rgb

This branch has not been deployed

No deployments
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.

2 participants