Skip to content

Tighten WorkUnit::total_shards() contract to NonZeroU32 #980

@scarmuega

Description

@scarmuega

Context

Surfaced by CodeRabbit on PR #978 (comment 3153861519). Tracking as a follow-up.

WorkUnit::total_shards() (crates/core/src/work_unit.rs:67) returns u32, defaulting to 1. Nothing in the type system stops an implementation from returning 0. If it does, run_lifecycle (crates/core/src/sync.rs::run_lifecycle) skips every per-shard phase but still runs initialize()finalize() + tip notifications, so the work unit can "complete" without ever processing a shard.

Current state

PR #978 mitigates the worst symptom: crates/cardano/src/shard.rs::shard_key_ranges now panic!s in all build profiles if total_shards == 0 (commit 56b6dbb9), so any sharded Cardano work unit fails loudly at the first load() call. But:

  • The trait contract still permits 0.
  • Future non-Cardano work units (or any code path that doesn't go through shard_key_ranges) still silently no-op.

Proposed fix

Change the trait to return NonZeroU32:

fn total_shards(&self) -> NonZeroU32 {
    NonZeroU32::new(1).unwrap()
}

run_lifecycle then loops start_shard..total_shards.get(). Implementations that derive shard count from persisted state (the three sharded Cardano units) wrap their cached u32 in NonZeroU32::new(...).expect(\"shard count must be >= 1\") after reading *_progress.total (already validated by validate_total_shards indirectly via shard_key_ranges, but the type makes it explicit at the boundary).

Alternative: keep u32 but add a runtime check in run_lifecycle that rejects 0 with a clear DomainError. Less type-safe but smaller blast radius if NonZeroU32 propagates inconveniently.

Files to touch

  • crates/core/src/work_unit.rs — trait signature + default impl
  • crates/core/src/sync.rs::run_lifecycle — loop bounds
  • crates/cardano/src/lib.rsCardanoWorkUnit::total_shards delegation
  • crates/cardano/src/{ewrap,estart,rupd}/work_unit.rs — return wrapped value
  • crates/cardano/src/{genesis,roll}/work_unit.rs — return NonZeroU32::new(1).unwrap()

Priority

Low. The Cardano sharded path is already protected at runtime by the shard.rs panic. This is a contract-tightening / future-proofing issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions