Sleep with Cancel

Hi All,

I’m trying to write a workflow that has a sleep that can be cancelled. The thought process was I’d use a Selector, and add a Receive handler for a channel where I’d send cancel requests. Then I’d add a Default handler with a workflow.Sleep call in it. My understanding is that this will only ever run the Default handler which would block selector.Select until the end of the timeout, and that the receive handler would be blocked until the end of this call also. Am I going about this the wrong way? A thought I had was that I’d only sleep for a short interval, check if it’s waited the entire time OR the channel received a value and continue on. The only downside to this is that I’m waking a potentially large number of workflows periodically just to check a time instead of letting them sleep and waking them only when I want to (with the channel).

Any suggestions on how I may design this to minimize waking?


A coworker has pointed out I glossed over the api for Timer and that I could just use that paired with AddFuture and a single call to selector.Select to achieve this.

Hopefully this blunder of mine helps someone else :slight_smile:

Busy wait inside a workflow code is an anti-pattern. There are various ways to solve this in a supported way.

If you just want to cancel the whole workflow you don’t need to do anything as the workflow.Context passed to the workflow function will be cancelled causing workflow.Sleep to fail with a CanceledError error.

If you want to cancel some part of the workflow based on the received signal I recommend using a timer instead of a Sleep and waiting on both a Future (which represents the timer) and the signal channel.

See the timer sample that demonstrates this approach. The sample cancels the timer on activity completion instead of a signal, but it gives the idea.

If for whatever reason you had to use blocking operation like Sleep then consider using goroutines started through workflow.Go. See parallel workflow example that demonstrates the use of workflow.Go.

1 Like