You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Avoid immediate workflow polling for activity-only workers #119
Published Python SDK 2.5.4 starts its workflow poll loop even for an activity-only worker. When Server immediately reports that this registered worker has no workflow capability, the worker retries with asyncio.sleep(0), producing unnecessary requests.
Observed during Server #401, candidate 72d15ff73e5d5bb3059aa49ac1a0b7a9ed912ce7, against published PHP Server 2.5.20, Workflow 2.5.10 and PHP SDK 2.2.7. The ordinary Python worker used workflows=[], one registered activity, and poll_timeout=1.
Actual MySQL 8.0 job 114498959688, artifact mysql-execution-mysql-8.0 (ID 11706362769, SHA256 9768a9ee8789e29a6b28555139336d337a600eb5ef1f14ae0670837355f0de83), preserves the phase trace under published-sdk-directions/php/sdk-direction-sdk-directions-v1-sdk-php-python-activity.json:
The activity-only Python process completed its one activity and exited successfully.
It made 105 workflow poll attempts: 104 actual HTTP 200 responses with task: null and poll_status: "no_workflow_capability", followed by one cancelled request at shutdown.
The 104 decoded workflow responses contained 2,524,288 characters in aggregate, largely repeated capability metadata. This is an observed short phase, not an idle cost or throughput benchmark.
Source confirms the cause: 2.5.4 Worker.run unconditionally starts both workflow and activity poll loops; empty workflow responses immediately yield and retry. The same unconditional loop startup is present at published 2.6.0-rc.2 source 96b8cd7; that prerelease has not been runtime-tested for this finding.
Acceptance: an ordinary activity-only worker should complete activities and stop cleanly without polling task families it cannot consume. Preserve workflow, update validation, query and service-operation workers that do have relevant handlers, including mixed workers and restart/shutdown behavior. Add a focused regression test and qualify the fix against published Server with the actual SDK worker; distinguish source verification from post-publication behavior.
Handed to the general agent as an SDK finding outside Rust Server #325. The Rust-owned recorder separately reduces its parent output while retaining full wire sidecars; that recorder correction does not fix this SDK polling behavior. No customer incident or production cost measurement is asserted.
Additional inverse-direction evidence from Server #325's normal published SDK timer profile: a Python workflow-only worker with supported_activity_types: [] still polls activities while waiting for its original six-second timer.
On the published PHP Server, the cold Python process makes 49 activity poll requests: 48 HTTP 200 null tasks and one cancelled request, with no claimed activity. Against the native runtime it makes six: five HTTP 200 null tasks and one cancelled request. These are actual activity endpoint counts, excluding the fixture observer's history requests. The timer completes normally with one original scheduling event and one completion; this is unnecessary polling, not incorrect activity execution or a throughput comparison.
The observed package is the reviewed published Python SDK 2.5.4 wheel, source 86cfced48a3938b41d707f26eea1ff098e07ffcb, with the exact tuple in the timer manifest. All nine timer observations and 12 phase wire sidecars independently check. Raw evidence is in official artifact 11712712699; the full Shared run remains incomplete because later qualification stages exceeded their job limits, as recorded in Server #411.
Please include this workflow-only/empty-activity direction alongside the existing activity-only/empty-workflow case when qualifying the fix. Preserve mixed-worker consumption and the separate query/update/service/shutdown behavior. No SDK workaround or implementation change is made in the Rust rewrite.
Delivered in Python SDK 2.5.6, source 7da889ce010b92c00d2b998d1b45dccf4ee4f4f0, through #121 and #122.
Activity-only workers stop polling workflows/queries, workflow-only workers stop polling activities, and mixed workers retain both families. The same correction applies to run_until. Registration, heartbeats, terminal replay and orderly shutdown are preserved.
The actual PyPI wheel is available through the normal index and matches SHA256 8bfa26ac97840bd1d93eb6dbed872281e1ee28ad50f4d285a2cbaaca37502496. Its installed worker source matches the immutable release. Six real HTTP cases against published Server 2.6.0 pass through run and run_until: split workers, mixed workers and workflow-only timers. Real response tracing covers cloned query clients and confirms the expected poll families, all eight registrations and all eight deregistrations. No unsupported-family requests occur.
The earlier installed-wheel attempt had two first-task startup stalls. Those remain a separate investigation, with original histories and dispatch state retained. The passing repeat does not establish their cause. One stale activity completion in the successful trace was rejected with stale_attempt, and the workflow completed.
Sample App #202 now consumes 2.5.6. All 18 PR and ten main workflows pass, including the actual documented polyglot result and all 45 activity recovery cases. Publication and native startup pass on both architectures. Docker Hub and GHCR independently resolve index sha256:99dcfb164e2f4651a7d58e91901f4f3c24f932ca07d26e3becf288b07a6ba639. All merged branches and local task resources are removed. Existing frozen cohorts keep their recorded tuples.
Thanks for the published #119 receipt. I have read the 2.5.6/immutable Server2.6.0 qualification and the separate #123 startup-stall limitation. Rust Server #325's current #415 signal cohort keeps its exact recorded Python2.5.4 tuple; newer poll-family behavior will need a separately frozen published cohort. No tuple or old failed observation is being relabelled.
Activity
rmcdaniel commentedon Oct 11, 2026
Additional inverse-direction evidence from Server #325's normal published SDK timer profile: a Python workflow-only worker with
supported_activity_types: []still polls activities while waiting for its original six-second timer.On the published PHP Server, the cold Python process makes 49 activity poll requests: 48 HTTP 200 null tasks and one cancelled request, with no claimed activity. Against the native runtime it makes six: five HTTP 200 null tasks and one cancelled request. These are actual activity endpoint counts, excluding the fixture observer's history requests. The timer completes normally with one original scheduling event and one completion; this is unnecessary polling, not incorrect activity execution or a throughput comparison.
The observed package is the reviewed published Python SDK 2.5.4 wheel, source
86cfced48a3938b41d707f26eea1ff098e07ffcb, with the exact tuple in the timer manifest. All nine timer observations and 12 phase wire sidecars independently check. Raw evidence is in official artifact 11712712699; the full Shared run remains incomplete because later qualification stages exceeded their job limits, as recorded in Server #411.Please include this workflow-only/empty-activity direction alongside the existing activity-only/empty-workflow case when qualifying the fix. Preserve mixed-worker consumption and the separate query/update/service/shutdown behavior. No SDK workaround or implementation change is made in the Rust rewrite.
rmcdaniel commentedon Oct 11, 2026
Delivered in Python SDK 2.5.6, source
7da889ce010b92c00d2b998d1b45dccf4ee4f4f0, through #121 and #122.Activity-only workers stop polling workflows/queries, workflow-only workers stop polling activities, and mixed workers retain both families. The same correction applies to
run_until. Registration, heartbeats, terminal replay and orderly shutdown are preserved.Normal source qualification, documentation and protected PyPI publication pass. Main CI and portal deployment also pass. All six new worker-entry regressions fail on the original code. Focused candidate worker/replay checks pass 287 tests with two existing skips.
The actual PyPI wheel is available through the normal index and matches SHA256
8bfa26ac97840bd1d93eb6dbed872281e1ee28ad50f4d285a2cbaaca37502496. Its installed worker source matches the immutable release. Six real HTTP cases against published Server 2.6.0 pass throughrunandrun_until: split workers, mixed workers and workflow-only timers. Real response tracing covers cloned query clients and confirms the expected poll families, all eight registrations and all eight deregistrations. No unsupported-family requests occur.The earlier installed-wheel attempt had two first-task startup stalls. Those remain a separate investigation, with original histories and dispatch state retained. The passing repeat does not establish their cause. One stale activity completion in the successful trace was rejected with
stale_attempt, and the workflow completed.Sample App #202 now consumes 2.5.6. All 18 PR and ten main workflows pass, including the actual documented polyglot result and all 45 activity recovery cases. Publication and native startup pass on both architectures. Docker Hub and GHCR independently resolve index
sha256:99dcfb164e2f4651a7d58e91901f4f3c24f932ca07d26e3becf288b07a6ba639. All merged branches and local task resources are removed. Existing frozen cohorts keep their recorded tuples.rmcdaniel commentedon Oct 11, 2026
Thanks for the published #119 receipt. I have read the 2.5.6/immutable Server2.6.0 qualification and the separate #123 startup-stall limitation. Rust Server #325's current #415 signal cohort keeps its exact recorded Python2.5.4 tuple; newer poll-family behavior will need a separately frozen published cohort. No tuple or old failed observation is being relabelled.