Can one macro pause in the middle of its execution for another macro to trigger and finish?

I want to download instagram reels and upload to telegram group. During this process, the time it takes to download the instagram reel differs. I can add pause action to wait for the download to finish but I also end up pausing my macro for unnecessarily prolonged time for those rare case scenarios where it takes more time to download. Hence I decided to execute the process of uploading separately (Let’s call it Macro C). Macro C would trigger when the file is downloaded to the specified folder (ignoring partial files).

But here’s the problem: I have Macro A that is designed to execute a set of actions (Here, set of actions are downloading and uploading. Let’s call this set of actions as Macro B, which would be fed as a subroutine to Macro A) for each instagram reel URL in a list. And Macro A would finish only when it exhausts all the URLs from the list. (Here's the example of Macro A.)

So now I have Macro C, that triggers independent of Macro A. So how do we make the Macro A pause until Macro C triggers and finishes?

My guess would be to use a Semaphore action (wiki action:Semaphore Lock [Keyboard Maestro Wiki]).

Put a Semaphore Lock action at the very start of both Macro A and Macro C. You’ll have to provide a name for the semaphore so call them both something like “Macro C in process”.

Now when Macro C starts it will lock the semaphore so that when Macro A starts it will be prevented from running until Macro C finishes (at which time the semaphore will be unlocked automatically).

If you need examples, search this forum for “semaphore”. Hopefully that’s a help to you.

Yes thankfully I know how semaphore locks work. So I would not need that.

Certainly!

I am not sure if it will work. Whereas if we put semaphore lock at the beginning of the actions steps of Macro A that should be executed AFTER Macro C, that would work (where Macro C beginning would have the identical semaphore lock action with same semaphore lock name).

I just need to pause Macro A for the duration that is required for Macro C to trigger. Once it is triggered, it won't even need to wait for that pause action of Macro A to end. So yes, even though it is not a full proof solution, it certainly is a good workaround. and I am going to use it now :+1:
Thank you

Oops - sorry, I got a bit confused. I misunderstood and thought Macro C was already triggered and Macro A was then triggered and should wait.

How about this then: the last action in C (so it will have done all its work by then) should be an Execute a Macro action to execute Macro A but, and this is important, the action should be set to “asynchronous”, to allow C to finish immediately. You would not then require a semaphore.

The one question remaining is this: you’ve never said what triggers Macro A. So currently I don’t understand why A has already been triggered before C since A’s purpose seems to be to process the result of Macro C having run?

Semaphores don't have to go at the beginning of a macro. Work out what stage Macro C will conflict with Macro A, and use it there. For example, it sounds like A has a loop -- you could set it inside the loop at the beginning and release at the end. Macro C will trigger and then queue if the if A is in the middle of the loop, then start continue execution when A goes back to the beginning of the loop, but now A has to pause until C has finished.

(I haven't tried a single, mutual, semaphore like that -- you may have to use two.)

That could get a bit confusing though. So the simpler method is a "Pause until..." at the appropriate point in Macro A, testing a Global variable that Macro C sets to one value when it starts and another just before it exits.

1 Like

You missed this point

And you're right using semaphore lock here is kind of cumbersome. (although I tried it successfully)

Using a variable as a switch is a great idea.

Thanks

@tiffle, it is hard for me but i hope you don't mind me marking @Nige_S answer as a solution, where I already had marked your answer as a solution. We gotta surface what's better among the responses for all those who'd bump into this thread years to come.

It would be manually triggered.

Unless Macro A fetch the URL from text file, the instagram reel won't be downloaded. And unless reel is downloaded in the specified folder, Macro C won't trigger (Macro C uploads the reel to telegram.)

No, I didn't. Semaphores can be scoped as tightly as a single action, and released after that action completes. If you want to pause A while some bit of C completes but have them running executing concurrently outside of that conflicting block it's certainly doable -- how will depend on the actual macros. Example:

Semaphore Test Macros.kmmacros (7.1 KB)

Images

and

...where if you trigger A manually then wait a second and trigger C, you'll get "mingled" sounds as they run concurrently, then just "beep"s while C locks out A, then mingled sounds again.

The best way to do this really does depend on the specifics of the workflow. But the simplest way to "Pause while another macro is running" is a global variable flag.

What I don't understand though is, if A downloads a file and C then processes and uploads it -- why not use the completion of the download part of A (or B, if that's an async sub) to trigger C rather than (what sounds to be) a watched folder trigger?

Parallelising operations like this often seems to be a good, efficient, way of doing things -- but the overhead and complexity involved, including that to make sure everything completes error-free and without conflict, can make simple serialisation a better bet on many occasions.

I gotta check this out.

I don't know if there is a way to tell KM that download part of Macro A is finished definitively. Because I checked 'pause until' action and it only has an option to pause until the file is added to the folder. But the added file could be a partial file till the download completes.

Only you can say definitively if you’ve reached a solution.

1 Like

That totally depends on how you do the download. KM's "Get URL" action will wait until the download is complete before going to the next action in the macro, curl in an "Execute Shell Script" can do similar, KM's "watch folder and wait until complete" trigger relies on the downloading agent doing a renaming shuffle that KM knows about (eg mydownload.inprogress to mydownload.zip on completion), you can do repeated folder size checks until the result remains unchanged, lsof in an "Execute Shell Script" can tell you when a file is no longer open for writing, there may be a "Cancel Download" UI element you can test for or when that informs you of completion...

There's no one true way because there's no one true method for downloading, so you'll have to find what works most effectively for you and your workflow.

And yes, it may be that you've already found the best way of doing it!

It is kind of crunch time this entire year for me so it is important for me to put minimum time in developing macros.

There may be better solutions out there but as long as my current macro is error free and works, I would rather keep using it.

None of the things you described seem to be applicable in my use case, because downloading happens completely based on recorded mouse clicks and keystrokes – and I don't give access to KM to detect elements visually on screen.

1 Like

I'm very much a pragmatic problem solver -- if it's working for you, go with it! But do keep an eye out for possible improvements. While many services have a business model that relies on keeping your eyeballs on their site, some do see the light and and provide APIs that make automation easier.

2 Likes