Hi Rich,
I hope I didn’t offend you but I am really trying to find an MVP (minimal viable product) to get this whole functionality delivered as soon as possible and then learn and extend from it.
Having slept over it I think the whole became unclear because I was mixing up the simple timer and the complex timer functionality. The simple timer was meant to have a really simple version of the timer and which would work for 80% of all tasks. Actually this didn’t have the else-branch but I may want to move this there while the more flexible shouldn’t have one. Note that the simple one by intention doesn’t even allow you to provide a name.
simple timer
if (this.timers['simpleTimer'] === null) {
this.timers['simpleTimer'] = scriptExecution.createTimer(zonedDateTime.now().plusSeconds(10), function(){
logger.error('abc')
})
} else {
this.timers['simpleTimer'].reschedule(zonedDateTime.now().plusSeconds(2))
}
Complex timer functionality
However, we have all the other methods of a timer available individually with which we probably can do most of you want to achieve.
Note that it does now allow yet to use dynamic names as I have no clue how to do that as blockly uses static code generation, so the name in the below case are always named “richEvent”. If I ever find out
Let me go through each of your examples and try to reproduce these.
1st example: this.tm.check("richEvent", "5m", runme);
Call runme after five minutes.
If called and the timer exists cancel the timer
producing
function runme() {
logger.info('abc')
}
if (this.timers['richEvent'] === null) {
this.timers['richEvent'] = scriptExecution.createTimer(zonedDateTime.now().plusMinutes(5), function(){
runme();
})
}
2nd example: this.tm.check(“richEvent”, “5m”, runme, true);`
Call runme after five minutes. If called and the timer exists, reschedule it for five minutes
- I changed the time to 5 seconds to allow easier testing
- Note that the rescheduling happens over and over again. If you didn’t want that put the rescheduling to the upper block
- I added a manual cancelation possibility via a switch to have a chance to “kill” the rescheduling timer.
function runme() {
logger.info('abc')
this.timers['richEvent'].reschedule(zonedDateTime.now().plusSeconds(2))
}
if (itemRegistry.getItem('cancelRichTimer').getState() == 'OFF') {
logger.info('canceling Timer')
if (this.timers['richEvent'] !== null) { this.timers['richEvent'].cancel()}
} else {
if (this.timers['richEvent'] === null) {
this.timers['richEvent'] = scriptExecution.createTimer(zonedDateTime.now().plusSeconds(2), function(){
runme();
})
}
}
3rd example:
this.tm.check(event.itemName, “1m”, null, false, flapping);
Create a timer for five minutes. Do nothing if the timer expires. If called again when the timer already exists call flapping. Do not reschedule
- the empty run bracket may look weird but it actually creates a noop-function like in your code
function flapping() {
logger.info('flapping ')
}
logger.error('running the rule')
if ((this.timers['richEvent'] && this.timers['richEvent'].isActive()) == true) {
flapping();
}
if (this.timers['richEvent'] === null) {
this.timers['richEvent'] = scriptExecution.createTimer(zonedDateTime.now().plusMinutes(1), function(){
})
}
4th example:
this.tm.check(“richEvent”, “5m”, null, true, flapping);
Create a timer for five minutes. Do nothing if the timer expires. If called again when the timer already exists, call flapping. Reschedule the timer for five minutes.
- Reschedule the timer for five minutes: What should happen there? If I get your code right it does reschedule the rule that doesn’t do anything
function flapping() {
logger.info('flapping')
}
if ((this.timers['richEvent'] && this.timers['richEvent'].isActive()) == true) {
flapping();
this.timers['richEvent'].reschedule(zonedDateTime.now().plusMinutes(5))
}
if (this.timers['richEvent'] === null) {
this.timers['richEvent'] = scriptExecution.createTimer(zonedDateTime.now().plusMinutes(5), function(){
})
}
5th example:
this.tm.check(event.itemName, “5m”, runme, false, flapping);
Create a timer for five minutes. Call runme if the timer expires. If called again when the timer already exists, call flapping. The timer will be cancelled and runme will not be called.
function runme() {
logger.info('runme was called')
}
function flapping() {
logger.info('flapping')
}
if ((this.timers['richEvent'] && this.timers['richEvent'].isActive()) == true) {
flapping();
if (this.timers['richEvent'] !== null) { this.timers['richEvent'].cancel()}
}
if (this.timers['richEvent'] === null) {
this.timers['richEvent'] = scriptExecution.createTimer(zonedDateTime.now().plusMinutes(5), function(){
runme();
})
}
6th example:
this.tm.check(event.itemName, “5m”, runme, true, flapping);
Create a timer for five minutes. Call runme if the timer expires. If called again when the timer already exists, call flapping. Reschedule the timer for five minutes.
function runme() {
logger.info('runme was called')
}
function flapping() {
logger.info('flapping')
}
if ((this.timers['richEvent'] && this.timers['richEvent'].isActive()) == true) {
flapping();
this.timers['richEvent'].reschedule(zonedDateTime.now().plusSeconds(5))
}
if (this.timers['richEvent'] === null) {
this.timers['richEvent'] = scriptExecution.createTimer(zonedDateTime.now().plusMinutes(5), function(){
runme();
})
}
Summary
I think we can achieve all of these examples you provided. I hope that this us both a good feeling to move forward
Final note:
In theses case I took out the automatically generated else branch of rescheduling which we probably should for the non-simple named timer.
For the simple one (at least for the MVP I would add the automatic rescheduling and maybe in a later version we can add another block that would allow options for retriggering.
I have applied all above mentioned changes. Also, from the fact showing that the above is possible with the blocks, I could imagine that it should be possible to create a block similar to your API that allows to create the code that is similar to what the individual blocks do. If you would provide an idea how the block would look like (rather big I think) I could start approaching it as the next step.