Repository navigation
fix: don't drop deferred custom events in ops.testing - #2811
tonyandrewmeyer wants to merge 8 commits into
Conversation
State.deferred only picked up notices whose event snapshot matched ops'
event regex, which needs an 'on/' in the handle path. A custom event from
an ObjectEvents created with a key ('MyCharm/on[key]/event[n]') or from an
EventSource directly on the charm ('MyCharm/event[n]') doesn't have one,
so the deferral was silently dropped and the event never ran again, while
ops itself re-emits every notice. The same snapshot then showed up in
State.stored_states as a bogus StoredState.
Read every notice instead, and leave anything with a notice out of the
stored states.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011NfZieBLjUD8cULjqRQpHm
Walking the snapshots and asking for each one's notices returned State.deferred in handle-path string order, since list_snapshots() has no ORDER BY, and apply_state then re-emitted them in that order on the next run. ops itself replays notices ordered by sequence, so do the same. The one test that changes was unpacking the opposite of what its own comment says. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
StoredState._handle_path rendered a None owner as a leading '/', while ops writes the framework's own stored state as StoredStateData[_stored]. After one State round trip that gave a second '_stored' entry with owner_path='' alongside the real one. With the path now correct, a StoredState that has no owner_path really does land on the framework's own key. A charm author who leaves out owner_path by mistake used to have the state silently ignored and would now get an obscure TypeError from the framework, so the consistency checker rejects that with a message saying what to set. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@chapman-von-monty review this PR. |
|
Here is my review of PR #2811: Executive Summary & VerdictVerdict: Request Changes Reconstructing deferred events directly from the storage notice stream ( There is one blocking validation issue in the newly introduced consistency checker rule: Blocking IssueValidate ownerless framework
Non-blocking Suggestions & Observations
|
This is a bit sycophantic for my taste, but if it doesn't always sound like that, then ignore this.
Sure, I definitely would not consider this blocking. It's extremely unrealistic: the framework's For the suggestion to reject ownerless StoredStates with other names, I would argue it's out of scope. Before this PR,
I wouldn't define the goal in this way. I'm fine adding an
This is not how changelogs/release notes are handled in any Charm Tech repos.
This is the best point in the review, but the bot missed the bug.
The description says this and there's a linked PR, so it seems like the bot should have been able to figure out this was already handled. Hard to me to know if the bot missed anything, so would be worth checking for that after James and Nhan review. |
…check The handle path treats owner_path='' the same as None, so the check for the framework's own stored state needs to as well, otherwise an empty owner_path slips through and overwrites the framework's state. Also check that event_count is an int, rather than only that it is present. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
State.deferredonly picks up a notice if its event's handle path matches ops' event regex, which needs anon/. A deferred custom event from anObjectEventscreated with a key (MyCharm/on[key]/event[n]), or from anEventSourcedirectly on the charm (MyCharm/event[n]), is silently dropped, so its handler never runs again, although ops itself re-emits every notice whatever the path. The same snapshot also shows up inState.stored_statesas a bogusStoredState.This reads every notice instead, as ops does, and leaves anything with a notice out of the stored states.
Two more things came out of looking at this, and they change what tests see, so they're worth calling out for the release notes:
State.deferredis now in the order the events were deferred, which is the order ops re-emits them in. It was in handle path string order (list_snapshots()has noORDER BY), so a test that unpackedout.deferredinto named variables may now get them the other way around. One of our own tests did, and its comment already said the new order.StoredStatewith noowner_pathis the framework's own stored state, and it is now written to the key ops reads (StoredStateData[_stored]rather than/StoredStateData[_stored]). That fixes a duplicate_storedentry withowner_path=''appearing after aStateround trip. It also means aStoredStatethat's meant to be the charm's but hasowner_pathleft out would overwrite the framework's state, so the consistency checker rejects that with a message saying what to set.Hyrum has one newly failing test and none newly passing. Valkey's
test_start_primarydefersunit_fully_started(anEventSourceon itsBaseEventsobject) in onestartrun and asserts the status after the next. With this change the deferred event is re-emitted before thatstart, as it would be in Juju, so the status differs. I think that's the test relying on the bug rather than a reason to keep it, so I think we should make this change, but open a PR to fix things there.It turned up in a multi-charm test of Valkey, where the dropped event meant its start lock was never released.