Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo test --all-targets
- run: >
cargo test --lib --tests --
--skip mpmc_stress
--skip stress_1m
--skip arbitrary_capacity_mpmc_stress
--skip arbitrary_capacity_stress
timeout-minutes: 5
- run: cargo test --doc
- run: >
Expand Down Expand Up @@ -101,6 +106,9 @@ jobs:
--skip mpmc_stress
--skip mpmc_blocking_recv
--skip mpmc_clone
--skip arbitrary_capacity_stress
--skip arbitrary_capacity_bounded_cross
--skip arbitrary_capacity_mpmc

# ── Cross-platform matrix build ──────────────────────────────────────
cross-platform:
Expand Down Expand Up @@ -170,14 +178,36 @@ jobs:
--skip mpmc_two_publishers
timeout-minutes: 5

# ── photon-ring-async tests ────────────────────────────────────────
async-crate:
name: photon-ring-async
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo test -p photon-ring-async

# ── photon-ring-metrics tests ──────────────────────────────────────
metrics-crate:
name: photon-ring-metrics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo test -p photon-ring-metrics

# ── Publish to crates.io (only on tagged releases) ───────────────────
publish:
name: publish
needs: [check, test, clippy, fmt, miri, cross-platform, wasm, no-default-features, hugepages, atomic-slots]
needs: [check, test, clippy, fmt, miri, cross-platform, wasm, no-default-features, hugepages, atomic-slots, async-crate, metrics-crate]
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- run: cargo publish -p photon-ring-derive --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
- run: cargo publish -p photon-ring-async --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
- run: cargo publish -p photon-ring-metrics --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
- run: cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@
*.d
rust_out
photon-ring-derive/target/
photon-ring-async/target/
photon-ring-metrics/target/
photon-ring-async/Cargo.lock
photon-ring-metrics/Cargo.lock
photon-ring-derive/Cargo.lock
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,37 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added
- **Arbitrary ring capacity:** Ring capacity no longer requires power-of-two.
Any capacity >= 2 is supported. Power-of-two uses bitwise AND (zero regression);
arbitrary capacity uses Lemire reciprocal-multiply fastmod (~1.5 ns).
15 new tests including exhaustive fastmod verification.
- **Pipeline `then_with()` API:** `StageBuilder::then_with(f, WaitStrategy)`,
`FanOutBuilder::then_a_with()`, `then_b_with()` for configurable stage wait
behavior. Existing `then()`/`then_a()`/`then_b()` unchanged (delegate with default).
- **`#[photon(as_enum)]` derive attribute:** The Message derive macro no longer
silently assumes unknown types are `#[repr(u8)]` enums. Unrecognized types now
produce a compile error. Use `#[photon(as_enum)]` to explicitly mark enum fields.
**Breaking change** for Message derive users with enum fields.
- **`photon-ring-async` crate:** Runtime-agnostic async wrappers for photon-ring
channels. `AsyncSubscriber`, `AsyncSubscriberGroup` with yield-based polling.
Named `RecvFuture`/`GroupRecvFuture` for `select!`/`join!` combinators.
Configurable spin budget. No tokio dependency. 8 tests.
- **`photon-ring-metrics` crate:** Observability wrappers with `SubscriberMetrics`
(snapshot/delta tracking), `PublisherMetrics`. Framework-agnostic. 7 tests.
- **Loom MPMC model tests:** Standalone loom model of the MPMC cursor advancement
protocol. 4 scenarios covering 2-producer basic, contention, consumer reads,
and cursor catch-up. Run with `cargo test --test loom_mpmc --release`.

### Changed
- `RingIndex` struct encapsulates capacity, mask, reciprocal, and is_pow2 flag.
Internal to the crate; no public API change.

### Breaking
- `#[derive(photon_ring::DeriveMessage)]` enum fields now require `#[photon(as_enum)]`.

## [2.4.0] - 2026-03-19

### Performance
Expand Down
171 changes: 171 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[workspace]
members = [".", "photon-ring-derive", "photon-ring-async", "photon-ring-metrics"]

[package]
name = "photon-ring"
version = "2.4.0"
Expand All @@ -13,6 +16,9 @@ homepage = "https://github.com/userFRM/photon-ring"
documentation = "https://docs.rs/photon-ring"
exclude = [".github/"]

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(loom)'] }

[features]
hugepages = ["dep:libc"]
derive = ["dep:photon-ring-derive"]
Expand All @@ -32,6 +38,7 @@ criterion = "0.8.2"
crossbeam-channel = "0.5.15"
disruptor = "4.0.0"
libc = "0.2.183"
loom = "0.7"

[[example]]
name = "market_data"
Expand Down
Loading
Loading