-
Notifications
You must be signed in to change notification settings - Fork 1
feat: improve ProSA book with some missing parts #72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
ac0adcb
feat: improve ProSA book with some missing parts
reneca 502bfb9
feat(book): add note for Grafana Cloud OTLP configuration
reneca 5624f1c
fix: cargo-prosa unit test for completion
reneca d43a1b1
fix: doc and add example according to code review
reneca b1708a9
fix(book): dotted line in message flow according to code review
reneca File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| # Architecture | ||
|
|
||
| This chapter provides a high-level overview of the ProSA architecture, explaining how all the components interact to form a working microservice platform. | ||
|
|
||
| ## Overview | ||
|
|
||
| ProSA follows a **service bus** pattern. At its core, a central **Main** processor routes messages between autonomous **Processors**, each of which communicates with external systems through an **Adaptor**. Messages flow through the system using an internal format called **TVF** (Tag-Value Field). | ||
|
|
||
| ```mermaid | ||
| graph TB | ||
| ext_a(External System A) | ||
| ext_b(External System B) | ||
|
|
||
| subgraph prosa[ProSA Instance] | ||
| subgraph main[Main - Service Bus] | ||
| main_task[Main task] | ||
| table>Service table] | ||
| table <--> main_task | ||
| end | ||
|
|
||
| subgraph proc_a[Processor A] | ||
| task_a[Task] | ||
| adaptor_a[Adaptor A] | ||
| task_a <--> adaptor_a | ||
| end | ||
|
|
||
| subgraph proc_b[Processor B] | ||
| task_b[Task] | ||
| adaptor_b[Adaptor B] | ||
| task_b <--> adaptor_b | ||
| end | ||
|
|
||
| table --> task_a | ||
| table --> task_b | ||
| end | ||
|
|
||
| ext_a <--> adaptor_a | ||
| ext_b <--> adaptor_b | ||
| ``` | ||
|
|
||
| ## Components | ||
|
|
||
| ### Main (Service Bus) | ||
|
|
||
| The **Main** is the central hub of a ProSA instance. It is responsible for: | ||
|
|
||
| - **Message routing**: forwarding requests and responses between processors | ||
| - **Service table management**: maintaining a registry of which processors provide which services | ||
| - **Processor lifecycle**: tracking processor registration, removal, crashes, and restarts | ||
| - **Observability**: collecting system-wide metrics (RAM usage, service counts, processor states) | ||
| - **Shutdown coordination**: propagating shutdown signals to all processors | ||
|
|
||
| There is exactly **one Main** per ProSA instance. It runs on the Tokio async runtime and processes messages from its internal queue. | ||
|
|
||
| ### Processors | ||
|
|
||
| A **Processor** is an autonomous unit that runs in its own thread(s). Processors: | ||
|
|
||
| - **Register** with the Main to join the service bus | ||
| - **Declare services** they can provide (e.g., `"PAYMENT"`, `"AUTH"`) | ||
| - **Send and receive messages** through the Main's routing system | ||
| - **Run independently**, each in their own Tokio runtime (configurable: single-thread, multi-thread, or shared with Main) | ||
|
|
||
| Processors communicate exclusively through the Main bus using **internal messages** (`InternalMsg`): | ||
|
|
||
| | Message Type | Purpose | | ||
| |-------------|---------| | ||
| | `Request` | Send a transaction to a service for processing | | ||
| | `Response` | Return the result of a processed request | | ||
| | `Error` | Return an error for a request (timeout, unreachable, protocol error) | | ||
| | `Service` | Update the processor's copy of the service table | | ||
| | `Shutdown` | Ask the processor to stop gracefully | | ||
|
|
||
| ### Adaptors | ||
|
|
||
| An **Adaptor** is the bridge between a processor and the outside world. It handles: | ||
|
|
||
| - **Protocol translation**: converting external protocol messages (HTTP, TCP, custom binary, etc.) into internal TVF messages | ||
| - **Initialization**: setting up connections and resources when the processor starts | ||
| - **Termination**: cleaning up when the processor shuts down | ||
|
|
||
| Each processor handle their adaptor as they wish. The adaptor is defined as a trait, so different protocol implementations can be swapped in without changing the processor logic. | ||
|
|
||
| Adaptors can return values either synchronously or asynchronously using the [`MaybeAsync`](https://docs.rs/prosa/latest/prosa/core/adaptor/enum.MaybeAsync.html) enum. | ||
|
|
||
| ### TVF (Tag-Value Field) | ||
|
|
||
| **TVF** is the internal message format. It is a trait, not a concrete type, which means different implementations can be used depending on performance or protocol requirements. | ||
|
|
||
| The TVF trait provides a key-value interface where fields are identified by numeric IDs and can hold various types: strings, integers, floats, bytes, dates, and nested TVF buffers. | ||
|
|
||
| `SimpleStringTvf` is the built-in reference implementation. See the [TVF chapter](ch02-01-tvf.md) for details. | ||
|
|
||
| ### Service Table | ||
|
|
||
| The **Service Table** is maintained by Main and distributed to all processors. It maps service names (strings) to processor queues. When multiple processors provide the same service, requests are distributed using **round-robin** load balancing. | ||
|
|
||
| When the service table changes, Main notifies all processors with an updated copy. | ||
|
|
||
| ## Message Flow | ||
|
|
||
| Here is the typical flow of a request through ProSA: | ||
|
|
||
| ```mermaid | ||
| sequenceDiagram | ||
| participant ExtA as External System A | ||
| participant ProcA as Processor A (Consume service) | ||
| participant Main as Main (Service Bus) | ||
| participant ProcB as Processor B (Expose service) | ||
| participant ExtB as External System B | ||
|
|
||
| ProcB-->>Main: Register service | ||
| Note over Main: Service table update | ||
| ExtA->>ProcA: Protocol message | ||
| Note over ProcA: Adaptor converts to TVF | ||
| ProcA->>Main: Lookup service | ||
| ProcA->>ProcB: RequestMsg (via service queue) | ||
| Note over ProcB: Adaptor processes request | ||
| ProcB->>ExtB: Protocol message (optional) | ||
| ExtB->>ProcB: Protocol response (optional) | ||
| ProcB->>ProcA: ResponseMsg | ||
| Note over ProcA: Adaptor converts from TVF | ||
| ProcA->>ExtA: Protocol response | ||
| ``` | ||
|
|
||
| Note that processors send requests **directly** to the target processor's queue (looked up from the service table). They do not go through Main for every transaction — Main is only involved in service registration and table distribution. | ||
|
|
||
| ## Processor Lifecycle | ||
|
|
||
| 1. **Creation**: `ProcConfig::create()` — allocates the processor with its settings and Main bus reference | ||
| 2. **Run**: `Proc::run()` — spawns the processor in its own thread/runtime | ||
| 3. **Registration**: `proc.add_proc()` — notifies Main that the processor is active | ||
| 4. **Service declaration**: `proc.add_service_proc(names)` — registers the services this processor provides | ||
| 5. **Processing loop**: `internal_run()` — the main event loop, receiving and processing messages | ||
| 6. **Shutdown**: on `InternalMsg::Shutdown`, the processor calls `adaptor.terminate()` and `proc.remove_proc()` | ||
|
|
||
| ### Error Recovery | ||
|
|
||
| If a processor's `internal_run()` returns an error: | ||
| - **Recoverable errors**: the processor restarts after a delay (exponential backoff up to a configured maximum) | ||
| - **Fatal errors**: the processor is marked as crashed and does not restart | ||
| - If ProSA is shutting down, no restart is attempted | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| # Putting It All Together | ||
|
|
||
| Now that you're familiar with [Cargo-ProSA](ch01-01-cargo-prosa.md), [configuration](ch01-02-config.md), [observability](ch01-02-01-observability.md), and [running ProSA](ch01-02-04-run.md), let's walk through a complete example from scratch using the built-in processors. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| You need [Rust and Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) installed, along with `cargo-prosa`: | ||
|
|
||
| ```bash | ||
| cargo install cargo-prosa | ||
| ``` | ||
|
|
||
| ## Create and scaffold a project | ||
|
|
||
| ```bash | ||
| cargo prosa new my-first-prosa | ||
| cd my-first-prosa | ||
| ``` | ||
|
|
||
| This generates a Rust project with a `ProSA.toml` descriptor, a `build.rs`, and a `main.rs` that will be auto-generated from your ProSA configuration. | ||
|
|
||
| You can inspect the available components with: | ||
|
|
||
| ```bash | ||
| cargo prosa list | ||
| ``` | ||
|
|
||
| This shows all discovered components: Main, TVF, Processors, and Adaptors. | ||
|
|
||
| ## Add processors | ||
|
|
||
| Add a **stub** processor that will respond to requests, and an **injector** that will send requests: | ||
|
|
||
| ```bash | ||
| cargo prosa add -n stub-1 -a StubParotAdaptor stub | ||
| cargo prosa add -n inj-1 -a InjDummyAdaptor inj | ||
| ``` | ||
|
|
||
| - `-n` sets the processor instance name (used in configuration) | ||
| - `-a` selects which adaptor to use | ||
|
|
||
| Your `ProSA.toml` file now contains the processor configuration. You can also edit this file manually. | ||
|
|
||
| ## Generate and edit the configuration | ||
|
|
||
| Build the project and retrieve the generated configuration from _target/config.yml_ (or _target/config.toml_). | ||
|
|
||
| You can also generate a default configuration using `--dry_run` (see [Run ProSA](ch01-02-04-run.md) for details on this flag): | ||
|
|
||
| ```bash | ||
| cargo run -- -c config.yaml --dry_run | ||
| ``` | ||
|
|
||
| Then edit `config.yaml` to wire the injector to the stub. The stub needs to declare a service name, and the injector needs to target that same service: | ||
|
|
||
| ```yaml | ||
| name: "my-first-prosa" | ||
| observability: | ||
| level: debug | ||
| metrics: | ||
| stdout: | ||
| level: info | ||
| traces: | ||
| stdout: | ||
| level: debug | ||
|
|
||
| stub_1: | ||
| service_names: | ||
| - "TEST_SERVICE" | ||
|
|
||
| inj_1: | ||
| service_name: "TEST_SERVICE" | ||
| max_speed: 1.0 | ||
| ``` | ||
|
|
||
| This configures: | ||
| - The stub to respond to requests on `"TEST_SERVICE"` | ||
| - The injector to send 2 transactions per second to `"TEST_SERVICE"` | ||
| - [Observability](ch01-02-01-observability.md) output to stdout so you can see what's happening | ||
|
|
||
| ## Run it | ||
|
|
||
| ```bash | ||
| cargo run -- -n "MyFirstProSA" -c config.yaml | ||
| ``` | ||
|
|
||
| You should see log output showing: | ||
| 1. ProSA starting with the configured name | ||
| 2. The stub processor registering `TEST_SERVICE` | ||
| 3. The injector discovering the service and starting to send transactions | ||
| 4. Responses flowing back from the stub to the injector | ||
|
|
||
| Press `Ctrl+C` to stop (see [Graceful Shutdown](ch01-02-04-run.md#graceful-shutdown)). | ||
|
|
||
| ## What's next? | ||
|
|
||
| You now know how to build and operate a ProSA instance. The next chapters cover how to develop your own components: | ||
| - **[Adaptor](ch02-00-adaptor.md)** — write custom protocol adaptors | ||
| - **[Processor](ch03-00-proc.md)** — write custom processors with their own business logic |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.