# DiMessageProcessor

Bridge library that integrates [EdpDependencyInjection](https://pip.e-deploy.com.br) with [MessageProcessor](https://pip.e-deploy.com.br), enabling dependency-injected message processor construction.

Instead of manually instantiating processors, this library resolves them from a `DependencyContext` at build time. Definitions accept either a type (resolved via DI) or a real `MessageProcessor` instance (used directly).

## Installation

```bash
pip install DiMessageProcessor --extra-index-url=https://pip.e-deploy.com.br
```

## Requirements

- Python >= 3.8
- `MessageProcessor >=4.3.0,<5`
- `EdpDependencyInjection >=3.0.0,<4`
- `messagebus` (provides `SubscriptionInfo`)

## Usage

### Message handler (recommended)

`DiMessageProcessorMessageHandler` is the top-level entry point that wires everything together. It also auto-discovers `AutoMappedEventProcessorBuilder` and `AutoMappedMessageProcessorBuilder` implementations registered in the DI context.

```python
from dimessageprocessor import DiMessageProcessorMessageHandler

handler = DiMessageProcessorMessageHandler(
    dependency_context=dependency_context,
    event_processor_definitions={
        "order_created": OrderCreatedProcessor,
        "order_cancelled": OrderCancelledProcessor,
    },
    message_processor_definitions={
        0x01: LoginProcessor,
        0x02: LogoutProcessor,
    },
    callback_definitions=[LoggingCallback, MetricsCallback],
)
```

### Auto-mapped builders

Modules can declare their processor mappings by implementing `AutoMappedEventProcessorBuilder` or `AutoMappedMessageProcessorBuilder`. These are automatically discovered by `DiMessageProcessorMessageHandler` via the DI context.

```python
from messagebus import SubscriptionInfo
from dimessageprocessor import AutoMappedEventProcessorBuilder, EventProcessorDefinition

class MyEventProcessorBuilder(AutoMappedEventProcessorBuilder):
    def build_events(self):
        return {
            "order_created": EventProcessorDefinition(processor_type=OrderCreatedProcessor, subscription_type=SubscriptionInfo.TYPE_REENTRANT),
            "order_cancelled": OrderCancelledProcessor,  # type reference also accepted
        }
```

```python
from dimessageprocessor import AutoMappedMessageProcessorBuilder, MessageProcessorDefinition

class MyMessageProcessorBuilder(AutoMappedMessageProcessorBuilder):
    def build_messages(self):
        return {
            0x01: MessageProcessorDefinition(processor_type=LoginProcessor),
            0x02: LogoutProcessor,
        }
```

### EventProcessorDefinition

`EventProcessorDefinition` wraps a processor type with a `subscription_type` that controls how the event bus delivers messages. Valid values come from `messagebus.SubscriptionInfo`:

| Constant | Value | Meaning |
|---|---|---|
| `SubscriptionInfo.TYPE_REENTRANT` | `1` | Processor can handle multiple events concurrently |
| `SubscriptionInfo.TYPE_NON_REENTRANT` | `2` | Processor handles events one at a time |

An invalid `subscription_type` raises `ValueError`.

### Event-based processor builder

Maps string event keys to processor types or instances resolved from the DI context.

```python
from dimessageprocessor import DiEventMessageProcessorBuilder

builder = DiEventMessageProcessorBuilder(
    dependency_context=dependency_context,
    processor_definitions={
        "order_created": OrderCreatedProcessor,
        "order_cancelled": already_built_instance,  # real instance also accepted
    }
)

processor = builder.build_message_processor("order_created")
```

### Message token-based processor builder

Maps integer tokens to processor types or instances resolved from the DI context.

```python
from dimessageprocessor import DiMessageMessageProcessorBuilder

builder = DiMessageMessageProcessorBuilder(
    dependency_context=dependency_context,
    processor_definitions={
        0x01: LoginProcessor,
        0x02: LogoutProcessor,
    }
)

processor = builder.build_message_processor(0x01)
```

### Executor factory with DI-resolved callbacks

Resolves `MessageProcessorCallback` instances from the DI context and creates `DefaultMessageProcessorExecutor` instances.

```python
from dimessageprocessor import DiMessageProcessorExecutorFactory

factory = DiMessageProcessorExecutorFactory(
    dependency_context=dependency_context,
    callback_definitions=[LoggingCallback, MetricsCallback]
)

executor = factory.build_executor(processor)
```

## Testing

```bash
poetry run python -m pytest test/ -v
```

## Authors

- Eduardo Almeida (eduardo.almeida@e-deploy.com.br)
- Max Guenes (max.santos@e-deploy.com.br)