-
Notifications
You must be signed in to change notification settings - Fork 0
fix: give payload blocks an actor receiver and a context #26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # rbs_inline: enabled | ||
|
|
||
| module SolidObjects | ||
| # Authorization context resolvers gained keywords after applications had | ||
| # already written them, so a resolver is called with what it declared it | ||
| # accepts rather than with everything the caller could offer. | ||
| module CallableKeywords | ||
| class << self | ||
| # @rbs (untyped, Symbol) -> bool | ||
| def accepts?(callable, keyword) | ||
| parameters(callable).any? do |type, name| | ||
| type == :keyrest || (%i[key keyreq].include?(type) && name == keyword) | ||
| end | ||
| end | ||
|
|
||
| private | ||
|
|
||
| # A lambda answers `parameters` directly; a callable object answers it | ||
| # through its `call` method. | ||
| # @rbs (untyped) -> Array[[ Symbol, Symbol ]] | ||
| def parameters(callable) | ||
| return callable.parameters if callable.respond_to?(:parameters) | ||
| return callable.method(:call).parameters if callable.respond_to?(:call) | ||
|
|
||
| [] | ||
| end | ||
| end | ||
| end | ||
| end |
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
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
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
Oops, something went wrong.
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a resolver, payload block, serialization, or transmission raises,
transmit_state_payloadsuppresses the error but this assignment still marks the entire revision as delivered. Subsequent broadcasts at the same revision are deduplicated, so the subscriber cannot receive the missing payload until the actor advances to a newer revision.Prompt To Fix With AI
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Confirmed and fixed in 36bb36d. You are right that this was reachable and quiet:
@payload_revisionadvanced whether or not anything was delivered, so a transient failure recorded the revision as done andnewer_payload_revision?deduplicated every later attempt at it. Within one connection the subscriber went without that payload until the actor happened to mutate again.The watermark now advances only when every payload for the revision settled.
transmit_state_payloadreturns whether it settled, and every name is still attempted before the decision is made, so one failure does not skip its siblings.Unauthorizedcounts as settled. That decision is stable, so holding the watermark open for it would re-deliver its authorized siblings on every subsequent broadcast at the same revision without ever changing the outcome.New test "a payload that failed is retried at the same revision" uses a payload that fails only its first attempt, then replays the same broadcast without mutating. It fails against the previous commit with
Expected nil to not be nil.bundle exec rake: 365 runs, 1248 assertions, 0 failures, 0 errors, 13 skips.@greptileai review
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fix is correct and the design is sound.
Watermark logic.
return if attempts.any?(false)correctly holds the revision open on any transient failure.Unauthorizedreturningtrue(settled) is the right call — retrying it would only re-deliver its authorized siblings without changing the outcome, and the comment makes that reasoning explicit.One edge case worth noting in docs: if a payload block fails persistently (not just transiently), the watermark never advances and every subsequent actor mutation retries all names for that revision indefinitely. That's the correct behavior for a transient error, but for a persistent bug it generates a
payload_broadcast_failedevent on every broadcast rather than just the first. The upgrade notes already recommend subscribing to that event — worth adding a line that a sustained stream of events for the samepayload_namesignals a persistent block error rather than a one-off.Test coverage. Failing only on the first attempt and replaying the broadcast without mutating is the right way to isolate the watermark behavior specifically — it rules out "actor advanced again" as the reason for re-delivery. Clean.
Tip: You can customize Greptile's behavior for this repo with
.greptile/rules.mdand.greptile/config.json.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in d2151ec. Kept the behaviour and documented the distinction, since retry-until-success is the correct response to a transient failure and the noise is the honest signal for a persistent one: each event means a subscriber really did miss that revision.
The docs now say retries are driven by broadcasts rather than a timer, so a persistent fault retries once per actor mutation and reports every attempt, while a transient one reports once and recovers. A repeating stream for one
payload_namemeans a persistent fault in that block.@greptileai review
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation lands exactly right. The transient/persistent distinction is stated in operational terms an on-call engineer can act on: one event that doesn't recur → transient, already recovered; repeating stream for one
payload_name→ persistent fault in that block. The retry cadence (once per actor mutation, not a timer) is also explicit, which matters for sizing the noise.Two smaller additions I noticed that weren't in scope of the original suggestion but are good additions:
turn,hand_forwithout explicitself) shows theinstance_execfix in the one place where it actually matters to a reader writing a payload block for the first time.Thread is resolved from my side.