[REVIEW] PSR-14 Event Dispatcher

320 views
Skip to first unread message

Cees-Jan Kiewiet

unread,
Jan 30, 2019, 1:05:11 PM1/30/19
to PHP Framework Interoperability Group
As of today, with a unanimous vote from the working group, we formally begin the REVIEW phase of the proposed PSR-14 (Event Dispatcher) specification. The proposed specification is in the fig-standards repository at the following locations: 


During the Review phase, acceptable changes to the specification include wording, typographical fixes, and clarifications. If you feel major changes are necessary or have, please bring your arguments/questions to the list under this thread. If any major changes are considered, we will return to the Draft phase. 

The Review period will end no sooner than 27 Jan 2019 at 11:59pm.  At that time, if the working group can demonstrate two viable trial implementations, and no need for major changes, I will call for an Acceptance Vote. 

Cees-Jan Kiewiet, your friendly neighbourhood PSR-14 Sponsor

Girgias

unread,
Jan 30, 2019, 1:17:51 PM1/30/19
to php...@googlegroups.com
The review period deadline needs to be changed. The 27th of Jan 2019 was two days ago.
Did you mean 27th of February 2019?

Best regards

George P. Banyard


--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/b235f95a-41f5-4abb-8e9a-3fedcdde23a7%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Cees-Jan Kiewiet

unread,
Jan 30, 2019, 1:31:18 PM1/30/19
to php...@googlegroups.com
Yes  27th of February 2019 is the correct deadline.


For more options, visit https://groups.google.com/d/optout.


--

Larry Garfield

unread,
Feb 21, 2019, 3:33:09 PM2/21/19
to php...@googlegroups.com
On Wed, Jan 30, 2019, at 12:31 PM, Cees-Jan Kiewiet wrote:
> Yes 27th of February 2019 is the correct deadline.
>
> On Wed, Jan 30, 2019 at 7:17 PM Girgias <george....@gmail.com> wrote:
> > The review period deadline needs to be changed. The 27th of Jan 2019 was two days ago.
> > Did you mean 27th of February 2019?
> >
> > Best regards
> >
> > George P. Banyard
> >
> >
> > On Wed, 30 Jan 2019 at 19:05, Cees-Jan Kiewiet <cees...@gmail.com> wrote:
> >> As of today, with a unanimous vote from the working group, we formally begin the REVIEW phase of the proposed PSR-14 (Event Dispatcher) specification. The proposed specification is in the fig-standards repository at the following locations:
> >>
> >> - Specification: https://github.com/php-fig/fig-standards/blob/master/proposed/event-dispatcher.md
> >> - Metadocument: https://github.com/php-fig/fig-standards/blob/master/proposed/event-dispatcher-meta.md
> >>
> >> During the Review phase, acceptable changes to the specification include wording, typographical fixes, and clarifications. If you feel major changes are necessary or have, please bring your arguments/questions to the list under this thread. If any major changes are considered, we will return to the Draft phase.
> >>
> >> The Review period will end no sooner than 27 Jan 2019 at 11:59pm. At that time, if the working group can demonstrate two viable trial implementations, and no need for major changes, I will call for an Acceptance Vote.
> >>
> >> Cees-Jan Kiewiet, your friendly neighbourhood PSR-14 Sponsor

Core Committee members: How shall the WG interpret your silence? :-) As approval or indifference?

If approval, please let us know that you're approving so we know not to worry when it comes time to call a vote. :-)

Beuller?

--Larry Garfield

Beau Simensen

unread,
Feb 22, 2019, 12:46:17 PM2/22/19
to PHP Framework Interoperability Group
I've read the spec, meta document, taken a look at two reference implementations, and explored the util package. If the working group is happy with the spec as-is, I have little to add or ask questions about at this point with one minor exception.

This wording seems a bit unclear: "Listener Providers MUST treat parent types identically to the Event's own type when determining listener applicability." It seems like there should be an easier way to say this that is more direct?

At the same time, the bit just below the example reads: "A Listener Provider MUST treat listener() as an applicable listener for $b, as it is type compatible, unless some other criteria prevents it from doing so."

Listener Providers MUST treat parent types identically, unless some other criteria prevents it from doing so? Is that the correct way to read this?

Alexandru Pătrănescu

unread,
Feb 23, 2019, 6:46:07 PM2/23/19
to php...@googlegroups.com
Hi working group,

I spent some time reviewing the specs.

I don't see any major issues but I have few items to discuss/improve:

1. Listeners. Phrase: A Listener MAY delegate actions to other code. That includes a Listener being a thin wrapper around retrieving an object from a service container that contains the actual business logic to run, or other similar forms of indirection. In that case, the callable containing the actual business logic SHOULD conform to the same rules as if it were called directly as a Listener.
I can see an example that look this like:
$thinWrapperListener = function(BusinessEvent $event) use ($container, $parameter2) {
    $businessService = $container->get(BusinessService::class);
    $businessService->process($event, $parameter2);
};
I can't see why BusinessService:: process() should have a single parameter and a void return. Or maybe this is not the intended meaning of the text the callable containing the actual business logic SHOULD conform to the same rules.
If meaning was different let's find a different phrasing.

Also, the mention about a Listener that could be a thin wrapper looks fine but the wrapper around part of the phrase I think it can be improved. I suggest this rephrasing https://github.com/php-fig/fig-standards/pull/1152

2. Dispatcher. Phrase: As an exception to the previous point, if the Event is a Promise object then the Dispatcher MAY return that Promise before all Listeners have executed. However, the Promise MUST NOT be treated as fulfilled until all Listeners have executed.
If the Event is a Promise, Listeners would probably attach logic to be run when the Promise will be resolved. But this would be exactly like the normal flow.
The only case where the Dispatcher could return the promise before executing all Listeners is if the Dispatcher would attach the Listeners execution logic to be run when the Promise would be resolved. But the only reason for this would be if the Listeners would be called with the event resolved Value, contradicting the main phrase of the Dispatcher section: invoking each Listener with that Event.
Also the Promise MUST NOT be treated as fulfilled until all Listeners have executed would be hard to implement with current libraries. If I'm not wrong a promise would fulfill in regards to the initial async fulfillment logic and, if one wants to have this behavior (adding more rules to fulfillment), it would create a new Promise object based on the previous one and the Listener execution calls.
With this in mind, I suggest we remove the line https://github.com/php-fig/fig-standards/pull/1153

3. Listener Provider. Phrase: A Listener Provider MUST treat listener() as an applicable listener for $b, as it is type compatible, unless some other criteria prevents it from doing so.
I think that MUST can be change to SHOULD, similar with how it was used in a previous phrase: Listener Providers SHOULD use the class name of an Event to differentiate one event from another.
As english is not my first language, I might miss on the interpretation of words.


Regards,
Alex


--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Larry Garfield

unread,
Feb 24, 2019, 12:28:32 PM2/24/19
to php...@googlegroups.com
On Fri, Feb 22, 2019, at 11:46 AM, Beau Simensen wrote:
> On Wednesday, January 30, 2019 at 12:05:11 PM UTC-6, Cees-Jan Kiewiet wrote:
> > As of today, with a unanimous vote from the working group, we formally begin the REVIEW phase of the proposed PSR-14 (Event Dispatcher) specification. The proposed specification is in the fig-standards repository at the following locations:
> >
> > - Specification: https://github.com/php-fig/fig-standards/blob/master/proposed/event-dispatcher.md <https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Fphp-fig%2Ffig-standards%2Fblob%2Fmaster%2Fproposed%2Fevent-dispatcher.md&sa=D&sntz=1&usg=AFQjCNFxqjlVyCx0rWLjURLKp1DHoCy8cw>
> > - Metadocument: https://github.com/php-fig/fig-standards/blob/master/proposed/event-dispatcher-meta.md
> >
> > During the Review phase, acceptable changes to the specification include wording, typographical fixes, and clarifications. If you feel major changes are necessary or have, please bring your arguments/questions to the list under this thread. If any major changes are considered, we will return to the Draft phase.
> >
> > The Review period will end no sooner than 27 Jan 2019 at 11:59pm. At that time, if the working group can demonstrate two viable trial implementations, and no need for major changes, I will call for an Acceptance Vote.
>
> I've read the spec, meta document, taken a look at two reference
> implementations, and explored the util package. If the working group is
> happy with the spec as-is, I have little to add or ask questions about
> at this point with one minor exception.
>
> This wording seems a bit unclear: "Listener Providers MUST treat parent
> types identically to the Event's own type when determining listener
> applicability." It seems like there should be an easier way to say this
> that is more direct?
>
> At the same time, the bit just below the example reads: "A Listener
> Provider MUST treat listener() as an applicable listener for $b, as it
> is type compatible, unless some other criteria prevents it from doing
> so."
>
> Listener Providers MUST treat parent types identically, unless some
> other criteria prevents it from doing so? Is that the correct way to
> read this?

Hi Beau.

Yeah, that bit is a little tricky to state succinctly. Let me explain it long-form and maybe someone has a better, tighter way to word it.

Providers get huge latitude to determine what listeners they return and in what order. The Dispatcher just trusts whatever it gets back. That makes Providers the key "customization" point. (In practice most Dispatchers will be largely the same, but Providers can vary enormously.)

The most common case, and the one that we should encourage as a default, is "if a listener is type-compatible with the event, then it applies." So a listener whose first parameter is "LoginHappened $event" should apply to any event that is an instance of LoginHappened. But then what do you do with an instance of AdminLoginHappened, which extends LoginHappened?

The intent of the spec is to say that since AdminLoginHappened is a subclass of LoginHappened, then all listeners that apply to LoginHappened will also apply to AdminLoginHappened. That offers several advantages:

1) You can special-case an event very easily without losing access to a large set of existing listeners.
2) You can "tag" events with interfaces to create event groups. Laravel has that functionality currently using a junior-regex style naming of events. This offers the same capability but built on native language functionality.

However, we don't want some implementations to pay attention to the inheritance tree and others to just look at the specific class of the event; that would mean Emitters (which in PSR-14 speak is the calling library) can't rely on AdminLoginHappened also triggering LoginHappened listeners, and they'll start firing both just to be safe, and that's just a mess. So the spec requires that they both apply.

HOWEVER! A Provider is also totally able to use criteria beyond the type if it wants to. It can also be configured such that certain listeners only apply if the current user is an administrator, if the current user is anonymous, if the current environment is/is not production, and so forth. For example, it's entirely possible that a particular listener for LoginHappened is configured to only apply in development, not production. In that case, if an AdminLoginHappened event fires in production then that listener should NOT be returned, but because it's in the wrong environment, not because it's type doesn't match. Other listeners for either LoginHappened or AdminLoginHappend would still apply.

I hope that clears up the intent there. If someone can suggest a better way to state that in the spec that isn't 6 paragraphs long, I'm happy to update the text.

--Larry Garfield

Chuck Burgess

unread,
Feb 27, 2019, 2:02:10 PM2/27/19
to php...@googlegroups.com

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

desig...@gmail.com

unread,
Mar 1, 2019, 3:40:10 PM3/1/19
to PHP Framework Interoperability Group
I've been thinking should the name of the package (and consequently, the interfaces) not be something like "MessageDispatcher"? This is a bit more generic and could cover messages, events and commands.

Cees-Jan Kiewiet

unread,
Mar 2, 2019, 5:19:21 PM3/2/19
to php...@googlegroups.com
Hey Alex,

Thank you for your input. About PR 1152 I'm to be perfectly honest about it indifferent about it. Both phrases work for me and I'll leave that up to the rest of the WG which one works best.

About PR 1153 totally agree, in retrospect we should have never included it. The whole dealing with promises shouldn't have been done within the event dispatcher because if you want to combine events with chaining it you're looking at something like https://github.com/rdohms/chainlink or https://github.com/thephpleague/pipeline infused with promises.  

With regards to the MUST vs SHOULD, MUST is correct here because B is inheriting from A and inherits the same base class.

Cheers,

Cees-Jan

Matthew Weier O'Phinney

unread,
Mar 3, 2019, 1:53:56 PM3/3/19
to php...@googlegroups.com
On Fri, Mar 1, 2019 at 2:40 PM <desig...@gmail.com> wrote:
I've been thinking should the name of the package (and consequently, the interfaces) not be something like "MessageDispatcher"? This is a bit more generic and could cover messages, events and commands.

For a long period of time, we were working with having both an EventDispatcher and a MessageDispatcher. However, on looking at the various use cases, we decided to narrow the focus to only the EventDispatcher.

There are two general styles of message dispatchers. One is for queueing, and in that case, you have both an object that will enqueue a message, and one that will dequeue messages and dispatch them to workers. When queueing a message, no listeners are involved; it's a 1:1 relationship between the message and the queue. Generally speaking, the same is true when dequeueing messages; only one worker will operate on the provided message. In each case, the message MUST be immutable to guarantee the ability to replay the queue. Both cases are very different use cases to the EventDispatcher we have specified, which posits a 1:N relationship between events and listeners.

The other type of message dispatcher can be seen in components such as symfony/messenger. On the surface, it looks quite similar. However, in practice, it's quite different: it acts like a command bus.

Command buses are very different from the specification we set out to develop. They posit:

- immutable commands, which are passed to
- a bus that executes middleware that can decorate the command (i.e., acts a bit like a filter chain, with each operating on the return value of the previous), and
- match the command to a single handler, which it then
- invokes, and thus executes the command.

The EventDispatcher as we have specified does not satisfy these criteria. You CAN use immutable instances, but we require the SAME instance be passed to each listener (i.e., no decoration allowed). We allow halting execution before all listeners are executed if the event indicates no further processing is required/possible (command buses generally only allow that via exceptions). Order of listener execution is determined by the _provider_ given to the event dispatcher, and there is no differentiation between listeners; they all have the same signature (no differentiation of concepts such as "middleware" or "handlers"). To be honest, PSR-15 is much closer to a command bus than this specification, albeit an HTTP-specific variant.

Interestingly, I think both a generic subject/observer pattern (which is close to the idea of a message notifier) and a command bus CAN be expressed and implemented using this specification as degenerate cases (we allow immutable objects; priority can be delegated to a provider, which can in turn do something akin to matching an event to a pipeline that ends in a "handler"; the "command" could be wrapped in an event, which allows the event to ask a an envelope for purposes of decoration/metadata), we specifically do not address these two use cases as we feel they likely need their own specifications, due to the subtle differences in usage and context.
 

For more options, visit https://groups.google.com/d/optout.


--
he/him
Reply all
Reply to author
Forward
0 new messages