I use semaphore locks AND I often pause macros. So at a time there could be multiple macros paused or waiting to start executing due to semaphore lock.
Suppose a macro is executing (rest others either paused or locked out due to semaphore) and something goes wrong. May be some file doesn't exist in the folder or click action executed before webpage loaded or any such thing where I need to manually cancel the macro.
I generally use 'cancel all the macros' using a keyboard shortcut. But that makes me loose all those macros as well that were paused or waiting for the execution due to semaphore lock. So then I have to remember and search for the macros that were supposed to get executed next. And then execute them manually.
Is there a way to avoid this?
[P.S. - Just bumped into this Can %ExecutingInstance% token be used here? I used 'display text' action to display what executing instance look like. It is a string of characters and doesn't display the name of macro. If this token can be used here, how to use it? Is knowing apple script a must here? Could not make the sense of the answers here]
@fluid_eye -- treat each time you have to manually cancel as a chance to improve things. That might be the workflow, getting things in order before the next step is taken. It might be logic -- why have you got so many interdependencies and locks, can you serialise operations with synchronous sub-macros/routines. Or it might be more automated cancellation, using timeouts or "If not whatever then Cancel this macro".
Whenever possible, cancelling macros should be both considered and deliberate so that you don't leave your machine in an "unknown" state -- whether that be folders where some files have been changed but others not, apps in weird situations (dialog box up?) that then block other macros, global variables (if you use them) having unexpected values, etc.
Also ensure there are appropriate timeouts on actions. For the most part, Keyboard Maestro defaults the timeout to 99 hours (essentially infinite), but you should consider and Pause Until or similar actions and set appropriate timeouts.
Main reason is I have created a pop up that asks me whether I want to execute the macro or pause it for some time (you can look at it as a snooze for reminder). and I often find myself busy with something and I end up pausing multiple such macros.
Other macros do not require me to carry out any task from my to-do list (these macros are automated. For example, periodically deleting a file) but they are locked out due to semaphore lock as earlier macros (reminders) did not execute.
All these macros are time based. Some of them trigger at specific time of the day or some of them trigger after specific duration since last execution.
I have "Macro A", a reminder to do "Job A" that I snooze if I'm already busy. As the snooze ends, it asks me with the same prompt (if I want to execute now or I'd like to snooze again). At this point, if I am free, I hit execute.
To give you more details, when I hit execute for 'Macro A", it starts and keep on executing until the specified duration completes. Typically, what "Macro A" does is, it simply executes pause action for specified time. This specified time could be 10 mins or 15 mins etc. This time is what I had decided to dedicate for "Job A". During the specified time, I don't want any pop ups from any other macros or I don't want to run any other macros that require user action. After the specified time is over, macro is complete and semaphore lock is unlocked automatically. Allowing next macro to throw its own prompt about whether to execute or to snooze.
Macro B does not require me to execute any task but it does give the same prompt as to execute or to snooze. If I hit execute, then it would go ahead and delete the file. And I want to 'hold' the "Macro B" until "Macro A" finishes.
I'm obviously missing something -- why is "B" a separate macro from "A"? This would appear to be a sequential operation:
Reminder to do something
Eventually do something
Do whatever "B" does
Unless you also have "C", "D", etc that you want to be blocked by "A" but not a pending "B"? In which case, consider using a final action in "A" that "Executes a Macro... B" and setting that action to "Asynchronously" so that "A" completes even while "B" is executing.
I think that what I'm trying (badly!) to find out is "Why are you executing "B" and 'holding' it rather than waiting until you are ready then executing it?" (either as actions within, or as a separate macro triggered by, "A").
There are multiple Macros like 'Macro A' and there are multiple macros like 'Macro B'. All macros are independent of each other.
It is possible that 'Macro A' triggers everyday at 1 PM. And Macro B triggers every 18 hours. 18 hours are counted from the point in time when Macro B is FINISHED executing.
I want to manually allow 'Macro B' to execute. I merely want it to TRIGGER automatically. And then when I hit execute, it should go ahead and execute. And Macro B could be of the type that takes away focus (keystrokes and mouse clicks) so that is also another reason why I can't run it simultaneously with 'Macro A.'
Also, to give you additional information, macros like 'Macro A' that trigger at specific time of the day are generally triggered from Apple calendar events (rather than KM feature like cron trigger). As I like have visual sense of what tasks do I have at specific date so that I can avoid overlapping my other plans (For example, offline plans).
So "quite complicated" would be an understatement...
If you've untangled them as much as you can, you're back back to the original problem of cancelling as few as possible any time you want to clear a "blockage". So concentrate on error-checking and timeouts so your macros can cancel themselves when they have a problem, rather you you having to hit the panic button. That also lets you do any necessary cleanup for each macro as part of the cancellation process.
As well as timeouts, have a look at the Try/Catch action and the ActionResult token -- those, along with If Then Else, will help you handle a huge range of errors within the macro itself.
Broadly speaking, there's two approaches to catching errors:
Look for a wrong thing happening
Look for the right thing not happening
...and you'll find yourself using each, even both, at different points in your macros.
You misunderstand -- you use actions to ensure correct state (either that something has happened or things are ready for something to happen) and handle the errors appropriately. To use your two examples:
Depending on what you are doing you can explicitly test for its presence with "If... file exists" and cancel if it doesn't, "Pause until... file exists" if you know it'll be there eventually and include a timeout just in case it never appears, "Try/Catch" the action you are performing so that if the operation fails because the file isn't there you can clean up and cancel...
So you "Pause until..." the webpage has loaded or, for "multi-loading" pages, "Pause until..." a certain condition is met such as an image/button on the page has loaded. Again, you can use a timeout for those times your network or the server is down to handle the "it never loads" situations.
There's no need to think of all the possible errors before you start using your macro -- each time you have to manually cancel it, go back to the macro and add the appropriate error handling. The next-best thing to a totally robust macro is one that fails gracefully, maybe with a notification and ideally leaving your system in a known "good" state without you having to intervene.