Message Handlers¶
Complete documentation of all 36 MessageBus handlers that execute business logic in the Expensis automation system.
Overview¶
| Metric | Count |
|---|---|
| Total Handlers | 36 |
| Command Mappings | 39 commands → 36 handlers |
| 1:1 Mappings | 35 perfect matches |
| Special Cases | 1 (multi-command handler) |
Each handler implements the MessageHandler interface and is decorated with #[AsMessageHandler].
Handler Architecture¶
sequenceDiagram
participant Dispatcher
participant MessageBus
participant Router
participant Handler
participant DB
participant Event
Dispatcher->>MessageBus: dispatch(Command)
MessageBus->>Router: Route to handler
Router->>Handler: __invoke(Command)
Handler->>DB: Execute business logic
Handler->>Event: Trigger WorkerMessageHandledEvent
Event->>Event: MessageConsumedHandler checks for chain
alt Has chain
Event->>MessageBus: Dispatch next command
end
All Handlers (Alphabetical)¶
Sync & Import Handlers¶
| Handler | Command | Purpose | Location |
|---|---|---|---|
| ActivateRoutitAddonsHandler | ActivateRoutitAddonsCommand | Activate mobile addons via Routit Nina API | src/MessageBus/AsynchronousHandler/ |
| CancelRoutitAddonsHandler | CancelRoutitAddonsCommand | Cancel mobile addons via Routit Nina API | src/MessageBus/AsynchronousHandler/ |
| GrexxAsyncHandler | GrexxAsyncCommand | Sync Grexx orders, create chains | src/MessageBus/AsynchronousHandler/ |
| IrmaScraperAsyncHandler | IrmaScraperAsyncCommand | Scrape IRMA data | src/MessageBus/AsynchronousHandler/ |
| KpnEenPartnerSyncHandler | KpnEenPartnerSyncCommand SyncTaskEndStateCommand |
KPN EEN partner sync (multi-command handler) | src/MessageBus/AsynchronousHandler/ |
| KpnEenSyncHandler | KpnEenSyncCommand | KPN EEN platform sync | src/MessageBus/AsynchronousHandler/ |
| KpnGripSyncHandler | KpnGripSyncCommand | KPN GRIP sync | src/MessageBus/AsynchronousHandler/ |
| KpnSp16ImportHandler | KpnSp16ImportCommand | Import KPN SP16 data | src/MessageBus/AsynchronousHandler/ |
| KpnSp16SyncHandler | KpnSp16SyncCommand | KPN SP16 sync orchestrator | src/MessageBus/AsynchronousHandler/ |
| PupeteerKpnSp16SyncHandler | PupeteerKpnSp16SyncCommand | KPN SP16 Puppeteer scraping | src/MessageBus/AsynchronousHandler/ |
| RoutitBillingSyncHandler | RoutitBillingSyncCommand | Routit billing sync | src/MessageBus/AsynchronousHandler/ |
| RoutitDownloadCdrsHandler | RoutitDownloadCdrsCommand | Download Routit CDR files | src/MessageBus/AsynchronousHandler/ |
| RoutitImportCdrsHandler | RoutitImportCdrsCommand | Import Routit CDRs (bulk insert) | src/MessageBus/AsynchronousHandler/ |
| RoutitInvoiceHandler | RoutitInvoiceCommand | Generate Routit invoice | src/MessageBus/AsynchronousHandler/ |
| RoutitRequestCdrsHandler | RoutitRequestCdrsCommand | Request CDRs from Routit API | src/MessageBus/AsynchronousHandler/ |
| RoutitSyncSubscriptionsHandler | RoutitSyncSubscriptionsCommand | Sync Routit subscriptions | src/MessageBus/AsynchronousHandler/ |
| TMobileCalviSyncHandler | TMobileCalviSyncCommand | T-Mobile Calvi sync | src/MessageBus/AsynchronousHandler/ |
| TMobileSyncHandler | TMobileSyncCommand | T-Mobile sync | src/MessageBus/AsynchronousHandler/ |
| VodafoneSyncHandler | VodafoneSyncCommand | Vodafone sync | src/MessageBus/AsynchronousHandler/ |
| YielderSyncHandler | YielderSyncCommand | Yielder/Odido sync | src/MessageBus/AsynchronousHandler/ |
Calculation Handlers¶
| Handler | Command | Purpose | Location |
|---|---|---|---|
| BillingInsightTotalsHandler | BillingInsightTotalsCommand | Generate billing insights | src/MessageBus/AsynchronousHandler/ |
| CalculateSubscriptionTotalsHandler | CalculateSubscriptionTotalsCommand | Calculate subscription-level totals | src/MessageBus/AsynchronousHandler/ |
| CalculateTotalsHandler | CalculateTotalsCommand | Calculate customer billing totals | src/MessageBus/AsynchronousHandler/ |
| CalculateTotalsRateplanHandler | CalculateTotalsRateplanCommand | Calculate totals with rate plan logic | src/MessageBus/AsynchronousHandler/ |
| DispatchTotalsBackupHandler | DispatchTotalsBackupCommand | Backup totals to historical table | src/MessageBus/AsynchronousHandler/ |
| DispatchTotalsHandler | DispatchTotalsCommand | Route to correct totals calculation | src/MessageBus/AsynchronousHandler/ |
Data Management Handlers¶
| Handler | Command | Purpose | Location |
|---|---|---|---|
| CalculationImportHandler | CalculationImportCommand | Import calculations from API | src/MessageBus/AsynchronousHandler/ |
| FillReportsHandler | FillReportsCommand | Generate and fill reports | src/MessageBus/AsynchronousHandler/ |
| GenerateCustomerExcelReportHandler | GenerateCustomerExcelReportCommand | Generate Excel export | src/MessageBus/AsynchronousHandler/ |
| GenerateKpnSP16InvoiceHandler | GenerateKpnSP16InvoiceCommand | Generate KPN SP16 invoice | src/MessageBus/AsynchronousHandler/ |
| FetchPdfKpnInvoiceHandler | FetchPdfKpnInvoiceCommand | Fetch KPN invoice PDF | src/MessageBus/AsynchronousHandler/ |
Administrative Handlers¶
| Handler | Command | Purpose | Location |
|---|---|---|---|
| SaveStatusHandler | SaveStatusCommand | Update status records | src/MessageBus/AsynchronousHandler/ |
| SyncProfileHandler | SyncProfileCommand | Master router for all provider syncs | src/MessageBus/AsynchronousHandler/ |
| UpdateCostCenterHandler | UpdateCostCenterCommand | Update cost center data | src/MessageBus/AsynchronousHandler/ |
| UpdateParentOrderHandler | UpdateParentOrderCommand | Update parent order relationships | src/MessageBus/AsynchronousHandler/ |
Critical Handlers¶
1. SyncProfileHandler (Master Router)¶
Purpose: Routes sync requests to provider-specific handlers
Location: src/MessageBus/AsynchronousHandler/SyncProfileHandler.php:153
Routing Logic:
public function __invoke(SyncProfileCommand $command) {
$syncType = $command->getSyncProfile()->getSyncType();
$syncCommand = match($syncType) {
SyncType::KPN_SP16, SyncType::GRIP
=> new KpnSp16SyncCommand(...),
SyncType::MY_VODAFONE
=> new VodafoneSyncCommand(...),
SyncType::T_MOBILE
=> new TMobileCalviSyncCommand(...),
SyncType::KPN_EEN
=> new KpnEenSyncCommand(...),
SyncType::YIELDER
=> new YielderSyncCommand(...),
};
$this->commandBus->dispatch($syncCommand);
}
Impact: If this handler fails, ALL automated provider syncs stop
Usage: Dispatched every 5 minutes by sync:manager
2. DispatchTotalsHandler (Calculation Router)¶
Purpose: Routes totals calculation to appropriate handler
Location: src/MessageBus/AsynchronousHandler/DispatchTotalsHandler.php
Routing Logic:
public function __invoke(DispatchTotalsCommand $command) {
if ($this->shouldUseRateplan($customer)) {
$this->dispatch(new CalculateTotalsRateplanCommand(...));
} else {
$this->dispatch(new CalculateTotalsCommand(...));
}
}
Impact: All billing calculation depends on this router
Usage: Dispatched after every provider sync
3. CalculateTotalsHandler¶
Purpose: Calculates billing totals from CDRs
Location: src/MessageBus/AsynchronousHandler/CalculateTotalsHandler.php
Process: 1. Query all CDRs for customer and billing cycle 2. Group by subscription and device 3. Apply rate plans 4. Calculate costs 5. Update totals table 6. Dispatch BillingInsightTotalsCommand
Impact: Core billing logic - incorrect calculations = incorrect bills
Performance: Handles 10k-50k CDRs per execution
Handlers That Create Chains¶
These handlers dispatch additional commands to create workflow chains:
| Handler | Dispatches To | Chain Purpose |
|---|---|---|
| SyncProfileHandler | Provider sync commands | Route to specific provider |
| KpnSp16SyncHandler | KpnSp16ImportCommand PupeteerKpnSp16SyncCommand DispatchTotalsCommand |
Complete KPN SP16 workflow |
| DispatchTotalsHandler | CalculateTotalsCommand OR CalculateTotalsRateplanCommand |
Route to correct calculation |
| CalculateTotalsHandler | BillingInsightTotalsCommand | Generate insights after calculation |
| RoutitInvoiceHandler | CalculateTotalsCommand BillingInsightTotalsCommand SaveStatusCommand |
Complete Routit billing chain |
| GrexxAsyncHandler | UpdateParentOrderCommand IrmaScraperAsyncCommand (optional) |
Order processing chain |
| VodafoneSyncHandler | DispatchTotalsCommand DispatchTotalsBackupCommand |
Vodafone complete flow |
| TMobileCalviSyncHandler | DispatchTotalsCommand DispatchTotalsBackupCommand |
T-Mobile complete flow |
| YielderSyncHandler | CalculateSubscriptionTotalsCommand DispatchTotalsCommand DispatchTotalsBackupCommand |
Yielder complete flow |
See: Workflows Documentation for complete chain traces
Handler Patterns¶
Standard Pattern¶
#[AsMessageHandler]
class ExampleHandler
{
public function __construct(
private EntityManagerInterface $entityManager,
private MessageBusInterface $commandBus,
private LoggerInterface $logger
) {}
public function __invoke(ExampleCommand $command): void
{
try {
// 1. Extract command data
$customerId = $command->getCustomerId();
// 2. Execute business logic
$result = $this->doWork($customerId);
// 3. Persist changes
$this->entityManager->flush();
// 4. Dispatch follow-up commands (if needed)
if ($command->hasChain()) {
foreach ($command->getChain() as $nextCommand) {
$this->commandBus->dispatch($nextCommand);
}
}
} catch (\Exception $e) {
$this->logger->error("Handler failed: {$e->getMessage()}");
throw $e;
}
}
}
Router Pattern¶
#[AsMessageHandler]
class RouterHandler
{
public function __invoke(RouterCommand $command): void
{
// Determine target handler
$target = $this->determineTarget($command);
// Create appropriate command
$targetCommand = match($target) {
'typeA' => new TypeACommand(...),
'typeB' => new TypeBCommand(...),
default => throw new \Exception("Unknown type")
};
// Forward with chain
if ($command->hasChain()) {
$targetCommand->withChain($command->getChain());
}
$this->commandBus->dispatch($targetCommand);
}
}
Special Cases¶
Multi-Command Handler¶
KpnEenPartnerSyncHandler handles TWO commands:
- KpnEenPartnerSyncCommand
- SyncTaskEndStateCommand
Configuration: config/services.yaml
App\MessageBus\AsynchronousHandler\KpnEenPartnerSyncHandler:
tags:
- { name: messenger.message_handler, handles: App\MessageBus\Command\KpnEenPartnerSyncCommand }
- { name: messenger.message_handler, handles: App\MessageBus\Command\SyncTaskEndStateCommand }
Why: Both commands perform similar sync finalization logic
Handler Complexity¶
Most Complex Handlers¶
| Handler | Lines of Code | External APIs | Database Tables | Complexity |
|---|---|---|---|---|
| KpnSp16SyncHandler | ~300 | 3 (KPN portals) | 8 | Very High |
| RoutitImportCdrsHandler | ~250 | File system | 5 | High |
| CalculateTotalsHandler | ~200 | None | 6 | High |
| VodafoneSyncHandler | ~180 | 2 (Vodafone API) | 7 | High |
| TMobileCalviSyncHandler | ~150 | 1 (Calvi API) | 6 | Medium |
Simplest Handlers¶
| Handler | Lines of Code | Purpose | Complexity |
|---|---|---|---|
| SaveStatusHandler | ~30 | Update status field | Very Low |
| DispatchTotalsBackupHandler | ~40 | Copy totals row | Low |
| ActivateRoutitAddonsHandler | ~50 | Single API call | Low |
Finding Handlers¶
By Provider¶
KPN: - KpnSp16SyncHandler - KpnSp16ImportHandler - PupeteerKpnSp16SyncHandler - KpnGripSyncHandler - KpnEenSyncHandler - KpnEenPartnerSyncHandler - GenerateKpnSP16InvoiceHandler - FetchPdfKpnInvoiceHandler
T-Mobile: - TMobileCalviSyncHandler - TMobileSyncHandler
Vodafone: - VodafoneSyncHandler
Routit: - RoutitRequestCdrsHandler - RoutitDownloadCdrsHandler - RoutitImportCdrsHandler - RoutitInvoiceHandler - RoutitBillingSyncHandler - RoutitSyncSubscriptionsHandler - ActivateRoutitAddonsHandler - CancelRoutitAddonsHandler
Yielder/Odido: - YielderSyncHandler
Other: - GrexxAsyncHandler - IrmaScraperAsyncHandler
By Function¶
Sync Operations: All handlers ending in "SyncHandler"
Calculations: - CalculateTotalsHandler - CalculateTotalsRateplanHandler - CalculateSubscriptionTotalsHandler - BillingInsightTotalsHandler - DispatchTotalsHandler - DispatchTotalsBackupHandler
Data Import: - KpnSp16ImportHandler - RoutitImportCdrsHandler - RoutitDownloadCdrsHandler - CalculationImportHandler
Report Generation: - GenerateCustomerExcelReportHandler - GenerateKpnSP16InvoiceHandler - FillReportsHandler - FetchPdfKpnInvoiceHandler
Administrative: - SaveStatusHandler - UpdateCostCenterHandler - UpdateParentOrderHandler
Related Documentation¶
- Console Commands - Commands that dispatch to handlers
- Event System - MessageConsumedHandler and chain execution
- Dispatch Points - Where handlers are triggered
- Workflows - Complete execution traces
- Dependencies - Handler relationships