fix(lifecycle): preserve normal owner shutdown reasons - #367
Merged
Merged
Conversation
Jido.Scheduler.Job and Jido.Sensor.Runtime stop when the owner process
they monitor exits, but wrapped every reason as {:owner_down, reason}.
A clean owner shutdown therefore produced a reason OTP classifies as
abnormal: every sensor and cron job logged a "GenServer terminating"
crash report on the normal shutdown path, and a :transient child would
be restarted after its owner was already gone.
Mirror :normal, :shutdown and {:shutdown, term} as-is and keep wrapping
anything else. Extract the classification into a single
Jido.Util.clean_exit_reason?/1, replacing the duplicate predicates in
AgentServer and Lifecycle.Keyed so the four copies cannot drift.
- no caller depends on the old shape; abnormal exits still yield
{:owner_down, reason}
- sensors implementing terminate/2 now receive the owner's own reason,
documented in the Sensor.Runtime moduledoc
- Scheduler.Job logs the owner exit for parity with Sensor.Runtime,
which otherwise leaves a clean owner exit with no trace
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011SvMs4VNrCVzWi6RNo4Xrv
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.
Description
Jido.Scheduler.JobandJido.Sensor.Runtimemonitor an owner process and stop when it exits, but both wrapped every reason as{:owner_down, reason}. A clean owner shutdown therefore produced an exit reason OTP classifies as abnormal:GenServer terminatingcrash report on the normal shutdown path (Jido.AgentServer.SensorLifecyclepassesowner_pid: self(), so each sensor monitors the agent server);:transientchild would be restarted after its owner was already gone.This mirrors
:normal,:shutdownand{:shutdown, term}as-is and keeps wrapping anything else.The runtime already had this exact classification in two other places —
AgentServer.normal_cron_exit?/1andLifecycle.Keyed.clean_shutdown?/1— so the fix would have made four copies. All four now route through a singleJido.Util.clean_exit_reason?/1.Notes:
grep owner_down lib/returns only the definitions). Abnormal exits still yield{:owner_down, reason}.terminate/2now receive the owner's own reason instead of{:owner_down, _}.@callback terminate(reason :: term(), ...)documents no shape, so this is not a contract break, and it makes standard OTP reason matching work in user sensors. Documented in a new Owner Monitoring section of theSensor.Runtimemoduledoc.Scheduler.Jobnow logs the owner exit at debug, for parity withSensor.Runtime— a clean owner exit otherwise leaves no trace at all.Type of Change
Breaking Changes
None. The only observable change on the abnormal path is unchanged; on the clean path the exit reason becomes the owner's own reason rather than a wrapper.
Testing
mix test) — 2283 passed, 187 excludedmix quality) — format,--warnings-as-errors, credo, dialyzer (0 errors)Each preserved reason is its own test rather than a loop, so one failing reason cannot mask the others. Verified by reverting the fix locally: all six
preserves …tests fail, and the twowraps an abnormal owner exitregression guards still pass.Checklist
CHANGELOG.md(it is auto-generated by git_ops)Related Issues
N/A
🤖 Generated with Claude Code
https://claude.ai/code/session_011SvMs4VNrCVzWi6RNo4Xrv
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.