fix: load the mailbox when the gem is required - #29
Merged
Conversation
Mailbox was reachable only through the caller path, which loads it as a side effect of SolidObjects.client. The reminder scheduler and the effect executor enqueue through it directly and run in solid_objects start, a process that never calls the client, so both raised NameError on every attempt. Reminders never fired and effect result messages never delivered, while the supervisor replaced the dying role over and over. Every test passed because a test process has already loaded the constant through some other path. That is the whole shape of the bug, so the regression test runs a due reminder through a real worker, and a load contract test asks a fresh process what requiring the gem actually defines. A file that stops being loaded now fails that test unless it is listed as deliberately deferred with a reason. The roadmap listed reminders as implemented and tested while they were broken in the only process that runs them.
Greptile SummaryThe PR fixes standalone worker failures by loading
Confidence Score: 5/5The PR appears safe to merge, with the mailbox dependency loaded before every standalone worker role that uses it and targeted regression coverage for the production load path. The production change is narrowly scoped to correcting require order, and the new fresh-process and worker subprocess tests exercise the previously broken paths without exposing a concrete regression. Important Files Changed
Reviews (1): Last reviewed commit: "fix: load the mailbox when the gem is re..." | Re-trigger Greptile |
Every miss in recent work reduces to a test passing for a reason unrelated to the behavior: a constant already loaded by the test process, a double without the ensure its real collaborator runs, a mock ignoring the signal under test, a skipped adapter test reading as a pass. Two rules cover almost all of it, and both are checkable in review rather than a reminder to be careful.
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.
Fixes the reported showstopper. Version bumped to 0.10.2.
Root cause
SolidObjects::Mailboxwas never required bylib/solid_objects.rb. It was reachable only as a side effect of the caller path:SolidObjects.clientis called when an application makes an actor call. The standalone worker never calls it. So insolid_objects start,Mailboxis undefined, andMailbox.newresolves through module nesting toSolidObjects::ReminderScheduler::Mailbox, which does not exist.Reproduced in a fresh process, which is exactly how production loads:
The reminder scheduler was not the only casualty.
effect_executor.rbcallsMailbox.newin four places, so effect success and failure messages back to actors failed the same way. Same bug, different role, also only in the standalone worker.Neither role rescues, so the NameError kills the thread, the supervisor replaces it, the replacement claims the same reminder and dies again. The reminder is released each time, so it stays due forever. The test output shows that churn directly.
Why every test passed
Your diagnosis was exactly right. In any test process something has already loaded
Mailbox—client.rb,doctor.rb, or a test file requiring it directly — so the constant resolves and the code under test never exercises the load path production uses. Passing in process says nothing about the worker.So the tests here run the thing that actually breaks:
1. A due reminder through a real
solid_objects startworker. Newtest/dummy/prepare_cli_reminder.rbinserts an already-due reminder; the test boots the CLI worker as a subprocess and asserts the reminder fires. Against the unfixed code it fails with the reported error, repeated once per supervisor replacement:2. A load contract test. Asks a fresh process what
require "solid_objects"actually defines, and compares the set of unloaded files against an explicit list of deliberate deferrals, each with a stated reason:A file that stops being loaded now fails the suite unless someone argues in that list that no runtime role reaches it. That generalises past this one constant, which matters because the same shape already bit this codebase once before:
WakeUpAdapters.forreferencingDatabaseAdapterbefore it was required.Both tests were verified to fail with the fix reverted.
The fix
One line in
lib/solid_objects.rb, requiring the mailbox alongside the other runtime dependencies, with a comment recording why it cannot be left to the caller path.Validation
bundle exec rake(SQLite)docs/roadmap.mdlisted reminders under "Implemented and tested" while they were broken in the only process that runs them. Corrected to say so, and to record that they are now exercised through a real worker.