Search code examples
gocadence-workflowtemporal-workflow

Changing the Uber Cadence Sleep time based on external (e.g. user) input


Is there an example of a Cadence workflow changing the sleep duration based on external input?

The scenario I'm looking for is this: the workflow goes into sleep until time X but after the sleep starts but before it completes, there is an external trigger that causes time X to change to time Y. Y can either be later or earlier than X. It can even be earlier than "now", which should release the sleep immediately.


Solution

  • Here is code snippet for what you are looking for

    func SampleTimerWorkflow(ctx workflow.Context, timerDelay time.Duration) error 
    {
        logger := workflow.GetLogger(ctx)
        resetCh := workflow.GetSignalChannel(ctx, "reset")
    
        timerFired := false
        delay := timerDelay
        for ;!timerFired; {
            selector := workflow.NewSelector(ctx)
    
            logger.Sugar().Infof("Setting up a timer to fire after: %v", delay)
            timerCancelCtx, cancelTimerHandler := workflow.WithCancel(ctx)
            timerFuture := workflow.NewTimer(timerCancelCtx, delay)
            selector.AddFuture(timerFuture, func(f workflow.Future) {
                logger.Info("Timer Fired.")
                timerFired = true
            })
    
            selector.AddReceive(resetCh, func(c workflow.Channel, more bool) {
                logger.Info("Reset signal received.")
                logger.Info("Cancel outstanding timer.")
                cancelTimerHandler()
    
                var t int
                c.Receive(ctx, &t)
                logger.Sugar().Infof("Reset delay: %v seconds", t)
                delay = time.Second * time.Duration(t)
            })
    
            logger.Info("Waiting for timer to fire.")
            selector.Select(ctx)
        }
    
        workflow.GetLogger(ctx).Info("Workflow completed.")
        return nil
    }
    

    Now you can send a signal to reset the timer to 10 seconds like below:

    cadence-cli --domain <domain> wf signal -w <workflow_id>  --name reset --input 10