refactor: replace string-based emitter with type-safe generic event system #28
Reference in New Issue
Block a user
Delete Branch "feat/better-emitter"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Description
This PR refactors the event emitter system from a string-based message passing approach to a type-safe generic implementation using typed events.
The previous system relied on string message names which were error-prone and lacked compile-time safety.
This refactoring introduces a generic
BaseEmitter[E comparable]that provides type safety while consolidating the various tracker packages into a unified plugins architecture.Key changes:
Emitterwith genericBaseEmitter[E comparable]for type-safe event handling.Eventtype enumeration withStartEvent,StepEvent, andStopEventconstants.Listener[E]interface withBaseListenerimplementation for better abstraction.explanation,performance, andstatisticspackages into unifiedinternal/pluginspackage.Items()iterator method toSetfor idiomatic Go 1.23+ range loops over sets.Decisions
Use generics for type-safe event handling.
This provides compile-time guarantees that event types match their handlers while maintaining flexibility for future event types.
Consolidate trackers into plugins architecture.
Previously separate packages (
explanation,performance,statistics) now live underinternal/plugins, making the plugin pattern explicit and easier to extend.Plugin constructors self-register with engine.
Each plugin's
New*constructor now handles its own event subscriptions, reducing boilerplate in the main CLI.Benefits
Type safety prevents runtime errors from typos in event names.
The compiler now catches mismatched event types at compile time rather than failing silently at runtime.
Cleaner plugin architecture makes adding new features easier.
New plugins follow a consistent pattern and live in a single location.
Reduced boilerplate in main CLI.
Plugin initialization is now a single function call rather than manual event registration.
Better testability through interface-based design.
The
Listener[E]interface allows for easier mocking and testing of event handlers.Checklist
<type>/<description>).