### Complete KartaAdapter Setup Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/configuration.md A full example demonstrating adapter initialization, callback registration, and event emission. ```go package main import ( "fmt" "time" "github.com/shengyanli1982/events" karta "github.com/shengyanli1982/events/contrib/karta" ) type myCallback struct{} func (c *myCallback) OnBefore(msg any) { fmt.Println("Task starting...") } func (c *myCallback) OnAfter(msg, result any, err error) { if err != nil { fmt.Printf("Task failed: %v\n", err) } else { fmt.Printf("Task succeeded: %v\n", result) } } func main() { // Configure adapter with 4 workers and a callback scheduler := karta.NewSimpleScheduler(256) adapter := karta.NewKartaAdapter(nil, scheduler, karta.WithWorkers(4), karta.WithCallback(&myCallback{}), ) // Create and configure emitter ee := events.NewEventEmitter(adapter) adapter.SetEventEmitter(ee) // Register handler ee.RegisterWithTopic("process", func(msg any) (any, error) { return fmt.Sprintf("Processed: %v", msg), nil }) // Emit _ = ee.EmitWithTopic("process", "data") time.Sleep(500 * time.Millisecond) ee.Stop() } ``` -------------------------------- ### Initialize KartaAdapter with Options Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/karta-adapter.md Example of initializing the adapter with multiple configuration options. ```go adapter := karta.NewKartaAdapter(nil, scheduler, karta.WithWorkers(8), karta.WithCallback(cb), ) ``` -------------------------------- ### Install Events Library Source: https://github.com/shengyanli1982/events/blob/main/README.md Commands to install the core events library and the karta adapter dependency. ```bash go get github.com/shengyanli1982/events go get github.com/shengyanli1982/events/contrib/karta ``` -------------------------------- ### Install Library Dependencies Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/README.md Commands to install the core library and optional contrib packages. ```bash go get github.com/shengyanli1982/events go get github.com/shengyanli1982/events/contrib/karta # Optional adapter go get github.com/shengyanli1982/events/contrib/lazy # Optional shortcut ``` -------------------------------- ### Callback Implementation Example Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/karta-adapter.md Demonstrates a custom implementation of the Callback interface and its registration with the Karta adapter. ```go type logCallback struct{} func (l *logCallback) OnBefore(msg any) { fmt.Printf("Task starting: %v\n", msg) } func (l *logCallback) OnAfter(msg, result any, err error) { if err != nil { fmt.Printf("Task failed: %v, error: %v\n", msg, err) } else { fmt.Printf("Task completed: %v -> %v\n", msg, result) } } adapter := karta.NewKartaAdapter(nil, scheduler, karta.WithCallback(&logCallback{})) ``` -------------------------------- ### Create and Configure Emitter Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/INDEX.md Demonstrates manual setup with a scheduler and adapter, or a simplified lazy initialization. ```go // Manual setup (explicit control) scheduler := karta.NewSimpleScheduler(512) adapter := karta.NewKartaAdapter(nil, scheduler, karta.WithWorkers(4)) ee := events.NewEventEmitter(adapter) adapter.SetEventEmitter(ee) // Lazy setup (one-liner) ee := lazy.NewSimpleEventEmitter(4, nil, nil) ``` -------------------------------- ### Initialize and Use EventEmitter Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/README.md Demonstrates basic setup of the KartaAdapter and EventEmitter, including topic registration and event emission. ```go adapter := karta.NewKartaAdapter(nil, karta.NewSimpleScheduler(256)) ee := events.NewEventEmitter(adapter) adapter.SetEventEmitter(ee) ee.RegisterWithTopic("msg", func(msg any) (any, error) { fmt.Printf("Received: %v\n", msg) return msg, nil }) _ = ee.EmitWithTopic("msg", "Hello") time.Sleep(100 * time.Millisecond) ee.Stop() ``` -------------------------------- ### Initialization Decision Tree Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/configuration.md Visual guide for selecting between simple one-line initialization and manual configuration. ```text Do you want one-line initialization? ├─ Yes, and 256-task buffer is OK │ └─ Use lazy.NewSimpleEventEmitter └─ No, or you need custom buffer/scheduler └─ Use manual setup with karta.NewKartaAdapter ├─ Configure workers with WithWorkers └─ Configure callback with WithCallback ``` -------------------------------- ### Configure LazyEmitter Instances Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/configuration.md Examples of initializing the emitter with varying worker counts, handlers, and callbacks. ```go // Simple: 4 workers, no callback, handler provided ee := lazy.NewSimpleEventEmitter(4, func(msg any) (any, error) { fmt.Printf("Received: %v\n", msg) return msg, nil }, nil) // Custom workload: 2 workers, with callback ee = lazy.NewSimpleEventEmitter(2, func(msg any) (any, error) { return msg, nil }, &myCallback{}) // No default handler ee = lazy.NewSimpleEventEmitter(8, nil, nil) ee.RegisterWithTopic("custom", customHandler) ``` -------------------------------- ### Manage Event Lifecycle Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/event.md Example of returning an event to the pool after processing. ```go event := ee.eventPool.Get() // Simplified illustration result, err := ee.DispatchEvent(event) // ... handle result/error ... ee.RecycleEvent(event) // Always return to pool ``` -------------------------------- ### Initialize SimpleEventEmitter via Manual Setup Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/lazy-emitter.md Demonstrates the two-phase initialization pattern that the lazy factory function wraps internally. ```go func NewSimpleEventEmitter(count int, handleFunc events.MessageHandleFunc, cb karta.Callback) *events.EventEmitter { var opts []karta.KartaOption if count > 0 { opts = append(opts, karta.WithWorkers(count)) } if cb != nil { opts = append(opts, karta.WithCallback(cb)) } // Phase 1: Create adapter with nil emitter adapter := karta.NewKartaAdapter(nil, karta.NewSimpleScheduler(256), opts...) // Phase 2: Create emitter and inject back ee := events.NewEventEmitter(adapter) adapter.SetEventEmitter(ee) // Phase 3: Register default handler if provided if handleFunc != nil { ee.Register(handleFunc) } return ee } ``` -------------------------------- ### Handle ErrTopicExecutedOnce Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/types.md Example showing the behavior when emitting multiple times to a topic registered with once semantics. ```go ee.RegisterOnceWithTopic("init", handler) _ = ee.EmitWithTopic("init", "first") // OK _ = ee.EmitWithTopic("init", "second") // Returns ErrTopicExecutedOnce ``` -------------------------------- ### Lazy Event Emitter Initialization Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/GUIDE.md Use this approach for quick setup when the default 256-task buffer size is sufficient for the application requirements. ```go ee := lazy.NewSimpleEventEmitter(8, nil, &myCallback{}) // Buffer size always 256, but good for most use cases ``` -------------------------------- ### Initialize Lazy Emitter with Default Handler Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/lazy-emitter.md Demonstrates basic setup using a default handler to process emitted messages. ```go package main import ( "fmt" "time" "github.com/shengyanli1982/events" "github.com/shengyanli1982/events/contrib/lazy" ) func defaultHandler(msg any) (any, error) { fmt.Printf("[Default] %v\n", msg) return msg, nil } func main() { ee := lazy.NewSimpleEventEmitter(4, events.MessageHandleFunc(defaultHandler), nil) _ = ee.Emit("Hello!") _ = ee.Emit("World!") time.Sleep(500 * time.Millisecond) ee.Stop() } ``` -------------------------------- ### Handle ErrTopicNotExists Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/errors.md Example of checking for ErrTopicNotExists and registering a handler dynamically. ```go if err := ee.EmitWithTopic("order", data); err != nil { if errors.Is(err, events.ErrTopicNotExists) { log.Printf("Topic 'order' not registered. Registering handler...") ee.RegisterWithTopic("order", orderHandler) // Try again _ = ee.EmitWithTopic("order", data) } else { log.Printf("Emit error: %v", err) } } ``` -------------------------------- ### Emit Events Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/INDEX.md Examples of immediate, default, and delayed event emission, including basic error handling. ```go // Immediate emit _ = ee.EmitWithTopic("order", orderData) // Default topic _ = ee.Emit(message) // Delayed emit _ = ee.EmitAfterWithTopic("reminder", msg, 5*time.Second) // Error handling if err := ee.Emit(msg); err != nil { log.Printf("Emit failed: %v", err) } ``` -------------------------------- ### Handle ErrTopicNotOnce Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/types.md Example showing the error returned when calling ResetOnceWithTopic on a standard registration. ```go ee.RegisterWithTopic("task", handler) // Normal registration if err := ee.ResetOnceWithTopic("task"); err != nil { // err == ErrTopicNotOnce } ``` -------------------------------- ### Tune Worker and Buffer Balance Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/configuration.md Examples of balancing scheduler buffer sizes with worker counts to manage latency and CPU contention. ```go // Too few workers + large buffer = high latency adapter1 := karta.NewKartaAdapter(nil, karta.NewSimpleScheduler(2048), karta.WithWorkers(2)) // Too many workers + small buffer = CPU contention adapter2 := karta.NewKartaAdapter(nil, karta.NewSimpleScheduler(64), karta.WithWorkers(32)) // Balanced for moderate load adapter3 := karta.NewKartaAdapter(nil, karta.NewSimpleScheduler(512), karta.WithWorkers(8)) ``` -------------------------------- ### Handle ErrEmitterStopped Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/types.md Example showing the error returned when emitting after calling Stop(). ```go ee.Stop() if err := ee.Emit(msg); err != nil { // err == ErrEmitterStopped } ``` -------------------------------- ### Handle ErrTopicNotOnce Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/errors.md Example of checking for ErrTopicNotOnce using errors.Is to handle reset attempts on non-once topics. ```go ee.RegisterWithTopic("task", taskHandler) // Normal registration (not once) if err := ee.ResetOnceWithTopic("task"); err != nil { if errors.Is(err, events.ErrTopicNotOnce) { log.Println("'task' was not registered as once semantics. No reset needed.") // If the topic shouldn't fire multiple times, consider: // - Unregister and re-register the handler, or // - Use RegisterOnceWithTopic instead } else if errors.Is(err, events.ErrTopicNotExists) { log.Println("Topic does not exist.") } } ``` -------------------------------- ### Get Event Data Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/event.md Retrieve the payload from an event. ```go func (e *Event) GetData() any ``` ```go data := event.GetData() order := data.(Order) ``` -------------------------------- ### Initialize KartaAdapter Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/karta-adapter.md Demonstrates the constructor signature for creating a new KartaAdapter instance. ```go func NewKartaAdapter(ee *events.EventEmitter, sched karta.Scheduler, opts ...KartaOption) *KartaAdapter ``` -------------------------------- ### Get Event Topic Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/event.md Retrieve the topic identifier from an event. ```go func (e *Event) GetTopic() string ``` ```go topic := event.GetTopic() fmt.Printf("Topic: %s\n", topic) ``` -------------------------------- ### Configure Event Emitter Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/README.md Demonstrates setting up workers, callbacks, and the scheduler buffer size. ```go // Workers: number of concurrent task processors karta.WithWorkers(8) // Callback: observe task lifecycle karta.WithCallback(&myCallback{}) // Scheduler: task queue configuration karta.NewSimpleScheduler(256) // 256-task buffer // Lazy factory: one-liner lazy.NewSimpleEventEmitter(workers, handleFunc, callback) ``` -------------------------------- ### Two-Phase Initialization with Karta Adapter Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/INDEX.md Use this pattern for explicit control over adapter and emitter lifecycle. Requires manual injection of the emitter into the adapter. ```go import ( "github.com/shengyanli1982/events" karta "github.com/shengyanli1982/events/contrib/karta" ) // Phase 1: Create adapter with nil emitter adapter := karta.NewKartaAdapter(nil, karta.NewSimpleScheduler(256)) // Phase 2: Create emitter and inject back into adapter ee := events.NewEventEmitter(adapter) adapter.SetEventEmitter(ee) // Register and use ee.RegisterWithTopic("order", func(msg any) (any, error) { fmt.Printf("Order: %v\n", msg) return msg, nil }) _ = ee.EmitWithTopic("order", "Order #123") // ... wait for async execution ... ee.Stop() ``` -------------------------------- ### Manual Event Emitter Initialization Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/GUIDE.md Use this approach for advanced configurations requiring custom buffer sizes, specific scheduler types, or explicit two-phase control. ```go scheduler := karta.NewSimpleScheduler(512) adapter := karta.NewKartaAdapter(nil, scheduler, karta.WithWorkers(8), karta.WithCallback(&myCallback{}), ) ee := events.NewEventEmitter(adapter) adapter.SetEventEmitter(ee) ``` -------------------------------- ### Manual vs Lazy EventEmitter Initialization Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/lazy-emitter.md Compares the verbose manual two-phase initialization process with the simplified one-line lazy factory approach. ```go adapter := karta.NewKartaAdapter(nil, karta.NewSimpleScheduler(256), karta.WithWorkers(4)) ee := events.NewEventEmitter(adapter) adapter.SetEventEmitter(ee) if handleFunc != nil { ee.Register(handleFunc) } ``` ```go ee := lazy.NewSimpleEventEmitter(4, handleFunc, nil) ``` -------------------------------- ### Initialize KartaAdapter with Direct Pattern Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/karta-adapter.md Use this pattern to initialize the adapter with a fully configured event emitter and functional options. ```go ee := events.NewEventEmitter(nil) adapter := karta.NewKartaAdapter(ee, karta.NewSimpleScheduler(256), karta.WithWorkers(4), karta.WithCallback(&myCallback{}), ) ``` -------------------------------- ### Prevent ErrInvalidMessage in Custom Pipeline Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/errors.md Example of type assertion to ensure messages are of type *Event before submission. ```go // When implementing the Pipeline interface: type CustomPipeline struct { ee *events.EventEmitter } func (p *CustomPipeline) SubmitWithFunc(fn events.MessageHandleFunc, msg any) error { // Ensure msg is an *Event event, ok := msg.(*events.Event) if !ok { return errors.New("message must be *Event") } // Submit handler that expects *Event return p.submit(fn, event) } ``` -------------------------------- ### Configure KartaAdapter with Callbacks Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/README.md Shows how to implement and register a callback structure to hook into event lifecycle events. ```go type logCB struct{} func (c *logCB) OnBefore(msg any) { fmt.Println("Starting") } func (c *logCB) OnAfter(msg, result any, err error) { if err != nil { fmt.Printf("Error: %v\n", err) } } adapter := karta.NewKartaAdapter(nil, scheduler, karta.WithCallback(&logCB{})) ``` -------------------------------- ### Handle ErrEventNil in Custom Pipeline Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/errors.md Example of validating event pointers within a custom pipeline handler. ```go // In a custom pipeline adapter's handler func customHandler(msg any) (any, error) { event, ok := msg.(*events.Event) if event == nil || !ok { return nil, events.ErrEventNil } // ... proceed ... } ``` -------------------------------- ### Initialize Karta Adapter with SimpleScheduler Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/karta-adapter.md Creates a new scheduler instance with a defined buffer size and initializes the Karta adapter. ```go scheduler := karta.NewSimpleScheduler(256) // 256-task buffer adapter := karta.NewKartaAdapter(nil, scheduler) ``` -------------------------------- ### Initialize KartaAdapter with Two-Phase Pattern Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/karta-adapter.md Use this pattern when the event emitter is not available at the time of adapter creation. ```go adapter := karta.NewKartaAdapter(nil, karta.NewSimpleScheduler(256)) ee := events.NewEventEmitter(adapter) adapter.SetEventEmitter(ee) // Inject emitter after creation ``` -------------------------------- ### Configure Karta Adapter Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/INDEX.md Initialize the adapter using functional options to set worker counts and lifecycle callbacks. ```go adapter := karta.NewKartaAdapter(nil, scheduler, karta.WithWorkers(8), // 8 concurrent workers karta.WithCallback(&myCallback), // Attach lifecycle callback ) ``` -------------------------------- ### Emit and Reset Once Topics Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/GUIDE.md Demonstrates the execution flow of once-only topics and how to reset them. ```go _ = ee.EmitWithTopic("setup", "v1") // once.Do() → executes _ = ee.EmitWithTopic("setup", "v2") // once.Do() → no-op, returns ErrTopicExecutedOnce _ = ee.ResetOnceWithTopic("setup") // New sync.Once created _ = ee.EmitWithTopic("setup", "v3") // New once.Do() → executes ``` -------------------------------- ### Initialize and Use EventEmitter Source: https://github.com/shengyanli1982/events/blob/main/README.md Demonstrates the two-phase initialization pattern required to resolve circular dependencies between the emitter and the pipeline adapter. ```go package main import ( "fmt" "time" "github.com/shengyanli1982/events" karta "github.com/shengyanli1982/events/contrib/karta" ) func handleOrder(msg any) (any, error) { fmt.Printf("[Order] %v\n", msg) return msg, nil } func main() { // Phase 1: Create adapter with nil emitter adapter := karta.NewKartaAdapter(nil, karta.NewSimpleScheduler(256)) // Phase 2: Create emitter, then inject it back into adapter ee := events.NewEventEmitter(adapter) adapter.SetEventEmitter(ee) ee.RegisterWithTopic("order", handleOrder) for i := range 5 { _ = ee.EmitWithTopic("order", fmt.Sprintf("order-%d", i)) } time.Sleep(500 * time.Millisecond) ee.Stop() } ``` -------------------------------- ### Register Event Handlers Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/INDEX.md Shows how to register handlers for specific topics, the default topic, or one-shot execution. ```go // Register on a topic ee.RegisterWithTopic("order", orderHandler) // Register on default topic ee.Register(defaultHandler) // Register one-shot ee.RegisterOnceWithTopic("init", initHandler) ``` -------------------------------- ### Manage Emitter Lifecycle Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/errors.md Demonstrates graceful shutdown and the subsequent error state when emitting after stopping. ```go ee := events.NewEventEmitter(adapter) // ... register handlers and emit events ... // Graceful shutdown if err := ee.Emit("shutdown signal"); err == nil { time.Sleep(500 * time.Millisecond) // Wait for in-flight tasks } ee.Stop() // From here on, all Emit calls fail with ErrEmitterStopped if err := ee.Emit("too late"); err == events.ErrEmitterStopped { fmt.Println("Cannot emit after stop") } ``` -------------------------------- ### Configure Karta Adapter with Callbacks Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/README.md Implement the callback interface to hook into task lifecycle events. Pass these to the KartaAdapter during initialization. ```go type myCallback struct{} func (c *myCallback) OnBefore(msg any) { fmt.Println("Task starting") } func (c *myCallback) OnAfter(msg, result any, err error) { if err != nil { fmt.Printf("Task failed: %v\n", err) } } adapter := karta.NewKartaAdapter(nil, scheduler, karta.WithWorkers(4), karta.WithCallback(&myCallback{}), ) ``` -------------------------------- ### Initialize Emitter with Lazy Shortcut Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/README.md A simplified initialization method for creating an event emitter. ```go ee := lazy.NewSimpleEventEmitter(4, nil, nil) ``` -------------------------------- ### Initialize Emitter with Two-Phase Pattern Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/README.md Use this pattern to resolve circular dependencies between the adapter and the emitter. ```go // Phase 1: Create adapter with nil emitter adapter := karta.NewKartaAdapter(nil, karta.NewSimpleScheduler(256)) // Phase 2: Create emitter and inject back ee := events.NewEventEmitter(adapter) adapter.SetEventEmitter(ee) // Now ready to use ee.RegisterWithTopic("order", handler) _ = ee.EmitWithTopic("order", data) ``` -------------------------------- ### One-Shot Initialization Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/GUIDE.md Registers a handler that executes only once for a specific topic. ```go ee.RegisterOnceWithTopic("db.init", initDatabase) _ = ee.EmitWithTopic("db.init", connStr) // Handler runs, subsequent emissions fail with ErrTopicExecutedOnce ``` -------------------------------- ### Handle ErrTopicExecutedOnce Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/errors.md Demonstrates how to handle the execution error and reset the topic state. ```go ee.RegisterOnceWithTopic("init", initHandler) if err := ee.EmitWithTopic("init", "config.v1"); err != nil { if errors.Is(err, events.ErrTopicExecutedOnce) { log.Println("Initialization already completed. To re-initialize, call ResetOnceWithTopic.") // Option 1: Reset if needed _ = ee.ResetOnceWithTopic("init") _ = ee.EmitWithTopic("init", "config.v2") // Option 2: Check before emitting } else { log.Printf("Emit error: %v", err) } } ``` -------------------------------- ### Workflow for Once-Executed Topics Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/errors.md A typical workflow showing registration, failure on second emission, and resetting the state. ```go // Register a one-time initialization handler ee.RegisterOnceWithTopic("database", initDatabase) // First emission succeeds _ = ee.EmitWithTopic("database", "postgres://localhost") // Handler runs // Second emission fails if err := ee.EmitWithTopic("database", "postgres://newhost"); err == events.ErrTopicExecutedOnce { fmt.Println("Database already initialized") } // To reinitialize, reset first _ = ee.ResetOnceWithTopic("database") _ = ee.EmitWithTopic("database", "postgres://newhost") // Handler runs again ``` -------------------------------- ### Register and emit a message handler Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/types.md Demonstrates registering a handler function for a specific topic and emitting a message to it. ```go handler := func(msg any) (any, error) { data := msg.(string) return strings.ToUpper(data), nil } ee.RegisterWithTopic("uppercase", handler) _ = ee.EmitWithTopic("uppercase", "hello") // Handler receives "hello" ``` -------------------------------- ### Initialize SimpleScheduler Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/configuration.md Creates a new scheduler instance with a specified task buffer size. ```go func NewSimpleScheduler(bufferSize int) *karta.SimpleScheduler ``` -------------------------------- ### One-Phase Initialization with Lazy Emitter Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/INDEX.md Use this factory method for simplified, one-line initialization of the event emitter. ```go import "github.com/shengyanli1982/events/contrib/lazy" ee := lazy.NewSimpleEventEmitter(4, nil, nil) ee.RegisterWithTopic("task", handleTask) _ = ee.EmitWithTopic("task", "data") // ... ee.Stop() ``` -------------------------------- ### Implement KartaAdapter Callback Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/configuration.md Defines the interface and implementation for observing task execution events. OnAfter is guaranteed to execute even if the handler panics. ```go func WithCallback(cb Callback) KartaOption ``` ```go type Callback interface { OnBefore(msg any) OnAfter(msg, result any, err error) } ``` ```go type logCallback struct { startTime map[string]time.Time } func (l *logCallback) OnBefore(msg any) { event := msg.(*events.Event) fmt.Printf("Starting task on topic: %s\n", event.GetTopic()) } func (l *logCallback) OnAfter(msg, result any, err error) { event := msg.(*events.Event) if err != nil { fmt.Printf("Task failed on topic %s: %v\n", event.GetTopic(), err) } else { fmt.Printf("Task succeeded on topic %s: %v\n", event.GetTopic(), result) } } adapter := karta.NewKartaAdapter(nil, scheduler, karta.WithCallback(&logCallback{})) ``` -------------------------------- ### Create New Event Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/event.md Instantiate a new event object. ```go func NewEvent() *Event ``` ```go event := events.NewEvent() event.SetTopic("order") event.SetData(Order{ID: 123}) ``` -------------------------------- ### Manage Event Lifecycle with Pooling Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/GUIDE.md Demonstrates the internal flow of acquiring an event from the pool, submitting it, and recycling it after completion. ```go // Internal pool (user doesn't create this) type eventPool struct { pool *sync.Pool } // When emitting: event := ee.eventPool.Get() // Get or allocate event.SetTopic(topic) event.SetData(msg) ee.pipeline.Submit(wrapFn, event) // After handler completes: ee.RecycleEvent(event) // Return to pool ``` -------------------------------- ### View Documentation File Structure Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/README.md The project documentation is organized into modular files covering architecture, types, errors, and API references. ```text /output/ ├── README.md (this file) ├── INDEX.md (start here) ├── GUIDE.md (architecture & implementation) ├── types.md (all types, interfaces, errors) ├── errors.md (error handling reference) ├── configuration.md (tuning & configuration) └── api-reference/ ├── event-emitter.md (EventEmitter methods) ├── event.md (Event type) ├── karta-adapter.md (KartaAdapter & callbacks) └── lazy-emitter.md (convenience factory) ``` -------------------------------- ### Initialize EventEmitter Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/event-emitter.md Create a new instance by providing an async pipeline implementation. ```go import ( "github.com/shengyanli1982/events" karta "github.com/shengyanli1982/events/contrib/karta" ) adapter := karta.NewKartaAdapter(nil, karta.NewSimpleScheduler(256)) ee := events.NewEventEmitter(adapter) adapter.SetEventEmitter(ee) ``` -------------------------------- ### Register and Emit Topic-Based Events Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/README.md Register handlers for specific topics and emit events asynchronously. Use HasTopic and Topics to inspect the current registry. ```go // Register a handler for a topic ee.RegisterWithTopic("order", func(msg any) (any, error) { return processOrder(msg), nil }) // Emit an event (async execution) _ = ee.EmitWithTopic("order", orderData) // Query registered topics if ee.HasTopic("order") { topics := ee.Topics() } ``` -------------------------------- ### Initialize EventEmitter with Two-Phase Pattern Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/GUIDE.md Manually configure the KartaAdapter and EventEmitter to resolve circular dependencies by injecting the emitter after creation. ```go // Before SetEventEmitter, the adapter's ee field is nil // DispatchEvent would panic if called adapter := karta.NewKartaAdapter(nil, scheduler) // Now create the emitter ee := events.NewEventEmitter(adapter) // Now it's safe for adapter to call ee.DispatchEvent adapter.SetEventEmitter(ee) ``` -------------------------------- ### SubmitWithFunc Method Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/types.md Submits a message for immediate asynchronous execution. ```go SubmitWithFunc(fn MessageHandleFunc, msg any) error ``` -------------------------------- ### NewKartaAdapter Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/karta-adapter.md Creates a new KartaAdapter instance configured with a scheduler and optional parameters. ```APIDOC ## NewKartaAdapter ### Description Creates a new KartaAdapter instance configured with a scheduler and optional parameters. It supports two-phase initialization if the event emitter is not immediately available. ### Signature `func NewKartaAdapter(ee *events.EventEmitter, sched karta.Scheduler, opts ...KartaOption) *KartaAdapter` ### Parameters - **ee** (*events.EventEmitter) - Optional - The event emitter instance. - **sched** (karta.Scheduler) - Required - The task scheduler instance. - **opts** (...KartaOption) - Optional - Variadic functional options such as WithWorkers or WithCallback. ### Returns - ***KartaAdapter** - A configured pipeline adapter instance. ### Example ```go ee := events.NewEventEmitter(nil) adapter := karta.NewKartaAdapter(ee, karta.NewSimpleScheduler(256), karta.WithWorkers(4), karta.WithCallback(&myCallback{}), ) ``` ``` -------------------------------- ### Configure Lifecycle Callback Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/karta-adapter.md Attaches a custom callback implementation to observe task execution events. ```go adapter := karta.NewKartaAdapter(nil, scheduler, karta.WithCallback(&logCallback{})) ``` -------------------------------- ### Initialize Karta Adapter with EventEmitter Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/GUIDE.md Ensure the adapter is linked to the event emitter using SetEventEmitter to avoid nil pointer panics during dispatch. ```go // ❌ Wrong: adapter.ee is nil, DispatchEvent will panic adapter := karta.NewKartaAdapter(nil, scheduler) ee := events.NewEventEmitter(adapter) _ = ee.Emit(msg) // Panic in adapter.DispatchEvent // ✅ Correct: adapter := karta.NewKartaAdapter(nil, scheduler) ee := events.NewEventEmitter(adapter) adapter.SetEventEmitter(ee) _ = ee.Emit(msg) // Works ``` -------------------------------- ### Observability via Callbacks Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/GUIDE.md Implements lifecycle hooks to track metrics before and after task execution. ```go type metricsCallback struct { metrics *MetricsCollector } func (m *metricsCallback) OnBefore(msg any) { m.metrics.IncrementTaskCount() } func (m *metricsCallback) OnAfter(msg, result any, err error) { if err != nil { m.metrics.IncrementErrorCount() } else { m.metrics.IncrementSuccessCount() } } adapter := karta.NewKartaAdapter(nil, scheduler, karta.WithCallback(&metricsCallback{metrics})) ``` -------------------------------- ### Handle Scheduler Backpressure Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/configuration.md Demonstrates how the scheduler behaves when the task buffer capacity is exceeded. ```go scheduler := karta.NewSimpleScheduler(10) // Small buffer for demo adapter := karta.NewKartaAdapter(nil, scheduler) ee := events.NewEventEmitter(adapter) // Fill the buffer for i := 0; i < 10; i++ { _ = ee.Emit(fmt.Sprintf("msg-%d", i)) } // This may fail with karta.ErrSchedulerFull if err := ee.Emit("msg-11"); err != nil { fmt.Printf("Backpressure: %v\n", err) } ``` -------------------------------- ### RegisterOnce Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/event-emitter.md Registers a one-shot handler on the default topic. ```APIDOC ## RegisterOnce ### Description Registers a one-shot handler on the default topic. Equivalent to `RegisterOnceWithTopic(DefaultTopicName, fn)`. ### Parameters - **fn** (MessageHandleFunc) - Required - The handler function. ``` -------------------------------- ### Initialize EventEmitter with Lazy Factory Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/GUIDE.md Use the lazy factory helper to automatically handle the two-phase initialization process in a single call. ```go // One-liner that does all three phases automatically ee := lazy.NewSimpleEventEmitter(4, handler, callback) ``` -------------------------------- ### Prevent ErrTopicNotOnce Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/errors.md Demonstrates proper registration of once versus normal topics to avoid triggering the error. ```go // Distinguish between once and normal registration at the call site ee.RegisterOnceWithTopic("connection_pool", initPool) // Once ee.RegisterWithTopic("request_handler", handleRequest) // Multiple // Later, reset only the once topic _ = ee.ResetOnceWithTopic("connection_pool") ``` -------------------------------- ### Register Multiple Topics for Lazy Emitter Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/lazy-emitter.md Shows how to route messages to specific handlers based on topics without a default handler. ```go ee := lazy.NewSimpleEventEmitter(4, nil, nil) // No default handler ee.RegisterWithTopic("order", func(msg any) (any, error) { fmt.Printf("[Order] %v\n", msg) return msg, nil }) ee.RegisterWithTopic("payment", func(msg any) (any, error) { fmt.Printf("[Payment] %v\n", msg) return msg, nil }) _ = ee.EmitWithTopic("order", "Order #1") _ = ee.EmitWithTopic("payment", "Payment #1") time.Sleep(500 * time.Millisecond) ee.Stop() ``` -------------------------------- ### RegisterOnceWithTopic Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/event-emitter.md Registers a one-shot handler that fires only on the first emission. ```APIDOC ## RegisterOnceWithTopic ### Description Registers a one-shot handler that fires only on the first emission. Subsequent emissions return `ErrTopicExecutedOnce`. Call `ResetOnceWithTopic` to re-enable. ### Parameters - **topic** (string) - Required - The topic identifier. - **fn** (MessageHandleFunc) - Required - The handler function. ``` -------------------------------- ### Define WithCallback Option Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/karta-adapter.md Function signature for attaching a lifecycle callback to the adapter. ```go func WithCallback(cb Callback) KartaOption ``` -------------------------------- ### RegisterOnceWithTopic Source: https://github.com/shengyanli1982/events/blob/main/README.md Registers a handler that fires only once for a specific topic. ```APIDOC ## RegisterOnceWithTopic(topic string, handler func) ### Description Registers a handler that fires only once for the specified topic. Subsequent emissions will return an error until ResetOnceWithTopic is called. ### Parameters - **topic** (string) - Required - The topic name to register the handler for. - **handler** (func) - Required - The function to execute upon emission. ``` -------------------------------- ### Initialize Lazy Event Emitter in Go Source: https://github.com/shengyanli1982/events/blob/main/README.md Uses the lazy package to create a simple event emitter with worker goroutines and a default handler. ```go package main import ( "fmt" "time" "github.com/shengyanli1982/events/contrib/lazy" ) func handleMsg(msg any) (any, error) { fmt.Println(msg) return msg, nil } func main() { ee := lazy.NewSimpleEventEmitter(4, handleMsg, nil) for i := range 5 { _ = ee.Emit(fmt.Sprint("msg-", i)) } time.Sleep(500 * time.Millisecond) ee.Stop() } ``` -------------------------------- ### Initialize EventEmitter from Configuration Struct Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/configuration.md Use this pattern to externalize configuration for larger applications. The factory function maps struct fields to Karta options. ```go type EmitterConfig struct { Workers int BufferSize int HasCallback bool } func NewEmitterFromConfig(cfg EmitterConfig) *events.EventEmitter { var opts []karta.KartaOption if cfg.Workers > 0 { opts = append(opts, karta.WithWorkers(cfg.Workers)) } if cfg.HasCallback { opts = append(opts, karta.WithCallback(&logCallback{})) } scheduler := karta.NewSimpleScheduler(cfg.BufferSize) adapter := karta.NewKartaAdapter(nil, scheduler, opts...) ee := events.NewEventEmitter(adapter) adapter.SetEventEmitter(ee) return ee } ``` -------------------------------- ### Use DefaultTopicName in emitter operations Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/types.md Demonstrates how the default topic is applied during registration, emission, and handler retrieval. ```go ee.Register(handler) // Registers on "default" topic _ = ee.Emit(msg) // Emits on "default" topic fn, _ := ee.GetMessageHandleFunc(events.DefaultTopicName) // Retrieves "default" handler ``` -------------------------------- ### Define ErrTopicExecutedOnce error Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/types.md Error returned when emitting to a 'once' topic that has already been triggered. ```go var ErrTopicExecutedOnce = errors.New("topic has been executed once") ``` -------------------------------- ### Implement Callback Hooks in Go Source: https://github.com/shengyanli1982/events/blob/main/README.md Defines a custom callback to observe task lifecycle events using the Karta adapter. ```go package main import ( "fmt" "github.com/shengyanli1982/events" karta "github.com/shengyanli1982/events/contrib/karta" ) type logCallback struct{} func (l *logCallback) OnBefore(msg any) { fmt.Printf("before: %v\n", msg) } func (l *logCallback) OnAfter(msg, result any, err error) { fmt.Printf("after: %v -> %v (err=%v)\n", msg, result, err) } func main() { adapter := karta.NewKartaAdapter(nil, karta.NewSimpleScheduler(256), karta.WithCallback(&logCallback{}), ) ee := events.NewEventEmitter(adapter) adapter.SetEventEmitter(ee) defer ee.Stop() } ``` -------------------------------- ### Project Directory Structure Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/MANIFEST.md Visual representation of the project's documentation file hierarchy. ```text /output/ ├── README.md ............................ Start here ├── INDEX.md ............................ API overview ├── GUIDE.md ............................ Architecture ├── MANIFEST.md (this file) .............. Documentation inventory │ ├── api-reference/ ....................... API signatures & examples │ ├── event-emitter.md ................ Core type (14 methods) │ ├── event.md ........................ Event type │ ├── karta-adapter.md ................ Pipeline adapter │ └── lazy-emitter.md ................. Convenience factory │ ├── types.md ............................ All types & interfaces ├── errors.md ........................... Error handling reference └── configuration.md .................... Configuration options ``` -------------------------------- ### List registered topics with Topics Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/event-emitter.md Retrieves all currently registered topic names as a slice. ```go for _, topic := range ee.Topics() { fmt.Printf("Registered topic: %s\n", topic) } ``` -------------------------------- ### Implement Backoff for Backpressure Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/configuration.md A pattern for handling scheduler full errors by retrying emission with exponential backoff. ```go func emitWithBackoff(ee *events.EventEmitter, topic string, msg any) error { backoff := time.Millisecond for { err := ee.EmitWithTopic(topic, msg) if err == nil { return nil } if !errors.Is(err, karta.ErrSchedulerFull) { return err // Non-backpressure error } if backoff > 100*time.Millisecond { return fmt.Errorf("backoff timeout: %v", err) } time.Sleep(backoff) backoff *= 2 } } ``` -------------------------------- ### Centralized Emit Wrapper in Go Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/errors.md Provides a safe wrapper for emitting events that checks emitter state and logs errors. ```go func safeEmit(ee *events.EventEmitter, topic string, msg any) error { if ee == nil || ee.IsStopped() { return events.ErrEmitterStopped } err := ee.EmitWithTopic(topic, msg) if err != nil { log.Printf("Failed to emit on topic '%s': %v", topic, err) } return err } ``` -------------------------------- ### Set Event Topic Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/event.md Assign a topic identifier to an event. ```go func (e *Event) SetTopic(topic string) ``` ```go event.SetTopic("order") ``` -------------------------------- ### Default Topic Usage Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/GUIDE.md Registers a handler for the default topic and emits events without specifying a topic. ```go ee.Register(defaultHandler) _ = ee.Emit(msg) // Uses default topic ``` -------------------------------- ### ResetOnce Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/event-emitter.md Re-enables a one-shot handler on the default topic. ```APIDOC ## ResetOnce ### Description Re-enables a one-shot handler on the default topic. Equivalent to `ResetOnceWithTopic(DefaultTopicName)`. ### Signature `func (ee *EventEmitter) ResetOnce() error` ### Returns - **error** - Same error cases as `ResetOnceWithTopic`. ``` -------------------------------- ### Handle Immediate Emission Errors Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/GUIDE.md Identify common errors returned during the synchronous emission phase, such as topic registration issues or buffer saturation. ```go if err := ee.Emit(msg); err != nil { // ErrTopicNotExists: topic not registered // ErrEmitterStopped: emitter is stopped // ErrTopicExecutedOnce: once handler already fired // karta.ErrSchedulerFull: pipeline buffer full } ``` -------------------------------- ### SubmitAfterWithFunc Method Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/types.md Submits a message for delayed asynchronous execution. ```go SubmitAfterWithFunc(fn MessageHandleFunc, msg any, delay time.Duration) error ``` -------------------------------- ### Overwrite event handlers Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/GUIDE.md Demonstrates that registering a new handler for an existing topic replaces the previous one. ```go ee.RegisterWithTopic("task", handler1) // Registry: {"task": handler1} ee.RegisterWithTopic("task", handler2) // Registry: {"task": handler2} ← handler1 replaced _ = ee.EmitWithTopic("task", data) // Executes handler2 ``` -------------------------------- ### Callback Interface Definition Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/karta-adapter.md Defines the required methods for observing task lifecycle events. ```go type Callback interface { OnBefore(msg any) OnAfter(msg, result any, err error) } ``` -------------------------------- ### Emit an event with a delay on the default topic Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/event-emitter.md Schedules an event to be emitted after a specified duration on the default topic. ```go _ = ee.EmitAfter("Delayed message", 500*time.Millisecond) ``` -------------------------------- ### Handle KartaAdapter Scheduler Full Error in Go Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/errors.md Implements a retry loop with backoff when encountering karta.ErrSchedulerFull during event emission. ```go retries := 0 maxRetries := 3 backoff := 10 * time.Millisecond for { if err := ee.EmitWithTopic("order", data); err == nil { break } else if errors.Is(err, karta.ErrSchedulerFull) && retries < maxRetries { log.Printf("Scheduler full, retrying... (attempt %d/%d)", retries+1, maxRetries) time.Sleep(backoff) retries++ } else { log.Fatalf("Emit failed: %v", err) } } ``` -------------------------------- ### Register Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/event-emitter.md Registers a handler for the default topic. ```APIDOC ## Register ### Description Registers a handler for the default topic ("default"). Equivalent to `RegisterWithTopic(DefaultTopicName, fn)`. ### Parameters - **fn** (MessageHandleFunc) - Required - The handler function. ``` -------------------------------- ### Implement Lifecycle Callbacks Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/lazy-emitter.md Utilizes a custom callback struct to hook into the before and after stages of message processing. ```go type myCallback struct{} func (c *myCallback) OnBefore(msg any) { fmt.Printf("Processing: %v\n", msg) } func (c *myCallback) OnAfter(msg, result any, err error) { if err != nil { fmt.Printf("Error: %v\n", err) } else { fmt.Printf("Success: %v\n", result) } } ee := lazy.NewSimpleEventEmitter(2, events.MessageHandleFunc(func(msg any) (any, error) { return msg, nil }), &myCallback{}, ) _ = ee.Emit("Task 1") time.Sleep(500 * time.Millisecond) ee.Stop() ``` -------------------------------- ### SubmitWithFunc Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/types.md Submits a message for immediate asynchronous execution. ```APIDOC ## SubmitWithFunc ### Description Submits a message for immediate asynchronous execution. ### Signature `SubmitWithFunc(fn MessageHandleFunc, msg any) error` ### Parameters - **fn** (MessageHandleFunc) - Required - The handler function to execute - **msg** (any) - Required - The message to pass to the handler ### Returns - **error** - nil on success; implementation-specific errors on failure ``` -------------------------------- ### NewSimpleEventEmitter Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/lazy-emitter.md Creates and initializes an EventEmitter with a KartaAdapter in one call, optionally registering a default handler. ```APIDOC ## NewSimpleEventEmitter ### Description Creates and initializes an `EventEmitter` with a `KartaAdapter` in one call, optionally registering a default handler. This function simplifies the setup process by handling internal adapter creation and configuration. ### Signature `func NewSimpleEventEmitter(count int, handleFunc events.MessageHandleFunc, cb karta.Callback) *events.EventEmitter` ### Parameters - **count** (int) - Required - Number of worker goroutines (ignored if <= 0). - **handleFunc** (events.MessageHandleFunc) - Optional - Handler to register on the default topic (ignored if nil). - **cb** (karta.Callback) - Optional - Lifecycle callback (ignored if nil). ### Returns - `*events.EventEmitter` - A fully initialized and ready-to-use event emitter. ### Example ```go ee := lazy.NewSimpleEventEmitter(4, handleFunc, nil) ``` ``` -------------------------------- ### WithCallback Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/karta-adapter.md Attaches a lifecycle callback to observe task execution events. ```APIDOC ## func WithCallback(cb Callback) KartaOption ### Description Attaches a lifecycle callback to observe task execution events. The callback is invoked for every task submission and completion. ### Parameters - **cb** (Callback) - Required - Callback interface implementation ### Example ```go adapter := karta.NewKartaAdapter(nil, scheduler, karta.WithCallback(&logCallback{})) ``` ``` -------------------------------- ### Topic-Based Routing Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/GUIDE.md Registers handlers for specific topics and emits events to those topics. ```go ee.RegisterWithTopic("user.created", onUserCreated) ee.RegisterWithTopic("user.deleted", onUserDeleted) ee.RegisterWithTopic("user.updated", onUserUpdated) _ = ee.EmitWithTopic("user.created", user) ``` -------------------------------- ### Topics() []string Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/event-emitter.md Returns a list of all currently registered topic names. ```APIDOC ## Topics() []string ### Description Returns a list of all currently registered topic names. ### Returns - **[]string** - Slice of topic identifiers (order is non-deterministic due to map iteration) ``` -------------------------------- ### lazy.NewSimpleEventEmitter(count int, handleFunc events.MessageHandleFunc, cb karta.Callback) Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/configuration.md Factory function for creating an EventEmitter with fixed buffer settings and two-phase initialization. ```APIDOC ## lazy.NewSimpleEventEmitter(count int, handleFunc events.MessageHandleFunc, cb karta.Callback) ### Description Simplifies configuration by handling two-phase initialization with a fixed buffer size of 256 and a SimpleScheduler. ### Parameters - **count** (int) - Required - Worker count. If <= 0, the library default is used. - **handleFunc** (events.MessageHandleFunc) - Optional - Default topic handler. - **cb** (karta.Callback) - Optional - Lifecycle callback. ``` -------------------------------- ### Register One-Shot Handler for Default Topic Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/api-reference/event-emitter.md Registers a handler that executes only once on the default topic. ```go ee.RegisterOnce(func(msg any) (any, error) { fmt.Println("This runs only once on the default topic") return msg, nil }) ``` -------------------------------- ### Implement Exponential Backoff Retry Source: https://github.com/shengyanli1982/events/blob/main/_autodocs/GUIDE.md Execute a retry loop with exponential backoff when encountering scheduler full errors. ```go func emitWithRetry(ee *events.EventEmitter, topic string, msg any) error { backoff := time.Millisecond for attempt := 0; attempt < 3; attempt++ { err := ee.EmitWithTopic(topic, msg) if err == nil { return nil } if !strings.Contains(err.Error(), "full") { return err // Non-backpressure error } time.Sleep(backoff) backoff *= 2 } return fmt.Errorf("max retries exceeded") } ```