Closed farwayer closed 7 years ago
Hi @farwayer sorry for the late reply.
As you can see, plugins will be soon able to send messages to the logger, which is a very important need that you pointed out, and we thank you for that.
On the other side, we are thinking about exposing the trigger()
method, so that plugins may trigger events on their own (even custom events, in this case). We didn't take the time to thoroughly talk about this feature with all the team but we'll do it soon (but we won't implement this feature in a rush since it may have consequences on the whole plugin architecture).
Again, thanks for your contributions and stay tuned!
My personal thoughts on this subject involve the use in Kuzzle of a Mailer plugin within a shopping cart checkout process. Imagine that
What would be the best way to do it?
send-mail
event, which would contain the whole mail (sender, receipients, Cc, Bcc and body) and just send it. Doesn't look very neat (and implies the use of trigger
within the Checkout plugin).{
"controller": "mailer",
"method": "send"
}
so that the Checkout plugin (assuming that it has access to the Kuzzle API) would call it to send the mail. Looks better and doesn't require the use of trigger
.
Any thoughts are welcome.
Thank you guys for your attention! Event system has more power. Let's discuss your example.
Think a bit what is really want to do Checkout controller. Does he want send email? No at all. Actually Checkout controller should notify user about purchase status. From this point of view things become more interesting.
We have decided to notify user by email. So lets add EmailUserNotificator
. Plugin will catch notify-user
events and send emails to user.
Over time we think that emails is obsolete (I don't think so :smiley:) and we certainly should add SMS notifications (or WhatsApp or Slack or whatever).
In your situation you will need to modify Checkout controller. In system based on events it will only need to add new SMSUserNotificator
plugin. Thats all. And even more: at any time you can turn on/off certain notification type without code change.
Another good example is logger
. Different loggers can write events to file, send over network, notify about critical errors by Slack.
But there is le revers de la médaille.
First of all there is harder to debug event systems. Especially if events dispatched async and stacktrace missed.
Second is you can forget to add some important plugins and it will be silently ignored. Solution in this case is create dependency system with required
and optional
features provided by another plugins. It will be usefull in any case regardless of using or not event system. It is not for kuzzle 1.0 of course.
:thinking:
I wouldn't say that event systems are absolutely more powerful. They just embrace a different approach. In event systems, entities are responsible of notifiying other entities (they know nothing about) with chunks of their state. Listeners are responsible to listening these events and act consequently. Take the Checkout example
More generally: given an action, in the event-based approach, the listeners are responsible of performing the action, while in the imperative approach the caller (i.e. the emitter) is responsible of performing the action.
I'm not really a promoter of imperative approaches and, yes, event-based approaches use to look neat in terms of concern separation and component decoupling.
We are legitimate to say that, here, the Checkout plugin is kept reusable, which is true.
But what about the UserNotifier? Even if it's living in the eventful world, it is actually coupled to the checkout
plugin. And that is for the following reasons
checkout
event (which I hope, since I would ignore what other checkout
event would mean),My point is that, in your example, one of the two components is not generic, so maybe the logic does not need to be split. Notifying the user is a concern of the Checkout plugin. What the Checkout plugin should not be responsible of is the way these notifications are sent.
A more reusable plugin would be, IMHO, a generic MailNotification (or SMS or Whatsapp or Slack) plugin, which would just enable the communication with a third-party service. Such a plugin shouldn't be responsible of listening to events, since it's meant to be a generic plugin.
To sum-up, IMHO, the main goal of the Kuzzle Controller Plugins is to extend the Kuzzle API with new methods to call. And this is bound by design to the existence of the frontend (which communicates with the backend in an imperative way, i.e. by calling methods). Making the cross-plugin communication imperative keeps this mechanism consistent without introducing a new, different, one.
It is still kind of difficult to clearly express the reasons why I feel that the event system is not necessary (and even a not-so-good idea), so this is a draft of my views.
Again, thanks a lot for your discussion, it really helps us pushing things forward!
@farwayer The PR #557 should solve part of your issue about handling logs, this feature should be available in the next release (1.0.0-RC8)
@dbengsch Thank you for notification! I saw it already. Good job!
@xbill82 I had in mind a slightly different thing. It is not about plugin event generation when something happened.
I meant service system when some plugins can provide functionality to others but without tight coupling. For example EmailUserNotificator
and SMSUserNotificator
can subscribe to notify-user
event and send messages to user when some controller request it.
On the another side CheckoutController don't know who is engaged in this work. So we have a very flexible system. You can very simple replace one plugin with another in runtime without changing code.
Of course events system is only one of possible implementation. Maybe it will be better to implement separate provider service registry controlled by the kuzzle core. Just like dynamic context.accessors
. CheckoutController can say to core: I need something that can notify user. And will receive one or several providers.
I want to throw error during plugin initialization with
log:error
event. But look like plugin must be privileged to get access topluginManager
. I do not need access to any internal functionality nor any internal data. Only throw event.I think throwing events it's very useful functionality for plugins and it should be available to all modules. Some plugins may throw events and another may catch them. It's very valuable case. I propose to add
trigger()
method to plugin context.Also it will be nice to have
logger
helper object inside context withwarn()
,info()
,debug()
,verbose()
anderror()
methods. This functions should throwlog:*
events. For convenience only.