Skip to content

Replace once_cell with std::sync::LazyLock and OnceLock#881

Open
Richardmsbr wants to merge 1 commit into
cloudflare:mainfrom
Richardmsbr:fix/replace-once-cell-with-std
Open

Replace once_cell with std::sync::LazyLock and OnceLock#881
Richardmsbr wants to merge 1 commit into
cloudflare:mainfrom
Richardmsbr:fix/replace-once-cell-with-std

Conversation

@Richardmsbr
Copy link
Copy Markdown

Summary

Removes the external once_cell dependency in favor of the now-stable
standard library equivalents:

  • once_cell::sync::Lazystd::sync::LazyLock (stable since Rust 1.80)
  • once_cell::sync::OnceCellstd::sync::OnceLock (stable since Rust 1.70)

Closes #721.

Changes

  • Removed once_cell = "1" from the workspace and from every member
    crate that depended on it (pingora, pingora-cache, pingora-core,
    pingora-memory-cache, pingora-proxy, pingora-runtime,
    pingora-timeout).
  • Updated all imports and call sites across 30+ source/test files.
  • Updated docs/user_guide/rate_limiter.md and the doc-comment in
    pingora-prometheus to match the new API.
  • Bumped workspace rust-version to 1.80 (required by LazyLock).

The one non-trivial change: try_insert

OnceLock in std does not yet expose a try_insert equivalent
(see rust-lang/rust#116693).
The single occurrence in pingora-runtime::NoStealRuntime::get_pools()
was replaced with the set() + get().unwrap() pattern suggested in
the issue, preserving the existing race-safe initialization semantics:

match self.pools.set(pools) {
    Ok(()) => {
        // we won the race: also initialize controls
        self.controls.set(controls).unwrap();
        // safe: just inserted above via set()
        self.pools.get().unwrap()
    }
    // another thread already set it, just return it
    Err(_my_pools) => self.pools.get().unwrap(),
}

The semantics are equivalent: when set succeeds, we know the value
we just inserted is the one stored, so get().unwrap() is sound. When
set fails, another thread won the race and get() will return its
value.

Validation

Locally (Linux, Rust 1.95.0):

  • cargo check --workspace — clean
  • cargo fmt --all -- --check — clean
  • cargo test --workspace --lib706 passed, 0 failed, 2 ignored
    (matches main exactly: I ran the same suite on main after
    stashing this diff and got identical counts per crate)
  • cargo clippy --workspace --all-targets — same output as main
    (the two pre-existing iter::for_each + unreachable! warnings in
    pingora-http/src/lib.rs are present on main too)

Integration tests that depend on the openresty mock origin were
not exercised in this environment.

Notes

  • This is a breaking change for downstream users on Rust < 1.80.
    If preserving a lower MSRV is important, an alternative is to keep
    once_cell as an optional std shim, but the simpler approach is
    to bump the MSRV as the issue requested.
  • No public API changes other than the MSRV bump.

Closes cloudflare#721

The once_cell crate's Lazy and OnceCell primitives are now available
in the standard library as LazyLock (stable since 1.80) and OnceLock
(stable since 1.70). This removes an external dependency and aligns
with the standard library going forward.

Notes:
- Bumped workspace MSRV to 1.80 (required by LazyLock).
- OnceCell::try_insert has no stable std equivalent yet
  (rust-lang/rust#116693). Replaced with set() + get().unwrap()
  pattern in pingora-runtime::NoStealRuntime::get_pools(),
  preserving the race-safe semantics.
- Documentation example in docs/user_guide/rate_limiter.md and
  doc-comment in pingora-prometheus were updated to match.
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.

Replace once_cell dependency with std LazyLock and OnceLock

1 participant