[blockly] Support storing timers in shared cache (#1870)

Closes #1858.

Adds support for storing timers in the shared or the private cache (until now, private cache was default).
Timers in the shared cache can be managed by rules/scripts other than the one in which the timer was created.

Also-by: Florian Hotze <florianh_dev@icloud.com>
Signed-off-by: Stefan Höhn <mail@stefanhoehn.com>
pull/1876/head
stefan-hoehn 2023-05-06 23:59:57 +02:00 committed by GitHub
parent cb253f6b4d
commit 8b3ace362f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 79 additions and 27 deletions

View File

@ -53,9 +53,16 @@ export default function defineOHBlocks_Timers (f7, isGraalJs) {
.appendField('after')
this.appendDummyInput()
.appendField(new Blockly.FieldDropdown([['seconds', 'plusSeconds'], ['minutes', 'plusMinutes'], ['hours', 'plusHours'], ['days', 'plusDays'], ['weeks', 'plusWeeks'], ['months', 'plusMonths']]), 'delayUnits')
this.appendValueInput('timerName')
const tn = this.appendValueInput('timerName')
.setCheck(null)
.appendField('do with timer')
if (isGraalJs) {
tn
.appendField('do with')
.appendField(new Blockly.FieldDropdown([['private', 'private'], ['shared', 'shared']]), 'cache')
.appendField('timer')
} else {
tn.appendField('do with timer')
}
this.setColour(0)
this.appendStatementInput('timerCode')
.setCheck(null)
@ -78,10 +85,11 @@ export default function defineOHBlocks_Timers (f7, isGraalJs) {
const timerCode = javascriptGenerator.statementToCode(block, 'timerCode')
if (isGraalJs) {
let code = `if (cache.private.exists(${timerName}) === false || cache.private.get(${timerName}).hasTerminated()) {\n`
code += ` cache.private.put(${timerName}, actions.ScriptExecution.createTimer(${timerName}, time.ZonedDateTime.now().${delayUnits}(${delay}), function () {\n`
const cacheType = getCacheType(this)
let code = `if (cache.${cacheType}.exists(${timerName}) === false || cache.${cacheType}.get(${timerName}).hasTerminated()) {\n`
code += ` cache.${cacheType}.put(${timerName}, actions.ScriptExecution.createTimer(${timerName}, time.ZonedDateTime.now().${delayUnits}(${delay}), function () {\n`
code += timerCode.replace(/^/gm, ' ')
code += ` cache.private.remove(${timerName});\n`
code += ` cache.${cacheType}.remove(${timerName});\n`
code += ' }));\n'
code += '};\n'
return code
@ -110,9 +118,16 @@ export default function defineOHBlocks_Timers (f7, isGraalJs) {
.appendField('after')
this.appendDummyInput()
.appendField(new Blockly.FieldDropdown([['seconds', 'plusSeconds'], ['minutes', 'plusMinutes'], ['hours', 'plusHours'], ['days', 'plusDays'], ['weeks', 'plusWeeks'], ['months', 'plusMonths']]), 'delayUnits')
this.appendValueInput('timerName')
.setCheck('String')
.appendField('do with timer')
const tn = this.appendValueInput('timerName')
.setCheck(null)
if (isGraalJs) {
tn
.appendField('do with')
.appendField(new Blockly.FieldDropdown([['private', 'private'], ['shared', 'shared']]), 'cache')
.appendField('timer')
} else {
tn.appendField('do with timer')
}
this.appendStatementInput('timerCode')
this.appendDummyInput()
.appendField(new Blockly.FieldDropdown([['reschedule', 'reschedule'], ['cancel', 'cancel'], ['do nothing', 'nothing']]), 'retrigger')
@ -138,19 +153,20 @@ export default function defineOHBlocks_Timers (f7, isGraalJs) {
const retrigger = block.getFieldValue('retrigger')
if (isGraalJs) {
let code = `if (cache.private.exists(${timerName}) === false || cache.private.get(${timerName}).hasTerminated()) {\n`
code += ` cache.private.put(${timerName}, actions.ScriptExecution.createTimer(${timerName}, time.ZonedDateTime.now().${delayUnits}(${delay}), function () {\n`
const cacheType = getCacheType(this)
let code = `if (cache.${cacheType}.exists(${timerName}) === false || cache.${cacheType}.get(${timerName}).hasTerminated()) {\n`
code += ` cache.${cacheType}.put(${timerName}, actions.ScriptExecution.createTimer(${timerName}, time.ZonedDateTime.now().${delayUnits}(${delay}), function () {\n`
code += timerCode.replace(/^/gm, ' ')
code += ` cache.private.remove(${timerName});\n`
code += ` cache.${cacheType}.remove(${timerName});\n`
code += ' }));\n'
code += '} else {\n'
switch (retrigger) {
case 'reschedule':
code += ` cache.private.get(${timerName}).reschedule(time.ZonedDateTime.now().${delayUnits}(${delay}));\n`
code += ` cache.${cacheType}.get(${timerName}).reschedule(time.ZonedDateTime.now().${delayUnits}(${delay}));\n`
break
case 'cancel':
code += ` cache.private.remove(${timerName}).cancel();\n`
code += ` cache.${cacheType}.remove(${timerName}).cancel();\n`
break
case 'nothing':
@ -194,8 +210,14 @@ export default function defineOHBlocks_Timers (f7, isGraalJs) {
*/
Blockly.Blocks['oh_timer_isActive'] = {
init: function () {
this.appendDummyInput()
.appendField('timer')
if (isGraalJs) {
this.appendDummyInput()
.appendField(new Blockly.FieldDropdown([['private', 'private'], ['shared', 'shared']]), 'cache')
.appendField('timer')
} else {
this.appendDummyInput()
.appendField('timer')
}
this.appendValueInput('timerName')
.setCheck('String')
this.appendDummyInput()
@ -215,7 +237,8 @@ export default function defineOHBlocks_Timers (f7, isGraalJs) {
javascriptGenerator['oh_timer_isActive'] = function (block) {
const timerName = javascriptGenerator.valueToCode(block, 'timerName', javascriptGenerator.ORDER_ATOMIC)
if (isGraalJs) {
return [`cache.private.exists(${timerName}) && cache.private.get(${timerName}).isActive()`, javascriptGenerator.ORDER_NONE]
const cacheType = getCacheType(this)
return [`cache.${cacheType}.exists(${timerName}) && cache.${cacheType}.get(${timerName}).isActive()`, javascriptGenerator.ORDER_NONE]
} else {
addGlobalTimer()
@ -231,8 +254,14 @@ export default function defineOHBlocks_Timers (f7, isGraalJs) {
*/
Blockly.Blocks['oh_timer_isRunning'] = {
init: function () {
this.appendDummyInput()
.appendField('timer')
if (isGraalJs) {
this.appendDummyInput()
.appendField(new Blockly.FieldDropdown([['private', 'private'], ['shared', 'shared']]), 'cache')
.appendField('timer')
} else {
this.appendDummyInput()
.appendField('timer')
}
this.appendValueInput('timerName')
.setCheck('String')
this.appendDummyInput()
@ -253,7 +282,8 @@ export default function defineOHBlocks_Timers (f7, isGraalJs) {
const timerName = javascriptGenerator.valueToCode(block, 'timerName', javascriptGenerator.ORDER_ATOMIC)
if (isGraalJs) {
// Keep the isRunning block although it doesn't make sense because in GraalJS access to the context is synchronized and therefore it is not possible to run some code the same time a timer is running
return [`cache.private.exists(${timerName}) && cache.private.get(${timerName}).isRunning()`, javascriptGenerator.ORDER_NONE]
const cacheType = getCacheType(this)
return [`cache.${cacheType}.exists(${timerName}) && cache.${cacheType}.get(${timerName}).isRunning()`, javascriptGenerator.ORDER_NONE]
} else {
addGlobalTimer()
@ -269,8 +299,15 @@ export default function defineOHBlocks_Timers (f7, isGraalJs) {
*/
Blockly.Blocks['oh_timer_hasTerminated'] = {
init: function () {
this.appendDummyInput()
.appendField('timer')
if (isGraalJs) {
this.appendDummyInput()
.appendField(new Blockly.FieldDropdown([['private', 'private'], ['shared', 'shared']]), 'cache')
.appendField('timer')
} else {
this.appendDummyInput()
.appendField('timer')
}
this.appendValueInput('timerName')
.setCheck('String')
this.appendDummyInput()
@ -290,7 +327,8 @@ export default function defineOHBlocks_Timers (f7, isGraalJs) {
javascriptGenerator['oh_timer_hasTerminated'] = function (block) {
const timerName = javascriptGenerator.valueToCode(block, 'timerName', javascriptGenerator.ORDER_ATOMIC)
if (isGraalJs) {
return [`cache.private.exists(${timerName}) && cache.private.get(${timerName}).hasTerminated()`, javascriptGenerator.ORDER_NONE]
const cacheType = getCacheType(this)
return [`cache.${cacheType}.exists(${timerName}) && cache.${cacheType}.get(${timerName}).hasTerminated()`, javascriptGenerator.ORDER_NONE]
} else {
addGlobalTimer()
@ -306,9 +344,13 @@ export default function defineOHBlocks_Timers (f7, isGraalJs) {
*/
Blockly.Blocks['oh_timer_cancel'] = {
init: function () {
this.appendValueInput('timerName')
let tn = this.appendValueInput('timerName')
.setCheck('String')
.appendField('cancel timer')
.appendField('cancel')
if (isGraalJs) {
tn.appendField(new Blockly.FieldDropdown([['private', 'private'], ['shared', 'shared']]), 'cache')
}
this.setPreviousStatement(true, null)
this.setNextStatement(true, null)
this.setColour(0)
@ -325,7 +367,8 @@ export default function defineOHBlocks_Timers (f7, isGraalJs) {
javascriptGenerator['oh_timer_cancel'] = function (block) {
const timerName = javascriptGenerator.valueToCode(block, 'timerName', javascriptGenerator.ORDER_ATOMIC)
if (isGraalJs) {
return `if (cache.private.exists(${timerName})) { cache.private.remove(${timerName}).cancel(); };\n`
const cacheType = getCacheType(this)
return `if (cache.${cacheType}.exists(${timerName})) { cache.${cacheType}.remove(${timerName}).cancel(); };\n`
} else {
addGlobalTimer()
let code = `if (typeof this.timers[${timerName}] !== 'undefined') {\n`
@ -348,9 +391,13 @@ export default function defineOHBlocks_Timers (f7, isGraalJs) {
.setCheck('Number')
this.appendDummyInput()
.appendField(new Blockly.FieldDropdown([['seconds', 'plusSeconds'], ['minutes', 'plusMinutes'], ['hours', 'plusHours'], ['days', 'plusDays'], ['weeks', 'plusWeeks'], ['months', 'plusMonths']]), 'delayUnits')
this.appendValueInput('timerName')
let tn = this.appendValueInput('timerName')
.setCheck('String')
.appendField('reschedule')
if (isGraalJs) {
tn.appendField(new Blockly.FieldDropdown([['private', 'private'], ['shared', 'shared']]), 'cache')
}
this.setInputsInline(true)
this.setPreviousStatement(true, null)
this.setNextStatement(true, null)
@ -370,7 +417,8 @@ export default function defineOHBlocks_Timers (f7, isGraalJs) {
const delay = javascriptGenerator.valueToCode(block, 'delay', javascriptGenerator.ORDER_ATOMIC)
const timerName = javascriptGenerator.valueToCode(block, 'timerName', javascriptGenerator.ORDER_ATOMIC)
if (isGraalJs) {
return `if (cache.private.exists(${timerName})) { cache.private.get(${timerName}).reschedule(time.ZonedDateTime.now().${delayUnits}(${delay})); };\n`
const cacheType = getCacheType(this)
return `if (cache.${cacheType}.exists(${timerName})) { cache.${cacheType}.get(${timerName}).reschedule(time.ZonedDateTime.now().${delayUnits}(${delay})); };\n`
} else {
const zdt = addZonedDateTime()
addGlobalTimer()
@ -396,4 +444,8 @@ export default function defineOHBlocks_Timers (f7, isGraalJs) {
let globaltimervars = 'if (typeof this.timers === \'undefined\') {\n this.timers = [];\n}'
javascriptGenerator.provideFunction_('globaltimervars', [globaltimervars])
}
function getCacheType (block) {
return (block.getField('cache')) ? block.getFieldValue('cache') : 'private'
}
}