Honor Remove on a supervisor that has not started - #81
Open
youdie006 wants to merge 1 commit into
Open
Conversation
Add has a not-yet-running branch that registers the service directly, and its doc says the returned token may be passed to Remove. Remove and RemoveAndWait have no matching branch: they go straight to sendControl, which returns ErrSupervisorNotStarted and changes nothing. So NewSimple, Add, Remove, ServeBackground leaves the supervisor managing the removed service and starts it. Delete the service directly when the supervisor is still notRunning. Remove already maps the sibling ErrSupervisorNotRunning to nil, so a removal that needs no work returning nil follows the existing shape. A stale id left in restartQueue is inert: both readers look the id up in services and skip it when absent, then reset the queue.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addhas an explicit not-yet-running branch (v4/supervisor.go:274) that registers the service directly instead of going through the control channel, and its doc comment says:Remove(v4/supervisor.go:704) andRemoveAndWait(:726) have no matching branch. Both go straight tosendControl, which returnsErrSupervisorNotStartedand mutates nothing.Doing the same thing after
Serveworks correctly, so the gap is specifically the pre-start state thatAddgoes out of its way to support.The fix
Delete the service directly while the supervisor is still
notRunning, mirroringAdd's branch.Removealready maps the siblingErrSupervisorNotRunningtonilat:709, so "a removal that needed no work returns nil" is the shape this file already uses.I checked the rest of the state that
Add's pre-start branch writes. It also appends torestartQueue, and I deliberately left that alone: both readers (:345and:425) donamedService, present := s.services[id]and skip when absent, then reset the queue, so a stale id there is inert. Deleting fromservicesis sufficient.Behaviour change
Remove/RemoveAndWaiton a never-started supervisor now returnnilinstead ofErrSupervisorNotStarted. No existing test row changes --ErrSupervisorNotStartedis asserted nowhere in the suite (its only references are the twosendControlsites), and the full suite is green unmodified.Verification
go test -count=1 ./...inv4-- ok, with and without the change.go vet ./...clean.gofmt -l .listsdoc.go errors_after_13.go errors_before_13.go service.goboth before and after;supervisor.goandsuture_test.goare not among them, so the count is unchanged at 4.One table test added to
suture_test.go, covering both entry points. I mutation-checked each call site on its own rather than reverting the pair together:Removecall siteTestRemoveBeforeServe/RemovealoneRemoveAndWaitcall siteTestRemoveBeforeServe/RemoveAndWaitalonestate != notRunningguard from the helperTestRemoveAndWait, then the suite times outThe third is the one that matters: without the guard the helper would delete from
serviceswhile the supervisor is running and racing the control loop, so the guard is load-bearing rather than decoration.A note on how I got there, since it nearly cost the test its value: my first version of the table did not re-bind the loop variable.
go.moddeclaresgo 1.9, so the subtests closed over the samettand both ran the second case -- and the "revert only theRemovesite" mutation passed.go vetcaught it (loop variable tt captured by func literal). Withtt := ttadded, each site fails independently as shown above.Two things I want to flag rather than leave you to find
go test -racefails on unmodifiedmastertoo, inTestShim,TestFailures,TestRemoveAndWaitand others, atsupervisor.go:566/574. That is pre-existing and unrelated to these lines -- I mention it only so the failures are not attributed to this change. There is no CI in the repo andpre-commitruns plaingo test.ok, and the change itself is green on every run. I have no explanation for it, so I would rather say so than let it pass unmentioned.What I did not change
restartQueue(stale ids are inert, as above),cancellations(never populated beforerunService),Services()which still returns nil before start, and the documentedAdd-after-terminate no-op.Disclosure: AI-assisted. I found and prepared this with an AI assistant, and I ran and verified everything above myself.