go.uber.org/cadence@v1.2.9/internal/interceptors.go (about)

     1  // Modifications Copyright (c) 2020 Uber Technologies Inc.
     2  // Copyright (c) 2020 Temporal Technologies, Inc.
     3  //
     4  // Permission is hereby granted, free of charge, to any person obtaining a copy
     5  // of this software and associated documentation files (the "Software"), to deal
     6  // in the Software without restriction, including without limitation the rights
     7  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8  // copies of the Software, and to permit persons to whom the Software is
     9  // furnished to do so, subject to the following conditions:
    10  //
    11  // The above copyright notice and this permission notice shall be included in
    12  // all copies or substantial portions of the Software.
    13  //
    14  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    20  // THE SOFTWARE.
    21  
    22  package internal
    23  
    24  import (
    25  	"time"
    26  
    27  	"github.com/uber-go/tally"
    28  	"go.uber.org/zap"
    29  )
    30  
    31  // WorkflowInterceptorFactory is used to create a single link in the interceptor chain
    32  type WorkflowInterceptorFactory interface {
    33  	// NewInterceptor creates an interceptor instance. The created instance must delegate every call to
    34  	// the next parameter for workflow code function correctly.
    35  	NewInterceptor(info *WorkflowInfo, next WorkflowInterceptor) WorkflowInterceptor
    36  }
    37  
    38  // WorkflowInterceptor is an interface that can be implemented to intercept calls to the workflow function
    39  // as well calls done by the workflow code.
    40  // Use worker.WorkflowInterceptorBase as a base struct for implementations that do not want to implement every method.
    41  // Interceptor implementation must forward calls to the next in the interceptor chain.
    42  // All code in the interceptor is executed in the context of a workflow. So all the rules and restrictions
    43  // that apply to the workflow code should be obeyed by the interceptor implementation.
    44  // Use workflow.IsReplaying(ctx) to filter out duplicated calls.
    45  type WorkflowInterceptor interface {
    46  	// Intercepts workflow function invocation. As calls to other intercepted functions are done from a workflow
    47  	// function this function is the first to be called and completes workflow as soon as it returns.
    48  	// workflowType argument is for information purposes only and should not be mutated.
    49  	ExecuteWorkflow(ctx Context, workflowType string, args ...interface{}) []interface{}
    50  
    51  	ExecuteActivity(ctx Context, activityType string, args ...interface{}) Future
    52  	ExecuteLocalActivity(ctx Context, activityType string, args ...interface{}) Future
    53  	ExecuteChildWorkflow(ctx Context, childWorkflowType string, args ...interface{}) ChildWorkflowFuture
    54  	GetWorkflowInfo(ctx Context) *WorkflowInfo
    55  	GetLogger(ctx Context) *zap.Logger
    56  	GetMetricsScope(ctx Context) tally.Scope
    57  	Now(ctx Context) time.Time
    58  	NewTimer(ctx Context, d time.Duration) Future
    59  	Sleep(ctx Context, d time.Duration) (err error)
    60  	RequestCancelExternalWorkflow(ctx Context, workflowID, runID string) Future
    61  	SignalExternalWorkflow(ctx Context, workflowID, runID, signalName string, arg interface{}) Future
    62  	UpsertSearchAttributes(ctx Context, attributes map[string]interface{}) error
    63  	GetSignalChannel(ctx Context, signalName string) Channel
    64  	SideEffect(ctx Context, f func(ctx Context) interface{}) Value
    65  	MutableSideEffect(ctx Context, id string, f func(ctx Context) interface{}, equals func(a, b interface{}) bool) Value
    66  	GetVersion(ctx Context, changeID string, minSupported, maxSupported Version) Version
    67  	SetQueryHandler(ctx Context, queryType string, handler interface{}) error
    68  	IsReplaying(ctx Context) bool
    69  	HasLastCompletionResult(ctx Context) bool
    70  	GetLastCompletionResult(ctx Context, d ...interface{}) error
    71  }
    72  
    73  var _ WorkflowInterceptor = (*WorkflowInterceptorBase)(nil)
    74  
    75  // WorkflowInterceptorBase is a helper type that can simplify creation of WorkflowInterceptorChainFactories
    76  type WorkflowInterceptorBase struct {
    77  	Next WorkflowInterceptor
    78  }
    79  
    80  // ExecuteWorkflow forwards to t.Next
    81  func (t *WorkflowInterceptorBase) ExecuteWorkflow(ctx Context, workflowType string, args ...interface{}) []interface{} {
    82  	return t.Next.ExecuteWorkflow(ctx, workflowType, args...)
    83  }
    84  
    85  // ExecuteActivity forwards to t.Next
    86  func (t *WorkflowInterceptorBase) ExecuteActivity(ctx Context, activityType string, args ...interface{}) Future {
    87  	return t.Next.ExecuteActivity(ctx, activityType, args...)
    88  }
    89  
    90  // ExecuteLocalActivity forwards to t.Next
    91  func (t *WorkflowInterceptorBase) ExecuteLocalActivity(ctx Context, activityType string, args ...interface{}) Future {
    92  	return t.Next.ExecuteLocalActivity(ctx, activityType, args...)
    93  }
    94  
    95  // ExecuteChildWorkflow forwards to t.Next
    96  func (t *WorkflowInterceptorBase) ExecuteChildWorkflow(ctx Context, childWorkflowType string, args ...interface{}) ChildWorkflowFuture {
    97  	return t.Next.ExecuteChildWorkflow(ctx, childWorkflowType, args...)
    98  }
    99  
   100  // GetWorkflowInfo forwards to t.Next
   101  func (t *WorkflowInterceptorBase) GetWorkflowInfo(ctx Context) *WorkflowInfo {
   102  	return t.Next.GetWorkflowInfo(ctx)
   103  }
   104  
   105  // GetLogger forwards to t.Next
   106  func (t *WorkflowInterceptorBase) GetLogger(ctx Context) *zap.Logger {
   107  	return t.Next.GetLogger(ctx)
   108  }
   109  
   110  // GetMetricsScope forwards to t.Next
   111  func (t *WorkflowInterceptorBase) GetMetricsScope(ctx Context) tally.Scope {
   112  	return t.Next.GetMetricsScope(ctx)
   113  }
   114  
   115  // Now forwards to t.Next
   116  func (t *WorkflowInterceptorBase) Now(ctx Context) time.Time {
   117  	return t.Next.Now(ctx)
   118  }
   119  
   120  // NewTimer forwards to t.Next
   121  func (t *WorkflowInterceptorBase) NewTimer(ctx Context, d time.Duration) Future {
   122  	return t.Next.NewTimer(ctx, d)
   123  }
   124  
   125  // Sleep forwards to t.Next
   126  func (t *WorkflowInterceptorBase) Sleep(ctx Context, d time.Duration) (err error) {
   127  	return t.Next.Sleep(ctx, d)
   128  }
   129  
   130  // RequestCancelExternalWorkflow forwards to t.Next
   131  func (t *WorkflowInterceptorBase) RequestCancelExternalWorkflow(ctx Context, workflowID, runID string) Future {
   132  	return t.Next.RequestCancelExternalWorkflow(ctx, workflowID, runID)
   133  }
   134  
   135  // SignalExternalWorkflow forwards to t.Next
   136  func (t *WorkflowInterceptorBase) SignalExternalWorkflow(ctx Context, workflowID, runID, signalName string, arg interface{}) Future {
   137  	return t.Next.SignalExternalWorkflow(ctx, workflowID, runID, signalName, arg)
   138  }
   139  
   140  // UpsertSearchAttributes forwards to t.Next
   141  func (t *WorkflowInterceptorBase) UpsertSearchAttributes(ctx Context, attributes map[string]interface{}) error {
   142  	return t.Next.UpsertSearchAttributes(ctx, attributes)
   143  }
   144  
   145  // GetSignalChannel forwards to t.Next
   146  func (t *WorkflowInterceptorBase) GetSignalChannel(ctx Context, signalName string) Channel {
   147  	return t.Next.GetSignalChannel(ctx, signalName)
   148  }
   149  
   150  // SideEffect forwards to t.Next
   151  func (t *WorkflowInterceptorBase) SideEffect(ctx Context, f func(ctx Context) interface{}) Value {
   152  	return t.Next.SideEffect(ctx, f)
   153  }
   154  
   155  // MutableSideEffect forwards to t.Next
   156  func (t *WorkflowInterceptorBase) MutableSideEffect(ctx Context, id string, f func(ctx Context) interface{}, equals func(a, b interface{}) bool) Value {
   157  	return t.Next.MutableSideEffect(ctx, id, f, equals)
   158  }
   159  
   160  // GetVersion forwards to t.Next
   161  func (t *WorkflowInterceptorBase) GetVersion(ctx Context, changeID string, minSupported, maxSupported Version) Version {
   162  	return t.Next.GetVersion(ctx, changeID, minSupported, maxSupported)
   163  }
   164  
   165  // SetQueryHandler forwards to t.Next
   166  func (t *WorkflowInterceptorBase) SetQueryHandler(ctx Context, queryType string, handler interface{}) error {
   167  	return t.Next.SetQueryHandler(ctx, queryType, handler)
   168  }
   169  
   170  // IsReplaying forwards to t.Next
   171  func (t *WorkflowInterceptorBase) IsReplaying(ctx Context) bool {
   172  	return t.Next.IsReplaying(ctx)
   173  }
   174  
   175  // HasLastCompletionResult forwards to t.Next
   176  func (t *WorkflowInterceptorBase) HasLastCompletionResult(ctx Context) bool {
   177  	return t.Next.HasLastCompletionResult(ctx)
   178  }
   179  
   180  // GetLastCompletionResult forwards to t.Next
   181  func (t *WorkflowInterceptorBase) GetLastCompletionResult(ctx Context, d ...interface{}) error {
   182  	return t.Next.GetLastCompletionResult(ctx, d...)
   183  }