{"id":19358364,"url":"https://github.com/paritytech/orchestra","last_synced_at":"2025-10-08T19:09:24.373Z","repository":{"id":60507740,"uuid":"540436520","full_name":"paritytech/orchestra","owner":"paritytech","description":"A partial actor pattern with a global orchestrator.","archived":false,"fork":false,"pushed_at":"2024-09-23T10:21:09.000Z","size":446,"stargazers_count":27,"open_issues_count":20,"forks_count":3,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-28T09:07:24.988Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/paritytech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2022-09-23T12:45:42.000Z","updated_at":"2024-09-30T20:14:25.000Z","dependencies_parsed_at":"2022-09-30T15:40:13.045Z","dependency_job_id":"c964b9fa-0bc5-4df3-a7a4-1aa070782b29","html_url":"https://github.com/paritytech/orchestra","commit_stats":{"total_commits":91,"total_committers":18,"mean_commits":5.055555555555555,"dds":0.6703296703296704,"last_synced_commit":"af1422111d2b9b89bfa1cd3d1a64e150dfc4f442"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paritytech%2Forchestra","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paritytech%2Forchestra/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paritytech%2Forchestra/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paritytech%2Forchestra/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paritytech","download_url":"https://codeload.github.com/paritytech/orchestra/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247767238,"owners_count":20992548,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-11-10T07:11:24.821Z","updated_at":"2025-10-08T19:09:19.350Z","avatar_url":"https://github.com/paritytech.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# orchestra\n\nThe orchestra pattern is a partial actor pattern, with a global orchestrator regarding\nrelevant work items.\n\n## proc-macro\n\nThe proc macro provides a convenience generator with a builder pattern,\nwhere at it's core it creates and spawns a set of subsystems, which are purely\ndeclarative.\n\n```rust\n    #[orchestra(signal=SigSigSig, event=Event, gen=AllMessages, error=OrchestraError)]\n    pub struct Opera {\n        #[subsystem(MsgA, sends: [MsgB])]\n        sub_a: AwesomeSubSysA,\n\n        #[cfg(any(feature = \"feature1\", feature = \"feature2\"))]\n        #[subsystem(MsgB, sends: [MsgA])]\n        sub_b: AwesomeSubSysB,\n    }\n```\n\n* Each subsystem is annotated with `#[subsystem(_)]` where `MsgA` respectively `MsgB` are the messages\nbeing consumed by that particular subsystem. Each of those subsystems is required to implement the subsystem\ntrait with the correct trait bounds. Commonly this is achieved\nby using `#[subsystem]` and `#[contextbounds]` macro.\n  * `#[contextbounds(Foo, error=Yikes, prefix=wherethetraitsat)]` can applied to `impl`-blocks and `fn`-blocks. It will add additional trait bounds for the generic `Context` with `Context: FooContextTrait` for `\u003cContext as FooContextTrait\u003e::Sender: FooSenderTrait` besides a few more. Note that `Foo` here references the name of the subsystem as declared in `#[orchestra(..)]` macro.\n  * `#[subsystem(Foo, error=Yikes, prefix=wherethetraitsat)]` is a extension to the above, implementing `trait Subsystem\u003cContext, Yikes\u003e`.\n* `error=` tells the orchestra to use the user provided\nerror type, if not provided a builtin one is used. Note that this is the one error type used throughout all calls, so make sure it does impl `From\u003cE\u003e` for all other error types `E` that are relevant to your application.\n* `event=` declares an external event type, that injects certain events\ninto the orchestra, without participating in the subsystem pattern.\n* `signal=` defines a signal type to be used for the orchestra. This is a shared \"tick\" or \"clock\" for all subsystems.\n* `gen=` defines a wrapping `enum` type that is used to wrap all messages that can be consumed by _any_ subsystem.\n* Features can be feature gated by `#[cfg(feature = \"feature\")]` attribute macro expressions. Currently supported are `any`, `all`, `not` and `feature`.\n\n```rust\n    /// Execution context, always required.\n    pub struct DummyCtx;\n\n    /// Task spawner, always required\n    /// and must implement `trait orchestra::Spawner`.\n    pub struct DummySpawner;\n\n    fn main() {\n        let _orchestra = Opera::builder()\n            .sub_a(AwesomeSubSysA::default())\n            .sub_b(AwesomeSubSysB::default())\n            .spawner(DummySpawner)\n            .build();\n    }\n```\n\nIn the shown `main`, the orchestra is created by means of a generated, compile time erroring\nbuilder pattern.\n\nThe builder requires all subsystems, baggage fields (additional struct data) and spawner to be\nset via the according setter method before `build` method could even be called. Failure to do\nsuch an initialization will lead to a compile error. This is implemented by encoding each\nbuilder field in a set of so called `state generics`, meaning that each field can be either\n`Init\u003cT\u003e` or `Missing\u003cT\u003e`, so each setter translates a state from `Missing` to `Init` state\nfor the specific struct field. Therefore, if you see a compile time error that blames about\n`Missing` where `Init` is expected it usually means that some subsystems or baggage fields were\nnot set prior to the `build` call.\n\nTo exclude subsystems from such a check, one can set `wip` attribute on some subsystem that\nis not ready to be included in the `orchestra`:\n\n```rust\n    #[orchestra(signal=SigSigSig, event=Event, gen=AllMessages, error=OrchestraError)]\n    pub struct Opera {\n        #[subsystem(MsgA, sends: MsgB)]\n        sub_a: AwesomeSubSysA,\n\n        #[subsystem(MsgB, sends: MsgA), wip]\n        sub_b: AwesomeSubSysB, // This subsystem will not be required nor allowed to be set\n    }\n```\n\nBaggage fields can be initialized more than one time, however, it is not true for subsystems:\nsubsystems must be initialized only once (another compile time check) or be _replaced_ by\na special setter like method `replace_\u003csubsystem\u003e`.\n\nA task spawner and subsystem context are required to be defined with `Spawner` and respectively `SubsystemContext` implemented.\n\n## Debugging\n\nAs always, debugging is notoriously annoying with bugged proc-macros, see [feature `\"expand\"`](#feature-expand).\n\n## Features\n\n### feature `\"expand\"`\n\n[`expander`](https://github.com/drahnr/expander) is employed to yield better\nerror messages. Enable with `--features=orchestra/expand`.\n\n### feature `\"dotgraph\"`\n\nGenerate a directed graph which shows the connectivity according to the\ndeclared messages to be send and consumed. Enable with `--features=orchestra/dotgraph`.\nThe path to the generated file will be displayed and is of the form\n`${OUT_DIR}/${orchestra|lowercase}-subsystem-messaging.dot`.\nUse `dot -Tpng ${OUT_DIR}/${orchestra|lowercase}-subsystem-messaging.dot \u003e connectivity.dot` to\nconvert to i.e. a `png` image or use your favorite dot file viewer.\nIt also creates a `.svg` alongside the `.dot` graph, derived from the `.dot` graph for\ndirect usage.\n\n## Caveats\n\nNo tool is without caveats, and `orchestra` is no exception.\n\n### Large Message Types\n\nIt is not recommended to have large messages that are sent via channels, just like for other\nimplementations of channels.\nIf you need to transfer data that is larger than a few dozend bytes, use `Box\u003c_\u003e` around it or use a global identifier to access persisted state such as a database, depending on the use case.\n\n### Response Channels\n\nIt seems very appealing to have response channels as part of messages, and for many cases,\nthese are a very convenient way of maintaining a strucutured data flow, yet they are ready\nto shoot you in the foot when not used diligently. The diligence required is regarding three\ntopics:\n\n1. Circular message dependencies leading to a dead-lock for single threaded subsystems\n2. Too deep message dependencies across _many_ subsystems\n3. Delays due to response channels\n\nEach of them has a variety of solutions, such as local caching to remedy frequent lookups of the same information or splitting up subsystem into multiple to avoid circular dependencies or merging tiny topologically closely related to one subsystem in some exceptional cases, but strongly depend on the individual context in which orchestra is used.\n\nTo find these, the feature `dotgraph` is providing a visualization of all interactions of the subsystem to subsystem level (not on the message level, yet) to investigate cycles.\nKeep an eye on warnings during the generation phase.\n\n## License\n\nLicensed under either of\n\n* Apache License, Version 2.0, (LICENSE-APACHE or \u003chttp://www.apache.org/licenses/LICENSE-2.0\u003e)\n* MIT license (LICENSE-MIT or \u003chttp://opensource.org/licenses/MIT\u003e)\n\nat your option.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparitytech%2Forchestra","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fparitytech%2Forchestra","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparitytech%2Forchestra/lists"}