Skip to content

improvement(container-runtime): Simplify dirty state management in ContainerRuntime #24646

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

Draft
wants to merge 27 commits into
base: main
Choose a base branch
from

Conversation

markfields
Copy link
Member

@markfields markfields commented May 16, 2025

Description

Fixes AB#34161

Refactors dirty state tracking without making any behavior changes.

Dirty state tracking in ContainerRuntime appeared very ad hoc where the reality is the logic is quite simple:

  • isDirty is defined as (not attached) OR (has pending messages in Outbox or PendingStateManager)
  • Any time any of these underlying states changes, we need to check if this results in a change to dirty state, and emit the "dirty"/"saved" event if so

Reviewer Guidance

The sequence of commit was very deliberate, with extended commit descriptions explaining the change and why it's a no-op. Here's the one-line commit titles (read up from the bottom):

  • fdbd24b (HEAD -> cr/dirty-saved, fork/cr/dirty-saved) Final clean up
  • e82de84 Consolidate two updateDocumentDirtyState calls
  • 8e78133 Remove redundant if checks before updateDocumentDirtyState
  • f3ec7e5 Update isDirty to compute it, not use last emitted.
  • e675d34 Rename only: dirtyContainer to lastEmittedDirty
  • 3a729f4 Remove the asserts from updateDocumentDirtyState
  • cc05d47 Remove updateDocumentDirtyState param
  • 03faad4 Update each updateDocumentDirtyState callsite to use currentDirtyState()
  • 8ccd56c Prep

- Introduce currentDirtyState()
- Some no-op changes to simplify the code
- Some other small changes for this PR that won't affect subsequent
And add temp notes explaining why the old hardcoded values match the computed value
They're provably true now that we're using currentDirtyState rather than taking an arg

These asserts give even more confidence to this change
This will only change the result of public isDirty
for those moments between when a change to attach or pending state happens
and when we call updateDocumentDirtyState.

I checked all these codepaths, and they are all synchronous,
so this change will be a no-op for callers of this public API
In each case:
- The if check is equivalent to "no longer dirty" (meaning, we would skip if dirty)
- So the question is*: Could we have just switched from saved to dirty?  No.
  - Processing an op can't make us dirty from saved
  - Attaching can't make us dirty from saved

*This is the case where this commit's change would result in an extra dirty event where there isn't one today.
@Copilot Copilot AI review requested due to automatic review settings May 16, 2025 22:07
@github-actions github-actions bot added area: runtime Runtime related issues base: main PRs targeted against main branch labels May 16, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors the dirty state management logic in ContainerRuntime without changing behavior.

  • The test file now uses describe.only (with debug markers) instead of describe.
  • The dirty state variable is renamed from dirtyContainer to lastEmittedDirty, and updateDocumentDirtyState is refactored to compute the dirty state rather than receiving it as an argument.

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
packages/runtime/container-runtime/src/test/containerRuntime.spec.ts Changed test suite block to use describe.only with added debug comments, potentially limiting overall test execution
packages/runtime/container-runtime/src/containerRuntime.ts Renamed dirtyContainer to lastEmittedDirty and updated the updateDocumentDirtyState logic to simplify dirty state management
Comments suppressed due to low confidence (2)

packages/runtime/container-runtime/src/test/containerRuntime.spec.ts:851

  • The added debug markers ('//* ONLY') and the use of 'describe.only' may inadvertently limit the test suite execution. Please remove these debug comments and change 'describe.only' back to 'describe' to ensure that all tests run.
//* ONLY

packages/runtime/container-runtime/src/containerRuntime.ts:3313

  • Ensure that 'UsageError' is properly imported or defined in this file to avoid potential runtime issues.
throw new UsageError("already in staging mode");

@markfields
Copy link
Member Author

markfields commented May 16, 2025

Oops - I missed the point of isContainerMessageDirtyable, which is that some messages will sit in PSM but not make the container dirty. Thankfully a bunch of tests are failing.

Couple different ideas for how to fix it:

  • Add an override flag that indicates that the only pending messages are not "dirtyable"
  • Flip isDirty back to returning the class field (rename lastEmittedDirty back to something else). Leave the rest of the change where update fn doesn't take a param, etc.
  • Actually inspect the messages in Outbox/PSM inside isDirty call. This is the most correct, and I think even fixes bugs in the current code (where other calls to update don't consider non-dirtyable messages). Shouldn't be costly perf-wise since in most cases the first message we check is dirtyable

The more correct fix is to compute dirty state based on isDirtyable logic every time
@anthony-murphy
Copy link
Contributor

Oops - I missed the point of isContainerMessageDirtyable, which is that some messages will sit in PSM but not make the container dirty. Thankfully a bunch of tests are failing.

Couple different ideas for how to fix it:

  • Add an override flag that indicates that the only pending messages are not "dirtyable"
  • Flip isDirty back to returning the class field (rename lastEmittedDirty back to something else). Leave the rest of the change where update fn doesn't take a param, etc.
  • Actually inspect the messages in Outbox/PSM inside isDirty call. This is the most correct, and I think even fixes bugs in the current code (where other calls to update don't consider non-dirtyable messages). Shouldn't be costly perf-wise since in most cases the first message we check is dirtyable

why do we not dirty the container on some ops? Does this prevent switching from read to write connection mode or something?

Right before updating isDirty to calculate
@markfields markfields marked this pull request as draft May 20, 2025 16:32
@markfields
Copy link
Member Author

Back to Draft state. Might actually abandon, trying 1 or two more things to keep the current behavior but make it slightly more clear/consistent

if (this.dirtyContainer !== checkpointDirtyState) {
this.updateDocumentDirtyState(checkpointDirtyState);
}
this.updateDocumentDirtyState();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is another place where we recompute rather than restoring the previous last-emitted. Won't affect summarizer (we don't use Order Sequentially there), so should be ok.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed - Updated the "dirty" computation to account for these all the time.

@markfields
Copy link
Member Author

Test failures are due to a bug with submitting ID Allocation op before replaying pending states but we don't schedule a flush. So this PR makes the container dirty if that ID Allocation op is the only op, but then it can get stuck that way.

This prompted me to revive #24545 which delays the submission of that op until we're submitting other ops, which solves this issue. Blocking this PR until that one goes in.

It shouldn't be necessary anymore since the dirty state will be correct
since we're computing it robustly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: runtime Runtime related issues base: main PRs targeted against main branch Feature_StagingMode
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants