Hello! I have an interesting infrequent polling use case (~once an hour) that I’d like your advise on.
I’ll preface this with saying that I’ve read some other community threads and the recommended approach on infrequent polling implementation in the Typescript samples repository. That being said, I’m not sure the strategy of “implement polling within an activity, and let that activity fail benignly, retry, etc.” fits my use case. I could be wrong though.
So: our use case.
We have a timer that waits X amount of time. If the time passes before an isCondition is true, we want to execute some business logic (a reminder) and continue waiting for isCondition to become true.
isCondition can become true in two different ways:
Listening to a signal from a client, receiving that signal with an update handler, and, along with some other business logic, setting isCondition to true. This is implemented without any issue.
Polling an external service to see if a condition is true. If the results from this polling action returns true, we also want to set isCondition to true. This is where I’m not sure what the best pattern is to implement this business logic. Currently, I have:
An activity that pings the external service and sees if a condition is true
An async function that is called within the workflow itself, runs in the background, and implements a polling loop (using Temporal’s sleep functionality). I (think) I needed to do this so that the polling loop could directly affect the await condition(() => isCondition condition within the workflow itself.
Would this work? Am I missing anything about why this wouldn’t work? Is this a huge anti pattern, and can anyone think of a better way to implement this business logic, as I know this isn’t the recommended infrequent polling architecture discussed in other threads
Where “myPollingActivity” is implemented as suggested in the infrequent polling sample repository?
My biggest concern with the above is not really understanding how/when that T/F callback is invoked, and whether or not calling a polling activity WITHIN that callback is going to work as intended + expected.
That makes sense, and I’d prefer to set up infrequent polls with an activity!
However, would the code in my follow up comment work? Would I get the behavior I’m expecting if I await for my polling activity within the true/false condition callback?
Hmm I see what you mean. But if I await the polling activities separately, doesn’t that mean I wouldn’t be able to use the result from the polling activity to interrupt/stop the condition call? I’d like the result of the polling activity to “short-circuit” the condition call before the “timeUntilReminder” is hit.
Hi Maxim, follow up question. Ran into some issues when actually implementing this. As you can see in the screen shots below, leaving the call to the polling activity like isPollingResponseTrue = pollingActivityHere() (trying to get it to run in the background, parallel to the await condition call) causes the following typing issues:
I included some context to give you an idea of what the business logic I’m trying to implement.
Obviously, these typing issues could be resolved by changing the call to the polling activity to const isBillPlatformInvoiceStatusPaid = await pollInvoicePaymentStatus(billPlatformInvoiceId, invoiceNumber), but at that point, I don’t think the call to the polling activity runs in parallel to the condition? Unless, when the polling activity fails with a benign application failure, it still allows for the Temporal workflow to check the condition?
Interestingly, awaiting for the polling activity seemed to work (at least in a Temporal time skipping testing environment)! I was running into OOM errors (deployed on Render) when trying to implement it with the background thread method.