# Bus Package Specification ## Overview The Bus package provides a robust command and event bus implementation that matches Laravel's bus functionality. It integrates with our Queue, Event, and Pipeline packages to provide a complete message bus solution with support for command handling, event dispatching, and middleware processing. > **Related Documentation** > - See [Laravel Compatibility Roadmap](laravel_compatibility_roadmap.md) for implementation status > - See [Foundation Integration Guide](foundation_integration_guide.md) for integration patterns > - See [Testing Guide](testing_guide.md) for testing approaches > - See [Getting Started Guide](getting_started.md) for development setup > - See [Events Package Specification](events_package_specification.md) for event handling > - See [Queue Package Specification](queue_package_specification.md) for queue integration ## Core Features ### 1. Command Bus ```dart /// Core command bus implementation class CommandBus implements CommandBusContract { final Container _container; final QueueContract? _queue; final PipelineContract _pipeline; CommandBus( this._container, this._pipeline, [ this._queue ]); /// Dispatches a command Future dispatch(Command command) async { if (command is ShouldQueue && _queue != null) { return await dispatchToQueue(command); } return await dispatchNow(command); } /// Dispatches a command immediately Future dispatchNow(Command command) async { var handler = _resolveHandler(command); return await _pipeline .send(command) .through(_getPipes()) .then((cmd) => handler.handle(cmd)); } /// Dispatches a command to queue Future dispatchToQueue(Command command) async { await _queue!.push(QueuedCommandJob( command: command, handler: _resolveHandler(command) )); } /// Creates a command batch PendingBatch batch(List commands) { return PendingCommandBatch(this, commands); } /// Creates a command chain PendingChain chain(List commands) { return PendingCommandChain(this, commands); } /// Resolves command handler Handler _resolveHandler(Command command) { var handlerType = command.handler; return _container.make(handlerType); } /// Gets command pipes List _getPipes() { return [ TransactionPipe(), ValidationPipe(), AuthorizationPipe() ]; } } ``` ### 2. Event Bus ```dart /// Core event bus implementation class EventBus implements EventBusContract { final Container _container; final EventDispatcherContract _events; final QueueContract? _queue; EventBus( this._container, this._events, [ this._queue ]); /// Dispatches an event Future dispatch(Event event) async { if (event is ShouldQueue && _queue != null) { await dispatchToQueue(event); } else { await dispatchNow(event); } } /// Dispatches an event immediately Future dispatchNow(Event event) async { await _events.dispatch(event); } /// Dispatches an event to queue Future dispatchToQueue(Event event) async { await _queue!.push(QueuedEventJob( event: event, listeners: _events.getListeners(event.runtimeType) )); } /// Registers an event listener void listen(void Function(T event) listener) { _events.listen(listener); } /// Registers an event subscriber void subscribe(EventSubscriber subscriber) { _events.subscribe(subscriber); } } ``` ### 3. Bus Middleware ```dart /// Transaction middleware class TransactionPipe implements PipeContract { final DatabaseManager _db; TransactionPipe(this._db); @override Future handle(dynamic passable, Function next) async { return await _db.transaction((tx) async { return await next(passable); }); } } /// Validation middleware class ValidationPipe implements PipeContract { final Validator _validator; ValidationPipe(this._validator); @override Future handle(dynamic passable, Function next) async { if (passable is ValidatableCommand) { await _validator.validate( passable.toMap(), passable.rules() ); } return await next(passable); } } /// Authorization middleware class AuthorizationPipe implements PipeContract { final AuthManager _auth; AuthorizationPipe(this._auth); @override Future handle(dynamic passable, Function next) async { if (passable is AuthorizableCommand) { if (!await passable.authorize(_auth)) { throw UnauthorizedException(); } } return await next(passable); } } ``` ### 4. Command Batching ```dart /// Pending command batch class PendingCommandBatch implements PendingBatch { final CommandBus _bus; final List _commands; bool _allowFailures = false; PendingCommandBatch(this._bus, this._commands); /// Allows failures in batch PendingBatch allowFailures() { _allowFailures = true; return this; } /// Dispatches the batch Future dispatch() async { for (var command in _commands) { try { await _bus.dispatchNow(command); } catch (e) { if (!_allowFailures) rethrow; } } } } /// Pending command chain class PendingCommandChain implements PendingChain { final CommandBus _bus; final List _commands; PendingCommandChain(this._bus, this._commands); /// Dispatches the chain Future dispatch() async { dynamic result; for (var command in _commands) { if (command is ChainedCommand) { command.setPreviousResult(result); } result = await _bus.dispatchNow(command); } } } ``` ## Integration Examples ### 1. Command Bus Usage ```dart // Define command class CreateOrder implements Command { final String customerId; final List products; @override Type get handler => CreateOrderHandler; } // Define handler class CreateOrderHandler implements Handler { final OrderRepository _orders; CreateOrderHandler(this._orders); @override Future handle(CreateOrder command) async { return await _orders.create( customerId: command.customerId, products: command.products ); } } // Dispatch command var order = await bus.dispatch(CreateOrder( customerId: '123', products: ['abc', 'xyz'] )); ``` ### 2. Event Bus Usage ```dart // Define event class OrderCreated implements Event { final Order order; OrderCreated(this.order); } // Register listener eventBus.listen((event) async { await notifyCustomer(event.order); }); // Dispatch event await eventBus.dispatch(OrderCreated(order)); ``` ### 3. Command Batching ```dart // Create batch await bus.batch([ CreateOrder(...), UpdateInventory(...), NotifyShipping(...) ]) .allowFailures() .dispatch(); // Create chain await bus.chain([ CreateOrder(...), ProcessPayment(...), ShipOrder(...) ]) .dispatch(); ``` ## Testing ```dart void main() { group('Command Bus', () { test('dispatches commands', () async { var bus = CommandBus(container, pipeline); var command = CreateOrder(...); await bus.dispatch(command); verify(() => handler.handle(command)).called(1); }); test('handles command batch', () async { var bus = CommandBus(container, pipeline); await bus.batch([ CreateOrder(...), UpdateInventory(...) ]).dispatch(); verify(() => bus.dispatchNow(any())).called(2); }); }); group('Event Bus', () { test('dispatches events', () async { var bus = EventBus(container, dispatcher); var event = OrderCreated(order); await bus.dispatch(event); verify(() => dispatcher.dispatch(event)).called(1); }); test('queues events', () async { var bus = EventBus(container, dispatcher, queue); var event = OrderShipped(order); await bus.dispatch(event); verify(() => queue.push(any())).called(1); }); }); } ``` ## Next Steps 1. Implement core bus features 2. Add middleware support 3. Add batching/chaining 4. Add queue integration 5. Write tests 6. Add benchmarks ## Development Guidelines ### 1. Getting Started Before implementing bus features: 1. Review [Getting Started Guide](getting_started.md) 2. Check [Laravel Compatibility Roadmap](laravel_compatibility_roadmap.md) 3. Follow [Testing Guide](testing_guide.md) 4. Use [Foundation Integration Guide](foundation_integration_guide.md) 5. Review [Events Package Specification](events_package_specification.md) 6. Review [Queue Package Specification](queue_package_specification.md) ### 2. Implementation Process For each bus feature: 1. Write tests following [Testing Guide](testing_guide.md) 2. Implement following Laravel patterns 3. Document following [Getting Started Guide](getting_started.md#documentation) 4. Integrate following [Foundation Integration Guide](foundation_integration_guide.md) ### 3. Quality Requirements All implementations must: 1. Pass all tests (see [Testing Guide](testing_guide.md)) 2. Meet Laravel compatibility requirements 3. Follow integration patterns (see [Foundation Integration Guide](foundation_integration_guide.md)) 4. Match specifications in related packages ### 4. Integration Considerations When implementing bus features: 1. Follow patterns in [Foundation Integration Guide](foundation_integration_guide.md) 2. Ensure Laravel compatibility per [Laravel Compatibility Roadmap](laravel_compatibility_roadmap.md) 3. Use testing approaches from [Testing Guide](testing_guide.md) 4. Follow development setup in [Getting Started Guide](getting_started.md) ### 5. Performance Guidelines Bus system must: 1. Handle high command throughput 2. Process events efficiently 3. Support async operations 4. Scale horizontally 5. Meet performance targets in [Laravel Compatibility Roadmap](laravel_compatibility_roadmap.md#performance-benchmarks) ### 6. Testing Requirements Bus tests must: 1. Cover all command scenarios 2. Test event handling 3. Verify queue integration 4. Check middleware behavior 5. Follow patterns in [Testing Guide](testing_guide.md) ### 7. Documentation Requirements Bus documentation must: 1. Explain command patterns 2. Show event examples 3. Cover error handling 4. Include performance tips 5. Follow standards in [Getting Started Guide](getting_started.md#documentation)