0.0
No release in over 3 years
Event-driven architecture with pluggable storage backends, visualization tools, and comprehensive logging. Perfect for building decoupled, maintainable applications.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Development

~> 1.0
~> 4.0
~> 3.0
~> 1.0
~> 0.21
~> 0.9

Runtime

~> 2.0
 Project Readme

EventSystem

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.

Features

  • 🎯 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

Installation

Add this line to your application's Gemfile:

gem 'event_system'

And then execute:

bundle install

Or install it directly:

gem install event_system

Quick Start

Basic Usage

require '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)

Configuration

# 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)

Usage

Creating Events

# 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)

Event Subscribers

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)

Event Querying

# 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')

Storage Backends

Memory Storage (Default)

# 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')

File Storage

# 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' })

Visualization

# 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')

CLI Tool

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

Advanced Configuration

# 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)

Error Handling

# 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
end

API Reference

EventSystem Module

  • EventSystem.create_manager(config = nil) - Create a new event manager
  • EventSystem.create_event(type, source = nil, data = {}) - Create a new event
  • EventSystem.version - Get the current version

EventManager Class

  • #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

Event Class

  • #id - Unique event identifier
  • #type - Event type
  • #source - Event source
  • #data - Event data
  • #timestamp - Event timestamp
  • #to_json - JSON representation
  • #to_h - Hash representation
  • Event.from_json(json) - Create event from JSON

Storage Backends

  • EventSystem::Storage::MemoryStore - In-memory storage
  • EventSystem::Storage::FileStore - File-based storage
  • EventSystem::Storage::Base - Abstract base class for custom storage

Examples

Web Application

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
end

Microservice Communication

class 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
end

Testing

RSpec.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
end

Development

After 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.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/davidslv/event_system.