Skip to content

refactor(cluster): read status from snapshot in scheduler - #3563

Merged
mkoura merged 1 commit into
masterfrom
status_snapshot
Jul 29, 2026
Merged

refactor(cluster): read status from snapshot in scheduler#3563
mkoura merged 1 commit into
masterfrom
status_snapshot

Conversation

@mkoura

@mkoura mkoura commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

The scheduling loop in get_cluster_instance queried the status database repeatedly - several queries per cluster instance in every iteration, all while holding the global cluster lock.

Add StatusSnapshot to status_db that loads all status records with one query per table. Its read accessors mirror the module-level query functions, including the filter argument semantics, so the scheduler call sites change only from status_db.* to self.snap.*. Reads from the snapshot are plain list traversals, which shortens the time the global lock is held and makes scheduling decisions testable against an in-memory state.

Writes keep going directly to the database. Every write done by this process bumps a module-level generation counter and the snapshot refreshes itself when its generation is stale, so mid-iteration writes (e.g. mark cleanup) stay visible to subsequent reads, same as with the direct queries. Writes done by other processes cannot happen while the lock is held - the scheduler refreshes the snapshot explicitly right after acquiring the lock.

The _respin method intentionally keeps the direct database queries, as it runs outside the global lock.

@mkoura
mkoura requested a review from saratomaz as a code owner July 28, 2026 15:35
@mkoura
mkoura requested review from Copilot and removed request for saratomaz July 28, 2026 15:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 scheduler-side status reads to reduce repeated SQLite queries while holding the global cluster lock by introducing an in-memory StatusSnapshot in status_db. The snapshot loads all relevant status tables with one query each and serves subsequent reads from in-memory lists, while still ensuring freshness via a per-process write generation counter and an explicit refresh after lock acquisition.

Changes:

  • Add status_db.StatusSnapshot plus a module-level _write_generation counter to support auto-refresh on local writes and explicit refresh for cross-process writes.
  • Switch cluster_getter.get_cluster_instance scheduler read paths from direct status_db.* queries to self.snap.* snapshot accessors (refreshing once per lock acquisition).
  • Add framework_tests coverage to validate snapshot parity with module-level read functions and refresh behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
framework_tests/test_status_db.py Adds tests asserting StatusSnapshot accessor parity and refresh behavior.
cardano_node_tests/cluster_management/status_db.py Introduces write generation tracking, shared filter matching, and the StatusSnapshot implementation.
cardano_node_tests/cluster_management/cluster_getter.py Updates scheduler reads to use the snapshot and refreshes it immediately after acquiring the global lock.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread framework_tests/test_status_db.py Outdated
The scheduling loop in `get_cluster_instance` queried the status
database repeatedly - several queries per cluster instance in every
iteration, all while holding the global cluster lock.

Add `StatusSnapshot` to `status_db` that loads all status records with
one query per table. Its read accessors mirror the module-level query
functions, including the filter argument semantics, so the scheduler
call sites change only from `status_db.*` to `self.snap.*`. Reads from
the snapshot are plain list traversals, which shortens the time the
global lock is held and makes scheduling decisions testable against an
in-memory state.

Writes keep going directly to the database. Every write done by this
process bumps a module-level generation counter and the snapshot
refreshes itself when its generation is stale, so mid-iteration writes
(e.g. mark cleanup) stay visible to subsequent reads, same as with the
direct queries. Writes done by other processes cannot happen while the
lock is held - the scheduler refreshes the snapshot explicitly right
after acquiring the lock.

The `_respin` method intentionally keeps the direct database queries,
as it runs outside the global lock.
@mkoura
mkoura force-pushed the status_snapshot branch from da50f1f to 6e1e2cf Compare July 29, 2026 07:56
@mkoura
mkoura merged commit 8a26523 into master Jul 29, 2026
3 checks passed
@mkoura
mkoura deleted the status_snapshot branch July 29, 2026 08:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants