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 snap cronjobs #651
Add snap cronjobs #651
Conversation
72aebf0
to
93729fe
Compare
c1335f9
to
a6ef418
Compare
3a1903c
to
03d308d
Compare
6296ecb
to
c1425b1
Compare
b813338
to
2bef716
Compare
Here is the PR that will follow up this one (when merged/released) in order to complete the integration with MetaMask (Flask) Extension: MetaMask/metamask-extension#16239 |
After some research I found out that using of a CRON syntax might still be the best (in my opinion). For many scheduling requirements and cases it's highly possible for a developer to come across the CRON standard. Here are some examples of the CRON expressions and their meaning: There were some ideas for splitting parameters into the simpler format by its meaning, but it seems if the original format is kept, it's more powerful and meaningful for the one who already knows to use it. Since users of this feature would be developers, I do not think they're going to have much of a trouble with this. If we continue to use pure CRON way of doing the schedule we will have less to maintain and test in the future (avoid potential bugs as well). That way we have a feature out of the box that works well, is widely used and specified which means less concern about its functionality now and later. |
packages/utils/src/cronjob.test.ts
Outdated
it('successfully parses cronjob expression that is provided as an object', () => { | ||
const cronjobExpression = { | ||
minute: '*', | ||
hour: '*', | ||
dayOfMonth: '*', | ||
month: '*', | ||
dayOfWeek: '*', | ||
}; | ||
expect(() => parseCronExpression(cronjobExpression)).not.toThrow(); | ||
}); | ||
|
||
it('successfully parses cronjob expression that is provided as a string', () => { | ||
const cronjobExpression = '* * * * *'; | ||
expect(() => parseCronExpression(cronjobExpression)).not.toThrow(); | ||
}); |
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.
Rather than asserting that these don't throw, maybe check that the return value is correct.
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.
Maybe add a few different tests to ensure that the object properties are put in the right place too.
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've removed throw assertion and added couple of things that check the properties of the object returned which is from an external library cron-parser
. These methods will only work if the parsing is successful, otherwise it will throw an error which would break the test. I hope that's ok now.
b7b33ce
to
cbf0e5b
Compare
2697cd5
to
e462748
Compare
this.updateJobLastRunState(job.id, Date.now()); | ||
this.#messenger.call('SnapController:handleRequest', { | ||
snapId: job.snapId, | ||
origin: '', |
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.
Can we remove this? Or should it maybe be something like 'cron'
?
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.
We currently use empty string for transaction insights as well - It is currently required to have a value by the snap executor. We should perhaps figure out a way to only require it for certain handlers? Out of scope for this PR imo.
Fix build error Fix test Add part of cronjob caveat implementation Register cronjob caveat Add more caveat validations and tests Fix imports after rebase Fix conflict-merge issue after rebase Fix validation functions build issue Add configuration for caveat mapper Update CronjobService and add tests Add some more unit tests for CronjobService Update CronjobService to become CronjobController Add some refactoring and new features for the CronjobController Refactor and clean up More refactor and tests Add missing docstring Improve test coverage for CronjobController Improve test coverage for utils Improve test coverage for CronjobController Fix execution-environments commands Fix jest threshold after rebase Refactor directory structure Add support for object-like cron expressions Fix and rework a couple of things for structural expressions Add some refactoring & test improvements Code refactoring Add way to unregister all snaps on controller destroy method call Change timers and snapIds to be private with getters Remove eslint ignore instructions where they are not needed anymore Redesign the test with daily timeout check (schedule skip) Refactor unit tests
e462748
to
b5ab1ba
Compare
Fixes: #353
Cronjob feature will add new possibility to periodically run specific Snap RPC methods. Cronjob feature is implemented as a new permission with caveats that are used to specify job methods, parameters and schedule using CRON syntax.
For interpretation of a CRON syntax, cron-parser library is added: https://www.npmjs.com/package/cron-parser
cron-parser
is added as the dependency to thesnap-utils
andsnap-controllers
packages.New caveat specification is added under the
snap-utils
package insidecronjob.ts
.Cronjob feature's core is implemented as the Controller inside CronjobController.ts which is part of
snap-controllers
package.CronjobController is supposed to be registered in the extension within MetaMask Controller.
Example Cronjob Specification caveat:
Cronjob Controller will on its start subscribe to certain Snap events and check for possible cronjobs in order to register or remove them from schedule.
CronjobController will listen for the following events:
SnapController:snapInstalled
- will add cronjobs and schedule for snapSnapController:snapRemoved
- will remove all added/scheduled cronjobs for snapSnapController:snapUpdated
- will remove registered jobs and scheduled jobs and add them again according to the newest specification