A flexible, agnostic event system for Ruby applications. EventSystem provides event-driven architecture with pluggable storage backends, visualization tools, and comprehensive logging. Perfect for building decoupled, maintainable applications.
- 🎯 Event-Driven Architecture: Clean separation of concerns through events
- đź’ľ Pluggable Storage: Memory, file, and extensible storage backends
- 📊 Visualization Tools: HTML timeline generation for debugging
- đź”§ Flexible Configuration: Easy setup and customization
- 🚀 High Performance: Optimized for both development and production
- 📝 Comprehensive Logging: Built-in logging with configurable levels
- 🔍 Event Querying: Filter and search events by type, time, and more
- 🎨 Modern API: Clean, intuitive Ruby API
Add this line to your application's Gemfile:
gem 'event_system'And then execute:
bundle installOr install it directly:
gem install event_systemrequire 'event_system'
# Create an event manager
manager = EventSystem.create_manager
# Create and publish an event
manager.publish_event(:user_created, self, { user_id: 123, name: "John Doe" })
# Subscribe to events
class UserNotifier
include EventSystem::EventSubscriber
def handle_event(event)
puts "User event: #{event.type} - #{event.data}"
end
end
notifier = UserNotifier.new
manager.subscribe(:user_created, notifier)# Configure with file storage
config = {
storage_type: :file,
storage_options: { directory: "logs/events" },
session_id: "my_app_session"
}
manager = EventSystem.create_manager(config)
# Or use memory storage for testing
manager = EventSystem.create_manager(storage_type: :memory)# Create an event manually
event = EventSystem.create_event(:order_placed, self, {
order_id: 456,
customer_id: 789,
amount: 99.99
})
# Publish the event
manager.publish(event)class OrderProcessor
include EventSystem::EventSubscriber
def handle_event(event)
case event.type
when 'order_placed'
process_order(event.data)
when 'payment_received'
fulfill_order(event.data)
end
end
private
def process_order(data)
puts "Processing order #{data[:order_id]}"
end
def fulfill_order(data)
puts "Fulfilling order #{data[:order_id]}"
end
end
# Subscribe to specific events
processor = OrderProcessor.new
manager.subscribe(:order_placed, processor)
manager.subscribe(:payment_received, processor)
# Subscribe to all events
manager.subscribe_all(processor)# Query events by type
orders = manager.query_events(type: 'order_placed')
# Query events by time range
recent_events = manager.query_events(
start_time: 1.hour.ago,
end_time: Time.now
)
# Query with limit
last_10_events = manager.query_events(limit: 10)
# Query from specific session
session_events = manager.query_events(session_id: 'session_123')# Perfect for testing and development
manager = EventSystem.create_manager(storage_type: :memory)
# Switch sessions
manager.switch_session('test_session_1')
manager.publish_event(:test_event, self, { data: 'test' })
# Create new session
new_session = manager.create_session('my_new_session')# Persistent storage to disk
config = {
storage_type: :file,
storage_options: { directory: 'event_logs' }
}
manager = EventSystem.create_manager(config)
# Events are automatically saved to JSONL files
manager.publish_event(:user_action, self, { action: 'login' })# Generate HTML timeline visualization
generator = EventSystem::Visualization::TimelineGenerator.new(manager.storage)
html_file = generator.generate_timeline('session_123', 'timeline.html')
# Get event summary
summary = generator.event_summary('session_123')
puts summary
# => {"user_created" => 5, "order_placed" => 3, "payment_received" => 2}
# Get timeline data for custom visualizations
timeline_data = generator.timeline_data('session_123')The gem includes a command-line tool for managing events:
# Generate timeline visualization
event_system visualize session_123 timeline.html
# Show statistics
event_system stats
# List available sessions
event_system list
# Query events
event_system query session_123 order_placed
# Use file storage
event_system -s file -d /path/to/logs visualize# Custom configuration
config = EventSystem::Configuration.new
config.storage_type = :file
config.storage_options = { directory: 'custom_logs' }
config.session_id = 'production_session'
config.auto_flush = true
# Custom logger
require 'logger'
config.logger = Logger.new('event_system.log')
manager = EventSystem.create_manager(config)# Subscribers with error handling
class SafeSubscriber
include EventSystem::EventSubscriber
def handle_event(event)
# Your event handling logic
process_event(event)
rescue => e
# Errors are automatically logged by the event manager
puts "Error processing event: #{e.message}"
end
endEventSystem.create_manager(config = nil)- Create a new event managerEventSystem.create_event(type, source = nil, data = {})- Create a new eventEventSystem.version- Get the current version
#publish(event)- Publish an event#publish_event(type, source = nil, data = {})- Create and publish an event#subscribe(event_type, subscriber)- Subscribe to specific event type#subscribe_all(subscriber)- Subscribe to all events#unsubscribe(event_type, subscriber)- Unsubscribe from event type#query_events(options = {})- Query events with filters#switch_session(session_id)- Switch to different session#create_session(session_id = nil)- Create new session#stats- Get system statistics#close- Close the event manager
#id- Unique event identifier#type- Event type#source- Event source#data- Event data#timestamp- Event timestamp#to_json- JSON representation#to_h- Hash representationEvent.from_json(json)- Create event from JSON
EventSystem::Storage::MemoryStore- In-memory storageEventSystem::Storage::FileStore- File-based storageEventSystem::Storage::Base- Abstract base class for custom storage
class WebApp
def initialize
@event_manager = EventSystem.create_manager(
storage_type: :file,
storage_options: { directory: 'logs/events' }
)
# Subscribe to web events
@event_manager.subscribe(:request_received, self)
@event_manager.subscribe(:response_sent, self)
end
def handle_request(request)
@event_manager.publish_event(:request_received, self, {
path: request.path,
method: request.method,
ip: request.ip
})
end
def handle_event(event)
# Log web events
puts "Web event: #{event.type} - #{event.data}"
end
endclass OrderService
def initialize
@event_manager = EventSystem.create_manager
@event_manager.subscribe(:payment_processed, self)
end
def place_order(order_data)
@event_manager.publish_event(:order_created, self, order_data)
end
def handle_event(event)
if event.type == 'payment_processed'
fulfill_order(event.data[:order_id])
end
end
endRSpec.describe OrderService do
let(:event_manager) { EventSystem.create_manager(storage_type: :memory) }
let(:service) { OrderService.new(event_manager) }
it 'publishes order created event' do
expect(event_manager).to receive(:publish_event).with(:order_created, service, anything)
service.place_order({ customer_id: 123 })
end
endAfter checking out the repo, run bin/setup to install dependencies. You can also run bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and the created tag, and push the .gem file to rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/davidslv/event_system.