manager_handlers 0.2.0

This crate represents the implementation of manager capable of creating a microservice which has multiple handlers, which can be accesed via http from outside. Each handler can use the other ones via a bus to process the request. The handlers can have a number of replicas
Documentation

# Manager Crate

## Overview

`Manager` is a scalable, async-driven system that handles requests and communication between different components using a pub/sub model in Rust. It is built on top of the `Rocket` framework for HTTP server handling and utilizes the Tokio runtime for asynchronous tasks. This crate allows you to create handlers that process requests and handle messages via a message bus, making it highly modular and easy to extend.

## Features

- **Dynamic Handler Registration**: Register new handlers dynamically that can process requests and publish messages.
- **Pub/Sub Messaging**: Implement publish/subscribe messaging between different services or components.
- **Concurrency Control**: Uses a semaphore to limit to one request at the time from http request. The handlers inside the service can replicate as many times as they are configured.
- **Graceful Shutdown**: Includes an HTTP shutdown mechanism for controlled termination of the service.
- **Asynchronous Processing**: All handlers and requests are processed asynchronously using Tokio's async runtime.

## Prerequisites

Before you begin, ensure you have met the following requirements:

- Rust version >= 1.56 (due to the use of the `async_trait` crate and async/await syntax).
- `Rocket` version 0.5 or later.

## Installation

To use this crate in your project, add the following dependencies to your `Cargo.toml` file:

```toml
[dependencies]
rocket = { version = "0.5", features = ["json"] }
tokio = { version = "1", features = ["full"] }
async-trait = "0.1"
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
```

## How to Use

### Define a Handler

To create a custom handler, you need to implement the `Base` trait. The `Base` trait requires two functions:

- `run`: Handles the actual business logic of processing incoming messages.
- `create`: Handles the creation of the struct

It also gives two ways to communicate between handlers: 
- `publish`: Publishes messages to other components via the `MultiBus` and awaits the response.
- `dispatch`: Dispatches messages to another service or handler.

```rust
use async_trait::async_trait;
use std::sync::Arc;
use crate::multibus::MultiBus;

pub struct MyHandler;

#[async_trait]
impl Base for MyHandler {
    async fn run(&self, src: String, data: String, communication_line: Arc<MultiBus>) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
        // Your business logic goes here
        // Example of publish:   let response = self.publish(data, "handler_1".to_string(), "handler_2".to_string(), communication_line.clone()).await;
        // Example of dispatch:  self.dispatch(data, "handler_2".to_string(), communication_line.clone()).await;
        Ok("Handled successfully".to_string())
    }

    fn new() -> Self {
        MyHandler {}
    }
}
```

### Create and Start the Manager

The `Manager` is responsible for initializing all the handlers and launching the HTTP server. Add your custom handlers to the manager using `add_handler`.

```rust
use crate::manager::Manager;

#[tokio::main]
async fn main() {
    let mut manager = Manager::new();

    // Register custom handlers
    manager.add_handler::<MyHandler>("my_handler", 2);

    // Start the manager
    manager.start().await;
}
```

### HTTP Endpoints

This crate provides a couple of HTTP endpoints that allow interaction with the system.

1. **POST `/shutdown`**: Shuts down the server gracefully.
   
   Example:

   ```bash
   curl -X POST http://localhost:8080/shutdown
   ```

2. **POST `/handler_name`**: Sends a request to a registered handler with a string body. You can after that process into a JSON.

   Example:

   ```bash
   curl -X POST http://localhost:8080/my_handler -d "{\"key\": \"value\"}" -H "Content-Type: text/plain"
   ```


## Error Handling

Errors during request processing or message dispatching are handled gracefully, and appropriate error messages are returned via JSON. If a handler encounters an error, it logs the issue and returns an error message.

### Example Error Response

```json
{
    "status": "Error",
    "message": "An error occurred while processing the request."
}
```

## License

This crate is open-sourced under the MIT license.