[GH-ISSUE #12] Migrate job cancel onto POST /api/jobs/{job_id}/cancel #2

Closed
opened 2026-10-26 22:33:42 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @mattmillerai on GitHub (Jun 21, 2026).
Original GitHub issue: https://github.com/Comfy-Org/comfy-swift-sdk/issues/12

Background

The OpenAPI contract drift check (added in #11) flags two endpoints the SDK depends on that are on the deprecation path toward /api/jobs:

SDK use Current endpoint Contract status Target
Transport.fetchJobStatus (reattach / polling status read) GET /api/prompt/{prompt_id} not in the front-facing contract GET /api/jobs/{job_id} (getJobDetail)
Transport.cancelJob (cooperative + reattach cancel) POST /api/queue {"delete":[id]} deprecated: true POST /api/jobs/{job_id}/cancel (cancelJob)

Both appear as non-blocking warnings in the OpenAPI Contract CI job today.

Key fact

prompt_id and job_id are the same identifier. JobHandle.id (a prompt_id from submit) is already the correct path parameter for /api/jobs/{job_id} — no id mapping or extra lookup is required.

What changes

GET /api/jobs/{job_id} → JobDetailResponse

  • Status enum remap (JobDetailResponse.status is user-friendly, not the legacy ComfyUI strings):

    New (/api/jobs) Legacy (/api/prompt/{id}) JobEvent
    pending queued .queued
    in_progress running .progress
    completed success .complete
    failed error .failed
    cancelled cancelled .cancelled
  • outputs is unchanged — the spec describes it as the "Full outputs object from ComfyUI", i.e. the same node-keyed {images/videos/...} dict the SDK already decodes via NodeOutputPayload. The /api/view byte-fetch path does not change.

  • execution_error → ExecutionError (structured) for the .failed mapping; execution_status carries the timeline/progress.

POST /api/jobs/{job_id}/cancel → JobCancelResponse

  • Response is { "cancelled": boolean }. The SDK fires this best-effort and yields .cancelled, same as today.

Affected files

  • Internal/Transport.swift — fetchJobStatus, cancelJob
  • Internal/DTOs/JobStatusDTO.swift — add the /api/jobs response DTO + status normalization (foundation added in the linked PR)
  • Internal/PollingFallback.swift, Internal/ReattachCoordinator.swift — status-string handling
  • Internal/WebSocketSession.swift — cooperative-cancel POST
  • Tests + Scripts/contract/sdk-endpoints.yml (move the two entries onto /api/jobs)

Acceptance criteria

  • fetchJobStatus reads GET /api/jobs/{job_id} and maps the new status enum
  • cancelJob posts POST /api/jobs/{job_id}/cancel
  • Outputs continue to assemble via the unchanged /api/view path
  • Tests updated to the new endpoints/shapes; full suite green
  • Contract manifest moved onto /api/jobs; drift check returns 0 warnings for these
  • Staging smoke test against cloud.comfy.org confirms a real submit → status → output → cancel round-trip (this is the only thing the unit suite cannot prove)

Out of scope

WebSocket /ws and /oauth/* — not modeled by the contract; unaffected.

🤖 Generated with Claude Code

Originally created by @mattmillerai on GitHub (Jun 21, 2026). Original GitHub issue: https://github.com/Comfy-Org/comfy-swift-sdk/issues/12 ## Background The OpenAPI contract drift check (added in #11) flags two endpoints the SDK depends on that are on the deprecation path toward `/api/jobs`: | SDK use | Current endpoint | Contract status | Target | |---|---|---|---| | `Transport.fetchJobStatus` (reattach / polling status read) | `GET /api/prompt/{prompt_id}` | **not in the front-facing contract** | `GET /api/jobs/{job_id}` (`getJobDetail`) | | `Transport.cancelJob` (cooperative + reattach cancel) | `POST /api/queue {"delete":[id]}` | **`deprecated: true`** | `POST /api/jobs/{job_id}/cancel` (`cancelJob`) | Both appear as non-blocking warnings in the `OpenAPI Contract` CI job today. ## Key fact **`prompt_id` and `job_id` are the same identifier.** `JobHandle.id` (a `prompt_id` from `submit`) is already the correct path parameter for `/api/jobs/{job_id}` — no id mapping or extra lookup is required. ## What changes ### `GET /api/jobs/{job_id}` → `JobDetailResponse` - **Status enum remap** (`JobDetailResponse.status` is `user-friendly`, not the legacy ComfyUI strings): | New (`/api/jobs`) | Legacy (`/api/prompt/{id}`) | `JobEvent` | |---|---|---| | `pending` | `queued` | `.queued` | | `in_progress` | `running` | `.progress` | | `completed` | `success` | `.complete` | | `failed` | `error` | `.failed` | | `cancelled` | `cancelled` | `.cancelled` | - **`outputs` is unchanged** — the spec describes it as the "Full outputs object from ComfyUI", i.e. the same node-keyed `{images/videos/...}` dict the SDK already decodes via `NodeOutputPayload`. **The `/api/view` byte-fetch path does not change.** - `execution_error` → `ExecutionError` (structured) for the `.failed` mapping; `execution_status` carries the timeline/progress. ### `POST /api/jobs/{job_id}/cancel` → `JobCancelResponse` - Response is `{ "cancelled": boolean }`. The SDK fires this best-effort and yields `.cancelled`, same as today. ## Affected files - `Internal/Transport.swift` — `fetchJobStatus`, `cancelJob` - `Internal/DTOs/JobStatusDTO.swift` — add the `/api/jobs` response DTO + status normalization (foundation added in the linked PR) - `Internal/PollingFallback.swift`, `Internal/ReattachCoordinator.swift` — status-string handling - `Internal/WebSocketSession.swift` — cooperative-cancel POST - Tests + `Scripts/contract/sdk-endpoints.yml` (move the two entries onto `/api/jobs`) ## Acceptance criteria - [ ] `fetchJobStatus` reads `GET /api/jobs/{job_id}` and maps the new status enum - [ ] `cancelJob` posts `POST /api/jobs/{job_id}/cancel` - [ ] Outputs continue to assemble via the unchanged `/api/view` path - [ ] Tests updated to the new endpoints/shapes; full suite green - [ ] Contract manifest moved onto `/api/jobs`; drift check returns 0 warnings for these - [ ] **Staging smoke test against `cloud.comfy.org`** confirms a real submit → status → output → cancel round-trip (this is the only thing the unit suite cannot prove) ## Out of scope WebSocket `/ws` and `/oauth/*` — not modeled by the contract; unaffected. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bsakaguchi 2026-10-26 22:33:42 +00:00
Author
Owner

@coderabbitai[bot] commented on GitHub (Jun 21, 2026):

🔗 Related PRs

Comfy-Org/ComfyUI#14493 - Add jobs-namespace cancel endpoints (POST /api/jobs/{job_id}/cancel, POST /api/jobs/cancel) [merged]
Comfy-Org/comfy-cloud-mcp-server#384 - feat: add wait_for_job blocking tool to replace get_job_status polling (BE-1231) [merged]
Comfy-Org/ComfySwiftSDK#5 - fix(reattach): retry transient catch-up GET failures instead of failing the stream [merged]
Comfy-Org/ComfySwiftSDK#8 - fix(transport): migrate job-status fetch off tombstoned /api/prompt to /api/jobs [merged]
Comfy-Org/ComfySwiftSDK#11 - CI: build/test workflow + OpenAPI contract drift check [closed]


🧪 Issue enrichment is currently in open beta.

You can configure auto-planning by selecting labels in the issue_enrichment configuration.

To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

issue_enrichment:
  auto_enrich:
    enabled: false

💬 Have feedback or questions? Drop into our discord!

<!-- gh-comment-id:4761126883 --> @coderabbitai[bot] commented on GitHub (Jun 21, 2026): <!-- This is an auto-generated issue plan by CodeRabbit --> <details> <summary>🔗 Related PRs</summary> Comfy-Org/ComfyUI#14493 - Add jobs-namespace cancel endpoints (POST /api/jobs/{job_id}/cancel, POST /api/jobs/cancel) [merged] Comfy-Org/comfy-cloud-mcp-server#384 - feat: add wait_for_job blocking tool to replace get_job_status polling (BE-1231) [merged] Comfy-Org/ComfySwiftSDK#5 - fix(reattach): retry transient catch-up GET failures instead of failing the stream [merged] Comfy-Org/ComfySwiftSDK#8 - fix(transport): migrate job-status fetch off tombstoned /api/prompt to /api/jobs [merged] Comfy-Org/ComfySwiftSDK#11 - CI: build/test workflow + OpenAPI contract drift check [closed] </details> --- <details> <summary> 🧪 Issue enrichment is currently in open beta.</summary> You can configure auto-planning by selecting labels in the issue_enrichment configuration. To disable automatic issue enrichment, add the following to your `.coderabbit.yaml`: ```yaml issue_enrichment: auto_enrich: enabled: false ``` </details> 💬 Have feedback or questions? Drop into our [discord](https://discord.gg/coderabbit)!
Author
Owner

@mattmillerai commented on GitHub (Jun 21, 2026):

Update: the status-read half of this migration already shipped in #8 (GET /api/prompt/{id} → GET /api/jobs/{job_id}, with the status enum remap). This issue now tracks only the remaining piece:

  • Transport.cancelJob / WebSocketSession cooperative cancel still post to the deprecated POST /api/queue {"delete":[id]}.
  • Migrate to POST /api/jobs/{job_id}/cancel (prompt_id == job_id), response { "cancelled": boolean }, fired best-effort, still yielding .cancelled.
  • Then move the POST /api/queue entry in Scripts/contract/sdk-endpoints.yml onto /api/jobs/{job_id}/cancel — the contract drift check will go to 0 warnings.

Gate: a staging smoke test confirming a real cancel round-trip.

<!-- gh-comment-id:4761211193 --> @mattmillerai commented on GitHub (Jun 21, 2026): **Update:** the status-read half of this migration already shipped in #8 (`GET /api/prompt/{id}` → `GET /api/jobs/{job_id}`, with the status enum remap). This issue now tracks only the remaining piece: - `Transport.cancelJob` / `WebSocketSession` cooperative cancel still post to the **deprecated** `POST /api/queue {"delete":[id]}`. - Migrate to `POST /api/jobs/{job_id}/cancel` (`prompt_id` == `job_id`), response `{ "cancelled": boolean }`, fired best-effort, still yielding `.cancelled`. - Then move the `POST /api/queue` entry in `Scripts/contract/sdk-endpoints.yml` onto `/api/jobs/{job_id}/cancel` — the contract drift check will go to **0 warnings**. Gate: a staging smoke test confirming a real cancel round-trip.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Comfy-Org/comfy-swift-sdk#2
No description provided.