- Create AnsibleDeployStage using framework's Process module for secure command execution - Integrate AnsibleDeployStage into DeploymentPipelineCommands for production deployments - Add force_deploy flag support in Ansible playbook to override stale locks - Use PHP deployment module as orchestrator (php console.php deploy:production) - Fix ErrorAggregationInitializer to use Environment class instead of $_ENV superglobal Architecture: - BuildStage → AnsibleDeployStage → HealthCheckStage for production - Process module provides timeout, error handling, and output capture - Ansible playbook supports rollback via rollback-git-based.yml - Zero-downtime deployments with health checks
220 lines
8.1 KiB
PHP
220 lines
8.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../vendor/autoload.php';
|
|
|
|
use App\Framework\Notification\Notification;
|
|
use App\Framework\Notification\NotificationDispatcher;
|
|
use App\Framework\Notification\Dispatcher\DispatchStrategy;
|
|
use App\Framework\Notification\ValueObjects\NotificationChannel;
|
|
use App\Framework\Notification\ValueObjects\NotificationPriority;
|
|
use App\Framework\Notification\ValueObjects\SystemNotificationType;
|
|
|
|
/**
|
|
* Multi-Channel Notification Dispatch Example
|
|
*
|
|
* Demonstrates the four dispatch strategies:
|
|
* - ALL: Send to all channels regardless of failures
|
|
* - FIRST_SUCCESS: Stop after first successful delivery
|
|
* - FALLBACK: Try next only if previous failed
|
|
* - ALL_OR_NONE: All must succeed or entire dispatch fails
|
|
*/
|
|
|
|
echo "=== Multi-Channel Notification Dispatch Examples ===\n\n";
|
|
|
|
// Setup (in real app, get from DI container)
|
|
$dispatcher = $container->get(NotificationDispatcher::class);
|
|
|
|
// Example 1: ALL Strategy - Send to all channels
|
|
echo "1. ALL Strategy - Send to all channels\n";
|
|
echo str_repeat("-", 50) . "\n";
|
|
|
|
$notification = Notification::create(
|
|
recipientId: 'user_123',
|
|
type: new SystemNotificationType('system.update'),
|
|
title: 'System Update Available',
|
|
body: 'A new system update is available. Please review and install.',
|
|
NotificationChannel::TELEGRAM,
|
|
NotificationChannel::EMAIL,
|
|
NotificationChannel::SMS
|
|
)->withPriority(NotificationPriority::NORMAL);
|
|
|
|
$result = $dispatcher->sendNow($notification, DispatchStrategy::ALL);
|
|
|
|
echo "Status: " . ($result->isSuccess() ? "✅ SUCCESS" : "❌ FAILURE") . "\n";
|
|
echo "Successful channels: " . count($result->getSuccessful()) . "\n";
|
|
echo "Failed channels: " . count($result->getFailed()) . "\n";
|
|
|
|
foreach ($result->getSuccessful() as $channelResult) {
|
|
echo " ✅ {$channelResult->channel->value}: " . json_encode($channelResult->metadata) . "\n";
|
|
}
|
|
|
|
foreach ($result->getFailed() as $channelResult) {
|
|
echo " ❌ {$channelResult->channel->value}: {$channelResult->errorMessage}\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
// Example 2: FIRST_SUCCESS Strategy - Stop after first success
|
|
echo "2. FIRST_SUCCESS Strategy - Quick delivery\n";
|
|
echo str_repeat("-", 50) . "\n";
|
|
|
|
$notification = Notification::create(
|
|
recipientId: 'user_456',
|
|
type: new SystemNotificationType('order.shipped'),
|
|
title: 'Your Order Has Shipped',
|
|
body: 'Your order #12345 has been shipped and is on its way!',
|
|
NotificationChannel::TELEGRAM, // Try Telegram first
|
|
NotificationChannel::EMAIL, // Then Email if Telegram fails
|
|
NotificationChannel::SMS // Then SMS if Email fails
|
|
)->withPriority(NotificationPriority::HIGH);
|
|
|
|
$result = $dispatcher->sendNow($notification, DispatchStrategy::FIRST_SUCCESS);
|
|
|
|
echo "Status: " . ($result->isSuccess() ? "✅ SUCCESS" : "❌ FAILURE") . "\n";
|
|
echo "Delivery stopped after first success\n";
|
|
echo "Channels attempted: " . (count($result->getSuccessful()) + count($result->getFailed())) . "\n";
|
|
|
|
foreach ($result->getSuccessful() as $channelResult) {
|
|
echo " ✅ {$channelResult->channel->value}: Delivered successfully\n";
|
|
}
|
|
|
|
foreach ($result->getFailed() as $channelResult) {
|
|
echo " ❌ {$channelResult->channel->value}: {$channelResult->errorMessage}\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
// Example 3: FALLBACK Strategy - Telegram -> Email -> SMS chain
|
|
echo "3. FALLBACK Strategy - Graceful degradation\n";
|
|
echo str_repeat("-", 50) . "\n";
|
|
|
|
$notification = Notification::create(
|
|
recipientId: 'user_789',
|
|
type: new SystemNotificationType('security.alert'),
|
|
title: 'Security Alert',
|
|
body: 'Unusual login activity detected on your account.',
|
|
NotificationChannel::TELEGRAM, // Primary: Telegram (instant)
|
|
NotificationChannel::EMAIL, // Fallback 1: Email (reliable)
|
|
NotificationChannel::SMS // Fallback 2: SMS (last resort)
|
|
)->withPriority(NotificationPriority::URGENT);
|
|
|
|
$result = $dispatcher->sendNow($notification, DispatchStrategy::FALLBACK);
|
|
|
|
echo "Status: " . ($result->isSuccess() ? "✅ SUCCESS" : "❌ FAILURE") . "\n";
|
|
echo "Fallback chain executed\n";
|
|
|
|
foreach ($result->getSuccessful() as $channelResult) {
|
|
echo " ✅ {$channelResult->channel->value}: Delivered (fallback stopped here)\n";
|
|
}
|
|
|
|
foreach ($result->getFailed() as $channelResult) {
|
|
echo " ❌ {$channelResult->channel->value}: Failed, tried next channel\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
// Example 4: ALL_OR_NONE Strategy - Critical notifications
|
|
echo "4. ALL_OR_NONE Strategy - All must succeed\n";
|
|
echo str_repeat("-", 50) . "\n";
|
|
|
|
$notification = Notification::create(
|
|
recipientId: 'user_101',
|
|
type: new SystemNotificationType('account.deleted'),
|
|
title: 'Account Deletion Confirmation',
|
|
body: 'Your account has been permanently deleted as requested.',
|
|
NotificationChannel::EMAIL,
|
|
NotificationChannel::SMS
|
|
)->withPriority(NotificationPriority::URGENT);
|
|
|
|
$result = $dispatcher->sendNow($notification, DispatchStrategy::ALL_OR_NONE);
|
|
|
|
echo "Status: " . ($result->isSuccess() ? "✅ ALL SUCCEEDED" : "❌ STOPPED ON FIRST FAILURE") . "\n";
|
|
echo "Successful channels: " . count($result->getSuccessful()) . "\n";
|
|
echo "Failed channels: " . count($result->getFailed()) . "\n";
|
|
|
|
if ($result->isFailure()) {
|
|
echo "⚠️ Critical notification failed - some channels did not receive the message\n";
|
|
}
|
|
|
|
foreach ($result->getSuccessful() as $channelResult) {
|
|
echo " ✅ {$channelResult->channel->value}: Delivered\n";
|
|
}
|
|
|
|
foreach ($result->getFailed() as $channelResult) {
|
|
echo " ❌ {$channelResult->channel->value}: {$channelResult->errorMessage}\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
// Example 5: Async Multi-Channel with Strategy
|
|
echo "5. Async Multi-Channel Dispatch\n";
|
|
echo str_repeat("-", 50) . "\n";
|
|
|
|
$notification = Notification::create(
|
|
recipientId: 'user_202',
|
|
type: new SystemNotificationType('newsletter.weekly'),
|
|
title: 'Your Weekly Newsletter',
|
|
body: 'Check out this week\'s highlights and updates.',
|
|
NotificationChannel::EMAIL,
|
|
NotificationChannel::TELEGRAM
|
|
)->withPriority(NotificationPriority::LOW);
|
|
|
|
// Async dispatch - queued with priority mapping
|
|
$dispatcher->send($notification, async: true, strategy: DispatchStrategy::ALL);
|
|
|
|
echo "✅ Notification queued for async dispatch\n";
|
|
echo "Strategy: ALL (will attempt all channels in background)\n";
|
|
echo "Priority: LOW (mapped to queue priority)\n";
|
|
|
|
echo "\n";
|
|
|
|
// Example 6: Strategy Selection Based on Priority
|
|
echo "6. Dynamic Strategy Selection\n";
|
|
echo str_repeat("-", 50) . "\n";
|
|
|
|
function selectStrategy(NotificationPriority $priority): DispatchStrategy
|
|
{
|
|
return match ($priority) {
|
|
NotificationPriority::URGENT => DispatchStrategy::ALL_OR_NONE, // Critical: all must succeed
|
|
NotificationPriority::HIGH => DispatchStrategy::FIRST_SUCCESS, // Quick delivery
|
|
NotificationPriority::NORMAL => DispatchStrategy::FALLBACK, // Graceful degradation
|
|
NotificationPriority::LOW => DispatchStrategy::ALL, // Best effort
|
|
};
|
|
}
|
|
|
|
$urgentNotification = Notification::create(
|
|
recipientId: 'user_303',
|
|
type: new SystemNotificationType('payment.failed'),
|
|
title: 'Payment Failed',
|
|
body: 'Your payment could not be processed.',
|
|
NotificationChannel::EMAIL,
|
|
NotificationChannel::SMS
|
|
)->withPriority(NotificationPriority::URGENT);
|
|
|
|
$strategy = selectStrategy($urgentNotification->priority);
|
|
echo "Priority: {$urgentNotification->priority->value}\n";
|
|
echo "Selected Strategy: {$strategy->value}\n";
|
|
|
|
$result = $dispatcher->sendNow($urgentNotification, $strategy);
|
|
echo "Result: " . ($result->isSuccess() ? "✅ SUCCESS" : "❌ FAILURE") . "\n";
|
|
|
|
echo "\n";
|
|
|
|
// Summary
|
|
echo "=== Strategy Summary ===\n";
|
|
echo "ALL: Send to all channels, continue even if some fail\n";
|
|
echo " Use case: Non-critical updates, newsletters, marketing\n\n";
|
|
|
|
echo "FIRST_SUCCESS: Stop after first successful delivery\n";
|
|
echo " Use case: Time-sensitive notifications, quick delivery needed\n\n";
|
|
|
|
echo "FALLBACK: Try next only if previous failed\n";
|
|
echo " Use case: Graceful degradation, Telegram -> Email -> SMS chain\n\n";
|
|
|
|
echo "ALL_OR_NONE: All must succeed or entire dispatch fails\n";
|
|
echo " Use case: Critical notifications, legal compliance, account actions\n\n";
|
|
|
|
echo "✅ Multi-channel dispatch examples completed\n";
|