Class: Servus::Event
- Inherits:
-
Object
- Object
- Servus::Event
- Extended by:
- Schema::Declaration
- Defined in:
- lib/servus/event.rb
Overview
Base class for event definitions.
Event classes live in app/events/ and serve three purposes:
- Contract — declares the event exists and defines its name
- Validator — schema enforcement on any emission
- Declarative routing — optional
invokedeclarations
The event name can be set explicitly via event_name or inferred
from the class name (e.g. OrderPlaced becomes :order_placed).
Call ensure_registered! to trigger inference for classes that
don't declare an explicit name.
Class Method Summary collapse
-
.emit(payload) ⇒ void
Emits this event via the Bus.
-
.enqueue(service_class, options = {}) {|payload| ... } ⇒ void
Declares a service to enqueue in response to the event.
-
.ensure_registered! ⇒ void
Infers and registers the event name from the class name if not already set explicitly.
-
.event_name(name = nil) ⇒ Object
Declares or returns the event name.
-
.handle(payload) ⇒ Array
Handles an event by resolving and executing all invocations.
-
.invocations ⇒ Array<Hash>
Returns all service invocations declared for this event.
-
.invocations_for(payload) ⇒ Array<Servus::Events::Invocation>
Returns Invocation objects for the given payload, with conditions already evaluated.
-
.invoke(*_args, **_options) ⇒ Object
deprecated
Deprecated.
Use #enqueue.
-
.payload_schema ⇒ Hash?
The compiled payload schema.
-
.schema(payload: nil) ⇒ void
Declares the JSON schema for this event's payload.
Methods included from Schema::Declaration
declare_schemas, schema, schema_types
Class Method Details
.emit(payload) ⇒ void
This method returns an undefined value.
Emits this event via the Bus.
Provides a type-safe, discoverable way to emit events from anywhere in the application (controllers, jobs, rake tasks) without creating a service.
226 227 228 229 230 231 232 |
# File 'lib/servus/event.rb', line 226 def emit(payload) raise 'No event configured. Call event_name :name first.' unless @event_name Servus::Support::Validator.validate_event_payload!(self, payload) Servus::Events::Bus.emit(@event_name, payload) end |
.enqueue(service_class, options = {}) {|payload| ... } ⇒ void
This method returns an undefined value.
Declares a service to enqueue in response to the event.
An event can declare as many services as it needs; each is enqueued independently when the event fires. The block maps the event payload to the service's keyword arguments — without one, the full payload is passed through.
Invocation is always asynchronous. A reaction that ran inline would put its latency and its failures back into the emitting service, which is what events exist to avoid. This requires ActiveJob; see Servus::Events::Errors::AsyncBackendMissingError.
169 170 171 172 173 174 175 176 177 178 |
# File 'lib/servus/event.rb', line 169 def enqueue(service_class, = {}, &block) reject_async_option!() @invocations ||= [] @invocations << { service_class: service_class, options: , mapper: block || ->(payload) { payload } } end |
.ensure_registered! ⇒ void
This method returns an undefined value.
Infers and registers the event name from the class name if not already set explicitly. Safe to call multiple times — does nothing if already registered. Skips anonymous classes.
121 122 123 124 125 126 |
# File 'lib/servus/event.rb', line 121 def ensure_registered! return if @event_name return if name.nil? event_name(name.demodulize.underscore.to_sym) end |
.event_name(name) ⇒ void .event_name ⇒ Symbol?
Declares or returns the event name.
When called with an argument, sets the event name and registers with the Bus. When called without arguments, returns the current event name.
If never called explicitly, use ensure_registered! to infer
the name from the class name.
107 108 109 110 111 112 113 114 |
# File 'lib/servus/event.rb', line 107 def event_name(name = nil) return @event_name if name.nil? raise "Event already subscribed to :#{@event_name}. Cannot subscribe to :#{name}" if @event_name @event_name = name Servus::Events::Bus.register_event(name, self) end |
.handle(payload) ⇒ Array
Handles an event by resolving and executing all invocations.
255 256 257 |
# File 'lib/servus/event.rb', line 255 def handle(payload) invocations_for(payload).map(&:enqueue) end |
.invocations ⇒ Array<Hash>
Returns all service invocations declared for this event.
197 198 199 |
# File 'lib/servus/event.rb', line 197 def invocations @invocations || [] end |
.invocations_for(payload) ⇒ Array<Servus::Events::Invocation>
Returns Invocation objects for the given payload, with conditions already evaluated. This is what routers call to resolve actions.
239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/servus/event.rb', line 239 def invocations_for(payload) invocations.filter_map do |inv| next unless should_invoke?(payload, inv[:options]) Servus::Events::Invocation.new( service: inv[:service_class], params: inv[:mapper].call(payload), options: inv[:options].except(:if, :unless) ) end end |
.invoke(*_args, **_options) ⇒ Object
Use #enqueue.
Explains that invoke was renamed, rather than failing as a typo.
Event classes load at boot, so a bare NoMethodError here would read like
a misspelling instead of a rename. This covers both changes at once,
since the overwhelmingly common declaration was invoke Foo, async: true.
188 189 190 191 192 |
# File 'lib/servus/event.rb', line 188 def invoke(*_args, **, &) raise NoMethodError, '`invoke` was renamed to `enqueue` in 1.0.0 — event invocation is always ' \ 'asynchronous. Replace `invoke` with `enqueue`, and drop `async:` if present.' end |
.payload_schema ⇒ Hash?
Returns the compiled payload schema.
78 |
# File 'lib/servus/event.rb', line 78 declare_schemas :payload |
.schema(payload: nil) ⇒ void
This method returns an undefined value.
Declares the JSON schema for this event's payload.
The payload is validated on every emit. Schemas may reference shared fragments registered with Schema.register; refs are resolved on first read.
Omitting the keyword leaves any schema declared earlier — or by a
superclass — in place. Passing it explicitly as nil raises.
78 |
# File 'lib/servus/event.rb', line 78 declare_schemas :payload |