go.uber.org/cadence@v1.2.9/test/replaytests/parallel_workflow.go (about)

     1  // Copyright (c) 2017 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package replaytests
    22  
    23  import (
    24  	"errors"
    25  	"fmt"
    26  	"time"
    27  
    28  	"go.uber.org/zap"
    29  
    30  	"go.uber.org/cadence/workflow"
    31  )
    32  
    33  /**
    34   * This sample workflow executes multiple branches in parallel using workflow.Go() method.
    35   */
    36  
    37  // sampleParallelWorkflow workflow decider
    38  func sampleParallelWorkflow(ctx workflow.Context) error {
    39  	waitChannel := workflow.NewChannel(ctx)
    40  
    41  	ao := workflow.ActivityOptions{
    42  		ScheduleToStartTimeout: time.Minute,
    43  		StartToCloseTimeout:    time.Minute,
    44  		HeartbeatTimeout:       time.Second * 20,
    45  	}
    46  	ctx = workflow.WithActivityOptions(ctx, ao)
    47  
    48  	logger := workflow.GetLogger(ctx)
    49  	workflow.Go(ctx, func(ctx workflow.Context) {
    50  		err := workflow.ExecuteActivity(ctx, sampleActivity, "branch1.1").Get(ctx, nil)
    51  		if err != nil {
    52  			logger.Error("Activity failed", zap.Error(err))
    53  			waitChannel.Send(ctx, err.Error())
    54  			return
    55  		}
    56  		err = workflow.ExecuteActivity(ctx, sampleActivity, "branch1.2").Get(ctx, nil)
    57  		if err != nil {
    58  			logger.Error("Activity failed", zap.Error(err))
    59  			waitChannel.Send(ctx, err.Error())
    60  			return
    61  		}
    62  		waitChannel.Send(ctx, "")
    63  	})
    64  
    65  	workflow.Go(ctx, func(ctx workflow.Context) {
    66  		err := workflow.ExecuteActivity(ctx, sampleActivity, "branch2").Get(ctx, nil)
    67  		if err != nil {
    68  			logger.Error("Activity failed", zap.Error(err))
    69  			waitChannel.Send(ctx, err.Error())
    70  			return
    71  		}
    72  		waitChannel.Send(ctx, "")
    73  	})
    74  
    75  	// wait for both of the coroutinue to complete.
    76  	var errMsg string
    77  	for i := 0; i != 2; i++ {
    78  		waitChannel.Receive(ctx, &errMsg)
    79  		if errMsg != "" {
    80  			err := errors.New(errMsg)
    81  			logger.Error("Coroutine failed", zap.Error(err))
    82  			return err
    83  		}
    84  	}
    85  
    86  	logger.Info("Workflow completed.")
    87  	return nil
    88  }
    89  
    90  // Removing one branch from coroutine 1 made no difference. Here we remove one branch ie branch1.2from the coroutine 1. `
    91  func sampleParallelWorkflow2(ctx workflow.Context) error {
    92  	waitChannel := workflow.NewChannel(ctx)
    93  
    94  	ao := workflow.ActivityOptions{
    95  		ScheduleToStartTimeout: time.Minute,
    96  		StartToCloseTimeout:    time.Minute,
    97  		HeartbeatTimeout:       time.Second * 20,
    98  	}
    99  	ctx = workflow.WithActivityOptions(ctx, ao)
   100  
   101  	logger := workflow.GetLogger(ctx)
   102  	workflow.Go(ctx, func(ctx workflow.Context) {
   103  		err := workflow.ExecuteActivity(ctx, sampleActivity, "branch1.1").Get(ctx, nil)
   104  		if err != nil {
   105  			logger.Error("Activity failed", zap.Error(err))
   106  			waitChannel.Send(ctx, err.Error())
   107  			return
   108  		}
   109  		waitChannel.Send(ctx, "")
   110  	})
   111  
   112  	workflow.Go(ctx, func(ctx workflow.Context) {
   113  		err := workflow.ExecuteActivity(ctx, sampleActivity, "branch2").Get(ctx, nil)
   114  		if err != nil {
   115  			logger.Error("Activity failed", zap.Error(err))
   116  			waitChannel.Send(ctx, err.Error())
   117  			return
   118  		}
   119  		waitChannel.Send(ctx, "")
   120  	})
   121  
   122  	// wait for both of the coroutinue to complete.
   123  	var errMsg string
   124  	for i := 0; i != 2; i++ {
   125  		waitChannel.Receive(ctx, &errMsg)
   126  		if errMsg != "" {
   127  			err := errors.New(errMsg)
   128  			logger.Error("Coroutine failed", zap.Error(err))
   129  			return err
   130  		}
   131  	}
   132  
   133  	logger.Info("Workflow completed.")
   134  	return nil
   135  }
   136  
   137  func sampleActivity(input string) (string, error) {
   138  	name := "sampleActivity"
   139  	fmt.Printf("Run %s with input %v \n", name, input)
   140  	return "Result_" + name, nil
   141  }