What are the expectations around registering, subscribing, and publishing events with the built in “notfications” component, which is an instance of Dry::Monitior::Notifications
?
The following is a transcript of a discord discussion on the topic. I’ve decided to post it here for searchability for other’s who have the same question.
Aaron Allen
Dear Hanami, Where is the appropriate place for a slice to register_events in the notification system?
Adam Lassek
I do it in a provider like so:
CIAM::Slice.register_provider :webhooks do
start do
webhook = CIAM::Events::Webhook.new
webhook.subscribe CIAM::Events::Logger.new
if Enabled?(:webhook_events)
webhook.subscribe CIAM::Events::WebhookListener.new
end
register "events.webhook", webhook
end
end
Aaron Allen
Is this for the built in Dry Monitor or is this something custom?
Adam Lassek
Ah, you’re talking about dry-monitor for the container? My example is dry-events
Aaron Allen
yeah I was just planning to use the built in notification system
so that slices can chat
Adam Lassek
So your own custom monitor instance? i.e. you’re not talking about monitoring key usage?
Aaron Allen
I’m talking about:
app['notifications']
my_slice['notifications']
which is a shared instance of dry-monitor notifications
It’s there but it’s not super well documented how one should go about utilizing it
Adam Lassek
The simplest answer is probably initialize it as a top-level provider and autoinject it to every slice
I would only do that differently if you needed separate notification channels
Aaron Allen
it’s already auto injected but I can’t seem to do:
Hanami.app.configure_provider :notifications
#...
end
Without it barfing
I guess I could just do a generic:
MySlice::Slice.register_provider :events do
start do
EVENTS.each { |e| target['notifications'].register_event(e) }
end
end
but I was hoping there was some “official” way to go about this (edited)
Adam Lassek
There is no “official” integration yet AFAIK
Good candidate for an extension, though.
Aaron Allen
Cool hopefully @timriley can give clarity on the intended use when he wakes up
Adam Lassek
When you say “barfing” what exactly is the problem?
Aaron Allen
basically it appears if you do:
Hanami.app.configure_provider :notifications do
#...
end
it appears to override the default notifications provider
Adam Lassek
Are you using hanami-db
?
Aaron Allen
aye
Adam Lassek
okay there is official integration for this I was wrong hanami/lib/hanami/app.rb at 252f448781710f7cb73cda684a2dc02941d210e3 · hanami/hanami · GitHub
that was introduced with DB support I believe, because ROM relies on it
So you could reuse that, or define your own under a different key name
Aaron Allen
no what’s provided is plenty sufficient its just a matter of figuring out where events are meant to be registered in the stack
because you can’t subscribe to events that aren’t registered
Adam Lassek
configure_provider
isn’t working because this is coming from a dry-system extension, not a hanami provider
it is initialized in prepare_all
, before your providers will run. So you could define a provider that registers these events, you just need to name it differently
this is bad ergonomics, perhaps we should write an official provider to make configuration easier
Aaron Allen
MySlice::Slice.register_provider :events do
start do
target['notifications'].register_event('my_event')
end
end
my_slice['notifications'].subscribe('my_event')
# => you are trying to subscribe to an event: `my_event` that has not been registered (Dry::Events::InvalidSubscriberError)
Adam Lassek
did you run my_slice.start(:events)
?
Aaron Allen
same error
actually no running my_slice.start(:events)
Does make it work but am I meant to log in to every production console and run that every time the app restarts?
Adam Lassek
the console defaults to lazy-loading, production will generally run app.boot
root:0> app[:notifications].__bus__.events.values
=> [#<Dry::Events::Event id="test_event" payload={}>]
If you wanted production to also lazy-load, you could do something like
environment(:production) do
start :events
end
in config/app.rb
Aaron Allen
yeah this isn’t great DX I’d really like to see something like:
module MySlice
class Slice < Hanami::Slice
config.notifications.register_event('my_event')
end
end
or something of that nature
Adam Lassek
Not a bad suggestion, or something like
config.notifications += %w[
event_one
event_two
]
Aaron Allen
aye
or even better:
config.emits += #...
but most importantly it needs to be done in a way that I can subscribe to events in console without needing to run app.boot
oh and also important:
module MyOtherSlice
class Slice < Hanami::Slice
config.notifications.subscribe('event_one', 'listeners.my_event_one_listener')
end
end
because as of right now I have no earthly idea how I’m meant to handle actually subscribing to the events
Adam Lassek
Well, the bus doesn’t exist until the prepare lifecycle. So this means the earliest you could subscribe is inside a provider. I don’t think we could support doing this as configuration like that because I think block-based subscription is possible as well.
Aaron Allen
aye
Adam Lassek
To generalize the problem, we have a DX footgun happening because you need to run a provider when opening a console that depends on a side-effect, and it can’t be inferred by key name
Aaron Allen
It’s possible the intended use case was for notifications to be an internal tool strickly for Hanami to use but if so why expose it in the components?
Adam Lassek
Like I said, it was a dependency of ROM that introduced it, but I don’t think we specifically intended it to be internal-only either
if you wanted to access telemetry from ROM it’s necessary to be able to access the bus
But not a first-class feature, so didn’t get the ergonomic design DB configuration did
I would like to hear @timriley 's thoughts, but it sounds like replacing the dry-system plugin with a Hanami provider that supports configure_provider :notifications
would solve a lot of these problems
But we also want to preserve the lazy-loading aspect of the container system, so maybe it would be useful to have something like HANAMI_AUTOSTART=notifications