Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 19 additions & 15 deletions service/history/api/reapplyevents/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import (
"github.com/google/uuid"
historypb "go.temporal.io/api/history/v1"
"go.temporal.io/api/serviceerror"
enumsspb "go.temporal.io/server/api/enums/v1"
"go.temporal.io/server/common"
"go.temporal.io/server/common/definition"
"go.temporal.io/server/common/log/tag"
"go.temporal.io/server/common/metrics"
"go.temporal.io/server/common/namespace"
"go.temporal.io/server/common/persistence/versionhistory"
"go.temporal.io/server/service/history/api"
Expand Down Expand Up @@ -86,21 +86,25 @@ func Invoke(
baseRunID := mutableState.GetExecutionState().GetRunId()
resetRunID := uuid.New()
baseRebuildLastEventID := mutableState.GetLastCompletedWorkflowTaskStartedEventId()

// TODO when https://github.com/uber/cadence/issues/2420 is finished, remove this block,
// since cannot reapply event to a finished workflow which had no workflow tasks started
if baseRebuildLastEventID == common.EmptyEventID {
shardContext.GetLogger().Warn("cannot reapply event to a finished workflow with no workflow task",
tag.WorkflowNamespaceID(namespaceID.String()),
tag.WorkflowID(workflowID),
)
metrics.EventReapplySkippedCount.With(shardContext.GetMetricsHandler()).Record(
1,
metrics.OperationTag(metrics.HistoryReapplyEventsScope))
return &api.UpdateWorkflowAction{
Noop: true,
CreateWorkflowTask: false,
}, nil
// No completed workflow task. Pick the reset anchor by scenario:
// - real pending workflow task (scheduled/started): anchor at it. Resetting
// to a pending task is already supported by the resetter (it fails it).
// - transient (failing, attempt > 1) or speculative pending task: not a
// usable anchor - it has no persisted WorkflowTaskScheduled event (its
// ScheduledEventID is a not-yet-written NextEventID placeholder), so skip it.
// - no workflow task at all: nothing to anchor on.
// In the latter two, baseRebuildLastEventID stays EmptyEventID and the
// version-history lookup below fails the reapply.
if workflowTask := mutableState.GetPendingWorkflowTask(); workflowTask != nil &&
!mutableState.IsTransientWorkflowTask() &&
workflowTask.Type != enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE {
if workflowTask.StartedEventID != common.EmptyEventID {
baseRebuildLastEventID = workflowTask.StartedEventID
} else {
baseRebuildLastEventID = workflowTask.ScheduledEventID
}
}
}

baseVersionHistories := mutableState.GetExecutionInfo().GetVersionHistories()
Expand Down
21 changes: 21 additions & 0 deletions service/history/ndc/transaction_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import (
commonpb "go.temporal.io/api/common/v1"
historypb "go.temporal.io/api/history/v1"
"go.temporal.io/api/serviceerror"
enumsspb "go.temporal.io/server/api/enums/v1"
"go.temporal.io/server/chasm"
"go.temporal.io/server/common"
"go.temporal.io/server/common/cluster"
"go.temporal.io/server/common/locks"
"go.temporal.io/server/common/log"
Expand Down Expand Up @@ -309,6 +311,25 @@ func (r *transactionMgrImpl) backfillWorkflowEventsReapply(
baseRunID := baseMutableState.GetExecutionState().GetRunId()
resetRunID := uuid.NewString()
baseRebuildLastEventID := baseMutableState.GetLastCompletedWorkflowTaskStartedEventId()
if baseRebuildLastEventID == common.EmptyEventID {
// No completed workflow task. Pick the reset anchor by scenario:
// - real pending workflow task (scheduled/started): anchor at it. Resetting to a
// pending task is already supported by the resetter.
// - transient (failing, attempt > 1) or speculative pending task: not a usable
// anchor - it has no persisted WorkflowTaskScheduled event (its ScheduledEventID
// is a not-yet-written NextEventID placeholder), so skip it.
// - no workflow task at all: nothing to anchor on.
if workflowTask := baseMutableState.GetPendingWorkflowTask(); workflowTask != nil &&
!baseMutableState.IsTransientWorkflowTask() &&
workflowTask.Type != enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE {
if workflowTask.StartedEventID != common.EmptyEventID {
baseRebuildLastEventID = workflowTask.StartedEventID
} else {
baseRebuildLastEventID = workflowTask.ScheduledEventID
}
}
}

baseVersionHistories := baseMutableState.GetExecutionInfo().GetVersionHistories()
baseCurrentVersionHistory, err := versionhistory.GetCurrentVersionHistory(baseVersionHistories)
if err != nil {
Expand Down
Loading
Loading