Handling Error in signal handler

I have a workflow that has a timer and once that timer is reached it executes some activities and then is complete. Before the timer has expired i am listening for 2 types of signal. 1 example below

func OrderWorkflow(ctx workflow.Context, cmd commands.CreateOrderCommand) (model.Order, error) {
	var orderActivities *OrderActivities

	retryPolicy := &temporal2.RetryPolicy{
		InitialInterval:        time.Second,
		BackoffCoefficient:     2.0,
		MaximumInterval:        time.Second * 60, // 100 * InitialInterval
		MaximumAttempts:        0,
		NonRetryableErrorTypes: []string{"MyException"}, // empty
	}

	activityOptions := workflow.ActivityOptions{
		StartToCloseTimeout: 60 * time.Second,
		RetryPolicy:         retryPolicy,
	}

	localActivityOptions := workflow.LocalActivityOptions{
		StartToCloseTimeout: 60 * time.Second,
		RetryPolicy:         retryPolicy,
	}

	ctx = workflow.WithActivityOptions(ctx, activityOptions)
	ctx = workflow.WithLocalActivityOptions(ctx, localActivityOptions)

	logger := workflow.GetLogger(ctx)

	order := model.Order{
		OrderID:           cmd.OrderID,
		OrderAmount:       cmd.OrderAmount,
		CustomerID:        cmd.CustomerID,
		CreatedAt:          workflow.Now(ctx),
		ActionedBy:         cmd.ActionedBy,
	}

	var orderExecutionDateTime model2.OrderExecutionDateTime

	err := workflow.ExecuteLocalActivity(ctx, orderActivities.CalculateOrderDateTime, cmd.CustomerID).Get(ctx, &orderExecutionDateTime)
	if err != nil {
		return orderworkflow.Order{}, err
	}

	order.OrderDateTime = orderExecutionDateTime.OrderDateTime
	
	selector := workflow.NewSelector(ctx)

	var executionTimeReached bool

	// I need to capture an error here and deal with it 
	listenForCancelOrderSignal(ctx, selector, &order, orderActivities)

	logger.Info("TimerDuration: ", timerDuration)

	timer := workflow.NewTimer(ctx, timerDuration)

	// timer set for the sleepDuration will kick in once we hit
	selector.AddFuture(timer, func(f workflow.Future) {
		executionTimeReached = true
	})

	for !executionTimeReached {
		selector.Select(ctx)
	}
	// exit the selector, we cannot cancel now

	err = workflow.ExecuteActivity(ctx, orderActivities.ProcessOrder, order).Get(ctx, &order)

	if err != nil {
		return orderworkflow.Order{}, err
	}

	return order, nil
}


func listenForCancelOrderSignal(ctx workflow.Context, selector workflow.Selector, order *model.Order, myActivities *OrderActivities) {
   	cancelOrderSignalChannel := workflow.GetSignalChannel(ctx, model.CancelOrderChannel.String())

	var notif messages.CancelOrderRequest
	
	selector.AddReceive(cancelOrderSignalChannel, func(channel workflow.ReceiveChannel, more bool) {
		channel.Receive(ctx, &notif)
        // do some stuff
		
		err := workflow.ExecuteActivity(ctx, myActivities.CancelOrder, order.OrderID).Get(ctx, &status)
		if err != nil {
			panic(err)
		}
	})
}

The problem is that i have no way of handling any errors in the do some stuff part of this The selector AddRecieve has no return type and I need to return a MyBadException so i can return this and essentially fail the workflow

I would rewrite listenForCancelOrderSignal to return Future as it supports propagating error as well:

func listenForCancelOrderSignal(ctx workflow.Context, selector workflow.Selector, order *model.Order, myActivities *OrderActivities) Future {
	cancelOrderSignalChannel := workflow.GetSignalChannel(ctx, model.CancelOrderChannel.String())

	var notif messages.CancelOrderRequest
	result, setter := workflow.NewFuture(ctx)
	selector.AddReceive(cancelOrderSignalChannel, func(channel workflow.ReceiveChannel, more bool) {
		channel.Receive(ctx, &notif)
		// do some stuff

		activityResult := workflow.ExecuteActivity(ctx, myActivities.CancelOrder, order.OrderID)
		setter.Chain(activityResult)
	})
	return result
}

Check out the alternative pattern to implement business logic using workflow.AwaitWithTimeout. In my opinion it would simplify your logic. Here is the relevant await-signals sample.

Hi,

Is there a way of propagating signal error in the Python SDK?

I believe Python supports Futures.