# Message Publisher

## AMQP Distributed Bus

AMQP Distributed Bus is described in more details under [Distributed Bus section](/modelling/microservices-php/distributed-bus/amqp-distributed-bus-rabbitmq.md).

## Message Publisher

If you want to publish Message directly to Exchange, you may use of `Publisher.`

```php
class AMQPConfiguration
{
    #[ServiceContext] 
    public function registerAmqpConfig()
    {
        return 
            AmqpMessagePublisherConfiguration::create(
                MessagePublisher::class, // 1
                "delivery", // 2
                "application/json" // 3
            );
    }
}
```

1. `Reference name` - Name under which it will be available in Dependency Container.
2. `Exchange name` - Name of exchange where Message should be published
3. `Default Conversion [Optional]` - Default type, payload will be converted to.

### Publisher Configuration

```php
AmqpMessagePublisherConfiguration::create(
    MessagePublisher::class,
    "delivery"
)
    ->withDefaultPersistentDelivery(true) // 1
    ->withDefaultRoutingKey("someKey") // 2
    ->withRoutingKeyFromHeader("routingKey") // 3
    ->withHeaderMapper("application.*") // 4
```

1. `withDefaultPersistentDelivery` - should AMQP messages be `persistent`*.*
2. `withDefaultRoutingKey` - default routing key added to AMQP message
3. `withRoutingKeyFromHeader` - should routing key be retrieved from header with name
4. `withHeaderMapper` - On default headers are not send with AMQP message. You map provide mapping for headers that should be mapped to `AMQP Message`

## Available Exchange Configuration

```php
$amqpExchange = AmqpExchange::createDirectExchange
$amqpExchange = AmqpExchange::createFanoutExchange
$amqpExchange = AmqpExchange::createTopicExchange
$amqpExchange = AmqpExchange::createHeadersExchange

$amqpExchange = $amqpExchange
    ->withDurability(true) // exchanges survive broker restart
    ->withAutoDeletion() // exchange is deleted when last queue is unbound from it
```

## Available Queue configurations

```php
$amqpQueue = AmqpQueue::createDirectExchange
                ->withDurability(true) // the queue will survive a broker restart
                ->withExclusivity() // used by only one connection and the queue will be deleted when that connection closes
                ->withAutoDeletion() // queue that has had at least one consumer is deleted when last consumer unsubscribes
                ->withDeadLetterExchangeTarget($amqpExchange);
```

## Available Bindings Configuration

To connect consumer directly to a AMQP Queue, we need to provide `Ecotone` with information, how the Queue is configured.

```php
class AmqpConfiguration
{
    #[ServiceContext] 
    public function registerAmqpConfig(): array
    {
        return [
            AmqpQueue::createWith("orders"), // 1
            AmqpExchange::createDirectExchange("system"), // 2
            AmqpBinding::createFromNames("system", "orders", "placeOrder"), // 3
            AmqpMessageConsumerConfiguration::create("orders_consumer", "orders") // 4
        ];
    }
}
```

1. `AmqpQueue::createWith(string $name)` - Registers Queue with specific name
2. `AmqpExchange::create*(string $name)` - Registers of given type with specific name
3. `AmqpBinding::createFromName(string $exchangeName, string $queueName, string $routingKey)`- Registering binding between exchange and queue
4. Provides Consumer that will be registered at given name `"orders_consumer"` and will be polling `"orders"` queue

## Publisher Acknowledgments

By default Ecotone will aim for resiliency to avoid Message being lost. This protects from lost heartbeats issue (AMQP bug which make message vanish without exceptions) and ensures that Message are considered delivered only when Broker has acknowledged storing them on the Broker side (Using [Publisher confirms](https://www.rabbitmq.com/docs/confirms#publisher-confirms)).\
\
However Publisher confirms comes with time cost, as it makes publishing process awaits for acknowledge from RabbitMQ. Therefore if delivery guarantee is not an issue, and we can accept risk of losing messages we can consider disable it to speed up publishing time:

```php
#[ServiceContext]
public function amqpChannel() : array
{
    return [
        AmqpBackedMessageChannelBuilder::create("orders")
            ->withPublisherAcknowledgments(false)
    ];
}
```

{% hint style="success" %}
Publisher acknowledgments can be combined with [Outbox](/modelling/recovering-tracing-and-monitoring/resiliency/outbox-pattern.md) to ensure high message guarantee.
{% endhint %}

## Publisher Transactions

`Ecotone AMQP` comes with support for RabbitMQ Transaction for published messages.\
This means that, if you send more than one message at time, it will be commited together.

If you want to enable/disable for all [Asynchronous Endpoints](/tutorial-php-ddd-cqrs-event-sourcing/php-asynchronous-processing.md) or specific for Command Bus. You may use of `ServiceContext.`

{% hint style="info" %}
By default RabbitMQ transactions are disabled, as you may ensure consistency using [Resilient Sending](/modelling/recovering-tracing-and-monitoring/resiliency/resilient-sending.md).
{% endhint %}

```php
class ChannelConfiguration
{
    #[ServiceContext]
    public function registerTransactions() : array
    {
        return [
            AmqpConfiguration::createWithDefaults()
                ->withTransactionOnAsynchronousEndpoints(false)
                ->withTransactionOnCommandBus(false)
        ];
    }

}
```

To enable transactions on specific endpoint if default is disabled, mark consumer with `Ecotone\Amqp\AmqpTransaction\AmqpTransaction` annotation.

```php
    #[AmqpTransaction)]
    #[MessageConsumer("consumer")]
    public function execute(string $message) : void
    {
        // do something with Message
    }
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ecotone.tech/modules/amqp-support-rabbitmq/message-publisher.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
