Skip to content

refactor(sync): collapse SyncState to enum plus single non-trivial property#729

Merged
tcoratger merged 1 commit into
leanEthereum:mainfrom
tcoratger:refactor/sync-state-collapse
May 18, 2026
Merged

refactor(sync): collapse SyncState to enum plus single non-trivial property#729
tcoratger merged 1 commit into
leanEthereum:mainfrom
tcoratger:refactor/sync-state-collapse

Conversation

@tcoratger
Copy link
Copy Markdown
Collaborator

Summary

SyncState was 163 lines for a three-state enum. Most of the surface
was trivial state == SyncState.X wrappers and a state-machine helper
with one caller. Collapses to the enum plus a single non-trivial
property, with the transition logic inlined where it actually runs.

Net: -225 lines across 4 files, zero behavior change.

What changed

states.py — 163 -> 32 lines

Removed:

  • is_idle, is_syncing, is_synced properties — each wrapped a
    one-line == comparison. Zero clarity gain, extra API surface.
  • can_transition_to(target) method — used at exactly one call site.
  • Module-level _VALID_TRANSITIONS dict — only fed the helper above.
  • Heavy per-state prose docstrings ("The Lifecycle", "Transitions",
    etc.).

Kept:

  • The enum itself.
  • accepts_gossip — the only property that does real work
    (self in {SYNCING, SYNCED}), used at 3 call sites.

service.py — small net reduction

Removed SyncService.is_syncing and is_synced public properties.
Grep confirmed zero callers outside the file itself. Anyone needing
them can write service.state == SyncState.X.

Updated 3 call sites that used the removed enum properties:

  • self._state.is_syncing -> self._state == SyncState.SYNCING (x2)
  • self._state.is_idle -> self._state == SyncState.IDLE (x1)

Rewrote _transition_to to inline the validity check now that
can_transition_to is gone. The original 5-edge transition table
becomes two invariants:

forbidden = new_state == self._state or (
    self._state == SyncState.IDLE and new_state == SyncState.SYNCED
)

Verified case-by-case against the original table — same semantics.

test_states.py — 135 -> 47 lines

Dropped tests for removed methods (can_transition_to, is_X).
Kept and tightened tests for the enum and accepts_gossip.

test_service.py — +10 lines

Added test_self_transition_raises_value_error to maintain coverage
of the no-self-transition invariant, replacing the parametrized test
that lived on can_transition_to. The IDLE -> SYNCED forbidden case
was already covered by an existing test.

Test plan

  • ruff check, ruff format --check, ty check all pass
  • pytest tests/lean_spec/subspecs/sync tests/lean_spec/subspecs/networking/test_network_service.py
    -> 166 passed
  • All 9 (from, to) state pairs verified against the original
    transition table

Out of scope

The original review flagged other sync-layer items: _SyncStoreView
adapter, make_default_block_processor factory, and the
marketing-tone docstring on SyncService. Those stay queued for
follow-up PRs.

🤖 Generated with Claude Code

…operty

SyncState was 163 lines for a 3-state enum. Most of the surface was
trivial `state == SyncState.X` wrappers and a state-machine helper
whose only caller was sync service. Net change: -225 lines across
4 files, zero behavior change.

Changes:

- states.py drops `is_idle`, `is_syncing`, `is_synced` properties
  (trivial == wrappers), `can_transition_to` (one caller), and the
  module-level `_VALID_TRANSITIONS` table. Keeps the enum and
  `accepts_gossip`, the only property doing real work.
- service.py drops `SyncService.is_syncing` and `is_synced` public
  wrappers (zero external callers). Replaces three call sites that
  used the removed enum properties with direct comparisons.
- service.py rewrites `_transition_to` to inline the validity check.
  The original 5-edge transition table becomes two invariants:
  no self-transitions, no IDLE -> SYNCED shortcut. Same semantics
  verified case-by-case against the original table.
- test_states.py shrinks to cover the surviving surface (enum
  identity and accepts_gossip). The `_transition_to` invariants
  now have coverage in test_service.py, including a new
  self-transition test to replace the parametrized test that lived
  on `can_transition_to`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tcoratger tcoratger merged commit 75dfe92 into leanEthereum:main May 18, 2026
13 checks passed
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.

1 participant