{"id":33933599,"url":"https://github.com/zertyz/reactive-mutiny","last_synced_at":"2026-04-08T19:31:03.912Z","repository":{"id":115193608,"uuid":"606667223","full_name":"zertyz/reactive-mutiny","owner":"zertyz","description":"async Event-Driven Reactive Library for Rust with optimized Stream executors -- loosely inspired on SmallRye's Mutiny Java Library","archived":false,"fork":false,"pushed_at":"2026-03-21T01:16:18.000Z","size":5402,"stargazers_count":8,"open_issues_count":2,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-03-21T16:59:29.127Z","etag":null,"topics":["async","event-driven","reactive-programming","rust","stream-processing"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zertyz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-02-26T07:17:52.000Z","updated_at":"2026-03-21T01:16:25.000Z","dependencies_parsed_at":"2023-11-17T23:05:39.307Z","dependency_job_id":"b9183653-e76b-4312-89ae-a99a33085aaf","html_url":"https://github.com/zertyz/reactive-mutiny","commit_stats":null,"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"purl":"pkg:github/zertyz/reactive-mutiny","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zertyz%2Freactive-mutiny","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zertyz%2Freactive-mutiny/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zertyz%2Freactive-mutiny/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zertyz%2Freactive-mutiny/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zertyz","download_url":"https://codeload.github.com/zertyz/reactive-mutiny/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zertyz%2Freactive-mutiny/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31571599,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T14:31:17.711Z","status":"ssl_error","status_checked_at":"2026-04-08T14:31:17.202Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","event-driven","reactive-programming","rust","stream-processing"],"created_at":"2025-12-12T13:05:39.716Z","updated_at":"2026-04-08T19:31:03.895Z","avatar_url":"https://github.com/zertyz.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# reactive-mutiny crate\n\n[gh-image]: https://github.com/zertyz/reactive-mutiny/workflows/Rust/badge.svg\n[gh-checks]: https://github.com/zertyz/reactive-mutiny/actions/workflows/rust.yml\n[cratesio-image]: https://img.shields.io/crates/v/reactive-mutiny.svg\n[cratesio]: https://crates.io/crates/reactive-mutiny\n[docsrs-image]: https://docs.rs/reactive-mutiny/badge.svg\n[docsrs]: https://docs.rs/reactive-mutiny\n\n[![reactive-mutiny GitHub Actions][gh-image]][gh-checks]\n[![reactive-mutiny on crates.io][cratesio-image]][cratesio]\n[![reactive-mutiny on docs.rs][docsrs-image]][docsrs]\n\n*async \u0026 zero-cost-abstraction Event-Driven Reactive Library for Rust with advanced \u0026 optimized containers and Stream executors*\n\nBrowse the [Docs][docsrs].\n\nRust's `reactive-mutiny` was designed to allow building efficient \u0026 elegant asynchronous event processing pipelines (using\nStreams -- a.k.a. \"async Iterators\"), easing flexible \u0026 decoupled microservice architectures (distributed or not), ready for production.\n\nThe core of this library is composed of a `Uni` and a `Multi` -- hence the name \"Mutiny\". Both process streams of events:\n  - `Uni` allows **a single listener OR multiple consumers** for each produced payload -- also definable as *allows a single event processing pipeline*;\n  - `Multi` allows **multiple listeners AND multiple consumers** for each produced payload, allowing *several event processing pipelines*\n    -- or, in Kafka parlance, allowing *several consumer groups*\n  - `Multi` may do what `Uni` does, but the later does it faster -- hence, justifying its existence: `Uni` doesn't use any\n    reference counting for the payloads and uses a single queue/channel (where `Multi` requires as many as there are listeners).\n\nMoreover, zero-cost-abstractions over metrics, logs \u0026 retrying are available -- getting optimized away if not used, as specified in const time initialization options\nand on functional, deeper API opt-ins.\n\nTaste the library in this excerpt:\n\n```rust\n    use reactive_mutiny::prelude::*;\n\n    fn logic_1(events_stream: impl Stream\u003cItem=InputEventType\u003e) -\u003e impl Stream\u003cItem=OutputEventType\u003e {\n        // your logic goes here using Rust's Stream / Iterator functions\n    }\n\n    fn main() {\n        // build the event processing pipeline\n        let events_handle = UniZeroCopy::\u003cInputEventType, 1024, 1\u003e::new()\n        .spawn_non_futures_non_fallible_executor(\"Consumer of InputEventType and issiuer of OutputEventType\",\n                                                 |events_stream| {\n                                                     logic_2(logic_1(events_stream))\n                                                         .inspect(|outgoing_event| send(outgoing_event))\n                                                 },\n                                                 |_executor| async { /* on-close logic */ });\n\n    }\n\n    // see more details in examples/uni-microservice\n```\n\nCore components:\n  1) A set of channels through which events are sent from producers to consumers -- all context-switch-free (AKA \"lock-free\") -- including zero-copy \u0026 mmap log based implementations;\n  2) A set of generic `Stream` executors for all possible combinations of Future/non-Future \u0026 Fallible/non-Fallible event types, with the option of enforcing or not a Timeout on each event's resolution of their `Future`. *The API was carefully designed to allow the compiler to fully optimize everything: most of times, all of the reactive code ends up in the executors and the whole Multi / Uni abstractions are zeroed out;*\n  3) Instrumentation \u0026 Metrics collectors for visibility of the performance and operation (as said earlier, as a zero-cost-abstraction);\n  4) The main `Multi` and `Uni` objects, along with a set of prelude type aliases binding the channels and allocators together.\n  5) Constant-pool based allocators, for superior performance and flexibility -- see the `AtomicZeroCopy` channel benchmarks;\n\n\n**NOTE: This crate is rather new (less than 1yo), but actively maintained and used in production: no known bugs exist (and MIRI says we're fine), speed is amazing, API has been throughoutly tested \u0026 reviewed and is stable, but improved docs \u0026 code cleanup / refactorings will still be (slowly) addressed to improve the cosmetics. Anyway, evolutions are always driven from community feedback**\n\n**MIRI: Not all parts of this crate are testable with MIRI, as of 2023-06-14: \"ready events from epoll_wait is not yet implemented\"; \"mmap syscalls\" and some other functionalities are not available in MIRI -- but what is able to be tested, passes.**\n\n\n# Performance\n\nThis crate was very loosely inspired by the SmallRye's Mutiny library for Java, from which some names were borrowed.\nLittle had to be done to bring the same functionality to Rust, due to the native functional approach, powerful error\nhandling, async support and wonderful \u0026 flexible Iterator/Stream APIs supported by the language, so the focus of this work went into\nbringing the events to their maximum processing speed \u0026 operability: special queues, topics, stacks, channels and Stream executors have\nbeen created, offering a superior performance over the Rust's native \u0026 community versions -- inspect the `benches` folder for details:\n\n![reactive-mutiny's channels latencies](screenshots/channels_latencies.png)\n![reactive-mutiny's channels throughput](screenshots/channels_throughput.png)\n*performance characteristics of the standard/community vs our provided raw senders of payloads from one thread to another*\n\n![reactive-mutiny's allocators \u0026 type wrappers](screenshots/allocators_and_type_wrappers.png)\n*performance characteristics comparison of standard vs our provided type wrappers and allocators, used for zero-copy channels -- with raw `memcopy` and allocators baselines*\n\n# Where to go next\n\nDocs will still be improved. Meanwhile, the following sequence is suggested for new users of this crate:\n  1) Look at the `examples/`;\n  2) Study the type aliases in `reactive-mutiny::prelude::advanced::*` -- at this point, it is safe to trust that the docs will provide everything you'll need;\n  3) For an advanced usage example, inspect the `reactive-messaging` crate -- in special, how easily \u0026 decoupled the reactive abstractions allow upgrading a processor that doesn't pass any answers back to one that does pass them back to the peers.\n\n# Comparisons\n\nIf you're familiar with SmallRye's Mutiny, here are some key differences:\n  - Both our `Uni` and `Multi` here process streams of events. On the original library, a Uni is like a single\n    \"async future\" and, since we don't need that in Rust, the names were repurposed: the other Multi is our `Uni` (may also work as our `Multi` when using \"subscriptions\") and the other Uni you may get by just using any Rust's async calls \u0026 handling any `Result\u003c\u003e`, for error treatment;\n  - Each event fed into the pipeline will be executed, regardless if there is an answer at the end; also, there is no \"subscription\"\n    (subscription semantics is achieved by adding pipelines to a `Multi`);\n  - Executors \u0026 their settings are set when the pair producer/pipeline comes to be (when the `Uni` / `Multi` object is created): there\n    is no .merge() nor .executeAt() to call in the pipeline;\n  - No Multi/Uni pipeline conversion and the corresponding plethora of functions -- they are simply not needed;\n  - No timeouts are set in the pipeline -- they are a matter for the executor, which will simply cancel events (that are `Future`s) that take longer than the configured executor's maximum\n    (SmallRye's Uni timeouts are attainable using Tokio's \"futures\" timeouts, just like one would do for any async function call);\n  - Incredibly faster: Rust's compiler makes your pipelines (and most of this library) behave as a zero-cost abstraction (when compiled in Release mode). The used-and-abused Const Generics play a great role in such optimizations -- at the expense of our rather complex type definitions in `reactive_mutiny::prelude::advanced`.\n  - To fully get the original Mutiny's behavior, you'll have to use:\n    - Rust's `reactive-mutiny` (for reactive async event-processing);\n    - `Tokio` (to get responses from Futures and to specify timeouts in async calls, async sleeps... saving a ton of APIs for this crate);\n    - Streams (here we don't mix Multi \u0026 Stream \u0026 Iterator functionalities -- which, in practice, leads to inefficient abuses of\n      the original Java library's abstractions -- for using a new instance of their Multi where a Stream or Iterator could be used is a common bad parctice / anti-pattern);","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzertyz%2Freactive-mutiny","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzertyz%2Freactive-mutiny","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzertyz%2Freactive-mutiny/lists"}