Macro Queuing: To Execute Synchronously

Quidn

Passionate Member


● Background​


Unlike general programming languages, on MacroDroid not only global variables but also local variables could be changed by another simultanous running(macro instance), so their is no way to protect or guarantee consistency of variables.

Action blocks have per-instance "Working Variables", but some core actions including "Wait Until Trigger" doesn't supported in action blocks(In opposite, "Exit" action is supported only in action Blocks).

Therefore, variables couldn't be trusted except for if triggers are guaranteed to be never fire before its previous running is completed.

Multiple simultanous runnings(macro instances) problem is not just limited about "to protect variables" and may lead to various unintended results.




● Multiple running easily happens​


Currently, macros start to run when invoked whether or not it's already running(previous running wasn't finished yet).

Constraint "Macro(s) (Not) Invoked Recently" may help to prevent invoking. But a recently invoked macro may needs to be invoked again if previous running was finished in quick. Moreover, it couldn't prevent multiple runnings(macro instances) in any way if previous running is delaying than average.




● Preventing multiple running never easy​


However, preventing unwanted multiple simultanous runnings(macro instances) perfectly is not an easy challenge.

- Approach: Flagging-in-variable method​


This mainly has two problems.​
Firstly, dismissing(revert to initial value) may fail due to various reasons including system reboot or killed MacroDroid by system or so on. The flag needs to be constantly updated and keep been monitored from another watchdog macro, and even with these efforts it can't be perfect.​
Secondly, to detect variable changing by "Wain Until Trigger" is not works as expected. This resumes macro by unknown reasons even if variable wasn't changed(I reported yesterday to @MacroDroidDev).​

- Approach: Using action blocks method​


As I mentioned above, at least action blocks have working variables which are protected from outside and guaranteed to be consistent in a single run, but this also failed mainly because of some core actions are missing in action blocks as I mentioned above too.​
Additionally, handling complicated dictionary/array and "magic text" in them as input variable results not as expected. And futhermore their is only "Macro(s) (Not) Invoked Recently" constraint and no "Action Block(s) (Not) Invoked Recently" one.​




● Suggested features as solution​


- New Option: Queuing(Wait until previous running finishes)​

  • If this macro is running currently, then push this invocation to the queue list of ((defined || default)) priority.
    This global option is inherits to all macros, and overrides by per-macro and/or per-category setting.

- New Constraint: "Macro(s) or Action Block(s) is/are (Not) Running"​

  • Returns ((true || false)) whether ((all || some)) of the ((macros? || action blocks?)) is/are ((running currently)).

- New Trigger: "Macro(s) or Action Block(s) is/are Finished"​

  • When a trigger itself is finalizing its initialization(i.e., just after starting up):
    - Fires immediately if ((all || some)) of the ((macros? || action blocks?)) is/are ((not running currently)).
  • After initialization(i.e., noemally):
    - Fires when ((all || some)) of the ((macros? || action blocks?)) is/are ((just finished || idle)).
  • This makes possible to being reliable sequential processing and polling.

- "Working Variable" in Macros​

  • Per-instance(single running) variables which behaviour identical as working variables in action blocks.



 
Top