Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Messenger Azure Bundle Laravel Package

aymdev/messenger-azure-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:
    composer require aymdev/messenger-azure-bundle nyholm/psr7
    
  2. Configure messenger.yaml:
    framework:
        messenger:
            transports:
                azure_queue:
                    dsn: '%env(AZURE_SERVICE_BUS_DSN)%'
                    options:
                        entity_path: 'your-queue-name'
    
  3. Set environment variable (URL-encode special characters in keys):
    AZURE_SERVICE_BUS_DSN=azure://KEY_NAME:KEY_VALUE@NAMESPACE
    
  4. Dispatch a test message:
    use Symfony\Component\Messenger\MessageBusInterface;
    
    $bus->dispatch(new YourMessage());
    

First Use Case: Queue Consumer

  1. Define a message handler:
    use Symfony\Component\Messenger\Attribute\AsMessageHandler;
    
    #[AsMessageHandler]
    public function __invoke(YourMessage $message)
    {
        // Handle message
    }
    
  2. Run the worker:
    php bin/console messenger:consume azure_queue -vv
    

Implementation Patterns

Common Workflows

1. Topic/Subscription Setup

  • Topic Configuration:
    transports:
        azure_topic:
            dsn: '%env(AZURE_SERVICE_BUS_DSN)%'
            options:
                entity_path: 'your-topic'
                subscription: 'your-subscription'
    
  • Publish a message:
    $bus->dispatch(new YourMessage());
    

2. Message Serialization

  • Custom Serializer (extend AymDev\MessengerAzureBundle\Serializer\AzureSerializer):
    use AymDev\MessengerAzureBundle\Serializer\AzureSerializer;
    
    class YourAzureSerializer extends AzureSerializer
    {
        public function encode(array $data): string
        {
            return json_encode($data, JSON_THROW_ON_ERROR);
        }
    
        public function decode(string $data): array
        {
            return json_decode($data, true, 512, JSON_THROW_ON_ERROR);
        }
    }
    
  • Register in messenger.yaml:
    transports:
        azure_transport:
            serializer: 'App\Serializer\YourAzureSerializer'
    

3. Broker Properties

  • Add custom properties (via AzureBrokerPropertiesStamp):
    use AymDev\MessengerAzureBundle\Messenger\Stamp\AzureBrokerPropertiesStamp;
    
    $stamp = new AzureBrokerPropertiesStamp([
        'CustomProperty' => 'value',
        'TimeToLive' => 3600.0, // Must be float (seconds)
    ]);
    $bus->dispatch(new YourMessage(), [$stamp]);
    

4. Delayed Messages

  • Use DelayStamp (converted to ScheduledEnqueueTimeUtc):
    use Symfony\Component\Messenger\Stamp\DelayStamp;
    
    $bus->dispatch(new YourMessage(), [new DelayStamp(3600)]);
    

5. Error Handling

  • Listen for decoding failures (via console.error event):
    use AymDev\MessengerAzureBundle\Messenger\Exception\SerializerDecodingException;
    use Symfony\Component\Console\Event\ConsoleErrorEvent;
    
    $eventDispatcher->addListener(ConsoleErrorEvent::class, function (ConsoleErrorEvent $event) {
        if ($event->getError() instanceof SerializerDecodingException) {
            $stamp = $event->getError()->getEnvelope()->all()[AzureMessageStamp::class];
            // Log topic/queue, subscription, and original message
        }
    });
    

Integration Tips

1. Environment-Specific Configs

  • Use %env(AZURE_SERVICE_BUS_DSN)% with .env files for different environments (dev/staging/prod).
  • Example .env.prod:
    AZURE_SERVICE_BSN=azure://PROD_KEY_NAME:PROD_KEY_VALUE@PROD_NAMESPACE
    

2. Retry Logic

  • Leverage Symfony Messenger’s retryable exceptions:
    use Symfony\Component\Messenger\Attribute\AsMessageHandler;
    use Symfony\Component\Messenger\Exception\RetryException;
    
    #[AsMessageHandler]
    public function __invoke(YourMessage $message)
    {
        if ($someFailure) {
            throw new RetryException('Failed to process', 3); // Retry 3 times
        }
    }
    

3. Monitoring

  • Log stamps for debugging:
    use AymDev\MessengerAzureBundle\Messenger\Stamp\AzureMessageStamp;
    
    #[AsMessageHandler]
    public function __invoke(YourMessage $message, AzureMessageStamp $stamp)
    {
        $this->logger->info('Processing message from topic: '.$stamp->getEntityPath());
    }
    

4. Testing

  • Mock the transport in PHPUnit:
    use AymDev\MessengerAzureBundle\Transport\AzureTransport;
    
    $transport = $this->createMock(AzureTransport::class);
    $transport->method('send')->willReturn(new Envelope(new YourMessage()));
    $this->container->set(AzureTransport::class, $transport);
    

Gotchas and Tips

Pitfalls

  1. DSN URL Encoding

    • Issue: Special characters in KEY_NAME/KEY_VALUE break URL parsing.
    • Fix: URL-encode the DSN:
      $dsn = str_replace(':', '%3A', 'azure://key:name@namespace');
      
    • Workaround: Use %2F for /, %3A for :, etc.
  2. TimeToLive Must Be Float

    • Issue: TimeToLive broker property must be a float (seconds), not an integer.
    • Fix:
      $stamp = new AzureBrokerPropertiesStamp(['TimeToLive' => 3600.0]);
      
  3. SAS Token Expiry

    • Issue: Default token_expiry: 3600 (1 hour) may cause auth failures if messages take longer to process.
    • Fix: Increase expiry or regenerate tokens dynamically (handled automatically in v1.3.0+).
  4. Peek-Lock vs. Receive-and-Delete

    • Issue: peek-lock mode requires manual deletion of messages (via AzureMessageStamp::getDeleteUrl()).
    • Fix: Always delete messages in handlers:
      #[AsMessageHandler]
      public function __invoke(YourMessage $message, AzureMessageStamp $stamp)
      {
          try {
              // Process message
          } finally {
              if ($stamp->getDeleteUrl()) {
                  $this->httpClient->request('DELETE', $stamp->getDeleteUrl());
              }
          }
      }
      
  5. DateTime Timezone Mismatch

    • Issue: AzureBrokerPropertiesStamp may deserialize DateTime objects with incorrect timezones.
    • Fix: Explicitly set timezone:
      $stamp = new AzureBrokerPropertiesStamp(['ScheduledEnqueueTimeUtc' => new \DateTime('+1 hour', new \DateTimeZone('UTC'))]);
      

Debugging Tips

  1. Enable HTTP Client Logging

    • Add to config/packages/dev/messenger.yaml:
      transports:
          azure_transport:
              options:
                  http_client:
                      logger: true
      
    • View logs with:
      php bin/console messenger:consume azure_transport -vv
      
  2. Inspect Raw Azure Responses

    • Use a custom middleware to log raw requests/responses:
      use Symfony\Component\HttpClient\Middleware\LoggerMiddleware;
      
      $client = HttpClient::create([
          'middlewares' => [
              new LoggerMiddleware(Logger::class),
          ],
      ]);
      
  3. Validate SAS Tokens

    • Test token generation manually:
      use AymDev\MessengerAzureBundle\Transport\AzureTransport;
      
      $transport = new AzureTransport($dsn, $options);
      $token = $transport->generateSasToken();
      // Verify token works in Azure Portal or Postman
      

Extension Points

  1. Custom Stamps

    • Extend AzureBrokerPropertiesStamp for additional Azure-specific metadata:
      class CustomAzureStamp extends AzureBrokerPropertiesStamp
      {
          public function __construct(array $properties, private string $customField)
          {
              parent::__construct($properties);
          }
      
          public function getCustomField(): string
          {
              return $this->customField;
          }
      }
      
  2. Transport Decorators

    • Decorate AzureTransport to add pre/post-processing:
      use AymDev\MessengerAzureBundle\Transport\AzureTransportInterface;
      
      class
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver