Files
tasks/service/history/replication/executable_activity_state_task.go
Tim Deeb-SwihartandGitHub dae78a6d83 Rename metricDefinition getters to follow Go's guidelines (#5185)
## What changed?
I renamed the getters on `metricDefinition` to follow go's guidelines.

## Why?
Not only does it save typing, it's better Go.

Quoth [Effective Go](https://go.dev/doc/effective_go#Getters):

> ...it's neither idiomatic nor necessary to put Get into the getter's
name. If you have a field called owner (lower case, unexported), the
getter method should be called Owner (upper case, exported), not
GetOwner.

## How did you test it?
Our current tests are sufficient

## Potential risks
None

## Is hotfix candidate?
No.
2023-11-30 16:34:29 -08:00

212 lines
6.3 KiB
Go

// The MIT License
//
// Copyright (c) 2020 Temporal Technologies Inc. All rights reserved.
//
// Copyright (c) 2020 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package replication
import (
"context"
"time"
"go.temporal.io/api/serviceerror"
enumsspb "go.temporal.io/server/api/enums/v1"
"go.temporal.io/server/api/historyservice/v1"
persistencespb "go.temporal.io/server/api/persistence/v1"
replicationspb "go.temporal.io/server/api/replication/v1"
"go.temporal.io/server/common/definition"
"go.temporal.io/server/common/headers"
"go.temporal.io/server/common/log/tag"
"go.temporal.io/server/common/metrics"
"go.temporal.io/server/common/namespace"
serviceerrors "go.temporal.io/server/common/serviceerror"
ctasks "go.temporal.io/server/common/tasks"
)
type (
ExecutableActivityStateTask struct {
ProcessToolBox
definition.WorkflowKey
ExecutableTask
req *historyservice.SyncActivityRequest
}
)
var _ ctasks.Task = (*ExecutableActivityStateTask)(nil)
var _ TrackableExecutableTask = (*ExecutableActivityStateTask)(nil)
func NewExecutableActivityStateTask(
processToolBox ProcessToolBox,
taskID int64,
taskCreationTime time.Time,
task *replicationspb.SyncActivityTaskAttributes,
sourceClusterName string,
) *ExecutableActivityStateTask {
return &ExecutableActivityStateTask{
ProcessToolBox: processToolBox,
WorkflowKey: definition.NewWorkflowKey(task.NamespaceId, task.WorkflowId, task.RunId),
ExecutableTask: NewExecutableTask(
processToolBox,
taskID,
metrics.SyncActivityTaskScope,
taskCreationTime,
time.Now().UTC(),
sourceClusterName,
),
req: &historyservice.SyncActivityRequest{
NamespaceId: task.NamespaceId,
WorkflowId: task.WorkflowId,
RunId: task.RunId,
Version: task.Version,
ScheduledEventId: task.ScheduledEventId,
ScheduledTime: task.ScheduledTime,
StartedEventId: task.StartedEventId,
StartedTime: task.StartedTime,
LastHeartbeatTime: task.LastHeartbeatTime,
Details: task.Details,
Attempt: task.Attempt,
LastFailure: task.LastFailure,
LastWorkerIdentity: task.LastWorkerIdentity,
BaseExecutionInfo: task.BaseExecutionInfo,
VersionHistory: task.VersionHistory,
},
}
}
func (e *ExecutableActivityStateTask) QueueID() interface{} {
return e.WorkflowKey
}
func (e *ExecutableActivityStateTask) Execute() error {
if e.TerminalState() {
return nil
}
namespaceName, apply, nsError := e.GetNamespaceInfo(headers.SetCallerInfo(
context.Background(),
headers.SystemPreemptableCallerInfo,
), e.NamespaceID)
if nsError != nil {
return nsError
} else if !apply {
e.Logger.Warn("Skipping the replication task",
tag.WorkflowNamespaceID(e.NamespaceID),
tag.WorkflowID(e.WorkflowID),
tag.WorkflowRunID(e.RunID),
tag.TaskID(e.ExecutableTask.TaskID()),
)
e.MetricsHandler.Counter(metrics.ReplicationTasksSkipped.Name()).Record(
1,
metrics.OperationTag(metrics.SyncActivityTaskScope),
metrics.NamespaceTag(namespaceName),
)
return nil
}
ctx, cancel := newTaskContext(namespaceName)
defer cancel()
shardContext, err := e.ShardController.GetShardByNamespaceWorkflow(
namespace.ID(e.NamespaceID),
e.WorkflowID,
)
if err != nil {
return err
}
engine, err := shardContext.GetEngine(ctx)
if err != nil {
return err
}
return engine.SyncActivity(ctx, e.req)
}
func (e *ExecutableActivityStateTask) HandleErr(err error) error {
switch retryErr := err.(type) {
case nil, *serviceerror.NotFound:
return nil
case *serviceerrors.RetryReplication:
namespaceName, _, nsError := e.GetNamespaceInfo(headers.SetCallerInfo(
context.Background(),
headers.SystemPreemptableCallerInfo,
), e.NamespaceID)
if nsError != nil {
return err
}
ctx, cancel := newTaskContext(namespaceName)
defer cancel()
if doContinue, resendErr := e.Resend(
ctx,
e.ExecutableTask.SourceClusterName(),
retryErr,
ResendAttempt,
); resendErr != nil || !doContinue {
return err
}
return e.Execute()
default:
e.Logger.Error("activity state replication task encountered error",
tag.WorkflowNamespaceID(e.NamespaceID),
tag.WorkflowID(e.WorkflowID),
tag.WorkflowRunID(e.RunID),
tag.TaskID(e.ExecutableTask.TaskID()),
tag.Error(err),
)
return err
}
}
func (e *ExecutableActivityStateTask) MarkPoisonPill() error {
shardContext, err := e.ShardController.GetShardByNamespaceWorkflow(
namespace.ID(e.NamespaceID),
e.WorkflowID,
)
if err != nil {
return err
}
// TODO: GetShardID will break GetDLQReplicationMessages we need to handle DLQ for cross shard replication.
replicationTaskInfo := &persistencespb.ReplicationTaskInfo{
NamespaceId: e.NamespaceID,
WorkflowId: e.WorkflowID,
RunId: e.RunID,
TaskId: e.ExecutableTask.TaskID(),
TaskType: enumsspb.TASK_TYPE_REPLICATION_SYNC_ACTIVITY,
ScheduledEventId: e.req.ScheduledEventId,
Version: e.req.Version,
}
e.Logger.Error("enqueue activity state replication task to DLQ",
tag.ShardID(shardContext.GetShardID()),
tag.WorkflowNamespaceID(e.NamespaceID),
tag.WorkflowID(e.WorkflowID),
tag.WorkflowRunID(e.RunID),
tag.TaskID(e.ExecutableTask.TaskID()),
)
ctx, cancel := newTaskContext(e.NamespaceID)
defer cancel()
return writeTaskToDLQ(ctx, e.DLQWriter, shardContext, e.SourceClusterName(), replicationTaskInfo)
}