Per the robustness plan's §9 (flagged as the single highest-leverage
perf change in the crate): headless_engine_dispatch_json used to clone
the entire EngineState before the reducer ran, clone it again after,
then StatePatch::diff did a deep PartialEq walk across all 16 domains
and cloned each changed one a third time — cost scaled with everything
the user has ever loaded (full catalogs, episode lists), not with what
the action actually touched.
Introduces Tracked<T> (src/headless_engine/state.rs): wraps each
EngineState domain field so any mutable access — a field write, a
whole-value replacement via DerefMut, a method call taking &mut —
flips a dirty bit automatically. Serialize/Deserialize delegate
straight to the wrapped value, so the wire format is byte-for-byte
unchanged (verified by the golden wire fixtures added in the prior
commit, which pass unmodified). EngineState::diff_dirty() replaces
StatePatch::diff(before, after): it clones only domains whose dirty
bit is set and clears it, so both the pre-dispatch full clone and the
post-dispatch PartialEq walk are gone entirely. The ~16 call sites that
did whole-domain replacement (`engine.state.detail = DetailState {
...}`) needed `*engine.state.detail = ...` instead — the compiler
catches any site the migration missed as a type error, so there's no
way for this rewrite to silently skip a domain the way a hand-added
mark_dirty() call could.
Also fixes headless_engine_snapshot_json, which used to serialize
while still holding the engines mutex; it now clones the state and
drops the lock before calling serde_json::to_string.
Adds benches/ (criterion, `--features bench` dev-only surface via a
new bench_targets re-export module mirroring the existing fuzz_targets
pattern): headless_engine_dispatch benches a NavigationRequested
dispatch against a 500-stream detail state (a domain the action
doesn't touch, so the win is directly visible), and stream_ranking
benches player_source_sidebar_plan_json grouping 500 streams. CI gets
a bench-check job compiling and smoke-running both (`--test`) without
paying for full timing runs on every push.
|
||
|---|---|---|
| .github/workflows | ||
| benches | ||
| docs | ||
| fluxa-streaming-engine | ||
| fuzz | ||
| src | ||
| tests/wire | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| LICENSE | ||
| README.md | ||
| uniffi-bindgen.rs | ||
| uniffi.toml | ||
fluxa-core
The platform-agnostic Rust core behind Fluxa, a media-streaming app.
State management · Stream policy · Addon protocol · Effect-driven I/O
What it does
fluxa-core holds all of Fluxa's domain logic — content discovery, stream selection,
playback state, profiles, library, calendar, and external sync with Trakt/Simkl — so the
same Rust codebase can run unmodified on Android, desktop, and (via WASM) the web. It
contains no platform-specific code and never performs I/O itself: it takes an action and
returns state plus a list of typed effects, and the host platform executes those
effects and reports results back.
Host → dispatch(action_json)
← { state, effects: [{ id, type, payload }] }
Host → executes each effect (HTTP / storage / player / ...)
→ completeEffect({ effectId, result })
← { state, effects: [...] }
This repo also contains a companion crate, fluxa-streaming-engine/, which handles
the runtime streaming side: torrent download (via librqbit), local HTTP proxying, and
Dolby Vision / HDR10+ stream rewriting.
Who uses this
| Platform | Repo | How it links |
|---|---|---|
| Android (mobile + TV) | Fluxa | JNI (primary, ~157 functions) + a small UniFFI surface |
| Desktop (Linux/macOS/Windows) | FluxaDesktop | Plain Rust dependency — calls FluxaCore/core_invoke directly, no FFI marshaling |
| iOS / tvOS | not in this workspace | UniFFI (bindings/uniffi.rs) |
| webOS | not in this workspace | WASM (bindings/wasm.rs, wasm feature) |
See docs/integrating.md for how each platform actually wires
this crate in, including how to add a new capability for a given platform.
Architecture
headless_engine/— the primary state machine. State is a typedEngineStatestruct made of per-feature sub-structs (home, detail, player, library, search, ...); cross-module writes go throughpub(super)setters, never raw field access.app_state.rs— a second, simpler engine for overlapping concerns, used by Android via UniFFI. The split is intentional, not duplication to be cleaned up.- Three uncoordinated exposure mechanisms, one per platform's needs:
core_api::FluxaCore(minimal, desktop-only),ffi::core_invoke(string-routed dispatcher, desktop + Swift), andbindings/jni.rs(Android, no equivalent elsewhere).
Full architecture notes, the effect catalog, and the wire-format reference live in
docs/:
docs/overview.md— architecture, state engines, module mapdocs/effect-loop.md— the dispatch/effect/completeEffect cycledocs/effects.md— everyEffectKindand its payload shapedocs/integrating.md— per-platform integration guidedocs/building.md— features, commands, cross-compilation
Building from source
git clone https://github.com/KhooLy/fluxa-core.git
cd fluxa-core
cargo build # default (native) features — what Android uses
cargo test --lib # ~190 tests, fast
Prerequisites
- Rust stable
- For Android cross-compilation:
rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android
cargo check --no-default-features --features wasm # sanity-check the webOS/WASM path
cd fluxa-streaming-engine && cargo build # the companion crate builds independently
See docs/building.md for the full feature matrix, UniFFI binding
generation, and release-build details.
Repo layout
src/ domain logic, headless_engine, FFI bindings
fluxa-streaming-engine/ torrent + Dolby Vision/HDR10+ stream rewriting (separate crate)
fuzz/ cargo-fuzz targets for parsers (episode matching, manifests, percent-decode)
docs/ architecture, effects reference, integration guide
Stack
Rust · JNI · UniFFI · wasm-bindgen · axum · tokio · librqbit · dolby_vision · serde
Legal — fluxa-core is a domain-logic library for a client-side interface to user-installed Stremio addons. It does not host, serve, or distribute any media content, and never makes a network call itself — all I/O is performed by the host platform. Fluxa is not affiliated with any addon developer, repository, or content provider. Users are responsible for ensuring they have the right to access what they stream.
Related projects
- Fluxa for Android — the Android counterpart consuming this crate
- FluxaDesktop — the desktop counterpart consuming this crate