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

     1  // Copyright (c) 2017-2020 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 activity
    22  
    23  import (
    24  	"context"
    25  
    26  	"github.com/uber-go/tally"
    27  	"go.uber.org/zap"
    28  
    29  	"go.uber.org/cadence/internal"
    30  )
    31  
    32  type (
    33  	// Type identifies an activity type.
    34  	Type = internal.ActivityType
    35  
    36  	// Info contains information about a currently executing activity.
    37  	Info = internal.ActivityInfo
    38  
    39  	// RegisterOptions consists of options for registering an activity
    40  	RegisterOptions = internal.RegisterActivityOptions
    41  )
    42  
    43  // ErrResultPending is returned from activity's implementation to indicate the activity is not completed when
    44  // activity method returns.  The Activity needs to be completed by [go.uber.org/cadence/client.Client.CompleteActivity]
    45  // separately.
    46  //
    47  // For example, if an activity requires human interaction (like approving an expense report), the activity could push
    48  // its [Info.TaskToken] to an external system, and return [ErrResultPending].  Later on, a human can approve it, and the
    49  // system can use the associated token with [go.uber.org/cadence/client.Client.CompleteActivity] to finish the
    50  // still-"running" activity.
    51  //
    52  // Caution: since using this frequently implies "long" timeouts, but there is no actually-running activity function
    53  // that can use [go.uber.org/cadence/client.Client.RecordActivityHeartbeat], activity-worker losses prior to recording
    54  // the [Info.TaskToken] in an external system may not be noticed until the "long" timeout occurs.  This can be resolved
    55  // by having another system call RecordActivityHeartbeat while that external action is running, but there is currently
    56  // no way to mitigate this issue without these heartbeats.
    57  //
    58  // If you cannot heartbeat and cannot tolerate this kind of delayed-activity-loss detection, consider emulating a long
    59  // activity via a signal channel instead: you can start a short-lived activity and wait for a "saved to external system"
    60  // signal, retrying as necessary, and then wait for an "external system finished" signal containing the final result.
    61  var ErrResultPending = internal.ErrActivityResultPending
    62  
    63  // Register - calls RegisterWithOptions with default registration options.
    64  // Deprecated: Global activity registration methods are replaced by equivalent Worker instance methods.
    65  // This method is kept to maintain backward compatibility and should not be used.
    66  func Register(activityFunc interface{}) {
    67  	internal.RegisterActivity(activityFunc)
    68  }
    69  
    70  // RegisterWithOptions registers the activity function with options
    71  // The user can use options to provide an external name for the activity or leave it empty if no
    72  // external name is required. This can be used as
    73  //
    74  //	client.Register(barActivity, RegisterOptions{})
    75  //	client.Register(barActivity, RegisterOptions{Name: "barExternal"})
    76  //
    77  // An activity takes a context and input and returns a (result, error) or just error.
    78  // Examples:
    79  //
    80  //	func sampleActivity(ctx context.Context, input []byte) (result []byte, err error)
    81  //	func sampleActivity(ctx context.Context, arg1 int, arg2 string) (result *customerStruct, err error)
    82  //	func sampleActivity(ctx context.Context) (err error)
    83  //	func sampleActivity() (result string, err error)
    84  //	func sampleActivity(arg1 bool) (result int, err error)
    85  //	func sampleActivity(arg1 bool) (err error)
    86  //
    87  // Serialization of all primitive types, structures is supported ... except channels, functions, unsafe pointer.
    88  // If function implementation returns activity.ErrResultPending then activity is not completed from the
    89  // calling workflow point of view. See documentation of activity.ErrResultPending for more info.
    90  // This method calls panic if activityFunc doesn't comply with the expected format.
    91  // Deprecated: Global activity registration methods are replaced by equivalent Worker instance methods.
    92  // This method is kept to maintain backward compatibility and should not be used.
    93  func RegisterWithOptions(activityFunc interface{}, opts RegisterOptions) {
    94  	internal.RegisterActivityWithOptions(activityFunc, opts)
    95  }
    96  
    97  // GetInfo returns information about currently executing activity.
    98  func GetInfo(ctx context.Context) Info {
    99  	return internal.GetActivityInfo(ctx)
   100  }
   101  
   102  // GetLogger returns a logger that can be used in activity
   103  func GetLogger(ctx context.Context) *zap.Logger {
   104  	return internal.GetActivityLogger(ctx)
   105  }
   106  
   107  // GetMetricsScope returns a metrics scope that can be used in activity
   108  func GetMetricsScope(ctx context.Context) tally.Scope {
   109  	return internal.GetActivityMetricsScope(ctx)
   110  }
   111  
   112  // RecordHeartbeat sends heartbeat for the currently executing activity
   113  // If the activity is either cancelled (or) workflow/activity doesn't exist then we would cancel
   114  // the context with error context.Canceled.
   115  //
   116  // details - the details that you provided here can be seen in the workflow when it receives TimeoutError, you
   117  // can check error with TimeoutType()/Details().
   118  func RecordHeartbeat(ctx context.Context, details ...interface{}) {
   119  	internal.RecordActivityHeartbeat(ctx, details...)
   120  }
   121  
   122  // HasHeartbeatDetails checks if there is heartbeat details from last attempt.
   123  func HasHeartbeatDetails(ctx context.Context) bool {
   124  	return internal.HasHeartbeatDetails(ctx)
   125  }
   126  
   127  // GetHeartbeatDetails extract heartbeat details from last failed attempt. This is used in combination with retry policy.
   128  // An activity could be scheduled with an optional retry policy on ActivityOptions. If the activity failed then server
   129  // would attempt to dispatch another activity task to retry according to the retry policy. If there was heartbeat
   130  // details reported by activity from the failed attempt, the details would be delivered along with the activity task for
   131  // retry attempt. Activity could extract the details by GetHeartbeatDetails() and resume from the progress.
   132  // See TestActivityEnvironment.SetHeartbeatDetails() for unit test support.
   133  func GetHeartbeatDetails(ctx context.Context, d ...interface{}) error {
   134  	return internal.GetHeartbeatDetails(ctx, d...)
   135  }
   136  
   137  // GetWorkerStopChannel returns a read-only channel. The closure of this channel indicates the activity worker is stopping.
   138  // When the worker is stopping, it will close this channel and wait until the worker stop timeout finishes. After the timeout
   139  // hit, the worker will cancel the activity context and then exit. The timeout can be defined by worker option: WorkerStopTimeout.
   140  // Use this channel to handle activity graceful exit when the activity worker stops.
   141  func GetWorkerStopChannel(ctx context.Context) <-chan struct{} {
   142  	return internal.GetWorkerStopChannel(ctx)
   143  }