A high-performance, type-safe message bus framework for Swift that eliminates boilerplate while maintaining sub-millisecond latency. Built with Swift's actor model for guaranteed thread safety and supporting clean architecture through layer-based routing.
- π Blazing Fast: 100K+ messages/second with <1ms P99 latency
- π Type Safe: Complete compile-time type safety with zero runtime casting
- π Actor-Based: Built on Swift actors for guaranteed thread safety
- π Extensible: Rich plugin system for middleware, logging, metrics, and more
- ποΈ Clean Architecture: Built-in layer-based routing for architectural boundaries
- π¦ Zero Dependencies: Pure Swift with minimal external dependencies
- π§© CQRS Ready: First-class support for Commands, Queries, and Events
Add SwiftMessageBus to your Package.swift:
dependencies: [
.package(url: "https://github.com/yourusername/SwiftMessageBus.git", from: "1.0.0")
]Then add to your target:
.target(
name: "YourApp",
dependencies: ["SwiftMessageBus"]
)- In Xcode, select File > Add Package Dependencies...
- Enter the repository URL:
https://github.com/yourusername/SwiftMessageBus - Select the version you want to use
- Click Add Package
Get up and running in less than 3 minutes:
import SwiftMessageBus
// 1. Define your message payloads
struct CreateUserPayload: MessagePayload {
let name: String
let email: String
}
struct UserCreatedPayload: MessagePayload {
let userId: String
let name: String
}
// 2. Create the message bus
let messageBus = MessageBus()
// 3. Register command handlers
await messageBus.handleCommand(CreateUserPayload.self) { command in
// Process the command
let userId = UUID().uuidString
print("Creating user: \(command.payload.name)")
// Publish an event
let event = Event(
source: .domain,
payload: UserCreatedPayload(userId: userId, name: command.payload.name)
)
await messageBus.publish(event)
return CommandResult.success
}
// 4. Subscribe to events
await messageBus.subscribe(to: UserCreatedPayload.self) { event in
print("User created: \(event.payload.userId)")
}
// 5. Send a command
let command = Command(
source: .presentation,
destination: .application,
payload: CreateUserPayload(name: "John Doe", email: "john@example.com")
)
let result = try await messageBus.send(command)
print("Command result: \(result)")βββββββββββββββββββ
β Presentation β β SwiftUI/UIKit Views
βββββββββββββββββββ€
β Application β β Use Cases/Services
βββββββββββββββββββ€
β Domain β β Business Logic
βββββββββββββββββββ€
β Infrastructure β β Database/Network
βββββββββββββββββββ
β
Message Bus β Routes messages between layers
The framework enforces clean architecture through layer-based routing:
- Messages flow downward through layers
- Responses flow back up
- Cross-layer communication is validated
- Layer violations are caught at runtime
SwiftMessageBus supports three primary message patterns:
- Represent actions to be performed
- Have a single handler
- Return a result
- Example: CreateUser, UpdateProfile, DeleteAccount
- Request data without side effects
- Have a single handler
- Return the requested data
- Example: GetUser, ListProducts, SearchOrders
- Notify about something that happened
- Can have multiple subscribers
- Fire-and-forget pattern
- Example: UserCreated, OrderPlaced, PaymentReceived
Extend functionality with built-in plugins:
// Add logging
messageBus.use(LoggingPlugin())
// Add metrics collection
messageBus.use(MetricsPlugin())
// Add retry logic
messageBus.use(RetryPlugin(maxAttempts: 3))
// Create custom plugins
struct CustomPlugin: MessageBusPlugin {
func willSend<T: Message>(_ message: T) async {
// Pre-processing logic
}
func didSend<T: Message>(_ message: T, result: Result<Any, Error>) async {
// Post-processing logic
}
}Benchmarked on M1 MacBook Pro:
| Metric | Value | Target |
|---|---|---|
| Throughput | 150K msgs/sec | 100K+ |
| P50 Latency | 0.2ms | <0.5ms |
| P99 Latency | 0.8ms | <1ms |
| Memory (1K subscribers) | 3.2MB | <5MB |
Run benchmarks yourself:
swift run -c release MessageBusBenchmarks- Architecture Guide - Deep dive into the framework design
- Plugin Development - Create custom plugins
- Performance Tuning - Optimization tips
- Migration Guide - Upgrading from other solutions
- API Documentation - Full API reference
The framework includes comprehensive testing utilities:
import SwiftMessageBusTestKit
class MyTests: XCTestCase {
func testMessageHandling() async {
let bus = TestMessageBus()
// Verify messages were sent
await bus.send(command)
XCTAssertEqual(bus.sentCommands.count, 1)
// Simulate responses
bus.simulateResponse(for: query, response: mockData)
}
}We welcome contributions! Please see our Contributing Guidelines for details.
Quick contribution checklist:
- Fork the repository
- Create a feature branch
- Write tests for your changes
- Ensure all tests pass
- Submit a pull request
- Core message bus implementation
- Layer-based routing
- Plugin system
- Swift Macros for reduced boilerplate (v1.1)
- Distributed messaging support (v1.2)
- Persistence plugins (v1.2)
- GraphQL subscription support (v1.3)
- WebSocket transport (v1.3)
SwiftMessageBus is released under the MIT License. See LICENSE for details.
- π Report bugs
- π‘ Request features
- π¬ Discussions
- π Wiki
Special thanks to all contributors and the Swift community for their feedback and support.
Made with β€οΈ by the Swift community