Skip to content

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

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

    area:cardanoCardano ledger / epoch / pots logicenhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions