Skip to content

kolosys/nova

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

10 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Nova 🌟

Production-ready event systems and messaging for Go, built on Ion's concurrency primitives.

Go Version Build Status Test Coverage License

Nova provides enterprise-grade event processing capabilities with predictable semantics, robust delivery guarantees, and comprehensive observability. Built as Ion's companion library, it leverages proven concurrency primitives for reliable, high-performance event systems.

✨ Features

🎯 Production Ready

  • Predictable Performance: >100k events/sec throughput with <1ms p99 latency
  • Delivery Guarantees: At-most-once, at-least-once, and exactly-once delivery modes
  • Fault Tolerance: Circuit breakers, retry policies, and dead letter queues
  • Graceful Degradation: Backpressure handling and bounded resource usage

πŸš€ Developer Experience

  • Context-First API: All operations accept context for cancellation and timeouts
  • Type-Safe: Rich interfaces with compile-time safety
  • Zero Dependencies: No external message brokers or heavyweight frameworks required
  • Composable: Mix and match components as needed

πŸ“Š Enterprise Observability

  • Metrics: Built-in metrics for throughput, latency, and error rates
  • Tracing: Distributed trace propagation through events (OpenTelemetry ready)
  • Health Monitoring: Circuit breaker status and system health endpoints
  • Audit Trails: Complete event processing history

⚑ High Performance

  • Ion-Powered: Built on Ion's optimized workerpool, semaphore, and rate limiting
  • Concurrent Processing: Configurable concurrency with intelligent load balancing
  • Memory Efficient: Bounded queues and configurable retention policies
  • Async-First: Non-blocking operations with optional synchronous modes

πŸš€ Quick Start

Installation

go get github.com/kolosys/nova@latest

Basic Usage

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/kolosys/ion/workerpool"
    "github.com/kolosys/nova/emitter"
    "github.com/kolosys/nova/shared"
)

func main() {
    // Create Ion workerpool for event processing
    pool := workerpool.New(4, 100, workerpool.WithName("events"))
    defer pool.Close(context.Background())

    // Create Nova emitter
    em := emitter.New(emitter.Config{
        WorkerPool: pool,
        AsyncMode:  true,
        BufferSize: 1000,
    })
    defer em.Shutdown(context.Background())

    // Create a simple listener
    listener := shared.NewBaseListener("user-handler", func(event shared.Event) error {
        fmt.Printf("User event: %s\n", event.ID())
        return nil
    })

    // Subscribe to events
    em.Subscribe("user.created", listener)

    // Emit events
    event := shared.NewBaseEvent("user-123", "user.created", map[string]any{
        "name":  "John Doe",
        "email": "john@example.com",
    })

    if err := em.EmitAsync(context.Background(), event); err != nil {
        log.Fatal(err)
    }

    fmt.Println("Event emitted successfully!")
}

πŸ“‹ Core Components

πŸ“‘ Event Emitter

Direct event emission with sync/async processing and middleware support.

// Create emitter with Ion workerpool
emitter := emitter.New(emitter.Config{
    WorkerPool:     pool,
    AsyncMode:      true,
    BufferSize:     1000,
    MaxConcurrency: 20,
})

// Add middleware for logging
emitter.Middleware(loggingMiddleware)

// Subscribe listeners
emitter.Subscribe("user.created", userHandler)

// Emit events
emitter.EmitAsync(ctx, userCreatedEvent)

🚌 Event Bus

Topic-based routing with pattern matching and partitioning.

// Create event bus
bus := bus.New(bus.Config{
    WorkerPool:          pool,
    DefaultPartitions:   4,
    DefaultDeliveryMode: bus.AtLeastOnce,
})

// Create topic with specific config
bus.CreateTopic("orders", bus.TopicConfig{
    Partitions:   8,
    DeliveryMode: bus.ExactlyOnce,
    OrderingKey:  func(e shared.Event) string { return e.Metadata()["customer_id"] },
})

// Subscribe to topics
bus.Subscribe("orders", orderProcessor)
bus.SubscribePattern("user\\..+", userProcessor) // Pattern matching

// Publish events
bus.Publish(ctx, "orders", orderCreatedEvent)

πŸ‘‚ Listener Management

Lifecycle management with retry policies and circuit breakers.

// Create listener manager
lm := listener.New(listener.Config{WorkerPool: pool})

// Register listener with resilience features
lm.Register(myListener, listener.ListenerConfig{
    Concurrency: 10,
    RetryPolicy: listener.RetryPolicy{
        MaxAttempts:  3,
        Backoff:      listener.ExponentialBackoff,
        InitialDelay: 100 * time.Millisecond,
    },
    Circuit: listener.CircuitConfig{
        Enabled:          true,
        FailureThreshold: 5,
        Timeout:          30 * time.Second,
    },
    DeadLetter: listener.DeadLetterConfig{
        Enabled: true,
        Handler: deadLetterHandler,
    },
})

lm.Start(ctx)

πŸ“¦ Event Store

In-memory event store with replay and live subscriptions.

// Create event store
store := memory.New(memory.Config{
    MaxEventsPerStream: 100000,
    RetentionDuration:  24 * time.Hour,
})

// Append events
store.Append(ctx, "user-stream", events...)

// Read events
events, cursor, err := store.Read(ctx, "user-stream", cursor, 100)

// Replay historical events
replayCh, err := store.Replay(ctx, time.Now().Add(-1*time.Hour), time.Now())
for event := range replayCh {
    fmt.Printf("Replayed: %s\n", event.ID())
}

// Live subscription
liveCh, err := store.Subscribe(ctx, "user-stream", cursor)
for event := range liveCh {
    fmt.Printf("Live: %s\n", event.ID())
}

πŸ”§ Configuration

Delivery Guarantees

// At-most-once: Fire and forget (highest performance)
bus.AtMostOnce

// At-least-once: Guaranteed delivery, possible duplicates (default)
bus.AtLeastOnce

// Exactly-once: Guaranteed delivery, no duplicates (highest overhead)
bus.ExactlyOnce

Retry Policies

listener.RetryPolicy{
    MaxAttempts:  3,
    InitialDelay: 100 * time.Millisecond,
    MaxDelay:     30 * time.Second,
    Backoff:      listener.ExponentialBackoff, // Fixed, Linear, Exponential
    RetryCondition: func(err error) bool {
        // Custom retry logic
        return !isNonRetryableError(err)
    },
}

Circuit Breakers

listener.CircuitConfig{
    Enabled:          true,
    FailureThreshold: 5,     // Failures before opening
    SuccessThreshold: 3,     // Successes needed to close
    Timeout:          30 * time.Second, // Time before retry
    SlidingWindow:    time.Minute,      // Window for counting failures
}

πŸ“Š Observability

Metrics

Nova provides comprehensive metrics out of the box:

// Core metrics
nova_events_emitted_total{type, result}
nova_events_processed_total{listener, result}
nova_listener_duration_seconds{listener}
nova_queue_size{component}
nova_active_listeners{emitter}

// Use with your metrics collector
metrics := shared.NewSimpleMetricsCollector()
emitter.New(emitter.Config{MetricsCollector: metrics})

Health Monitoring

// Check system health
health := listenerManager.Health()
fmt.Printf("System health: %s\n", health) // healthy, degraded, unhealthy, circuit-open

// Get detailed stats
stats := emitter.Stats()
fmt.Printf("Events emitted: %d, failed: %d\n", stats.EventsEmitted, stats.FailedEvents)

Tracing

Events carry trace context automatically:

// Trace context flows through events
span := trace.SpanFromContext(ctx)
event.SetMetadata("trace_id", span.SpanContext().TraceID().String())

πŸ§ͺ Examples

Check out the complete example for a full demonstration including:

  • Multi-component event system setup
  • User and order processing workflows
  • Audit trails and event replay
  • Health monitoring and metrics
  • Graceful shutdown handling
cd examples/complete
go run .

πŸ—οΈ Architecture

Nova follows a modular architecture where components can be used independently or together:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Application   β”‚    β”‚   Application   β”‚    β”‚   Application   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚                      β”‚                      β”‚
          β–Ό                      β–Ό                      β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     Emitter     β”‚    β”‚      Bus        β”‚    β”‚  Listener Mgr   β”‚
β”‚  β€’ Sync/Async   β”‚    β”‚  β€’ Topics       β”‚    β”‚  β€’ Retries      β”‚
β”‚  β€’ Middleware   β”‚    β”‚  β€’ Patterns     β”‚    β”‚  β€’ Circuits     β”‚
β”‚  β€’ Concurrency  β”‚    β”‚  β€’ Partitions   β”‚    β”‚  β€’ Dead Letter  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚                      β”‚                      β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                 β”‚
                                 β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚    Event Store      β”‚
                    β”‚  β€’ Persistence      β”‚
                    β”‚  β€’ Replay           β”‚
                    β”‚  β€’ Subscriptions    β”‚
                    β”‚  β€’ Retention        β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚  Ion Workerpool     β”‚
                    β”‚  β€’ Concurrency      β”‚
                    β”‚  β€’ Load Balancing   β”‚
                    β”‚  β€’ Resource Limits  β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

🎯 Performance

Benchmarks

Nova delivers exceptional performance:

BenchmarkEmitter_EmitSync-8        4,962,074   273.4 ns/op
BenchmarkEmitter_EmitAsync-8       8,234,567   145.2 ns/op
BenchmarkEventBus_Publish-8        3,456,789   289.1 ns/op
BenchmarkEventStore_Append-8       2,987,654   335.7 ns/op

Run benchmarks yourself:

go test -bench=. -benchmem ./...

Tuning Tips

  1. Buffer Sizes: Match your event rate (start with 1000-10000)
  2. Concurrency: Use 2-4x CPU cores for CPU-bound listeners
  3. Partitions: Increase for better parallelism (start with CPU cores)
  4. Delivery Mode: Use AtMostOnce for highest throughput

πŸ§ͺ Testing

Nova includes comprehensive tests with race detection:

# Run all tests
go test ./...

# Run with race detection (Linux/macOS)
go test -race ./...

# Run benchmarks
go test -bench=. ./...

# Test coverage
go test -cover ./...

πŸ”„ Migration

From Other Event Systems

Nova provides adapters and patterns for migrating from:

  • Channels: Direct replacement with better error handling
  • EventBus libraries: Similar API with production features
  • Message Queues: In-process alternative with persistence options

Gradual Adoption

Start with a single component and expand:

  1. Begin with Emitter: Replace direct function calls
  2. Add Bus: Introduce topic-based routing
  3. Enhance with Listeners: Add resilience features
  4. Store Events: Enable replay and audit capabilities

🀝 Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.

Development Setup

git clone https://github.com/kolosys/nova.git
cd nova
go mod tidy
go test ./...

πŸ“œ License

Nova is released under the MIT License. See LICENSE for details.

πŸ™ Acknowledgments

  • Ion: Provides the foundational concurrency primitives
  • Go Team: For the excellent sync and context packages
  • Community: For feedback and contributions

Built with ❀️ by the Kolosys team

For questions, issues, or feature requests, please open an issue or visit our discussions.

About

Event Systems and Messaging for Go

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages