commandHandler method
Process a command through the full pipeline This is the main entry point for command processing
Uses explicit locking to prevent race conditions when multiple commands arrive in rapid succession. This ensures that even if there are subtle timing issues in the async flow, commands are always processed sequentially.
Implementation
@override
Future<void> commandHandler(Command command) async {
// Wrap entire command processing in a lock to guarantee sequential execution
// This fixes the concurrency bug reported in EVENTADOR_CONCURRENCY_BUG.md
return await _commandLock.synchronized(() async {
try {
// Ensure aggregate is initialized
if (!isInitialized) {
_currentState = createInitialState();
}
// Check optimistic concurrency control
await _checkConcurrency(command);
// Handle the command and generate events
final events = await handleCommand(currentState, command);
// Persist all generated events (this also updates state via eventHandler)
if (events.isNotEmpty) {
await persistEvents(events);
}
// Call command processing hook
await onCommandProcessed(command, events);
} catch (e) {
await onCommandFailure(command, e);
rethrow;
}
});
}