Skip to content

fix(scheduler): try PUT before GET for schedule pause/resume (fixes #101) - #107

Draft
ambiorix2099 wants to merge 2 commits into
mainfrom
fix/scheduler-pause-resume-verb
Draft

fix(scheduler): try PUT before GET for schedule pause/resume (fixes #101)#107
ambiorix2099 wants to merge 2 commits into
mainfrom
fix/scheduler-pause-resume-verb

Conversation

@ambiorix2099

Copy link
Copy Markdown
Contributor

Pull Request type

  • Bugfix
  • Feature
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • WHOSUSING.md
  • Other (please describe):

NOTE: ./gradlew spotlessApply is not applicable — this repository is Go. go build,
go vet and go test ./... pass, and the three files touched here are gofmt clean.

Changes in this PR

conductor schedule pause and conductor schedule resume are completely broken against OSS
Conductor:

$ conductor schedule pause my_schedule
Error: Failed to pause schedule 'my_schedule': Request method 'GET' is not supported (status: 405)

The conductor-go SDK issues GET for both operations (v1.8.0,
api_scheduler_resource.go:188 and :255), but upstream OSS declares them @PutMapping.

Neither verb alone is correct, because the accepted method varies by deployment:

Deployment GET PUT
OSS Conductor (main and rc.23) 405 200
Orkes Conductor >= 2026-07-14 200 200
Orkes Conductor < 2026-07-14 200 405

Orkes gained PUT in orkes-conductor 1854375f0c ("accept PUT (not just GET) for per-schedule
pause/resume", 2026-07-14), so deployments older than that still require GET.

This tries PUT first and falls back to GET only on a 4xx. That satisfies all three rows and
converges on the RESTful verb as older Orkes builds age out, at which point the fallback can be
deleted.

The 4xx restriction is deliberate: retrying a 5xx or a transport error with a different verb would
mask the real fault and surface a misleading "method not supported" in its place.

Why in the CLI rather than the SDK. Hardcoding a.Put in conductor-go would fix OSS and break
every Orkes deployment predating 2026-07-14. Driving the endpoint from the CLI also means the
release is not gated on an SDK release cycle. The implementation bypasses
SchedulerClient.PauseSchedule/ResumeSchedule and uses the shared APIClient, which already
exposes both verbs. Adds internal.GetAPIClient, documented as a last resort for when a typed SDK
client issues the wrong request.

Testing. Stub servers model all three deployment shapes plus both-rejected, recording the verbs
received — so the tests assert not merely that the call succeeds but that the client converges on
PUT and falls back only when forced. Also covered: the 5xx no-fallback rule, and path escaping for
schedule names.

Verified end to end against Conductor OSS built from conductor-oss/conductor main: pause sets
"paused": true, resume clears it, both exit 0. Both previously returned 405.

Issue #
Fixes #101.

Found during release validation of the CLI against a server built from conductor-oss/conductor
main. Note the defect is invisible to current CI, which runs only against Orkes — where GET is
accepted. test/e2e/schedule.bats tests 15 and 16 already cover pause/resume and pass on Orkes;
they will exercise this path on both venues once #106 adds an OSS job.

Alternatives considered

Fix a.Geta.Put in conductor-go. The tidiest change (two lines) and the right long-term
end state, but it would break Orkes deployments older than 2026-07-14, and it gates this release on
an SDK release. Worth doing upstream once no supported Orkes build predates PUT — the CLI fallback
can then be removed.

Send GET first, PUT on failure. Symmetric, but it keeps the legacy verb as the default forever
and never converges. PUT-first means the fallback becomes dead code we can delete.

Branch on --server-type. Rejected: server type is OSS-vs-Enterprise, which is not the axis
that determines the verb — a recent Orkes build accepts PUT while an old one does not, and both
report the same server type. Probing the actual response is correct where a config flag would guess.

Fall back on any error, not just 4xx. Simpler, but a 500 or a dropped connection would be
retried as GET and reported as a verb problem, hiding the real failure.

🤖 Generated with Claude Code

`conductor schedule pause` and `conductor schedule resume` fail against OSS
Conductor with 405 "Request method 'GET' is not supported". The conductor-go SDK
issues GET for both (v1.8.0 api_scheduler_resource.go:188 and :255), but upstream
OSS declares them @PutMapping.

The accepted verb varies by deployment, so neither verb alone is correct:

  OSS Conductor                  PUT only  (GET -> 405)
  Orkes Conductor >= 2026-07-14  PUT or GET
  Orkes Conductor <  2026-07-14  GET only  (PUT -> 405)

Orkes gained PUT in orkes-conductor 1854375f0c ("accept PUT (not just GET) for
per-schedule pause/resume", 2026-07-14), so deployments older than that still need
GET. This tries PUT first and falls back to GET only on a 4xx, which satisfies all
three and converges on the RESTful verb as older builds age out — at which point the
fallback can be deleted.

The fallback is deliberately limited to 4xx. Retrying a 5xx or a transport error with
a different verb would mask the real fault and report a misleading "method not
supported" instead.

Implemented in the CLI rather than the SDK on purpose: hardcoding PUT in conductor-go
would fix OSS and break every Orkes deployment predating the change. It bypasses
SchedulerClient.PauseSchedule/ResumeSchedule via the shared APIClient, which already
exposes both verbs, so no SDK bump is needed to unblock the release.

Adds internal.GetAPIClient for that purpose, documented as a last resort for when a
typed SDK client issues the wrong request.

Tests cover all three deployment shapes plus both-rejected, using stub servers that
record the verbs received — asserting not just success but that the client converges
on PUT and only falls back when forced. Also covers the 5xx no-fallback rule and path
escaping.

Verified end to end against Conductor OSS built from main: pause sets "paused": true,
resume clears it, both exit 0. Previously both returned 405.

Fixes #101

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 79.16667% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
cmd/scheduler.go 77.27% 4 Missing and 1 partial ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Flag Coverage Δ
unittests 21.95% <79.16%> (+5.30%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
internal/settings.go 13.79% <100.00%> (+13.79%) ⬆️
cmd/scheduler.go 16.45% <77.27%> (+4.78%) ⬆️

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mp-orkes mp-orkes left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The correct fix for this is in the SDK.

#101 (comment)

Comment thread cmd/scheduler.go Outdated
Comment thread cmd/scheduler.go Outdated
Review feedback from @kowser-orkes on #107.

Narrows the fallback trigger from any 4xx to exactly 405. 405 is the only status that
means "wrong verb"; other 4xx have distinct causes and retrying them with GET was
wrong:

  404  the schedule, or the whole scheduler module, is absent. The retry produced a
       second 404 and reported that, masking the actionable hint added in #86.
  401  auth failure. The retry simply repeated the rejection.

Confirmed against OSS Conductor: wrong verb returns 405, a missing schedule and a
missing endpoint both return 404 — so the previous range genuinely conflated them.
`conductor schedule pause does_not_exist` now surfaces the scheduler-module hint
again instead of a fallback-induced error.

Also trims the doc comment to the three lines that carry information a reader cannot
get from the code.

Tests gain 404 and 401 cases asserting no fallback is attempted, alongside the
existing 405-falls-back and 5xx-does-not cases. Re-verified end to end against
Conductor OSS built from main: pause sets "paused": true, resume clears it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ambiorix2099 added a commit to conductor-oss/go-sdk that referenced this pull request Aug 5, 2026
Follow-up to review feedback on the downstream CLI change
(conductor-oss/conductor-cli#107), applied here so the two implementations do not
diverge.

405 is the only status that means "wrong verb". The previous 4xx range also caught
statuses with unrelated causes, and retrying those with GET was wrong:

  404  the schedule, or the whole scheduler module, is absent — the retry produced a
       second 404 and reported that instead of the real cause
  401  auth failure — the retry simply repeated the rejection

Verified against OSS Conductor: a wrong verb returns 405, while a missing schedule
and a missing endpoint both return 404, so the range genuinely conflated them.

Tests gain 404 and 401 cases asserting no fallback is attempted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ambiorix2099

Copy link
Copy Markdown
Contributor Author

Both addressed in 67c8300 — thanks, the 405 point was a real correctness fix, not just tidying.

Narrowed to 405. You were right that the 4xx range was too broad. Checked what OSS actually returns:

Condition Status
Wrong verb 405
Schedule doesn't exist 404
Endpoint absent (no scheduler module) 404

So the range conflated "wrong verb" with "not found". Concretely, schedule pause does_not_exist used to retry with GET and report the retry's error; it now surfaces the scheduler-module hint added in #86:

Error: Failed to pause schedule 'does_not_exist': scheduler API returned 404.
Hint: schedules require the scheduler module on the Conductor server...

Added tests asserting 404 and 401 do not trigger a fallback, alongside the existing 405-does and 5xx-does-not cases.

Comment trimmed to three lines.

Also applied the same 405 narrowing to the SDK PR (conductor-oss/go-sdk#276) so the two implementations don't diverge — see the note below on which one we keep.


On placement: @mp-orkes asked for this to live in the SDK instead, and he's right — I've opened conductor-oss/go-sdk#276 with the same logic in PauseSchedule/ResumeSchedule. Verified that an unmodified CLI built against that branch pauses and resumes correctly against OSS, so no CLI-side change is needed once it lands.

This PR is therefore likely to be closed in favour of a go.mod bump. Holding it open pending that decision; flagging so nobody reviews it twice.

Comment thread cmd/scheduler.go
// setSchedulePaused pauses or resumes a schedule. OSS Conductor accepts only PUT on
// these endpoints, older Orkes deployments only GET, so try PUT and fall back to GET
// on 405. Any other status is returned as-is.
func setSchedulePaused(ctx context.Context, name, action string) error {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you are making these changes conductor-oss/go-sdk#276, let's go with that instead of setSchedulePaused.

@ambiorix2099

ambiorix2099 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

@mp-orkes I'd like your call rather than guess.

So the fix definitely lands in the SDK, which is in this Go SDK PR #276.

The open question is whether this CLI PR should be closed or kept as a fallback.

@mp-orkes

mp-orkes commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

@mp-orkes your CHANGES_REQUESTED here is still the only thing blocking this, so I'd like your call rather than guess.

The SDK fix you asked for is up and approved: conductor-oss/go-sdk#276. Your review comments there are addressed in e156e73 — including the doc comment that still said "4xx" after the code was narrowed to 405, which was a real contradiction, and the trimming.

So the fix definitely lands in the SDK. The open question is only whether this CLI PR still has a job.

Option A — close this. The SDK is the right home and #276 covers it. Once it releases (or we pin the merge commit) go.mod is bumped and the CLI needs no change at all. I verified an unmodified CLI built against that branch pauses and resumes correctly on OSS, so this is provably sufficient.

Option B — keep it as a bridge. The CLI cannot consume #276 until it is released or we pin a pseudo-version, and #101 is release-blocking. Keeping this means schedule pause/resume work on OSS from the next CLI build, independent of the SDK's timeline. The cost is the same logic in two layers, with the CLI's copy shadowing the SDK's until removed.

If B, I'd suggest the removal be tied to the go.mod bump rather than left to memory — happy to open the follow-up issue now so it isn't lost.

One thing that needs doing either way: test/e2e/schedule.bats has a skip_if_oss_101 guard that shipped with #106, skipping tests 15/16 on OSS. Whichever route we take, that guard should be deleted as part of it, otherwise the tests covering this exact behaviour stay skipped and CI reports green over nothing. Noted on #101.

@ambiorix2099 tell your agent, I want a human reply.

@mp-orkes

mp-orkes commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

@mp-orkes I'd like your call rather than guess.

So the fix definitely lands in the SDK, which is in this Go SDK PR #276.

The open question is whether this CLI PR should be closed or kept as a fallback.

We need a CLI PR to update the SDK and make the scheduler tests run in OSS, not skip.

@mp-orkes
mp-orkes marked this pull request as draft August 6, 2026 15:34
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.

schedule pause/resume broken on OSS Conductor: SDK sends GET where server requires PUT (405)

5 participants