-
Notifications
You must be signed in to change notification settings - Fork 124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add pipes & hooks wildcard event #1305
Conversation
Codecov Report
@@ Coverage Diff @@
## 1-dev #1305 +/- ##
==========================================
+ Coverage 93.84% 93.85% +<.01%
==========================================
Files 98 98
Lines 6884 6895 +11
==========================================
+ Hits 6460 6471 +11
Misses 424 424
Continue to review full report at Codecov.
|
@@ -831,8 +831,15 @@ class PluginsManager { | |||
* @returns {Promise} | |||
*/ | |||
function triggerHooks(emitter, event, data) { | |||
const wildcardEvents = getWildcardEvents(event) | |||
// filter events like 'foo:*' because EventEmitter2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be simpler (and better) to completely get rid of EventEmitter2, since we're only using it for wildcards (this should be a light change since EventEmitter2 has the same interface than the native EventEmitter).
And instead manage wildcards ourselves entirely, because that kind of exception handling is a bit costly performances wide, and events triggering is a critical part of Kuzzle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, this code is unsafe because getWildcardEvents
can return null.
} | ||
|
||
return null; | ||
const wildcardEvents = ['*:*', `${scope}:*`]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I disagree with the event *:*
because:
- we can have an arbitrary number of separators (for instance we have a core:auth:strategyAdded event)
- I think that
*
would be much simpler
const wildcardEvents = ['*:*', `${scope}:*`]; | |
const wildcardEvents = ['*', `${scope}:*`]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we discuss with @thomasarbona, it could be nice to handle wildcard
pattern directly as regex. So we do not need to define rules for patterns and use regex syntax.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Veto: regexp are slow, and the number and frequency of events triggered make them a critical part of the code.
Why do we need regular expressions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right I didn't get that this action appends at funnel level. Ignore my previous comment 😅
if (indexDelimiter !== 1) { | ||
return event.substring(0, indexDelimiter+1) + '*'; | ||
function getWildcardEvents (event) { | ||
const [scope, name] = event.split(':'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This leaves events with 3 or more separator out of the picture.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ugly but I think it can help you to figure out how to handle more than 3 separators:
const [scope, name] = event.split(':'); | |
const rawEvents = event.split(':'); | |
const [name] = rawEvents.pop(); | |
const [scope] = rawEvents; |
|
||
if (preparedHooks) { | ||
preparedHooks.forEach(hook => { | ||
hook(data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure but what if the hook function provided by the developer throw an error ? Can't we have a unhandled rejection here ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
more importantly: this bypasses Kuzzle as an event emitter, which is not the purpose of hooks
if (preparedHooks) { | ||
preparedHooks.forEach(hook => { | ||
try { | ||
hook(data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is still broken: plugins aren't the only objects using events
why don't you let the kuzzle object, which inherits from eventemitter, emit that event?
1234067
to
3f9331f
Compare
const delimIndex = event.lastIndexOf(':'); | ||
|
||
if (delimIndex === -1) { | ||
return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to prevent breaking code using the return value of this function without first checking that it didn't return null:
return null; | |
return []; |
} | ||
}]; | ||
|
||
pluginsManager.run() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that promise must be returned, otherwise the test isn't awaited and it always passes
} | ||
}]; | ||
|
||
pluginsManager.run() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
} | ||
}]; | ||
|
||
pluginsManager.run() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
SonarQube analysis reported 1 issue Note: The following issues were found on lines that were not modified in the pull request. Because these issues can't be reported as line comments, they are summarized here:
|
- add documentation for wildcard events (kuzzleio/kuzzle#1305) ### How should this be manually tested? - `npm install && npm run dev` - visit http://localhost:8080/core/1/plugins/plugins/events/wildcard-events/ ### Boyscout - [ @xbill82 ] Disabled C++ and Java tests from local execution - fix pages sorting (page with an order set to 0 isn't classified first)
Release 1.8.0 Bug fixes [ #1311 ] Fix promise leaks (scottinet) [ #1298 ] Fix disabled protocol initialization (Aschen) [ #1297 ] Fix timeouts on plugin action returing the request (benoitvidis) [ #1288 ] Fix an error when trying a non-partial bulk update (scottinet) [ #1286 ] Allows bulk inserts on aliases (benoitvidis) [ #1282 ] Scan keys on redis cluster (benoitvidis) [ #1279 ] Users must be authenticated to use auth:logout (scottinet) New features [ #1315 ] Add the new Vault module to handle encrypted application secrets (Aschen) [ #1302 ] Add write and mWrite (Aschen) [ #1305 ] Add pipes & hooks wildcard event (thomasarbona) Enhancements [ #1318 ] Add a maximum ttl to auth:login (benoitvidis) [ #1301 ] Upgrade the WebSocket libraries (scottinet) [ #1308 ] Events triggering refactor (scottinet) [ #1300 ] Collection specifications methods cloisoned to a collection (thomasarbona) [ #1295 ] Improve validation error messages (benoitvidis) [ #1292 ] Throw an error when the realtime controller is invoked by plugin developers (benoitvidis) [ #1257 ] Add ability to define mapping policy for new fields (Aschen) [ #1291 ] Fix --help on subcommands (Yoann-Abbes) [ #1289 ] Handle ping/pong packets (scottinet) [ #1273 ] Fix incomplete access logs (scottinet) Others [ #1317 ] Add ps dependency to plugin-dev Docker image for pm2 (benoitvidis) [ #1312 ] Check that .kuzzlerc.sample is well-formed (scottinet) [ #1299 ] Add Kuzzle Nightly & Redis 3 and 4 test (alexandrebouthinon)
What does this PR do ?
'foo:*'
'foo:after*'
'foo:before*'
How should this be manually tested?