{"action":"created","issue":{"url":"https://api.github.com/repos/zendframework/zend-eventmanager/issues/4","labels_url":"https://api.github.com/repos/zendframework/zend-eventmanager/issues/4/labels{/name}","comments_url":"https://api.github.com/repos/zendframework/zend-eventmanager/issues/4/comments","events_url":"https://api.github.com/repos/zendframework/zend-eventmanager/issues/4/events","html_url":"https://github.com/zendframework/zend-eventmanager/pull/4","id":92741693,"number":4,"title":"[WIP] Alternate EventManager refactor","user":{"login":"weierophinney","id":25943,"avatar_url":"https://avatars.githubusercontent.com/u/25943?v=3","gravatar_id":"","url":"https://api.github.com/users/weierophinney","html_url":"https://github.com/weierophinney","followers_url":"https://api.github.com/users/weierophinney/followers","following_url":"https://api.github.com/users/weierophinney/following{/other_user}","gists_url":"https://api.github.com/users/weierophinney/gists{/gist_id}","starred_url":"https://api.github.com/users/weierophinney/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/weierophinney/subscriptions","organizations_url":"https://api.github.com/users/weierophinney/orgs","repos_url":"https://api.github.com/users/weierophinney/repos","events_url":"https://api.github.com/users/weierophinney/events{/privacy}","received_events_url":"https://api.github.com/users/weierophinney/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/zendframework/zend-eventmanager/labels/BC%20Break","name":"BC Break","color":"e11d21"},{"url":"https://api.github.com/repos/zendframework/zend-eventmanager/labels/enhancement","name":"enhancement","color":"84b6eb"},{"url":"https://api.github.com/repos/zendframework/zend-eventmanager/labels/WIP","name":"WIP","color":"0b02e1"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/zendframework/zend-eventmanager/milestones/2","html_url":"https://github.com/zendframework/zend-eventmanager/milestones/3.0.0","labels_url":"https://api.github.com/repos/zendframework/zend-eventmanager/milestones/2/labels","id":1137638,"number":2,"title":"3.0.0","description":"next backward compatibility break release","creator":{"login":"Maks3w","id":1301698,"avatar_url":"https://avatars.githubusercontent.com/u/1301698?v=3","gravatar_id":"","url":"https://api.github.com/users/Maks3w","html_url":"https://github.com/Maks3w","followers_url":"https://api.github.com/users/Maks3w/followers","following_url":"https://api.github.com/users/Maks3w/following{/other_user}","gists_url":"https://api.github.com/users/Maks3w/gists{/gist_id}","starred_url":"https://api.github.com/users/Maks3w/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Maks3w/subscriptions","organizations_url":"https://api.github.com/users/Maks3w/orgs","repos_url":"https://api.github.com/users/Maks3w/repos","events_url":"https://api.github.com/users/Maks3w/events{/privacy}","received_events_url":"https://api.github.com/users/Maks3w/received_events","type":"User","site_admin":false},"open_issues":1,"closed_issues":0,"state":"open","created_at":"2015-05-28T09:27:58Z","updated_at":"2015-07-02T21:42:41Z","due_on":null,"closed_at":null},"comments":7,"created_at":"2015-07-02T21:41:14Z","updated_at":"2015-07-03T16:18:53Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/zendframework/zend-eventmanager/pulls/4","html_url":"https://github.com/zendframework/zend-eventmanager/pull/4","diff_url":"https://github.com/zendframework/zend-eventmanager/pull/4.diff","patch_url":"https://github.com/zendframework/zend-eventmanager/pull/4.patch"},"body":"- Removes:\r\n  - `SharedEventAggregateAwareInterface::detachAggregate`\r\n  - `SharedEventManagerAwareInterface::getSharedManager` and `unsetSharedManager`.\r\n  - `SharedEventManagerInterface::detach`\r\n  - `EventManagerInterface::detach`, `detachAggregate`, and `addIdentifiers`.\r\n- Modifies:\r\n  - `EventManagerInterface::attach` renames `$callback` to `$listener`, typehints it as callable, and makes it required. The method no longer has a return value.\r\n  - `EventManagerInterface::trigger` now typehints the `$callback` argument as callable\r\n  - `SharedEventManagerInterface::getListeners` now markes the `$event` argument as optional, and returns an array.\r\n- Adds:\r\n  - `Exception\\RuntimeException`\r\n\r\nAll implementations of the above interfaces were modified accordingly.\r\n\r\n`SharedEventManager` was modified to store the various listeners within structured arrays instead of `EventManager` and/or `PriorityQueue` instances.\r\n\r\n`EventManager` was altered to accept both identifiers and a `SharedEventManager` instance to the constructor. Additionally, once both identifiers and the shared manager instance are present, a call is made to a new method, `prepareListeners`; this method does the following:\r\n\r\n- It loops through all identifiers,\r\n- pulls listeners from the shared manager based on those identifiers,\r\n- caching wildcard listeners for later,\r\n- and attaches all other listeners directly to the instance.\r\n\r\nIt then loops through wildcard identifiers, with the same logic.\r\n\r\nFinally, it loops through any known events, and attaches all wildcard listeners to each of the events.\r\n\r\nThe BC breaks from this approach are as follows:\r\n\r\n- Obviously, if you used any of the removed methods, they are no longer available.\r\n\r\n- `CallbackHandler` instances can no longer be used when calling `attach()`\r\n\r\n- Any shared listeners attached *after* the instance is created will not be executed. This means attachment of shared listeners should be done early, preferably during application bootstrap, but really anytime before an instance is fetched from the service manager.\r\n\r\nThe changes, however, are essentially BC with the current solution.\r\n\r\n**My initial benchmarks show that execution is around twice as fast as the current solution.** This keeps the differentiating features of our solution, including the granularity of listener attachment, at a substantial speed savings.\r\n\r\n## TODO\r\n\r\n- [ ] Testing\r\n- [ ] Migration scripts\r\n- [ ] Performance benchmarking tests (via Athletic)"},"comment":{"url":"https://api.github.com/repos/zendframework/zend-eventmanager/issues/comments/118386040","html_url":"https://github.com/zendframework/zend-eventmanager/pull/4#issuecomment-118386040","issue_url":"https://api.github.com/repos/zendframework/zend-eventmanager/issues/4","id":118386040,"user":{"login":"weierophinney","id":25943,"avatar_url":"https://avatars.githubusercontent.com/u/25943?v=3","gravatar_id":"","url":"https://api.github.com/users/weierophinney","html_url":"https://github.com/weierophinney","followers_url":"https://api.github.com/users/weierophinney/followers","following_url":"https://api.github.com/users/weierophinney/following{/other_user}","gists_url":"https://api.github.com/users/weierophinney/gists{/gist_id}","starred_url":"https://api.github.com/users/weierophinney/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/weierophinney/subscriptions","organizations_url":"https://api.github.com/users/weierophinney/orgs","repos_url":"https://api.github.com/users/weierophinney/repos","events_url":"https://api.github.com/users/weierophinney/events{/privacy}","received_events_url":"https://api.github.com/users/weierophinney/received_events","type":"User","site_admin":false},"created_at":"2015-07-03T16:18:53Z","updated_at":"2015-07-03T16:18:53Z","body":"@codeliner Thanks for the feedback! I've updated to re-add `addIdentifiers()`, which necessitated deferring the attachment of shared listeners to the first `trigger()` operation. This actually solves a lingering doubt I had with the original refactor, as aggregating shared listeners early leads to some potential order-of-operations issues (which you confirmed in your comment). This also simplified the logic for aggregating wildcard events — and posed no changes to the initial performance improvements I observed!\r\n\r\n(However, if you attempt to add identifiers or a shared manager after the first `trigger` operation an exception is now raised. I consider those situations to be edge cases in the current implementation, and feel raising the exception is a reasonable change at this time.)\r\n\r\nIt also addresses your second point. It's rare (in fact, I cannot think of any time it happens in the current MVC) that either identifiers or additional shared listeners will be added *after* you have triggered the first event. However, it's not uncommon that you'll still be setting up both after you initialize the EM instance. As such, the changes in the latest commit address those issues."}}