[PR #22] [MERGED] test: SSE conformance leg for the gateway e2e suite (+ graceful 501 degradation) #29

Closed
opened 2026-10-31 22:00:53 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/Comfy-Org/comfy-python-sdk/pull/22
Author: @sundar-svg
Created: 7/29/2026
Status: ✅ Merged
Merged: 7/30/2026
Merged by: @wei-hai

Base: main ← Head: sundar/sse-conformance-leg


📝 Commits (2)

  • 308330c test: SSE conformance leg for the gateway e2e suite
  • b77aef5 feat: events() degrades gracefully when the events endpoint is 501

📊 Changes

4 files changed (+121 additions, -2 deletions)

View changed files

📝 src/comfy_sdk/jobs.py (+13 -0)
📝 tests/conftest.py (+5 -0)
📝 tests/integration/test_gateway_e2e.py (+61 -1)
📝 tests/test_events.py (+42 -1)

📄 Description

Description

The platform-gateway now implements GET /jobs/{id}/events (SSE v1: status snapshot/change frames, output frames, 15s keepalives). This turns the manual staging smoke into a repeatable, env-gated conformance test, and pins the SDK's behavior when a surface answers the events endpoint with 501.

Commit 1 — conformance leg + behavior pins

  • test_stream_delivers_lifecycle in the env-gated gateway e2e suite: submits the model-free workflow and consumes job.events() under a daemon-thread watchdog (120s hard cap, so a wedged stream fails instead of hanging CI). Asserts: a StatusChange snapshot arrives promptly after connect (generous 30s bound; ~0.4s observed live), an OutputReady arrives before the terminal frame, iteration ends on its own at a terminal StatusChange(succeeded), and job.refresh() agrees. Duplicate frames are tolerated (snapshot semantics — no counts asserted).
  • Stub server gains an events_not_implemented mode (501 + not_implemented ErrorEnvelope) and the then-current behavior was pinned: events() raised the protocol-level comfy_low.errors.ApiError.
  • Adds the one uncovered backstop combination: a stream ending cleanly without a terminal frame + poll already terminal → synthetic terminal StatusChange, no reconnect (clean-end/poll-running and idle-timeout/poll-terminal were already covered).

Commit 2 — graceful 501 degradation

  • A 501 from the events endpoint now ends events() iteration silently (yield nothing) instead of raising, sync and async. Rationale: the spec declares 501 contract-legal for surfaces without SSE, and the SDK is poll-first with SSE as enhancement — wait()/result() remain fully functional, so a hard raise punished users for a server's legal choice. Any other ApiError from the stream still raises. Pin tests updated (old expectation documented in the docstring), including asserting wait() still completes and that there is no reconnect loop on 501.

How tested

  • uv run pytest: 105 passed, 4 skipped — the 4 skips are the integration leg without COMFY_BASE_URL/COMFY_API_KEY, proving the gating works.
  • uv run ruff check / ruff format --check / mypy src: clean.
  • The equivalent stream consumption was verified manually against staging (snapshot ~0.4s after connect, live output frame, terminal status frame, clean stream end ~20s total); this PR makes that repeatable.

🤖 Generated with Claude Code

https://claude.ai/code/session_01M2mBv9d3kfp7SmZ9uMc4tR


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/Comfy-Org/comfy-python-sdk/pull/22 **Author:** [@sundar-svg](https://github.com/sundar-svg) **Created:** 7/29/2026 **Status:** ✅ Merged **Merged:** 7/30/2026 **Merged by:** [@wei-hai](https://github.com/wei-hai) **Base:** `main` ← **Head:** `sundar/sse-conformance-leg` --- ### 📝 Commits (2) - [`308330c`](https://github.com/Comfy-Org/comfy-python-sdk/commit/308330c24a0d4d0c20558f2c59ef539afa9a1575) test: SSE conformance leg for the gateway e2e suite - [`b77aef5`](https://github.com/Comfy-Org/comfy-python-sdk/commit/b77aef5642e2ec5f33910e89c2b6ade180076e2b) feat: events() degrades gracefully when the events endpoint is 501 ### 📊 Changes **4 files changed** (+121 additions, -2 deletions) <details> <summary>View changed files</summary> 📝 `src/comfy_sdk/jobs.py` (+13 -0) 📝 `tests/conftest.py` (+5 -0) 📝 `tests/integration/test_gateway_e2e.py` (+61 -1) 📝 `tests/test_events.py` (+42 -1) </details> ### 📄 Description ## Description The platform-gateway now implements `GET /jobs/{id}/events` (SSE v1: `status` snapshot/change frames, `output` frames, 15s keepalives). This turns the manual staging smoke into a repeatable, env-gated conformance test, and pins the SDK's behavior when a surface answers the events endpoint with 501. **Commit 1 — conformance leg + behavior pins** - `test_stream_delivers_lifecycle` in the env-gated gateway e2e suite: submits the model-free workflow and consumes `job.events()` under a daemon-thread watchdog (120s hard cap, so a wedged stream fails instead of hanging CI). Asserts: a `StatusChange` snapshot arrives promptly after connect (generous 30s bound; ~0.4s observed live), an `OutputReady` arrives before the terminal frame, iteration ends on its own at a terminal `StatusChange(succeeded)`, and `job.refresh()` agrees. Duplicate frames are tolerated (snapshot semantics — no counts asserted). - Stub server gains an `events_not_implemented` mode (501 + `not_implemented` ErrorEnvelope) and the then-current behavior was pinned: `events()` raised the protocol-level `comfy_low.errors.ApiError`. - Adds the one uncovered backstop combination: a stream ending **cleanly** without a terminal frame + poll already terminal → synthetic terminal `StatusChange`, no reconnect (clean-end/poll-running and idle-timeout/poll-terminal were already covered). **Commit 2 — graceful 501 degradation** - A 501 from the events endpoint now ends `events()` iteration silently (yield nothing) instead of raising, sync and async. Rationale: the spec declares 501 contract-legal for surfaces without SSE, and the SDK is poll-first with SSE as enhancement — `wait()`/`result()` remain fully functional, so a hard raise punished users for a server's legal choice. Any other `ApiError` from the stream still raises. Pin tests updated (old expectation documented in the docstring), including asserting `wait()` still completes and that there is no reconnect loop on 501. ## How tested - `uv run pytest`: 105 passed, 4 skipped — the 4 skips are the integration leg without `COMFY_BASE_URL`/`COMFY_API_KEY`, proving the gating works. - `uv run ruff check` / `ruff format --check` / `mypy src`: clean. - The equivalent stream consumption was verified manually against staging (snapshot ~0.4s after connect, live output frame, terminal status frame, clean stream end ~20s total); this PR makes that repeatable. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01M2mBv9d3kfp7SmZ9uMc4tR --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 22:00:53 +00:00
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-python-sdk#29
No description provided.