Atlas › Test

TestNewServerWithJSONEncoding

Exact test identity: go.temporal.io/server/temporal/TestNewServerWithJSONEncoding

Package
go.temporal.io/server/temporal
Suite / test hierarchy
TestNewServerWithJSONEncoding
Test
TestNewServerWithJSONEncoding
Introduced at
metric_client.go ×3 Frontier kind: Joint frontier
Covered ranges
10450
Covered lines
44180
Covered files
758

Covered source

Expand a file to inspect source; the > gutter marks covered lines.

go.temporal.io/server/service/history/workflow/mutable_state_impl.go 1566 covered LOC · 463 ranges

Open complete file

298 runID string,
299 startTime time.Time,
300 > ) *MutableStateImpl { mutable_state_impl.go
301 >
302 > namespaceName := namespaceEntry.Name().String()
303 > logger = log.NewLazyLogger(logger, func() []tag.Tag {
304 > return []tag.Tag{ mutable_state_impl.go
305 > tag.WorkflowNamespace(namespaceName),
306 > tag.WorkflowID(workflowID),
307 > tag.WorkflowRunID(runID),
308 > }
309 > })
310
311 > s := &MutableStateImpl{ mutable_state_impl.go
312 > updateActivityInfos: make(map[int64]*persistencespb.ActivityInfo),
313 > pendingActivityTimerHeartbeats: make(map[int64]time.Time),
314 > pendingActivityInfoIDs: make(map[int64]*persistencespb.ActivityInfo),
315 > pendingActivityIDToEventID: make(map[string]int64),
316 > deleteActivityInfos: make(map[int64]struct{}),
317 > syncActivityTasks: make(map[int64]struct{}),
318 >
319 > pendingTimerInfoIDs: make(map[string]*persistencespb.TimerInfo),
320 > pendingTimerEventIDToID: make(map[int64]string),
321 > updateTimerInfos: make(map[string]*persistencespb.TimerInfo),
322 > deleteTimerInfos: make(map[string]struct{}),
323 >
324 > updateChildExecutionInfos: make(map[int64]*persistencespb.ChildExecutionInfo),
325 > pendingChildExecutionInfoIDs: make(map[int64]*persistencespb.ChildExecutionInfo),
326 > deleteChildExecutionInfos: make(map[int64]struct{}),
327 >
328 > updateRequestCancelInfos: make(map[int64]*persistencespb.RequestCancelInfo),
329 > pendingRequestCancelInfoIDs: make(map[int64]*persistencespb.RequestCancelInfo),
330 > deleteRequestCancelInfos: make(map[int64]struct{}),
331 >
332 > updateSignalInfos: make(map[int64]*persistencespb.SignalInfo),
333 > pendingSignalInfoIDs: make(map[int64]*persistencespb.SignalInfo),
334 > deleteSignalInfos: make(map[int64]struct{}),
335 >
336 > updateSignalRequestedIDs: make(map[string]struct{}),
337 > pendingSignalRequestedIDs: make(map[string]struct{}),
338 > deleteSignalRequestedIDs: make(map[string]struct{}),
339 >
340 > // This field will be initialized with a real chasm tree at the end of this function
341 > // when feature flag is enabled.
342 > chasmTree: &noopChasmTree{},
343 >
344 > approximateSize: 0,
345 > chasmNodeSizes: make(map[string]int),
346 > totalTombstones: 0,
347 > currentVersion: namespaceEntry.FailoverVersion(workflowID),
348 > bufferEventsInDB: nil,
349 > stateInDB: enumsspb.WORKFLOW_EXECUTION_STATE_VOID,
350 > nextEventIDInDB: common.FirstEventID,
351 > dbRecordVersion: 1,
352 > namespaceEntry: namespaceEntry,
353 > appliedEvents: make(map[string]struct{}),
354 > InsertTasks: make(map[tasks.Category][]tasks.Task),
355 > BestEffortDeleteTasks: make(map[tasks.Category][]tasks.Key),
356 > transitionHistoryEnabled: shard.GetConfig().EnableTransitionHistory(namespaceName),
357 > visibilityUpdated: false,
358 > executionStateUpdated: false,
359 > workflowTaskUpdated: false,
360 > updateInfoUpdated: make(map[string]struct{}),
361 > timerInfosUserDataUpdated: make(map[string]struct{}),
362 > activityInfosUserDataUpdated: make(map[int64]struct{}),
363 > reapplyEventsCandidate: []*historypb.HistoryEvent{},
364 >
365 > QueryRegistry: NewQueryRegistry(),
366 >
367 > shard: shard,
368 > clusterMetadata: shard.GetClusterMetadata(),
369 > eventsCache: eventsCache,
370 > config: shard.GetConfig(),
371 > timeSource: shard.GetTimeSource(),
372 > logger: logger,
373 > metricsHandler: shard.GetMetricsHandler().WithTags(metrics.OperationTag(metrics.WorkflowContextScope)),
374 > endpointRegistry: shard.EndpointRegistry(),
375 > }
376 >
377 > s.executionInfo = &persistencespb.WorkflowExecutionInfo{
378 > NamespaceId: namespaceEntry.ID().String(),
379 > WorkflowId: workflowID,
380 >
381 > WorkflowTaskVersion: common.EmptyVersion,
382 > WorkflowTaskScheduledEventId: common.EmptyEventID,
383 > WorkflowTaskStartedEventId: common.EmptyEventID,
384 > WorkflowTaskRequestId: emptyUUID,
385 > WorkflowTaskTimeout: timestamp.DurationFromSeconds(0),
386 > WorkflowTaskAttempt: 1,
387 >
388 > LastCompletedWorkflowTaskStartedEventId: common.EmptyEventID,
389 >
390 > StartTime: timestamppb.New(startTime),
391 > ExecutionTime: timestamppb.New(startTime),
392 > VersionHistories: versionhistory.NewVersionHistories(&historyspb.VersionHistory{}),
393 > ExecutionStats: &persistencespb.ExecutionStats{HistorySize: 0},
394 > SubStateMachinesByType: make(map[string]*persistencespb.StateMachineMap),
395 > }
396 > s.executionInfo.TaskGenerationShardClockTimestamp = shard.CurrentVectorClock().GetClock()
397 > s.approximateSize += s.executionInfo.Size()
398 >
399 > s.executionState = &persistencespb.WorkflowExecutionState{
400 > RunId: runID,
401 >
402 > State: enumsspb.WORKFLOW_EXECUTION_STATE_CREATED,
403 > Status: enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING,
404 > StartTime: timestamppb.New(startTime),
405 > RequestIds: make(map[string]*persistencespb.RequestIDInfo),
406 > }
407 > s.approximateSize += s.executionState.Size()
408 >
409 > s.hBuilder = historybuilder.New(
410 > s.timeSource,
411 > s.shard.GenerateTaskIDs,
412 > s.currentVersion,
413 > common.FirstEventID,
414 > s.bufferEventsInDB,
415 > s.metricsHandler,
416 > s.config.MaximumEventBatchSizeInBytes,
417 > )
418 > s.taskGenerator = GetTaskGeneratorProvider().NewTaskGenerator(shard, s)
419 > s.workflowTaskManager = newWorkflowTaskStateMachine(s, s.metricsHandler)
420 >
421 > s.mustInitHSM()
422 >
423 > // TODO@time-skipping: support time skipping for chasm
424 > if s.config.EnableChasm(namespaceName) {
425 > s.chasmTree = chasm.NewEmptyTree( mutable_state_impl.go
426 > shard.ChasmRegistry(),
427 > shard.GetTimeSource(),
428 > s,
429 > chasm.DefaultPathEncoder,
430 > logger,
431 > shard.GetMetricsHandler().WithTags(metrics.NamespaceTag(namespaceName)),
432 > )
433 > }
434
435 > if s.executionInfo.GetTimeSkippingInfo() != nil { mutable_state_impl.go
436 s.wrapTimeSourceWithTimeSkipping()
437 }
438 > return s mutable_state_impl.go
439 }
440
446 dbRecord *persistencespb.WorkflowMutableState,
447 dbRecordVersion int64,
448 > ) (*MutableStateImpl, error) { mutable_state_impl.go
449 > // startTime will be overridden by DB record
450 > startTime := time.Time{}
451 >
452 > mutableState := NewMutableState(
453 > shard,
454 > eventsCache,
455 > logger,
456 > namespaceEntry,
457 > dbRecord.ExecutionInfo.WorkflowId,
458 > dbRecord.ExecutionState.RunId,
459 > startTime,
460 > )
461 >
462 > if dbRecord.ActivityInfos != nil {
463 > mutableState.pendingActivityInfoIDs = dbRecord.ActivityInfos mutable_state_impl.go
464 > mutableState.approximateSize += int64SizeBytes * len(mutableState.pendingActivityInfoIDs)
465 > }
466 > for _, activityInfo := range dbRecord.ActivityInfos { mutable_state_impl.go
467 mutableState.pendingActivityIDToEventID[activityInfo.ActivityId] = activityInfo.ScheduledEventId
468 mutableState.approximateSize += activityInfo.Size()
474 }
475
476 > if dbRecord.TimerInfos != nil { mutable_state_impl.go
477 > mutableState.pendingTimerInfoIDs = dbRecord.TimerInfos mutable_state_impl.go
478 > }
479 > for timerID, timerInfo := range dbRecord.TimerInfos { mutable_state_impl.go
480 mutableState.pendingTimerEventIDToID[timerInfo.GetStartedEventId()] = timerInfo.GetTimerId()
481 mutableState.approximateSize += timerInfo.Size()
483 }
484
485 > if dbRecord.ChildExecutionInfos != nil { mutable_state_impl.go
486 > mutableState.pendingChildExecutionInfoIDs = dbRecord.ChildExecutionInfos mutable_state_impl.go
487 > mutableState.approximateSize += int64SizeBytes * len(mutableState.pendingChildExecutionInfoIDs)
488 > }
489 > for _, childInfo := range dbRecord.ChildExecutionInfos { mutable_state_impl.go
490 mutableState.approximateSize += childInfo.Size()
491 }
492
493 > if dbRecord.RequestCancelInfos != nil { mutable_state_impl.go
494 > mutableState.pendingRequestCancelInfoIDs = dbRecord.RequestCancelInfos mutable_state_impl.go
495 > mutableState.approximateSize += int64SizeBytes * len(mutableState.pendingRequestCancelInfoIDs)
496 > }
497 > for _, cancelInfo := range dbRecord.RequestCancelInfos { mutable_state_impl.go
498 mutableState.approximateSize += cancelInfo.Size()
499 }
500
501 > if dbRecord.SignalInfos != nil { mutable_state_impl.go
502 > mutableState.pendingSignalInfoIDs = dbRecord.SignalInfos mutable_state_impl.go
503 > mutableState.approximateSize += int64SizeBytes * len(mutableState.pendingSignalInfoIDs)
504 > }
505 > for _, signalInfo := range dbRecord.SignalInfos { mutable_state_impl.go
506 mutableState.approximateSize += signalInfo.Size()
507 }
508
509 > mutableState.pendingSignalRequestedIDs = convert.StringSliceToSet(dbRecord.SignalRequestedIds) mutable_state_impl.go
510 > for requestID := range mutableState.pendingSignalRequestedIDs {
511 mutableState.approximateSize += len(requestID)
512 }
513
514 > for _, tombstoneBatch := range dbRecord.ExecutionInfo.SubStateMachineTombstoneBatches { mutable_state_impl.go
515 > mutableState.totalTombstones += len(tombstoneBatch.StateMachineTombstones) mutable_state_impl.go
516 > }
517
518 // FirstExecutionRunId was duplicated from ExecutionInfo onto ExecutionState so the dedup /
519 // conflict path can surface it without loading ExecutionInfo. Backfill in memory for records
520 // written before that change so the next persist writes it through.
521 > if dbRecord.ExecutionState.FirstExecutionRunId == "" && dbRecord.ExecutionInfo.FirstExecutionRunId != "" { mutable_state_impl.go
522 dbRecord.ExecutionState.FirstExecutionRunId = dbRecord.ExecutionInfo.FirstExecutionRunId
523 }
524
525 > mutableState.approximateSize += dbRecord.ExecutionState.Size() - mutableState.executionState.Size() mutable_state_impl.go
526 > mutableState.executionState = dbRecord.ExecutionState
527 > mutableState.approximateSize += dbRecord.ExecutionInfo.Size() - mutableState.executionInfo.Size()
528 > mutableState.executionInfo = dbRecord.ExecutionInfo
529 >
530 > // StartTime was moved from ExecutionInfo to executionState
531 > if mutableState.executionState.StartTime == nil && dbRecord.ExecutionInfo.StartTime != nil {
532 mutableState.executionState.StartTime = dbRecord.ExecutionInfo.StartTime
533 }
534
535 > mutableState.hBuilder = historybuilder.New( mutable_state_impl.go
536 > mutableState.timeSource,
537 > mutableState.shard.GenerateTaskIDs,
538 > common.EmptyVersion,
539 > dbRecord.NextEventId,
540 > dbRecord.BufferedEvents,
541 > mutableState.metricsHandler,
542 > mutableState.config.MaximumEventBatchSizeInBytes,
543 > )
544 > mutableState.currentVersion = common.EmptyVersion
545 > mutableState.bufferEventsInDB = dbRecord.BufferedEvents
546 > mutableState.stateInDB = dbRecord.ExecutionState.State
547 > mutableState.nextEventIDInDB = dbRecord.NextEventId
548 > mutableState.dbRecordVersion = dbRecordVersion
549 > mutableState.checksum = dbRecord.Checksum
550 > mutableState.initVersionedTransitionInDB()
551 >
552 > if len(dbRecord.Checksum.GetValue()) > 0 {
553 switch {
554 case mutableState.shouldInvalidateCheckum():
566 }
567
568 > mutableState.mustInitHSM() mutable_state_impl.go
569 >
570 > // Track chasm node size even if chasm is not enabled,
571 > // because those nodes are still stored in the mutable state,
572 > // and should be taken into account when deciding if execution
573 > // should be terminated based on mutable state size.
574 > for key, node := range dbRecord.ChasmNodes {
575 nodeSize := len(key) + node.Size()
576 mutableState.approximateSize += nodeSize
579
580 // TODO@time-skipping: support time skipping for chasm
581 > if shard.GetConfig().EnableChasm(namespaceEntry.Name().String()) { mutable_state_impl.go
582 > var err error mutable_state_impl.go
583 > mutableState.chasmTree, err = chasm.NewTreeFromDB(
584 > dbRecord.ChasmNodes,
585 > shard.ChasmRegistry(),
586 > shard.GetTimeSource(),
587 > mutableState,
588 > chasm.DefaultPathEncoder,
589 > mutableState.logger, // this logger is tagged with execution key.
590 > shard.GetMetricsHandler().WithTags(metrics.NamespaceTag(namespaceEntry.Name().String())),
591 > )
592 > if err != nil {
593 return nil, err
594 }
595 }
596 > if mutableState.executionInfo.GetTimeSkippingInfo() != nil { mutable_state_impl.go
597 mutableState.wrapTimeSourceWithTimeSkipping()
598 }
599 > return mutableState, nil mutable_state_impl.go
600 }
601
655 }
656
657 > func (ms *MutableStateImpl) mustInitHSM() { mutable_state_impl.go
658 > if ms.executionInfo.SubStateMachinesByType == nil {
659 ms.executionInfo.SubStateMachinesByType = make(map[string]*persistencespb.StateMachineMap)
660 }
661
662 // Error only occurs if some initialization path forgets to register the workflow state machine.
663 > stateMachineNode, err := hsm.NewRoot(ms.shard.StateMachineRegistry(), StateMachineType, ms, ms.executionInfo.SubStateMachinesByType, ms) mutable_state_impl.go
664 > if err != nil {
665 panic(err)
666 }
667 > ms.stateMachineNode = stateMachineNode mutable_state_impl.go
668 }
669
670 > func (ms *MutableStateImpl) IsWorkflow() bool { mutable_state_impl.go
671 > return ms.chasmTree.ArchetypeID() == chasm.WorkflowArchetypeID
672 > }
673
674 > func (ms *MutableStateImpl) HSM() *hsm.Node { mutable_state_impl.go
675 > return ms.stateMachineNode
676 > }
677
678 > func (ms *MutableStateImpl) ChasmTree() historyi.ChasmTree { mutable_state_impl.go
679 > return ms.chasmTree
680 > }
681
682 // ChasmEnabled returns true if the mutable state has a real chasm tree.
684 // enabled when the mutable state is created. Once the EnableChasm dynamic config is removed and the tree is always
685 // initialized, this helper can be removed.
686 > func (ms *MutableStateImpl) ChasmEnabled() bool { mutable_state_impl.go
687 > _, isNoop := ms.chasmTree.(*noopChasmTree)
688 > return !isNoop
689 > }
690
691 // chasmCallbacksEnabled returns true if CHASM callbacks are enabled for this workflow.
738 // Returns both the workflow component and a read-only CHASM context.
739 // This method is for read-only operations.
740 > func (ms *MutableStateImpl) ChasmWorkflowComponentReadOnly(ctx context.Context) (*chasmworkflow.Workflow, chasm.Context, error) { mutable_state_impl.go
741 > chasmCtx := chasm.NewContext(ctx, ms.chasmTree.(*chasm.Node))
742 > rootComponent, err := ms.chasmTree.ComponentByPath(chasmCtx, nil)
743 > if err != nil {
744 return nil, nil, err
745 }
746 > wf, ok := rootComponent.(*chasmworkflow.Workflow) mutable_state_impl.go
747 > if !ok {
748 return nil, nil, serviceerror.NewInternalf("expected workflow component, but got %T", rootComponent)
749 }
750 > return wf, chasmCtx, nil mutable_state_impl.go
751 }
752
991 }
992
993 > func (ms *MutableStateImpl) GetWorkflowKey() definition.WorkflowKey { mutable_state_impl.go
994 > return definition.NewWorkflowKey(
995 > ms.executionInfo.NamespaceId,
996 > ms.executionInfo.WorkflowId,
997 > ms.executionState.RunId,
998 > )
999 > }
1000
1001 > func (ms *MutableStateImpl) GetCurrentBranchToken() ([]byte, error) { mutable_state_impl.go
1002 > currentVersionHistory, err := versionhistory.GetCurrentVersionHistory(ms.executionInfo.VersionHistories)
1003 > if err != nil {
1004 return nil, err
1005 }
1006 > return currentVersionHistory.GetBranchToken(), nil mutable_state_impl.go
1007 }
1008
1024 runTimeout *durationpb.Duration,
1025 treeID string,
1026 > ) error { mutable_state_impl.go
1027 > // NOTE: Unfortunately execution timeout and run timeout are not yet initialized into ms.executionInfo at this point.
1028 > // TODO: Consider explicitly initializing mutable state with these timeout parameters instead of passing them in.
1029 > workflowKey := ms.GetWorkflowKey()
1030 >
1031 > archetypeID := ms.ChasmTree().ArchetypeID()
1032 > if archetypeID != chasm.WorkflowArchetypeID {
1033 return softassert.UnexpectedInternalErr(
1034 ms.logger,
1042 }
1043
1044 > var retentionDuration *durationpb.Duration mutable_state_impl.go
1045 > if duration := ms.namespaceEntry.Retention(); duration > 0 {
1046 > retentionDuration = durationpb.New(duration) mutable_state_impl.go
1047 > }
1048 > initialBranchToken, err := ms.shard.GetExecutionManager().GetHistoryBranchUtil().NewHistoryBranch( mutable_state_impl.go
1049 > workflowKey.NamespaceID,
1050 > workflowKey.WorkflowID,
1051 > workflowKey.RunID,
1052 > treeID,
1053 > nil,
1054 > []*persistencespb.HistoryBranchRange{},
1055 > runTimeout.AsDuration(),
1056 > executionTimeout.AsDuration(),
1057 > retentionDuration.AsDuration(),
1058 > )
1059 > if err != nil {
1060 return err
1061 }
1062 > return ms.SetCurrentBranchToken(initialBranchToken) mutable_state_impl.go
1063 }
1064
1065 func (ms *MutableStateImpl) SetCurrentBranchToken(
1066 branchToken []byte,
1067 > ) error { mutable_state_impl.go
1068 > currentVersionHistory, err := versionhistory.GetCurrentVersionHistory(ms.executionInfo.VersionHistories)
1069 > if err != nil {
1070 return err
1071 }
1072 > versionhistory.SetVersionHistoryBranchToken(currentVersionHistory, branchToken) mutable_state_impl.go
1073 > return nil
1074 }
1075
1120 }
1121
1122 > func (ms *MutableStateImpl) GetExecutionInfo() *persistencespb.WorkflowExecutionInfo { mutable_state_impl.go
1123 > return ms.executionInfo
1124 > }
1125
1126 > func (ms *MutableStateImpl) GetExecutionState() *persistencespb.WorkflowExecutionState { mutable_state_impl.go
1127 > return ms.executionState
1128 > }
1129
1130 func (ms *MutableStateImpl) FlushBufferedEvents() {
1138 version int64,
1139 forceUpdate bool,
1140 > ) error { mutable_state_impl.go
1141 > if ms.transitionHistoryEnabled && len(ms.executionInfo.TransitionHistory) != 0 {
1142 > // this make sure current version >= last write version mutable_state_impl.go
1143 > lastVersionedTransition := ms.CurrentVersionedTransition()
1144 > ms.currentVersion = lastVersionedTransition.NamespaceFailoverVersion
1145 > } else { mutable_state_impl.go
1146 versionHistory, err := versionhistory.GetCurrentVersionHistory(ms.executionInfo.VersionHistories)
1147 if err != nil {
1159 }
1160
1161 > if version > ms.currentVersion || forceUpdate { mutable_state_impl.go
1162 ms.currentVersion = version
1163 }
1164
1165 > ms.hBuilder = historybuilder.New( mutable_state_impl.go
1166 > ms.timeSource,
1167 > ms.shard.GenerateTaskIDs,
1168 > ms.currentVersion,
1169 > ms.nextEventIDInDB,
1170 > ms.bufferEventsInDB,
1171 > ms.metricsHandler,
1172 > ms.config.MaximumEventBatchSizeInBytes,
1173 > )
1174 >
1175 > return nil
1176 }
1177
1178 > func (ms *MutableStateImpl) GetCurrentVersion() int64 { mutable_state_impl.go
1179 > // TODO: can we always return ms.currentVersion here?
1180 > if ms.executionInfo.VersionHistories != nil {
1181 > return ms.currentVersion
1182 > }
1183
1184 if ms.transitionHistoryEnabled && len(ms.executionInfo.TransitionHistory) != 0 {
1190
1191 // NextTransitionCount implements hsm.NodeBackend.
1192 > func (ms *MutableStateImpl) NextTransitionCount() int64 { mutable_state_impl.go
1193 > if !ms.transitionHistoryEnabled {
1194 return 0
1195 }
1196
1197 > currentVersionedTransition := ms.CurrentVersionedTransition() mutable_state_impl.go
1198 > if currentVersionedTransition == nil {
1199 > // it is possible that this is the first transition and mutable_state_impl.go
1200 > // transition history has not been updated yet.
1201 > return 1
1202 > }
1203 > return currentVersionedTransition.TransitionCount + 1 mutable_state_impl.go
1204 }
1205
1206 > func (ms *MutableStateImpl) GetStartVersion() (int64, error) { mutable_state_impl.go
1207 > if ms.executionInfo.VersionHistories != nil {
1208 > versionHistory, err := versionhistory.GetCurrentVersionHistory(ms.executionInfo.VersionHistories)
1209 > if err != nil {
1210 return 0, err
1211 }
1212
1213 > if !versionhistory.IsEmptyVersionHistory(versionHistory) { mutable_state_impl.go
1214 > firstItem, err := versionhistory.GetFirstVersionHistoryItem(versionHistory)
1215 > if err != nil {
1216 return 0, err
1217 }
1218 > return firstItem.GetVersion(), nil mutable_state_impl.go
1219 }
1220 }
1234 }
1235
1236 > func (ms *MutableStateImpl) GetCloseVersion() (int64, error) { mutable_state_impl.go
1237 > // TODO: Remove this special handling for zombie workflow.
1238 > // This method should not be called for zombie workflow as it's not considered closed (though it's not running either).
1239 > //
1240 > // However, most callers in this codebase simply check if workflowIsRunning before calling this method, so we cloud reach here
1241 > // even if the workflow is zombie.
1242 > // Most callers are in task executor logic, and we should just prevent any task executor from running when workflow is in zombie state.
1243 > if ms.executionState.State == enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE {
1244 return ms.GetLastWriteVersion()
1245 }
1247 // Do NOT use ms.IsWorkflowExecutionRunning() for the check.
1248 // Zombie workflow is not considered running but also not closed.
1249 > if ms.executionState.State != enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED { mutable_state_impl.go
1250 return common.EmptyVersion, serviceerror.NewInternalf("workflow still running, current state: %v", ms.executionState.State.String())
1251 }
1253 // if workflow is closing in the current transation,
1254 // then the last event is closed event and the event version is the close version
1255 > if lastEventVersion, ok := ms.hBuilder.LastEventVersion(); ok { mutable_state_impl.go
1256 > return lastEventVersion, nil mutable_state_impl.go
1257 > }
1258
1259 // We check version history first to prevserve the existing behaior of workflow to minimize risk.
1261 // That assumption is true today, but no necessarily true in the future. We should fix this if we ever
1262 // have such a case.
1263 > if ms.executionInfo.VersionHistories != nil { mutable_state_impl.go
1264 > isEmpty, err := versionhistory.IsCurrentVersionHistoryEmpty(ms.executionInfo.VersionHistories)
1265 > if err != nil {
1266 return common.EmptyVersion, err
1267 }
1268 > if !isEmpty { mutable_state_impl.go
1269 > return ms.GetLastEventVersion() mutable_state_impl.go
1270 > }
1271 }
1272
1287 }
1288
1289 > func (ms *MutableStateImpl) GetLastWriteVersion() (int64, error) { mutable_state_impl.go
1290 > if ms.transitionHistoryEnabled && len(ms.executionInfo.TransitionHistory) != 0 {
1291 > lastVersionedTransition := ms.CurrentVersionedTransition() mutable_state_impl.go
1292 > return lastVersionedTransition.NamespaceFailoverVersion, nil
1293 > }
1294
1295 return ms.GetLastEventVersion()
1296 }
1297
1298 > func (ms *MutableStateImpl) GetLastEventVersion() (int64, error) { mutable_state_impl.go
1299 > if ms.executionInfo.VersionHistories != nil {
1300 > versionHistory, err := versionhistory.GetCurrentVersionHistory(ms.executionInfo.VersionHistories)
1301 > if err != nil {
1302 return 0, err
1303 }
1304 > lastItem, err := versionhistory.GetLastVersionHistoryItem(versionHistory) mutable_state_impl.go
1305 > if err != nil {
1306 return 0, err
1307 }
1308 > return lastItem.GetVersion(), nil mutable_state_impl.go
1309 }
1310
1312 }
1313
1314 > func (ms *MutableStateImpl) IsCurrentWorkflowGuaranteed() bool { mutable_state_impl.go
1315 > // stateInDB is used like a bloom filter:
1316 > //
1317 > // 1. stateInDB being created / running meaning that this workflow must be the current
1318 > // workflow (assuming there is no rebuild of mutable state).
1319 > // 2. stateInDB being completed does not guarantee this workflow being the current workflow
1320 > // 3. stateInDB being zombie guarantees this workflow not being the current workflow
1321 > // 4. stateInDB cannot be void, void is only possible when mutable state is just initialized
1322 >
1323 > switch ms.stateInDB {
1324 case enumsspb.WORKFLOW_EXECUTION_STATE_VOID:
1325 return false
1326 case enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:
1327 return true
1328 > case enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING: mutable_state_impl.go
1329 > return true
1330 case enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED:
1331 return false
1358 }
1359
1360 > func (ms *MutableStateImpl) GetNamespaceEntry() *namespace.Namespace { mutable_state_impl.go
1361 > return ms.namespaceEntry
1362 > }
1363
1364 // AddHistoryEvent adds any history event to this workflow execution.
1429 }
1430
1431 > func (ms *MutableStateImpl) CurrentTaskQueue() *taskqueuepb.TaskQueue { mutable_state_impl.go
1432 > if ms.IsStickyTaskQueueSet() {
1433 return &taskqueuepb.TaskQueue{
1434 Name: ms.executionInfo.StickyTaskQueue,
1437 }
1438 }
1439 > return &taskqueuepb.TaskQueue{ mutable_state_impl.go
1440 > Name: ms.executionInfo.TaskQueue,
1441 > Kind: enumspb.TASK_QUEUE_KIND_NORMAL,
1442 > }
1443 }
1444
1445 > func (ms *MutableStateImpl) SetStickyTaskQueue(name string, scheduleToStartTimeout *durationpb.Duration) { mutable_state_impl.go
1446 > ms.executionInfo.StickyTaskQueue = name
1447 > ms.executionInfo.StickyScheduleToStartTimeout = scheduleToStartTimeout
1448 > }
1449
1450 > func (ms *MutableStateImpl) ClearStickyTaskQueue() { mutable_state_impl.go
1451 > ms.executionInfo.StickyTaskQueue = ""
1452 > ms.executionInfo.StickyScheduleToStartTimeout = nil
1453 > }
1454
1455 > func (ms *MutableStateImpl) IsStickyTaskQueueSet() bool { mutable_state_impl.go
1456 > return ms.executionInfo.StickyTaskQueue != ""
1457 > }
1458
1459 // TaskQueueScheduleToStartTimeout returns TaskQueue struct and corresponding StartToClose timeout.
1461 // in mutable state and provided name.
1462 // ScheduleToStartTimeout is set based on queue kind and workflow task type.
1463 > func (ms *MutableStateImpl) TaskQueueScheduleToStartTimeout(tqName string) (*taskqueuepb.TaskQueue, *durationpb.Duration) { mutable_state_impl.go
1464 > isStickyTq := ms.executionInfo.StickyTaskQueue == tqName
1465 > if isStickyTq {
1466 return &taskqueuepb.TaskQueue{
1467 Name: ms.executionInfo.StickyTaskQueue,
1472
1473 // If tqName is normal task queue name.
1474 > normalTq := &taskqueuepb.TaskQueue{ mutable_state_impl.go
1475 > Name: ms.executionInfo.TaskQueue,
1476 > Kind: enumspb.TASK_QUEUE_KIND_NORMAL,
1477 > }
1478 > if ms.executionInfo.WorkflowTaskType == enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE {
1479 // Speculative WFT has ScheduleToStartTimeout even on normal task queue.
1480 // See comment in GenerateScheduleSpeculativeWorkflowTaskTasks for details.
1482 }
1483 // No WFT ScheduleToStart timeout for normal WFT on normal task queue.
1484 > return normalTq, ms.executionInfo.WorkflowRunTimeout mutable_state_impl.go
1485 }
1486
1487 > func (ms *MutableStateImpl) GetWorkflowType() *commonpb.WorkflowType { mutable_state_impl.go
1488 > wType := &commonpb.WorkflowType{}
1489 > wType.Name = ms.executionInfo.WorkflowTypeName
1490 >
1491 > return wType
1492 > }
1493
1494 > func (ms *MutableStateImpl) GetQueryRegistry() historyi.QueryRegistry { mutable_state_impl.go
1495 > return ms.QueryRegistry
1496 > }
1497
1498 // VisitUpdates visits mutable state update entries, ordered by the ID of the history event pointed to by the mutable
1499 // state entry. Thus, for example, updates entries in Admitted state will be visited in the order that their Admitted
1500 // events were added to history.
1501 > func (ms *MutableStateImpl) VisitUpdates(visitor func(updID string, updInfo *persistencespb.UpdateInfo)) { mutable_state_impl.go
1502 > type updateEvent struct {
1503 > updId string
1504 > updInfo *persistencespb.UpdateInfo
1505 > eventId int64
1506 > }
1507 > var updateEvents []updateEvent
1508 > for updID, updInfo := range ms.executionInfo.GetUpdateInfos() {
1509 u := updateEvent{
1510 updId: updID,
1520 updateEvents = append(updateEvents, u)
1521 }
1522 > slices.SortFunc(updateEvents, func(u1, u2 updateEvent) int { return cmp.Compare(u1.eventId, u2.eventId) }) mutable_state_impl.go
1523
1524 > for _, u := range updateEvents { mutable_state_impl.go
1525 visitor(u.updId, u.updInfo)
1526 }
1778 }
1779
1780 > func (ms *MutableStateImpl) GetCronBackoffDuration() time.Duration { mutable_state_impl.go
1781 > if ms.executionInfo.CronSchedule == "" {
1782 > return backoff.NoBackoff
1783 > }
1784 executionTime := timestamp.TimeValue(ms.GetExecutionInfo().GetExecutionTime())
1785 // todo@time-skipping: time skipping is naturally supported for cron backoff, and need to
1916 }
1917
1918 > func (ms *MutableStateImpl) Now() time.Time { mutable_state_impl.go
1919 > return ms.timeSource.Now()
1920 > }
1921
1922 // GetWorkflowCloseTime returns workflow closed time, returns a zero time for open workflow
1923 > func (ms *MutableStateImpl) GetWorkflowCloseTime(ctx context.Context) (time.Time, error) { mutable_state_impl.go
1924 > if ms.executionState.GetState() == enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED && ms.executionInfo.CloseTime == nil {
1925 // This is for backward compatible. Prior to v1.16 does not have close time in mutable state (Added by 05/21/2022).
1926 // TODO: remove this logic when all mutable state contains close time.
1931 return completionEvent.GetEventTime().AsTime(), nil
1932 }
1933 > return ms.executionInfo.CloseTime.AsTime(), nil mutable_state_impl.go
1934 }
1935
1936 // GetWorkflowExecutionDuration returns the workflow execution duration.
1937 // Returns zero for open workflow.
1938 > func (ms *MutableStateImpl) GetWorkflowExecutionDuration(ctx context.Context) (time.Duration, error) { mutable_state_impl.go
1939 > closeTime, err := ms.GetWorkflowCloseTime(ctx)
1940 > if err != nil {
1941 return 0, err
1942 }
1943 > if closeTime.IsZero() || ms.executionInfo.ExecutionTime == nil { mutable_state_impl.go
1944 return 0, nil
1945 }
1946 > return closeTime.Sub(ms.executionInfo.ExecutionTime.AsTime()), nil mutable_state_impl.go
1947 }
1948
1987 func (ms *MutableStateImpl) GetFirstRunID(
1988 ctx context.Context,
1989 > ) (string, error) { mutable_state_impl.go
1990 > // Prefer the canonical source on ExecutionState; the equivalent field on ExecutionInfo is
1991 > // deprecated. NewMutableStateFromDB backfills ExecutionState from ExecutionInfo on load, so
1992 > // records that pre-date the ExecutionState field also resolve here.
1993 > if firstRunID := ms.executionState.FirstExecutionRunId; firstRunID != "" {
1994 > return firstRunID, nil
1995 > }
1996 if firstRunID := ms.executionInfo.FirstExecutionRunId; firstRunID != "" {
1997 return firstRunID, nil
2071 func (ms *MutableStateImpl) writeEventToCache(
2072 event *historypb.HistoryEvent,
2074 > // For start event: store it here so the recordWorkflowStarted transfer task doesn't need to
2075 > // load it from database.
2076 > // For completion event: store it here so we can communicate the result to parent execution
2077 > // during the processing of DeleteTransferTask without loading this event from database.
2078 > // For Update events: store it here so that Update disposition lookups can be fast.
2079 > ms.eventsCache.PutEvent(
2080 > events.EventKey{
2081 > NamespaceID: namespace.ID(ms.executionInfo.NamespaceId),
2082 > WorkflowID: ms.executionInfo.WorkflowId,
2083 > RunID: ms.executionState.RunId,
2084 > EventID: event.GetEventId(),
2085 > Version: event.GetVersion(),
2086 > },
2087 > event,
2088 > )
2089 > }
2090
2091 > func (ms *MutableStateImpl) HasParentExecution() bool { mutable_state_impl.go
2092 > return ms.executionInfo.ParentNamespaceId != "" && ms.executionInfo.ParentWorkflowId != ""
2093 > }
2094
2095 func (ms *MutableStateImpl) UpdateActivityProgress(
2336
2337 // GetWorkflowTaskByID returns details about the current workflow task by scheduled event ID.
2338 > func (ms *MutableStateImpl) GetWorkflowTaskByID(scheduledEventID int64) *historyi.WorkflowTaskInfo { mutable_state_impl.go
2339 > return ms.workflowTaskManager.GetWorkflowTaskByID(scheduledEventID)
2340 > }
2341
2342 > func (ms *MutableStateImpl) GetPendingActivityInfos() map[int64]*persistencespb.ActivityInfo { mutable_state_impl.go
2343 > return ms.pendingActivityInfoIDs
2344 > }
2345
2346 > func (ms *MutableStateImpl) GetPendingTimerInfos() map[string]*persistencespb.TimerInfo { mutable_state_impl.go
2347 > return ms.pendingTimerInfoIDs
2348 > }
2349
2350 > func (ms *MutableStateImpl) GetPendingChildExecutionInfos() map[int64]*persistencespb.ChildExecutionInfo { mutable_state_impl.go
2351 > return ms.pendingChildExecutionInfoIDs
2352 > }
2353
2354 func (ms *MutableStateImpl) GetPendingChildIds() map[int64]struct{} {
2360 }
2361
2362 > func (ms *MutableStateImpl) GetPendingRequestCancelExternalInfos() map[int64]*persistencespb.RequestCancelInfo { mutable_state_impl.go
2363 > return ms.pendingRequestCancelInfoIDs
2364 > }
2365
2366 > func (ms *MutableStateImpl) GetPendingSignalExternalInfos() map[int64]*persistencespb.SignalInfo { mutable_state_impl.go
2367 > return ms.pendingSignalInfoIDs
2368 > }
2369
2370 func (ms *MutableStateImpl) GetPendingSignalRequestedIds() []string {
2380 }
2381
2382 > func (ms *MutableStateImpl) GetPendingWorkflowTask() *historyi.WorkflowTaskInfo { mutable_state_impl.go
2383 > return ms.workflowTaskManager.GetPendingWorkflowTask()
2384 > }
2385
2386 > func (ms *MutableStateImpl) HasStartedWorkflowTask() bool { mutable_state_impl.go
2387 > return ms.workflowTaskManager.HasStartedWorkflowTask()
2388 > }
2389
2390 > func (ms *MutableStateImpl) GetStartedWorkflowTask() *historyi.WorkflowTaskInfo { mutable_state_impl.go
2391 > return ms.workflowTaskManager.GetStartedWorkflowTask()
2392 > }
2393
2394 > func (ms *MutableStateImpl) IsTransientWorkflowTask() bool { mutable_state_impl.go
2395 > return ms.executionInfo.WorkflowTaskAttempt > 1
2396 > }
2397
2398 func (ms *MutableStateImpl) ClearTransientWorkflowTask() error {
2441 }
2442
2443 > func (ms *MutableStateImpl) GetAssignedBuildId() string { mutable_state_impl.go
2444 > return ms.executionInfo.AssignedBuildId
2445 > }
2446
2447 > func (ms *MutableStateImpl) GetInheritedBuildId() string { mutable_state_impl.go
2448 > return ms.executionInfo.InheritedBuildId
2449 > }
2450
2451 > func (ms *MutableStateImpl) GetMostRecentWorkerVersionStamp() *commonpb.WorkerVersionStamp { mutable_state_impl.go
2452 > return ms.executionInfo.MostRecentWorkerVersionStamp
2453 > }
2454
2455 > func (ms *MutableStateImpl) HasBufferedEvents() bool { mutable_state_impl.go
2456 > return ms.hBuilder.HasBufferEvents()
2457 > }
2458
2459 // HasAnyBufferedEvent returns true if there is at least one buffered event that matches the provided filter.
2464 // GetLastFirstEventIDTxnID returns last first event ID and corresponding transaction ID
2465 // first event ID is the ID of a batch of events in a single history events record
2466 > func (ms *MutableStateImpl) GetLastFirstEventIDTxnID() (int64, int64) { mutable_state_impl.go
2467 > return ms.executionInfo.LastFirstEventId, ms.executionInfo.LastFirstEventTxnId
2468 > }
2469
2470 // GetNextEventID returns next event ID
2471 > func (ms *MutableStateImpl) GetNextEventID() int64 { mutable_state_impl.go
2472 > return ms.hBuilder.NextEventID()
2473 > }
2474
2475 // GetStartedEventIdForLastCompletedWorkflowTask returns last started workflow task event ID
2476 > func (ms *MutableStateImpl) GetLastCompletedWorkflowTaskStartedEventId() int64 { mutable_state_impl.go
2477 > return ms.executionInfo.LastCompletedWorkflowTaskStartedEventId
2478 > }
2479
2480 > func (ms *MutableStateImpl) IsWorkflowExecutionRunning() bool { mutable_state_impl.go
2481 > switch ms.executionState.State {
2482 > case enumsspb.WORKFLOW_EXECUTION_STATE_CREATED: mutable_state_impl.go
2483 > return true
2484 > case enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING: mutable_state_impl.go
2485 > return true
2486 > case enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: mutable_state_impl.go
2487 > return false
2488 case enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:
2489 return false
2534 // GetApproximatePersistedSize returns approximate size of in-memory objects that will be written to
2535 // persistence + size of buffered events in history builder if they will not be flushed
2536 > func (ms *MutableStateImpl) GetApproximatePersistedSize() int { mutable_state_impl.go
2537 > // include buffered events in the size if they will not be flushed
2538 > if ms.BufferSizeAcceptable() && ms.HasStartedWorkflowTask() {
2539 > return ms.approximateSize + ms.hBuilder.SizeInBytesOfBufferedEvents() mutable_state_impl.go
2540 > }
2541 > return ms.approximateSize mutable_state_impl.go
2542 }
2543
2580 eventType enumspb.EventType,
2581 eventID int64,
2583 > ms.approximateSize -= ms.executionState.Size()
2584 > if ms.executionState.RequestIds == nil {
2585 ms.executionState.RequestIds = make(map[string]*persistencespb.RequestIDInfo, 1)
2586 }
2587 > ms.executionState.RequestIds[requestID] = &persistencespb.RequestIDInfo{ mutable_state_impl.go
2588 > EventType: eventType,
2589 > EventId: eventID,
2590 > }
2591 > if eventType == enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_STARTED {
2592 > ms.executionState.CreateRequestId = requestID
2593 > }
2594 > ms.approximateSize += ms.executionState.Size()
2595 }
2596
2887 execution *commonpb.WorkflowExecution,
2888 startRequest *historyservice.StartWorkflowExecutionRequest,
2889 > ) (*historypb.HistoryEvent, error) { mutable_state_impl.go
2890 > return ms.AddWorkflowExecutionStartedEventWithOptions(
2891 > execution,
2892 > startRequest,
2893 > nil, // resetPoints
2894 > "", // prevRunID
2895 > execution.GetRunId(),
2896 > )
2897 > }
2898
2899 func (ms *MutableStateImpl) AddWorkflowExecutionStartedEventWithOptions(
2903 prevRunID string,
2904 firstRunID string,
2905 > ) (*historypb.HistoryEvent, error) { mutable_state_impl.go
2906 > opTag := tag.WorkflowActionWorkflowStarted
2907 > if err := ms.checkMutability(opTag); err != nil {
2908 return nil, err
2909 }
2910
2911 > eventID := ms.GetNextEventID() mutable_state_impl.go
2912 > if eventID != common.FirstEventID {
2913 ms.logger.Warn(mutableStateInvalidHistoryActionMsg, opTag,
2914 tag.WorkflowEventID(eventID),
2917 }
2918
2919 > event := ms.hBuilder.AddWorkflowExecutionStartedEvent( mutable_state_impl.go
2920 > ms.executionState.StartTime.AsTime(),
2921 > startRequest,
2922 > resetPoints,
2923 > prevRunID,
2924 > firstRunID,
2925 > execution.GetRunId(),
2926 > )
2927 > if err := ms.ApplyWorkflowExecutionStartedEvent(
2928 > startRequest.GetParentExecutionInfo().GetClock(),
2929 > execution,
2930 > startRequest.StartRequest.GetRequestId(),
2931 > event,
2932 > ); err != nil {
2933 return nil, err
2934 }
2935
2936 // TODO merge active & passive task generation
2937 > var err error mutable_state_impl.go
2938 > ms.executionInfo.WorkflowExecutionTimerTaskStatus, err = ms.taskGenerator.GenerateWorkflowStartTasks(
2939 > event,
2940 > )
2941 > if err != nil {
2942 return nil, err
2943 }
2944
2945 > if err := ms.taskGenerator.GenerateRecordWorkflowStartedTasks( mutable_state_impl.go
2946 > event,
2947 > ); err != nil {
2948 return nil, err
2949 }
2950
2951 // Versioning Override set on StartWorkflowExecutionRequest
2952 > if startRequest.GetStartRequest().GetVersioningOverride() != nil { mutable_state_impl.go
2953 metrics.WorkerDeploymentVersioningOverrideCounter.With(
2954 ms.metricsHandler.WithTags(
2969 requestID string,
2970 startEvent *historypb.HistoryEvent,
2971 > ) error { mutable_state_impl.go
2972 > if ms.executionInfo.NamespaceId != ms.namespaceEntry.ID().String() {
2973 return serviceerror.NewInternalf("applying conflicting namespace ID: %v != %v",
2974 ms.executionInfo.NamespaceId, ms.namespaceEntry.ID().String())
2975 }
2976 > if ms.executionInfo.WorkflowId != execution.GetWorkflowId() { mutable_state_impl.go
2977 return serviceerror.NewInternalf("applying conflicting workflow ID: %v != %v",
2978 ms.executionInfo.WorkflowId, execution.GetWorkflowId())
2979 }
2980 > if ms.executionState.RunId != execution.GetRunId() { mutable_state_impl.go
2981 return serviceerror.NewInternalf("applying conflicting run ID: %v != %v",
2982 ms.executionState.RunId, execution.GetRunId())
2983 }
2984
2985 > event := startEvent.GetWorkflowExecutionStartedEventAttributes() mutable_state_impl.go
2986 > ms.AttachRequestID(requestID, startEvent.EventType, startEvent.EventId)
2987 >
2988 > ms.approximateSize -= ms.executionInfo.Size()
2989 > ms.executionInfo.FirstExecutionRunId = event.GetFirstExecutionRunId()
2990 > ms.executionInfo.TaskQueue = event.TaskQueue.GetName()
2991 > ms.executionInfo.WorkflowTypeName = event.WorkflowType.GetName()
2992 > ms.executionInfo.WorkflowRunTimeout = event.GetWorkflowRunTimeout()
2993 > ms.executionInfo.WorkflowExecutionTimeout = event.GetWorkflowExecutionTimeout()
2994 > ms.executionInfo.DefaultWorkflowTaskTimeout = event.GetWorkflowTaskTimeout()
2995 > ms.executionInfo.OriginalExecutionRunId = event.GetOriginalExecutionRunId()
2996 >
2997 > ms.approximateSize -= ms.executionState.Size()
2998 > ms.executionState.FirstExecutionRunId = event.GetFirstExecutionRunId()
2999 > if err := ms.addCompletionCallbacks(
3000 > startEvent,
3001 > requestID,
3002 > event.GetCompletionCallbacks(),
3003 > ); err != nil {
3004 return err
3005 }
3006 > if _, err := ms.UpdateWorkflowStateStatus( mutable_state_impl.go
3007 > enumsspb.WORKFLOW_EXECUTION_STATE_CREATED,
3008 > enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING,
3009 > ); err != nil {
3010 return err
3011 }
3012 > ms.executionInfo.LastCompletedWorkflowTaskStartedEventId = common.EmptyEventID mutable_state_impl.go
3013 > ms.executionInfo.LastFirstEventId = startEvent.GetEventId()
3014 >
3015 > ms.executionInfo.WorkflowTaskVersion = common.EmptyVersion
3016 > ms.executionInfo.WorkflowTaskScheduledEventId = common.EmptyEventID
3017 > ms.executionInfo.WorkflowTaskStartedEventId = common.EmptyEventID
3018 > ms.executionInfo.WorkflowTaskRequestId = emptyUUID
3019 > ms.executionInfo.WorkflowTaskTimeout = timestamp.DurationFromSeconds(0)
3020 >
3021 > ms.executionInfo.CronSchedule = event.GetCronSchedule()
3022 >
3023 > if event.ParentWorkflowExecution != nil {
3024 ms.executionInfo.ParentNamespaceId = event.GetParentWorkflowNamespaceId()
3025 ms.executionInfo.ParentWorkflowId = event.ParentWorkflowExecution.GetWorkflowId()
3028 }
3029
3030 > if event.ParentInitiatedEventId != 0 { mutable_state_impl.go
3031 ms.executionInfo.ParentInitiatedId = event.GetParentInitiatedEventId()
3032 > } else { mutable_state_impl.go
3033 > ms.executionInfo.ParentInitiatedId = common.EmptyEventID mutable_state_impl.go
3034 > }
3035
3036 > if event.ParentInitiatedEventVersion != 0 { mutable_state_impl.go
3037 ms.executionInfo.ParentInitiatedVersion = event.GetParentInitiatedEventVersion()
3038 > } else { mutable_state_impl.go
3039 > ms.executionInfo.ParentInitiatedVersion = common.EmptyVersion mutable_state_impl.go
3040 > }
3041
3042 > if event.RootWorkflowExecution != nil { mutable_state_impl.go
3043 ms.executionInfo.RootWorkflowId = event.RootWorkflowExecution.GetWorkflowId()
3044 ms.executionInfo.RootRunId = event.RootWorkflowExecution.GetRunId()
3045 > } else { mutable_state_impl.go
3046 > ms.executionInfo.RootWorkflowId = execution.GetWorkflowId()
3047 > ms.executionInfo.RootRunId = execution.GetRunId()
3048 > }
3049
3050 // todo@time-skipping: apply time skipping to WorkflowStartDelay
3051 > ms.executionInfo.ExecutionTime = timestamppb.New( mutable_state_impl.go
3052 > ms.executionState.StartTime.AsTime().Add(event.GetFirstWorkflowTaskBackoff().AsDuration()),
3053 > )
3054 >
3055 > ms.executionInfo.Attempt = event.GetAttempt()
3056 > if !timestamp.TimeValue(event.GetWorkflowExecutionExpirationTime()).IsZero() {
3057 ms.executionInfo.WorkflowExecutionExpirationTime = event.GetWorkflowExecutionExpirationTime()
3058 }
3059
3060 > var workflowRunTimeoutTime time.Time mutable_state_impl.go
3061 > workflowRunTimeoutDuration := ms.executionInfo.WorkflowRunTimeout.AsDuration()
3062 > // if workflowRunTimeoutDuration == 0 then the workflowRunTimeoutTime will be 0
3063 > // meaning that there is not workflow run timeout
3064 > if workflowRunTimeoutDuration != 0 {
3065 firstWorkflowTaskDelayDuration := event.GetFirstWorkflowTaskBackoff().AsDuration()
3066 workflowRunTimeoutDuration = workflowRunTimeoutDuration + firstWorkflowTaskDelayDuration
3072 }
3073 }
3074 > ms.executionInfo.WorkflowRunExpirationTime = timestamppb.New(workflowRunTimeoutTime) mutable_state_impl.go
3075 >
3076 > if event.RetryPolicy != nil {
3077 ms.executionInfo.HasRetryPolicy = true
3078 ms.executionInfo.RetryBackoffCoefficient = event.RetryPolicy.GetBackoffCoefficient()
3083 }
3084
3085 > ms.executionInfo.AutoResetPoints = rolloverAutoResetPointsWithExpiringTime( mutable_state_impl.go
3086 > event.GetPrevAutoResetPoints(),
3087 > event.GetContinuedExecutionRunId(),
3088 > timestamp.TimeValue(startEvent.GetEventTime()),
3089 > ms.namespaceEntry.Retention(),
3090 > )
3091 >
3092 > if event.Memo != nil {
3093 ms.executionInfo.Memo = event.Memo.GetFields()
3094 }
3095 > if event.SearchAttributes != nil { mutable_state_impl.go
3096 ms.executionInfo.SearchAttributes = event.SearchAttributes.GetIndexedFields()
3097 }
3098
3099 > if event.GetVersioningOverride() != nil { mutable_state_impl.go
3100 if ms.executionInfo.VersioningInfo == nil {
3101 ms.executionInfo.VersioningInfo = &workflowpb.WorkflowExecutionVersioningInfo{}
3136 }
3137
3138 > if event.GetInheritedPinnedVersion() != nil { mutable_state_impl.go
3139 if ms.executionInfo.VersioningInfo == nil {
3140 ms.executionInfo.VersioningInfo = &workflowpb.WorkflowExecutionVersioningInfo{}
3147 // target version upgrade from the started event. This is the same public API
3148 // type, so no conversion needed.
3149 > if event.GetContinuedExecutionRunId() != "" && event.GetInheritedPinnedVersion() != nil { mutable_state_impl.go
3150 ms.executionInfo.DeclinedTargetVersionUpgrade = event.GetDeclinedTargetVersionUpgrade()
3151 }
3152
3153 // Populate the versioningInfo if the inheritedAutoUpgradeInfo is present.
3154 > if event.GetInheritedAutoUpgradeInfo() != nil { mutable_state_impl.go
3155 ms.SetVersioningRevisionNumber(event.GetInheritedAutoUpgradeInfo().GetSourceDeploymentRevisionNumber())
3156 // TODO (Shivam): Remove this once you make SetDeploymentVersion and SetVersioningBehavior methods with nil checks
3164 }
3165
3166 > if inheritedBuildId := event.InheritedBuildId; inheritedBuildId != "" { mutable_state_impl.go
3167 ms.executionInfo.InheritedBuildId = inheritedBuildId
3168 if err := ms.UpdateBuildIdAssignment(inheritedBuildId); err != nil {
3169 return err
3170 }
3171 > } else if event.SourceVersionStamp.GetUseVersioning() && event.SourceVersionStamp.GetBuildId() != "" || mutable_state_impl.go
3172 > ms.GetEffectiveVersioningBehavior() != enumspb.VERSIONING_BEHAVIOR_UNSPECIFIED {
3173 // TODO: [cleanup-old-wv]
3174 limit := ms.config.SearchAttributesSizeOfValueLimit(string(ms.namespaceEntry.Name()))
3181
3182 // This will include override and inheritance, but not transition, because WF never starts with a transition
3183 > ms.executionInfo.WorkerDeploymentName = ms.GetEffectiveDeployment().GetSeriesName() mutable_state_impl.go
3184 >
3185 > if inheritedBuildId := event.InheritedBuildId; inheritedBuildId != "" {
3186 ms.executionInfo.InheritedBuildId = inheritedBuildId
3187 if err := ms.UpdateBuildIdAssignment(inheritedBuildId); err != nil {
3190 }
3191
3192 > ms.executionInfo.MostRecentWorkerVersionStamp = event.SourceVersionStamp mutable_state_impl.go
3193 > ms.executionInfo.Priority = event.Priority
3194 >
3195 > if tsc, stateProp := event.GetTimeSkippingConfig(), event.GetTimeSkippingStatePropagation(); tsc != nil || stateProp.GetInitialSkippedDuration().AsDuration() > 0 {
3196 if err := ms.initTimeSkippingInfo(tsc, stateProp); err != nil {
3197 return err
3199 }
3200
3201 > ms.approximateSize += ms.executionInfo.Size() mutable_state_impl.go
3202 > ms.approximateSize += ms.executionState.Size()
3203 >
3204 > ms.writeEventToCache(startEvent)
3205 > return nil
3206 }
3207
3208 > func (ms *MutableStateImpl) IsWorkflowExecutionStatusPaused() bool { mutable_state_impl.go
3209 > return ms.executionState.GetStatus() == enumspb.WORKFLOW_EXECUTION_STATUS_PAUSED
3210 > }
3211
3212 func (ms *MutableStateImpl) AddWorkflowExecutionPausedEvent(
3386 requestID string,
3387 completionCallbacks []*commonpb.Callback,
3388 > ) error { mutable_state_impl.go
3389 > if len(completionCallbacks) == 0 {
3390 > return nil mutable_state_impl.go
3391 > }
3392 if ms.chasmCallbacksEnabled() {
3393 // Initialize chasm tree once for new workflows.
3471 startEvent *historypb.HistoryEvent,
3472 bypassTaskGeneration bool,
3473 > ) (int64, error) { mutable_state_impl.go
3474 > opTag := tag.WorkflowActionWorkflowTaskScheduled
3475 > if err := ms.checkMutability(opTag); err != nil {
3476 return common.EmptyEventID, err
3477 }
3478 > scheduleEventID, err := ms.workflowTaskManager.AddFirstWorkflowTaskScheduled(startEvent, bypassTaskGeneration) mutable_state_impl.go
3479 > if err != nil {
3480 return 0, err
3481 }
3482 > if parentClock != nil { mutable_state_impl.go
3483 ms.executionInfo.ParentClock = parentClock
3484 }
3485 > return scheduleEventID, nil mutable_state_impl.go
3486 }
3487
3538 targetDeploymentVersion *deploymentpb.WorkerDeploymentVersion,
3539 targetRevisionNumber int64,
3540 > ) (*historypb.HistoryEvent, *historyi.WorkflowTaskInfo, error) { mutable_state_impl.go
3541 > opTag := tag.WorkflowActionWorkflowTaskStarted
3542 > if err := ms.checkMutability(opTag); err != nil {
3543 return nil, nil, err
3544 }
3545 > return ms.workflowTaskManager.AddWorkflowTaskStartedEvent(scheduledEventID, requestID, taskQueue, identity, versioningStamp, redirectInfo, skipVersioningCheck, updateReg, targetDeploymentVersion, targetRevisionNumber) mutable_state_impl.go
3546 }
3547
3568 workflowTask *historyi.WorkflowTaskInfo,
3569 identity string,
3570 > ) *historyspb.TransientWorkflowTaskInfo { mutable_state_impl.go
3571 > if !ms.IsTransientWorkflowTask() && workflowTask.Type != enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE {
3572 > return nil mutable_state_impl.go
3573 > }
3574 return ms.workflowTaskManager.GetTransientWorkflowTaskInfo(workflowTask, identity)
3575 }
3607 eventID int64,
3608 maxResetPoints int,
3609 > ) bool { mutable_state_impl.go
3610 > resetPoints := ms.executionInfo.AutoResetPoints.GetPoints()
3611 > for _, rp := range resetPoints {
3612 if rp.GetBinaryChecksum() == binaryChecksum && rp.GetBuildId() == buildId {
3613 return false
3617 // todo@time-skipping: time skipping is naturally supported for auto reset points, and need to
3618 // decide if this the best default policy for auto reset points
3619 > newPoint := &workflowpb.ResetPointInfo{ mutable_state_impl.go
3620 > BinaryChecksum: binaryChecksum,
3621 > BuildId: buildId,
3622 > RunId: ms.executionState.GetRunId(),
3623 > FirstWorkflowTaskCompletedId: eventID,
3624 > CreateTime: timestamppb.New(ms.timeSource.Now()),
3625 > Resettable: ms.CheckResettable() == nil,
3626 > }
3627 > ms.executionInfo.AutoResetPoints = &workflowpb.ResetPoints{
3628 > Points: util.SliceTail(append(resetPoints, newPoint), maxResetPoints),
3629 > }
3630 > return true
3631 }
3632
3762 usedVersion *deploymentpb.WorkerDeploymentVersion,
3763 maxSearchAttributeValueSize int,
3764 > ) error { mutable_state_impl.go
3765 > changed, err := ms.addBuildIDAndDeploymentInfoToSearchAttributesWithNoVisibilityTask(stamp, usedVersion, maxSearchAttributeValueSize)
3766 > if err != nil {
3767 return err
3768 }
3769
3770 > if !changed { mutable_state_impl.go
3771 return nil
3772 }
3773 > return ms.taskGenerator.GenerateUpsertVisibilityTask() mutable_state_impl.go
3774 }
3775
3776 > func (ms *MutableStateImpl) loadBuildIds() ([]string, error) { mutable_state_impl.go
3777 > searchAttributes := ms.executionInfo.SearchAttributes
3778 > if searchAttributes == nil {
3779 > return []string{}, nil
3780 > }
3781 saPayload, found := searchAttributes[sadefs.BuildIds]
3782 if !found {
3797 }
3798
3799 > func (ms *MutableStateImpl) loadSearchAttributeString(saName string) (string, error) { mutable_state_impl.go
3800 > searchAttributes := ms.executionInfo.SearchAttributes
3801 > if searchAttributes == nil {
3802 > return "", nil
3803 > }
3804 saPayload, found := searchAttributes[saName]
3805 if !found {
3820 }
3821
3822 > func (ms *MutableStateImpl) loadUsedDeploymentVersions() ([]string, error) { mutable_state_impl.go
3823 > searchAttributes := ms.executionInfo.SearchAttributes
3824 > if searchAttributes == nil {
3825 > return []string{}, nil
3826 > }
3827 saPayload, found := searchAttributes[sadefs.TemporalUsedWorkerDeploymentVersions]
3828 if !found {
3851 existingValues []string,
3852 stamp *commonpb.WorkerVersionStamp,
3853 > ) []string { mutable_state_impl.go
3854 > var newValues []string
3855 > var buildId string
3856 >
3857 > behavior := ms.GetWorkflowVersioningBehaviorSA()
3858 >
3859 > // set up the unversioned or assigned:x sentinels (versioning v2)
3860 > if !stamp.GetUseVersioning() && behavior == enumspb.VERSIONING_BEHAVIOR_UNSPECIFIED { // unversioned workflows may still have non-nil deployment, so we don't check deployment
3861 > newValues = append(newValues, worker_versioning.UnversionedSearchAttribute)
3862 > } else if ms.GetAssignedBuildId() != "" && behavior == enumspb.VERSIONING_BEHAVIOR_UNSPECIFIED {
3863 newValues = append(newValues, worker_versioning.AssignedBuildIdSearchAttribute(ms.GetAssignedBuildId()))
3864 }
3865
3866 // get the most up-to-date pinned entry put it at the front (v3 reachability and v3.1 drainage)
3867 > if behavior == enumspb.VERSIONING_BEHAVIOR_PINNED { mutable_state_impl.go
3868 newValues = append(newValues, worker_versioning.PinnedBuildIdSearchAttribute(ms.GetWorkerDeploymentVersionSA()))
3869 }
3870
3871 // get the build id entry (all versions of versioning)
3872 > if stamp != nil { mutable_state_impl.go
3873 > buildId = worker_versioning.VersionStampToBuildIdSearchAttribute(stamp) mutable_state_impl.go
3874 > }
3875
3876 // add all previous values except for unversioned, assigned, or pinned (there can only be one, and we just added it)
3877 > foundBuildId := false mutable_state_impl.go
3878 > for _, existingValue := range existingValues {
3879 if existingValue == buildId {
3880 foundBuildId = true
3887
3888 // add buildId to the list only if it wasn't there before
3889 > if !foundBuildId && buildId != "" { mutable_state_impl.go
3890 > newValues = append(newValues, buildId) mutable_state_impl.go
3891 > }
3892 > return newValues mutable_state_impl.go
3893 }
3894
3895 > func (ms *MutableStateImpl) addUsedDeploymentVersionToLoadedSearchAttribute(existingValues []string, usedVersion *deploymentpb.WorkerDeploymentVersion) []string { mutable_state_impl.go
3896 > if usedVersion == nil {
3897 > return existingValues
3898 > }
3899
3900 // Get the current deployment version string (already formatted via ExternalWorkerDeploymentVersionToString)
3918 }
3919
3920 > func (ms *MutableStateImpl) saveBuildIds(buildIds []string, maxSearchAttributeValueSize int) error { mutable_state_impl.go
3921 > searchAttributes := ms.executionInfo.SearchAttributes
3922 > if searchAttributes == nil {
3923 > searchAttributes = make(map[string]*commonpb.Payload, 1)
3924 > ms.executionInfo.SearchAttributes = searchAttributes
3925 > }
3926
3927 > hasUnversionedOrAssigned := false mutable_state_impl.go
3928 > if len(buildIds) > 0 { // len is 0 if we are removing the pinned search attribute and the workflow was never unversioned or assigned
3929 > hasUnversionedOrAssigned = worker_versioning.IsUnversionedOrAssignedBuildIdSearchAttribute(buildIds[0])
3930 > }
3931 > for {
3932 > saPayload, err := sadefs.EncodeValue(buildIds, enumspb.INDEXED_VALUE_TYPE_KEYWORD_LIST)
3933 > if err != nil {
3934 return err
3935 }
3936 > if len(buildIds) == 0 || len(saPayload.GetData()) <= maxSearchAttributeValueSize { mutable_state_impl.go
3937 > ms.updateSearchAttributes(map[string]*commonpb.Payload{sadefs.BuildIds: saPayload})
3938 > break
3939 }
3940 if len(buildIds) == 1 {
4025 usedVersion *deploymentpb.WorkerDeploymentVersion,
4026 maxSearchAttributeValueSize int,
4027 > ) (bool, error) { mutable_state_impl.go
4028 > // get all the existing SAs
4029 > existingBuildIds, err := ms.loadBuildIds()
4030 > if err != nil {
4031 return false, err
4032 }
4033 > existingUsedDeploymentVersions, err := ms.loadUsedDeploymentVersions() mutable_state_impl.go
4034 > if err != nil {
4035 return false, err
4036 }
4037 > existingDeployment, err := ms.loadSearchAttributeString(sadefs.TemporalWorkerDeployment) mutable_state_impl.go
4038 > if err != nil {
4039 return false, err
4040 }
4041 > existingVersion, err := ms.loadSearchAttributeString(sadefs.TemporalWorkerDeploymentVersion) mutable_state_impl.go
4042 > if err != nil {
4043 return false, err
4044 }
4045 > existingBehavior, err := ms.loadSearchAttributeString(sadefs.TemporalWorkflowVersioningBehavior) mutable_state_impl.go
4046 > if err != nil {
4047 return false, err
4048 }
4049
4050 // modify them
4051 > modifiedBuildIds := ms.addBuildIdToLoadedSearchAttribute(existingBuildIds, stamp) mutable_state_impl.go
4052 > modifiedUsedDeploymentVersions := ms.addUsedDeploymentVersionToLoadedSearchAttribute(existingUsedDeploymentVersions, usedVersion)
4053 > modifiedDeployment := ms.GetWorkerDeploymentSA()
4054 > modifiedVersion := ms.GetWorkerDeploymentVersionSA()
4055 > modifiedBehavior := ""
4056 > if b := ms.GetWorkflowVersioningBehaviorSA(); b != enumspb.VERSIONING_BEHAVIOR_UNSPECIFIED {
4057 modifiedBehavior = b.String()
4058 }
4059
4060 // check equality
4061 > if slices.Equal(existingBuildIds, modifiedBuildIds) && mutable_state_impl.go
4062 > slices.Equal(existingUsedDeploymentVersions, modifiedUsedDeploymentVersions) &&
4063 > existingDeployment == modifiedDeployment &&
4064 > existingVersion == modifiedVersion &&
4065 > existingBehavior == modifiedBehavior {
4066 return false, nil
4067 }
4068
4069 // save build ids if changed
4070 > if !slices.Equal(existingBuildIds, modifiedBuildIds) { mutable_state_impl.go
4071 > err = ms.saveBuildIds(modifiedBuildIds, maxSearchAttributeValueSize)
4072 > if err != nil {
4073 return false, err // if err != nil, nothing will be written
4074 }
4076
4077 // save used deployment versions if changed
4078 > if !slices.Equal(existingUsedDeploymentVersions, modifiedUsedDeploymentVersions) { mutable_state_impl.go
4079 err = ms.saveUsedDeploymentVersions(modifiedUsedDeploymentVersions, maxSearchAttributeValueSize)
4080 if err != nil {
4084
4085 // save deployment search attributes if changed
4086 > if existingDeployment != modifiedDeployment || mutable_state_impl.go
4087 > existingVersion != modifiedVersion ||
4088 > existingBehavior != modifiedBehavior {
4089 err = ms.saveDeploymentSearchAttributes(modifiedDeployment, modifiedVersion, modifiedBehavior, maxSearchAttributeValueSize)
4090 if err != nil {
4098
4099 // CheckResettable check if workflow can be reset
4100 > func (ms *MutableStateImpl) CheckResettable() error { mutable_state_impl.go
4101 > if len(ms.GetPendingChildExecutionInfos()) > 0 {
4102 return serviceerror.NewInvalidArgument("it is not allowed resetting to a point that workflow has pending child workflow.")
4103 }
4104 > if len(ms.GetPendingRequestCancelExternalInfos()) > 0 { mutable_state_impl.go
4105 return serviceerror.NewInvalidArgument("it is not allowed resetting to a point that workflow has pending request cancel.")
4106 }
4107 > if len(ms.GetPendingSignalExternalInfos()) > 0 { mutable_state_impl.go
4108 return serviceerror.NewInvalidArgument("it is not allowed resetting to a point that workflow has pending signals to send.")
4109 }
4110 > return nil mutable_state_impl.go
4111 }
4112
4115 request *workflowservice.RespondWorkflowTaskCompletedRequest,
4116 limits historyi.WorkflowTaskCompletionLimits,
4117 > ) (*historypb.HistoryEvent, error) { mutable_state_impl.go
4118 > opTag := tag.WorkflowActionWorkflowTaskCompleted
4119 > if err := ms.checkMutability(opTag); err != nil {
4120 return nil, err
4121 }
4122 > return ms.workflowTaskManager.AddWorkflowTaskCompletedEvent(workflowTask, request, limits) mutable_state_impl.go
4123 }
4124
4664 // GenerateActivityCancelCommandsForClose generates WorkerCommandsTasks to cancel all
4665 // in-flight activities that have a worker control queue.
4666 > func (ms *MutableStateImpl) GenerateActivityCancelCommandsForClose() error { mutable_state_impl.go
4667 > if !ms.config.EnableCancelActivityWorkerCommand(ms.namespaceEntry.Name().String()) {
4668 > return nil mutable_state_impl.go
4669 > }
4670
4671 // Cancel commands are best-effort and only dispatched on the active cluster.
4829 command *commandpb.CompleteWorkflowExecutionCommandAttributes,
4830 newExecutionRunID string,
4831 > ) (*historypb.HistoryEvent, error) { mutable_state_impl.go
4832 > opTag := tag.WorkflowActionWorkflowCompleted
4833 > if err := ms.checkMutability(opTag); err != nil {
4834 return nil, err
4835 }
4836
4837 > event, batchID := ms.hBuilder.AddCompletedWorkflowEvent(workflowTaskCompletedEventID, command, newExecutionRunID) mutable_state_impl.go
4838 > if err := ms.ApplyWorkflowExecutionCompletedEvent(batchID, event); err != nil {
4839 return nil, err
4840 }
4841 // TODO merge active & passive task generation
4842 > if err := ms.taskGenerator.GenerateWorkflowCloseTasks( mutable_state_impl.go
4843 > event.GetEventTime().AsTime(),
4844 > false,
4845 > false, // skipCloseTransferTask
4846 > ); err != nil {
4847 return nil, err
4848 }
4849 > return event, nil mutable_state_impl.go
4850 }
4851
4853 batchID int64,
4854 event *historypb.HistoryEvent,
4855 > ) error { mutable_state_impl.go
4856 > if _, err := ms.UpdateWorkflowStateStatus(
4857 > enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED,
4858 > enumspb.WORKFLOW_EXECUTION_STATUS_COMPLETED,
4859 > ); err != nil {
4860 return err
4861 }
4862 > ms.executionInfo.CompletionEventBatchId = batchID // Used when completion event needs to be loaded from database mutable_state_impl.go
4863 > ms.executionInfo.NewExecutionRunId = event.GetWorkflowExecutionCompletedEventAttributes().GetNewExecutionRunId()
4864 > ms.executionInfo.CloseTime = event.GetEventTime()
4865 > ms.ClearStickyTaskQueue()
4866 > ms.writeEventToCache(event)
4867 > return ms.processCloseCallbacks()
4868 }
4869
6305 newExecutionStartTime time.Time,
6306 namespaceRetention time.Duration,
6307 > ) *workflowpb.ResetPoints { mutable_state_impl.go
6308 > if resetPoints.GetPoints() == nil {
6309 > return resetPoints
6310 > }
6311 newPoints := make([]*workflowpb.ResetPointInfo, 0, len(resetPoints.Points))
6312 // For continue-as-new, new execution start time is the same as previous execution close time,
7043 }
7044
7045 > func (ms *MutableStateImpl) RemoveReportedProblemsSearchAttribute() error { mutable_state_impl.go
7046 > if ms.executionInfo.SearchAttributes == nil {
7047 return nil
7048 }
7049
7050 > temporalReportedProblems := ms.executionInfo.SearchAttributes[sadefs.TemporalReportedProblems] mutable_state_impl.go
7051 > if temporalReportedProblems == nil {
7052 > return nil
7053 > }
7054
7055 // Log the removal of the search attribute
7140 }
7141
7142 > func (ms *MutableStateImpl) AddExternalPayloadSize(size int64) { mutable_state_impl.go
7143 > if ms.executionInfo.ExecutionStats == nil {
7144 ms.executionInfo.ExecutionStats = &persistencespb.ExecutionStats{}
7145 }
7146 > ms.executionInfo.ExecutionStats.ExternalPayloadSize += size mutable_state_impl.go
7147 }
7148
7151 }
7152
7153 > func (ms *MutableStateImpl) AddExternalPayloadCount(count int64) { mutable_state_impl.go
7154 > if ms.executionInfo.ExecutionStats == nil {
7155 ms.executionInfo.ExecutionStats = &persistencespb.ExecutionStats{}
7156 }
7157 > ms.executionInfo.ExecutionStats.ExternalPayloadCount += count mutable_state_impl.go
7158 }
7159
7189 // processCloseCallbacks triggers "WorkflowClosed" callbacks, applying the state machine transition that schedules
7190 // callback tasks.
7191 > func (ms *MutableStateImpl) processCloseCallbacks() error { mutable_state_impl.go
7192 > resetRunID := ms.GetExecutionInfo().GetResetRunId()
7193 > if ms.GetExecutionInfo().GetWorkflowWasReset() && resetRunID != "" && resetRunID != ms.executionState.RunId {
7194 return nil
7195 }
7199 // were enabled can still be triggered even if the EnableCHASMCallbacks dynamic config is later
7200 // turned off. Once created in CHASM, callbacks should always be processed as long as CHASM is enabled.
7201 > if ms.ChasmEnabled() { mutable_state_impl.go
7202 > if err := ms.processCloseCallbacksChasm(); err != nil { mutable_state_impl.go
7203 return err
7204 }
7206
7207 // Always process HSM callbacks as well (a workflow can have both)
7208 > return ms.processCloseCallbacksHsm() mutable_state_impl.go
7209 }
7210
7211 // processCloseCallbacksHsm triggers "WorkflowClosed" callbacks using the HSM implementation.
7212 > func (ms *MutableStateImpl) processCloseCallbacksHsm() error { mutable_state_impl.go
7213 > coll := callbacks.MachineCollection(ms.HSM())
7214 > for _, node := range coll.List() {
7215 cb, err := coll.Data(node.Key.ID)
7216 if err != nil {
7228 }
7229 }
7230 > return nil mutable_state_impl.go
7231 }
7232
7233 // processCloseCallbacksChasm triggers "WorkflowClosed" callbacks using the CHASM implementation.
7234 > func (ms *MutableStateImpl) processCloseCallbacksChasm() error { mutable_state_impl.go
7235 > wf, _, err := ms.ChasmWorkflowComponentReadOnly(context.Background())
7236 > if err != nil {
7237 return err
7238 }
7239
7240 // Return early if there are no chasm callbacks to process.
7241 > if len(wf.Callbacks) == 0 && len(wf.Updates) == 0 { mutable_state_impl.go
7242 > return nil
7243 > }
7244
7245 // If there are callbacks to process, create a writable workflow component.
7254 func (ms *MutableStateImpl) AddTasks(
7255 newTasks ...tasks.Task,
7257 > now := ms.Now()
7258 > for _, task := range newTasks {
7259 > if chasmTask, ok := task.(*tasks.ChasmTask); ok &&
7260 > chasmTask.GetCategory() == tasks.CategoryVisibility &&
7261 > ms.stateInDB == enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED {
7262 softassert.Fail(ms.logger, "CHASM visibility task added on already-closed execution")
7263 }
7264
7265 > category := task.GetCategory() mutable_state_impl.go
7266 > // Drop tasks scheduled too far in the future. VisibilityTime hasn't been
7267 > // shifted to wall-clock yet (the conversion runs below), so both sides are
7268 > // virtual here; the difference is frame-invariant (skip cancels). Keep
7269 > // `now` from ms.Now() so both stay in the same frame.
7270 > if category.Type() == tasks.CategoryTypeScheduled &&
7271 > task.GetVisibilityTime().Sub(now) > maxScheduledTaskDuration {
7272 ms.logger.Info("Dropped long duration scheduled task.", tasks.Tags(task)...)
7273 continue
7279 // vs. real distinction. The CategoryTypeScheduled drop-check above runs first so it
7280 // compares virtual-vs-virtual (now is also virtual).
7281 > if category.Type() == tasks.CategoryTypeScheduled { mutable_state_impl.go
7282 > task.SetVisibilityTime(ms.ToRealTime(task.GetVisibilityTime())) mutable_state_impl.go
7283 > }
7284
7285 > if chasmPureTask, ok := task.(*tasks.ChasmTaskPure); ok { mutable_state_impl.go
7286 ms.chasmPureTasks = append(ms.chasmPureTasks, chasmPureTask)
7287 maxPureTasks := ms.config.ChasmMaxInMemoryPureTasks()
7296 }
7297
7298 > ms.InsertTasks[category] = append(ms.InsertTasks[category], task) mutable_state_impl.go
7299 }
7300 }
7306 }
7307
7308 > func (ms *MutableStateImpl) DeleteCHASMPureTasks(maxScheduledTime time.Time) { mutable_state_impl.go
7309 > for lastTaskIdx := len(ms.chasmPureTasks) - 1; lastTaskIdx >= 0; lastTaskIdx-- {
7310 task := ms.chasmPureTasks[lastTaskIdx]
7311 if !task.GetVisibilityTime().Before(maxScheduledTime) {
7322 // If we reach here, all tasks have visibility time before maxScheduledTime
7323 // and need to be deleted.
7324 > ms.chasmPureTasks = ms.chasmPureTasks[:0] mutable_state_impl.go
7325 }
7326
7360 }
7361
7362 > func (ms *MutableStateImpl) RemoveSpeculativeWorkflowTaskTimeoutTask() { mutable_state_impl.go
7363 > if ms.speculativeWorkflowTaskTimeoutTask != nil {
7364 // Cancelling task prevents it from being submitted to scheduler in memoryScheduledQueue.
7365 ms.speculativeWorkflowTaskTimeoutTask.Cancel()
7368 }
7369
7370 > func (ms *MutableStateImpl) SetWorkflowTaskScheduleToStartTimeoutTask(task *tasks.WorkflowTaskTimeoutTask) { mutable_state_impl.go
7371 > ms.wftScheduleToStartTimeoutTask = task
7372 > }
7373
7374 > func (ms *MutableStateImpl) SetWorkflowTaskStartToCloseTimeoutTask(task *tasks.WorkflowTaskTimeoutTask) { mutable_state_impl.go
7375 > ms.wftStartToCloseTimeoutTask = task
7376 > }
7377
7378 > func (ms *MutableStateImpl) GetWorkflowTaskScheduleToStartTimeoutTask() *tasks.WorkflowTaskTimeoutTask { mutable_state_impl.go
7379 > return ms.wftScheduleToStartTimeoutTask
7380 > }
7381
7382 > func (ms *MutableStateImpl) GetWorkflowTaskStartToCloseTimeoutTask() *tasks.WorkflowTaskTimeoutTask { mutable_state_impl.go
7383 > return ms.wftStartToCloseTimeoutTask
7384 > }
7385
7386 > func (ms *MutableStateImpl) GetWorkflowStateStatus() (enumsspb.WorkflowExecutionState, enumspb.WorkflowExecutionStatus) { mutable_state_impl.go
7387 > return ms.executionState.State, ms.executionState.Status
7388 > }
7389
7390 func (ms *MutableStateImpl) UpdateWorkflowStateStatus(
7391 state enumsspb.WorkflowExecutionState,
7392 status enumspb.WorkflowExecutionStatus,
7393 > ) (bool, error) { mutable_state_impl.go
7394 > if state == ms.executionState.State && status == ms.executionState.Status {
7395 > return false, nil mutable_state_impl.go
7396 > }
7397 > if state != enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE && mutable_state_impl.go
7398 > ms.executionState.State != enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE {
7399 > // Suppress and Revive workflows are cluster local operations. mutable_state_impl.go
7400 > ms.executionStateUpdated = true
7401 > ms.visibilityUpdated = true // workflow status & state change triggers visibility change as well
7402 > }
7403 > return true, setStateStatus(ms.executionState, state, status) mutable_state_impl.go
7404 }
7405
7407 // However, certain in-memory changes (e.g. speculative workflow task) won't be cleared before releasing
7408 // the lock and have to be excluded from the check.
7409 > func (ms *MutableStateImpl) IsDirty() bool { mutable_state_impl.go
7410 > return ms.hBuilder.IsDirty() ||
7411 > len(ms.InsertTasks) > 0 ||
7412 > (ms.stateMachineNode != nil && ms.stateMachineNode.Dirty()) ||
7413 > ms.chasmTree.IsDirty()
7414 > }
7415
7416 // isStateDirty is used upon closing transaction to determine if application data has been updated, and
7417 // mutable state should move to a new versioned transition.
7418 > func (ms *MutableStateImpl) isStateDirty() bool { mutable_state_impl.go
7419 > // TODO: we need to track more workflow state changes
7420 > // e.g. changes to executionInfo.CancelRequested
7421 > // They are mostly covered by history builder check today.
7422 > return ms.hBuilder.IsDirty() ||
7423 > len(ms.activityInfosUserDataUpdated) > 0 ||
7424 > len(ms.deleteActivityInfos) > 0 ||
7425 > len(ms.timerInfosUserDataUpdated) > 0 ||
7426 > len(ms.deleteTimerInfos) > 0 ||
7427 > len(ms.updateChildExecutionInfos) > 0 ||
7428 > len(ms.deleteChildExecutionInfos) > 0 ||
7429 > len(ms.updateRequestCancelInfos) > 0 ||
7430 > len(ms.deleteRequestCancelInfos) > 0 ||
7431 > len(ms.updateSignalInfos) > 0 ||
7432 > len(ms.deleteSignalInfos) > 0 ||
7433 > len(ms.updateSignalRequestedIDs) > 0 ||
7434 > len(ms.deleteSignalRequestedIDs) > 0 ||
7435 > len(ms.updateInfoUpdated) > 0 ||
7436 > ms.visibilityUpdated ||
7437 > ms.executionStateUpdated ||
7438 > ms.workflowTaskUpdated ||
7439 > (ms.stateMachineNode != nil && ms.stateMachineNode.Dirty()) ||
7440 > ms.chasmTree.IsStateDirty() ||
7441 > ms.isResetStateUpdated ||
7442 > ms.timeSkippingInfoUpdated
7443 > }
7444
7445 func (ms *MutableStateImpl) IsTransitionHistoryEnabled() bool {
7449 func (ms *MutableStateImpl) StartTransaction(
7450 namespaceEntry *namespace.Namespace,
7451 > ) (bool, error) { mutable_state_impl.go
7452 > if ms.IsDirty() {
7453 ms.logger.Error("MutableState encountered dirty transaction",
7454 tag.WorkflowNamespaceID(ms.executionInfo.NamespaceId),
7461 }
7462
7463 > ms.transitionHistoryEnabled = ms.config.EnableTransitionHistory(namespaceEntry.Name().String()) mutable_state_impl.go
7464 >
7465 > namespaceEntry, err := ms.startTransactionHandleNamespaceMigration(namespaceEntry)
7466 > if err != nil {
7467 return false, err
7468 }
7469 > ms.namespaceEntry = namespaceEntry mutable_state_impl.go
7470 > if err := ms.UpdateCurrentVersion(namespaceEntry.FailoverVersion(ms.executionInfo.WorkflowId), false); err != nil {
7471 return false, err
7472 }
7473
7474 > flushBeforeReady, err := ms.startTransactionHandleWorkflowTaskFailover() mutable_state_impl.go
7475 > if err != nil {
7476 return false, err
7477 }
7478
7479 > return flushBeforeReady, nil mutable_state_impl.go
7480 }
7481
7483 ctx context.Context,
7484 transactionPolicy historyi.TransactionPolicy,
7485 > ) (*persistence.WorkflowMutation, []*persistence.WorkflowEvents, error) { mutable_state_impl.go
7486 > result, err := ms.closeTransaction(ctx, transactionPolicy)
7487 > if err != nil {
7488 return nil, nil, err
7489 }
7490
7491 > if result.skipPersistence { mutable_state_impl.go
7492 if err := ms.cleanupTransaction(); err != nil {
7493 return nil, nil, err
7496 }
7497
7498 > workflowMutation := &persistence.WorkflowMutation{ mutable_state_impl.go
7499 > ExecutionInfo: ms.executionInfo,
7500 > ExecutionState: ms.executionState,
7501 > NextEventID: ms.hBuilder.NextEventID(),
7502 >
7503 > UpsertActivityInfos: ms.updateActivityInfos,
7504 > DeleteActivityInfos: ms.deleteActivityInfos,
7505 > UpsertTimerInfos: ms.updateTimerInfos,
7506 > DeleteTimerInfos: ms.deleteTimerInfos,
7507 > UpsertChildExecutionInfos: ms.updateChildExecutionInfos,
7508 > DeleteChildExecutionInfos: ms.deleteChildExecutionInfos,
7509 > UpsertRequestCancelInfos: ms.updateRequestCancelInfos,
7510 > DeleteRequestCancelInfos: ms.deleteRequestCancelInfos,
7511 > UpsertSignalInfos: ms.updateSignalInfos,
7512 > DeleteSignalInfos: ms.deleteSignalInfos,
7513 > UpsertSignalRequestedIDs: ms.updateSignalRequestedIDs,
7514 > DeleteSignalRequestedIDs: ms.deleteSignalRequestedIDs,
7515 > UpsertChasmNodes: result.chasmNodesMutation.UpdatedNodes,
7516 > DeleteChasmNodes: result.chasmNodesMutation.DeletedNodes,
7517 > NewBufferedEvents: result.bufferEvents,
7518 > ClearBufferedEvents: result.clearBuffer,
7519 >
7520 > Tasks: ms.InsertTasks,
7521 > BestEffortDeleteTasks: ms.BestEffortDeleteTasks,
7522 >
7523 > Condition: ms.nextEventIDInDB,
7524 > DBRecordVersion: ms.dbRecordVersion,
7525 > Checksum: result.checksum,
7526 > }
7527 >
7528 > ms.checksum = result.checksum
7529 > if err := ms.cleanupTransaction(); err != nil {
7530 return nil, nil, err
7531 }
7532 > return workflowMutation, result.workflowEventsSeq, nil mutable_state_impl.go
7533 }
7534
7536 ctx context.Context,
7537 transactionPolicy historyi.TransactionPolicy,
7538 > ) (*persistence.WorkflowSnapshot, []*persistence.WorkflowEvents, error) { mutable_state_impl.go
7539 > result, err := ms.closeTransaction(ctx, transactionPolicy)
7540 > if err != nil {
7541 return nil, nil, err
7542 }
7543
7544 > if len(result.bufferEvents) > 0 { mutable_state_impl.go
7545 // TODO do we need the functionality to generate snapshot with buffered events?
7546 return nil, nil, softassert.UnexpectedInternalErr(
7551 }
7552
7553 > workflowSnapshot := &persistence.WorkflowSnapshot{ mutable_state_impl.go
7554 > ExecutionInfo: ms.executionInfo,
7555 > ExecutionState: ms.executionState,
7556 > NextEventID: ms.hBuilder.NextEventID(),
7557 >
7558 > ActivityInfos: ms.pendingActivityInfoIDs,
7559 > TimerInfos: ms.pendingTimerInfoIDs,
7560 > ChildExecutionInfos: ms.pendingChildExecutionInfoIDs,
7561 > RequestCancelInfos: ms.pendingRequestCancelInfoIDs,
7562 > SignalInfos: ms.pendingSignalInfoIDs,
7563 > SignalRequestedIDs: ms.pendingSignalRequestedIDs,
7564 > ChasmNodes: ms.chasmTree.Snapshot(nil).Nodes,
7565 >
7566 > Tasks: ms.InsertTasks,
7567 >
7568 > Condition: ms.nextEventIDInDB,
7569 > DBRecordVersion: ms.dbRecordVersion,
7570 > Checksum: result.checksum,
7571 > }
7572 >
7573 > ms.checksum = result.checksum
7574 > if err := ms.cleanupTransaction(); err != nil {
7575 return nil, nil, err
7576 }
7577 > return workflowSnapshot, result.workflowEventsSeq, nil mutable_state_impl.go
7578 }
7579
7599 func (ms *MutableStateImpl) updateSearchAttributes(
7600 updatedPayloadMap map[string]*commonpb.Payload,
7602 > ms.executionInfo.SearchAttributes = payload.MergeMapOfPayload(
7603 > ms.executionInfo.SearchAttributes,
7604 > updatedPayloadMap,
7605 > )
7606 > ms.visibilityUpdated = true
7607 > }
7608
7609 func (ms *MutableStateImpl) updateMemo(
7628 func (ms *MutableStateImpl) SetContextMetadata(
7629 ctx context.Context,
7631 > switch ms.chasmTree.ArchetypeID() {
7632 > case chasm.WorkflowArchetypeID, chasm.UnspecifiedArchetypeID: mutable_state_impl.go
7633 > // Set workflow type
7634 > if wfType := ms.GetWorkflowType(); wfType != nil && wfType.GetName() != "" {
7635 > contextutil.ContextMetadataSet(ctx, contextutil.MetadataKeyWorkflowType, wfType.GetName()) mutable_state_impl.go
7636 > }
7637
7638 // Set workflow task queue
7639 > if ms.executionInfo != nil && ms.executionInfo.TaskQueue != "" { mutable_state_impl.go
7640 > contextutil.ContextMetadataSet(ctx, contextutil.MetadataKeyWorkflowTaskQueue, ms.executionInfo.TaskQueue) mutable_state_impl.go
7641 > }
7642
7643 > for _, activityID := range contextutil.ContextMetadataGetMarkedActivityIDs(ctx) { mutable_state_impl.go
7644 if ai, ok := ms.GetActivityByActivityID(activityID); ok {
7645 contextutil.ContextMetadataSet(ctx, contextutil.ActivityTypeKey(ai.ScheduledEventId), ai.ActivityType.GetName())
7660 ctx context.Context,
7661 transactionPolicy historyi.TransactionPolicy,
7662 > ) (closeTransactionResult, error) { mutable_state_impl.go
7663 > ms.SetContextMetadata(ctx)
7664 >
7665 > if err := ms.closeTransactionWithPolicyCheck(
7666 > transactionPolicy,
7667 > ); err != nil {
7668 return closeTransactionResult{}, err
7669 }
7670
7671 > if err := ms.closeTransactionHandleWorkflowTask( mutable_state_impl.go
7672 > transactionPolicy,
7673 > ); err != nil {
7674 return closeTransactionResult{}, err
7675 }
7681 // and need to reconsider the sequence of time skipping close trx handling in this function
7682 // when supporting chasm.
7683 > regenTimerTasksForWorkflowTimeSkipping := ms.closeTransactionHandleWorkflowTimeSkipping(ctx, transactionPolicy) mutable_state_impl.go
7684 >
7685 > // Save if the state is dirty before closeTransactionPrepareEvents since it flushes the buffer
7686 > // events, and therefore change the dirty state.
7687 > isStateDirty := ms.isStateDirty()
7688 >
7689 > // closeTransactionPrepareEvents must be called after closeTransactionHandleWorkflowTask because
7690 > // the latter might fail the workflow task and buffered events must be flushed afterwards.
7691 > // We need to save the value of ms.isStateDirty() before calling closeTransactionPrepareEvents
7692 > // because flushing the buffered events might change the dirty state.
7693 > workflowEventsSeq, eventBatches, bufferEvents, clearBuffer, err := ms.closeTransactionPrepareEvents(transactionPolicy)
7694 > if err != nil {
7695 return closeTransactionResult{}, err
7696 }
7699 // cluster — standby (passive) replays events that were already stamped by
7700 // the active side, and we must not overwrite those principals.
7701 > if transactionPolicy == historyi.TransactionPolicyActive { mutable_state_impl.go
7702 > principal := headers.GetPrincipal(ctx) mutable_state_impl.go
7703 > for _, we := range workflowEventsSeq {
7704 > for _, event := range we.Events { mutable_state_impl.go
7705 > // Skip events that already have a principal. Those are previously
7706 > // buffered events (e.g., signals) that were stamped when originally
7707 > // created and are now being flushed into history by a different caller
7708 > // (e.g., the worker completing a workflow task).
7709 > if event.Principal == nil {
7710 > event.Principal = principal
7711 > }
7712 }
7713 }
7714 > for _, event := range bufferEvents { mutable_state_impl.go
7715 event.Principal = principal
7716 }
7719 // CloseTransaction() on chasmTree may update execution state & status,
7720 // so must be called before closeTransactionUpdateTransitionHistory().
7721 > chasmNodesMutation, err := ms.chasmTree.CloseTransaction() mutable_state_impl.go
7722 > if err != nil {
7723 return closeTransactionResult{}, err
7724 }
7725
7726 > if ms.closeTransactionShouldSkipPersistence(isStateDirty, chasmNodesMutation) { mutable_state_impl.go
7727 return closeTransactionResult{
7728 skipPersistence: true,
7730 }
7731
7732 > for nodePath := range chasmNodesMutation.DeletedNodes { mutable_state_impl.go
7733 ms.approximateSize -= ms.chasmNodeSizes[nodePath]
7734 delete(ms.chasmNodeSizes, nodePath)
7735 }
7736 > for nodePath, node := range chasmNodesMutation.UpdatedNodes { mutable_state_impl.go
7737 newSize := len(nodePath) + node.Size()
7738 ms.approximateSize += newSize - ms.chasmNodeSizes[nodePath]
7740 }
7741
7742 > if isStateDirty { mutable_state_impl.go
7743 > if err := ms.closeTransactionUpdateTransitionHistory( mutable_state_impl.go
7744 > transactionPolicy,
7745 > ); err != nil {
7746 return closeTransactionResult{}, err
7747 }
7748 > ms.closeTransactionHandleUnknownVersionedTransition() mutable_state_impl.go
7749 > ms.closeTransactionUpdateLastRunningClock(transactionPolicy, workflowEventsSeq)
7750 }
7751
7752 // todo@TimeSkipping, we can move update versioned transition to inside closeTransactionHandleWorkflowTimeSkipping
7753 > ms.closeTransactionTrackLastUpdateVersionedTransition( mutable_state_impl.go
7754 > transactionPolicy,
7755 > )
7756 >
7757 > ms.closeTransactionTrackTombstones(transactionPolicy, chasmNodesMutation)
7758 >
7759 > // generate tasks
7760 > if err := ms.closeTransactionPrepareTasks(
7761 > transactionPolicy,
7762 > eventBatches,
7763 > clearBuffer,
7764 > regenTimerTasksForWorkflowTimeSkipping,
7765 > ); err != nil {
7766 return closeTransactionResult{}, err
7767 }
7768
7769 > ms.executionInfo.StateTransitionCount += 1 mutable_state_impl.go
7770 > ms.executionInfo.LastUpdateTime = timestamppb.New(ms.timeSource.Now())
7771 >
7772 > // We generate checksum here based on the assumption that the returned
7773 > // snapshot object is considered immutable. As of this writing, the only
7774 > // code that modifies the returned object lives inside Context.resetWorkflowExecution.
7775 > // Currently, the updates done inside Context.resetWorkflowExecution don't
7776 > // impact the checksum calculation.
7777 > checksum := ms.generateChecksum()
7778 >
7779 > if ms.dbRecordVersion == 0 {
7780 // noop, existing behavior
7781 > } else { mutable_state_impl.go
7782 > ms.dbRecordVersion += 1 mutable_state_impl.go
7783 > }
7784
7785 > return closeTransactionResult{ mutable_state_impl.go
7786 > workflowEventsSeq: workflowEventsSeq,
7787 > bufferEvents: bufferEvents,
7788 > clearBuffer: clearBuffer,
7789 > checksum: checksum,
7790 > chasmNodesMutation: chasmNodesMutation,
7791 > }, nil
7792 }
7793
7794 > func (ms *MutableStateImpl) closeTransactionShouldSkipPersistence(isStateDirty bool, chasmNodesMutation chasm.NodesMutation) bool { mutable_state_impl.go
7795 > return !ms.IsWorkflow() && !isStateDirty && chasmNodesMutation.IsEmpty()
7796 > }
7797
7798 func (ms *MutableStateImpl) closeTransactionHandleWorkflowTask(
7799 transactionPolicy historyi.TransactionPolicy,
7800 > ) error { mutable_state_impl.go
7801 > if err := ms.closeTransactionHandleBufferedEventsLimit(
7802 > transactionPolicy,
7803 > ); err != nil {
7804 return err
7805 }
7806
7807 > if err := ms.closeTransactionHandleWorkflowTaskScheduling( mutable_state_impl.go
7808 > transactionPolicy,
7809 > ); err != nil {
7810 return err
7811 }
7812
7813 > return ms.closeTransactionHandleSpeculativeWorkflowTask(transactionPolicy) mutable_state_impl.go
7814 }
7815
7816 func (ms *MutableStateImpl) closeTransactionHandleWorkflowTaskScheduling(
7817 transactionPolicy historyi.TransactionPolicy,
7818 > ) error { mutable_state_impl.go
7819 > if transactionPolicy == historyi.TransactionPolicyPassive ||
7820 > !ms.IsWorkflowExecutionRunning() {
7821 > return nil mutable_state_impl.go
7822 > }
7823
7824 > for _, t := range ms.currentTransactionAddedStateMachineEventTypes { mutable_state_impl.go
7825 def, ok := ms.shard.StateMachineRegistry().EventDefinition(t)
7826 if !ok {
7840 }
7841
7842 > return nil mutable_state_impl.go
7843 }
7844
7845 func (ms *MutableStateImpl) closeTransactionHandleSpeculativeWorkflowTask(
7846 transactionPolicy historyi.TransactionPolicy,
7847 > ) error { mutable_state_impl.go
7848 > if transactionPolicy == historyi.TransactionPolicyPassive ||
7849 > !ms.IsWorkflowExecutionRunning() {
7850 > return nil mutable_state_impl.go
7851 > }
7852
7853 // It is important to convert speculative WT to normal before prepareEventsAndReplicationTasks,
7854 // because prepareEventsAndReplicationTasks will move internal buffered events to the history,
7855 // and WT related events (WTScheduled, in particular) need to go first.
7856 > return ms.workflowTaskManager.convertSpeculativeWorkflowTaskToNormal() mutable_state_impl.go
7857 }
7858
7859 func (ms *MutableStateImpl) closeTransactionUpdateTransitionHistory(
7860 transactionPolicy historyi.TransactionPolicy,
7861 > ) error { mutable_state_impl.go
7862 > if transactionPolicy != historyi.TransactionPolicyActive {
7863 // TODO: replication/standby logic will need a different way for updating transition history
7864 // when not syncing mutable state
7866 }
7867
7868 > if !ms.transitionHistoryEnabled { mutable_state_impl.go
7869 return nil
7870 }
7871
7872 // handle disable then re-enable of transition history
7873 > if len(ms.executionInfo.TransitionHistory) == 0 && len(ms.executionInfo.PreviousTransitionHistory) != 0 { mutable_state_impl.go
7874 ms.executionInfo.TransitionHistory = ms.executionInfo.PreviousTransitionHistory
7875 ms.executionInfo.PreviousTransitionHistory = nil
7876 }
7877
7878 > ms.executionInfo.TransitionHistory = UpdatedTransitionHistory( mutable_state_impl.go
7879 > ms.executionInfo.TransitionHistory,
7880 > ms.GetCurrentVersion(),
7881 > )
7882 >
7883 > return nil
7884 }
7885
7886 func (ms *MutableStateImpl) closeTransactionTrackLastUpdateVersionedTransition(
7887 transactionPolicy historyi.TransactionPolicy,
7889 > if transactionPolicy != historyi.TransactionPolicyActive {
7890 // TODO: replication/standby logic will need a different way for updating LastUpdatedVersionedTransition
7891 // when reapplying history, especially when history replication tasks got batched.
7893 }
7894
7895 > if !ms.transitionHistoryEnabled { mutable_state_impl.go
7896 // transition history is not enabled
7897 return
7898 }
7899 // transaction closed without any state change
7900 > if len(ms.executionInfo.TransitionHistory) == 0 { mutable_state_impl.go
7901 return
7902 }
7903
7904 > currentVersionedTransition := ms.CurrentVersionedTransition() mutable_state_impl.go
7905 > for activityId := range ms.activityInfosUserDataUpdated {
7906 ms.updateActivityInfos[activityId].LastUpdateVersionedTransition = currentVersionedTransition
7907 }
7908 > for timerId := range ms.timerInfosUserDataUpdated { mutable_state_impl.go
7909 ms.updateTimerInfos[timerId].LastUpdateVersionedTransition = currentVersionedTransition
7910 }
7911 > for _, childInfo := range ms.updateChildExecutionInfos { mutable_state_impl.go
7912 childInfo.LastUpdateVersionedTransition = currentVersionedTransition
7913 }
7914 > for _, cancelInfo := range ms.updateRequestCancelInfos { mutable_state_impl.go
7915 cancelInfo.LastUpdateVersionedTransition = currentVersionedTransition
7916 }
7917 > for _, signalInfo := range ms.updateSignalInfos { mutable_state_impl.go
7918 signalInfo.LastUpdateVersionedTransition = currentVersionedTransition
7919 }
7922 // signal requestedID.
7923 // Deletion of signalRequestID is not replicated today, so we can even drop the check on deleteSignalRequestedIDs
7924 > if len(ms.updateSignalRequestedIDs) != 0 || len(ms.deleteSignalRequestedIDs) != 0 { mutable_state_impl.go
7925 ms.executionInfo.SignalRequestIdsLastUpdateVersionedTransition = currentVersionedTransition
7926 }
7927
7928 > for updateID := range ms.updateInfoUpdated { mutable_state_impl.go
7929 ms.executionInfo.UpdateInfos[updateID].LastUpdateVersionedTransition = currentVersionedTransition
7930 }
7931
7932 > if ms.workflowTaskUpdated { mutable_state_impl.go
7933 > ms.executionInfo.WorkflowTaskLastUpdateVersionedTransition = currentVersionedTransition mutable_state_impl.go
7934 > }
7935
7936 > if ms.visibilityUpdated { mutable_state_impl.go
7937 > ms.executionInfo.VisibilityLastUpdateVersionedTransition = currentVersionedTransition mutable_state_impl.go
7938 > }
7939
7940 > if ms.executionStateUpdated { mutable_state_impl.go
7941 > ms.executionState.LastUpdateVersionedTransition = currentVersionedTransition mutable_state_impl.go
7942 > }
7943
7944 > if ms.timeSkippingInfoUpdated && ms.executionInfo.TimeSkippingInfo != nil { mutable_state_impl.go
7945 ms.executionInfo.TimeSkippingInfo.LastUpdateVersionedTransition = currentVersionedTransition
7946 }
7950 }
7951
7952 > func (ms *MutableStateImpl) closeTransactionHandleUnknownVersionedTransition() { mutable_state_impl.go
7953 > if len(ms.executionInfo.TransitionHistory) != 0 {
7954 > if transitionhistory.Compare( mutable_state_impl.go
7955 > ms.versionedTransitionInDB,
7956 > ms.CurrentVersionedTransition(),
7957 > ) != 0 {
7958 > // versioned transition updated in the transaction
7959 > return
7960 > }
7961 }
7962
8017 transactionPolicy historyi.TransactionPolicy,
8018 workflowEventsSeq []*persistence.WorkflowEvents,
8020 > if transactionPolicy != historyi.TransactionPolicyActive {
8021 return
8022 }
8024 // Events can only be generated while mutable state is running,
8025 // so we can update LastRunningClock blindly.
8026 > if len(workflowEventsSeq) > 0 { mutable_state_impl.go
8027 > lastEvents := workflowEventsSeq[len(workflowEventsSeq)-1].Events mutable_state_impl.go
8028 > lastEvent := lastEvents[len(lastEvents)-1]
8029 > ms.executionInfo.LastRunningClock = lastEvent.GetTaskId()
8030 > return
8031 > }
8032
8033 if !ms.IsWorkflowExecutionRunning() && !ms.IsCurrentWorkflowGuaranteed() {
8044 transactionPolicy historyi.TransactionPolicy,
8045 chasmNodesMutation chasm.NodesMutation,
8047 > if transactionPolicy != historyi.TransactionPolicyActive {
8048 // Passive/Replication logic will update tombstone list when applying mutable state
8049 // snapshot or mutation.
8051 }
8052
8053 > if !ms.transitionHistoryEnabled { mutable_state_impl.go
8054 // transition history is not enabled
8055 return
8056 }
8057
8058 > if len(ms.executionInfo.TransitionHistory) == 0 { mutable_state_impl.go
8059 // in an unknown state
8060 return
8061 }
8062
8063 > var tombstones []*persistencespb.StateMachineTombstone mutable_state_impl.go
8064 > if ms.stateMachineNode != nil {
8065 > opLog, err := ms.stateMachineNode.OpLog()
8066 > if err != nil {
8067 panic(fmt.Sprintf("Failed to get HSM operation log: %v", err))
8068 }
8069
8070 > for _, op := range opLog { mutable_state_impl.go
8071 if deleteOp, ok := op.(hsm.DeleteOperation); ok {
8072 path := deleteOp.Path()
8095 }
8096
8097 > for scheduledEventID := range ms.deleteActivityInfos { mutable_state_impl.go
8098 tombstones = append(tombstones, &persistencespb.StateMachineTombstone{
8099 StateMachineKey: &persistencespb.StateMachineTombstone_ActivityScheduledEventId{
8102 })
8103 }
8104 > for timerID := range ms.deleteTimerInfos { mutable_state_impl.go
8105 tombstones = append(tombstones, &persistencespb.StateMachineTombstone{
8106 StateMachineKey: &persistencespb.StateMachineTombstone_TimerId{
8109 })
8110 }
8111 > for initiatedEventId := range ms.deleteChildExecutionInfos { mutable_state_impl.go
8112 tombstones = append(tombstones, &persistencespb.StateMachineTombstone{
8113 StateMachineKey: &persistencespb.StateMachineTombstone_ChildExecutionInitiatedEventId{
8116 })
8117 }
8118 > for initiatedEventId := range ms.deleteRequestCancelInfos { mutable_state_impl.go
8119 tombstones = append(tombstones, &persistencespb.StateMachineTombstone{
8120 StateMachineKey: &persistencespb.StateMachineTombstone_RequestCancelInitiatedEventId{
8123 })
8124 }
8125 > for initiatedEventId := range ms.deleteSignalInfos { mutable_state_impl.go
8126 tombstones = append(tombstones, &persistencespb.StateMachineTombstone{
8127 StateMachineKey: &persistencespb.StateMachineTombstone_SignalExternalInitiatedEventId{
8130 })
8131 }
8132 > for chasmNodePath := range chasmNodesMutation.DeletedNodes { mutable_state_impl.go
8133 tombstones = append(tombstones, &persistencespb.StateMachineTombstone{
8134 StateMachineKey: &persistencespb.StateMachineTombstone_ChasmNodePath{
8142 // which is not supported by today's DB schema.
8143 // TODO: we don't delete updateInfo today. Track them here when we do.
8144 > currentVersionedTransition := ms.CurrentVersionedTransition() mutable_state_impl.go
8145 >
8146 > tombstoneBatch := &persistencespb.StateMachineTombstoneBatch{
8147 > VersionedTransition: currentVersionedTransition,
8148 > StateMachineTombstones: tombstones,
8149 > }
8150 > // As an optimization, we only track the first empty tombstone batch. So we can know the start point of the tombstone batch
8151 > if len(tombstones) > 0 || len(ms.executionInfo.SubStateMachineTombstoneBatches) == 0 {
8152 > ms.executionInfo.SubStateMachineTombstoneBatches = append(ms.executionInfo.SubStateMachineTombstoneBatches, tombstoneBatch)
8153 > }
8154
8155 > ms.totalTombstones += len(tombstones) mutable_state_impl.go
8156 > ms.capTombstoneCount()
8157 }
8158
8159 // capTombstoneCount limits the total number of tombstones stored in the mutable state.
8160 // This method should be called whenever tombstone batch list is updated or synced.
8161 > func (ms *MutableStateImpl) capTombstoneCount() { mutable_state_impl.go
8162 > tombstoneCountLimit := ms.config.MutableStateTombstoneCountLimit()
8163 > for ms.totalTombstones > tombstoneCountLimit &&
8164 > len(ms.executionInfo.SubStateMachineTombstoneBatches) > 0 {
8165 ms.totalTombstones -= len(ms.executionInfo.SubStateMachineTombstoneBatches[0].StateMachineTombstones)
8166 ms.executionInfo.SubStateMachineTombstoneBatches = ms.executionInfo.SubStateMachineTombstoneBatches[1:]
8173 clearBufferEvents bool,
8174 regenerateTimerTasksForTimeSkipping bool,
8175 > ) error { mutable_state_impl.go
8176 > if err := ms.closeTransactionHandleWorkflowResetTask(
8177 > transactionPolicy,
8178 > ); err != nil {
8179 return err
8180 }
8181
8182 > if err := ms.taskGenerator.GenerateDirtySubStateMachineTasks(ms.shard.StateMachineRegistry()); err != nil { mutable_state_impl.go
8183 return err
8184 }
8185
8186 > ms.closeTransactionCollapseVisibilityTasks() mutable_state_impl.go
8187 >
8188 > if err := ms.closeTransactionGenerateChasmRetentionTask(transactionPolicy); err != nil {
8189 return err
8190 }
8195 // regardless of how many activity & user timer created
8196 // so the calculation must be at the very end
8197 > if err := ms.closeTransactionHandleActivityUserTimerTasks(transactionPolicy); err != nil { mutable_state_impl.go
8198 return err
8199 }
8200 > if regenerateTimerTasksForTimeSkipping { mutable_state_impl.go
8201 if err := ms.closeTransactionRegenTimerTasksForWorkflowTimeSkipping(transactionPolicy); err != nil {
8202 return err
8204 }
8205
8206 > return ms.closeTransactionPrepareReplicationTasks(transactionPolicy, eventBatches, clearBufferEvents) mutable_state_impl.go
8207 }
8208
8209 func (ms *MutableStateImpl) closeTransactionGenerateChasmRetentionTask(
8210 transactionPolicy historyi.TransactionPolicy,
8211 > ) error { mutable_state_impl.go
8212 >
8213 > if ms.IsWorkflow() ||
8214 > ms.executionState.State != enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED ||
8215 > ms.stateInDB == enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED {
8216 > return nil mutable_state_impl.go
8217 > }
8218
8219 // Generate retention timer for chasm executions if it's currentely completed
8234 eventBatches [][]*historypb.HistoryEvent,
8235 clearBufferEvents bool,
8236 > ) error { mutable_state_impl.go
8237 > var replicationTasks []tasks.Task
8238 > if ms.config.ReplicationMultipleBatches() {
8239 task, err := ms.eventsToReplicationTask(transactionPolicy, eventBatches)
8240 if err != nil {
8242 }
8243 replicationTasks = append(replicationTasks, task...)
8244 > } else { mutable_state_impl.go
8245 > for _, historyEvents := range eventBatches {
8246 > task, err := ms.eventsToReplicationTask(transactionPolicy, [][]*historypb.HistoryEvent{historyEvents}) mutable_state_impl.go
8247 > if err != nil {
8248 return err
8249 }
8250 > replicationTasks = append(replicationTasks, task...) mutable_state_impl.go
8251 }
8252 }
8253 > replicationTasks = append(replicationTasks, ms.syncActivityToReplicationTask(transactionPolicy)...) mutable_state_impl.go
8254 > replicationTasks = append(replicationTasks, ms.dirtyHSMToReplicationTask(transactionPolicy, eventBatches, clearBufferEvents)...)
8255 >
8256 > archetypeID := ms.ChasmTree().ArchetypeID()
8257 > isWorkflow := archetypeID == chasm.WorkflowArchetypeID
8258 > if !isWorkflow && len(replicationTasks) != 0 {
8259 return softassert.UnexpectedInternalErr(ms.logger, "chasm execution generated workflow replication tasks", nil)
8260 }
8261
8262 > if ms.transitionHistoryEnabled { mutable_state_impl.go
8263 > switch transactionPolicy { mutable_state_impl.go
8264 > case historyi.TransactionPolicyActive: mutable_state_impl.go
8265 > if ms.generateReplicationTask() {
8266 now := time.Now().UTC()
8267 workflowKey := definition.NewWorkflowKey(
8336 }
8337
8338 > if transactionPolicy == historyi.TransactionPolicyPassive && mutable_state_impl.go
8339 > len(ms.InsertTasks[tasks.CategoryReplication]) > 0 {
8340 return softassert.UnexpectedInternalErr(
8341 ms.logger,
8345 }
8346
8347 > return nil mutable_state_impl.go
8348 }
8349
8350 > func (ms *MutableStateImpl) cleanupTransaction() error { mutable_state_impl.go
8351 > ms.updateActivityInfos = make(map[int64]*persistencespb.ActivityInfo)
8352 > ms.deleteActivityInfos = make(map[int64]struct{})
8353 > ms.syncActivityTasks = make(map[int64]struct{})
8354 >
8355 > ms.updateTimerInfos = make(map[string]*persistencespb.TimerInfo)
8356 > ms.deleteTimerInfos = make(map[string]struct{})
8357 >
8358 > ms.updateChildExecutionInfos = make(map[int64]*persistencespb.ChildExecutionInfo)
8359 > ms.deleteChildExecutionInfos = make(map[int64]struct{})
8360 >
8361 > ms.updateRequestCancelInfos = make(map[int64]*persistencespb.RequestCancelInfo)
8362 > ms.deleteRequestCancelInfos = make(map[int64]struct{})
8363 >
8364 > ms.updateSignalInfos = make(map[int64]*persistencespb.SignalInfo)
8365 > ms.deleteSignalInfos = make(map[int64]struct{})
8366 >
8367 > ms.updateSignalRequestedIDs = make(map[string]struct{})
8368 > ms.deleteSignalRequestedIDs = make(map[string]struct{})
8369 >
8370 > ms.visibilityUpdated = false
8371 > ms.executionStateUpdated = false
8372 > ms.workflowTaskUpdated = false
8373 > ms.isResetStateUpdated = false
8374 > ms.timeSkippingInfoUpdated = false
8375 > ms.updateInfoUpdated = make(map[string]struct{})
8376 > ms.timerInfosUserDataUpdated = make(map[string]struct{})
8377 > ms.activityInfosUserDataUpdated = make(map[int64]struct{})
8378 > ms.reapplyEventsCandidate = nil
8379 > ms.subStateMachineDeleted = false
8380 > ms.replayEventBatchID = common.EmptyEventID
8381 >
8382 > ms.stateInDB = ms.executionState.State
8383 > ms.nextEventIDInDB = ms.GetNextEventID()
8384 > if len(ms.executionInfo.TransitionHistory) != 0 {
8385 > ms.versionedTransitionInDB = ms.CurrentVersionedTransition() mutable_state_impl.go
8386 > } else { mutable_state_impl.go
8387 ms.versionedTransitionInDB = nil
8388 }
8389 // ms.dbRecordVersion remains the same
8390
8391 > ms.hBuilder = historybuilder.New( mutable_state_impl.go
8392 > ms.timeSource,
8393 > ms.shard.GenerateTaskIDs,
8394 > ms.GetCurrentVersion(),
8395 > ms.nextEventIDInDB,
8396 > ms.bufferEventsInDB,
8397 > ms.metricsHandler,
8398 > ms.config.MaximumEventBatchSizeInBytes,
8399 > )
8400 >
8401 > ms.InsertTasks = make(map[tasks.Category][]tasks.Task)
8402 > ms.BestEffortDeleteTasks = make(map[tasks.Category][]tasks.Key)
8403 >
8404 > // Clear outputs for the next transaction.
8405 > ms.stateMachineNode.ClearTransactionState()
8406 > // Clear out transient state machine state.
8407 > ms.currentTransactionAddedStateMachineEventTypes = nil
8408 >
8409 > return nil
8410 }
8411
8412 func (ms *MutableStateImpl) closeTransactionPrepareEvents(
8413 transactionPolicy historyi.TransactionPolicy,
8414 > ) ([]*persistence.WorkflowEvents, [][]*historypb.HistoryEvent, []*historypb.HistoryEvent, bool, error) { mutable_state_impl.go
8415 > currentBranchToken, err := ms.GetCurrentBranchToken()
8416 > if err != nil {
8417 return nil, nil, nil, false, err
8418 }
8419
8420 > historyMutation, err := ms.hBuilder.Finish(!ms.HasStartedWorkflowTask()) mutable_state_impl.go
8421 > if err != nil {
8422 return nil, nil, nil, false, err
8423 }
8424
8425 // TODO @wxing1292 need more refactoring to make the logic clean
8426 > ms.bufferEventsInDB = historyMutation.MemBufferBatch mutable_state_impl.go
8427 > newBufferBatch := historyMutation.DBBufferBatch
8428 > clearBuffer := historyMutation.DBClearBuffer
8429 > newEventsBatches := historyMutation.DBEventsBatches
8430 > ms.updatePendingEventIDs(historyMutation.ScheduledIDToStartedID, historyMutation.RequestIDToEventID)
8431 >
8432 > workflowEventsSeq := make([]*persistence.WorkflowEvents, len(newEventsBatches))
8433 > historyNodeTxnIDs, err := ms.shard.GenerateTaskIDs(len(newEventsBatches))
8434 > if err != nil {
8435 return nil, nil, nil, false, err
8436 }
8437 > for index, eventBatch := range newEventsBatches { mutable_state_impl.go
8438 > workflowEventsSeq[index] = &persistence.WorkflowEvents{ mutable_state_impl.go
8439 > NamespaceID: ms.executionInfo.NamespaceId,
8440 > WorkflowID: ms.executionInfo.WorkflowId,
8441 > RunID: ms.executionState.RunId,
8442 > BranchToken: currentBranchToken,
8443 > PrevTxnID: ms.executionInfo.LastFirstEventTxnId,
8444 > TxnID: historyNodeTxnIDs[index],
8445 > Events: eventBatch,
8446 > }
8447 > ms.executionInfo.LastFirstEventId = eventBatch[0].GetEventId()
8448 > ms.executionInfo.LastFirstEventTxnId = historyNodeTxnIDs[index]
8449 >
8450 > // Calculate and add the external payload size and count for this batch
8451 > if ms.config.ExternalPayloadsEnabled(ms.GetNamespaceEntry().Name().String()) {
8452 > externalPayloadSize, externalPayloadCount, err := CalculateExternalPayloadSize(eventBatch, ms.metricsHandler)
8453 > if err != nil {
8454 return nil, nil, nil, false, err
8455 }
8456 > ms.AddExternalPayloadSize(externalPayloadSize) mutable_state_impl.go
8457 > ms.AddExternalPayloadCount(externalPayloadCount)
8458 }
8459 }
8460
8461 > if err := ms.validateNoEventsAfterWorkflowFinish( mutable_state_impl.go
8462 > transactionPolicy,
8463 > workflowEventsSeq,
8464 > ); err != nil {
8465 return nil, nil, nil, false, err
8466 }
8467
8468 > if len(workflowEventsSeq) > 0 { mutable_state_impl.go
8469 > lastEvents := workflowEventsSeq[len(workflowEventsSeq)-1].Events mutable_state_impl.go
8470 > lastEvent := lastEvents[len(lastEvents)-1]
8471 > if err := ms.updateWithLastWriteEvent(
8472 > lastEvent,
8473 > transactionPolicy,
8474 > ); err != nil {
8475 return nil, nil, nil, false, err
8476 }
8477 }
8478
8479 > return workflowEventsSeq, newEventsBatches, newBufferBatch, clearBuffer, nil mutable_state_impl.go
8480 }
8481
8483 transactionPolicy historyi.TransactionPolicy,
8484 eventBatches [][]*historypb.HistoryEvent,
8485 > ) ([]tasks.Task, error) { mutable_state_impl.go
8486 > switch transactionPolicy {
8487 > case historyi.TransactionPolicyActive: mutable_state_impl.go
8488 > if ms.generateReplicationTask() {
8489 return ms.taskGenerator.GenerateHistoryReplicationTasks(eventBatches)
8490 }
8491 > return nil, nil mutable_state_impl.go
8492 case historyi.TransactionPolicyPassive:
8493 return nil, nil
8499 func (ms *MutableStateImpl) syncActivityToReplicationTask(
8500 transactionPolicy historyi.TransactionPolicy,
8501 > ) []tasks.Task { mutable_state_impl.go
8502 > now := time.Now().UTC()
8503 > switch transactionPolicy {
8504 > case historyi.TransactionPolicyActive: mutable_state_impl.go
8505 > if ms.generateReplicationTask() {
8506 var activityIDs map[int64]struct{}
8507 if ms.disablingTransitionHistory() {
8525 )
8526 }
8527 > return nil mutable_state_impl.go
8528 case historyi.TransactionPolicyPassive:
8529 return emptyTasks
8537 eventBatches [][]*historypb.HistoryEvent,
8538 clearBufferEvents bool,
8539 > ) []tasks.Task { mutable_state_impl.go
8540 > switch transactionPolicy {
8541 > case historyi.TransactionPolicyActive: mutable_state_impl.go
8542 > if !ms.generateReplicationTask() {
8543 > return emptyTasks mutable_state_impl.go
8544 > }
8545
8546 // Skip if there are no HSM children (no outbound tasks to generate)
8578 scheduledIDToStartedID map[int64]int64,
8579 requestIDToEventID map[string]int64,
8580 > ) error { mutable_state_impl.go
8581 > for scheduledEventID, startedEventID := range scheduledIDToStartedID {
8582 if activityInfo, ok := ms.GetActivityInfo(scheduledEventID); ok {
8583 activityInfo.StartedEventId = startedEventID
8592 }
8593 }
8594 > if len(requestIDToEventID) > 0 { mutable_state_impl.go
8595 var wf *chasmworkflow.Workflow
8596 var chasmCtx chasm.MutableContext
8621 lastEvent *historypb.HistoryEvent,
8622 transactionPolicy historyi.TransactionPolicy,
8623 > ) error { mutable_state_impl.go
8624 > if transactionPolicy == historyi.TransactionPolicyPassive {
8625 // already handled in mutable state.
8626 return nil
8627 }
8628
8629 > currentVersionHistory, err := versionhistory.GetCurrentVersionHistory(ms.executionInfo.VersionHistories) mutable_state_impl.go
8630 > if err != nil {
8631 return err
8632 }
8633 > if err := versionhistory.AddOrUpdateVersionHistoryItem(currentVersionHistory, versionhistory.NewVersionHistoryItem( mutable_state_impl.go
8634 > lastEvent.GetEventId(), lastEvent.GetVersion(),
8635 > )); err != nil {
8636 return err
8637 }
8638
8639 > return nil mutable_state_impl.go
8640 }
8641
8646 transactionPolicy historyi.TransactionPolicy,
8647 workflowEventSeq []*persistence.WorkflowEvents,
8648 > ) error { mutable_state_impl.go
8649 > if transactionPolicy == historyi.TransactionPolicyPassive ||
8650 > len(workflowEventSeq) == 0 {
8651 return nil
8652 }
8653
8654 // only do check if workflow is finished
8655 > if ms.executionState.State != enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED { mutable_state_impl.go
8656 > return nil mutable_state_impl.go
8657 > }
8658
8659 // workflow close
8661 // NOTE: do not apply this check on every batch, since transient
8662 // workflow task && workflow finish will be broken (the first batch)
8663 > eventBatch := workflowEventSeq[len(workflowEventSeq)-1].Events mutable_state_impl.go
8664 > lastEvent := eventBatch[len(eventBatch)-1]
8665 > switch lastEvent.GetEventType() {
8666 case enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED,
8667 enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_FAILED,
8669 enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_TERMINATED,
8670 enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_CONTINUED_AS_NEW,
8671 > enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_CANCELED: mutable_state_impl.go
8672 > return nil
8673
8674 default:
8685 func (ms *MutableStateImpl) startTransactionHandleNamespaceMigration(
8686 namespaceEntry *namespace.Namespace,
8687 > ) (*namespace.Namespace, error) { mutable_state_impl.go
8688 > // NOTE:
8689 > // the main idea here is to guarantee that buffered events & namespace migration works
8690 > // e.g. handle buffered events during version 0 => version > 0 by postponing namespace migration
8691 > // * flush buffered events as if namespace is still local
8692 > // * use updated namespace for actual call
8693 >
8694 > lastWriteVersion, err := ms.GetLastWriteVersion()
8695 > if err != nil {
8696 return nil, err
8697 }
8698
8699 // local namespace -> global namespace && with started workflow task
8700 > if lastWriteVersion == common.EmptyVersion && namespaceEntry.FailoverVersion(ms.executionInfo.WorkflowId) > common.EmptyVersion && ms.HasStartedWorkflowTask() { mutable_state_impl.go
8701 localNamespaceMutation := namespace.WithPretendLocalNamespace(
8702 ms.clusterMetadata.GetCurrentClusterName(),
8704 return namespaceEntry.Clone(localNamespaceMutation), nil
8705 }
8706 > return namespaceEntry, nil mutable_state_impl.go
8707 }
8708
8709 > func (ms *MutableStateImpl) startTransactionHandleWorkflowTaskFailover() (bool, error) { mutable_state_impl.go
8710 > if !ms.IsWorkflowExecutionRunning() {
8711 > return false, nil mutable_state_impl.go
8712 > }
8713
8714 // NOTE:
8717
8718 // Handling mutable state turn from standby to active, while having a workflow task on the fly
8719 > workflowTask := ms.GetStartedWorkflowTask() mutable_state_impl.go
8720 > currentVersion := ms.GetCurrentVersion()
8721 > if workflowTask == nil || workflowTask.Version >= currentVersion {
8722 > // no pending workflow tasks, no buffered events
8723 > // or workflow task has higher / equal version
8724 > return false, nil
8725 > }
8726
8727 lastEventVersion, err := ms.GetLastEventVersion()
8805 func (ms *MutableStateImpl) closeTransactionWithPolicyCheck(
8806 transactionPolicy historyi.TransactionPolicy,
8807 > ) error { mutable_state_impl.go
8808 > switch transactionPolicy {
8809 > case historyi.TransactionPolicyActive: mutable_state_impl.go
8810 > // Cannot use ms.namespaceEntry.ActiveClusterName() because currentVersion may be updated during this transaction in
8811 > // passive cluster. For example: if passive cluster sees conflict and decided to terminate this workflow. The
8812 > // currentVersion on mutable state would be updated to point to last write version which is current (passive) cluster.
8813 > activeCluster := ms.clusterMetadata.ClusterNameForFailoverVersion(ms.namespaceEntry.IsGlobalNamespace(), ms.GetCurrentVersion())
8814 > currentCluster := ms.clusterMetadata.GetCurrentClusterName()
8815 >
8816 > if activeCluster != currentCluster {
8817 namespaceID := ms.GetExecutionInfo().NamespaceId
8818 return serviceerror.NewNamespaceNotActive(namespaceID, currentCluster, activeCluster)
8819 }
8820 > return nil mutable_state_impl.go
8821 case historyi.TransactionPolicyPassive:
8822 return nil
8826 }
8827
8828 > func (ms *MutableStateImpl) BufferSizeAcceptable() bool { mutable_state_impl.go
8829 > if ms.hBuilder.NumBufferedEvents() > ms.config.MaximumBufferedEventsBatch() {
8830 return false
8831 }
8832
8833 > if ms.hBuilder.SizeInBytesOfBufferedEvents() > ms.config.MaximumBufferedEventsSizeInBytes() { mutable_state_impl.go
8834 return false
8835 }
8836 > return true mutable_state_impl.go
8837 }
8838
8839 func (ms *MutableStateImpl) closeTransactionHandleBufferedEventsLimit(
8840 transactionPolicy historyi.TransactionPolicy,
8841 > ) error { mutable_state_impl.go
8842 > if transactionPolicy == historyi.TransactionPolicyPassive ||
8843 > !ms.IsWorkflowExecutionRunning() {
8844 > return nil mutable_state_impl.go
8845 > }
8846
8847 > if ms.BufferSizeAcceptable() { mutable_state_impl.go
8848 > return nil mutable_state_impl.go
8849 > }
8850
8851 // Handling buffered events size issue
8870 func (ms *MutableStateImpl) closeTransactionHandleWorkflowResetTask(
8871 transactionPolicy historyi.TransactionPolicy,
8872 > ) error { mutable_state_impl.go
8873 > if transactionPolicy == historyi.TransactionPolicyPassive ||
8874 > !ms.IsWorkflowExecutionRunning() {
8875 > return nil mutable_state_impl.go
8876 > }
8877
8878 > namespaceEntry, err := ms.shard.GetNamespaceRegistry().GetNamespaceByID(namespace.ID(ms.executionInfo.NamespaceId)) mutable_state_impl.go
8879 > if err != nil {
8880 return err
8881 }
8882 > if _, pt := FindAutoResetPoint( mutable_state_impl.go
8883 > ms.timeSource,
8884 > namespaceEntry.VerifyBinaryChecksum,
8885 > ms.GetExecutionInfo().AutoResetPoints,
8886 > ); pt != nil {
8887 if err := ms.taskGenerator.GenerateWorkflowResetTasks(); err != nil {
8888 return err
8897 )
8898 }
8899 > return nil mutable_state_impl.go
8900 }
8901
8902 func (ms *MutableStateImpl) closeTransactionHandleActivityUserTimerTasks(
8903 transactionPolicy historyi.TransactionPolicy,
8904 > ) error { mutable_state_impl.go
8905 > switch transactionPolicy {
8906 > case historyi.TransactionPolicyActive: mutable_state_impl.go
8907 > if !ms.IsWorkflowExecutionRunning() {
8908 > return nil mutable_state_impl.go
8909 > }
8910 > if err := ms.taskGenerator.GenerateActivityTimerTasks(); err != nil { mutable_state_impl.go
8911 return err
8912 }
8913 > return ms.taskGenerator.GenerateUserTimerTasks() mutable_state_impl.go
8914 case historyi.TransactionPolicyPassive:
8915 return nil
8923 // Any other task type is preserved in order.
8924 // Eg: [START, UPSERT, TP1, CLOSE, TP2, TP3] -> [TP1, CLOSE, TP2, TP3]
8925 > func (ms *MutableStateImpl) closeTransactionCollapseVisibilityTasks() { mutable_state_impl.go
8926 > visTasks := ms.InsertTasks[tasks.CategoryVisibility]
8927 > if len(visTasks) < 2 {
8928 > return mutable_state_impl.go
8929 > }
8930 > var visTaskToKeep tasks.Task mutable_state_impl.go
8931 > lastIndex := -1
8932 > for i, task := range visTasks {
8933 > switch task.GetType() {
8934 case enumsspb.TASK_TYPE_VISIBILITY_START_EXECUTION,
8935 enumsspb.TASK_TYPE_VISIBILITY_UPSERT_EXECUTION,
8936 enumsspb.TASK_TYPE_VISIBILITY_CLOSE_EXECUTION,
8937 > enumsspb.TASK_TYPE_VISIBILITY_DELETE_EXECUTION: mutable_state_impl.go
8938 > if visTaskToKeep == nil || task.GetType() >= visTaskToKeep.GetType() {
8939 > visTaskToKeep = task
8940 > }
8941 > lastIndex = i
8942 }
8943 }
8944 > if visTaskToKeep == nil { mutable_state_impl.go
8945 return
8946 }
8947 > collapsedVisTasks := make([]tasks.Task, 0, len(visTasks)) mutable_state_impl.go
8948 > for i, task := range visTasks {
8949 > switch task.GetType() {
8950 case enumsspb.TASK_TYPE_VISIBILITY_START_EXECUTION,
8951 enumsspb.TASK_TYPE_VISIBILITY_UPSERT_EXECUTION,
8952 enumsspb.TASK_TYPE_VISIBILITY_CLOSE_EXECUTION,
8953 > enumsspb.TASK_TYPE_VISIBILITY_DELETE_EXECUTION: mutable_state_impl.go
8954 > if i == lastIndex {
8955 > collapsedVisTasks = append(collapsedVisTasks, visTaskToKeep)
8956 > }
8957 default:
8958 collapsedVisTasks = append(collapsedVisTasks, task)
8959 }
8960 }
8961 > ms.InsertTasks[tasks.CategoryVisibility] = collapsedVisTasks mutable_state_impl.go
8962 }
8963
8964 > func (ms *MutableStateImpl) generateReplicationTask() bool { mutable_state_impl.go
8965 > return len(ms.namespaceEntry.ClusterNames(ms.GetWorkflowKey().WorkflowID)) > 1
8966 > }
8967
8968 func (ms *MutableStateImpl) checkMutability(
8969 actionTag tag.ZapTag,
8970 > ) error { mutable_state_impl.go
8971 > if !ms.IsWorkflowExecutionRunning() {
8972 ms.logWarn(
8973 mutableStateInvalidHistoryActionMsg,
8979 return ErrWorkflowFinished
8980 }
8981 > return nil mutable_state_impl.go
8982 }
8983
8984 > func (ms *MutableStateImpl) generateChecksum() *persistencespb.Checksum { mutable_state_impl.go
8985 > if !ms.shouldGenerateChecksum() {
8986 > return nil
8987 > }
8988 csum, err := generateMutableStateChecksum(ms)
8989 if err != nil {
8994 }
8995
8996 > func (ms *MutableStateImpl) shouldGenerateChecksum() bool { mutable_state_impl.go
8997 > if ms.namespaceEntry == nil {
8998 return false
8999 }
9000 > return rand.Intn(100) < ms.config.MutableStateChecksumGenProbability(ms.namespaceEntry.Name().String()) mutable_state_impl.go
9001 }
9002
9048 }
9049
9050 > func (ms *MutableStateImpl) HasCompletedAnyWorkflowTask() bool { mutable_state_impl.go
9051 > return ms.GetLastCompletedWorkflowTaskStartedEventId() != common.EmptyEventID
9052 > }
9053
9054 func (ms *MutableStateImpl) RefreshExpirationTimeoutTask(ctx context.Context) error {
9073 }
9074
9075 > func (ms *MutableStateImpl) CurrentVersionedTransition() *persistencespb.VersionedTransition { mutable_state_impl.go
9076 > return transitionhistory.LastVersionedTransition(ms.executionInfo.TransitionHistory)
9077 > }
9078
9079 func (ms *MutableStateImpl) ApplyMutation(
9586 }
9587
9588 > func (ms *MutableStateImpl) initVersionedTransitionInDB() { mutable_state_impl.go
9589 > if len(ms.executionInfo.TransitionHistory) != 0 {
9590 > ms.versionedTransitionInDB = ms.CurrentVersionedTransition() mutable_state_impl.go
9591 > }
9592 }
9593
9603 //
9604 // Note: Deployment objects are immutable, never change their fields.
9605 > func (ms *MutableStateImpl) GetEffectiveDeployment() *deploymentpb.Deployment { mutable_state_impl.go
9606 > return GetEffectiveDeployment(ms.GetExecutionInfo().GetVersioningInfo())
9607 > }
9608
9609 > func (ms *MutableStateImpl) GetWorkerDeploymentSA() string { mutable_state_impl.go
9610 > versioningInfo := ms.GetExecutionInfo().GetVersioningInfo()
9611 > if override := versioningInfo.GetVersioningOverride(); override != nil {
9612 if v := worker_versioning.GetOverrideTargetDeploymentVersion(override); v != nil {
9613 return v.GetDeploymentName()
9614 }
9615 }
9616 > if v := versioningInfo.GetDeploymentVersion(); v != nil { mutable_state_impl.go
9617 return v.GetDeploymentName()
9618 }
9619 > return ms.GetExecutionInfo().GetWorkerDeploymentName() mutable_state_impl.go
9620 }
9621
9622 > func (ms *MutableStateImpl) GetWorkerDeploymentVersionSA() string { mutable_state_impl.go
9623 > versioningInfo := ms.GetExecutionInfo().GetVersioningInfo()
9624 > if override := versioningInfo.GetVersioningOverride(); override != nil {
9625 if v := worker_versioning.GetOverrideTargetDeploymentVersion(override); v != nil {
9626 return worker_versioning.ExternalWorkerDeploymentVersionToString(v)
9627 }
9628 }
9629 > if v := versioningInfo.GetDeploymentVersion(); v != nil { mutable_state_impl.go
9630 return worker_versioning.ExternalWorkerDeploymentVersionToString(v)
9631 }
9632 //nolint:staticcheck // SA1019: worker versioning v0.31
9633 > return worker_versioning.ExternalWorkerDeploymentVersionToString(worker_versioning.ExternalWorkerDeploymentVersionFromStringV31(versioningInfo.GetVersion())) mutable_state_impl.go
9634 }
9635
9636 > func (ms *MutableStateImpl) GetWorkflowVersioningBehaviorSA() enumspb.VersioningBehavior { mutable_state_impl.go
9637 > if override := ms.executionInfo.GetVersioningInfo().GetVersioningOverride(); override != nil {
9638 if override.GetAutoUpgrade() {
9639 return enumspb.VERSIONING_BEHAVIOR_AUTO_UPGRADE
9644 return override.GetBehavior()
9645 }
9646 > return ms.executionInfo.GetVersioningInfo().GetBehavior() mutable_state_impl.go
9647 }
9648
9649 > func (ms *MutableStateImpl) GetDeploymentTransition() *workflowpb.DeploymentTransition { mutable_state_impl.go
9650 > vi := ms.GetExecutionInfo().GetVersioningInfo()
9651 > if t := vi.GetVersionTransition(); t != nil {
9652 //nolint:staticcheck // SA1019: worker versioning v0.30
9653 ret := &workflowpb.DeploymentTransition{}
9662 }
9663 //nolint:staticcheck // SA1019: worker versioning v0.30
9664 > return ms.GetExecutionInfo().GetVersioningInfo().GetDeploymentTransition() mutable_state_impl.go
9665 }
9666
9672 // 3. Behavior: this is returned when there is no override (most common case). Behavior is
9673 // set based on the worker-sent deployment in the latest WFT completion.
9674 > func (ms *MutableStateImpl) GetEffectiveVersioningBehavior() enumspb.VersioningBehavior { mutable_state_impl.go
9675 > return GetEffectiveVersioningBehavior(ms.GetExecutionInfo().GetVersioningInfo())
9676 > }
9677
9678 // StartDeploymentTransition starts a transition to the given deployment which must be
9736 }
9737
9738 > func (ms *MutableStateImpl) GetVersioningRevisionNumber() int64 { mutable_state_impl.go
9739 > return ms.GetExecutionInfo().GetVersioningInfo().GetRevisionNumber()
9740 > }
9741
9742 func (ms *MutableStateImpl) SetVersioningRevisionNumber(revisionNumber int64) {
9747 }
9748
9749 > func (ms *MutableStateImpl) GetShouldUseRampingVersion() bool { mutable_state_impl.go
9750 > execInfo := ms.GetExecutionInfo()
9751 > versioningInfo := execInfo.GetVersioningInfo()
9752 >
9753 > hasNoCompletedWorkflowTask := execInfo.GetLastCompletedWorkflowTaskStartedEventId() == common.EmptyEventID
9754 >
9755 > // Backward-compat note: history events written before ContinueAsNewInitialVersioningBehavior existed
9756 > // carry UNSPECIFIED, which does not match USE_RAMPING_VERSION, so those runs correctly fall through
9757 > // and return false — the same as AUTO_UPGRADE behavior.
9758 > hasInitialBehaviorUseRampingVersion := versioningInfo.GetContinueAsNewInitialVersioningBehavior() == enumspb.CONTINUE_AS_NEW_VERSIONING_BEHAVIOR_USE_RAMPING_VERSION
9759 >
9760 > // ContinueAsNewInitialVersioningBehavior is only populated (in ApplyWorkflowExecutionStartedEvent)
9761 > // from InheritedAutoUpgradeInfo, which always sets Behavior to AUTO_UPGRADE. So there is no world
9762 > // in which ContinueAsNewInitialVersioningBehavior is set without Behavior also being AUTO_UPGRADE.
9763 > // We could also check if the behavior is AUTO_UPGRADE, but that's redundant.
9764 > return hasNoCompletedWorkflowTask && hasInitialBehaviorUseRampingVersion
9765 > }
9766
9767 // reschedulePendingActivities reschedules all the activities that are not started, so they are
9923 }
9924
9925 > func (ms *MutableStateImpl) ToRealTime(virtualTime time.Time) time.Time { mutable_state_impl.go
9926 > if virtualTime.IsZero() {
9927 return virtualTime
9928 }
9929 > return virtualTime.Add(-ms.accumulatedSkippedDuration()) mutable_state_impl.go
9930 }
go.temporal.io/server/api/historyservice/v1/request_response.pb.go 933 covered LOC · 369 ranges

Open complete file

207 }
208
209 > func (x *StartWorkflowExecutionRequest) Reset() { request_response.pb.go
210 > *x = StartWorkflowExecutionRequest{}
211 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[1]
212 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
213 > ms.StoreMessageInfo(mi)
214 > }
215
216 func (x *StartWorkflowExecutionRequest) String() string {
220 func (*StartWorkflowExecutionRequest) ProtoMessage() {}
221
222 > func (x *StartWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
223 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[1]
224 > if x != nil {
225 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) request_response.pb.go
226 > if ms.LoadMessageInfo() == nil {
227 > ms.StoreMessageInfo(mi)
228 > }
229 > return ms
230 }
231 > return mi.MessageOf(x) request_response.pb.go
232 }
233
237 }
238
239 > func (x *StartWorkflowExecutionRequest) GetNamespaceId() string { request_response.pb.go
240 > if x != nil {
241 > return x.NamespaceId
242 > }
243 return ""
244 }
245
246 > func (x *StartWorkflowExecutionRequest) GetStartRequest() *v1.StartWorkflowExecutionRequest { request_response.pb.go
247 > if x != nil {
248 > return x.StartRequest
249 > }
250 return nil
251 }
252
253 > func (x *StartWorkflowExecutionRequest) GetParentExecutionInfo() *v11.ParentExecutionInfo { request_response.pb.go
254 > if x != nil {
255 > return x.ParentExecutionInfo
256 > }
257 return nil
258 }
259
260 > func (x *StartWorkflowExecutionRequest) GetAttempt() int32 { request_response.pb.go
261 > if x != nil {
262 > return x.Attempt
263 > }
264 return 0
265 }
279 }
280
281 > func (x *StartWorkflowExecutionRequest) GetContinuedFailure() *v13.Failure { request_response.pb.go
282 > if x != nil {
283 > return x.ContinuedFailure
284 > }
285 return nil
286 }
321 }
322
323 > func (x *StartWorkflowExecutionRequest) GetVersioningOverride() *v15.VersioningOverride { request_response.pb.go
324 > if x != nil {
325 > return x.VersioningOverride
326 > }
327 return nil
328 }
356 }
357
358 > func (x *StartWorkflowExecutionRequest) GetTimeSkippingStatePropagation() *v14.TimeSkippingStatePropagation { request_response.pb.go
359 > if x != nil {
360 > return x.TimeSkippingStatePropagation
361 > }
362 return nil
363 }
380 }
381
382 > func (x *StartWorkflowExecutionResponse) Reset() { request_response.pb.go
383 > *x = StartWorkflowExecutionResponse{}
384 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[2]
385 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
386 > ms.StoreMessageInfo(mi)
387 > }
388
389 func (x *StartWorkflowExecutionResponse) String() string {
393 func (*StartWorkflowExecutionResponse) ProtoMessage() {}
394
395 > func (x *StartWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
396 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[2]
397 > if x != nil {
398 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) request_response.pb.go
399 > if ms.LoadMessageInfo() == nil {
400 > ms.StoreMessageInfo(mi)
401 > }
402 > return ms
403 }
404 > return mi.MessageOf(x) request_response.pb.go
405 }
406
410 }
411
412 > func (x *StartWorkflowExecutionResponse) GetRunId() string { request_response.pb.go
413 > if x != nil {
414 > return x.RunId
415 > }
416 return ""
417 }
424 }
425
426 > func (x *StartWorkflowExecutionResponse) GetEagerWorkflowTask() *v1.PollWorkflowTaskQueueResponse { request_response.pb.go
427 > if x != nil {
428 > return x.EagerWorkflowTask
429 > }
430 return nil
431 }
438 }
439
440 > func (x *StartWorkflowExecutionResponse) GetStatus() v12.WorkflowExecutionStatus { request_response.pb.go
441 > if x != nil {
442 > return x.Status
443 > }
444 return v12.WorkflowExecutionStatus(0)
445 }
446
447 > func (x *StartWorkflowExecutionResponse) GetLink() *v14.Link { request_response.pb.go
448 > if x != nil {
449 > return x.Link
450 > }
451 return nil
452 }
453
454 > func (x *StartWorkflowExecutionResponse) GetFirstExecutionRunId() string { request_response.pb.go
455 > if x != nil {
456 > return x.FirstExecutionRunId
457 > }
458 return ""
459 }
484 func (*GetMutableStateRequest) ProtoMessage() {}
485
486 > func (x *GetMutableStateRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
487 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[3]
488 > if x != nil {
489 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
490 if ms.LoadMessageInfo() == nil {
501 }
502
503 > func (x *GetMutableStateRequest) GetNamespaceId() string { request_response.pb.go
504 > if x != nil {
505 > return x.NamespaceId
506 > }
507 return ""
508 }
515 }
516
517 > func (x *GetMutableStateRequest) GetExpectedNextEventId() int64 { request_response.pb.go
518 > if x != nil {
519 > return x.ExpectedNextEventId
520 > }
521 return 0
522 }
529 }
530
531 > func (x *GetMutableStateRequest) GetVersionHistoryItem() *v19.VersionHistoryItem { request_response.pb.go
532 > if x != nil {
533 > return x.VersionHistoryItem
534 > }
535 return nil
536 }
592 func (*GetMutableStateResponse) ProtoMessage() {}
593
594 > func (x *GetMutableStateResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
595 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[4]
596 > if x != nil {
597 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
598 if ms.LoadMessageInfo() == nil {
623 }
624
625 > func (x *GetMutableStateResponse) GetNextEventId() int64 { request_response.pb.go
626 > if x != nil {
627 > return x.NextEventId
628 > }
629 return 0
630 }
637 }
638
639 > func (x *GetMutableStateResponse) GetLastFirstEventId() int64 { request_response.pb.go
640 > if x != nil {
641 > return x.LastFirstEventId
642 > }
643 return 0
644 }
679 }
680
681 > func (x *GetMutableStateResponse) GetWorkflowStatus() v12.WorkflowExecutionStatus { request_response.pb.go
682 > if x != nil {
683 > return x.WorkflowStatus
684 > }
685 return v12.WorkflowExecutionStatus(0)
686 }
687
688 > func (x *GetMutableStateResponse) GetVersionHistories() *v19.VersionHistories { request_response.pb.go
689 > if x != nil {
690 > return x.VersionHistories
691 > }
692 return nil
693 }
735 }
736
737 > func (x *GetMutableStateResponse) GetTransitionHistory() []*v110.VersionedTransition { request_response.pb.go
738 > if x != nil {
739 > return x.TransitionHistory
740 > }
741 return nil
742 }
749 }
750
751 > func (x *GetMutableStateResponse) GetTransientOrSpeculativeTasks() *v19.TransientWorkflowTaskInfo { request_response.pb.go
752 > if x != nil {
753 > return x.TransientOrSpeculativeTasks
754 > }
755 return nil
756 }
780 func (*PollMutableStateRequest) ProtoMessage() {}
781
782 > func (x *PollMutableStateRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
783 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[5]
784 > if x != nil {
785 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
786 if ms.LoadMessageInfo() == nil {
868 func (*PollMutableStateResponse) ProtoMessage() {}
869
870 > func (x *PollMutableStateResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
871 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[6]
872 > if x != nil {
873 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
874 if ms.LoadMessageInfo() == nil {
1004 func (*ResetStickyTaskQueueRequest) ProtoMessage() {}
1005
1006 > func (x *ResetStickyTaskQueueRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
1007 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[7]
1008 > if x != nil {
1009 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1010 if ms.LoadMessageInfo() == nil {
1054 func (*ResetStickyTaskQueueResponse) ProtoMessage() {}
1055
1056 > func (x *ResetStickyTaskQueueResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
1057 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[8]
1058 > if x != nil {
1059 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1060 if ms.LoadMessageInfo() == nil {
1093 func (*ExecuteMultiOperationRequest) ProtoMessage() {}
1094
1095 > func (x *ExecuteMultiOperationRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
1096 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[9]
1097 > if x != nil {
1098 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1099 if ms.LoadMessageInfo() == nil {
1151 func (*ExecuteMultiOperationResponse) ProtoMessage() {}
1152
1153 > func (x *ExecuteMultiOperationResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
1154 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[10]
1155 > if x != nil {
1156 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1157 if ms.LoadMessageInfo() == nil {
1203 }
1204
1205 > func (x *RecordWorkflowTaskStartedRequest) Reset() { request_response.pb.go
1206 > *x = RecordWorkflowTaskStartedRequest{}
1207 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[11]
1208 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1209 > ms.StoreMessageInfo(mi)
1210 > }
1211
1212 func (x *RecordWorkflowTaskStartedRequest) String() string {
1216 func (*RecordWorkflowTaskStartedRequest) ProtoMessage() {}
1217
1218 > func (x *RecordWorkflowTaskStartedRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
1219 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[11]
1220 > if x != nil {
1221 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) request_response.pb.go
1222 > if ms.LoadMessageInfo() == nil {
1223 > ms.StoreMessageInfo(mi)
1224 > }
1225 > return ms
1226 }
1227 > return mi.MessageOf(x) request_response.pb.go
1228 }
1229
1233 }
1234
1235 > func (x *RecordWorkflowTaskStartedRequest) GetNamespaceId() string { request_response.pb.go
1236 > if x != nil {
1237 > return x.NamespaceId
1238 > }
1239 return ""
1240 }
1241
1242 > func (x *RecordWorkflowTaskStartedRequest) GetWorkflowExecution() *v14.WorkflowExecution { request_response.pb.go
1243 > if x != nil {
1244 > return x.WorkflowExecution
1245 > }
1246 return nil
1247 }
1248
1249 > func (x *RecordWorkflowTaskStartedRequest) GetScheduledEventId() int64 { request_response.pb.go
1250 > if x != nil {
1251 > return x.ScheduledEventId
1252 > }
1253 return 0
1254 }
1255
1256 > func (x *RecordWorkflowTaskStartedRequest) GetRequestId() string { request_response.pb.go
1257 > if x != nil {
1258 > return x.RequestId
1259 > }
1260 return ""
1261 }
1275 }
1276
1277 > func (x *RecordWorkflowTaskStartedRequest) GetBuildIdRedirectInfo() *v113.BuildIdRedirectInfo { request_response.pb.go
1278 > if x != nil {
1279 > return x.BuildIdRedirectInfo
1280 > }
1281 return nil
1282 }
1289 }
1290
1291 > func (x *RecordWorkflowTaskStartedRequest) GetVersionDirective() *v113.TaskVersionDirective { request_response.pb.go
1292 > if x != nil {
1293 > return x.VersionDirective
1294 > }
1295 return nil
1296 }
1297
1298 > func (x *RecordWorkflowTaskStartedRequest) GetStamp() int32 { request_response.pb.go
1299 > if x != nil {
1300 > return x.Stamp
1301 > }
1302 return 0
1303 }
1358 }
1359
1360 > func (x *RecordWorkflowTaskStartedResponse) Reset() { request_response.pb.go
1361 > *x = RecordWorkflowTaskStartedResponse{}
1362 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[12]
1363 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1364 > ms.StoreMessageInfo(mi)
1365 > }
1366
1367 func (x *RecordWorkflowTaskStartedResponse) String() string {
1371 func (*RecordWorkflowTaskStartedResponse) ProtoMessage() {}
1372
1373 > func (x *RecordWorkflowTaskStartedResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
1374 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[12]
1375 > if x != nil {
1376 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) request_response.pb.go
1377 > if ms.LoadMessageInfo() == nil {
1378 > ms.StoreMessageInfo(mi)
1379 > }
1380 > return ms
1381 }
1382 > return mi.MessageOf(x) request_response.pb.go
1383 }
1384
1402 }
1403
1404 > func (x *RecordWorkflowTaskStartedResponse) GetScheduledEventId() int64 { request_response.pb.go
1405 > if x != nil {
1406 > return x.ScheduledEventId
1407 > }
1408 return 0
1409 }
1410
1411 > func (x *RecordWorkflowTaskStartedResponse) GetStartedEventId() int64 { request_response.pb.go
1412 > if x != nil {
1413 > return x.StartedEventId
1414 > }
1415 return 0
1416 }
1423 }
1424
1425 > func (x *RecordWorkflowTaskStartedResponse) GetAttempt() int32 { request_response.pb.go
1426 > if x != nil {
1427 > return x.Attempt
1428 > }
1429 return 0
1430 }
1465 }
1466
1467 > func (x *RecordWorkflowTaskStartedResponse) GetStartedTime() *timestamppb.Timestamp { request_response.pb.go
1468 > if x != nil {
1469 > return x.StartedTime
1470 > }
1471 return nil
1472 }
1479 }
1480
1481 > func (x *RecordWorkflowTaskStartedResponse) GetClock() *v18.VectorClock { request_response.pb.go
1482 > if x != nil {
1483 > return x.Clock
1484 > }
1485 return nil
1486 }
1493 }
1494
1495 > func (x *RecordWorkflowTaskStartedResponse) GetVersion() int64 { request_response.pb.go
1496 > if x != nil {
1497 > return x.Version
1498 > }
1499 return 0
1500 }
1590 func (*RecordWorkflowTaskStartedResponseWithRawHistory) ProtoMessage() {}
1591
1592 > func (x *RecordWorkflowTaskStartedResponseWithRawHistory) ProtoReflect() protoreflect.Message { request_response.pb.go
1593 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[13]
1594 > if x != nil {
1595 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1596 > if ms.LoadMessageInfo() == nil {
1597 > ms.StoreMessageInfo(mi)
1598 > }
1599 > return ms
1600 }
1601 return mi.MessageOf(x)
1635 }
1636
1637 > func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetNextEventId() int64 { request_response.pb.go
1638 > if x != nil {
1639 > return x.NextEventId
1640 > }
1641 return 0
1642 }
1649 }
1650
1651 > func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetStickyExecutionEnabled() bool { request_response.pb.go
1652 > if x != nil {
1653 > return x.StickyExecutionEnabled
1654 > }
1655 return false
1656 }
1657
1658 > func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetTransientWorkflowTask() *v19.TransientWorkflowTaskInfo { request_response.pb.go
1659 > if x != nil {
1660 > return x.TransientWorkflowTask
1661 > }
1662 return nil
1663 }
1670 }
1671
1672 > func (x *RecordWorkflowTaskStartedResponseWithRawHistory) GetBranchToken() []byte { request_response.pb.go
1673 > if x != nil {
1674 > return x.BranchToken
1675 > }
1676 return nil
1677 }
1789 func (*RecordActivityTaskStartedRequest) ProtoMessage() {}
1790
1791 > func (x *RecordActivityTaskStartedRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
1792 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[14]
1793 > if x != nil {
1794 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1795 if ms.LoadMessageInfo() == nil {
1923 func (*RecordActivityTaskStartedResponse) ProtoMessage() {}
1924
1925 > func (x *RecordActivityTaskStartedResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
1926 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[15]
1927 > if x != nil {
1928 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1929 if ms.LoadMessageInfo() == nil {
2039 }
2040
2041 > func (x *RespondWorkflowTaskCompletedRequest) Reset() { request_response.pb.go
2042 > *x = RespondWorkflowTaskCompletedRequest{}
2043 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[16]
2044 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2045 > ms.StoreMessageInfo(mi)
2046 > }
2047
2048 func (x *RespondWorkflowTaskCompletedRequest) String() string {
2052 func (*RespondWorkflowTaskCompletedRequest) ProtoMessage() {}
2053
2054 > func (x *RespondWorkflowTaskCompletedRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
2055 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[16]
2056 > if x != nil {
2057 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) request_response.pb.go
2058 > if ms.LoadMessageInfo() == nil {
2059 > ms.StoreMessageInfo(mi)
2060 > }
2061 > return ms
2062 }
2063 > return mi.MessageOf(x) request_response.pb.go
2064 }
2065
2069 }
2070
2071 > func (x *RespondWorkflowTaskCompletedRequest) GetNamespaceId() string { request_response.pb.go
2072 > if x != nil {
2073 > return x.NamespaceId
2074 > }
2075 return ""
2076 }
2077
2078 > func (x *RespondWorkflowTaskCompletedRequest) GetCompleteRequest() *v1.RespondWorkflowTaskCompletedRequest { request_response.pb.go
2079 > if x != nil {
2080 > return x.CompleteRequest
2081 > }
2082 return nil
2083 }
2094 }
2095
2096 > func (x *RespondWorkflowTaskCompletedResponse) Reset() { request_response.pb.go
2097 > *x = RespondWorkflowTaskCompletedResponse{}
2098 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[17]
2099 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2100 > ms.StoreMessageInfo(mi)
2101 > }
2102
2103 func (x *RespondWorkflowTaskCompletedResponse) String() string {
2107 func (*RespondWorkflowTaskCompletedResponse) ProtoMessage() {}
2108
2109 > func (x *RespondWorkflowTaskCompletedResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
2110 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[17]
2111 > if x != nil {
2112 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) request_response.pb.go
2113 > if ms.LoadMessageInfo() == nil {
2114 > ms.StoreMessageInfo(mi)
2115 > }
2116 > return ms
2117 }
2118 > return mi.MessageOf(x) request_response.pb.go
2119 }
2120
2174 func (*RespondWorkflowTaskFailedRequest) ProtoMessage() {}
2175
2176 > func (x *RespondWorkflowTaskFailedRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
2177 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[18]
2178 > if x != nil {
2179 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2180 if ms.LoadMessageInfo() == nil {
2224 func (*RespondWorkflowTaskFailedResponse) ProtoMessage() {}
2225
2226 > func (x *RespondWorkflowTaskFailedResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
2227 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[19]
2228 > if x != nil {
2229 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2230 if ms.LoadMessageInfo() == nil {
2265 func (*IsWorkflowTaskValidRequest) ProtoMessage() {}
2266
2267 > func (x *IsWorkflowTaskValidRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
2268 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[20]
2269 > if x != nil {
2270 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2271 if ms.LoadMessageInfo() == nil {
2338 func (*IsWorkflowTaskValidResponse) ProtoMessage() {}
2339
2340 > func (x *IsWorkflowTaskValidResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
2341 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[21]
2342 > if x != nil {
2343 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2344 if ms.LoadMessageInfo() == nil {
2383 func (*RecordActivityTaskHeartbeatRequest) ProtoMessage() {}
2384
2385 > func (x *RecordActivityTaskHeartbeatRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
2386 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[22]
2387 > if x != nil {
2388 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2389 if ms.LoadMessageInfo() == nil {
2436 func (*RecordActivityTaskHeartbeatResponse) ProtoMessage() {}
2437
2438 > func (x *RecordActivityTaskHeartbeatResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
2439 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[23]
2440 > if x != nil {
2441 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2442 if ms.LoadMessageInfo() == nil {
2495 func (*RespondActivityTaskCompletedRequest) ProtoMessage() {}
2496
2497 > func (x *RespondActivityTaskCompletedRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
2498 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[24]
2499 > if x != nil {
2500 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2501 if ms.LoadMessageInfo() == nil {
2545 func (*RespondActivityTaskCompletedResponse) ProtoMessage() {}
2546
2547 > func (x *RespondActivityTaskCompletedResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
2548 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[25]
2549 > if x != nil {
2550 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2551 if ms.LoadMessageInfo() == nil {
2583 func (*RespondActivityTaskFailedRequest) ProtoMessage() {}
2584
2585 > func (x *RespondActivityTaskFailedRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
2586 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[26]
2587 > if x != nil {
2588 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2589 if ms.LoadMessageInfo() == nil {
2633 func (*RespondActivityTaskFailedResponse) ProtoMessage() {}
2634
2635 > func (x *RespondActivityTaskFailedResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
2636 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[27]
2637 > if x != nil {
2638 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2639 if ms.LoadMessageInfo() == nil {
2671 func (*RespondActivityTaskCanceledRequest) ProtoMessage() {}
2672
2673 > func (x *RespondActivityTaskCanceledRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
2674 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[28]
2675 > if x != nil {
2676 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2677 if ms.LoadMessageInfo() == nil {
2721 func (*RespondActivityTaskCanceledResponse) ProtoMessage() {}
2722
2723 > func (x *RespondActivityTaskCanceledResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
2724 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[29]
2725 > if x != nil {
2726 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2727 if ms.LoadMessageInfo() == nil {
2763 func (*IsActivityTaskValidRequest) ProtoMessage() {}
2764
2765 > func (x *IsActivityTaskValidRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
2766 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[30]
2767 > if x != nil {
2768 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2769 if ms.LoadMessageInfo() == nil {
2836 func (*IsActivityTaskValidResponse) ProtoMessage() {}
2837
2838 > func (x *IsActivityTaskValidResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
2839 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[31]
2840 > if x != nil {
2841 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2842 if ms.LoadMessageInfo() == nil {
2883 func (*SignalWorkflowExecutionRequest) ProtoMessage() {}
2884
2885 > func (x *SignalWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
2886 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[32]
2887 > if x != nil {
2888 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2889 if ms.LoadMessageInfo() == nil {
2948 func (*SignalWorkflowExecutionResponse) ProtoMessage() {}
2949
2950 > func (x *SignalWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
2951 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[33]
2952 > if x != nil {
2953 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2954 if ms.LoadMessageInfo() == nil {
2996 func (*SignalWithStartWorkflowExecutionRequest) ProtoMessage() {}
2997
2998 > func (x *SignalWithStartWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
2999 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[34]
3000 > if x != nil {
3001 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3002 if ms.LoadMessageInfo() == nil {
3053 func (*SignalWithStartWorkflowExecutionResponse) ProtoMessage() {}
3054
3055 > func (x *SignalWithStartWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
3056 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[35]
3057 > if x != nil {
3058 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3059 if ms.LoadMessageInfo() == nil {
3120 func (*RemoveSignalMutableStateRequest) ProtoMessage() {}
3121
3122 > func (x *RemoveSignalMutableStateRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
3123 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[36]
3124 > if x != nil {
3125 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3126 if ms.LoadMessageInfo() == nil {
3177 func (*RemoveSignalMutableStateResponse) ProtoMessage() {}
3178
3179 > func (x *RemoveSignalMutableStateResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
3180 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[37]
3181 > if x != nil {
3182 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3183 if ms.LoadMessageInfo() == nil {
3217 func (*TerminateWorkflowExecutionRequest) ProtoMessage() {}
3218
3219 > func (x *TerminateWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
3220 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[38]
3221 > if x != nil {
3222 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3223 if ms.LoadMessageInfo() == nil {
3281 func (*TerminateWorkflowExecutionResponse) ProtoMessage() {}
3282
3283 > func (x *TerminateWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
3284 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[39]
3285 > if x != nil {
3286 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3287 if ms.LoadMessageInfo() == nil {
3320 func (*DeleteWorkflowExecutionRequest) ProtoMessage() {}
3321
3322 > func (x *DeleteWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
3323 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[40]
3324 > if x != nil {
3325 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3326 if ms.LoadMessageInfo() == nil {
3377 func (*DeleteWorkflowExecutionResponse) ProtoMessage() {}
3378
3379 > func (x *DeleteWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
3380 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[41]
3381 > if x != nil {
3382 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3383 if ms.LoadMessageInfo() == nil {
3415 func (*ResetWorkflowExecutionRequest) ProtoMessage() {}
3416
3417 > func (x *ResetWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
3418 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[42]
3419 > if x != nil {
3420 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3421 if ms.LoadMessageInfo() == nil {
3466 func (*ResetWorkflowExecutionResponse) ProtoMessage() {}
3467
3468 > func (x *ResetWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
3469 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[43]
3470 > if x != nil {
3471 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3472 if ms.LoadMessageInfo() == nil {
3514 func (*RequestCancelWorkflowExecutionRequest) ProtoMessage() {}
3515
3516 > func (x *RequestCancelWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
3517 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[44]
3518 > if x != nil {
3519 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3520 if ms.LoadMessageInfo() == nil {
3585 func (*RequestCancelWorkflowExecutionResponse) ProtoMessage() {}
3586
3587 > func (x *RequestCancelWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
3588 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[45]
3589 > if x != nil {
3590 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3591 if ms.LoadMessageInfo() == nil {
3626 func (*ScheduleWorkflowTaskRequest) ProtoMessage() {}
3627
3628 > func (x *ScheduleWorkflowTaskRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
3629 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[46]
3630 > if x != nil {
3631 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3632 if ms.LoadMessageInfo() == nil {
3697 func (*ScheduleWorkflowTaskResponse) ProtoMessage() {}
3698
3699 > func (x *ScheduleWorkflowTaskResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
3700 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[47]
3701 > if x != nil {
3702 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3703 if ms.LoadMessageInfo() == nil {
3736 func (*VerifyFirstWorkflowTaskScheduledRequest) ProtoMessage() {}
3737
3738 > func (x *VerifyFirstWorkflowTaskScheduledRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
3739 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[48]
3740 > if x != nil {
3741 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3742 if ms.LoadMessageInfo() == nil {
3793 func (*VerifyFirstWorkflowTaskScheduledResponse) ProtoMessage() {}
3794
3795 > func (x *VerifyFirstWorkflowTaskScheduledResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
3796 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[49]
3797 > if x != nil {
3798 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3799 if ms.LoadMessageInfo() == nil {
3843 func (*RecordChildExecutionCompletedRequest) ProtoMessage() {}
3844
3845 > func (x *RecordChildExecutionCompletedRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
3846 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[50]
3847 > if x != nil {
3848 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3849 if ms.LoadMessageInfo() == nil {
3935 func (*RecordChildExecutionCompletedResponse) ProtoMessage() {}
3936
3937 > func (x *RecordChildExecutionCompletedResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
3938 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[51]
3939 > if x != nil {
3940 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3941 if ms.LoadMessageInfo() == nil {
3978 func (*VerifyChildExecutionCompletionRecordedRequest) ProtoMessage() {}
3979
3980 > func (x *VerifyChildExecutionCompletionRecordedRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
3981 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[52]
3982 > if x != nil {
3983 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3984 if ms.LoadMessageInfo() == nil {
4063 func (*VerifyChildExecutionCompletionRecordedResponse) ProtoMessage() {}
4064
4065 > func (x *VerifyChildExecutionCompletionRecordedResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
4066 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[53]
4067 > if x != nil {
4068 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4069 if ms.LoadMessageInfo() == nil {
4101 func (*DescribeWorkflowExecutionRequest) ProtoMessage() {}
4102
4103 > func (x *DescribeWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
4104 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[54]
4105 > if x != nil {
4106 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4107 if ms.LoadMessageInfo() == nil {
4159 func (*DescribeWorkflowExecutionResponse) ProtoMessage() {}
4160
4161 > func (x *DescribeWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
4162 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[55]
4163 > if x != nil {
4164 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4165 if ms.LoadMessageInfo() == nil {
4259 func (*ReplicateEventsV2Request) ProtoMessage() {}
4260
4261 > func (x *ReplicateEventsV2Request) ProtoReflect() protoreflect.Message { request_response.pb.go
4262 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[56]
4263 > if x != nil {
4264 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4265 if ms.LoadMessageInfo() == nil {
4344 func (*ReplicateEventsV2Response) ProtoMessage() {}
4345
4346 > func (x *ReplicateEventsV2Response) ProtoReflect() protoreflect.Message { request_response.pb.go
4347 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[57]
4348 > if x != nil {
4349 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4350 if ms.LoadMessageInfo() == nil {
4385 func (*ReplicateWorkflowStateRequest) ProtoMessage() {}
4386
4387 > func (x *ReplicateWorkflowStateRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
4388 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[58]
4389 > if x != nil {
4390 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4391 if ms.LoadMessageInfo() == nil {
4456 func (*ReplicateWorkflowStateResponse) ProtoMessage() {}
4457
4458 > func (x *ReplicateWorkflowStateResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
4459 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[59]
4460 > if x != nil {
4461 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4462 if ms.LoadMessageInfo() == nil {
4495 func (*SyncShardStatusRequest) ProtoMessage() {}
4496
4497 > func (x *SyncShardStatusRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
4498 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[60]
4499 > if x != nil {
4500 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4501 if ms.LoadMessageInfo() == nil {
4552 func (*SyncShardStatusResponse) ProtoMessage() {}
4553
4554 > func (x *SyncShardStatusResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
4555 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[61]
4556 > if x != nil {
4557 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4558 if ms.LoadMessageInfo() == nil {
4621 func (*SyncActivityRequest) ProtoMessage() {}
4622
4623 > func (x *SyncActivityRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
4624 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[62]
4625 > if x != nil {
4626 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4627 if ms.LoadMessageInfo() == nil {
5126 func (*SyncActivityResponse) ProtoMessage() {}
5127
5128 > func (x *SyncActivityResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
5129 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[65]
5130 > if x != nil {
5131 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5132 if ms.LoadMessageInfo() == nil {
5167 func (*DescribeMutableStateRequest) ProtoMessage() {}
5168
5169 > func (x *DescribeMutableStateRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
5170 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[66]
5171 > if x != nil {
5172 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5173 if ms.LoadMessageInfo() == nil {
5236 func (*DescribeMutableStateResponse) ProtoMessage() {}
5237
5238 > func (x *DescribeMutableStateResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
5239 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[67]
5240 > if x != nil {
5241 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5242 if ms.LoadMessageInfo() == nil {
5292 func (*DescribeHistoryHostRequest) ProtoMessage() {}
5293
5294 > func (x *DescribeHistoryHostRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
5295 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[68]
5296 > if x != nil {
5297 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5298 if ms.LoadMessageInfo() == nil {
5360 func (*DescribeHistoryHostResponse) ProtoMessage() {}
5361
5362 > func (x *DescribeHistoryHostResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
5363 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[69]
5364 > if x != nil {
5365 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5366 if ms.LoadMessageInfo() == nil {
5425 func (*CloseShardRequest) ProtoMessage() {}
5426
5427 > func (x *CloseShardRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
5428 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[70]
5429 > if x != nil {
5430 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5431 if ms.LoadMessageInfo() == nil {
5468 func (*CloseShardResponse) ProtoMessage() {}
5469
5470 > func (x *CloseShardResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
5471 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[71]
5472 > if x != nil {
5473 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5474 if ms.LoadMessageInfo() == nil {
5505 func (*GetShardRequest) ProtoMessage() {}
5506
5507 > func (x *GetShardRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
5508 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[72]
5509 > if x != nil {
5510 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5511 if ms.LoadMessageInfo() == nil {
5549 func (*GetShardResponse) ProtoMessage() {}
5550
5551 > func (x *GetShardResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
5552 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[73]
5553 > if x != nil {
5554 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5555 if ms.LoadMessageInfo() == nil {
5597 func (*RemoveTaskRequest) ProtoMessage() {}
5598
5599 > func (x *RemoveTaskRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
5600 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[74]
5601 > if x != nil {
5602 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5603 if ms.LoadMessageInfo() == nil {
5661 func (*RemoveTaskResponse) ProtoMessage() {}
5662
5663 > func (x *RemoveTaskResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
5664 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[75]
5665 > if x != nil {
5666 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5667 if ms.LoadMessageInfo() == nil {
5699 func (*GetReplicationMessagesRequest) ProtoMessage() {}
5700
5701 > func (x *GetReplicationMessagesRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
5702 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[76]
5703 > if x != nil {
5704 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5705 if ms.LoadMessageInfo() == nil {
5750 func (*GetReplicationMessagesResponse) ProtoMessage() {}
5751
5752 > func (x *GetReplicationMessagesResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
5753 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[77]
5754 > if x != nil {
5755 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5756 if ms.LoadMessageInfo() == nil {
5794 func (*GetDLQReplicationMessagesRequest) ProtoMessage() {}
5795
5796 > func (x *GetDLQReplicationMessagesRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
5797 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[78]
5798 > if x != nil {
5799 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5800 if ms.LoadMessageInfo() == nil {
5838 func (*GetDLQReplicationMessagesResponse) ProtoMessage() {}
5839
5840 > func (x *GetDLQReplicationMessagesResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
5841 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[79]
5842 > if x != nil {
5843 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5844 if ms.LoadMessageInfo() == nil {
5883 func (*QueryWorkflowRequest) ProtoMessage() {}
5884
5885 > func (x *QueryWorkflowRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
5886 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[80]
5887 > if x != nil {
5888 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5889 if ms.LoadMessageInfo() == nil {
5934 func (*QueryWorkflowResponse) ProtoMessage() {}
5935
5936 > func (x *QueryWorkflowResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
5937 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[81]
5938 > if x != nil {
5939 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5940 if ms.LoadMessageInfo() == nil {
5979 func (*ReapplyEventsRequest) ProtoMessage() {}
5980
5981 > func (x *ReapplyEventsRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
5982 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[82]
5983 > if x != nil {
5984 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5985 if ms.LoadMessageInfo() == nil {
6029 func (*ReapplyEventsResponse) ProtoMessage() {}
6030
6031 > func (x *ReapplyEventsResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
6032 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[83]
6033 > if x != nil {
6034 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
6035 if ms.LoadMessageInfo() == nil {
6071 func (*GetDLQMessagesRequest) ProtoMessage() {}
6072
6073 > func (x *GetDLQMessagesRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
6074 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[84]
6075 > if x != nil {
6076 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
6077 if ms.LoadMessageInfo() == nil {
6153 func (*GetDLQMessagesResponse) ProtoMessage() {}
6154
6155 > func (x *GetDLQMessagesResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
6156 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[85]
6157 > if x != nil {
6158 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
6159 if ms.LoadMessageInfo() == nil {
6221 func (*PurgeDLQMessagesRequest) ProtoMessage() {}
6222
6223 > func (x *PurgeDLQMessagesRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
6224 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[86]
6225 > if x != nil {
6226 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
6227 if ms.LoadMessageInfo() == nil {
6285 func (*PurgeDLQMessagesResponse) ProtoMessage() {}
6286
6287 > func (x *PurgeDLQMessagesResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
6288 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[87]
6289 > if x != nil {
6290 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
6291 if ms.LoadMessageInfo() == nil {
6327 func (*MergeDLQMessagesRequest) ProtoMessage() {}
6328
6329 > func (x *MergeDLQMessagesRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
6330 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[88]
6331 > if x != nil {
6332 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
6333 if ms.LoadMessageInfo() == nil {
6406 func (*MergeDLQMessagesResponse) ProtoMessage() {}
6407
6408 > func (x *MergeDLQMessagesResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
6409 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[89]
6410 > if x != nil {
6411 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
6412 if ms.LoadMessageInfo() == nil {
6453 func (*RefreshWorkflowTasksRequest) ProtoMessage() {}
6454
6455 > func (x *RefreshWorkflowTasksRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
6456 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[90]
6457 > if x != nil {
6458 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
6459 if ms.LoadMessageInfo() == nil {
6510 func (*RefreshWorkflowTasksResponse) ProtoMessage() {}
6511
6512 > func (x *RefreshWorkflowTasksResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
6513 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[91]
6514 > if x != nil {
6515 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
6516 if ms.LoadMessageInfo() == nil {
6551 func (*GenerateLastHistoryReplicationTasksRequest) ProtoMessage() {}
6552
6553 > func (x *GenerateLastHistoryReplicationTasksRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
6554 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[92]
6555 > if x != nil {
6556 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
6557 if ms.LoadMessageInfo() == nil {
6617 func (*GenerateLastHistoryReplicationTasksResponse) ProtoMessage() {}
6618
6619 > func (x *GenerateLastHistoryReplicationTasksResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
6620 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[93]
6621 > if x != nil {
6622 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
6623 if ms.LoadMessageInfo() == nil {
6669 func (*GetReplicationStatusRequest) ProtoMessage() {}
6670
6671 > func (x *GetReplicationStatusRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
6672 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[94]
6673 > if x != nil {
6674 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
6675 if ms.LoadMessageInfo() == nil {
6713 func (*GetReplicationStatusResponse) ProtoMessage() {}
6714
6715 > func (x *GetReplicationStatusResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
6716 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[95]
6717 > if x != nil {
6718 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
6719 if ms.LoadMessageInfo() == nil {
6943 func (*RebuildMutableStateRequest) ProtoMessage() {}
6944
6945 > func (x *RebuildMutableStateRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
6946 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[99]
6947 > if x != nil {
6948 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
6949 if ms.LoadMessageInfo() == nil {
6993 func (*RebuildMutableStateResponse) ProtoMessage() {}
6994
6995 > func (x *RebuildMutableStateResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
6996 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[100]
6997 > if x != nil {
6998 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
6999 if ms.LoadMessageInfo() == nil {
7034 func (*ImportWorkflowExecutionRequest) ProtoMessage() {}
7035
7036 > func (x *ImportWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
7037 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[101]
7038 > if x != nil {
7039 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7040 if ms.LoadMessageInfo() == nil {
7107 func (*ImportWorkflowExecutionResponse) ProtoMessage() {}
7108
7109 > func (x *ImportWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
7110 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[102]
7111 > if x != nil {
7112 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7113 if ms.LoadMessageInfo() == nil {
7161 func (*DeleteWorkflowVisibilityRecordRequest) ProtoMessage() {}
7162
7163 > func (x *DeleteWorkflowVisibilityRecordRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
7164 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[103]
7165 > if x != nil {
7166 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7167 if ms.LoadMessageInfo() == nil {
7225 func (*DeleteWorkflowVisibilityRecordResponse) ProtoMessage() {}
7226
7227 > func (x *DeleteWorkflowVisibilityRecordResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
7228 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[104]
7229 > if x != nil {
7230 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7231 if ms.LoadMessageInfo() == nil {
7266 func (*UpdateWorkflowExecutionRequest) ProtoMessage() {}
7267
7268 > func (x *UpdateWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
7269 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[105]
7270 > if x != nil {
7271 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7272 if ms.LoadMessageInfo() == nil {
7317 func (*UpdateWorkflowExecutionResponse) ProtoMessage() {}
7318
7319 > func (x *UpdateWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
7320 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[106]
7321 > if x != nil {
7322 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7323 if ms.LoadMessageInfo() == nil {
7364 func (*StreamWorkflowReplicationMessagesRequest) ProtoMessage() {}
7365
7366 > func (x *StreamWorkflowReplicationMessagesRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
7367 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[107]
7368 > if x != nil {
7369 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7370 if ms.LoadMessageInfo() == nil {
7431 func (*StreamWorkflowReplicationMessagesResponse) ProtoMessage() {}
7432
7433 > func (x *StreamWorkflowReplicationMessagesResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
7434 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[108]
7435 > if x != nil {
7436 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7437 if ms.LoadMessageInfo() == nil {
7496 func (*PollWorkflowExecutionUpdateRequest) ProtoMessage() {}
7497
7498 > func (x *PollWorkflowExecutionUpdateRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
7499 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[109]
7500 > if x != nil {
7501 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7502 if ms.LoadMessageInfo() == nil {
7547 func (*PollWorkflowExecutionUpdateResponse) ProtoMessage() {}
7548
7549 > func (x *PollWorkflowExecutionUpdateResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
7550 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[110]
7551 > if x != nil {
7552 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7553 if ms.LoadMessageInfo() == nil {
7579 }
7580
7581 > func (x *GetWorkflowExecutionHistoryRequest) Reset() { request_response.pb.go
7582 > *x = GetWorkflowExecutionHistoryRequest{}
7583 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[111]
7584 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7585 > ms.StoreMessageInfo(mi)
7586 > }
7587
7588 func (x *GetWorkflowExecutionHistoryRequest) String() string {
7592 func (*GetWorkflowExecutionHistoryRequest) ProtoMessage() {}
7593
7594 > func (x *GetWorkflowExecutionHistoryRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
7595 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[111]
7596 > if x != nil {
7597 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) request_response.pb.go
7598 > if ms.LoadMessageInfo() == nil {
7599 > ms.StoreMessageInfo(mi)
7600 > }
7601 > return ms
7602 }
7603 > return mi.MessageOf(x) request_response.pb.go
7604 }
7605
7609 }
7610
7611 > func (x *GetWorkflowExecutionHistoryRequest) GetNamespaceId() string { request_response.pb.go
7612 > if x != nil {
7613 > return x.NamespaceId
7614 > }
7615 return ""
7616 }
7617
7618 > func (x *GetWorkflowExecutionHistoryRequest) GetRequest() *v1.GetWorkflowExecutionHistoryRequest { request_response.pb.go
7619 > if x != nil {
7620 > return x.Request
7621 > }
7622 return nil
7623 }
7631 }
7632
7633 > func (x *GetWorkflowExecutionHistoryResponse) Reset() { request_response.pb.go
7634 > *x = GetWorkflowExecutionHistoryResponse{}
7635 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[112]
7636 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7637 > ms.StoreMessageInfo(mi)
7638 > }
7639
7640 func (x *GetWorkflowExecutionHistoryResponse) String() string {
7644 func (*GetWorkflowExecutionHistoryResponse) ProtoMessage() {}
7645
7646 > func (x *GetWorkflowExecutionHistoryResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
7647 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[112]
7648 > if x != nil {
7649 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) request_response.pb.go
7650 > if ms.LoadMessageInfo() == nil {
7651 > ms.StoreMessageInfo(mi)
7652 > }
7653 > return ms
7654 }
7655 > return mi.MessageOf(x) request_response.pb.go
7656 }
7657
7697 func (*GetWorkflowExecutionHistoryResponseWithRaw) ProtoMessage() {}
7698
7699 > func (x *GetWorkflowExecutionHistoryResponseWithRaw) ProtoReflect() protoreflect.Message { request_response.pb.go
7700 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[113]
7701 > if x != nil {
7702 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7703 > if ms.LoadMessageInfo() == nil {
7704 > ms.StoreMessageInfo(mi)
7705 > }
7706 > return ms
7707 }
7708 return mi.MessageOf(x)
7749 func (*GetWorkflowExecutionHistoryReverseRequest) ProtoMessage() {}
7750
7751 > func (x *GetWorkflowExecutionHistoryReverseRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
7752 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[114]
7753 > if x != nil {
7754 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7755 if ms.LoadMessageInfo() == nil {
7800 func (*GetWorkflowExecutionHistoryReverseResponse) ProtoMessage() {}
7801
7802 > func (x *GetWorkflowExecutionHistoryReverseResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
7803 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[115]
7804 > if x != nil {
7805 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7806 if ms.LoadMessageInfo() == nil {
7848 func (*GetWorkflowExecutionRawHistoryV2Request) ProtoMessage() {}
7849
7850 > func (x *GetWorkflowExecutionRawHistoryV2Request) ProtoReflect() protoreflect.Message { request_response.pb.go
7851 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[116]
7852 > if x != nil {
7853 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7854 if ms.LoadMessageInfo() == nil {
7899 func (*GetWorkflowExecutionRawHistoryV2Response) ProtoMessage() {}
7900
7901 > func (x *GetWorkflowExecutionRawHistoryV2Response) ProtoReflect() protoreflect.Message { request_response.pb.go
7902 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[117]
7903 > if x != nil {
7904 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7905 if ms.LoadMessageInfo() == nil {
7944 func (*GetWorkflowExecutionRawHistoryRequest) ProtoMessage() {}
7945
7946 > func (x *GetWorkflowExecutionRawHistoryRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
7947 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[118]
7948 > if x != nil {
7949 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
7950 if ms.LoadMessageInfo() == nil {
7995 func (*GetWorkflowExecutionRawHistoryResponse) ProtoMessage() {}
7996
7997 > func (x *GetWorkflowExecutionRawHistoryResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
7998 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[119]
7999 > if x != nil {
8000 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8001 if ms.LoadMessageInfo() == nil {
8042 func (*ForceDeleteWorkflowExecutionRequest) ProtoMessage() {}
8043
8044 > func (x *ForceDeleteWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
8045 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[120]
8046 > if x != nil {
8047 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8048 if ms.LoadMessageInfo() == nil {
8100 func (*ForceDeleteWorkflowExecutionResponse) ProtoMessage() {}
8101
8102 > func (x *ForceDeleteWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
8103 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[121]
8104 > if x != nil {
8105 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8106 if ms.LoadMessageInfo() == nil {
8149 func (*DeleteExecutionRequest) ProtoMessage() {}
8150
8151 > func (x *DeleteExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
8152 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[122]
8153 > if x != nil {
8154 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8155 if ms.LoadMessageInfo() == nil {
8220 func (*DeleteExecutionResponse) ProtoMessage() {}
8221
8222 > func (x *DeleteExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
8223 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[123]
8224 > if x != nil {
8225 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8226 if ms.LoadMessageInfo() == nil {
8260 func (*GetDLQTasksRequest) ProtoMessage() {}
8261
8262 > func (x *GetDLQTasksRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
8263 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[124]
8264 > if x != nil {
8265 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8266 if ms.LoadMessageInfo() == nil {
8322 func (*GetDLQTasksResponse) ProtoMessage() {}
8323
8324 > func (x *GetDLQTasksResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
8325 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[125]
8326 > if x != nil {
8327 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8328 if ms.LoadMessageInfo() == nil {
8374 func (*DeleteDLQTasksRequest) ProtoMessage() {}
8375
8376 > func (x *DeleteDLQTasksRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
8377 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[126]
8378 > if x != nil {
8379 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8380 if ms.LoadMessageInfo() == nil {
8426 func (*DeleteDLQTasksResponse) ProtoMessage() {}
8427
8428 > func (x *DeleteDLQTasksResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
8429 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[127]
8430 > if x != nil {
8431 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8432 if ms.LoadMessageInfo() == nil {
8472 func (*ListQueuesRequest) ProtoMessage() {}
8473
8474 > func (x *ListQueuesRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
8475 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[128]
8476 > if x != nil {
8477 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8478 if ms.LoadMessageInfo() == nil {
8531 func (*ListQueuesResponse) ProtoMessage() {}
8532
8533 > func (x *ListQueuesResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
8534 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[129]
8535 > if x != nil {
8536 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8537 if ms.LoadMessageInfo() == nil {
8587 func (*AddTasksRequest) ProtoMessage() {}
8588
8589 > func (x *AddTasksRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
8590 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[130]
8591 > if x != nil {
8592 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8593 if ms.LoadMessageInfo() == nil {
8637 func (*AddTasksResponse) ProtoMessage() {}
8638
8639 > func (x *AddTasksResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
8640 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[131]
8641 > if x != nil {
8642 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8643 if ms.LoadMessageInfo() == nil {
8674 func (*ListTasksRequest) ProtoMessage() {}
8675
8676 > func (x *ListTasksRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
8677 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[132]
8678 > if x != nil {
8679 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8680 if ms.LoadMessageInfo() == nil {
8718 func (*ListTasksResponse) ProtoMessage() {}
8719
8720 > func (x *ListTasksResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
8721 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[133]
8722 > if x != nil {
8723 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8724 if ms.LoadMessageInfo() == nil {
8777 func (*CompleteNexusOperationChasmRequest) ProtoMessage() {}
8778
8779 > func (x *CompleteNexusOperationChasmRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
8780 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[134]
8781 > if x != nil {
8782 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8783 if ms.LoadMessageInfo() == nil {
8891 func (*CompleteNexusOperationChasmResponse) ProtoMessage() {}
8892
8893 > func (x *CompleteNexusOperationChasmResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
8894 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[135]
8895 > if x != nil {
8896 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8897 if ms.LoadMessageInfo() == nil {
8942 func (*CompleteNexusOperationRequest) ProtoMessage() {}
8943
8944 > func (x *CompleteNexusOperationRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
8945 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[136]
8946 > if x != nil {
8947 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
8948 if ms.LoadMessageInfo() == nil {
9056 func (*CompleteNexusOperationResponse) ProtoMessage() {}
9057
9058 > func (x *CompleteNexusOperationResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
9059 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[137]
9060 > if x != nil {
9061 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9062 if ms.LoadMessageInfo() == nil {
9109 func (*InvokeStateMachineMethodRequest) ProtoMessage() {}
9110
9111 > func (x *InvokeStateMachineMethodRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
9112 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[138]
9113 > if x != nil {
9114 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9115 if ms.LoadMessageInfo() == nil {
9189 func (*InvokeStateMachineMethodResponse) ProtoMessage() {}
9190
9191 > func (x *InvokeStateMachineMethodResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
9192 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[139]
9193 > if x != nil {
9194 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9195 if ms.LoadMessageInfo() == nil {
9233 func (*DeepHealthCheckRequest) ProtoMessage() {}
9234
9235 > func (x *DeepHealthCheckRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
9236 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[140]
9237 > if x != nil {
9238 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9239 if ms.LoadMessageInfo() == nil {
9279 func (*DeepHealthCheckResponse) ProtoMessage() {}
9280
9281 > func (x *DeepHealthCheckResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
9282 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[141]
9283 > if x != nil {
9284 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9285 if ms.LoadMessageInfo() == nil {
9336 func (*SyncWorkflowStateRequest) ProtoMessage() {}
9337
9338 > func (x *SyncWorkflowStateRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
9339 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[142]
9340 > if x != nil {
9341 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9342 if ms.LoadMessageInfo() == nil {
9415 func (*SyncWorkflowStateResponse) ProtoMessage() {}
9416
9417 > func (x *SyncWorkflowStateResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
9418 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[143]
9419 > if x != nil {
9420 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9421 if ms.LoadMessageInfo() == nil {
9463 func (*UpdateActivityOptionsRequest) ProtoMessage() {}
9464
9465 > func (x *UpdateActivityOptionsRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
9466 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[144]
9467 > if x != nil {
9468 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9469 if ms.LoadMessageInfo() == nil {
9515 func (*UpdateActivityOptionsResponse) ProtoMessage() {}
9516
9517 > func (x *UpdateActivityOptionsResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
9518 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[145]
9519 > if x != nil {
9520 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9521 if ms.LoadMessageInfo() == nil {
9561 func (*PauseActivityRequest) ProtoMessage() {}
9562
9563 > func (x *PauseActivityRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
9564 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[146]
9565 > if x != nil {
9566 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9567 if ms.LoadMessageInfo() == nil {
9611 func (*PauseActivityResponse) ProtoMessage() {}
9612
9613 > func (x *PauseActivityResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
9614 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[147]
9615 > if x != nil {
9616 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9617 if ms.LoadMessageInfo() == nil {
9650 func (*UnpauseActivityRequest) ProtoMessage() {}
9651
9652 > func (x *UnpauseActivityRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
9653 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[148]
9654 > if x != nil {
9655 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9656 if ms.LoadMessageInfo() == nil {
9700 func (*UnpauseActivityResponse) ProtoMessage() {}
9701
9702 > func (x *UnpauseActivityResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
9703 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[149]
9704 > if x != nil {
9705 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9706 if ms.LoadMessageInfo() == nil {
9739 func (*ResetActivityRequest) ProtoMessage() {}
9740
9741 > func (x *ResetActivityRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
9742 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[150]
9743 > if x != nil {
9744 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9745 if ms.LoadMessageInfo() == nil {
9789 func (*ResetActivityResponse) ProtoMessage() {}
9790
9791 > func (x *ResetActivityResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
9792 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[151]
9793 > if x != nil {
9794 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9795 if ms.LoadMessageInfo() == nil {
9829 func (*UpdateWorkflowExecutionOptionsRequest) ProtoMessage() {}
9830
9831 > func (x *UpdateWorkflowExecutionOptionsRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
9832 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[152]
9833 > if x != nil {
9834 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9835 if ms.LoadMessageInfo() == nil {
9884 func (*UpdateWorkflowExecutionOptionsResponse) ProtoMessage() {}
9885
9886 > func (x *UpdateWorkflowExecutionOptionsResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
9887 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[153]
9888 > if x != nil {
9889 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9890 if ms.LoadMessageInfo() == nil {
9937 func (*PauseWorkflowExecutionRequest) ProtoMessage() {}
9938
9939 > func (x *PauseWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
9940 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[154]
9941 > if x != nil {
9942 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9943 if ms.LoadMessageInfo() == nil {
9987 func (*PauseWorkflowExecutionResponse) ProtoMessage() {}
9988
9989 > func (x *PauseWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
9990 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[155]
9991 > if x != nil {
9992 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
9993 if ms.LoadMessageInfo() == nil {
10026 func (*UnpauseWorkflowExecutionRequest) ProtoMessage() {}
10027
10028 > func (x *UnpauseWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
10029 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[156]
10030 > if x != nil {
10031 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
10032 if ms.LoadMessageInfo() == nil {
10076 func (*UnpauseWorkflowExecutionResponse) ProtoMessage() {}
10077
10078 > func (x *UnpauseWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
10079 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[157]
10080 > if x != nil {
10081 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
10082 if ms.LoadMessageInfo() == nil {
10115 func (*StartNexusOperationRequest) ProtoMessage() {}
10116
10117 > func (x *StartNexusOperationRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
10118 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[158]
10119 > if x != nil {
10120 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
10121 if ms.LoadMessageInfo() == nil {
10173 func (*StartNexusOperationResponse) ProtoMessage() {}
10174
10175 > func (x *StartNexusOperationResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
10176 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[159]
10177 > if x != nil {
10178 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
10179 if ms.LoadMessageInfo() == nil {
10219 func (*CancelNexusOperationRequest) ProtoMessage() {}
10220
10221 > func (x *CancelNexusOperationRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
10222 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[160]
10223 > if x != nil {
10224 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
10225 if ms.LoadMessageInfo() == nil {
10277 func (*CancelNexusOperationResponse) ProtoMessage() {}
10278
10279 > func (x *CancelNexusOperationResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
10280 > mi := &file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[161]
10281 > if x != nil {
10282 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
10283 if ms.LoadMessageInfo() == nil {
11956 }
11957
11958 > func init() { file_temporal_server_api_historyservice_v1_request_response_proto_init() } request_response.pb.go
11959 > func file_temporal_server_api_historyservice_v1_request_response_proto_init() {
11960 > if File_temporal_server_api_historyservice_v1_request_response_proto != nil {
11961 > return
11962 > }
11963 > file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[107].OneofWrappers = []any{
11964 > (*StreamWorkflowReplicationMessagesRequest_SyncReplicationState)(nil),
11965 > }
11966 > file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[108].OneofWrappers = []any{
11967 > (*StreamWorkflowReplicationMessagesResponse_Messages)(nil),
11968 > }
11969 > file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[134].OneofWrappers = []any{
11970 > (*CompleteNexusOperationChasmRequest_Success)(nil),
11971 > (*CompleteNexusOperationChasmRequest_Failure)(nil),
11972 > }
11973 > file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[136].OneofWrappers = []any{
11974 > (*CompleteNexusOperationRequest_Success)(nil),
11975 > (*CompleteNexusOperationRequest_Failure)(nil),
11976 > }
11977 > file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[162].OneofWrappers = []any{
11978 > (*ExecuteMultiOperationRequest_Operation_StartWorkflow)(nil),
11979 > (*ExecuteMultiOperationRequest_Operation_UpdateWorkflow)(nil),
11980 > }
11981 > file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes[163].OneofWrappers = []any{
11982 > (*ExecuteMultiOperationResponse_Response_StartWorkflow)(nil),
11983 > (*ExecuteMultiOperationResponse_Response_UpdateWorkflow)(nil),
11984 > }
11985 > type x struct{}
11986 > out := protoimpl.TypeBuilder{
11987 > File: protoimpl.DescBuilder{
11988 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
11989 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_historyservice_v1_request_response_proto_rawDesc), len(file_temporal_server_api_historyservice_v1_request_response_proto_rawDesc)),
11990 > NumEnums: 0,
11991 > NumMessages: 171,
11992 > NumExtensions: 1,
11993 > NumServices: 0,
11994 > },
11995 > GoTypes: file_temporal_server_api_historyservice_v1_request_response_proto_goTypes,
11996 > DependencyIndexes: file_temporal_server_api_historyservice_v1_request_response_proto_depIdxs,
11997 > MessageInfos: file_temporal_server_api_historyservice_v1_request_response_proto_msgTypes,
11998 > ExtensionInfos: file_temporal_server_api_historyservice_v1_request_response_proto_extTypes,
11999 > }.Build()
12000 > File_temporal_server_api_historyservice_v1_request_response_proto = out.File
12001 > file_temporal_server_api_historyservice_v1_request_response_proto_goTypes = nil
12002 > file_temporal_server_api_historyservice_v1_request_response_proto_depIdxs = nil
12003 }
go.temporal.io/server/service/history/shard/context_impl.go 745 covered LOC · 169 ranges

Open complete file

205 )
206
207 > func (s *ContextImpl) String() string { context_impl.go
208 > // constant from initialization, no need for locks
209 > return s.stringRepr
210 > }
211
212 > func (s *ContextImpl) GetShardID() int32 { context_impl.go
213 > // constant from initialization, no need for locks
214 > return s.shardID
215 > }
216
217 func (s *ContextImpl) GetRangeID() int64 {
222 }
223
224 > func (s *ContextImpl) GetOwner() string { context_impl.go
225 > // constant from initialization, no need for locks
226 > return s.owner
227 > }
228
229 > func (s *ContextImpl) GetExecutionManager() persistence.ExecutionManager { context_impl.go
230 > // constant from initialization, no need for locks
231 > return s.executionManager
232 > }
233
234 > func (s *ContextImpl) GetPingChecks() []pingable.Check { context_impl.go
235 > return []pingable.Check{
236 > {
237 > Name: s.String() + "-shard-lock",
238 > // rwLock may be held for the duration of renewing shard rangeID, which are called with a
239 > // timeout of shardIOTimeout.
240 > Timeout: s.config.ShardIOTimeout() + 30*time.Second,
241 > Ping: func() []pingable.Pingable {
242 > // call rwLock.Lock directly to bypass metrics since this isn't a real request
243 > s.rwLock.Lock()
244 > //nolint:staticcheck // SA2001 just checking if we can acquire the lock
245 > s.rwLock.Unlock()
246 > return nil
247 > },
248 MetricsName: metrics.DDShardLockLatency.Name(),
249 },
253 // of 10 sec.
254 Timeout: 10*time.Second + 30*time.Second,
255 > Ping: func() []pingable.Pingable { context_impl.go
256 > _ = s.ioSemaphore.Acquire(context.Background(), locks.PriorityHigh, 1)
257 > s.ioSemaphore.Release(1)
258 > return nil
259 > },
260 MetricsName: metrics.DDShardIOSemaphoreLatency.Name(),
261 },
265 func (s *ContextImpl) GetEngine(
266 ctx context.Context,
267 > ) (historyi.Engine, error) { context_impl.go
268 > return s.engineFuture.Get(ctx)
269 > }
270
271 func (s *ContextImpl) AssertOwnership(
272 ctx context.Context,
273 > ) error { context_impl.go
274 > if err := s.ioSemaphoreAcquire(ctx); err != nil {
275 return err
276 }
277 > defer s.ioSemaphoreRelease() context_impl.go
278 >
279 > s.wLock()
280 >
281 > // timeout check should be done within the shard lock, in case of shard lock contention
282 > ctx, cancel, err := s.newDetachedContext(ctx)
283 > if err != nil {
284 s.wUnlock()
285 return err
286 }
287 > defer cancel() context_impl.go
288 >
289 > if err := s.errorByState(); err != nil {
290 s.wUnlock()
291 return err
292 }
293
294 > request := &persistence.AssertShardOwnershipRequest{ context_impl.go
295 > ShardID: s.shardID,
296 > RangeID: s.getRangeIDLocked(),
297 > }
298 > s.wUnlock()
299 >
300 > err = s.persistenceShardManager.AssertShardOwnership(ctx, request)
301 > return s.handleWriteError(request.RangeID, err)
302 }
303
304 > func (s *ContextImpl) NewVectorClock() (*clockspb.VectorClock, error) { context_impl.go
305 > s.wLock()
306 > defer s.wUnlock()
307 >
308 > clock, err := s.generateTaskIDLocked()
309 > if err != nil {
310 return nil, err
311 }
312 > return vclock.NewVectorClock(s.clusterMetadata.GetClusterID(), s.shardID, clock), nil context_impl.go
313 }
314
315 > func (s *ContextImpl) CurrentVectorClock() *clockspb.VectorClock { context_impl.go
316 > s.rLock()
317 > defer s.rUnlock()
318 >
319 > nextTaskKey := s.taskKeyManager.peekTaskKey(tasks.CategoryTransfer)
320 > return vclock.NewVectorClock(s.clusterMetadata.GetClusterID(), s.shardID, nextTaskKey.TaskID)
321 > }
322
323 func (s *ContextImpl) GenerateTaskID() (int64, error) {
328 }
329
330 > func (s *ContextImpl) GetFinalizer() *finalizer.Finalizer { context_impl.go
331 > return s.finalizer
332 > }
333
334 > func (s *ContextImpl) GenerateTaskIDs(number int) ([]int64, error) { context_impl.go
335 > s.wLock()
336 > defer s.wUnlock()
337 >
338 > result := []int64{}
339 > for range number {
340 > id, err := s.generateTaskIDLocked() context_impl.go
341 > if err != nil {
342 return nil, err
343 }
344 > result = append(result, id) context_impl.go
345 }
346 > return result, nil context_impl.go
347 }
348
349 func (s *ContextImpl) GetQueueExclusiveHighReadWatermark(
350 category tasks.Category,
351 > ) tasks.Key { context_impl.go
352 > s.wLock()
353 > defer s.wUnlock()
354 >
355 > return s.taskKeyManager.getExclusiveReaderHighWatermark(category)
356 > }
357
358 func (s *ContextImpl) GetQueueState(
359 category tasks.Category,
360 > ) (*persistencespb.QueueState, bool) { context_impl.go
361 > s.rLock()
362 > defer s.rUnlock()
363 >
364 > queueState, ok := s.shardInfo.QueueStates[int32(category.ID())]
365 > if !ok {
366 > return nil, false context_impl.go
367 > }
368 // need to make a deep copy, in case UpdateReplicationQueueReaderState does a partial update
369 blob, _ := s.payloadSerializer.QueueStateToBlob(queueState)
525 ctx context.Context,
526 request *persistence.GetHistoryTasksRequest,
527 > ) (*persistence.GetHistoryTasksResponse, error) { context_impl.go
528 > if err := s.errorByState(); err != nil {
529 > return nil, err context_impl.go
530 > }
531
532 > resp, err := s.executionManager.GetHistoryTasks(ctx, request) context_impl.go
533 > return resp, s.handleReadError(err)
534 }
535
537 ctx context.Context,
538 request *persistence.CreateWorkflowExecutionRequest,
539 > ) (*persistence.CreateWorkflowExecutionResponse, error) { context_impl.go
540 >
541 > // do not try to get namespace cache within shard lock
542 > namespaceID := namespace.ID(request.NewWorkflowSnapshot.ExecutionInfo.NamespaceId)
543 > namespaceEntry, err := s.GetNamespaceRegistry().GetNamespaceByID(namespaceID)
544 > if err != nil {
545 return nil, err
546 }
547
548 > if err := s.ioSemaphoreAcquire(ctx); err != nil { context_impl.go
549 return nil, err
550 }
551 > defer s.ioSemaphoreRelease() context_impl.go
552 >
553 > s.wLock()
554 >
555 > // timeout check should be done within the shard lock, in case of shard lock contention
556 > ctx, cancel, err := s.newDetachedContext(ctx)
557 > if err != nil {
558 s.wUnlock()
559 return nil, err
560 }
561 > defer cancel() context_impl.go
562 >
563 > if err := s.errorByState(); err != nil {
564 s.wUnlock()
565 return nil, err
566 }
567
568 > if err := s.errorByNamespaceStateLocked(namespaceEntry.Name(), request.NewWorkflowSnapshot.ExecutionInfo.WorkflowId); err != nil { context_impl.go
569 s.wUnlock()
570 return nil, err
571 }
572
573 > requestCompletionFn, err := s.taskKeyManager.setAndTrackTaskKeys( context_impl.go
574 > request.NewWorkflowSnapshot.Tasks,
575 > )
576 > if err != nil {
577 s.wUnlock()
578 return nil, err
579 }
580 > s.updateCloseTaskIDs(request.NewWorkflowSnapshot.ExecutionInfo, request.NewWorkflowSnapshot.Tasks) context_impl.go
581 >
582 > currentRangeID := s.getRangeIDLocked()
583 > request.RangeID = currentRangeID
584 >
585 > s.wUnlock()
586 > resp, err := s.executionManager.CreateWorkflowExecution(ctx, request)
587 > requestCompletionFn(err)
588 >
589 > if err = s.handleWriteError(request.RangeID, err); err != nil {
590 return nil, err
591 }
592 > return resp, nil context_impl.go
593 }
594
596 ctx context.Context,
597 request *persistence.UpdateWorkflowExecutionRequest,
598 > ) (*persistence.UpdateWorkflowExecutionResponse, error) { context_impl.go
599 > // do not try to get namespace cache within shard lock
600 > namespaceID := namespace.ID(request.UpdateWorkflowMutation.ExecutionInfo.NamespaceId)
601 > namespaceEntry, err := s.GetNamespaceRegistry().GetNamespaceByID(namespaceID)
602 > if err != nil {
603 return nil, err
604 }
605
606 > if err := s.ioSemaphoreAcquire(ctx); err != nil { context_impl.go
607 return nil, err
608 }
609 > defer s.ioSemaphoreRelease() context_impl.go
610 >
611 > s.wLock()
612 >
613 > // timeout check should be done within the shard lock, in case of shard lock contention
614 > ctx, cancel, err := s.newDetachedContext(ctx)
615 > if err != nil {
616 s.wUnlock()
617 return nil, err
618 }
619 > defer cancel() context_impl.go
620 >
621 > if err := s.errorByState(); err != nil {
622 s.wUnlock()
623 return nil, err
624 }
625
626 > if err := s.errorByNamespaceStateLocked(namespaceEntry.Name(), request.UpdateWorkflowMutation.ExecutionInfo.WorkflowId); err != nil { context_impl.go
627 s.wUnlock()
628 return nil, err
629 }
630
631 > taskMaps := make([]map[tasks.Category][]tasks.Task, 0, 2) context_impl.go
632 > taskMaps = append(taskMaps, request.UpdateWorkflowMutation.Tasks)
633 > if request.NewWorkflowSnapshot != nil {
634 taskMaps = append(taskMaps, request.NewWorkflowSnapshot.Tasks)
635 }
636 > requestCompletionFn, err := s.taskKeyManager.setAndTrackTaskKeys(taskMaps...) context_impl.go
637 > if err != nil {
638 s.wUnlock()
639 return nil, err
640 }
641 > s.updateCloseTaskIDs(request.UpdateWorkflowMutation.ExecutionInfo, request.UpdateWorkflowMutation.Tasks) context_impl.go
642 > if request.NewWorkflowSnapshot != nil {
643 s.updateCloseTaskIDs(request.NewWorkflowSnapshot.ExecutionInfo, request.NewWorkflowSnapshot.Tasks)
644 }
645
646 > request.RangeID = s.getRangeIDLocked() context_impl.go
647 > s.wUnlock()
648 >
649 > resp, err := s.executionManager.UpdateWorkflowExecution(ctx, request)
650 > requestCompletionFn(err)
651 > if err = s.handleWriteError(request.RangeID, err); err != nil {
652 return nil, err
653 }
654 > return resp, nil context_impl.go
655 }
656
657 > func (s *ContextImpl) updateCloseTaskIDs(executionInfo *persistencespb.WorkflowExecutionInfo, tasksByCategory map[tasks.Category][]tasks.Task) { context_impl.go
658 > for _, t := range tasksByCategory[tasks.CategoryTransfer] {
659 > if t.GetType() == enumsspb.TASK_TYPE_TRANSFER_CLOSE_EXECUTION { context_impl.go
660 > executionInfo.CloseTransferTaskId = t.GetTaskID() context_impl.go
661 > break
662 }
663 }
664 > for _, t := range tasksByCategory[tasks.CategoryVisibility] { context_impl.go
665 > if t.GetType() == enumsspb.TASK_TYPE_VISIBILITY_CLOSE_EXECUTION || context_impl.go
666 > t.GetType() == enumsspb.TASK_TYPE_CHASM {
667 > executionInfo.CloseVisibilityTaskId = t.GetTaskID() context_impl.go
668 > break
669 }
670 }
807 ctx context.Context,
808 request *persistence.GetWorkflowExecutionRequest,
809 > ) (*persistence.GetWorkflowExecutionResponse, error) { context_impl.go
810 > if err := s.errorByState(); err != nil {
811 return nil, err
812 }
813
814 > resp, err := s.executionManager.GetWorkflowExecution(ctx, request) context_impl.go
815 > if err = s.handleReadError(err); err != nil {
816 // also return resp, for RebuildMutableState API
817 return resp, err
818 }
819 > return resp, nil context_impl.go
820 }
821
1100 }
1101
1102 > func (s *ContextImpl) GetConfig() *configs.Config { context_impl.go
1103 > // constant from initialization, no need for locks
1104 > return s.config
1105 > }
1106
1107 > func (s *ContextImpl) GetEventsCache() events.Cache { context_impl.go
1108 > // constant from initialization (except for tests), no need for locks
1109 > return s.eventsCache
1110 > }
1111
1112 > func (s *ContextImpl) GetLogger() log.Logger { context_impl.go
1113 > // constant from initialization, no need for locks
1114 > return s.contextTaggedLogger
1115 > }
1116
1117 > func (s *ContextImpl) GetThrottledLogger() log.Logger { context_impl.go
1118 > // constant from initialization, no need for locks
1119 > return s.throttledLogger
1120 > }
1121
1122 > func (s *ContextImpl) getRangeIDLocked() int64 { context_impl.go
1123 > return s.shardInfo.GetRangeId()
1124 > }
1125
1126 > func (s *ContextImpl) errorByState() error { context_impl.go
1127 > s.stateLock.Lock()
1128 > defer s.stateLock.Unlock()
1129 >
1130 > switch s.state {
1131 > case contextStateInitialized, contextStateAcquiring: context_impl.go
1132 > return ErrShardStatusUnknown
1133 > case contextStateAcquired: context_impl.go
1134 > return nil
1135 case contextStateStopping, contextStateStopped:
1136 return s.newShardClosedErrorWithShardID()
1143 namespaceName namespace.Name,
1144 workflowID string,
1145 > ) error { context_impl.go
1146 > if s.handoverTracker.IsInHandover(namespaceName, workflowID) {
1147 return consts.ErrNamespaceHandover
1148 }
1149 > return nil context_impl.go
1150 }
1151
1152 > func (s *ContextImpl) generateTaskIDLocked() (int64, error) { context_impl.go
1153 > taskKey, err := s.taskKeyManager.generateTaskKey(tasks.CategoryTransfer)
1154 > if err != nil {
1155 return -1, err
1156 }
1157 > return taskKey.TaskID, nil context_impl.go
1158 }
1159
1160 > func (s *ContextImpl) renewRangeLocked(isStealing bool) error { context_impl.go
1161 > // We must drain all in-flight requests before updating the rangeID.
1162 > // This is because requests are conditioned on rangeID, if rangeID
1163 > // is updated before draining them, those requests could fail.
1164 > // This also means renew rangeID will be the only in-flight request
1165 > // when it's issued, so it doesn't matter if semaphore is acquired or not
1166 > // before calling this method.
1167 > s.taskKeyManager.drainTaskRequests()
1168 >
1169 > updatedShardInfo := trimShardInfo(s.config, s.clusterMetadata.GetAllClusterInfo(), s.copyShardInfo(s.shardInfo))
1170 > updatedShardInfo.RangeId++
1171 > if isStealing {
1172 > updatedShardInfo.StolenSinceRenew++
1173 > }
1174
1175 > ctx, cancel := s.newIOContext() context_impl.go
1176 > defer cancel()
1177 >
1178 > previousRangeID := s.getRangeIDLocked()
1179 > err := s.persistenceShardManager.UpdateShard(ctx, &persistence.UpdateShardRequest{
1180 > ShardInfo: updatedShardInfo,
1181 > PreviousRangeID: previousRangeID,
1182 > })
1183 > if err != nil {
1184 // Failure in updating shard to grab new RangeID
1185 s.contextTaggedLogger.Error("Persistent store operation failure",
1193
1194 // Range is successfully updated in cassandra now update shard context to reflect new range
1195 > s.contextTaggedLogger.Info("Range updated for shardID", context_impl.go
1196 > tag.ShardRangeID(updatedShardInfo.RangeId),
1197 > tag.PreviousShardRangeID(s.shardInfo.RangeId),
1198 > )
1199 >
1200 > s.shardInfo = trimShardInfo(s.config, s.clusterMetadata.GetAllClusterInfo(), s.copyShardInfo(updatedShardInfo))
1201 > s.taskKeyManager.setRangeID(s.shardInfo.RangeId)
1202 >
1203 > return nil
1204 }
1205
1206 > func (s *ContextImpl) monitorQueueMetrics() { context_impl.go
1207 > timer := time.NewTimer(queueMetricUpdateInterval)
1208 > defer timer.Stop()
1209 >
1210 > done := s.lifecycleCtx.Done()
1211 > for {
1212 > select {
1213 > case <-done: context_impl.go
1214 > return
1215 case <-timer.C:
1216 s.emitShardInfoMetricsLogs()
1350 }
1351
1352 > func (s *ContextImpl) GetCurrentTime(cluster string) time.Time { context_impl.go
1353 > if cluster != s.GetClusterMetadata().GetCurrentClusterName() {
1354 s.wLock()
1355 defer s.wUnlock()
1356 return s.getOrUpdateRemoteClusterInfoLocked(cluster).CurrentTime
1357 }
1358 > return s.timeSource.Now().UTC() context_impl.go
1359 }
1360
1361 > func (s *ContextImpl) getLastUpdatedTime() time.Time { context_impl.go
1362 > s.rLock()
1363 > defer s.rUnlock()
1364 > return s.lastUpdated
1365 > }
1366
1367 > func (s *ContextImpl) handleReadError(err error) error { context_impl.go
1368 > switch err.(type) {
1369 > case nil: context_impl.go
1370 > return nil
1371
1372 case *persistence.ShardOwnershipLostError:
1384 requestRangeID int64,
1385 err error,
1386 > ) error { context_impl.go
1387 > s.wLock()
1388 > defer s.wUnlock()
1389 >
1390 > return s.handleWriteErrorLocked(requestRangeID, err)
1391 > }
1392
1393 func (s *ContextImpl) handleWriteErrorLocked(
1394 requestRangeID int64,
1395 err error,
1396 > ) error { context_impl.go
1397 >
1398 > if requestRangeID != s.getRangeIDLocked() {
1399 return err
1400 }
1401
1402 > if valid := s.IsValid(); !valid { context_impl.go
1403 return err
1404 }
1405 > switch err.(type) { context_impl.go
1406 > case nil: context_impl.go
1407 > // Persistence success: update max read level
1408 > return nil
1409
1410 case *persistence.AppendHistoryTimeoutError:
1442 }
1443
1444 > func (s *ContextImpl) maybeRecordShardAcquisitionLatency(ownershipChanged bool) { context_impl.go
1445 > if ownershipChanged {
1446 > metrics.ShardContextAcquisitionLatency.With(s.GetMetricsHandler()).
1447 > Record(s.GetCurrentTime(s.GetClusterMetadata().GetCurrentClusterName()).Sub(s.getLastUpdatedTime()),
1448 > metrics.OperationTag(metrics.ShardInfoScope),
1449 > )
1450 > }
1451 }
1452
1453 > func (s *ContextImpl) createEngine() historyi.Engine { context_impl.go
1454 > s.contextTaggedLogger.Info("", tag.LifeCycleStarting, tag.ComponentShardEngine)
1455 > engine := s.engineFactory.CreateEngine(s)
1456 > engine.Start()
1457 > s.contextTaggedLogger.Info("", tag.LifeCycleStarted, tag.ComponentShardEngine)
1458 > return engine
1459 > }
1460
1461 // start should only be called by the controller.
1462 > func (s *ContextImpl) start() { context_impl.go
1463 > _ = s.transition(contextRequestAcquire{})
1464 > }
1465
1466 func (s *ContextImpl) UnloadForOwnershipLost() {
1469
1470 // FinishStop should only be called by the controller.
1471 > func (s *ContextImpl) FinishStop() { context_impl.go
1472 > // After this returns, engineFuture.Set may not be called anymore, so if we don't get see
1473 > // an Engine here, we won't ever have one.
1474 > _ = s.transition(contextRequestFinishStop{})
1475 >
1476 > // Use a context that we know is cancelled so that this doesn't block.
1477 > engine, _ := s.engineFuture.Get(s.lifecycleCtx)
1478 >
1479 > // Stop the engine if it was running (outside the lock but before returning).
1480 > if engine != nil {
1481 > s.contextTaggedLogger.Info("", tag.LifeCycleStopping, tag.ComponentShardEngine) context_impl.go
1482 > engine.Stop()
1483 > s.contextTaggedLogger.Info("", tag.LifeCycleStopped, tag.ComponentShardEngine)
1484 > }
1485
1486 // Run finalizer to cleanup any of the shard's associated resources that are registered.
1487 > if s.finalizer != nil { context_impl.go
1488 > s.finalizer.Run(s.config.ShardFinalizerTimeout()) context_impl.go
1489 > }
1490 }
1491
1492 > func (s *ContextImpl) IsValid() bool { context_impl.go
1493 > s.stateLock.Lock()
1494 > defer s.stateLock.Unlock()
1495 > return s.state < contextStateStopping
1496 > }
1497
1498 > func (s *ContextImpl) GetLifecycleContext() context.Context { context_impl.go
1499 > return s.lifecycleCtx
1500 > }
1501
1502 func (s *ContextImpl) stoppedForOwnershipLost() bool {
1506 }
1507
1508 > func (s *ContextImpl) wLock() { context_impl.go
1509 > handler := s.metricsHandler.WithTags(metrics.OperationTag(metrics.ShardInfoScope))
1510 > metrics.LockRequests.With(handler).Record(1)
1511 > startTime := time.Now().UTC()
1512 > defer func() { metrics.LockLatency.With(handler).Record(time.Since(startTime)) }()
1513
1514 > s.rwLock.Lock() context_impl.go
1515 }
1516
1517 > func (s *ContextImpl) rLock() { context_impl.go
1518 > handler := s.metricsHandler.WithTags(metrics.OperationTag(metrics.ShardInfoScope))
1519 > metrics.LockRequests.With(handler).Record(1)
1520 > startTime := time.Now().UTC()
1521 > defer func() { metrics.LockLatency.With(handler).Record(time.Since(startTime)) }()
1522
1523 > s.rwLock.RLock() context_impl.go
1524 }
1525
1526 > func (s *ContextImpl) wUnlock() { context_impl.go
1527 > s.rwLock.Unlock()
1528 > }
1529
1530 > func (s *ContextImpl) rUnlock() { context_impl.go
1531 > s.rwLock.RUnlock()
1532 > }
1533
1534 func (s *ContextImpl) ioSemaphoreAcquire(
1535 ctx context.Context,
1536 > ) (retErr error) { context_impl.go
1537 > priority := locks.PriorityHigh
1538 > callerInfo := headers.GetCallerInfo(ctx)
1539 > if callerInfo.CallerType == headers.CallerTypePreemptable {
1540 priority = locks.PriorityLow
1541 }
1542
1543 > handler := s.metricsHandler.WithTags(metrics.OperationTag(metrics.ShardInfoScope), metrics.PriorityTag(priority)) context_impl.go
1544 > metrics.SemaphoreRequests.With(handler).Record(1)
1545 > startTime := time.Now().UTC()
1546 > defer func() {
1547 > metrics.SemaphoreLatency.With(handler).Record(time.Since(startTime))
1548 > if retErr != nil {
1549 metrics.SemaphoreFailures.With(handler).Record(1)
1550 }
1551 }()
1552
1553 > return s.ioSemaphore.Acquire(ctx, priority, 1) context_impl.go
1554 }
1555
1556 > func (s *ContextImpl) ioSemaphoreRelease() { context_impl.go
1557 > s.ioSemaphore.Release(1)
1558 > }
1559
1560 > func (s *ContextImpl) transition(request contextRequest) error { context_impl.go
1561 > /* State transitions:
1562 >
1563 > The normal pattern:
1564 > Initialized
1565 > controller calls start()
1566 > Acquiring
1567 > acquireShard gets the shard
1568 > Acquired
1569 >
1570 > If we get a transient error from persistence:
1571 > Acquired
1572 > transient error: handleErrorLocked calls transition(contextRequestLost)
1573 > Acquiring
1574 > acquireShard gets the shard
1575 > Acquired
1576 >
1577 > If we get shard ownership lost:
1578 > Acquired
1579 > ShardOwnershipLostError: handleErrorLocked calls transition(contextRequestStop)
1580 > Stopping
1581 > controller removes from map and calls FinishStop()
1582 > Stopped
1583 >
1584 > Stopping can be triggered internally (if we get a ShardOwnershipLostError, or fail to acquire the rangeid
1585 > lock after several minutes) or externally (from controller, e.g. controller shutting down or admin force-
1586 > unload shard). If it's triggered internally, we transition to Stopping, then make an asynchronous callback
1587 > to controller, which will remove us from the map and call FinishStop(), which will transition to Stopped and
1588 > stop the engine. If it's triggered externally, we'll skip over Stopping and go straight to Stopped.
1589 >
1590 > If we transition externally to Stopped, and the acquireShard goroutine is still running, we can't kill it,
1591 > but we should make sure that it can't do anything: the context it uses for persistence ops will be
1592 > canceled, and if it tries to transition states, it will fail.
1593 >
1594 > Invariants:
1595 > - Once state is Stopping, it can only go to Stopped.
1596 > - Once state is Stopped, it can't go anywhere else.
1597 > - At the start of acquireShard, state must be Acquiring.
1598 > - By the end of acquireShard, state must not be Acquiring: either acquireShard set it to Acquired, or the
1599 > controller set it to Stopped.
1600 > - If state is Acquiring, acquireShard should be running in the background.
1601 > - Only acquireShard can use contextRequestAcquired (i.e. transition from Acquiring to Acquired).
1602 > - Once state has reached Acquired at least once, and not reached Stopped, engineFuture must be set.
1603 > - Only the controller may call start() and FinishStop().
1604 > - The controller must call FinishStop() for every ContextImpl it creates.
1605 >
1606 > */
1607 >
1608 > s.stateLock.Lock()
1609 > defer s.stateLock.Unlock()
1610 >
1611 > setStateAcquiring := func() {
1612 > s.state = contextStateAcquiring context_impl.go
1613 > s.contextTaggedLogger.Info("", tag.LifeCycleStarted, tag.ComponentShardContext)
1614 > go s.acquireShard()
1615 > }
1616
1617 > setStateStopping := func(request contextRequestStop) { context_impl.go
1618 s.state = contextStateStopping
1619 s.stopReason = request.reason
1627 }
1628
1629 > setStateStopped := func() { context_impl.go
1630 > s.state = contextStateStopped context_impl.go
1631 > s.contextTaggedLogger.Info("", tag.LifeCycleStopped, tag.ComponentShardContext)
1632 > // Do this again in case we skipped the stopping state, which could happen
1633 > // when calling CloseShardByID or the controller is shutting down.
1634 > s.lifecycleCancel()
1635 > }
1636
1637 > switch s.state { context_impl.go
1638 > case contextStateInitialized: context_impl.go
1639 > switch request := request.(type) {
1640 > case contextRequestAcquire:
1641 > setStateAcquiring()
1642 > return nil
1643 case contextRequestStop:
1644 setStateStopping(request)
1648 return nil
1649 }
1650 > case contextStateAcquiring: context_impl.go
1651 > switch request := request.(type) {
1652 case contextRequestAcquire:
1653 return nil // nothing to do, already acquiring
1654 > case contextRequestAcquired: context_impl.go
1655 > s.state = contextStateAcquired
1656 > if request.engine != nil {
1657 > // engineFuture.Set should only be called inside stateLock when state is context_impl.go
1658 > // Acquiring, so that other code (i.e. FinishStop) can know that after a state
1659 > // transition to Stopping/Stopped, engineFuture cannot be Set.
1660 > if s.engineFuture.Ready() {
1661 // defensive check, this should never happen
1662 s.contextTaggedLogger.Warn("transition to acquired with engine set twice")
1663 return errInvalidTransition
1664 }
1665 > s.engineFuture.Set(request.engine, nil) context_impl.go
1666 }
1667 > if !s.engineFuture.Ready() { context_impl.go
1668 // we should either have an engine from a previous transition, or set one now
1669 s.contextTaggedLogger.Warn("transition to acquired but no engine set")
1671 }
1672
1673 > return nil context_impl.go
1674 case contextRequestLost:
1675 return nil // nothing to do, already acquiring
1681 return nil
1682 }
1683 > case contextStateAcquired: context_impl.go
1684 > switch request := request.(type) {
1685 case contextRequestAcquire:
1686 return nil // nothing to do, already acquired
1691 setStateStopping(request)
1692 return nil
1693 > case contextRequestFinishStop: context_impl.go
1694 > setStateStopped()
1695 > return nil
1696 }
1697 case contextStateStopping:
1720 // notifyQueueProcessor sends notification to all queue processors for triggering a load
1721 // NOTE: this method assumes engineFuture is already in a ready state.
1722 > func (s *ContextImpl) notifyQueueProcessor() { context_impl.go
1723 > // use a cancelled ctx so the method won't be blocked if engineFuture is not ready
1724 > cancelledCtx, cancel := context.WithCancel(context.Background())
1725 > cancel()
1726 >
1727 > // we will get the engine when the Future is ready
1728 > engine, err := s.engineFuture.Get(cancelledCtx)
1729 > if err != nil {
1730 s.contextTaggedLogger.Warn("tried to notify queue processor when engine is not ready")
1731 return
1732 }
1733
1734 > now := s.timeSource.Now() context_impl.go
1735 > fakeTasks := make(map[tasks.Category][]tasks.Task)
1736 > for _, category := range s.taskCategoryRegistry.GetCategories() {
1737 > fakeTasks[category] = []tasks.Task{tasks.NewFakeTask(definition.WorkflowKey{}, category, now)}
1738 > }
1739
1740 > engine.NotifyNewTasks(fakeTasks) context_impl.go
1741 }
1742
1743 > func (s *ContextImpl) updateHandoverNamespacePendingTaskID() { context_impl.go
1744 > s.wLock()
1745 >
1746 > if s.errorByState() != nil {
1747 // if not in acquired state, this function will be called again
1748 // later when shard is re-acquired.
1751 }
1752
1753 > maxReplicationTaskID := s.getMaxReplicationTaskID() context_impl.go
1754 > s.handoverTracker.ResolvePendingTaskIDs(maxReplicationTaskID)
1755 > s.wUnlock()
1756 >
1757 > s.notifyReplicationQueueProcessor(maxReplicationTaskID)
1758 }
1759
1760 > func (s *ContextImpl) getMaxReplicationTaskID() int64 { context_impl.go
1761 > return s.taskKeyManager.getExclusiveReaderHighWatermark(tasks.CategoryReplication).TaskID - 1
1762 > }
1763
1764 > func (s *ContextImpl) notifyReplicationQueueProcessor(taskID int64) { context_impl.go
1765 > // Replication ack level won't exceed the max taskID it received via task notification.
1766 > // Since here we want it's ack level to advance to at least the input taskID, we need to
1767 > // trigger an fake notification.
1768 >
1769 > cancelledCtx, cancel := context.WithCancel(context.Background())
1770 > cancel()
1771 >
1772 > engine, err := s.engineFuture.Get(cancelledCtx)
1773 > if err != nil {
1774 s.contextTaggedLogger.Warn("tried to notify replication queue processor when engine is not ready")
1775 return
1776 }
1777
1778 > fakeReplicationTask := tasks.NewFakeTask(definition.WorkflowKey{}, tasks.CategoryReplication, tasks.MinimumKey.FireTime) context_impl.go
1779 > fakeReplicationTask.SetTaskID(taskID)
1780 >
1781 > engine.NotifyNewTasks(map[tasks.Category][]tasks.Task{
1782 > tasks.CategoryReplication: {fakeReplicationTask},
1783 > })
1784 }
1785
1786 > func (s *ContextImpl) loadShardMetadata(ownershipChanged *bool) error { context_impl.go
1787 > // Only have to do this once, we can just re-acquire the rangeid lock after that
1788 > s.rLock()
1789 > if s.shardInfo != nil {
1790 s.rUnlock()
1791 return nil
1792 }
1793 > s.rUnlock() context_impl.go
1794 >
1795 > // We don't have any shardInfo yet, load it (outside of context rwlock)
1796 > ctx, cancel := s.newIOContext()
1797 > defer cancel()
1798 > resp, err := s.persistenceShardManager.GetOrCreateShard(ctx, &persistence.GetOrCreateShardRequest{
1799 > ShardID: s.shardID,
1800 > LifecycleContext: s.lifecycleCtx,
1801 > })
1802 > if err != nil {
1803 s.contextTaggedLogger.Error("Failed to load shard", tag.Error(err))
1804 return err
1805 }
1806 > *ownershipChanged = resp.ShardInfo.Owner != s.owner context_impl.go
1807 > shardInfo := trimShardInfo(s.config, s.clusterMetadata.GetAllClusterInfo(), s.copyShardInfo(resp.ShardInfo))
1808 > shardInfo.Owner = s.owner
1809 >
1810 > // initialize the cluster current time to be the same as ack level
1811 > remoteClusterInfos := make(map[string]*remoteClusterInfo)
1812 > var taskMinScheduledTime time.Time
1813 > currentClusterName := s.GetClusterMetadata().GetCurrentClusterName()
1814 > taskCategories := s.taskCategoryRegistry.GetCategories()
1815 > for clusterName, info := range s.GetClusterMetadata().GetAllClusterInfo() {
1816 > if !info.Enabled {
1817 continue
1818 }
1819
1820 > exclusiveMaxReadTime := tasks.DefaultFireTime context_impl.go
1821 > for categoryID, queueState := range shardInfo.QueueStates {
1822 category, ok := taskCategories[int(categoryID)]
1823 if !ok || category.Type() != tasks.CategoryTypeScheduled {
1833 // Once we validate the rest of the code can worker correctly with higher precision, the code should simply be
1834 // taskMinScheduledTime = util.MaxTime(taskMinScheduledTime, maxReadTime)
1835 > taskMinScheduledTime = util.MaxTime( context_impl.go
1836 > taskMinScheduledTime,
1837 > exclusiveMaxReadTime.Add(common.ScheduledTaskMinPrecision).Truncate(common.ScheduledTaskMinPrecision),
1838 > )
1839 >
1840 > if clusterName != currentClusterName {
1841 remoteClusterInfos[clusterName] = &remoteClusterInfo{
1842 CurrentTime: exclusiveMaxReadTime,
1847 }
1848
1849 > s.wLock() context_impl.go
1850 > defer s.wUnlock()
1851 >
1852 > s.shardInfo = shardInfo
1853 > s.remoteClusterInfos = remoteClusterInfos
1854 > s.taskKeyManager.setTaskMinScheduledTime(taskMinScheduledTime)
1855 >
1856 > return nil
1857 }
1858
1920 }
1921
1922 > func (s *ContextImpl) acquireShard() { context_impl.go
1923 > // This is called in two contexts: initially acquiring the rangeid lock, and trying to
1924 > // re-acquire it after a persistence error. In both cases, we retry the acquire operation
1925 > // (renewRangeLocked) for 5 minutes. Each individual attempt uses shardIOTimeout (by default, 5s) as
1926 > // the timeout. This lets us handle a few minutes of persistence unavailability without
1927 > // dropping and reloading the whole shard context, which is relatively expensive (includes
1928 > // caches that would have to be refilled, etc.).
1929 > //
1930 > // We stop retrying on any of:
1931 > // 1. We succeed in acquiring the rangeid lock.
1932 > // 2. We get ShardOwnershipLostError or lifecycleCtx ended.
1933 > // 3. The state changes to Stopping or Stopped.
1934 > //
1935 > // If the shard controller sees that service resolver has assigned ownership to someone
1936 > // else, it will call FinishStop, which will trigger case 3 above, and also cancel
1937 > // lifecycleCtx. The persistence operations called here use lifecycleCtx as their context,
1938 > // so if we were blocked in any of them, they should return immediately with a context
1939 > // canceled error.
1940 > policy := s.acquireShardRetryPolicy
1941 > if policy == nil {
1942 > policy = backoff.NewExponentialRetryPolicy(1 * time.Second).WithExpirationInterval(5 * time.Minute) context_impl.go
1943 > }
1944
1945 // Remember this value across attempts
1946 > ownershipChanged := false context_impl.go
1947 >
1948 > op := func() error {
1949 > if !s.IsValid() {
1950 return s.newShardClosedErrorWithShardID()
1951 }
1952
1953 // Initial load of shard metadata
1954 > err := s.loadShardMetadata(&ownershipChanged) context_impl.go
1955 > if err != nil {
1956 return err
1957 }
1967 // in-flight requests before making the call. So it's guaranteed that the renew rangeID
1968 // UpdateShard call is the only one in flight.
1969 > s.wLock() context_impl.go
1970 > err = s.renewRangeLocked(true)
1971 > s.wUnlock()
1972 > if err != nil {
1973 return err
1974 }
1975
1976 > s.contextTaggedLogger.Info("Acquired shard") context_impl.go
1977 >
1978 > // The first time we get the shard, we have to create the engine
1979 > var engine historyi.Engine
1980 > if !s.engineFuture.Ready() {
1981 > s.maybeRecordShardAcquisitionLatency(ownershipChanged) context_impl.go
1982 > engine = s.createEngine()
1983 > }
1984
1985 // NOTE: engine is created & started before setting shard state to acquired.
1987 // -> information for handover namespace is recorded before shard can servce traffic
1988 // -> upon shard reload, no history api or task can go through for ns in handover state
1989 > err = s.transition(contextRequestAcquired{engine: engine}) context_impl.go
1990 >
1991 > if err != nil {
1992 if engine != nil {
1993 // We tried to set the engine but the context was already stopped
1999 // we know engineFuture must be ready here, and we can notify queue processor
2000 // to trigger a load as queue max level can be updated to a newer value
2001 > s.notifyQueueProcessor() context_impl.go
2002 > // This runs until the lifecycleCtx is cancelled, so we only need to start it once
2003 > s.queueMetricEmitter.Do(func() {
2004 > go s.monitorQueueMetrics()
2005 > })
2006
2007 > s.updateHandoverNamespacePendingTaskID() context_impl.go
2008 >
2009 > return nil
2010 }
2011
2012 // keep retrying except ShardOwnershipLostError or lifecycle context ended
2013 > acquireShardRetryable := func(err error) (isRetryable bool) { context_impl.go
2014 defer func() {
2015 s.contextTaggedLogger.Error(
2028 return true
2029 }
2030 > err := backoff.ThrottleRetry(op, policy, acquireShardRetryable) context_impl.go
2031 > if err != nil {
2032 // We got an non-retryable error, e.g. ShardOwnershipLostError
2033 s.contextTaggedLogger.Error("Couldn't acquire shard", tag.Error(err))
2072 endpointRegistry chasm.EndpointRegistry,
2073 handoverTrackerFactory HandoverTrackerFactory,
2074 > ) (*ContextImpl, error) { context_impl.go
2075 > hostIdentity := hostInfoProvider.HostInfo().Identity()
2076 > sequenceID := atomic.AddInt64(&shardContextSequenceID, 1)
2077 >
2078 > lifecycleCtx, lifecycleCancel := context.WithCancel(context.Background())
2079 >
2080 > ioConcurrency := historyConfig.ShardIOConcurrency()
2081 > if ioConcurrency != 1 && persistenceConfig.DataStores[persistenceConfig.DefaultStore].Cassandra != nil {
2082 throttledLogger.Warn(
2083 fmt.Sprintf("Cassandra persistence implementation only supports %v == 1", dynamicconfig.ShardIOConcurrency),
2087 }
2088
2089 > taggedLogger := log.With(logger, tag.ShardID(shardID), tag.Address(hostIdentity)) context_impl.go
2090 > shardContext := &ContextImpl{
2091 > state: contextStateInitialized,
2092 > shardID: shardID,
2093 > owner: fmt.Sprintf("%s-%v-%v", hostIdentity, sequenceID, uuid.NewString()),
2094 > stringRepr: fmt.Sprintf("Shard(%d)", shardID),
2095 > executionManager: persistenceExecutionManager,
2096 > metricsHandler: metricsHandler,
2097 > eventLogger: eventLogger,
2098 > closeCallback: closeCallback,
2099 > config: historyConfig,
2100 > finalizer: finalizer.New(taggedLogger, metricsHandler),
2101 > contextTaggedLogger: taggedLogger,
2102 > throttledLogger: log.With(throttledLogger, tag.ShardID(shardID), tag.Address(hostIdentity)),
2103 > engineFactory: factory,
2104 > persistenceShardManager: persistenceShardManager,
2105 > clientBean: clientBean,
2106 > historyClient: historyClient,
2107 > payloadSerializer: payloadSerializer,
2108 > timeSource: timeSource,
2109 > namespaceRegistry: namespaceRegistry,
2110 > saProvider: saProvider,
2111 > saMapperProvider: saMapperProvider,
2112 > clusterMetadata: clusterMetadata,
2113 > archivalMetadata: archivalMetadata,
2114 > hostInfoProvider: hostInfoProvider,
2115 > taskCategoryRegistry: taskCategoryRegistry,
2116 > lifecycleCtx: lifecycleCtx,
2117 > lifecycleCancel: lifecycleCancel,
2118 > engineFuture: future.NewFuture[historyi.Engine](),
2119 > queueMetricEmitter: sync.Once{},
2120 > ioSemaphore: locks.NewPrioritySemaphore(ioConcurrency),
2121 > stateMachineRegistry: stateMachineRegistry,
2122 > chasmRegistry: chasmRegistry,
2123 > chasmWorkflowRegistry: chasmWorkflowRegistry,
2124 > endpointRegistry: endpointRegistry,
2125 > businessIDRateLimiters: cache.New(
2126 > historyConfig.BusinessIDReuseLimiterCacheSize(),
2127 > &cache.Options{TTL: historyConfig.BusinessIDReuseLimiterCacheTTL()},
2128 > ),
2129 > }
2130 > shardContext.taskKeyManager = newTaskKeyManager(
2131 > shardContext.taskCategoryRegistry,
2132 > timeSource,
2133 > historyConfig,
2134 > shardContext.GetLogger(),
2135 > func() error {
2136 return shardContext.renewRangeLocked(false)
2137 },
2138 )
2139 > shardContext.handoverTracker = handoverTrackerFactory(HandoverTrackerParams{ context_impl.go
2140 > ClusterMetadata: clusterMetadata,
2141 > GetMaxReplicationTaskID: shardContext.getMaxReplicationTaskID,
2142 > ErrorByStateFn: shardContext.errorByState,
2143 > NotifyReplicationFn: shardContext.notifyReplicationQueueProcessor,
2144 > NamespaceRegistry: namespaceRegistry,
2145 > Logger: taggedLogger,
2146 > })
2147 > if shardContext.GetConfig().EnableHostLevelEventsCache() {
2148 shardContext.eventsCache = eventsCache
2149 > } else { context_impl.go
2150 > shardContext.eventsCache = events.NewShardLevelEventsCache(
2151 > shardContext.executionManager,
2152 > shardContext.config,
2153 > shardContext.metricsHandler,
2154 > shardContext.contextTaggedLogger,
2155 > false,
2156 > )
2157 > }
2158 > shardContext.initLastUpdatesTime()
2159 > return shardContext, nil
2160 }
2161
2162 > func (s *ContextImpl) initLastUpdatesTime() { context_impl.go
2163 > // We need to set lastUpdate time to "now" - "wait between shard updates time" + "first update interval".
2164 > // This is done to make sure that first shard update` will happen around "first update interval" after "now".
2165 > // The idea is to allow queue to persist even in the case of (relativly) constantly
2166 > // moving shards between hosts.
2167 > // Note: it still may prevent queue from progressing if shard moving rate is too high
2168 > lastUpdated := s.timeSource.Now()
2169 > lastUpdated = lastUpdated.Add(-1 * s.config.ShardUpdateMinInterval())
2170 > lastUpdated = lastUpdated.Add(s.config.ShardFirstUpdateInterval())
2171 > s.lastUpdated = lastUpdated
2172 > }
2173
2174 // TODO: why do we need a deep copy here?
2175 > func (s *ContextImpl) copyShardInfo(shardInfo *persistencespb.ShardInfo) *persistencespb.ShardInfo { context_impl.go
2176 > // need to ser/de to make a deep copy of queue state
2177 > queueStates := make(map[int32]*persistencespb.QueueState, len(shardInfo.QueueStates))
2178 > for k, v := range shardInfo.QueueStates {
2179 blob, _ := s.payloadSerializer.QueueStateToBlob(v)
2180 queueState, _ := s.payloadSerializer.QueueStateFromBlob(blob)
2182 }
2183
2184 > return &persistencespb.ShardInfo{ context_impl.go
2185 > ShardId: shardInfo.ShardId,
2186 > Owner: shardInfo.Owner,
2187 > RangeId: shardInfo.RangeId,
2188 > StolenSinceRenew: shardInfo.StolenSinceRenew,
2189 > ReplicationDlqAckLevel: maps.Clone(shardInfo.ReplicationDlqAckLevel),
2190 > UpdateTime: shardInfo.UpdateTime,
2191 > QueueStates: queueStates,
2192 > }
2193 }
2194
2197 }
2198
2199 > func (s *ContextImpl) GetPayloadSerializer() serialization.Serializer { context_impl.go
2200 > return s.payloadSerializer
2201 > }
2202
2203 func (s *ContextImpl) GetHistoryClient() historyservice.HistoryServiceClient {
2212 }
2213
2214 > func (s *ContextImpl) GetMetricsHandler() metrics.Handler { context_impl.go
2215 > return s.metricsHandler
2216 > }
2217
2218 > func (s *ContextImpl) GetTimeSource() cclock.TimeSource { context_impl.go
2219 > return s.timeSource
2220 > }
2221
2222 > func (s *ContextImpl) GetNamespaceRegistry() namespace.Registry { context_impl.go
2223 > return s.namespaceRegistry
2224 > }
2225
2226 > func (s *ContextImpl) GetSearchAttributesProvider() searchattribute.Provider { context_impl.go
2227 > return s.saProvider
2228 > }
2229
2230 > func (s *ContextImpl) GetSearchAttributesMapperProvider() searchattribute.MapperProvider { context_impl.go
2231 > return s.saMapperProvider
2232 > }
2233
2234 > func (s *ContextImpl) GetClusterMetadata() cluster.Metadata { context_impl.go
2235 > return s.clusterMetadata
2236 > }
2237
2238 > func (s *ContextImpl) GetArchivalMetadata() archiver.ArchivalMetadata { context_impl.go
2239 > return s.archivalMetadata
2240 > }
2241
2242 > func (s *ContextImpl) StateMachineRegistry() *hsm.Registry { context_impl.go
2243 > return s.stateMachineRegistry
2244 > }
2245
2246 > func (s *ContextImpl) ChasmRegistry() *chasm.Registry { context_impl.go
2247 > return s.chasmRegistry
2248 > }
2249
2250 > func (s *ContextImpl) ChasmWorkflowRegistry() *chasmworkflow.Registry { context_impl.go
2251 > return s.chasmWorkflowRegistry
2252 > }
2253
2254 > func (s *ContextImpl) EndpointRegistry() chasm.EndpointRegistry { context_impl.go
2255 > return s.endpointRegistry
2256 > }
2257
2258 > func (s *ContextImpl) BusinessIDReuseRateLimiter(namespaceID namespace.ID, businessID string, archetypeID chasm.ArchetypeID) quotas.RateLimiter { context_impl.go
2259 > rps := s.config.BusinessIDReuseRate(namespaceID.String())
2260 > if rps <= 0 {
2261 > return nil context_impl.go
2262 > }
2263 burst := max(1, int(float64(rps)*s.config.BusinessIDReuseBurstRatio(namespaceID.String())))
2264 key := namespaceID.String() + "/" + businessID + "/" + strconv.Itoa(int(archetypeID))
2303 func (s *ContextImpl) newDetachedContext(
2304 ctx context.Context,
2305 > ) (context.Context, context.CancelFunc, error) { context_impl.go
2306 > if err := ctx.Err(); err != nil {
2307 return nil, nil, err
2308 }
2309
2310 > detachedContext := rpc.CopyContextValues(s.lifecycleCtx, ctx) context_impl.go
2311 >
2312 > var cancel context.CancelFunc
2313 > deadline, ok := ctx.Deadline()
2314 > if ok {
2315 > timeout := max(deadline.Sub(s.GetTimeSource().Now()), minContextTimeout) context_impl.go
2316 > detachedContext, cancel = context.WithTimeout(detachedContext, timeout)
2317 > } else { context_impl.go
2318 > cancel = func() {} context_impl.go
2319 }
2320
2321 > return detachedContext, cancel, nil context_impl.go
2322 }
2323
2324 > func (s *ContextImpl) newIOContext() (context.Context, context.CancelFunc) { context_impl.go
2325 > ctx, cancel := context.WithTimeout(s.lifecycleCtx, s.config.ShardIOTimeout())
2326 > ctx = headers.SetCallerInfo(ctx, headers.SystemBackgroundHighCallerInfo)
2327 >
2328 > return ctx, cancel
2329 > }
2330
2331 // newShardClosedErrorWithShardID when shard is closed and a req cannot be processed
2341 allClusterInfo map[string]cluster.ClusterInformation,
2342 shardInfo *persistencespb.ShardInfo,
2343 > ) *persistencespb.ShardInfo { context_impl.go
2344 > if shardInfo.QueueStates != nil && shardInfo.QueueStates[int32(tasks.CategoryIDReplication)] != nil {
2345 for readerID := range shardInfo.QueueStates[int32(tasks.CategoryIDReplication)].ReaderStates {
2346 clusterID, _ := ReplicationReaderIDToClusterShardID(readerID)
go.temporal.io/server/service/matching/task_queue_partition_manager.go 628 covered LOC · 167 ranges

Open complete file

135 metricsHandler metrics.Handler,
136 userDataManager userDataManager,
137 > ) (*taskQueuePartitionManagerImpl, error) { task_queue_partition_manager.go
138 > rateLimitManager := newRateLimitManager(
139 > userDataManager,
140 > tqConfig,
141 > partition.TaskQueue().TaskType())
142 >
143 > var taskHooks []hooks.TaskHook
144 > for _, hookFactory := range e.taskHookFactories {
145 > taskHook := hookFactory.Create(&hooks.TaskHookFactoryCreateDetails{ task_queue_partition_manager.go
146 > Namespace: ns,
147 > Partition: partition,
148 > })
149 > if taskHook != nil {
150 taskHooks = append(taskHooks, taskHook)
151 }
153
154 // create partition scaler + manager if root
155 > var scaleManager *scaleManager task_queue_partition_manager.go
156 > if partition.IsRoot() && e.partitionScalerFactory != nil {
157 > partitionScaler := e.partitionScalerFactory.New( task_queue_partition_manager.go
158 > ns.Name(),
159 > partition.TaskQueue().Name(),
160 > partition.TaskQueue().TaskType(),
161 > )
162 > if partitionScaler != nil {
163 > baseCtx := headers.SetCallerInfo(context.Background(), headers.NewBackgroundLowCallerInfo(ns.Name().String()))
164 > scaleManager = newScaleManager(
165 > baseCtx,
166 > partition,
167 > logger,
168 > metricsHandler,
169 > userDataManager,
170 > e.matchingRawClient,
171 > partitionScaler,
172 > e.timeSource,
173 > tqConfig.PartitionScaleManagerSettings,
174 > tqConfig.NumWritePartitions,
175 > tqConfig.BreakdownMetricsByTaskQueue,
176 > )
177 > }
178 }
179
180 > pm := &taskQueuePartitionManagerImpl{ task_queue_partition_manager.go
181 > engine: e,
182 > partition: partition,
183 > ns: ns,
184 > config: tqConfig,
185 > logger: logger,
186 > throttledLogger: throttledLogger,
187 > matchingClient: e.matchingRawClient,
188 > metricsHandler: metricsHandler,
189 > versionedQueues: make(map[PhysicalTaskQueueVersion]physicalTaskQueueManager),
190 > userDataManager: userDataManager,
191 > rateLimitManager: rateLimitManager,
192 > scaleManager: scaleManager,
193 > defaultQueueFuture: future.NewFuture[physicalTaskQueueManager](),
194 > autoEnableRateLimiter: quotas.NewRateLimiter(1.0/60, 1),
195 > taskHooks: taskHooks,
196 > }
197 > pm.initCtx, pm.initCancel = context.WithCancel(context.Background())
198 >
199 > if pm.partition.IsRoot() {
200 > pm.cache = cache.New(10000, &cache.Options{ task_queue_partition_manager.go
201 > TTL: max(1, tqConfig.TaskQueueInfoByBuildIdTTL())}, // ensure TTL is never zero (which would disable TTL)
202 > )
203 > }
204
205 > return pm, nil task_queue_partition_manager.go
206 }
207
208 // computeEffectiveConfig determines the effective NewMatcher and EnableFairness config values
209 // based on fairnessState, autoEnable, and the base dynamic config values.
210 > func (pm *taskQueuePartitionManagerImpl) computeEffectiveConfig(autoEnable, fairness, newMatcher bool) (effectiveNewMatcher, effectiveEnableFairness bool) { task_queue_partition_manager.go
211 > effectiveEnableFairness = fairness && pm.partition.SupportsFairness()
212 > effectiveNewMatcher = newMatcher || fairness
213 > if !autoEnable {
215 > }
216
217 switch pm.fairnessState {
233 }
234
235 > func (pm *taskQueuePartitionManagerImpl) initialize() (retErr error) { task_queue_partition_manager.go
236 > defer pm.initCancel()
237 > defer func() { pm.defaultQueueFuture.SetIfNotReady(nil, retErr) }()
238
239 > err := pm.userDataManager.WaitUntilInitialized(pm.initCtx) task_queue_partition_manager.go
240 > if err != nil {
242 > }
243 > data, _, err := pm.getPerTypeUserData() task_queue_partition_manager.go
244 > if err != nil {
245 return err
246 }
247
248 > pm.fairnessState = data.GetFairnessState() task_queue_partition_manager.go
249 > changeKey := pm.partition.GradualChangeKey()
250 >
251 > var autoEnable, fairness, newMatcher bool
252 > autoEnable, pm.cancelAutoEnableSub = pm.config.AutoEnableV2Sub(pm.autoEnableChanged)
253 >
254 > unloadOnBaseConfigChange := func(bool) {
255 if pm.fairnessState == enumsspb.FAIRNESS_STATE_UNSPECIFIED || !pm.config.AutoEnableV2() {
256 pm.unloadFromEngine(unloadCauseConfigChange)
258 }
259
260 > newMatcher, pm.cancelNewMatcherSub = dynamicconfig.SubscribeGradualChange( task_queue_partition_manager.go
261 > pm.config.NewMatcherSub, changeKey, unloadOnBaseConfigChange, pm.engine.timeSource)
262 > fairness, pm.cancelFairnessSub = dynamicconfig.SubscribeGradualChange(
263 > pm.config.EnableFairnessSub, changeKey, unloadOnBaseConfigChange, pm.engine.timeSource)
264 >
265 > // Determine initial config values
266 > pm.config.NewMatcher, pm.config.EnableFairness = pm.computeEffectiveConfig(autoEnable, fairness, newMatcher)
267 >
268 > defaultQ, err := newPhysicalTaskQueueManager(pm, UnversionedQueueKey(pm.partition))
269 > if err != nil {
270 return err
271 }
272 > pm.defaultQueueFuture.Set(defaultQ, nil) task_queue_partition_manager.go
273 > defaultQ.Start()
274 > pm.goroGroup.Go(pm.updateEphemeralData)
275 > pm.goroGroup.Go(pm.emitLogicalBacklogMetrics)
276 >
277 > // Whenever a root partition is loaded, we need to force all child partitions to load.
278 > // If there is a backlog of tasks on any child partitions, force loading will ensure
279 > // that they can forward their tasks the poller which caused the root partition to be
280 > // loaded. We're in a separate goroutine in initialize() so we can do it here.
281 > if defaultQ.WaitUntilInitialized(pm.initCtx) == nil {
282 > pm.ForceLoadAllChildPartitions()
283 > }
284
286 }
287
288 > func (pm *taskQueuePartitionManagerImpl) defaultQueue() physicalTaskQueueManager { task_queue_partition_manager.go
289 > queue, err := pm.defaultQueueFuture.GetIfReady()
290 > if err != nil {
291 softassert.Fail(pm.logger, "defaultQueue used but not initialized or initialization failed", tag.Error(err))
292 }
293 > return queue task_queue_partition_manager.go
294 }
295
296 > func (pm *taskQueuePartitionManagerImpl) Start() { task_queue_partition_manager.go
297 > pm.loadTime = time.Now()
298 > pm.engine.updateTaskQueuePartitionGauge(pm.Namespace(), pm.partition, 1)
299 > pm.rateLimitManager.Start()
300 > pm.userDataManager.Start()
301 > for _, hook := range pm.taskHooks {
302 hook.Start()
303 }
304
305 //nolint:errcheck
306 > go pm.initialize() task_queue_partition_manager.go
307 }
308
309 // Stop does not unload the partition from matching engine. It is intended to be called by matching engine when
310 // unloading the partition. For stopping and unloading a partition call unloadFromEngine instead.
311 > func (pm *taskQueuePartitionManagerImpl) Stop(unloadCause unloadCause) { task_queue_partition_manager.go
312 > pm.initCancel()
313 > queue, err := pm.defaultQueueFuture.Get(context.Background())
314 > if err == nil {
315 > queue.Stop(unloadCause)
316 > pm.emitZeroLogicalBacklogForQueue(queue.QueueKey().Version(), queue)
317 > }
318
319 > if pm.cancelFairnessSub != nil { task_queue_partition_manager.go
320 > pm.cancelFairnessSub() task_queue_partition_manager.go
321 > }
322 > if pm.cancelNewMatcherSub != nil { task_queue_partition_manager.go
323 > pm.cancelNewMatcherSub() task_queue_partition_manager.go
324 > }
325 > if pm.cancelAutoEnableSub != nil { task_queue_partition_manager.go
326 > pm.cancelAutoEnableSub() task_queue_partition_manager.go
327 > }
328 > pm.scaleManager.Stop() task_queue_partition_manager.go
329 >
330 > pm.versionedQueuesLock.Lock()
331 > for version, vq := range pm.versionedQueues {
332 vq.Stop(unloadCause)
333 pm.emitZeroLogicalBacklogForQueue(version, vq)
334 }
335 > pm.versionedQueuesLock.Unlock() task_queue_partition_manager.go
336 >
337 > for _, hook := range pm.taskHooks {
338 hook.Stop()
339 }
340
341 // Then, stop user data manager to wrap up any reads/writes.
342 > pm.userDataManager.Stop() task_queue_partition_manager.go
343 >
344 > // Finally, stop rate limit manager (used by queues and using user data manager).
345 > pm.rateLimitManager.Stop()
346 >
347 > pm.engine.updateTaskQueuePartitionGauge(pm.Namespace(), pm.partition, -1)
348 >
349 > pm.goroGroup.Cancel()
350 }
351
352 > func (pm *taskQueuePartitionManagerImpl) StartScaleManager(scaleState *persistencespb.PartitionScaleState) { task_queue_partition_manager.go
353 > // Note that this must be called before defaultQueue is marked initialized!
354 > // Otherwise child partitions will see empty scale info in their first ephemeral data update.
355 > pm.scaleManager.Start(scaleState, pm.defaultQueue())
356 > }
357
358 > func (pm *taskQueuePartitionManagerImpl) checkPartitionCounts(ctx context.Context, forWrite bool) error { task_queue_partition_manager.go
359 > normal, ok := pm.partition.(*tqid.NormalPartition)
360 > if !ok {
361 > return nil // only normal partitions do dynamic scaling task_queue_partition_manager.go
362 > }
363 > id := normal.PartitionId() task_queue_partition_manager.go
364 >
365 > // userDataManager must be initialized here already so we can just ask it for scale info
366 > scaleInfo := pm.userDataManager.PartitionScale()
367 >
368 > if scaleInfo.GetRead() <= 0 || scaleInfo.GetWrite() <= 0 || scaleInfo.Write > scaleInfo.Read {
369 > return nil // missing or invalid scale info
370 > }
371
372 // always validate partition id based on read/write counts and scale info
437 // signalPartitionScaler sends a signal to the partition scaler that a new task has arrived
438 // (directly from history, not forwarded).
439 > func (pm *taskQueuePartitionManagerImpl) signalPartitionScaler() { task_queue_partition_manager.go
440 > if pm.scaleManager == nil {
441 return // only run on root partition
442 }
443 > scaleInfo := pm.userDataManager.PartitionScale() task_queue_partition_manager.go
444 > effectiveWrite := int(scaleInfo.GetWrite())
445 > // if no target is set yet, get effective count from dynamic config (matches client behavior)
446 > if effectiveWrite == 0 {
447 > effectiveWrite = max(1, pm.config.NumWritePartitions())
448 > }
449 // we assume that tasks are balanced uniformly across partitions, so if the root has
450 // seen 1 task then all have seen ~1 task, so the whole queue has seen 'effective'
452 // TODO(dp): this will change when we add non-uniform load balancing. we should eventually
453 // aggregate real stats instead of assuming
454 > pm.scaleManager.AddedTasks(effectiveWrite) task_queue_partition_manager.go
455 }
456
457 > func (pm *taskQueuePartitionManagerImpl) sendPartitionCountTrailer(ctx context.Context) { task_queue_partition_manager.go
458 > // note this sends the trailer even if there is no scale info (i.e. dynamic partition
459 > // scaling is not enabled). that will instruct clients to fall back to dynamic config.
460 > scaleInfo := pm.userDataManager.PartitionScale()
461 > err := matching.PartitionCounts{
462 > Read: scaleInfo.GetRead(),
463 > Write: scaleInfo.GetWrite(),
464 > BacklogCap: number.Compact8(scaleInfo.GetBacklogCap()),
465 > BacklogCount: []byte(scaleInfo.GetBacklogCounts()),
466 > }.SetTrailer(ctx)
467 > if err != nil {
468 > // TODO(dp): this is very noisy in unit tests, figure out how to log it only in non-test task_queue_partition_manager.go
469 > pm.throttledLogger.Debug("error setting partition count trailer", tag.Error(err))
470 > }
471 }
472
475 }
476
477 > func (pm *taskQueuePartitionManagerImpl) Namespace() *namespace.Namespace { task_queue_partition_manager.go
478 > return pm.ns
479 > }
480
481 > func (pm *taskQueuePartitionManagerImpl) MarkAlive() { task_queue_partition_manager.go
482 > dbq := pm.defaultQueue()
483 > if dbq != nil {
484 > dbq.MarkAlive()
485 > }
486 }
487
488 > func (pm *taskQueuePartitionManagerImpl) WaitUntilInitialized(ctx context.Context) error { task_queue_partition_manager.go
489 > queue, err := pm.defaultQueueFuture.Get(ctx)
490 > if err != nil {
492 > }
493 > return queue.WaitUntilInitialized(ctx) task_queue_partition_manager.go
494 }
495
524 }
525
526 > func (pm *taskQueuePartitionManagerImpl) autoEnableIfNeeded(ctx context.Context, params addTaskParams) { task_queue_partition_manager.go
527 > if pm.fairnessState != enumsspb.FAIRNESS_STATE_UNSPECIFIED {
528 return
529 }
530 > if params.taskInfo.Priority.GetFairnessKey() == "" { task_queue_partition_manager.go
531 > if params.taskInfo.Priority.GetPriorityKey() == int32(0) { task_queue_partition_manager.go
533 > }
534 // Do not auto enable if we only see priority and we're using new matcher already
535 if pm.config.NewMatcher {
558 ctx context.Context,
559 params addTaskParams,
560 > ) (buildId string, syncMatched bool, err error) { task_queue_partition_manager.go
561 > defer pm.sendPartitionCountTrailer(ctx)
562 > if err := pm.checkPartitionCounts(ctx, true); err != nil {
563 return "", false, err
564 }
565 > if params.forwardInfo == nil { task_queue_partition_manager.go
566 > pm.signalPartitionScaler() task_queue_partition_manager.go
567 > }
568
569 > var spoolQueue, syncMatchQueue physicalTaskQueueManager task_queue_partition_manager.go
570 > directive := params.taskInfo.GetVersionDirective()
571 >
572 > pm.autoEnableIfNeeded(ctx, params)
573 > // spoolQueue will be nil iff task is forwarded.
574 > reredirectTask:
575 > spoolQueue, syncMatchQueue, _, taskDispatchRevisionNumber, targetVersion, err := pm.getPhysicalQueuesForAdd(ctx, directive, params.forwardInfo, params.taskInfo.GetRunId(), params.taskInfo.GetWorkflowId(), false)
576 > if err != nil {
577 return "", false, err
578 }
579
580 > syncMatchTask := newInternalTaskForSyncMatch(params.taskInfo, params.forwardInfo, taskDispatchRevisionNumber, targetVersion) task_queue_partition_manager.go
581 > pm.config.setDefaultPriority(syncMatchTask)
582 > if spoolQueue != nil && spoolQueue.QueueKey().Version().BuildId() != syncMatchQueue.QueueKey().Version().BuildId() {
583 // Task is not forwarded and build ID is different on the two queues -> redirect rule is being applied.
584 // Set redirectInfo in the task as it will be needed if we have to forward the task.
588 }
589
590 > dbq := pm.defaultQueue() task_queue_partition_manager.go
591 > if dbq == nil {
592 return "", false, errDefaultQueueNotInit
593 }
594 > if dbq != syncMatchQueue { task_queue_partition_manager.go
595 // default queue should stay alive even if requests go to other queues
596 dbq.MarkAlive()
597 }
598
599 > if pm.partition.IsRoot() { task_queue_partition_manager.go
600 > // Only emit the no-recent-poller metric if BOTH conditions are met: task_queue_partition_manager.go
601 > // 1. Partition has been loaded for more than noPollerThreshold (2 minutes)
602 > // 2. No pollers have polled in the last noPollerThreshold (2 minutes)
603 > // This prevents false positives for newly loaded partitions that haven't had time to receive pollers yet.
604 > if time.Since(pm.loadTime) > noPollerThreshold && !pm.HasAnyPollerAfter(time.Now().Add(-noPollerThreshold)) {
605 pm.metricsHandler.Counter(metrics.NoRecentPollerTasksPerTaskQueueCounter.Name()).Record(1)
606 }
607 }
608
609 > isActive, err := pm.isActiveInCluster() task_queue_partition_manager.go
610 > if err != nil {
611 return "", false, err
612 }
613
614 > behavior := directive.GetBehavior() task_queue_partition_manager.go
615 > forwarded := params.forwardInfo != nil
616 >
617 > var outcome syncMatchOutcome
618 > if isActive {
619 > outcome, err = syncMatchQueue.TrySyncMatch(ctx, syncMatchTask)
620 > syncMatched = outcome == syncMatchSuccess
621 > if syncMatched && !pm.shouldBacklogSyncMatchTaskOnError(err) {
622 // Only fire hooks for non-forwarded tasks. Forwarded tasks already had hooks fired
623 // on the child partition that originally received the task.
639 // By omitting the build ID from this response we help History immediately know that no MS update is needed.
640 return "", syncMatched, err
641 > } else if errors.Is(err, errReprocessTask) { task_queue_partition_manager.go
642 // We get this if userdata changed while the task was blocked in TrySyncMatch
643 // (only for backlog tasks forwarded to root with the new matcher)
647 }
648
649 > if spoolQueue == nil { task_queue_partition_manager.go
650 // This means the task is being forwarded. Child partition will persist the task when sync match fails.
651 syncMatchQueue.RecordTaskAdd(metrics.TaskAddResultSyncMatchUnavail, forwarded, behavior)
653 }
654
655 > var assignedBuildId string task_queue_partition_manager.go
656 > if directive.GetUseAssignmentRules() != nil {
657 > // return build ID only if a new one is assigned. task_queue_partition_manager.go
658 > assignedBuildId = spoolQueue.QueueKey().Version().BuildId()
659 > }
660
661 > err = spoolQueue.SpoolTask(params.taskInfo) task_queue_partition_manager.go
662 > if err == nil {
663 > spoolQueue.RecordTaskAdd(metrics.TaskAddResultBacklog, forwarded, behavior)
664 > // We should not use targetVersion because targetVersion is always routing-config-deriven.
665 > // For pinned workflows, targetVersion is not necessarily the same as the pinned version.
666 > // Also, note that we use syncMatchQueue's version, and not spoolQueue's version. This is
667 > // because for unpinned tasks spoolQueue is always the default (unversioned) queue.
668 > // Unpinned tasks are written to the default queue for late binding, in case target version
669 > // changes by the time they can be dispatched.
670 > pm.processTaskAddHooks(ctx, syncMatchQueue.QueueKey().Version().WorkerDeploymentVersionS(), outcome)
671 > } else {
672 spoolQueue.RecordTaskAdd(taskAddErrResult(err), forwarded, behavior)
673 }
674
675 > return assignedBuildId, false, err task_queue_partition_manager.go
676 }
677
689 }
690
691 > func (pm *taskQueuePartitionManagerImpl) processTaskAddHooks(ctx context.Context, targetVersion *deploymentspb.WorkerDeploymentVersion, outcome syncMatchOutcome) { task_queue_partition_manager.go
692 > for _, l := range pm.taskHooks {
693 hookOutcome := syncMatchOutcomeToHook(outcome)
694 l.ProcessTaskAdd(ctx, &hooks.TaskAddHookDetails{
718 }
719
720 > func (pm *taskQueuePartitionManagerImpl) isActiveInCluster() (bool, error) { task_queue_partition_manager.go
721 > ns, err := pm.engine.namespaceRegistry.GetNamespaceByID(pm.ns.ID())
722 > if err == nil {
723 > //nolint:forbidigo // partition manager is namespace-scoped
724 > return ns.ActiveInCluster(pm.engine.clusterMeta.GetCurrentClusterName()), nil
725 > }
726 return false, err
727 }
731 ctx context.Context,
732 pollMetadata *pollMetadata,
733 > ) (*internalTask, bool, error) { task_queue_partition_manager.go
734 > defer pm.sendPartitionCountTrailer(ctx)
735 > if err := pm.checkPartitionCounts(ctx, false); err != nil {
736 return nil, false, err
737 }
738
739 > var err error task_queue_partition_manager.go
740 > dbq := pm.defaultQueue()
741 > if dbq == nil {
742 return nil, false, errDefaultQueueNotInit
743 }
744 > versionSetUsed := false task_queue_partition_manager.go
745 > deployment, err := worker_versioning.DeploymentFromCapabilities(pollMetadata.workerVersionCapabilities, pollMetadata.deploymentOptions)
746 > if err != nil {
747 return nil, false, err
748 }
749
750 > if deployment != nil { task_queue_partition_manager.go
751 if pm.partition.Kind() == enumspb.TASK_QUEUE_KIND_STICKY {
752 // TODO: reject poller of old sticky queue if newer version exist
760 }
761 }
762 > } else if pollMetadata.workerVersionCapabilities.GetUseVersioning() { task_queue_partition_manager.go
763 // V1 & V2 versioning
764 userData, _, err := pm.userDataManager.GetUserData()
825 }
826
827 > identity, hasIdentity := ctx.Value(identityKey).(string) task_queue_partition_manager.go
828 > if hasIdentity && identity != "" {
829 > dbq.UpdatePollerInfo(pollerIdentity(identity), pollMetadata) task_queue_partition_manager.go
830 > }
831
832 // The desired global rate limit for the task queue can come from multiple sources:
839 // UpdateRateLimit implicitly handles whether an update is required or not,
840 // based on whether the effectiveRPS has changed.
841 > pm.rateLimitManager.InjectWorkerRPS(pollMetadata) task_queue_partition_manager.go
842 >
843 > task, err := dbq.PollTask(ctx, pollMetadata)
844 > if task != nil {
845 > task.pollerScalingDecision = dbq.MakePollerScalingDecision(ctx, pollMetadata.localPollStartTime) task_queue_partition_manager.go
846 > }
847
848 // Update poller timestamp when poll ends, unless cancelled (e.g., shutdown/disconnect).
849 // Skip on cancellation to avoid re-adding entry after RemovePoller was called.
850 > if hasIdentity && identity != "" && ctx.Err() != context.Canceled { task_queue_partition_manager.go
851 > dbq.UpdatePollerInfo(pollerIdentity(identity), pollMetadata) task_queue_partition_manager.go
852 > }
853
854 > return task, versionSetUsed, err task_queue_partition_manager.go
855 }
856
860 ctx context.Context,
861 physicalQueue physicalTaskQueueManager,
862 > ) *taskqueuepb.TaskQueueStats { task_queue_partition_manager.go
863 > // buildID would be empty for either the unversioned queue or when using v3 worker-versioning.
864 > buildID := physicalQueue.QueueKey().Version().BuildId()
865 >
866 > // Check if the queue is versioned queue using v3 worker-versioning
867 > deployment := physicalQueue.QueueKey().Version().Deployment()
868 > if deployment != nil {
869 buildID = worker_versioning.ExternalWorkerDeploymentVersionToString(worker_versioning.ExternalWorkerDeploymentVersionFromDeployment(deployment))
870 }
871
872 > partitionInfo, err := pm.Describe(ctx, map[string]bool{buildID: true}, false, true, false, false) task_queue_partition_manager.go
873 > if err != nil {
874 return nil
875 }
876
877 > info, ok := partitionInfo.GetVersionsInfoInternal()[buildID] task_queue_partition_manager.go
878 > if !ok || info.GetPhysicalTaskQueueInfo().GetTaskQueueStats() == nil {
879 return nil
880 }
881 > return info.GetPhysicalTaskQueueInfo().GetTaskQueueStats() task_queue_partition_manager.go
882 }
883
950 task *internalTask,
951 backlogQueue *PhysicalTaskQueueKey,
953 > taskInfo := task.event.GetData()
954 > // This task came from taskReader so task.event is always set here.
955 > directive := taskInfo.GetVersionDirective()
956 > assignedBuildId := backlogQueue.Version().BuildId()
957 > if assignedBuildId != "" {
958 // construct directive based on the build ID of the spool queue
959 directive = worker_versioning.MakeBuildIdDirective(assignedBuildId)
960 }
961 > newBacklogQueue, syncMatchQueue, _, taskDispatchRevisionNumber, targetVersion, err := pm.getPhysicalQueuesForAdd( task_queue_partition_manager.go
962 > ctx,
963 > directive,
964 > nil,
965 > taskInfo.GetRunId(),
966 > taskInfo.GetWorkflowId(),
967 > false,
968 > )
969 > if err != nil {
970 return err
971 }
972
973 > task.targetWorkerDeploymentVersion = targetVersion task_queue_partition_manager.go
974 >
975 > // Update the task dispatch revision number on the task since the routingConfig of the partition
976 > // may have changed after the task was spooled.
977 > task.taskDispatchRevisionNumber = taskDispatchRevisionNumber
978 >
979 > // set redirect info if spoolQueue and syncMatchQueue build ids are different (V2 versioning)
980 > if assignedBuildId != syncMatchQueue.QueueKey().Version().BuildId() {
981 task.redirectInfo = &taskqueuespb.BuildIdRedirectInfo{
982 AssignedBuildId: assignedBuildId,
983 }
985 > // make sure to reset redirectInfo in case it was set in a previous loop cycle task_queue_partition_manager.go
986 > task.redirectInfo = nil
987 > }
988 // mark if task is being redirected from queue it was read from (V2 or V3 versioning)
989 > task.redirectedFromBacklog = syncMatchQueue.QueueKey() != backlogQueue task_queue_partition_manager.go
990 > if !backlogQueue.version.Deployment().Equal(newBacklogQueue.QueueKey().version.Deployment()) {
991 // Backlog queue has changed, spool to the new queue. This should happen rarely: when
992 // activity of pinned workflow was determined independent and sent to the default queue
1160 }
1161
1162 > func (pm *taskQueuePartitionManagerImpl) GetUserDataManager() userDataManager { task_queue_partition_manager.go
1163 > return pm.userDataManager
1164 > }
1165
1166 func (pm *taskQueuePartitionManagerImpl) GetConfig() *taskQueueConfig {
1285 buildIds map[string]bool,
1286 includeAllActive, reportStats, reportPollers, internalTaskQueueStatus bool,
1287 > ) (*matchingservice.DescribeTaskQueuePartitionResponse, error) { task_queue_partition_manager.go
1288 > return pm.describe(ctx, buildIds, includeAllActive, reportStats, reportPollers, internalTaskQueueStatus, false)
1289 > }
1290
1291 // Describe returns information about physical queues for the requested versions, including
1302 buildIds map[string]bool,
1303 includeAllActive, reportStats, reportPollers, internalTaskQueueStatus, skipMarkAlive bool,
1304 > ) (*matchingservice.DescribeTaskQueuePartitionResponse, error) { task_queue_partition_manager.go
1305 > pm.versionedQueuesLock.RLock()
1306 >
1307 > versions := make(map[PhysicalTaskQueueVersion]bool)
1308 >
1309 > // Active means that the physical queue for that version is loaded.
1310 > // An empty string refers to the unversioned queue, which is always loaded.
1311 > // In the future, active will mean that the physical queue for that version has had a task added recently or a recent poller.
1312 > if includeAllActive {
1313 for k := range pm.versionedQueues {
1314 versions[k] = true
1352 }
1353
1354 > pm.versionedQueuesLock.RUnlock() task_queue_partition_manager.go
1355 >
1356 > var unversionedStatsByPriority map[int32]*taskqueuepb.TaskQueueStats
1357 > var currentVersion *deploymentspb.WorkerDeploymentVersion
1358 > var rampingVersion *deploymentspb.WorkerDeploymentVersion
1359 > var rampPercentage float32
1360 > var currentExists bool
1361 > var rampingExists bool
1362 > var isRamping bool
1363 > var unversionedCurrentShareByPriority map[int32]*taskqueuepb.TaskQueueStats
1364 > var unversionedRampingShareByPriority map[int32]*taskqueuepb.TaskQueueStats
1365 >
1366 > if reportStats {
1367 > // Consider the default/unversioned queue. For current/ramping deployment versions, tasks are backlogged
1368 > // here, so we include this queue's stats if the version to describe is a current/ramping version.
1369 > dbq := pm.defaultQueue()
1370 > if dbq == nil {
1371 return nil, errDefaultQueueNotInit
1372 }
1373 > unversionedStatsByPriority = dbq.GetStatsByPriority(true) task_queue_partition_manager.go
1374 >
1375 > userData, _, err := pm.GetUserDataManager().GetUserData()
1376 > if err != nil {
1377 return nil, err
1378 }
1379 > perType := userData.GetData().GetPerType()[int32(pm.Partition().TaskType())] task_queue_partition_manager.go
1380 > deploymentData := perType.GetDeploymentData()
1381 >
1382 > currentVersion, _, _, rampingVersion, isRamping, rampPercentage, _, _ =
1383 > worker_versioning.CalculateTaskQueueVersioningInfo(deploymentData)
1384 >
1385 > // Technically, one could have a current version of "unversioned" which shall make currentExists false according
1386 > // to the current logic. However, as of now, the user cannot query the stats of the "unversioned" version so this
1387 > // logic is fine. In other words, this logic is used to only attribute the unversioned backlog to the current version
1388 > // when current version is NOT "unversioned".
1389 > //
1390 > // When the ramping version is "unversioned", isRamping is true which shall make the attribution logic work as expected.
1391 > currentExists = currentVersion != nil
1392 > rampingExists = isRamping && rampPercentage > 0
1393 >
1394 > // Split the unversioned queue's stats per priority so TaskQueueStatsByPriorityKey can
1395 > // be adjusted consistently with TaskQueueStats.
1396 > unversionedCurrentShareByPriority = map[int32]*taskqueuepb.TaskQueueStats{}
1397 > unversionedRampingShareByPriority = map[int32]*taskqueuepb.TaskQueueStats{}
1398 > if rampingExists {
1399 unversionedCurrentShareByPriority, unversionedRampingShareByPriority =
1400 splitStatsByPriorityByRampPercentage(unversionedStatsByPriority, rampPercentage)
1401 > } else if currentExists { task_queue_partition_manager.go
1402 // If there exist no ramping version, we attribute the entire unversioned backlog to the current version.
1403 unversionedCurrentShareByPriority = cloneStatsByPriority(unversionedStatsByPriority)
1405 }
1406
1407 > versionsInfo := make(map[string]*taskqueuespb.TaskQueueVersionInfoInternal, len(versions)) task_queue_partition_manager.go
1408 > for v := range versions {
1409 > vInfo := &taskqueuespb.TaskQueueVersionInfoInternal{
1410 > PhysicalTaskQueueInfo: &taskqueuespb.PhysicalTaskQueueInfo{},
1411 > }
1412 >
1413 > // `getPhysicalQueue` always needs the right buildID passed to function correctly. If the version is a worker-deployment version and an empty buildID is passed,
1414 > // the function returns the default queue which is not what we want.
1415 > // The following assigns buildID to either a v2 based buildID or a buildID part of a worker-deployment version.
1416 > buildID := v.BuildId()
1417 > if v.Deployment() != nil {
1418 buildID = v.Deployment().BuildId
1419 }
1420
1421 > physicalQueue, err := pm.getPhysicalQueue(ctx, buildID, v.Deployment()) task_queue_partition_manager.go
1422 > if err != nil {
1423 return nil, err
1424 }
1425 > if reportPollers { task_queue_partition_manager.go
1426 vInfo.PhysicalTaskQueueInfo.Pollers = physicalQueue.GetAllPollerInfo()
1427 }
1428 > if reportStats { task_queue_partition_manager.go
1429 > physicalStatsByPriority := physicalQueue.GetStatsByPriority(true)
1430 >
1431 > // Clone the physical queue's stats by priority so we can adjust (either add, subtract) them based on the
1432 > // attribution model defined below.
1433 > adjustedStatsByPriority := cloneStatsByPriority(physicalStatsByPriority)
1434 >
1435 > // Attribution model (applied per-priority):
1436 > // - If current and/or ramping deployment versions exist, we first "give away" a portion of the
1437 > // unversioned queue's per-priority stats.
1438 > //
1439 > // Depending on the version described, we have the following options:
1440 > // - For the unversioned version itself, subtract the given-away portion (so we don't double count).
1441 > // - For current/ramping versions, add their share on top of their physical queue stats.
1442 > deploymentVersion := worker_versioning.DeploymentVersionFromDeployment(v.Deployment())
1443 >
1444 > isUnversionedDescribe := deploymentVersion == nil
1445 > isCurrentDescribe := deploymentVersion.GetDeploymentName() == currentVersion.GetDeploymentName() &&
1446 > deploymentVersion.GetBuildId() == currentVersion.GetBuildId()
1447 >
1448 > // "Ramping to unversioned" is represented by "rampingExists==true AND rampingVersion==nil".
1449 > // In that case, the ramp share should remain attributed to the unversioned queue stats and
1450 > // there is no separate versioned queue to merge that share into.
1451 > isRampingToUnversioned := rampingExists && rampingVersion == nil
1452 > isRampingDescribe := deploymentVersion.GetDeploymentName() == rampingVersion.GetDeploymentName() &&
1453 > deploymentVersion.GetBuildId() == rampingVersion.GetBuildId()
1454 >
1455 > if isUnversionedDescribe {
1456 > // Reduce unversioned stats by any shares attributed to versioned queues. task_queue_partition_manager.go
1457 > if currentExists {
1458 subtractStatsByPriority(adjustedStatsByPriority, unversionedCurrentShareByPriority)
1459 }
1460 // Only subtract the ramping share when ramping is to a versioned deployment. If ramping is to
1461 // unversioned, that share should remain part of the unversioned queue stats.
1462 > if rampingExists && !isRampingToUnversioned { task_queue_partition_manager.go
1463 subtractStatsByPriority(adjustedStatsByPriority, unversionedRampingShareByPriority)
1464 }
1469 }
1470
1471 > vInfo.PhysicalTaskQueueInfo.TaskQueueStatsByPriorityKey = adjustedStatsByPriority task_queue_partition_manager.go
1472 > vInfo.PhysicalTaskQueueInfo.TaskQueueStats = aggregateStats(adjustedStatsByPriority)
1473 }
1474 > if internalTaskQueueStatus { task_queue_partition_manager.go
1475 vInfo.PhysicalTaskQueueInfo.InternalTaskQueueStatus = physicalQueue.GetInternalTaskQueueStatus()
1476 }
1480 // the full worker-deployment version string is used as an entry in the versionsInfo map. Moreover, to keep things backwards compatible, users requesting
1481 // information for non-deployment related builds will only see the buildID as an entry in the versionsInfo map.
1482 > bid := v.BuildId() task_queue_partition_manager.go
1483 > if v.Deployment() != nil {
1484 bid = worker_versioning.ExternalWorkerDeploymentVersionToString(worker_versioning.ExternalWorkerDeploymentVersionFromDeployment(v.Deployment()))
1485 }
1486 > versionsInfo[bid] = vInfo task_queue_partition_manager.go
1487 >
1488 > if !skipMarkAlive {
1489 > // Skipped by periodic metrics emission to avoid resetting the idle timeout, task_queue_partition_manager.go
1490 > // which would prevent queues from ever being unloaded.
1491 > physicalQueue.MarkAlive()
1492 > }
1493 }
1494
1495 > return &matchingservice.DescribeTaskQueuePartitionResponse{ task_queue_partition_manager.go
1496 > VersionsInfoInternal: versionsInfo,
1497 > ScaleInfo: pm.userDataManager.PartitionScale(),
1498 > }, nil
1499 }
1500
1501 > func (pm *taskQueuePartitionManagerImpl) updateEphemeralData(ctx context.Context) error { task_queue_partition_manager.go
1502 > // for now, this only applies to normal workflow task queues, only with new matcher
1503 > if pm.partition.Kind() != enumspb.TASK_QUEUE_KIND_NORMAL ||
1504 > pm.partition.TaskType() != enumspb.TASK_QUEUE_TYPE_WORKFLOW ||
1505 > !pm.config.NewMatcher {
1507 > }
1508
1509 > var prevBacklogPriority map[PhysicalTaskQueueVersion]int64 task_queue_partition_manager.go
1510 >
1511 > for {
1512 > interval := pm.config.EphemeralDataUpdateInterval()
1513 > if interval == 0 {
1514 _ = util.InterruptibleSleep(ctx, time.Minute)
1515 continue
1516 }
1517
1519 > case <-ctx.Done(): task_queue_partition_manager.go
1520 > return ctx.Err()
1521
1522 case <-time.After(backoff.Jitter(interval, 0.05)):
1565 }
1566
1567 > func (pm *taskQueuePartitionManagerImpl) emitLogicalBacklogMetrics(ctx context.Context) error { task_queue_partition_manager.go
1568 > for {
1569 > interval := pm.config.BacklogMetricsEmitInterval()
1570 > if interval == 0 { // disabled
1571 _ = util.InterruptibleSleep(ctx, time.Minute)
1572 if ctx.Err() != nil {
1648 // Those attributed-only keys are not zeroed here, which could leave stale gauge values for
1649 // priority keys that existed only through attribution.
1650 > func (pm *taskQueuePartitionManagerImpl) emitZeroLogicalBacklogForQueue(version PhysicalTaskQueueVersion, pq physicalTaskQueueManager) { task_queue_partition_manager.go
1651 > if !pm.config.BreakdownMetricsByTaskQueue() || !pm.config.BreakdownMetricsByPartition() {
1652 return
1653 }
1654 > deploymentName, buildID := parseDeploymentFromVersionKey(version.MetricsTagValue()) task_queue_partition_manager.go
1655 > handler := pm.metricsHandler.WithTags(
1656 > metrics.WorkerVersionTag(version.MetricsTagValue(), pm.config.BreakdownMetricsByBuildID()),
1657 > metrics.WorkerDeploymentNameTag(deploymentName, pm.config.BreakdownMetricsByBuildID()),
1658 > metrics.WorkerDeploymentBuildIDTag(buildID, pm.config.BreakdownMetricsByBuildID()),
1659 > )
1660 > for pri := range pq.GetStatsByPriority(false) {
1661 > metrics.ApproximateBacklogCount.With(handler).Record(0, metrics.MatchingTaskPriorityTag(pri))
1662 > }
1663 > metrics.ApproximateBacklogAgeSeconds.With(handler).Record(0)
1664 }
1665
1669 // unversioned queues. Returns empty strings when the delimiter is not found (unversioned or
1670 // V2 version-set keys).
1671 > func parseDeploymentFromVersionKey(versionKey string) (deploymentName, buildID string) { task_queue_partition_manager.go
1672 > if name, id, found := strings.Cut(versionKey, worker_versioning.WorkerDeploymentVersionDelimiter); found {
1673 return name, id
1674 }
1675 > return "", "" task_queue_partition_manager.go
1676 }
1677
1724 }
1725
1726 > func cloneTaskQueueStats(in *taskqueuepb.TaskQueueStats) *taskqueuepb.TaskQueueStats { task_queue_partition_manager.go
1727 > if in == nil {
1728 return &taskqueuepb.TaskQueueStats{ApproximateBacklogAge: durationpb.New(0)}
1729 }
1730 > age := in.GetApproximateBacklogAge() task_queue_partition_manager.go
1731 > if age == nil {
1732 age = durationpb.New(0)
1733 }
1734 > return &taskqueuepb.TaskQueueStats{ task_queue_partition_manager.go
1735 > ApproximateBacklogCount: in.GetApproximateBacklogCount(),
1736 > ApproximateBacklogAge: durationpb.New(age.AsDuration()),
1737 > TasksAddRate: in.GetTasksAddRate(),
1738 > TasksDispatchRate: in.GetTasksDispatchRate(),
1739 > }
1740 }
1741
1742 > func cloneStatsByPriority(in map[int32]*taskqueuepb.TaskQueueStats) map[int32]*taskqueuepb.TaskQueueStats { task_queue_partition_manager.go
1743 > out := make(map[int32]*taskqueuepb.TaskQueueStats, len(in))
1744 > for pri, s := range in {
1745 > out[pri] = cloneTaskQueueStats(s)
1746 > }
1747 > return out
1748 }
1749
1877 }
1878
1879 > func (pm *taskQueuePartitionManagerImpl) Partition() tqid.Partition { task_queue_partition_manager.go
1880 > return pm.partition
1881 > }
1882
1883 func (pm *taskQueuePartitionManagerImpl) PartitionCount() int {
1888 }
1889
1890 > func (pm *taskQueuePartitionManagerImpl) LongPollExpirationInterval() time.Duration { task_queue_partition_manager.go
1891 > return pm.config.LongPollExpirationInterval()
1892 > }
1893
1894 > func (pm *taskQueuePartitionManagerImpl) callerInfoContext(ctx context.Context) context.Context { task_queue_partition_manager.go
1895 > return headers.SetCallerInfo(ctx, headers.NewBackgroundHighCallerInfo(pm.ns.Name().String()))
1896 > }
1897
1898 // ForceLoadAllChildPartitions force-loads known child (read) partitions in new goroutines.
1899 // TODO(dp): consider moving this into scaleManager.backgroundWork after auto-scaling is enabled everywhere.
1900 > func (pm *taskQueuePartitionManagerImpl) ForceLoadAllChildPartitions() { task_queue_partition_manager.go
1901 > if !pm.partition.IsRoot() {
1903 > }
1904
1905 > partitions := pm.userDataManager.PartitionScale().GetRead() task_queue_partition_manager.go
1906 > if partitions == 0 {
1907 > partitions = int32(pm.config.NumReadPartitions())
1908 > }
1909 > if partitions <= 1 {
1911 > }
1912
1913 // record total-1 as we won't try to load the root partition.
2132 targetVersion *deploymentspb.WorkerDeploymentVersion,
2133 err error,
2135 > // Note: Revision number mechanics are only involved if the dynamic config, UseRevisionNumberForWorkerVersioning, is enabled.
2136 > // Represents the revision number used by the task and is max(taskDirectiveRevisionNumber, routingConfigRevisionNumber) for the task.
2137 > var taskDispatchRevisionNumber, targetDeploymentRevisionNumber int64
2138 >
2139 > wfBehavior := directive.GetBehavior()
2140 > deployment := worker_versioning.DirectiveDeployment(directive)
2141 >
2142 > perTypeUserData, userDataChanged, err := pm.getPerTypeUserData()
2143 > if err != nil {
2144 return nil, nil, nil, 0, nil, err
2145 }
2146 > deploymentData := perTypeUserData.GetDeploymentData() task_queue_partition_manager.go
2147 > taskDirectiveRevisionNumber := directive.GetRevisionNumber()
2148 >
2149 > dbq := pm.defaultQueue()
2150 > if dbq == nil {
2151 return nil, nil, nil, 0, nil, errDefaultQueueNotInit
2152 }
2153
2154 > current, currentRevisionNumber, _, ramping, _, rampingPercentage, rampingRevisionNumber, _ := worker_versioning.CalculateTaskQueueVersioningInfo(deploymentData) task_queue_partition_manager.go
2155 > targetDeploymentVersion, targetDeploymentRevisionNumber := worker_versioning.FindTargetDeploymentVersionAndRevisionNumberForWorkflowID(
2156 > current,
2157 > currentRevisionNumber,
2158 > ramping,
2159 > rampingPercentage,
2160 > rampingRevisionNumber,
2161 > workflowId,
2162 > directive.GetUseRampingVersion(),
2163 > )
2164 > targetDeployment := worker_versioning.DeploymentFromDeploymentVersion(targetDeploymentVersion)
2165 >
2166 > if wfBehavior == enumspb.VERSIONING_BEHAVIOR_PINNED {
2167 if pm.partition.Kind() == enumspb.TASK_QUEUE_KIND_STICKY {
2168 // TODO (shahab): we can verify the passed deployment matches the last poller's deployment
2210 }
2211
2212 > var targetDeploymentQueue physicalTaskQueueManager task_queue_partition_manager.go
2213 > if directive.GetAssignedBuildId() == "" && targetDeployment != nil {
2214 if pm.partition.Kind() == enumspb.TASK_QUEUE_KIND_STICKY {
2215 if !deployment.Equal(targetDeployment) {
2242 }
2243
2244 > if forwardInfo != nil { task_queue_partition_manager.go
2245 // Forwarded from child partition - only do sync match.
2246 // No need to calculate build ID, just dispatch based on source partition's instructions.
2259 }
2260
2261 > if directive.GetBuildId() == nil { task_queue_partition_manager.go
2262 // The task belongs to an unversioned execution. Keep using unversioned. But also return
2263 // userDataChanged so if current deployment is set, the task redirects to that deployment.
2265 }
2266
2267 > userData, userDataChanged, err := pm.userDataManager.GetUserData() task_queue_partition_manager.go
2268 > if err != nil {
2269 return nil, nil, nil, 0, nil, err
2270 }
2271
2272 > data := userData.GetData().GetVersioningData() task_queue_partition_manager.go
2273 >
2274 > var buildId, redirectBuildId string
2275 > var versionSet string
2276 > switch dir := directive.GetBuildId().(type) {
2277 > case *taskqueuespb.TaskVersionDirective_UseAssignmentRules: task_queue_partition_manager.go
2278 > // Need to assign build ID. Assignment rules take precedence, fallback to version sets if no matching rule is found
2279 > if len(data.GetAssignmentRules()) > 0 {
2280 buildId = FindAssignmentBuildId(data.GetAssignmentRules(), runId)
2281 }
2282 > if buildId == "" { task_queue_partition_manager.go
2283 > versionSet, err = pm.getVersionSetForAdd(directive, data) task_queue_partition_manager.go
2284 > if err != nil {
2285 return nil, nil, nil, 0, nil, err
2286 }
2301 }
2302
2303 > redirectBuildId = FindRedirectBuildId(buildId, data.GetRedirectRules()) task_queue_partition_manager.go
2304 >
2305 > if pm.partition.Kind() == enumspb.TASK_QUEUE_KIND_STICKY {
2306 // We may kick off this worker if there's a new default build ID in the version set.
2307 // unknownBuild flag is ignored because we don't have any special logic for it anymore. unknown build can
2333 return nil, nil, nil, 0, nil, err
2334 }
2336 > syncMatchQueue, err = pm.getPhysicalQueue(ctx, redirectBuildId, nil)
2337 > if err != nil {
2338 return nil, nil, nil, 0, nil, err
2339 }
2340 // redirect rules are not applied when spooling a task. They'll be applied when dispatching the spool task.
2341 > spoolQueue, err = pm.getPhysicalQueue(ctx, buildId, nil) task_queue_partition_manager.go
2342 > if err != nil {
2343 return nil, nil, nil, 0, nil, err
2344 }
2345 }
2346
2347 > return spoolQueue, syncMatchQueue, userDataChanged, taskDispatchRevisionNumber, targetDeploymentVersion, err task_queue_partition_manager.go
2348 }
2349
2373 }
2374
2375 > func (pm *taskQueuePartitionManagerImpl) getVersionSetForAdd(directive *taskqueuespb.TaskVersionDirective, data *persistencespb.VersioningData) (string, error) { task_queue_partition_manager.go
2376 > var buildId string
2377 > switch dir := directive.GetBuildId().(type) {
2378 > case *taskqueuespb.TaskVersionDirective_UseAssignmentRules: task_queue_partition_manager.go
2379 // leave buildId = "", lookupVersionSetForAdd understands that to mean "default"
2380 case *taskqueuespb.TaskVersionDirective_AssignedBuildId:
2447 }
2448
2449 > func (pm *taskQueuePartitionManagerImpl) getPerTypeUserData() (*persistencespb.TaskQueueTypeUserData, <-chan struct{}, error) { task_queue_partition_manager.go
2450 > userData, userDataChanged, err := pm.userDataManager.GetUserData()
2451 > if err != nil {
2452 return nil, nil, err
2453 }
2454 > perType := userData.GetData().GetPerType()[int32(pm.Partition().TaskType())] task_queue_partition_manager.go
2455 > return perType, userDataChanged, nil
2456 }
2457
2458 > func (pm *taskQueuePartitionManagerImpl) userDataChanged(to *persistencespb.VersionedTaskQueueUserData) { task_queue_partition_manager.go
2459 > // Update rateLimits if any change is userData.
2460 > pm.rateLimitManager.UserDataChanged()
2461 >
2462 > // Do not use defaultQueue() because that treats
2463 > // not being ready as an error, which is expected during bringup here.
2464 > defaultQ, err := pm.defaultQueueFuture.GetIfReady()
2465 > // Initialization error or not ready yet
2466 > if err != nil {
2468 > }
2469
2470 > taskType := int32(pm.Partition().TaskType()) task_queue_partition_manager.go
2471 > if to.GetData().GetPerType()[taskType].GetFairnessState() != pm.fairnessState {
2472 pm.logger.Debug("unloading partitionManager due to change in FairnessState")
2473 pm.unloadFromEngine(unloadCauseConfigChange)
2476
2477 // Notify all queues so they can re-evaluate their backlog.
2478 > pm.versionedQueuesLock.RLock() task_queue_partition_manager.go
2479 > for _, vq := range pm.versionedQueues {
2480 go vq.UserDataChanged()
2481 }
2482 > pm.versionedQueuesLock.RUnlock() task_queue_partition_manager.go
2483 >
2484 > // Do this one in this goroutine.
2485 > defaultQ.UserDataChanged()
2486 }
go.temporal.io/server/service/matching/matching_engine.go 598 covered LOC · 115 ranges

Open complete file

208
209 // Add registers a poller for a worker instance. Thread-safe.
210 > func (t *workerPollerTracker) Add(workerKey, pollerID string, cancel context.CancelFunc) { matching_engine.go
211 > t.lock.Lock()
212 > defer t.lock.Unlock()
213 > util.GetOrSetMap(t.pollers, workerKey)[pollerID] = cancel
214 > }
215
216 // Remove unregisters a poller. Cleans up empty worker entries to prevent memory leak. Thread-safe.
217 > func (t *workerPollerTracker) Remove(workerKey, pollerID string) { matching_engine.go
218 > t.lock.Lock()
219 > defer t.lock.Unlock()
220 > util.DeleteFromMap(t.pollers, workerKey, pollerID)
221 > }
222
223 // CancelAll cancels all pollers for a worker and removes the worker entry. Returns cancelled count. Thread-safe.
285 taskHookFactories []hooks.TaskHookFactory,
286 partitionScalerFactory PartitionScalerFactory,
287 > ) Engine { matching_engine.go
288 > scopedMetricsHandler := metricsHandler.WithTags(metrics.OperationTag(metrics.MatchingEngineScope))
289 > e := &matchingEngineImpl{
290 > status: common.DaemonStatusInitialized,
291 > taskManager: taskManager,
292 > fairTaskManager: fairTaskManager,
293 > historyClient: historyClient,
294 > matchingRawClient: matchingRawClient,
295 > tokenSerializer: tasktoken.NewSerializer(),
296 > workerDeploymentClient: workerDeploymentClient,
297 > historySerializer: historySerializer,
298 > logger: log.With(logger, tag.ComponentMatchingEngine),
299 > throttledLogger: log.With(throttledLogger, tag.ComponentMatchingEngine),
300 > namespaceRegistry: namespaceRegistry,
301 > hostInfoProvider: hostInfoProvider,
302 > serviceResolver: resolver,
303 > membershipChangedCh: make(chan *membership.ChangedEvent, 1), // allow one signal to be buffered while we're working
304 > clusterMeta: clusterMeta,
305 > timeSource: clock.NewRealTimeSource(), // No need to mock this at the moment
306 > visibilityManager: visibilityManager,
307 > nexusEndpointClient: newEndpointClient(config.NexusEndpointsRefreshInterval, nexusEndpointManager),
308 > // nexusEndpointsOwnershipLostCh initialized below
309 > saProvider: saProvider,
310 > saMapperProvider: saMapperProvider,
311 > metricsHandler: scopedMetricsHandler,
312 > partitions: make(map[tqid.PartitionKey]taskQueuePartitionManager),
313 > gaugeMetrics: gaugeMetrics{
314 > loadedTaskQueueFamilyCount: make(map[taskQueueCounterKey]int),
315 > loadedTaskQueueCount: make(map[taskQueueCounterKey]int),
316 > loadedTaskQueuePartitionCount: make(map[taskQueueCounterKey]int),
317 > loadedPhysicalTaskQueueCount: make(map[taskQueueCounterKey]int),
318 > },
319 > config: config,
320 > versionChecker: headers.NewDefaultVersionChecker(),
321 > testHooks: testHooks,
322 > queryResults: collection.NewSyncMap[string, chan *queryResult](),
323 > nexusResults: collection.NewSyncMap[string, chan *nexusResult](),
324 > outstandingPollers: collection.NewSyncMap[string, context.CancelFunc](),
325 > workerInstancePollers: workerPollerTracker{pollers: make(map[string]map[string]context.CancelFunc)},
326 > shutdownWorkers: cache.New(shutdownWorkersCacheMaxSize, &cache.Options{TTL: shutdownWorkersCacheTTL}),
327 > namespaceReplicationQueue: namespaceReplicationQueue,
328 > userDataUpdateBatchers: collection.NewSyncMap[namespace.ID, *stream_batcher.Batcher[*userDataUpdate, error]](),
329 > rateLimiter: rateLimiter,
330 > taskHookFactories: taskHookFactories,
331 > partitionScalerFactory: partitionScalerFactory,
332 > }
333 > e.nexusEndpointsOwnershipLostCh.Store(make(chan struct{}))
334 > e.reachabilityCache = newReachabilityCache(
335 > metrics.NoopMetricsHandler,
336 > visibilityManager,
337 > e.config.ReachabilityCacheOpenWFsTTL(),
338 > e.config.ReachabilityCacheClosedWFsTTL())
339 > return e
340 > }
341
342 > func (e *matchingEngineImpl) Start() { matching_engine.go
343 > if !atomic.CompareAndSwapInt32(
344 > &e.status,
345 > common.DaemonStatusInitialized,
346 > common.DaemonStatusStarted,
347 > ) {
348 return
349 }
350
351 > go e.watchMembership() matching_engine.go
352 > _ = e.serviceResolver.AddListener(e.listenerKey(), e.membershipChangedCh)
353 }
354
355 > func (e *matchingEngineImpl) Stop() { matching_engine.go
356 > if !atomic.CompareAndSwapInt32(
357 > &e.status,
358 > common.DaemonStatusStarted,
359 > common.DaemonStatusStopped,
360 > ) {
361 return
362 }
363
364 > _ = e.serviceResolver.RemoveListener(e.listenerKey()) matching_engine.go
365 > close(e.membershipChangedCh)
366 >
367 > e.nexusEndpointClient.notifyOwnershipChanged(false)
368 >
369 > for _, l := range e.getTaskQueuePartitions(math.MaxInt32) {
370 > l.Stop(unloadCauseShuttingDown) matching_engine.go
371 > }
372 }
373
374 > func (e *matchingEngineImpl) listenerKey() string { matching_engine.go
375 > return fmt.Sprintf("matchingEngine[%p]", e)
376 > }
377
378 > func (e *matchingEngineImpl) watchMembership() { matching_engine.go
379 > self := e.hostInfoProvider.HostInfo().Identity()
380 > rc, ok := e.matchingRawClient.(matching.RoutingClient)
381 > if !ok {
382 e.logger.Warn("watchMembership found non-routing matching client")
383 return // this should only happen in unit tests
384 }
385 > ownedByOther := func(p tqid.Partition) bool { matching_engine.go
386 addr, err := rc.Route(p)
387 // don't take action on lookup error
389 }
390
391 > for range e.membershipChangedCh { matching_engine.go
392 > delay := e.config.MembershipUnloadDelay()
393 > if delay == 0 {
394 continue
395 }
396
397 > e.notifyNexusEndpointsOwnershipChange() matching_engine.go
398 >
399 > // Check all our loaded partitions to see if we lost ownership of any of them.
400 > e.partitionsLock.RLock()
401 > partitions := make([]tqid.Partition, 0, len(e.partitions))
402 > for _, pm := range e.partitions {
403 partitions = append(partitions, pm.Partition())
404 }
405 > e.partitionsLock.RUnlock() matching_engine.go
406 >
407 > partitions = util.FilterSlice(partitions, ownedByOther)
408 >
409 > const batchSize = 100
410 > for i := 0; i < len(partitions); i += batchSize {
411 // We don't own these anymore, but don't unload them immediately, wait a few seconds to ensure
412 // the membership update has propagated everywhere so that they won't get immediately re-loaded.
433 }
434
435 > func (e *matchingEngineImpl) getTaskQueuePartitions(maxCount int) (lists []taskQueuePartitionManager) { matching_engine.go
436 > e.partitionsLock.RLock()
437 > defer e.partitionsLock.RUnlock()
438 > lists = make([]taskQueuePartitionManager, 0, len(e.partitions))
439 > count := 0
440 > for _, tlMgr := range e.partitions {
441 > lists = append(lists, tlMgr) matching_engine.go
442 > count++
443 > if count >= maxCount {
444 break
445 }
446 }
447 > return matching_engine.go
448 }
449
465 create bool,
466 loadCause loadCause,
467 > ) (retPM taskQueuePartitionManager, retCreated bool, retErr error) { matching_engine.go
468 > defer func() {
469 > if retErr != nil || retPM == nil {
470 return
471 }
472 > if retErr = retPM.WaitUntilInitialized(ctx); retErr != nil { matching_engine.go
473 > e.unloadTaskQueuePartition(retPM, unloadCauseInitError) matching_engine.go
474 > }
475 }()
476
477 > key := partition.Key() matching_engine.go
478 > e.partitionsLock.RLock()
479 > pm, ok := e.partitions[key]
480 > e.partitionsLock.RUnlock()
481 > if ok {
482 > return pm, false, nil matching_engine.go
483 > }
484
485 > if !create { matching_engine.go
486 return nil, false, nil
487 }
488
489 > namespaceEntry, err := e.namespaceRegistry.GetNamespaceByID(namespace.ID(partition.NamespaceId())) matching_engine.go
490 > if err != nil {
491 return nil, false, err
492 }
493
494 > var newPM *taskQueuePartitionManagerImpl matching_engine.go
495 > tqConfig := newTaskQueueConfig(partition.TaskQueue(), e.config, namespaceEntry.Name())
496 > tqConfig.loadCause = loadCause
497 > logger, throttledLogger, metricsHandler := e.loggerAndMetricsForPartition(namespaceEntry, partition, tqConfig)
498 > onFatalErr := func(cause unloadCause) { newPM.unloadFromEngine(cause) }
499 > onUserDataChanged := func(to *persistencespb.VersionedTaskQueueUserData) { newPM.userDataChanged(to) }
500 > onEphemeralDataChanged := func(data *taskqueuespb.EphemeralData) { newPM.ephemeralDataChanged(data) }
501 > userDataManager := newUserDataManager(
502 > e.taskManager,
503 > e.matchingRawClient,
504 > onFatalErr,
505 > onUserDataChanged,
506 > onEphemeralDataChanged,
507 > partition,
508 > tqConfig,
509 > logger,
510 > e.namespaceRegistry,
511 > )
512 > newPM, err = newTaskQueuePartitionManager(
513 > e,
514 > namespaceEntry,
515 > partition,
516 > tqConfig,
517 > logger,
518 > throttledLogger,
519 > metricsHandler,
520 > userDataManager,
521 > )
522 > if err != nil {
523 return nil, false, err
524 }
525
526 // If it gets here, write lock and check again in case a task queue is created between the two locks
527 > e.partitionsLock.Lock() matching_engine.go
528 > pm, ok = e.partitions[key]
529 > if ok {
530 > e.partitionsLock.Unlock() matching_engine.go
531 > // Lost the race with a concurrent load of the same partition. The unstarted
532 > // newPM holds no external references (subscriptions etc. are only registered
533 > // in Start), so it can simply be dropped and garbage collected.
534 > return pm, false, nil
535 > }
536
537 > e.partitions[key] = newPM matching_engine.go
538 > e.partitionsLock.Unlock()
539 >
540 > newPM.Start()
541 > return newPM, true, nil
542 }
543
546 partition tqid.Partition,
547 tqConfig *taskQueueConfig,
548 > ) (log.Logger, log.Logger, metrics.Handler) { matching_engine.go
549 > nsName := nsEntry.Name().String()
550 > var nsState string
551 > //nolint:forbidigo // metric tag for namespace state, not per-workflow
552 > if nsEntry.ActiveInCluster(e.clusterMeta.GetCurrentClusterName()) {
553 > nsState = metrics.ActiveNamespaceStateTagValue
554 > } else {
555 nsState = metrics.PassiveNamespaceStateTagValue
556 }
557 > logger := log.With(e.logger, matching_engine.go
558 > tag.WorkflowTaskQueueName(partition.RpcName()),
559 > tag.WorkflowTaskQueueType(partition.TaskType()),
560 > tag.WorkflowNamespace(nsName))
561 > throttledLogger := log.With(e.throttledLogger,
562 > tag.WorkflowTaskQueueName(partition.RpcName()),
563 > tag.WorkflowTaskQueueType(partition.TaskType()),
564 > tag.WorkflowNamespace(nsName))
565 > metricsHandler := metrics.GetPerTaskQueuePartitionIDScope(
566 > e.metricsHandler,
567 > nsName,
568 > partition,
569 > tqConfig.BreakdownMetricsByTaskQueue(),
570 > tqConfig.BreakdownMetricsByPartition(),
571 > metrics.OperationTag(metrics.MatchingTaskQueuePartitionManagerScope),
572 > ).WithTags(metrics.NamespaceStateTag(nsState))
573 > return logger, throttledLogger, metricsHandler
574 }
575
584 ctx context.Context,
585 addRequest *matchingservice.AddWorkflowTaskRequest,
586 > ) (buildId string, syncMatch bool, err error) { matching_engine.go
587 > partition, err := tqid.PartitionFromProto(addRequest.TaskQueue, addRequest.NamespaceId, enumspb.TASK_QUEUE_TYPE_WORKFLOW)
588 > if err != nil {
589 return "", false, err
590 }
591 > sticky := partition.Kind() == enumspb.TASK_QUEUE_KIND_STICKY matching_engine.go
592 > if !softassert.That(e.logger, partition.Kind() == enumspb.TASK_QUEUE_KIND_NORMAL || sticky,
593 > "AddWorkflowTask called with unexpected partition kind") {
594 return "", false, serviceerror.NewInternal("AddWorkflowTask called with unexpected partition kind")
595 }
596
597 // do not load sticky task queues if not already loaded, which means they have no poller.
598 > pm, _, err := e.getTaskQueuePartitionManager(ctx, partition, !sticky, loadCauseTask) matching_engine.go
599 > if err != nil {
600 return "", false, err
601 > } else if sticky && !stickyWorkerAvailable(pm) { matching_engine.go
602 return "", false, serviceerrors.NewStickyWorkerUnavailable()
603 }
604
605 // This needs to move to history see - https://go.temporal.io/server/issues/181
606 > var expirationTime *timestamppb.Timestamp matching_engine.go
607 > now := time.Now().UTC()
608 > expirationDuration := addRequest.GetScheduleToStartTimeout().AsDuration()
609 > if expirationDuration != 0 {
610 expirationTime = timestamppb.New(now.Add(expirationDuration))
611 }
612 > taskInfo := &persistencespb.TaskInfo{ matching_engine.go
613 > NamespaceId: addRequest.NamespaceId,
614 > RunId: addRequest.Execution.GetRunId(),
615 > WorkflowId: addRequest.Execution.GetWorkflowId(),
616 > ScheduledEventId: addRequest.GetScheduledEventId(),
617 > Clock: addRequest.GetClock(),
618 > ExpiryTime: expirationTime,
619 > CreateTime: timestamppb.New(now),
620 > VersionDirective: addRequest.VersionDirective,
621 > Stamp: addRequest.Stamp,
622 > Priority: addRequest.Priority,
623 > }
624 >
625 > return pm.AddTask(ctx, addTaskParams{
626 > taskInfo: taskInfo,
627 > forwardInfo: addRequest.ForwardInfo,
628 > })
629 }
630
674 req *matchingservice.PollWorkflowTaskQueueRequest,
675 opMetrics metrics.Handler,
676 > ) (*matchingservice.PollWorkflowTaskQueueResponseWithRawHistory, error) { matching_engine.go
677 > namespaceID := namespace.ID(req.GetNamespaceId())
678 > pollerID := req.GetPollerId()
679 > request := req.PollRequest
680 > taskQueueName := request.TaskQueue.GetName()
681 >
682 > // Namespace field is not populated for forwarded requests.
683 > if len(request.Namespace) == 0 {
684 ns, err := e.namespaceRegistry.GetNamespaceName(namespace.ID(req.GetNamespaceId()))
685 if err != nil {
689 }
690
691 > pollLoop: matching_engine.go
692 > for {
693 > err := common.IsValidContext(ctx)
694 > if err != nil {
695 return nil, err
696 }
697 // Add frontend generated pollerID to context so taskqueueMgr can support cancellation of
698 // long-poll when frontend calls CancelOutstandingPoll API
699 > pollerCtx := context.WithValue(ctx, pollerIDKey, pollerID) matching_engine.go
700 > pollerCtx = context.WithValue(pollerCtx, identityKey, request.GetIdentity())
701 > partition, err := tqid.PartitionFromProto(request.TaskQueue, req.NamespaceId, enumspb.TASK_QUEUE_TYPE_WORKFLOW)
702 > if err != nil {
703 return nil, err
704 }
705 > pollMetadata := &pollMetadata{ matching_engine.go
706 > workerVersionCapabilities: request.WorkerVersionCapabilities,
707 > deploymentOptions: request.DeploymentOptions,
708 > forwardedFrom: req.ForwardedSource,
709 > conditions: req.Conditions,
710 > workerInstanceKey: request.WorkerInstanceKey,
711 > workerControlTaskQueue: request.WorkerControlTaskQueue,
712 > }
713 > task, versionSetUsed, err := e.pollTask(pollerCtx, partition, pollMetadata)
714 > if err != nil {
715 > if errors.Is(err, errNoTasks) { matching_engine.go
716 > return emptyPollWorkflowTaskQueueResponse, nil
717 > }
718 > return nil, err matching_engine.go
719 }
720 > if task.isStarted() { matching_engine.go
721 // tasks received from remote are already started. So, simply forward the response
722 // no need to emit task dispatch latency metric because the parent partition already did it.
724 }
725
726 > if task.isQuery() { matching_engine.go
727 task.finish(taskFinishResult{consumedToken: true}) // this only means query task sync match succeed.
728
773 }
774
775 > requestClone := request matching_engine.go
776 > if versionSetUsed {
777 // We remove build ID from workerVersionCapabilities so History can differentiate between
778 // old and new versioning in Record*TaskStart.
781 requestClone.WorkerVersionCapabilities.BuildId = ""
782 }
783 > resp, err := e.recordWorkflowTaskStarted(ctx, requestClone, task) matching_engine.go
784 > if err != nil {
785 switch err := err.(type) {
786 case *serviceerror.Internal:
858 }
859
860 > task.finish(taskFinishResult{consumedToken: true}) matching_engine.go
861 > e.emitTaskDispatchLatency(task, partition, req.GetNamespaceId(), request.Namespace, pollMetadata)
862 > return e.createPollWorkflowTaskQueueResponse(task, resp, opMetrics), nil
863 }
864 }
949 req *matchingservice.PollActivityTaskQueueRequest,
950 opMetrics metrics.Handler,
951 > ) (*matchingservice.PollActivityTaskQueueResponse, error) { matching_engine.go
952 > pollerID := req.GetPollerId()
953 > request := req.PollRequest
954 > taskQueueName := request.TaskQueue.GetName()
955 >
956 > // Namespace field is not populated for forwarded requests.
957 > if len(request.Namespace) == 0 {
958 ns, err := e.namespaceRegistry.GetNamespaceName(namespace.ID(req.GetNamespaceId()))
959 if err != nil {
963 }
964
965 > pollLoop: matching_engine.go
966 > for {
967 > err := common.IsValidContext(ctx)
968 > if err != nil {
969 return nil, err
970 }
971
972 > partition, err := tqid.PartitionFromProto(request.TaskQueue, req.NamespaceId, enumspb.TASK_QUEUE_TYPE_ACTIVITY) matching_engine.go
973 > if err != nil {
974 return nil, err
975 }
977 // Add frontend generated pollerID to context so taskqueueMgr can support cancellation of
978 // long-poll when frontend calls CancelOutstandingPoll API
979 > pollerCtx := context.WithValue(ctx, pollerIDKey, pollerID) matching_engine.go
980 > pollerCtx = context.WithValue(pollerCtx, identityKey, request.GetIdentity())
981 > pollMetadata := &pollMetadata{
982 > taskQueueMetadata: request.TaskQueueMetadata,
983 > workerVersionCapabilities: request.WorkerVersionCapabilities,
984 > deploymentOptions: request.DeploymentOptions,
985 > forwardedFrom: req.ForwardedSource,
986 > conditions: req.Conditions,
987 > workerInstanceKey: request.WorkerInstanceKey,
988 > workerControlTaskQueue: request.WorkerControlTaskQueue,
989 > }
990 > task, versionSetUsed, err := e.pollTask(pollerCtx, partition, pollMetadata)
991 > if err != nil {
992 > if errors.Is(err, errNoTasks) { matching_engine.go
993 > return emptyPollActivityTaskQueueResponse, nil
994 > }
995 return nil, err
996 }
1212 _ context.Context,
1213 request *matchingservice.CancelOutstandingPollRequest,
1214 > ) error { matching_engine.go
1215 > cancel, ok := e.outstandingPollers.Pop(request.PollerId)
1216 > if ok {
1217 > cancel()
1218 > }
1219 > return nil
1220 }
1221
2178 ctx context.Context,
2179 req *matchingservice.GetTaskQueueUserDataRequest,
2180 > ) (*matchingservice.GetTaskQueueUserDataResponse, error) { matching_engine.go
2181 > partition, err := tqid.PartitionFromProto(&taskqueuepb.TaskQueue{Name: req.GetTaskQueue()}, req.NamespaceId, req.TaskQueueType)
2182 > if err != nil {
2183 return nil, err
2184 }
2185 > pm, _, err := e.getTaskQueuePartitionManager(ctx, partition, !req.OnlyIfLoaded, loadCauseUserData) matching_engine.go
2186 > if err != nil {
2187 return nil, err
2188 > } else if pm == nil { matching_engine.go
2189 return nil, serviceerror.NewFailedPrecondition("partition was not loaded")
2190 }
2191 > if req.WaitNewData { matching_engine.go
2192 > // mark alive so that it doesn't unload while a child partition is doing a long poll matching_engine.go
2193 > pm.MarkAlive()
2194 > }
2195 > return pm.GetUserDataManager().HandleGetUserDataRequest(ctx, req) matching_engine.go
2196 }
2197
2542 ctx context.Context,
2543 req *matchingservice.ForceUnloadTaskQueuePartitionRequest,
2544 > ) (*matchingservice.ForceUnloadTaskQueuePartitionResponse, error) { matching_engine.go
2545 > partition := tqid.PartitionFromPartitionProto(req.GetTaskQueuePartition(), req.GetNamespaceId())
2546 >
2547 > wasLoaded := e.unloadTaskQueuePartitionByKey(partition, nil, unloadCauseForce)
2548 > return &matchingservice.ForceUnloadTaskQueuePartitionResponse{WasLoaded: wasLoaded}, nil
2549 > }
2550
2551 func (e *matchingEngineImpl) UpdateTaskQueueUserData(ctx context.Context, request *matchingservice.UpdateTaskQueueUserDataRequest) (*matchingservice.UpdateTaskQueueUserDataResponse, error) {
2868 }
2869
2870 > func (e *matchingEngineImpl) ListNexusEndpoints(ctx context.Context, request *matchingservice.ListNexusEndpointsRequest) (*matchingservice.ListNexusEndpointsResponse, error) { matching_engine.go
2871 > lastKnownVersion := request.LastKnownTableVersion
2872 > // Read API, verify table ownership via membership.
2873 > isOwner, ownershipLostCh, err := e.checkNexusEndpointsOwnership()
2874 > if err != nil {
2875 e.logger.Error("Failed to check Nexus endpoints ownership", tag.Error(err))
2876 return nil, serviceerror.NewAbortedf("cannot verify ownership of Nexus endpoints table: %v", err)
2877 }
2878 > if !isOwner { matching_engine.go
2879 e.logger.Error("Matching node doesn't think it's the Nexus endpoints table owner", tag.Error(err))
2880 return nil, serviceerror.NewAborted("matching node doesn't think it's the Nexus endpoints table owner")
2881 }
2882
2883 > if request.Wait { matching_engine.go
2884 > if request.NextPageToken != nil {
2885 return nil, serviceerror.NewInvalidArgument("request Wait=true and NextPageToken!=nil on ListNexusEndpoints request. waiting is only allowed on first page")
2886 }
2887
2888 // if waiting, send request with unknown table version so we get the newest view of the table
2889 > request.LastKnownTableVersion = 0 matching_engine.go
2890 >
2891 > var cancel context.CancelFunc
2892 > ctx, cancel = contextutil.WithDeadlineBuffer(ctx, e.config.ListNexusEndpointsLongPollTimeout(), returnEmptyTaskTimeBudget)
2893 > defer cancel()
2894 }
2895
2896 > for { matching_engine.go
2897 > resp, tableVersionChanged, err := e.nexusEndpointClient.ListNexusEndpoints(ctx, request)
2898 > if err != nil {
2899 return resp, err
2900 }
2901
2902 > if request.Wait && lastKnownVersion == resp.TableVersion { matching_engine.go
2903 > // long-poll: wait for data to change/appear
2904 > select {
2905 case <-ownershipLostCh:
2906 return nil, serviceerror.NewAborted("Nexus endpoints table ownership lost")
2907 > case <-ctx.Done(): matching_engine.go
2908 > return resp, nil
2909 case <-tableVersionChanged:
2910 continue
2912 }
2913
2914 > return resp, err matching_engine.go
2915 }
2916 }
2917
2918 > func (e *matchingEngineImpl) checkNexusEndpointsOwnership() (bool, <-chan struct{}, error) { matching_engine.go
2919 > // Get the channel before checking the condition to prevent the channel from being closed while we're running this
2920 > // check.
2921 > ch := e.nexusEndpointsOwnershipLostCh.Load().(chan struct{}) //nolint:revive // type is always chan struct{}
2922 > self := e.hostInfoProvider.HostInfo().Identity()
2923 > owner, err := e.serviceResolver.Lookup(nexusEndpointsTablePartitionRoutingKey)
2924 > if err != nil {
2925 return false, nil, fmt.Errorf("cannot resolve Nexus endpoints partition owner: %w", err)
2926 }
2927 > return owner.Identity() == self, ch, nil matching_engine.go
2928 }
2929
2930 > func (e *matchingEngineImpl) notifyNexusEndpointsOwnershipChange() { matching_engine.go
2931 > // We don't care about the channel returned here. This method is ensured to only be called from the single
2932 > // watchMembership method and is the only way the channel may be replaced.
2933 > isOwner, _, err := e.checkNexusEndpointsOwnership()
2934 > if err != nil {
2935 e.logger.Error("Failed to check Nexus endpoints ownership", tag.Error(err))
2936 return
2937 }
2938 > if !isOwner { matching_engine.go
2939 close(e.nexusEndpointsOwnershipLostCh.Swap(make(chan struct{})).(chan struct{})) //nolint:revive // type is always chan struct{}
2940 }
2941 > e.nexusEndpointClient.notifyOwnershipChanged(isOwner) matching_engine.go
2942 }
2943
3009 partition tqid.Partition,
3010 pollMetadata *pollMetadata,
3011 > ) (*internalTask, bool, error) { matching_engine.go
3012 > pm, _, err := e.getTaskQueuePartitionManager(ctx, partition, true, loadCausePoll)
3013 > if err != nil {
3014 > return nil, false, err matching_engine.go
3015 > }
3016
3017 > pollMetadata.localPollStartTime = e.timeSource.Now() matching_engine.go
3018 >
3019 > // We need to set a shorter timeout than the original ctx; otherwise, by the time ctx deadline is
3020 > // reached, instead of emptyTask, context timeout error is returned to the frontend by the rpc stack,
3021 > // which counts against our SLO. By shortening the timeout by a very small amount, the emptyTask can be
3022 > // returned to the handler before a context timeout error is generated.
3023 > workerInstanceKey := pollMetadata.workerInstanceKey
3024 > if workerInstanceKey != "" && e.shutdownWorkers.Get(workerInstanceKey) != nil {
3025 e.logger.Info("Rejecting poll from recently-shutdown worker",
3026 tag.WorkflowNamespaceID(partition.NamespaceId()),
3035 // times across pollers and prevent thundering herd reconnects. Jitter is capped so the
3036 // interval never falls below forwardedPollMinInterval.
3037 > longPollInterval := pm.LongPollExpirationInterval() matching_engine.go
3038 > if pollMetadata.forwardedFrom == "" {
3039 > jitterMax := time.Duration(float64(longPollInterval) * forwardedPollJitterRatio) matching_engine.go
3040 > if longPollInterval-jitterMax < forwardedPollMinInterval {
3041 jitterMax = longPollInterval - forwardedPollMinInterval
3042 }
3043 > if jitterMax > 0 { matching_engine.go
3044 > longPollInterval -= backoff.FullJitter(jitterMax) matching_engine.go
3045 > }
3046 }
3047 > ctx, cancel := contextutil.WithDeadlineBuffer(ctx, longPollInterval, returnEmptyTaskTimeBudget) matching_engine.go
3048 > defer cancel()
3049 >
3050 > if pollerID, ok := ctx.Value(pollerIDKey).(string); ok && pollerID != "" {
3051 > e.outstandingPollers.Set(pollerID, cancel) matching_engine.go
3052 >
3053 > // Also track by worker instance key for bulk cancellation during shutdown.
3054 > // Use UUID (not pollerID) because pollerID is reused when forwarded.
3055 > pollerTrackerKey := uuid.NewString()
3056 > if workerInstanceKey != "" {
3057 > e.workerInstancePollers.Add(workerInstanceKey, pollerTrackerKey, cancel) matching_engine.go
3058 > }
3059
3060 > defer func() { matching_engine.go
3061 > e.outstandingPollers.Delete(pollerID)
3062 > if workerInstanceKey != "" {
3063 > e.workerInstancePollers.Remove(workerInstanceKey, pollerTrackerKey) matching_engine.go
3064 > }
3065 }()
3066 }
3067 > return pm.PollTask(ctx, pollMetadata) matching_engine.go
3068 }
3069
3090 namespaceName string,
3091 pollMetadata *pollMetadata,
3092 > ) { matching_engine.go
3093 > tqName := partition.TaskQueue().Name()
3094 > taskType := partition.TaskType()
3095 >
3096 > if !e.config.EmitTaskDispatchLatencyAtPoll(namespaceName, tqName, taskType) {
3097 return
3098 }
3099
3100 > taskCreateTime := task.getCreateTime() matching_engine.go
3101 > if taskCreateTime == nil {
3102 return
3103 }
3105 // Determine origin partition: for forwarded tasks use the origin partition from
3106 // forward info; for local tasks use the current partition.
3107 > originPartition := partition matching_engine.go
3108 > if task.isForwarded() && task.forwardInfo.GetOriginPartition() != "" {
3109 o, err := tqid.NormalPartitionFromRpcName(task.forwardInfo.GetOriginPartition(), namespaceID, taskType)
3110 if err == nil {
3113 }
3114
3115 > workerVersion := worker_versioning.WorkerDeploymentVersionToStringV32(worker_versioning.DeploymentVersionFromOptions(pollMetadata.deploymentOptions)) matching_engine.go
3116 >
3117 > handler := metrics.GetPerTaskQueuePartitionIDScope(
3118 > e.metricsHandler,
3119 > namespaceName,
3120 > originPartition,
3121 > e.config.BreakdownMetricsByTaskQueue(namespaceName, tqName, taskType),
3122 > e.config.BreakdownMetricsByPartition(namespaceName, tqName, taskType),
3123 > )
3124 >
3125 > metrics.TaskDispatchLatencyPerTaskQueue.With(handler).Record(
3126 > time.Since(timestamp.TimeValue(taskCreateTime)),
3127 > metrics.TaskSourceTag(task.source),
3128 > metrics.ForwardedTag(task.isForwarded()),
3129 > metrics.MatchingTaskPriorityTag(task.getPriority().GetPriorityKey()),
3130 > metrics.WorkerVersionTag(workerVersion, e.config.BreakdownMetricsByBuildID(namespaceName, tqName, taskType)),
3131 > )
3132 }
3133
3135 // partitions map), then does nothing.
3136 // partitions map), unloadPM.Stop(...) is still called.
3137 > func (e *matchingEngineImpl) unloadTaskQueuePartition(unloadPM taskQueuePartitionManager, unloadCause unloadCause) { matching_engine.go
3138 > e.unloadTaskQueuePartitionByKey(unloadPM.Partition(), unloadPM, unloadCause)
3139 > }
3140
3141 // Unloads a task queue partition by id. If unloadPM is given and the loaded partition for queueID does not match
3146 unloadPM taskQueuePartitionManager,
3147 unloadCause unloadCause,
3148 > ) bool { matching_engine.go
3149 > key := partition.Key()
3150 > e.partitionsLock.Lock()
3151 > foundTQM, ok := e.partitions[key]
3152 > if !ok || (unloadPM != nil && foundTQM != unloadPM) {
3153 > e.partitionsLock.Unlock() matching_engine.go
3154 > return false
3155 > }
3156 > delete(e.partitions, key) matching_engine.go
3157 > e.partitionsLock.Unlock()
3158 > foundTQM.Stop(unloadCause)
3159 > return true
3160 }
3161
3166 version PhysicalTaskQueueVersion,
3167 delta int,
3168 > ) { matching_engine.go
3169 > // calculating versioned to be one of: “unversioned” or "buildId” or “versionSet”
3170 > versioned := "unversioned"
3171 > if dep := version.Deployment(); dep != nil {
3172 versioned = "deployment"
3173 > } else if buildID := version.BuildId(); buildID != "" { matching_engine.go
3174 versioned = "buildId"
3175 > } else if versionSet := version.VersionSet(); versionSet != "" { matching_engine.go
3176 versioned = "versionSet"
3177 }
3178
3179 > physicalTaskQueueParameters := taskQueueCounterKey{ matching_engine.go
3180 > namespaceID: partition.NamespaceId(),
3181 > taskType: partition.TaskType(),
3182 > partitionType: partition.Kind(),
3183 > versioned: versioned,
3184 > }
3185 >
3186 > e.gaugeMetrics.lock.Lock()
3187 > e.gaugeMetrics.loadedPhysicalTaskQueueCount[physicalTaskQueueParameters] += delta
3188 > loadedPhysicalTaskQueueCounter := e.gaugeMetrics.loadedPhysicalTaskQueueCount[physicalTaskQueueParameters]
3189 > e.gaugeMetrics.lock.Unlock()
3190 >
3191 > metrics.LoadedPhysicalTaskQueueGauge.With(
3192 > metrics.GetPerTaskQueuePartitionTypeScope(
3193 > e.metricsHandler,
3194 > ns.Name().String(),
3195 > partition,
3196 > // TODO: Track counters per TQ name so we can honor pm.config.BreakdownMetricsByTaskQueue(),
3197 > false,
3198 > )).Record(
3199 > float64(loadedPhysicalTaskQueueCounter),
3200 > metrics.VersionedTag(versioned),
3201 > )
3202 }
3203
3208 partition tqid.Partition,
3209 delta int,
3210 > ) { matching_engine.go
3211 > // each metric shall be accessed based on the mentioned parameters
3212 > taskQueueFamilyParameters := taskQueueCounterKey{
3213 > namespaceID: partition.NamespaceId(),
3214 > }
3215 >
3216 > taskQueueParameters := taskQueueCounterKey{
3217 > namespaceID: partition.NamespaceId(),
3218 > taskType: partition.TaskType(),
3219 > }
3220 >
3221 > taskQueuePartitionParameters := taskQueueCounterKey{
3222 > namespaceID: partition.NamespaceId(),
3223 > taskType: partition.TaskType(),
3224 > partitionType: partition.Kind(),
3225 > }
3226 >
3227 > rootPartition := partition.IsRoot()
3228 > e.gaugeMetrics.lock.Lock()
3229 >
3230 > loadedTaskQueueFamilyCounter, loadedTaskQueueCounter, loadedTaskQueuePartitionCounter :=
3231 > e.gaugeMetrics.loadedTaskQueueFamilyCount[taskQueueFamilyParameters], e.gaugeMetrics.loadedTaskQueueCount[taskQueueParameters],
3232 > e.gaugeMetrics.loadedTaskQueuePartitionCount[taskQueuePartitionParameters]
3233 >
3234 > loadedTaskQueuePartitionCounter += delta
3235 > e.gaugeMetrics.loadedTaskQueuePartitionCount[taskQueuePartitionParameters] = loadedTaskQueuePartitionCounter
3236 > if rootPartition {
3237 > loadedTaskQueueCounter += delta matching_engine.go
3238 > e.gaugeMetrics.loadedTaskQueueCount[taskQueueParameters] = loadedTaskQueueCounter
3239 > if partition.TaskType() == enumspb.TASK_QUEUE_TYPE_WORKFLOW {
3240 > loadedTaskQueueFamilyCounter += delta matching_engine.go
3241 > e.gaugeMetrics.loadedTaskQueueFamilyCount[taskQueueFamilyParameters] = loadedTaskQueueFamilyCounter
3242 > }
3243 }
3244 > e.gaugeMetrics.lock.Unlock() matching_engine.go
3245 >
3246 > nsName := ns.Name().String()
3247 >
3248 > e.metricsHandler.Gauge(metrics.LoadedTaskQueueFamilyGauge.Name()).Record(
3249 > float64(loadedTaskQueueFamilyCounter),
3250 > metrics.NamespaceTag(nsName),
3251 > )
3252 >
3253 > metrics.LoadedTaskQueueGauge.With(e.metricsHandler).Record(
3254 > float64(loadedTaskQueueCounter),
3255 > metrics.NamespaceTag(nsName),
3256 > metrics.TaskQueueTypeTag(taskQueueParameters.taskType),
3257 > )
3258 >
3259 > taggedHandler := metrics.GetPerTaskQueuePartitionTypeScope(
3260 > e.metricsHandler,
3261 > nsName,
3262 > partition,
3263 > // TODO: Track counters per TQ name so we can honor pm.config.BreakdownMetricsByTaskQueue(),
3264 > false,
3265 > )
3266 > metrics.LoadedTaskQueuePartitionGauge.With(taggedHandler).Record(float64(loadedTaskQueuePartitionCounter))
3267 }
3268
3272 recordStartResp *historyservice.RecordWorkflowTaskStartedResponse,
3273 metricsHandler metrics.Handler,
3274 > ) *matchingservice.PollWorkflowTaskQueueResponseWithRawHistory { matching_engine.go
3275 >
3276 > var serializedToken []byte
3277 > if task.isQuery() {
3278 // for a query task
3279 queryRequest := task.query.request
3284 }
3285 serializedToken, _ = e.tokenSerializer.SerializeQueryTaskToken(queryTaskToken)
3286 > } else { matching_engine.go
3287 > taskToken := tasktoken.NewWorkflowTaskToken(
3288 > task.event.Data.GetNamespaceId(),
3289 > task.event.Data.GetWorkflowId(),
3290 > task.event.Data.GetRunId(),
3291 > recordStartResp.GetScheduledEventId(),
3292 > recordStartResp.GetStartedEventId(),
3293 > recordStartResp.GetStartedTime(),
3294 > recordStartResp.GetAttempt(),
3295 > recordStartResp.GetClock(),
3296 > recordStartResp.GetVersion(),
3297 > )
3298 > serializedToken, _ = e.tokenSerializer.Serialize(taskToken)
3299 > if task.responseC == nil {
3300 > ct := timestamp.TimeValue(task.event.Data.CreateTime) matching_engine.go
3301 > metrics.AsyncMatchLatencyPerTaskQueue.With(metricsHandler).Record(time.Since(ct))
3302 > }
3303 }
3304
3305 > response := common.CreateMatchingPollWorkflowTaskQueueResponse( matching_engine.go
3306 > recordStartResp,
3307 > task.workflowExecution(),
3308 > serializedToken)
3309 >
3310 > if task.query != nil {
3311 response.Query = task.query.request.QueryRequest.Query
3312 }
3313 > if task.backlogCountHint != nil { matching_engine.go
3314 > response.BacklogCountHint = task.backlogCountHint()
3315 > }
3316 > response.PollerScalingDecision = task.pollerScalingDecision
3317 > return response
3318 }
3319
3445 pollReq *workflowservice.PollWorkflowTaskQueueRequest,
3446 task *internalTask,
3447 > ) (*historyservice.RecordWorkflowTaskStartedResponse, error) { matching_engine.go
3448 >
3449 > metrics.OperationCounter.With(e.metricsHandler).Record(
3450 > 1,
3451 > metrics.OperationTag("RecordWorkflowTaskStarted"),
3452 > metrics.NamespaceTag(pollReq.Namespace),
3453 > metrics.TaskTypeTag(""), // Added to make tags consistent with history task executor.
3454 > )
3455 > if e.rateLimiter != nil {
3456 err := e.rateLimiter.Wait(ctx, quotas.Request{
3457 API: "RecordWorkflowTaskStarted",
3465 }
3466
3467 > ctx, cancel := newRecordTaskStartedContext(ctx, task) matching_engine.go
3468 > defer cancel()
3469 >
3470 > sentTargetVersion := worker_versioning.ExternalWorkerDeploymentVersionFromVersion(task.targetWorkerDeploymentVersion)
3471 >
3472 > recordStartedRequest := &historyservice.RecordWorkflowTaskStartedRequest{
3473 > NamespaceId: task.event.Data.GetNamespaceId(),
3474 > WorkflowExecution: task.workflowExecution(),
3475 > ScheduledEventId: task.event.Data.GetScheduledEventId(),
3476 > Clock: task.event.Data.GetClock(),
3477 > RequestId: uuid.NewString(),
3478 > PollRequest: pollReq,
3479 > BuildIdRedirectInfo: task.redirectInfo,
3480 > // TODO: stop sending ScheduledDeployment. [cleanup-old-wv]
3481 > ScheduledDeployment: worker_versioning.DirectiveDeployment(task.event.Data.VersionDirective),
3482 > VersionDirective: task.event.Data.VersionDirective,
3483 > Stamp: task.event.Data.GetStamp(),
3484 > TaskDispatchRevisionNumber: task.taskDispatchRevisionNumber,
3485 > TargetDeploymentVersion: sentTargetVersion,
3486 > }
3487 >
3488 > resp, err := e.historyClient.RecordWorkflowTaskStarted(ctx, recordStartedRequest)
3489 > if err != nil {
3490 return nil, err
3491 }
3501 // 2. RawHistory (old path) - auto-deserialized to *History by gRPC wire compatibility
3502 // 3. History - use directly (raw history disabled)
3503 > if len(resp.RawHistoryBytes) > 0 { matching_engine.go
3504 // New path: raw bytes in field 21, pass through to frontend without processing.
3505 // Search attributes will be processed by frontend.
3506 > } else if resp.RawHistory != nil { //nolint:staticcheck matching_engine.go
3507 // Old path: history service using deprecated RawHistory field (field 20).
3508 // The gRPC client auto-deserializes repeated bytes into *History via wire compatibility.
3519 // If neither RawHistoryBytes nor RawHistory is set, resp.History should already have the data.
3520
3521 > return resp, nil matching_engine.go
3522 }
3523
3577 parentCtx context.Context,
3578 task *internalTask,
3579 > ) (context.Context, context.CancelFunc) { matching_engine.go
3580 > timeout := recordTaskStartedDefaultTimeout
3581 > if task.isSyncMatchTask() {
3582 timeout = recordTaskStartedSyncMatchTimeout
3583 }
3584
3585 > return context.WithTimeout(parentCtx, timeout) matching_engine.go
3586 }
3587
3816 }
3817
3818 > func (e *matchingEngineImpl) newTaskTracker() *taskTracker { matching_engine.go
3819 > return newTaskTracker(e.timeSource, 5*time.Second, 30*time.Second)
3820 > }
3821
3822 // migrateOldFormatVersions moves versions present in the given deployment from the
go.temporal.io/server/service/frontend/fx.go 538 covered LOC · 55 ranges

Open complete file

110 fx.Provide(AuthorizationInterceptorProvider),
111 fx.Provide(NamespaceCheckerProvider),
112 > fx.Provide(func(so GrpcServerOptions) *grpc.Server { return grpc.NewServer(so.Options...) }), fx.go
113 fx.Provide(callbackValidatorProvider),
114 fx.Provide(HandlerProvider),
154 metricsHandler metrics.Handler,
155 membershipMonitor membership.Monitor,
156 > ) *Service { fx.go
157 > return NewService(
158 > serviceConfig,
159 > server,
160 > healthServer,
161 > httpAPIServer,
162 > handler,
163 > adminHandler,
164 > operatorHandler,
165 > versionChecker,
166 > visibilityMgr,
167 > logger,
168 > grpcListener,
169 > metricsHandler,
170 > membershipMonitor,
171 > )
172 > }
173
174 // GrpcServerOptions are the options to build the frontend gRPC server along
189 audienceGetter authorization.JWTAudienceMapper,
190 dc *dynamicconfig.Collection,
191 > ) *authorization.Interceptor { fx.go
192 > return authorization.NewInterceptor(
193 > claimMapper,
194 > authorizer,
195 > metricsHandler,
196 > logger,
197 > namespaceChecker,
198 > audienceGetter,
199 > cfg.Global.Authorization.AuthHeaderName,
200 > cfg.Global.Authorization.AuthExtraHeaderName,
201 > serviceConfig.ExposeAuthorizerErrors,
202 > dynamicconfig.EnableCrossNamespaceCommands.Get(dc),
203 > dynamicconfig.EnablePrincipalPropagation.Get(dc),
204 > dynamicconfig.DisableStreamingAuthorizer.Get(dc),
205 > )
206 > }
207
208 > func NamespaceCheckerProvider(registry namespace.Registry) authorization.NamespaceChecker { fx.go
209 > return &namespaceChecker{r: registry}
210 > }
211
212 func (n *namespaceChecker) Exists(name namespace.Name) error {
249 customStreamInterceptors []grpc.StreamServerInterceptor,
250 metricsHandler metrics.Handler,
251 > ) GrpcServerOptions { fx.go
252 > kep := keepalive.EnforcementPolicy{
253 > MinTime: serviceConfig.KeepAliveMinTime(),
254 > PermitWithoutStream: serviceConfig.KeepAlivePermitWithoutStream(),
255 > }
256 > kp := keepalive.ServerParameters{
257 > MaxConnectionIdle: serviceConfig.KeepAliveMaxConnectionIdle(),
258 > MaxConnectionAge: serviceConfig.KeepAliveMaxConnectionAge(),
259 > MaxConnectionAgeGrace: serviceConfig.KeepAliveMaxConnectionAgeGrace(),
260 > Time: serviceConfig.KeepAliveTime(),
261 > Timeout: serviceConfig.KeepAliveTimeout(),
262 > }
263 > var grpcServerOptions []grpc.ServerOption
264 > var err error
265 > switch serviceName {
266 > case primitives.FrontendService:
267 > grpcServerOptions, err = rpcFactory.GetFrontendGRPCServerOptions()
268 case primitives.InternalFrontendService:
269 grpcServerOptions, err = rpcFactory.GetInternodeGRPCServerOptions()
271 err = fmt.Errorf("unexpected frontend service name %q", serviceName)
272 }
273 > if err != nil { fx.go
274 logger.Fatal("creating gRPC server options failed", tag.Error(err))
275 }
276 > unaryInterceptors := []grpc.UnaryServerInterceptor{ fx.go
277 > // Order of interceptors is important
278 > // Mask error interceptor should be the most outer interceptor since it handle the errors format
279 > // Service Error Interceptor should be the next most outer interceptor on error handling
280 > maskInternalErrorDetailsInterceptor.Intercept,
281 > serviceErrorInterceptor.Intercept,
282 > interceptor.NewFrontendServiceErrorInterceptor(logger),
283 > // BusinessID interceptor extracts business ID and adds it to context for use, must be before any interceptor that touches namespaces (namespaceValidator, handoverInterceptor)
284 > businessIDInterceptor.Intercept,
285 > namespaceValidatorInterceptor.NamespaceValidateIntercept,
286 > namespaceLogInterceptor.Intercept, // TODO: Deprecate this with a outer custom interceptor
287 > metrics.NewServerMetricsContextInjectorInterceptor(),
288 > authInterceptor.Intercept,
289 > // Handover interceptor has to above redirection because the request will route to the correct cluster after handover completed.
290 > // And retry cannot be performed before customInterceptors.
291 > namespaceHandoverInterceptor.Intercept,
292 > redirectionInterceptor.Intercept,
293 > // Telemetry interceptor must be after redirection to ensure metrics are recorded in the correct cluster
294 > telemetryInterceptor.UnaryIntercept,
295 > healthInterceptor.Intercept,
296 > namespaceValidatorInterceptor.StateValidationIntercept,
297 > namespaceCountLimiterInterceptor.Intercept,
298 > namespaceRateLimiterInterceptor.Intercept,
299 > rateLimitInterceptor.Intercept,
300 > sdkVersionInterceptor.Intercept,
301 > callerInfoInterceptor.Intercept,
302 > slowRequestLoggerInterceptor.Intercept,
303 > chasmRequestVisibilityInterceptor.Intercept,
304 > contextMetadataInterceptor.Intercept,
305 > }
306 > if len(customInterceptors) > 0 {
307 > // TODO: Deprecate WithChainedFrontendGrpcInterceptors and provide a inner custom interceptor fx.go
308 > unaryInterceptors = append(unaryInterceptors, customInterceptors...)
309 > }
310 // retry interceptor should be the most inner interceptor
311 > unaryInterceptors = append(unaryInterceptors, retryableInterceptor.Intercept) fx.go
312 >
313 > streamInterceptor := []grpc.StreamServerInterceptor{
314 > authInterceptor.InterceptStream,
315 > telemetryInterceptor.StreamIntercept,
316 > }
317 > if len(customStreamInterceptors) > 0 {
318 streamInterceptor = append(streamInterceptor, customStreamInterceptors...)
319 }
320
321 > grpcServerOptions = append( fx.go
322 > grpcServerOptions,
323 > grpc.KeepaliveParams(kp),
324 > grpc.KeepaliveEnforcementPolicy(kep),
325 > grpc.ChainUnaryInterceptor(unaryInterceptors...),
326 > grpc.ChainStreamInterceptor(streamInterceptor...),
327 > )
328 >
329 > multiStats := rpc.MultiStatsHandler{}
330 > if traceStatsHandler != nil {
331 multiStats = append(multiStats, traceStatsHandler)
332 }
333 > if metricsStatsHandler != nil { fx.go
334 > multiStats = append(multiStats, metricsStatsHandler)
335 > }
336 > if len(multiStats) > 0 {
337 > grpcServerOptions = append(grpcServerOptions, grpc.StatsHandler(multiStats))
338 > }
339 > return GrpcServerOptions{Options: grpcServerOptions, UnaryInterceptors: unaryInterceptors}
340 }
341
343 dc *dynamicconfig.Collection,
344 persistenceConfig config.Persistence,
345 > ) *Config { fx.go
346 > return NewConfig(
347 > dc,
348 > persistenceConfig.NumHistoryShards,
349 > )
350 > }
351
352 func ServiceErrorInterceptorProvider(
353 dc *dynamicconfig.Collection,
354 > ) *interceptor.ServiceErrorInterceptor { fx.go
355 > return interceptor.NewServiceErrorInterceptor(
356 > dynamicconfig.MaxServiceErrorMessageLength.Get(dc),
357 > )
358 > }
359
360 > func ThrottledLoggerRpsFnProvider(serviceConfig *Config) resource.ThrottledLoggerRpsFn { fx.go
361 > return func() float64 { return float64(serviceConfig.ThrottledLogRPS()) }
362 }
363
365 namespaceLogger resource.NamespaceLogger,
366 namespaceRegistry namespace.Registry,
367 > ) *interceptor.NamespaceLogInterceptor { fx.go
368 > return interceptor.NewNamespaceLogInterceptor(
369 > namespaceRegistry,
370 > namespaceLogger)
371 > }
372
373 > func RetryableInterceptorProvider() *interceptor.RetryableInterceptor { fx.go
374 > return interceptor.NewRetryableInterceptor(
375 > common.CreateFrontendHandlerRetryPolicy(),
376 > common.IsServiceHandlerRetryableError,
377 > )
378 > }
379
380 func RedirectionInterceptorProvider(
387 timeSource clock.TimeSource,
388 clusterMetadata cluster.Metadata,
389 > ) *interceptor.Redirection { fx.go
390 > return interceptor.NewRedirection(
391 > configuration.EnableNamespaceNotActiveAutoForwarding,
392 > configuration.ForceNamespaceSelectedAPIAutoForwarding,
393 > namespaceCache,
394 > policy,
395 > logger,
396 > clientBean,
397 > metricsHandler,
398 > timeSource,
399 > clusterMetadata,
400 > )
401 > }
402
403 func BusinessIDInterceptorProvider(
404 extractor interceptor.RoutingKeyExtractor,
405 logger log.Logger,
406 > ) *interceptor.RoutingKeyInterceptor { fx.go
407 > return interceptor.NewRoutingKeyInterceptor(
408 > []interceptor.RoutingKeyExtractorFunc{
409 > interceptor.WorkflowServiceExtractor(extractor),
410 > },
411 > logger,
412 > )
413 > }
414
415 type NamespaceHandoverInterceptorParams struct {
426 func NamespaceHandoverInterceptorProvider(
427 params NamespaceHandoverInterceptorParams,
428 > ) *interceptor.NamespaceHandoverInterceptor { fx.go
429 > return interceptor.NewNamespaceHandoverInterceptor(
430 > params.DynamicConfig,
431 > params.NamespaceRegistry,
432 > params.MetricsHandler,
433 > params.Logger,
434 > params.TimeSource,
435 > params.RequestErrorHandler,
436 > params.AdditionalAllowedMethodsDuringHandover,
437 > )
438 > }
439
440 func ErrorHandlerProvider(
441 logger log.Logger,
442 serviceConfig *Config,
443 > ) *interceptor.RequestErrorHandler { fx.go
444 > return interceptor.NewRequestErrorHandler(
445 > logger,
446 > serviceConfig.LogAllReqErrors,
447 > )
448 > }
449
450 func TelemetryInterceptorProvider(
454 serviceConfig *Config,
455 requestErrorHandler *interceptor.RequestErrorHandler,
456 > ) *interceptor.TelemetryInterceptor { fx.go
457 > return interceptor.NewTelemetryInterceptor(
458 > namespaceRegistry,
459 > metricsHandler,
460 > logger,
461 > serviceConfig.LogAllReqErrors,
462 > requestErrorHandler,
463 > )
464 > }
465
466 > func getRateFnWithMetrics(rateFn quotas.RateFn, handler metrics.Handler) quotas.RateFn { fx.go
467 > return func() float64 {
468 > rate := rateFn()
469 > metrics.HostRPSLimit.With(handler).Record(rate)
470 > return rate
471 > }
472 }
473
477 handler metrics.Handler,
478 logger log.SnTaggedLogger,
479 > ) *interceptor.RateLimitInterceptor { fx.go
480 > rateFn := calculator.NewLoggedCalculator(
481 > calculator.ClusterAwareQuotaCalculator{
482 > MemberCounter: frontendServiceResolver,
483 > PerInstanceQuota: serviceConfig.RPS,
484 > GlobalQuota: serviceConfig.GlobalRPS,
485 > },
486 > log.With(logger, tag.ComponentRPCHandler, tag.ScopeHost),
487 > ).GetQuota
488 > rateFnWithMetrics := getRateFnWithMetrics(rateFn, handler)
489 >
490 > namespaceReplicationInducingRateFn := func() float64 {
491 > return float64(serviceConfig.NamespaceReplicationInducingAPIsRPS())
492 > }
493
494 > return interceptor.NewRateLimitInterceptor( fx.go
495 > configs.NewRequestToRateLimiter(
496 > quotas.NewDefaultIncomingRateBurst(rateFnWithMetrics),
497 > quotas.NewDefaultIncomingRateBurst(rateFn),
498 > quotas.NewDefaultIncomingRateBurst(namespaceReplicationInducingRateFn),
499 > serviceConfig.OperatorRPSRatio,
500 > ),
501 > map[string]int{
502 > healthpb.Health_Check_FullMethodName: 0, // exclude health check requests from rate limiting.
503 > adminservice.AdminService_DeepHealthCheck_FullMethodName: 0, // exclude deep health check requests from rate limiting.
504 > },
505 > )
506 }
507
509 logger log.Logger,
510 dc *dynamicconfig.Collection,
511 > ) *interceptor.ContextMetadataInterceptor { fx.go
512 > setTrailer := dynamicconfig.FrontendContextMetadataSetTrailer.Get(dc)()
513 > return interceptor.NewContextMetadataInterceptor(setTrailer, logger)
514 > }
515
516 func MaskInternalErrorDetailsInterceptorProvider(
518 serviceConfig *Config,
519 namespaceRegistry namespace.Registry,
520 > ) *interceptor.MaskInternalErrorDetailsInterceptor { fx.go
521 > return interceptor.NewMaskInternalErrorDetailsInterceptor(
522 > serviceConfig.MaskInternalErrorDetails, namespaceRegistry, logger,
523 > )
524 > }
525
526 func NamespaceRateLimitInterceptorProvider(
531 metricsHandler metrics.Handler,
532 logger log.SnTaggedLogger,
533 > ) interceptor.NamespaceRateLimitInterceptor { fx.go
534 > var globalNamespaceRPS, globalNamespaceVisibilityRPS, globalNamespaceNamespaceReplicationInducingAPIsRPS dynamicconfig.IntPropertyFnWithNamespaceFilter
535 >
536 > switch serviceName {
537 > case primitives.FrontendService:
538 > globalNamespaceRPS = serviceConfig.GlobalNamespaceRPS
539 > globalNamespaceVisibilityRPS = serviceConfig.GlobalNamespaceVisibilityRPS
540 > globalNamespaceNamespaceReplicationInducingAPIsRPS = serviceConfig.GlobalNamespaceNamespaceReplicationInducingAPIsRPS
541 case primitives.InternalFrontendService:
542 globalNamespaceRPS = serviceConfig.InternalFEGlobalNamespaceRPS
548 }
549
550 > namespaceRateFn := calculator.NewLoggedNamespaceCalculator( fx.go
551 > calculator.ClusterAwareNamespaceQuotaCalculator{
552 > MemberCounter: frontendServiceResolver,
553 > PerInstanceQuota: serviceConfig.MaxNamespaceRPSPerInstance,
554 > GlobalQuota: globalNamespaceRPS,
555 > },
556 > log.With(logger, tag.ComponentRPCHandler, tag.ScopeNamespace),
557 > ).GetQuota
558 > visibilityRateFn := calculator.NewLoggedNamespaceCalculator(
559 > calculator.ClusterAwareNamespaceQuotaCalculator{
560 > MemberCounter: frontendServiceResolver,
561 > PerInstanceQuota: serviceConfig.MaxNamespaceVisibilityRPSPerInstance,
562 > GlobalQuota: globalNamespaceVisibilityRPS,
563 > },
564 > log.With(logger, tag.ComponentVisibilityHandler, tag.ScopeNamespace),
565 > ).GetQuota
566 > namespaceReplicationInducingRateFn := calculator.NewLoggedNamespaceCalculator(
567 > calculator.ClusterAwareNamespaceQuotaCalculator{
568 > MemberCounter: frontendServiceResolver,
569 > PerInstanceQuota: serviceConfig.MaxNamespaceNamespaceReplicationInducingAPIsRPSPerInstance,
570 > GlobalQuota: globalNamespaceNamespaceReplicationInducingAPIsRPS,
571 > },
572 > log.With(logger, tag.ComponentNamespaceReplication, tag.ScopeNamespace),
573 > ).GetQuota
574 > namespaceRateLimiter := quotas.NewNamespaceRequestRateLimiter(
575 > func(req quotas.Request) quotas.RequestRateLimiter {
576 > return configs.NewRequestToRateLimiter( fx.go
577 > quotas.NewNamespaceRateBurst(
578 > req.Caller,
579 > namespaceRateFn,
580 > quotas.NamespaceBurstRatioFn(serviceConfig.MaxNamespaceBurstRatioPerInstance),
581 > ),
582 > quotas.NewNamespaceRateBurst(
583 > req.Caller,
584 > visibilityRateFn,
585 > quotas.NamespaceBurstRatioFn(serviceConfig.MaxNamespaceVisibilityBurstRatioPerInstance),
586 > ),
587 > quotas.NewNamespaceRateBurst(
588 > req.Caller,
589 > namespaceReplicationInducingRateFn,
590 > quotas.NamespaceBurstRatioFn(serviceConfig.MaxNamespaceNamespaceReplicationInducingAPIsBurstRatioPerInstance),
591 > ),
592 > serviceConfig.OperatorRPSRatio,
593 > )
594 > },
595 )
596 > return interceptor.NewNamespaceRateLimitInterceptor( fx.go
597 > namespaceRegistry,
598 > namespaceRateLimiter,
599 > map[string]int{}, // no token overrides
600 > configs.PollTaskAPISet,
601 > serviceConfig.PollWaitForNamespaceRateLimitToken,
602 > metricsHandler,
603 > )
604 }
605
609 serviceResolver membership.ServiceResolver,
610 logger log.SnTaggedLogger,
611 > ) *interceptor.ConcurrentRequestLimitInterceptor { fx.go
612 > return interceptor.NewConcurrentRequestLimitInterceptor(
613 > namespaceRegistry,
614 > serviceResolver,
615 > logger,
616 > serviceConfig.MaxConcurrentLongRunningRequestsPerInstance,
617 > serviceConfig.MaxGlobalConcurrentLongRunningRequests,
618 > configs.ExecutionAPICountLimitOverride,
619 > )
620 > }
621
622 type NamespaceValidatorInterceptorParams struct {
629 func NamespaceValidatorInterceptorProvider(
630 params NamespaceValidatorInterceptorParams,
631 > ) *interceptor.NamespaceValidatorInterceptor { fx.go
632 > return interceptor.NewNamespaceValidatorInterceptor(
633 > params.NamespaceRegistry,
634 > params.ServiceConfig.EnableTokenNamespaceEnforcement,
635 > params.ServiceConfig.MaxIDLengthLimit,
636 > params.AdditionalAllowedMethodsDuringHandover,
637 > )
638 > }
639
640 > func SDKVersionInterceptorProvider() *interceptor.SDKVersionInterceptor { fx.go
641 > return interceptor.NewSDKVersionInterceptor()
642 > }
643
644 func CallerInfoInterceptorProvider(
645 namespaceRegistry namespace.Registry,
646 > ) *interceptor.CallerInfoInterceptor { fx.go
647 > return interceptor.NewCallerInfoInterceptor(namespaceRegistry)
648 > }
649
650 func SlowRequestLoggerInterceptorProvider(
651 logger log.Logger,
652 dc *dynamicconfig.Collection,
653 > ) *interceptor.SlowRequestLoggerInterceptor { fx.go
654 > return interceptor.NewSlowRequestLoggerInterceptor(
655 > logger,
656 > dynamicconfig.SlowRequestLoggingThreshold.Get(dc),
657 > )
658 > }
659
660 func PersistenceRateLimitingParamsProvider(
662 persistenceLazyLoadedServiceResolver service.PersistenceLazyLoadedServiceResolver,
663 logger log.SnTaggedLogger,
664 > ) service.PersistenceRateLimitingParams { fx.go
665 > return service.NewPersistenceRateLimitingParams(
666 > serviceConfig.PersistenceMaxQPS,
667 > serviceConfig.PersistenceGlobalMaxQPS,
668 > serviceConfig.PersistenceNamespaceMaxQPS,
669 > serviceConfig.PersistenceGlobalNamespaceMaxQPS,
670 > serviceConfig.PersistencePerShardNamespaceMaxQPS,
671 > serviceConfig.OperatorRPSRatio,
672 > serviceConfig.PersistenceQPSBurstRatio,
673 > serviceConfig.PersistenceDynamicRateLimitingParams,
674 > persistenceLazyLoadedServiceResolver,
675 > logger,
676 > )
677 > }
678
679 func VisibilityManagerProvider(
689 chasmRegistry *chasm.Registry,
690 serializer serialization.Serializer,
691 > ) (manager.VisibilityManager, error) { fx.go
692 > return visibility.NewManager(
693 > *persistenceConfig,
694 > persistenceServiceResolver,
695 > customVisibilityStoreFactory,
696 > nil, // frontend visibility never write
697 > saProvider,
698 > searchAttributesMapperProvider,
699 > namespaceRegistry,
700 > chasmRegistry,
701 > serviceConfig.VisibilityPersistenceMaxReadQPS,
702 > serviceConfig.VisibilityPersistenceMaxWriteQPS,
703 > serviceConfig.OperatorRPSRatio,
704 > serviceConfig.VisibilityPersistenceSlowQueryThreshold,
705 > serviceConfig.EnableReadFromSecondaryVisibility,
706 > serviceConfig.VisibilityEnableShadowReadMode,
707 > dynamicconfig.GetStringPropertyFn(visibility.SecondaryVisibilityWritingModeOff), // frontend visibility never write
708 > serviceConfig.VisibilityDisableOrderByClause,
709 > serviceConfig.VisibilityEnableManualPagination,
710 > serviceConfig.VisibilityEnableUnifiedQueryConverter,
711 > metricsHandler,
712 > logger,
713 > serializer,
714 > )
715 > }
716
717 func FEReplicatorNamespaceReplicationQueueProvider(
718 namespaceReplicationQueue persistence.NamespaceReplicationQueue,
719 clusterMetadata cluster.Metadata,
720 > ) FEReplicatorNamespaceReplicationQueue { fx.go
721 > var replicatorNamespaceReplicationQueue persistence.NamespaceReplicationQueue
722 > if clusterMetadata.IsGlobalNamespaceEnabled() {
723 replicatorNamespaceReplicationQueue = namespaceReplicationQueue
724 }
725 > return replicatorNamespaceReplicationQueue fx.go
726 }
727
729 membershipMonitor membership.Monitor,
730 serviceName primitives.ServiceName,
731 > ) (membership.ServiceResolver, error) { fx.go
732 > return membershipMonitor.GetResolver(serviceName)
733 > }
734
735 func AdminHandlerProvider(
766 schedulerClient schedulerpb.SchedulerServiceClient,
767 namespaceDLQHandler nsreplication.DLQMessageHandler,
768 > ) *AdminHandler { fx.go
769 > args := NewAdminHandlerArgs{
770 > persistenceConfig,
771 > configuration,
772 > namespaceReplicationQueue,
773 > replicatorNamespaceReplicationQueue,
774 > visibilityMgr,
775 > logger,
776 > taskManager,
777 > fairTaskManager,
778 > persistenceExecutionManager,
779 > clusterMetadataManager,
780 > persistenceMetadataManager,
781 > clientFactory,
782 > clientBean,
783 > historyClient,
784 > sdkClientFactory,
785 > membershipMonitor,
786 > hostInfoProvider,
787 > metricsHandler,
788 > namespaceRegistry,
789 > saProvider,
790 > saManager,
791 > saMapperProvider,
792 > clusterMetadata,
793 > healthServer,
794 > eventSerializer,
795 > timeSource,
796 > chasmRegistry,
797 > namespaceDataMerger,
798 > schedulerClient,
799 > taskCategoryRegistry,
800 > matchingClient,
801 > }
802 > return NewAdminHandler(args, namespaceDLQHandler)
803 > }
804
805 // NamespaceDLQHandlerProvider provides the default namespace DLQ message handler.
812 logger log.SnTaggedLogger,
813 testHooks testhooks.TestHooks,
814 > ) nsreplication.DLQMessageHandler { fx.go
815 > taskExecutor := nsreplication.NewTaskExecutor(
816 > clusterMetadata.GetCurrentClusterName(),
817 > persistenceMetadataManager,
818 > namespaceDataMerger,
819 > namespaceAdmitter,
820 > logger,
821 > testHooks,
822 > )
823 > return nsreplication.NewDLQMessageHandler(
824 > taskExecutor,
825 > namespaceReplicationQueue,
826 > logger,
827 > )
828 > }
829
830 func OperatorHandlerProvider(
842 namespaceRegistry namespace.Registry,
843 nexusEndpointClient *NexusEndpointClient,
844 > ) *OperatorHandlerImpl { fx.go
845 > args := NewOperatorHandlerImplArgs{
846 > configuration,
847 > logger,
848 > sdkClientFactory,
849 > metricsHandler,
850 > visibilityMgr,
851 > saManager,
852 > healthServer,
853 > historyClient,
854 > clusterMetadataManager,
855 > clusterMetadata,
856 > clientFactory,
857 > namespaceRegistry,
858 > nexusEndpointClient,
859 > }
860 > return NewOperatorHandlerImpl(args)
861 > }
862
863 // callbackValidatorProvider creates a callback Validator using the production dynamic config keys
864 // so that existing operator configurations (callback.allowedAddresses) are honored.
865 > func callbackValidatorProvider(dc *dynamicconfig.Collection) callback.Validator { fx.go
866 > return callback.NewValidator(
867 > callback.MaxPerExecution.Get(dc),
868 > dynamicconfig.FrontendCallbackURLMaxLength.Get(dc),
869 > dynamicconfig.FrontendCallbackHeaderMaxSize.Get(dc),
870 > callback.AllowedAddresses.Get(dc),
871 > )
872 > }
873
874 func HandlerProvider(
911 registry *chasm.Registry,
912 frontendServiceResolver membership.ServiceResolver,
913 > ) Handler { fx.go
914 > workerDeploymentReadRateLimiter := configs.NewGlobalNamespaceRateLimiter(
915 > frontendServiceResolver,
916 > serviceConfig.GlobalWorkerDeploymentReadRPS,
917 > serviceConfig.GlobalWorkerDeploymentReadBurstRatio,
918 > log.With(logger, tag.ComponentRPCHandler, tag.ScopeNamespace),
919 > )
920 >
921 > wfHandler := NewWorkflowHandler(
922 > callbackValidator,
923 > serviceConfig,
924 > namespaceReplicationQueue,
925 > visibilityMgr,
926 > logger,
927 > throttledLogger,
928 > persistenceExecutionManager.GetName(),
929 > clusterMetadataManager,
930 > persistenceMetadataManager,
931 > historyClient,
932 > matchingClient,
933 > workerDeploymentStoreClient,
934 > schedulerClient,
935 > archiverProvider,
936 > payloadSerializer,
937 > namespaceRegistry,
938 > saMapperProvider,
939 > saProvider,
940 > saValidator,
941 > clusterMetadata,
942 > archivalMetadata,
943 > healthServer,
944 > timeSource,
945 > membershipMonitor,
946 > healthInterceptor,
947 > scheduleSpecBuilder,
948 > httpEnabled(cfg, serviceName),
949 > activityHandler,
950 > nexusOperationHandler,
951 > registry,
952 > workerDeploymentReadRateLimiter,
953 > chasmworkflow.NewValidator(
954 > chasmworkflow.NewConfig(dc),
955 > saMapperProvider,
956 > saValidator,
957 > ),
958 > )
959 > return wfHandler
960 > }
961
962 func RegisterNexusOperationHTTPHandler(
963 h *NexusOperationHTTPHandler,
964 router *mux.Router,
965 > ) { fx.go
966 > h.RegisterRoutes(router)
967 > }
968
969 func RegisterNexusCompletionHTTPHandler(
970 h *nexusCompletionHTTPHandler,
971 router *mux.Router,
972 > ) { fx.go
973 > h.RegisterRoutes(router)
974 > }
975
976 func RegisterOpenAPIHTTPHandler(
978 logger log.Logger,
979 router *mux.Router,
980 > ) *OpenAPIHTTPHandler { fx.go
981 > h := NewOpenAPIHTTPHandler(
982 > rateLimitInterceptor,
983 > logger,
984 > )
985 > h.RegisterRoutes(router)
986 > return h
987 > }
988
989 > func MuxRouterProvider() *mux.Router { fx.go
990 > // Instantiate a router to support additional route prefixes.
991 > return mux.NewRouter().UseEncodedPath()
992 > }
993
994 > func httpEnabled(cfg *config.Config, serviceName primitives.ServiceName) bool { fx.go
995 > // If the service is not the frontend service, HTTP API is disabled
996 > if serviceName != primitives.FrontendService && serviceName != primitives.InternalFrontendService {
997 return false
998 }
999 // If HTTP API port is 0, it is disabled
1000 > return cfg.Services[string(serviceName)].RPC.HTTPPort != 0 fx.go
1001 }
1002
1016 logger log.Logger,
1017 router *mux.Router,
1018 > ) (*HTTPAPIServer, error) { fx.go
1019 > if !httpEnabled(cfg, serviceName) {
1020 return nil, nil
1021 }
1022 > rpcConfig := cfg.Services[string(serviceName)].RPC fx.go
1023 > return NewHTTPAPIServer(
1024 > serviceConfig,
1025 > rpcConfig,
1026 > grpcListener,
1027 > tlsConfigProvider,
1028 > handler,
1029 > operatorHandler,
1030 > grpcServerOptions.UnaryInterceptors,
1031 > metricsHandler,
1032 > router,
1033 > namespaceRegistry,
1034 > logger,
1035 > )
1036 }
1037
1042 nexusEndpointManager persistence.NexusEndpointManager,
1043 logger log.Logger,
1044 > ) *NexusEndpointClient { fx.go
1045 > clientConfig := newNexusEndpointClientConfig(dc)
1046 > return newNexusEndpointClient(
1047 > clientConfig,
1048 > namespaceRegistry,
1049 > matchingClient,
1050 > nexusEndpointManager,
1051 > logger,
1052 > )
1053 > }
1054
1055 > func ServiceLifetimeHooks(lc fx.Lifecycle, svc *Service) { fx.go
1056 > lc.Append(fx.StartStopHook(svc.Start, svc.Stop))
1057 > }
go.temporal.io/server/service/history/workflow/workflow_task_state_machine.go 516 covered LOC · 90 ranges

Open complete file

53 ms *MutableStateImpl,
54 metricsHandler metrics.Handler,
55 > ) *workflowTaskStateMachine { workflow_task_state_machine.go
56 > return &workflowTaskStateMachine{
57 > ms: ms,
58 > metricsHandler: metricsHandler,
59 > }
60 > }
61
62 func (m *workflowTaskStateMachine) ApplyWorkflowTaskScheduledEvent(
69 originalScheduledTimestamp *timestamppb.Timestamp,
70 workflowTaskType enumsspb.WorkflowTaskType,
71 > ) (*historyi.WorkflowTaskInfo, error) { workflow_task_state_machine.go
72 >
73 > // set workflow state to running, since workflow task is scheduled
74 > // NOTE: for zombie workflow, should not change the state
75 > state, _ := m.ms.GetWorkflowStateStatus()
76 > if state != enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE {
77 > if _, err := m.ms.UpdateWorkflowStateStatus(
78 > enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING,
79 > enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING,
80 > ); err != nil {
81 return nil, err
82 }
83 }
84
85 > workflowTask := &historyi.WorkflowTaskInfo{ workflow_task_state_machine.go
86 > Version: version,
87 > ScheduledEventID: scheduledEventID,
88 > StartedEventID: common.EmptyEventID,
89 > RequestID: emptyUUID,
90 > WorkflowTaskTimeout: startToCloseTimeout.AsDuration(),
91 > TaskQueue: taskQueue,
92 > Attempt: attempt,
93 > AttemptsSinceLastSuccess: m.ms.executionInfo.WorkflowTaskAttemptsSinceLastSuccess,
94 > ScheduledTime: scheduledTime.AsTime(),
95 > StartedTime: time.Time{},
96 > OriginalScheduledTime: originalScheduledTimestamp.AsTime(),
97 > Type: workflowTaskType,
98 > SuggestContinueAsNew: false, // reset, will be recomputed on workflow task started
99 > SuggestContinueAsNewReasons: nil, // reset, will be recomputed on workflow task started
100 > HistorySizeBytes: 0, // reset, will be recomputed on workflow task started
101 > Stamp: m.ms.GetExecutionInfo().GetWorkflowTaskStamp(),
102 > }
103 >
104 > m.retainWorkflowTaskBuildIdInfo(workflowTask)
105 > m.UpdateWorkflowTask(workflowTask)
106 > return workflowTask, nil
107 }
108
111 // - BuildIdRedirectCounter so add the right BuildIdRedirectCounter to the WFT started event that will be
112 // created at WFT completion time
113 > func (m *workflowTaskStateMachine) retainWorkflowTaskBuildIdInfo(workflowTask *historyi.WorkflowTaskInfo) { workflow_task_state_machine.go
114 > if workflowTask.Attempt > 1 {
115 workflowTask.BuildId = m.ms.executionInfo.WorkflowTaskBuildId
116 workflowTask.BuildIdRedirectCounter = m.ms.executionInfo.BuildIdRedirectCounter
179 redirectCounter int64,
180 suggestContinueAsNewReasons []enumspb.SuggestContinueAsNewReason,
181 > ) (*historyi.WorkflowTaskInfo, error) { workflow_task_state_machine.go
182 > // When this function is called from ApplyEvents, workflowTask is nil.
183 > // It is safe to look up the workflow task as it does not have to deal with transient workflow task case.
184 > if workflowTask == nil {
185 workflowTask = m.GetWorkflowTaskByID(scheduledEventID)
186 if workflowTask == nil {
202 }
203
204 > workflowTask = &historyi.WorkflowTaskInfo{ workflow_task_state_machine.go
205 > Version: version,
206 > ScheduledEventID: scheduledEventID,
207 > StartedEventID: startedEventID,
208 > RequestID: requestID,
209 > WorkflowTaskTimeout: workflowTask.WorkflowTaskTimeout,
210 > Attempt: workflowTask.Attempt,
211 > AttemptsSinceLastSuccess: workflowTask.AttemptsSinceLastSuccess,
212 > StartedTime: startedTime,
213 > ScheduledTime: workflowTask.ScheduledTime,
214 > TaskQueue: workflowTask.TaskQueue,
215 > OriginalScheduledTime: workflowTask.OriginalScheduledTime,
216 > Type: workflowTask.Type,
217 > SuggestContinueAsNew: suggestContinueAsNew,
218 > SuggestContinueAsNewReasons: suggestContinueAsNewReasons,
219 > HistorySizeBytes: historySizeBytes,
220 > BuildIdRedirectCounter: redirectCounter,
221 > Stamp: m.ms.GetExecutionInfo().GetWorkflowTaskStamp(),
222 > }
223 >
224 > if buildId := worker_versioning.BuildIdIfUsingVersioning(versioningStamp); buildId != "" {
225 if redirectCounter == 0 {
226 // this is the initial build ID, it should normally be persisted after scheduling the wf task,
308 originalScheduledTimestamp *timestamppb.Timestamp,
309 workflowTaskType enumsspb.WorkflowTaskType,
310 > ) (*historyi.WorkflowTaskInfo, error) { workflow_task_state_machine.go
311 > opTag := tag.WorkflowActionWorkflowTaskScheduled
312 > if m.HasPendingWorkflowTask() {
313 m.ms.logger.Warn(mutableStateInvalidHistoryActionMsg, opTag,
314 tag.WorkflowEventID(m.ms.GetNextEventID()),
322 // and
323 // - is not speculative.
324 > createWorkflowTaskScheduledEvent := !m.ms.IsTransientWorkflowTask() && workflowTaskType != enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE workflow_task_state_machine.go
325 >
326 > // If while scheduling a workflow task and new events has come, then this workflow task cannot be a transient/speculative.
327 > // Flush any buffered events before creating the workflow task, otherwise it will result in invalid IDs for
328 > // transient/speculative workflow task and will cause in timeout processing to not work for transient workflow tasks.
329 > if m.ms.HasBufferedEvents() {
330 m.ms.executionInfo.WorkflowTaskAttempt = 1
331 workflowTaskType = enumsspb.WORKFLOW_TASK_TYPE_NORMAL
333 m.ms.updatePendingEventIDs(m.ms.hBuilder.FlushBufferToCurrentBatch())
334 }
335 > if m.ms.IsTransientWorkflowTask() { workflow_task_state_machine.go
336 // TODO: ideally this should be the version of the last started workflow task.
337 // but we are using the last event version here instead since there's no other
351 }
352
353 > scheduleTime := m.ms.timeSource.Now().UTC() workflow_task_state_machine.go
354 > attempt := m.ms.executionInfo.WorkflowTaskAttempt
355 > // TaskQueue should already be set from workflow execution started event.
356 > taskQueue := m.ms.CurrentTaskQueue()
357 > // DefaultWorkflowTaskTimeout should already be set from workflow execution started event.
358 > startToCloseTimeout := m.getStartToCloseTimeout(m.ms.executionInfo.DefaultWorkflowTaskTimeout, attempt)
359 >
360 > var scheduledEvent *historypb.HistoryEvent
361 > var scheduledEventID int64
362 >
363 > if createWorkflowTaskScheduledEvent {
364 > scheduledEvent = m.ms.hBuilder.AddWorkflowTaskScheduledEvent( workflow_task_state_machine.go
365 > taskQueue,
366 > startToCloseTimeout,
367 > attempt,
368 > scheduleTime,
369 > )
370 > scheduledEventID = scheduledEvent.GetEventId()
372 // WorkflowTaskScheduledEvent will be created later.
373 scheduledEventID = m.ms.GetNextEventID()
374 }
375
376 > workflowTask, err := m.ApplyWorkflowTaskScheduledEvent( workflow_task_state_machine.go
377 > m.ms.GetCurrentVersion(),
378 > scheduledEventID,
379 > taskQueue,
380 > startToCloseTimeout,
381 > attempt,
382 > timestamppb.New(scheduleTime),
383 > originalScheduledTimestamp,
384 > workflowTaskType,
385 > )
386 > if err != nil {
387 return nil, err
388 }
389
390 // TODO merge active & passive task generation
391 > if !bypassTaskGeneration { workflow_task_state_machine.go
392 > if workflowTask.Type == enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE { workflow_task_state_machine.go
393 err = m.ms.taskGenerator.GenerateScheduleSpeculativeWorkflowTaskTasks(workflowTask)
395 > err = m.ms.taskGenerator.GenerateScheduleWorkflowTaskTasks(scheduledEventID) workflow_task_state_machine.go
396 > }
397 > if err != nil { workflow_task_state_machine.go
398 return nil, err
399 }
400 }
401
402 > return workflowTask, nil workflow_task_state_machine.go
403 }
404
408 bypassTaskGeneration bool,
409 workflowTaskType enumsspb.WorkflowTaskType,
410 > ) (*historyi.WorkflowTaskInfo, error) { workflow_task_state_machine.go
411 > return m.AddWorkflowTaskScheduledEventAsHeartbeat(bypassTaskGeneration, timestamppb.New(m.ms.timeSource.Now()), workflowTaskType)
412 > }
413
414 // AddFirstWorkflowTaskScheduled adds the first workflow task scheduled event unless it should be delayed as indicated
419 startEvent *historypb.HistoryEvent,
420 bypassTaskGeneration bool,
421 > ) (int64, error) { workflow_task_state_machine.go
422 > // below handles the following cases:
423 > // 1. if not continue as new & if workflow has no parent
424 > // -> schedule workflow task & schedule delayed workflow task
425 > // 2. if not continue as new & if workflow has parent
426 > // -> this function should not be called during workflow start, but should be called as
427 > // part of schedule workflow task in 2 phase commit
428 > //
429 > // if continue as new
430 > // 1. whether has parent workflow or not
431 > // -> schedule workflow task & schedule delayed workflow task
432 >
433 > startAttr := startEvent.GetWorkflowExecutionStartedEventAttributes()
434 > workflowTaskBackoffDuration := timestamp.DurationValue(startAttr.GetFirstWorkflowTaskBackoff())
435 >
436 > if workflowTaskBackoffDuration != 0 {
437 > err := m.ms.taskGenerator.GenerateDelayedWorkflowTasks( workflow_task_state_machine.go
438 > startEvent,
439 > )
440 > return 0, err
442 > info, err := m.AddWorkflowTaskScheduledEvent( workflow_task_state_machine.go
443 > bypassTaskGeneration,
444 > enumsspb.WORKFLOW_TASK_TYPE_NORMAL,
445 > )
446 > if err != nil {
447 return 0, err
448 }
449 > return info.ScheduledEventID, nil workflow_task_state_machine.go
450 }
451 }
462 targetDeploymentVersion *deploymentpb.WorkerDeploymentVersion,
463 targetRevisionNumber int64,
464 > ) (*historypb.HistoryEvent, *historyi.WorkflowTaskInfo, error) { workflow_task_state_machine.go
465 > opTag := tag.WorkflowActionWorkflowTaskStarted
466 > workflowTask := m.GetWorkflowTaskByID(scheduledEventID)
467 > if workflowTask == nil || workflowTask.StartedEventID != common.EmptyEventID {
468 m.ms.logger.Warn(mutableStateInvalidHistoryActionMsg, opTag,
469 tag.WorkflowEventID(m.ms.GetNextEventID()),
473 }
474
475 > m.ms.RemoveSpeculativeWorkflowTaskTimeoutTask() workflow_task_state_machine.go
476 >
477 > scheduledEventID = workflowTask.ScheduledEventID
478 > startedEventID := scheduledEventID + 1
479 > startTime := m.ms.timeSource.Now()
480 >
481 > // The history size computed here might not include this workflow task scheduled or started
482 > // events. That's okay, it doesn't have to be 100% accurate. It just has to be kept
483 > // consistent between the started event in history and the event that was sent to the SDK
484 > // that resulted in the successful completion.
485 > historySizeBytes, suggestContinueAsNewReasons := m.getHistorySizeInfo()
486 > suggestContinueAsNew := len(suggestContinueAsNewReasons) > 0
487 > if updateReg != nil && updateReg.SuggestContinueAsNew() {
488 suggestContinueAsNew = cmp.Or(suggestContinueAsNew, true)
489 suggestContinueAsNewReasons = append(suggestContinueAsNewReasons, enumspb.SUGGEST_CONTINUE_AS_NEW_REASON_TOO_MANY_UPDATES)
490 }
491
492 > if m.ms.config.EnableSendTargetVersionChanged(m.ms.namespaceEntry.Name().String()) && workflow_task_state_machine.go
493 > m.ms.GetEffectiveVersioningBehavior() != enumspb.VERSIONING_BEHAVIOR_UNSPECIFIED {
494
495 // effectiveDeploymentVersion may be nil if the workflow is on an unversioned build;
542 }
543 // emit metric
544 > if m.targetWorkerDeploymentVersionChangedForStartedEvent() { workflow_task_state_machine.go
545 metrics.WorkflowTargetVersionChangedCount.With(m.metricsHandler.WithTags(
546 metrics.NamespaceTag(m.ms.namespaceEntry.Name().String()),
548 )).Record(1)
549 }
550 > if suggestContinueAsNew { workflow_task_state_machine.go
551 metrics.WorkflowSuggestContinueAsNewCount.With(m.metricsHandler.WithTags(
552 metrics.NamespaceTag(m.ms.namespaceEntry.Name().String()),
561 }
562
563 > workflowTask, scheduledEventCreatedForRedirect, redirectCounter, err := m.processBuildIdRedirectInfo(versioningStamp, workflowTask, taskQueue, redirectInfo, skipVersioningCheck) workflow_task_state_machine.go
564 > if err != nil {
565 return nil, nil, err
566 }
567
568 > workflowTaskScheduledEventCreated := scheduledEventCreatedForRedirect || workflow_task_state_machine.go
569 > (!m.ms.IsTransientWorkflowTask() && workflowTask.Type != enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE)
570 >
571 > // If new events came since transient/speculative WT was scheduled or failover happened during lifetime of transient/speculative WT,
572 > // transient/speculative WT needs to be converted to normal WT, i.e. WorkflowTaskScheduledEvent needs to be created now.
573 > if !workflowTaskScheduledEventCreated &&
574 > (workflowTask.ScheduledEventID != m.ms.GetNextEventID() || workflowTask.Version != m.ms.GetCurrentVersion()) {
575
576 workflowTask.Attempt = 1
590 // Create WorkflowTaskStartedEvent only if WorkflowTaskScheduledEvent was created.
591 // (it wasn't created for transient/speculative WT).
592 > var startedEvent *historypb.HistoryEvent workflow_task_state_machine.go
593 > if workflowTaskScheduledEventCreated {
594 > startedEvent = m.ms.hBuilder.AddWorkflowTaskStartedEvent( workflow_task_state_machine.go
595 > scheduledEventID,
596 > requestID,
597 > identity,
598 > startTime,
599 > suggestContinueAsNew,
600 > historySizeBytes,
601 > versioningStamp,
602 > redirectCounter,
603 > suggestContinueAsNewReasons,
604 > m.targetWorkerDeploymentVersionChangedForStartedEvent(),
605 > )
606 > m.ms.hBuilder.FlushAndCreateNewBatch()
607 > startedEventID = startedEvent.GetEventId()
608 > }
609
610 > workflowTask, err = m.ApplyWorkflowTaskStartedEvent( workflow_task_state_machine.go
611 > workflowTask,
612 > m.ms.GetCurrentVersion(),
613 > scheduledEventID,
614 > startedEventID,
615 > requestID,
616 > startTime,
617 > suggestContinueAsNew,
618 > historySizeBytes,
619 > versioningStamp,
620 > redirectCounter,
621 > suggestContinueAsNewReasons,
622 > )
623 > if err != nil {
624 return nil, nil, err
625 }
626
627 > m.emitWorkflowTaskAttemptStats(workflowTask.Attempt) workflow_task_state_machine.go
628 >
629 > // TODO merge active & passive task generation
630 > if err = m.ms.taskGenerator.GenerateStartWorkflowTaskTasks(
631 > scheduledEventID,
632 > ); err != nil {
633 return nil, nil, err
634 }
635
636 > return startedEvent, workflowTask, nil workflow_task_state_machine.go
637 }
638
648 redirectInfo *taskqueuespb.BuildIdRedirectInfo,
649 skipVersioningCheck bool,
650 > ) (newWorkflowTask *historyi.WorkflowTaskInfo, converted bool, redirectCounter int64, err error) { workflow_task_state_machine.go
651 > buildId := worker_versioning.BuildIdIfUsingVersioning(versioningStamp)
652 > if buildId == "" && (m.ms.GetAssignedBuildId() == "" || // unversioned workflow
653 > skipVersioningCheck || // resetter may add WFT started events without stamps, it sets skipVersioningCheck=true
654 > (taskQueue.GetKind() == enumspb.TASK_QUEUE_KIND_STICKY && m.ms.executionInfo.GetStickyTaskQueue() == taskQueue.GetName())) {
655 > // build ID is expected to be empty for sticky queues until old versioning is removed [cleanup-old-wv]
656 > return workflowTask, false, 0, nil
657 > }
658
659 redirectCounter, err = m.ms.validateBuildIdRedirectInfo(versioningStamp, redirectInfo)
685 }
686
687 > func (m *workflowTaskStateMachine) skipWorkflowTaskCompletedEvent(workflowTaskType enumsspb.WorkflowTaskType, request *workflowservice.RespondWorkflowTaskCompletedRequest) bool { workflow_task_state_machine.go
688 > if workflowTaskType != enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE {
689 > // Only Speculative WT can skip WorkflowTaskCompletedEvent. workflow_task_state_machine.go
690 > return false
691 > }
692
693 if len(request.GetCommands()) != 0 {
763 request *workflowservice.RespondWorkflowTaskCompletedRequest,
764 limits historyi.WorkflowTaskCompletionLimits,
765 > ) (*historypb.HistoryEvent, error) { workflow_task_state_machine.go
766 >
767 > m.ms.RemoveSpeculativeWorkflowTaskTimeoutTask()
768 >
769 > // Capture if WorkflowTaskScheduled and WorkflowTaskStarted events were created
770 > // before calling m.beforeAddWorkflowTaskCompletedEvent() because it will delete workflow task info from mutable state.
771 > workflowTaskScheduledStartedEventsCreated := !m.ms.IsTransientWorkflowTask() && workflowTask.Type != enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE
772 > m.beforeAddWorkflowTaskCompletedEvent()
773 >
774 > if m.skipWorkflowTaskCompletedEvent(workflowTask.Type, request) {
775 return nil, nil
776 }
777
778 > if !workflowTaskScheduledStartedEventsCreated { workflow_task_state_machine.go
779 // Create corresponding WorkflowTaskScheduled and WorkflowTaskStarted events for transient/speculative workflow tasks.
780 scheduledEvent := m.ms.hBuilder.AddWorkflowTaskScheduledEvent(
810 }
811
812 > deploymentName := request.GetDeploymentOptions().GetDeploymentName() workflow_task_state_machine.go
813 > if deploymentName == "" {
814 > //nolint:staticcheck // SA1019 deprecated Deployment will clean up later
815 > deploymentName = request.GetDeployment().GetSeriesName()
816 > }
817
818 > vb := request.VersioningBehavior workflow_task_state_machine.go
819 > if request.DeploymentOptions != nil && request.DeploymentOptions.GetWorkerVersioningMode() != enumspb.WORKER_VERSIONING_MODE_VERSIONED {
820 // SDK has a bug that reports behavior if user has specified a default behavior without enabling versioning.
821 // Until that is fixed, we should adjust this value so the workflow works correctly.
824
825 //nolint:staticcheck // SA1019 deprecated Deployment will clean up later
826 > wftDeployment := worker_versioning.DeploymentOrVersion(request.Deployment, worker_versioning.DeploymentVersionFromOptions(request.DeploymentOptions)) workflow_task_state_machine.go
827 >
828 > // Now write the completed event
829 > event := m.ms.hBuilder.AddWorkflowTaskCompletedEvent(
830 > workflowTask.ScheduledEventID,
831 > workflowTask.StartedEventID,
832 > request.Identity,
833 > request.BinaryChecksum,
834 > request.WorkerVersionStamp,
835 > request.SdkMetadata,
836 > request.MeteringMetadata,
837 > deploymentName,
838 > wftDeployment,
839 > vb,
840 > )
841 >
842 > override := m.ms.GetExecutionInfo().GetVersioningInfo().GetVersioningOverride()
843 > // Capture the pending one-time target before afterAddWorkflowTaskCompletedEvent,
844 > // which clears the override when this WFT completes on the target version.
845 > var oneTimeTarget *deploymentpb.WorkerDeploymentVersion
846 > if oneTime := override.GetOneTime(); oneTime != nil {
847 oneTimeTarget = oneTime.GetTargetDeploymentVersion()
848 }
849
850 > wftScheduleToClose := event.GetEventTime().AsTime().Sub(workflowTask.ScheduledTime) workflow_task_state_machine.go
851 > err := m.afterAddWorkflowTaskCompletedEvent(event, limits, wftScheduleToClose)
852 > if err != nil {
853 return nil, err
854 }
855 // afterAddWorkflowTaskCompletedEvent clears the one-time override. Emit fulfillment
856 // telemetry only on this live completion path, not when applying rebuilt history.
857 > if oneTimeTarget != nil && wftCompletedOnTargetVersion(wftDeployment, oneTimeTarget) { workflow_task_state_machine.go
858 metrics.WorkerDeploymentVersioningOneTimeOverrideCounter.With(m.metricsHandler).Record(1)
859 m.ms.logger.Info("One-time versioning override fulfilled",
865 }
866
867 > metrics.WorkflowTasksCompleted.With(m.metricsHandler).Record(1, workflow_task_state_machine.go
868 > metrics.NamespaceTag(m.ms.GetNamespaceEntry().Name().String()),
869 > metrics.VersioningBehaviorTag(vb),
870 > metrics.FirstAttemptTag(workflowTask.Attempt),
871 > )
872 >
873 > numConsecutiveWorkflowTaskProblemsToTriggerSearchAttribute := m.ms.config.NumConsecutiveWorkflowTaskProblemsToTriggerSearchAttribute(m.ms.GetNamespaceEntry().Name().String())
874 > if numConsecutiveWorkflowTaskProblemsToTriggerSearchAttribute > 0 {
875 > if err := m.ms.RemoveReportedProblemsSearchAttribute(); err != nil {
876 return nil, err
877 }
878 }
879
880 > return event, nil workflow_task_state_machine.go
881 }
882
883 > func (m *workflowTaskStateMachine) targetWorkerDeploymentVersionChangedForStartedEvent() bool { workflow_task_state_machine.go
884 > return m.ms.config.EnableSendTargetVersionChanged(m.ms.namespaceEntry.Name().String()) &&
885 > m.ms.GetEffectiveVersioningBehavior() == enumspb.VERSIONING_BEHAVIOR_PINNED &&
886 > m.ms.executionInfo.GetLastNotifiedTargetVersion() != nil
887 > }
888
889 func (m *workflowTaskStateMachine) AddWorkflowTaskFailedEvent(
1023 }
1024
1025 > func (m *workflowTaskStateMachine) recordTimeoutTasksForDeletion(workflowTask *historyi.WorkflowTaskInfo) { workflow_task_state_machine.go
1026 > // Record persisted workflow task timeout tasks for deletion after successful persistence update.
1027 > if task := workflowTask.ScheduleToStartTimeoutTask; task != nil {
1028 key := task.GetKey()
1029 if key.FireTime.Sub(workflowTask.ScheduledTime) < maxWorkflowTaskTimeoutToDelete {
1096
1097 // deleteWorkflowTask deletes a workflow task.
1098 > func (m *workflowTaskStateMachine) deleteWorkflowTask() { workflow_task_state_machine.go
1099 > // Get current workflow task info before deleting it, to capture timeout tasks for deletion
1100 > currentWorkflowTask := m.getWorkflowTaskInfo()
1101 > m.recordTimeoutTasksForDeletion(currentWorkflowTask)
1102 >
1103 > // Clear in-memory timeout tasks
1104 > m.ms.SetWorkflowTaskScheduleToStartTimeoutTask(nil)
1105 > m.ms.SetWorkflowTaskStartToCloseTimeoutTask(nil)
1106 >
1107 > resetWorkflowTaskInfo := &historyi.WorkflowTaskInfo{
1108 > Version: common.EmptyVersion,
1109 > ScheduledEventID: common.EmptyEventID,
1110 > StartedEventID: common.EmptyEventID,
1111 > RequestID: emptyUUID,
1112 > WorkflowTaskTimeout: time.Duration(0),
1113 > Attempt: 1,
1114 > StartedTime: time.Unix(0, 0).UTC(),
1115 > ScheduledTime: time.Unix(0, 0).UTC(),
1116 >
1117 > TaskQueue: nil,
1118 > // Keep the last original scheduled Timestamp, so that AddWorkflowTaskScheduledEventAsHeartbeat can continue with it.
1119 > OriginalScheduledTime: currentWorkflowTask.OriginalScheduledTime,
1120 > Type: enumsspb.WORKFLOW_TASK_TYPE_UNSPECIFIED,
1121 > SuggestContinueAsNew: false,
1122 > SuggestContinueAsNewReasons: nil,
1123 > HistorySizeBytes: 0,
1124 > }
1125 > m.UpdateWorkflowTask(resetWorkflowTaskInfo)
1126 > }
1127
1128 // UpdateWorkflowTask updates a workflow task.
1129 func (m *workflowTaskStateMachine) UpdateWorkflowTask(
1130 workflowTask *historyi.WorkflowTaskInfo,
1132 > if m.HasStartedWorkflowTask() && workflowTask.StartedEventID == common.EmptyEventID {
1133 > // reset the flag whenever started workflow task closes, there could be three cases: workflow_task_state_machine.go
1134 > // 1. workflow task completed:
1135 > // a. workflow task contains close workflow command, the fact that workflow task
1136 > // completes successfully means workflow will also close and the value of the
1137 > // flag doesn't matter.
1138 > // b. workflow task doesn't contain close workflow command, then by definition,
1139 > // workflow is not trying to close, so unset the flag.
1140 > // 2. workflow task timedout: we don't know if workflow is trying to close or not,
1141 > // reset the flag to be safe. It's possible that workflow task is trying to signal
1142 > // itself within a local activity when this flag is set, which may result in timeout.
1143 > // reset the flag will allow the workflow to proceed.
1144 > // 3. workflow failed: always reset the flag here. If failure is due to unhandled command,
1145 > // AddWorkflowTaskFailedEvent will set the flag.
1146 > m.ms.workflowCloseAttempted = false
1147 > }
1148
1149 > m.ms.executionInfo.WorkflowTaskVersion = workflowTask.Version workflow_task_state_machine.go
1150 > m.ms.executionInfo.WorkflowTaskScheduledEventId = workflowTask.ScheduledEventID
1151 > m.ms.executionInfo.WorkflowTaskStartedEventId = workflowTask.StartedEventID
1152 > m.ms.executionInfo.WorkflowTaskRequestId = workflowTask.RequestID
1153 > m.ms.executionInfo.WorkflowTaskTimeout = durationpb.New(workflowTask.WorkflowTaskTimeout)
1154 > m.ms.executionInfo.WorkflowTaskAttempt = workflowTask.Attempt
1155 > m.ms.executionInfo.WorkflowTaskAttemptsSinceLastSuccess = workflowTask.AttemptsSinceLastSuccess
1156 > if !workflowTask.StartedTime.IsZero() {
1157 > m.ms.executionInfo.WorkflowTaskStartedTime = timestamppb.New(workflowTask.StartedTime) workflow_task_state_machine.go
1158 > }
1159 > if !workflowTask.ScheduledTime.IsZero() { workflow_task_state_machine.go
1160 > m.ms.executionInfo.WorkflowTaskScheduledTime = timestamppb.New(workflowTask.ScheduledTime)
1161 > }
1162 > m.ms.executionInfo.WorkflowTaskOriginalScheduledTime = timestamppb.New(workflowTask.OriginalScheduledTime)
1163 > m.ms.executionInfo.WorkflowTaskType = workflowTask.Type
1164 > m.ms.executionInfo.WorkflowTaskSuggestContinueAsNew = workflowTask.SuggestContinueAsNew
1165 > m.ms.executionInfo.WorkflowTaskSuggestContinueAsNewReasons = workflowTask.SuggestContinueAsNewReasons
1166 > m.ms.executionInfo.WorkflowTaskHistorySizeBytes = workflowTask.HistorySizeBytes
1167 > m.ms.executionInfo.WorkflowTaskBuildId = workflowTask.BuildId
1168 > m.ms.executionInfo.WorkflowTaskBuildIdRedirectCounter = workflowTask.BuildIdRedirectCounter
1169 >
1170 > m.ms.workflowTaskUpdated = true
1171 >
1172 > // NOTE:
1173 > // - do not update executionInfo.TaskQueue!
1174 >
1175 > m.ms.logger.Debug("Workflow task updated",
1176 > tag.WorkflowScheduledEventID(workflowTask.ScheduledEventID),
1177 > tag.WorkflowStartedEventID(workflowTask.StartedEventID),
1178 > tag.WorkflowTaskRequestId(workflowTask.RequestID),
1179 > tag.WorkflowTaskTimeout(workflowTask.WorkflowTaskTimeout),
1180 > tag.Attempt(workflowTask.Attempt),
1181 > tag.WorkflowStartedTimestamp(workflowTask.StartedTime),
1182 > tag.WorkflowTaskType(workflowTask.Type.String()))
1183 }
1184
1185 > func (m *workflowTaskStateMachine) HasPendingWorkflowTask() bool { workflow_task_state_machine.go
1186 > return m.ms.executionInfo.WorkflowTaskScheduledEventId != common.EmptyEventID
1187 > }
1188
1189 > func (m *workflowTaskStateMachine) GetPendingWorkflowTask() *historyi.WorkflowTaskInfo { workflow_task_state_machine.go
1190 > if !m.HasPendingWorkflowTask() {
1191 return nil
1192 }
1193
1194 > workflowTask := m.getWorkflowTaskInfo() workflow_task_state_machine.go
1195 > return workflowTask
1196 }
1197
1198 > func (m *workflowTaskStateMachine) HasStartedWorkflowTask() bool { workflow_task_state_machine.go
1199 > return m.ms.executionInfo.WorkflowTaskScheduledEventId != common.EmptyEventID &&
1200 > m.ms.executionInfo.WorkflowTaskStartedEventId != common.EmptyEventID
1201 > }
1202
1203 > func (m *workflowTaskStateMachine) GetStartedWorkflowTask() *historyi.WorkflowTaskInfo { workflow_task_state_machine.go
1204 > if !m.HasStartedWorkflowTask() {
1205 > return nil workflow_task_state_machine.go
1206 > }
1207
1208 > workflowTask := m.getWorkflowTaskInfo() workflow_task_state_machine.go
1209 > return workflowTask
1210 }
1211
1215
1216 // GetWorkflowTaskByID returns details about the current workflow task by scheduled event ID.
1217 > func (m *workflowTaskStateMachine) GetWorkflowTaskByID(scheduledEventID int64) *historyi.WorkflowTaskInfo { workflow_task_state_machine.go
1218 > workflowTask := m.getWorkflowTaskInfo()
1219 > if scheduledEventID == workflowTask.ScheduledEventID {
1220 > return workflowTask
1221 > }
1222
1223 return nil
1284 }
1285
1286 > func (m *workflowTaskStateMachine) getWorkflowTaskInfo() *historyi.WorkflowTaskInfo { workflow_task_state_machine.go
1287 > wft := &historyi.WorkflowTaskInfo{
1288 > Version: m.ms.executionInfo.WorkflowTaskVersion,
1289 > ScheduledEventID: m.ms.executionInfo.WorkflowTaskScheduledEventId,
1290 > StartedEventID: m.ms.executionInfo.WorkflowTaskStartedEventId,
1291 > RequestID: m.ms.executionInfo.WorkflowTaskRequestId,
1292 > WorkflowTaskTimeout: m.ms.executionInfo.WorkflowTaskTimeout.AsDuration(),
1293 > Attempt: m.ms.executionInfo.WorkflowTaskAttempt,
1294 > AttemptsSinceLastSuccess: m.ms.executionInfo.WorkflowTaskAttemptsSinceLastSuccess,
1295 > StartedTime: m.ms.executionInfo.WorkflowTaskStartedTime.AsTime(),
1296 > ScheduledTime: m.ms.executionInfo.WorkflowTaskScheduledTime.AsTime(),
1297 > TaskQueue: m.ms.CurrentTaskQueue(),
1298 > OriginalScheduledTime: m.ms.executionInfo.WorkflowTaskOriginalScheduledTime.AsTime(),
1299 > Type: m.ms.executionInfo.WorkflowTaskType,
1300 > SuggestContinueAsNew: m.ms.executionInfo.WorkflowTaskSuggestContinueAsNew,
1301 > SuggestContinueAsNewReasons: m.ms.executionInfo.WorkflowTaskSuggestContinueAsNewReasons,
1302 > HistorySizeBytes: m.ms.executionInfo.WorkflowTaskHistorySizeBytes,
1303 > BuildId: m.ms.executionInfo.WorkflowTaskBuildId,
1304 > BuildIdRedirectCounter: m.ms.executionInfo.WorkflowTaskBuildIdRedirectCounter,
1305 > ScheduleToStartTimeoutTask: m.ms.GetWorkflowTaskScheduleToStartTimeoutTask(),
1306 > StartToCloseTimeoutTask: m.ms.GetWorkflowTaskStartToCloseTimeoutTask(),
1307 > Stamp: m.ms.executionInfo.WorkflowTaskStamp,
1308 > }
1309 >
1310 > return wft
1311 > }
1312
1313 > func (m *workflowTaskStateMachine) beforeAddWorkflowTaskCompletedEvent() { workflow_task_state_machine.go
1314 > // Make sure to delete workflow task before adding events. Otherwise they are buffered rather than getting appended.
1315 > m.deleteWorkflowTask()
1316 > }
1317
1318 func (m *workflowTaskStateMachine) afterAddWorkflowTaskCompletedEvent(
1320 limits historyi.WorkflowTaskCompletionLimits,
1321 wftScheduleToClose time.Duration,
1323 > attrs := event.GetWorkflowTaskCompletedEventAttributes()
1324 > m.ms.executionInfo.LastCompletedWorkflowTaskStartedEventId = attrs.GetStartedEventId()
1325 > m.ms.executionInfo.MostRecentWorkerVersionStamp = attrs.GetWorkerVersion()
1326 > m.ms.executionInfo.WorkerDeploymentName = attrs.GetWorkerDeploymentName()
1327 >
1328 > //nolint:staticcheck // SA1019 deprecated Deployment will clean up later
1329 > wftDeployment := attrs.GetDeployment()
1330 > if v := attrs.GetWorkerDeploymentVersion(); v != "" { //nolint:staticcheck // SA1019: worker versioning v0.31
1331 dv, _ := worker_versioning.WorkerDeploymentVersionFromStringV31(v)
1332 wftDeployment = worker_versioning.DeploymentFromDeploymentVersion(dv)
1333 }
1334 > if v := attrs.GetDeploymentVersion(); v != nil { workflow_task_state_machine.go
1335 wftDeployment = worker_versioning.DeploymentFromExternalDeploymentVersion(v)
1336 }
1337 > wftBehavior := attrs.GetVersioningBehavior() workflow_task_state_machine.go
1338 > versioningInfo := m.ms.GetExecutionInfo().GetVersioningInfo()
1339 > transition := m.ms.GetDeploymentTransition()
1340 >
1341 > var completedTransition bool
1342 > if transition != nil {
1343 // It's possible that the completed WFT is not yet from the current transition because when
1344 // the transition started, the current wft was already started. In this case, we allow the
1353
1354 // Deployment and behavior before applying the data came from the completed wft.
1355 > wfDeploymentBefore := m.ms.GetEffectiveDeployment() workflow_task_state_machine.go
1356 > wfBehaviorBefore := m.ms.GetEffectiveVersioningBehavior()
1357 >
1358 > // Change deployment and behavior based on completed wft.
1359 > if wftBehavior == enumspb.VERSIONING_BEHAVIOR_UNSPECIFIED {
1360 > if versioningInfo != nil {
1361 versioningInfo.Behavior = wftBehavior
1362 // Deployment Version is not set for unversioned workers.
1380 versioningInfo.DeploymentVersion = worker_versioning.ExternalWorkerDeploymentVersionFromDeployment(wftDeployment)
1381 }
1382 > if oneTime := versioningInfo.GetVersioningOverride().GetOneTime(); oneTime != nil && workflow_task_state_machine.go
1383 > wftCompletedOnTargetVersion(wftDeployment, oneTime.GetTargetDeploymentVersion()) {
1384 // Clear before computing effective deployment/behavior so the worker-reported base state takes effect.
1385 versioningInfo.VersioningOverride = nil
1387
1388 // Deployment and behavior after applying the data came from the completed wft.
1389 > wfDeploymentAfter := m.ms.GetEffectiveDeployment() workflow_task_state_machine.go
1390 > wfBehaviorAfter := m.ms.GetEffectiveVersioningBehavior()
1391 > // We reschedule activities if a transition was completed because during the transition
1392 > // ATs might have been dropped. Note that it is possible that transition completes and still
1393 > // `wfDeploymentBefore == wfDeploymentAfter`. Example: wf was on deployment1, started
1394 > // transition to deployment2, before completing the transition it changed the transition to
1395 > // deployment1 (maybe user rolled back current deployment), now the transition completes.
1396 > if completedTransition ||
1397 > // It is possible that this WFT is changing workflow's deployment even if there was no
1398 > // ongoing transition in the MS. That is possible when the wft is speculative. We still
1399 > // want to reschedule the activities so they are queued with the up-to-date directive.
1400 > !wfDeploymentBefore.Equal(wfDeploymentAfter) ||
1401 > // If effective behavior changes we also want to reschedule the pending activities, so
1402 > // they go to the right matching queues.
1403 > wfBehaviorBefore != wfBehaviorAfter {
1404 if err := m.ms.reschedulePendingActivities(wftScheduleToClose); err != nil {
1405 return err
1408
1409 //nolint:staticcheck // SA1019: worker versioning v2
1410 > buildId := attrs.GetWorkerVersion().GetBuildId() workflow_task_state_machine.go
1411 > if wftDeployment != nil {
1412 buildId = wftDeployment.GetBuildId()
1413 }
1414 > addedResetPoint := m.ms.addResetPointFromCompletion( workflow_task_state_machine.go
1415 > attrs.GetBinaryChecksum(),
1416 > buildId,
1417 > event.GetEventId(),
1418 > limits.MaxResetPoints,
1419 > )
1420 >
1421 > // For v3 versioned workflows (ms.GetEffectiveVersioningBehavior() != UNSPECIFIED), this will update the reachability
1422 > // search attribute based on the execution_info.deployment and/or override deployment if one exists. We must update the
1423 > // search attribute here because the reachability deployment may have just been changed by CompleteDeploymentTransition.
1424 > // This is also useful for unversioned workers.
1425 > // For v1 and v2 versioned workflows the search attributes should be already up-to-date based on the task started events.
1426 > //nolint:staticcheck // SA1019
1427 > if err := m.ms.updateBuildIdsAndDeploymentSearchAttributes(attrs.GetWorkerVersion(), worker_versioning.ExternalWorkerDeploymentVersionFromDeployment(wftDeployment), limits.MaxSearchAttributeValueSize); err != nil {
1428 return err
1429 }
1430 > if addedResetPoint && len(attrs.GetBinaryChecksum()) > 0 { workflow_task_state_machine.go
1431 if err := m.ms.updateBinaryChecksumSearchAttribute(); err != nil {
1432 return err
1433 }
1434 }
1435 > return nil workflow_task_state_machine.go
1436 }
1437
1449 func (m *workflowTaskStateMachine) emitWorkflowTaskAttemptStats(
1450 attempt int32,
1452 > namespaceName := m.ms.GetNamespaceEntry().Name().String()
1453 > metrics.WorkflowTaskAttempt.With(m.ms.metricsHandler).
1454 > Record(int64(attempt), metrics.NamespaceTag(namespaceName))
1455 > if attempt >= int32(m.ms.shard.GetConfig().WorkflowTaskCriticalAttempts()) {
1456 m.ms.shard.GetThrottledLogger().Warn("Critical attempts processing workflow task",
1457 tag.WorkflowNamespace(namespaceName),
1466 defaultTimeout *durationpb.Duration,
1467 attempt int32,
1468 > ) *durationpb.Duration { workflow_task_state_machine.go
1469 > // This util function is only for calculating active workflow task timeout.
1470 > // Transient workflow task in passive cluster won't call this function and
1471 > // always use default timeout as it will either be completely overwritten by
1472 > // a replicated workflow schedule event from active cluster, or if used, it's
1473 > // attempt will be reset to 1.
1474 > // Check ApplyTransientWorkflowTaskScheduled for details.
1475 >
1476 > if defaultTimeout == nil {
1477 defaultTimeout = durationpb.New(0)
1478 }
1479
1480 > if attempt <= workflowTaskRetryBackoffMinAttempts { workflow_task_state_machine.go
1481 > return defaultTimeout
1482 > }
1483
1484 policy := backoff.NewExponentialRetryPolicy(workflowTaskRetryInitialInterval).
1489 }
1490
1491 > func (m *workflowTaskStateMachine) getHistorySizeInfo() (int64, []enumspb.SuggestContinueAsNewReason) { workflow_task_state_machine.go
1492 > var reasons []enumspb.SuggestContinueAsNewReason
1493 > stats := m.ms.GetExecutionInfo().ExecutionStats
1494 > if stats == nil {
1495 return 0, reasons
1496 }
1498 // include the workflow task started event that we're currently writing. That's okay, it
1499 // doesn't have to be 100% accurate.
1500 > historySize := stats.HistorySize workflow_task_state_machine.go
1501 > // This is called right before AddWorkflowTaskStartedEvent, so at this point, nextEventID
1502 > // is the ID of the workflow task started event.
1503 > historyCount := m.ms.GetNextEventID()
1504 > config := m.ms.shard.GetConfig()
1505 > namespaceName := m.ms.GetNamespaceEntry().Name().String()
1506 > sizeLimit := int64(config.HistorySizeSuggestContinueAsNew(namespaceName))
1507 > countLimit := int64(config.HistoryCountSuggestContinueAsNew(namespaceName))
1508 > if historySize >= sizeLimit {
1509 reasons = append(reasons, enumspb.SUGGEST_CONTINUE_AS_NEW_REASON_HISTORY_SIZE_TOO_LARGE)
1510 }
1511 > if historyCount >= countLimit { workflow_task_state_machine.go
1512 reasons = append(reasons, enumspb.SUGGEST_CONTINUE_AS_NEW_REASON_TOO_MANY_HISTORY_EVENTS)
1513 }
1514 > return historySize, reasons workflow_task_state_machine.go
1515 }
1516
1517 > func (m *workflowTaskStateMachine) convertSpeculativeWorkflowTaskToNormal() error { workflow_task_state_machine.go
1518 > if m.ms.executionInfo.WorkflowTaskType != enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE {
1519 > return nil workflow_task_state_machine.go
1520 > }
1521
1522 // Workflow task can't be persisted as Speculative, because when it is completed,
go.temporal.io/server/temporal/fx.go 474 covered LOC · 93 ranges

Open complete file

158 )
159
160 > func NewServerFx(topLevelModule fx.Option, opts ...ServerOption) (*ServerFx, error) { fx.go
161 > var s ServerFx
162 > s.app = fx.New(
163 > topLevelModule,
164 > fx.Supply(opts),
165 > fx.Populate(&s.startupSynchronizationMode),
166 > fx.Populate(&s.logger),
167 > )
168 > if err := s.app.Err(); err != nil {
169 return nil, err
170 }
171 > return &s, nil fx.go
172 }
173
174 > func ServerOptionsProvider(opts []ServerOption) (serverOptionsProvider, error) { fx.go
175 > so := newServerOptions(opts)
176 >
177 > err := so.loadAndValidate()
178 > if err != nil {
179 return serverOptionsProvider{}, err
180 }
181
182 // Logger
183 > logger := so.logger fx.go
184 > if logger == nil {
185 logger = log.NewZapLogger(log.BuildZapLogger(so.config.Log))
186 }
187
188 > persistenceConfig := so.config.Persistence fx.go
189 > err = verifyPersistenceCompatibleVersion(persistenceConfig, so.persistenceServiceResolver, logger)
190 > if err != nil {
191 return serverOptionsProvider{}, err
192 }
193
194 > stopChan := make(chan any) fx.go
195 >
196 > // ClientFactoryProvider
197 > clientFactoryProvider := so.clientFactoryProvider
198 > if clientFactoryProvider == nil {
199 > clientFactoryProvider = client.NewFactoryProvider()
200 > }
201
202 // MetricsHandler
203 > metricHandler := so.metricHandler fx.go
204 > if metricHandler == nil {
205 > metricHandler, err = metrics.MetricsHandlerFromConfig(logger, so.config.Global.Metrics)
206 > if err != nil {
207 return serverOptionsProvider{}, fmt.Errorf("unable to create metrics handler: %w", err)
208 }
212 // if injected, else a no-op provider that discards events. A deployment opts in by injecting a
213 // provider via WithCustomEventLoggerProvider.
214 > eventLoggerProvider := so.eventLoggerProvider fx.go
215 > if eventLoggerProvider == nil {
216 > eventLoggerProvider = lognoop.NewLoggerProvider()
217 > }
218
219 // DynamicConfigClient
220 > dcClient := so.dynamicConfigClient fx.go
221 > if dcClient == nil {
222 dcConfig := so.config.DynamicConfigClient
223 if dcConfig != nil {
234
235 // TLSConfigProvider
236 > tlsConfigProvider := so.tlsConfigProvider fx.go
237 > if tlsConfigProvider == nil {
238 > tlsConfigProvider, err = encryption.NewTLSConfigProviderFromConfig(so.config.Global.TLS, metricHandler, logger, nil)
239 > if err != nil {
240 return serverOptionsProvider{}, err
241 }
243
244 // EsConfig / EsClient
245 > var esConfig *esclient.Config fx.go
246 > var esClient esclient.Client
247 >
248 > if persistenceConfig.SecondaryVisibilityConfigExist() &&
249 > persistenceConfig.DataStores[persistenceConfig.SecondaryVisibilityStore].Elasticsearch != nil {
250 esConfig = persistenceConfig.DataStores[persistenceConfig.SecondaryVisibilityStore].Elasticsearch
251 esConfig.SetHttpClient(so.elasticsearchHttpClient)
252 }
253 > if persistenceConfig.VisibilityConfigExist() && fx.go
254 > persistenceConfig.DataStores[persistenceConfig.VisibilityStore].Elasticsearch != nil {
255 esConfig = persistenceConfig.DataStores[persistenceConfig.VisibilityStore].Elasticsearch
256 esConfig.SetHttpClient(so.elasticsearchHttpClient)
257 }
258
259 > if esConfig != nil { fx.go
260 esHttpClient := so.elasticsearchHttpClient
261 if esHttpClient == nil {
275
276 // check that when static hosts are defined, they are defined for all required hosts
277 > if len(so.hostsByService) > 0 { fx.go
278 for _, service := range DefaultServices {
279 hosts := so.hostsByService[primitives.ServiceName(service)]
284 }
285
286 > if so.config.Global.Authorization.RemoteClusterAuth.Require && so.tokenProvider == nil { fx.go
287 return serverOptionsProvider{}, errors.New("global.authorization.remoteClusterAuth.require is true but no TokenProvider is configured: use WithTokenProvider")
288 }
291 // Coarse check: any remote-cluster TLS entry passes; per-hostname config is still validated
292 // lazily on first dial.
293 > if so.tokenProvider != nil && so.tlsConfigProvider == nil && len(so.config.Global.TLS.RemoteClusters) == 0 { fx.go
294 return serverOptionsProvider{}, errors.New("WithTokenProvider is set but no remote-cluster TLS is configured: supply global.tls.remoteClusters in config, or pass a provider via WithTLSConfigProvider")
295 }
296
297 > return serverOptionsProvider{ fx.go
298 > ServerOptions: so,
299 > StopChan: stopChan,
300 > StartupSynchronizationMode: so.startupSynchronizationMode,
301 >
302 > Config: so.config,
303 > PProfConfig: &so.config.Global.PProf,
304 > LogConfig: so.config.Log,
305 >
306 > ServiceNames: so.serviceNames,
307 > ServiceHosts: so.hostsByService,
308 > NamespaceLogger: so.namespaceLogger,
309 >
310 > ServiceResolver: so.persistenceServiceResolver,
311 > CustomDataStoreFactory: so.customDataStoreFactory,
312 > CustomVisibilityStore: so.customVisibilityStoreFactory,
313 > CustomHistoryArchiverFactory: so.customHistoryArchiverFactory,
314 > CustomVisibilityArchiverFactory: so.customVisibilityArchiverFactory,
315 >
316 > SearchAttributesMapper: so.searchAttributesMapper,
317 > CustomFrontendInterceptors: so.customFrontendInterceptors,
318 > Authorizer: so.authorizer,
319 > ClaimMapper: so.claimMapper,
320 > AudienceGetter: so.audienceGetter,
321 > TokenProvider: so.tokenProvider,
322 >
323 > Logger: logger,
324 > ClientFactoryProvider: clientFactoryProvider,
325 > DynamicConfigClient: dcClient,
326 > TLSConfigProvider: tlsConfigProvider,
327 > EsClient: esClient,
328 > MetricsHandler: metricHandler,
329 > EventLoggerProvider: eventLoggerProvider,
330 > }, nil
331 }
332
333 // Start temporal server.
334 // This function should be called only once, Server doesn't support multiple restarts.
335 > func (s *ServerFx) Start() error { fx.go
336 > err := s.app.Start(context.Background())
337 > if err != nil {
338 return err
339 }
340
341 > if s.startupSynchronizationMode.blockingStart { fx.go
342 // If s.so.interruptCh is nil this will wait forever.
343 interruptSignal := <-s.startupSynchronizationMode.interruptCh
346 }
347
348 > return nil fx.go
349 }
350
351 // Stop stops the server.
352 > func (s *ServerFx) Stop() error { fx.go
353 > return s.app.Stop(context.Background())
354 > }
355
356 > func (svc *ServicesMetadata) Stop(ctx context.Context) { fx.go
357 > stopCtx, cancelFunc := context.WithTimeout(ctx, serviceStopTimeout)
358 > defer cancelFunc()
359 > err := svc.app.Stop(stopCtx)
360 > if err != nil {
361 svc.logger.Error("Failed to stop service", tag.Service(svc.serviceName), tag.Error(err))
362 }
405 // into fx providers here. Essentially, we want an `fx.In` object in the server graph, and an `fx.Out` object in the
406 // service graphs. This is a workaround to achieve something similar.
407 > func (params ServiceProviderParamsCommon) GetCommonServiceOptions(serviceName primitives.ServiceName) fx.Option { fx.go
408 > membershipModule := ringpop.MembershipModule
409 > if len(params.StaticServiceHosts) > 0 {
410 membershipModule = static.MembershipModule(params.StaticServiceHosts)
411 }
412
413 > return fx.Options( fx.go
414 > fx.Supply(
415 > serviceName,
416 > params.PersistenceConfig,
417 > params.ClusterMetadata,
418 > params.Cfg,
419 > params.SpanExporters,
420 > ),
421 > fx.Provide(
422 > resource.DefaultSnTaggedLoggerProvider,
423 > params.PersistenceFactoryProvider,
424 > func() persistenceClient.AbstractDataStoreFactory {
425 > return params.DataStoreFactory
426 > },
427 > func() visibility.VisibilityStoreFactory {
428 > return params.VisibilityStoreFactory
429 > },
430 > func() provider.CustomHistoryArchiverFactory {
431 > return params.CustomHistoryArchiverFactory
432 > },
433 > func() provider.CustomVisibilityArchiverFactory {
434 > return params.CustomVisibilityArchiverFactory
435 > },
436 > func() client.FactoryProvider {
437 > return params.ClientFactoryProvider
438 > },
439 > func() authorization.JWTAudienceMapper {
440 > return params.AudienceGetter
441 > },
442 > func() resolver.ServiceResolver {
443 > return params.PersistenceServiceResolver
444 > },
445 > func() searchattribute.Mapper {
446 > return params.SearchAttributesMapper
447 > },
448 > func() authorization.Authorizer {
449 > return params.Authorizer
450 > },
451 func() authorization.ClaimMapper {
452 return params.ClaimMapper
453 },
454 > func() auth.TokenProvider { fx.go
455 > return params.TokenProvider
456 > },
457 > func() encryption.TLSConfigProvider {
458 > return params.TlsConfigProvider
459 > },
460 > func() dynamicconfig.Client {
461 > return params.DynamicConfigClient
462 > },
463 > func() log.Logger {
464 > return params.Logger
465 > },
466 > func() metrics.Handler {
467 > return params.MetricsHandler.WithTags(metrics.ServiceNameTag(serviceName))
468 > },
469 > func() otellog.Logger {
470 > return wideevents.NewLogger(params.EventLoggerProvider, string(serviceName))
471 > },
472 func() esclient.Client {
473 return params.EsClient
474 },
475 > func() resource.NamespaceLogger { fx.go
476 > return params.NamespaceLogger
477 > },
478 > func() tasks.TaskCategoryRegistry {
479 > return params.TaskCategoryRegistry
480 > },
481 ),
482 ServiceTracingModule,
494 // registry in the server graph, and then propagate it to the service graphs. Otherwise, it would be isolated to the
495 // history service's graph.
496 > func TaskCategoryRegistryProvider(archivalMetadata archiver.ArchivalMetadata) tasks.TaskCategoryRegistry { fx.go
497 > registry := tasks.NewDefaultTaskCategoryRegistry()
498 > if archivalMetadata.GetHistoryConfig().StaticClusterState() == archiver.ArchivalEnabled ||
499 > archivalMetadata.GetVisibilityConfig().StaticClusterState() == archiver.ArchivalEnabled {
500 > registry.AddCategory(tasks.CategoryArchival) fx.go
501 > }
502 > return registry fx.go
503 }
504
505 > func NewService(app *fx.App, serviceName primitives.ServiceName, logger log.Logger) ServicesGroupOut { fx.go
506 > return ServicesGroupOut{
507 > Services: &ServicesMetadata{
508 > app: app,
509 > serviceName: serviceName,
510 > logger: logger,
511 > },
512 > }
513 > }
514
515 func HistoryServiceProvider(
516 params ServiceProviderParamsCommon,
517 > ) (ServicesGroupOut, error) { fx.go
518 > serviceName := primitives.HistoryService
519 >
520 > if _, ok := params.ServiceNames[serviceName]; !ok {
521 params.Logger.Info("Service is not requested, skipping initialization.", tag.Service(serviceName))
522 return ServicesGroupOut{}, nil
523 }
524
525 > app := fx.New( fx.go
526 > params.GetCommonServiceOptions(serviceName),
527 > history.QueueModule,
528 > history.Module,
529 > replication.Module,
530 > )
531 >
532 > return NewService(app, serviceName, params.Logger), app.Err()
533 }
534
535 func MatchingServiceProvider(
536 params ServiceProviderParamsCommon,
537 > ) (ServicesGroupOut, error) { fx.go
538 > serviceName := primitives.MatchingService
539 >
540 > if _, ok := params.ServiceNames[serviceName]; !ok {
541 params.Logger.Info("Service is not requested, skipping initialization.", tag.Service(serviceName))
542 return ServicesGroupOut{}, nil
543 }
544
545 > app := fx.New( fx.go
546 > params.GetCommonServiceOptions(serviceName),
547 > matching.Module,
548 > )
549 >
550 > return NewService(app, serviceName, params.Logger), app.Err()
551 }
552
553 func FrontendServiceProvider(
554 params ServiceProviderParamsCommon,
555 > ) (ServicesGroupOut, error) { fx.go
556 > return genericFrontendServiceProvider(params, primitives.FrontendService)
557 > }
558
559 func InternalFrontendServiceProvider(
560 params ServiceProviderParamsCommon,
561 > ) (ServicesGroupOut, error) { fx.go
562 > return genericFrontendServiceProvider(params, primitives.InternalFrontendService)
563 > }
564
565 func genericFrontendServiceProvider(
566 params ServiceProviderParamsCommon,
567 serviceName primitives.ServiceName,
568 > ) (ServicesGroupOut, error) { fx.go
569 > if _, ok := params.ServiceNames[serviceName]; !ok {
570 > params.Logger.Info("Service is not requested, skipping initialization.", tag.Service(serviceName))
571 > return ServicesGroupOut{}, nil
572 > }
573
574 > app := fx.New( fx.go
575 > params.GetCommonServiceOptions(serviceName),
576 > fx.Supply(params.CustomFrontendInterceptors),
577 > fx.Supply([]grpc.StreamServerInterceptor{}),
578 > fx.Decorate(func() authorization.ClaimMapper {
579 > switch serviceName {
580 > case primitives.FrontendService:
581 > return params.ClaimMapper
582 case primitives.InternalFrontendService:
583 return authorization.NewInternalClaimMapper()
586 }
587 }),
588 > fx.Decorate(func() log.SnTaggedLogger { fx.go
589 > // Use "frontend" for logs even if serviceName is "internal-frontend", but add an
590 > // extra tag to differentiate.
591 > tags := []tag.Tag{tag.Service(primitives.FrontendService)}
592 > if serviceName == primitives.InternalFrontendService {
593 tags = append(tags, tag.Bool("internal-frontend", true))
594 }
595 > return log.With(params.Logger, tags...) fx.go
596 }),
597 frontend.Module,
598 )
599
600 > return NewService(app, serviceName, params.Logger), app.Err() fx.go
601 }
602
603 func WorkerServiceProvider(
604 params ServiceProviderParamsCommon,
605 > ) (ServicesGroupOut, error) { fx.go
606 > serviceName := primitives.WorkerService
607 >
608 > if _, ok := params.ServiceNames[serviceName]; !ok {
609 params.Logger.Info("Service is not requested, skipping initialization.", tag.Service(serviceName))
610 return ServicesGroupOut{}, nil
611 }
612
613 > app := fx.New( fx.go
614 > params.GetCommonServiceOptions(serviceName),
615 > worker.Module,
616 > )
617 >
618 > return NewService(app, serviceName, params.Logger), app.Err()
619 }
620
632 metricsHandler metrics.Handler,
633 serializer serialization.Serializer,
634 > ) (*cluster.Config, config.Persistence, error) { fx.go
635 > ctx := context.TODO()
636 > logger = log.With(logger, tag.ComponentMetadataInitializer)
637 > metricsHandler = metricsHandler.WithTags(metrics.ServiceNameTag(primitives.ServerService))
638 > clusterName := persistenceClient.ClusterName(svc.ClusterMetadata.CurrentClusterName)
639 > dataStoreFactory := persistenceClient.DataStoreFactoryProvider(
640 > clusterName,
641 > persistenceServiceResolver,
642 > &svc.Persistence,
643 > customDataStoreFactory,
644 > logger,
645 > metricsHandler,
646 > telemetry.NoopTracerProvider,
647 > serializer,
648 > )
649 > factory := persistenceFactoryProvider(persistenceClient.NewFactoryParams{
650 > DataStoreFactory: dataStoreFactory,
651 > Cfg: &svc.Persistence,
652 > PersistenceMaxQPS: nil,
653 > PersistenceNamespaceMaxQPS: nil,
654 > ClusterName: persistenceClient.ClusterName(svc.ClusterMetadata.CurrentClusterName),
655 > MetricsHandler: metricsHandler,
656 > Logger: logger,
657 > Serializer: serializer,
658 > })
659 > defer factory.Close()
660 >
661 > clusterMetadataManager, err := factory.NewClusterMetadataManager()
662 > if err != nil {
663 return svc.ClusterMetadata, svc.Persistence, fmt.Errorf("error initializing cluster metadata manager: %w", err)
664 }
665 > defer clusterMetadataManager.Close() fx.go
666 >
667 > visCSAOverride := map[enumspb.IndexedValueType]int{}
668 > for tpName, value := range svc.Visibility.PersistenceCustomSearchAttributes {
669 saType, ok := enumspb.IndexedValueType_shorthandValue[tpName]
670 if !ok {
684 }
685
686 > visDataStores := []config.DataStore{ fx.go
687 > svc.Persistence.GetVisibilityStoreConfig(),
688 > svc.Persistence.GetSecondaryVisibilityStoreConfig(),
689 > }
690 > indexSearchAttributes := make(map[string]*persistencespb.IndexSearchAttributes)
691 > for _, ds := range visDataStores {
692 > indexSearchAttributes[ds.GetIndexName()] = sadefs.GetDBIndexSearchAttributes(visCSAOverride)
693 > }
694
695 > clusterMetadata := svc.ClusterMetadata fx.go
696 > if len(clusterMetadata.ClusterInformation) > 1 {
697 logger.Warn(
698 "All remote cluster settings under ClusterMetadata.ClusterInformation config will be ignored. "+
700 tag.Key("clusterInformation"))
701 }
702 > if _, ok := clusterMetadata.ClusterInformation[clusterMetadata.CurrentClusterName]; !ok { fx.go
703 logger.Error("Current cluster setting is missing under clusterMetadata.ClusterInformation",
704 tag.ClusterName(clusterMetadata.CurrentClusterName))
705 return svc.ClusterMetadata, svc.Persistence, missingCurrentClusterMetadataErr
706 }
707 > ctx = headers.SetCallerInfo(ctx, headers.SystemOperatorCallerInfo) fx.go
708 > resp, err := clusterMetadataManager.GetClusterMetadata(
709 > ctx,
710 > &persistence.GetClusterMetadataRequest{ClusterName: clusterMetadata.CurrentClusterName},
711 > )
712 > switch err.(type) {
713 case nil:
714 // Update current record
728 logger,
729 )
730 > case *serviceerror.NotFound: fx.go
731 > // Initialize current cluster record
732 > if initErr := initCurrentClusterMetadataRecord(
733 > ctx,
734 > clusterMetadataManager,
735 > svc,
736 > indexSearchAttributes,
737 > logger,
738 > ); initErr != nil {
739 return svc.ClusterMetadata, svc.Persistence, initErr
740 }
743 }
744
745 > clusterLoader := NewClusterMetadataLoader(clusterMetadataManager, logger) fx.go
746 > err = clusterLoader.LoadAndMergeWithStaticConfig(ctx, svc)
747 > if err != nil {
748 return svc.ClusterMetadata, svc.Persistence, fmt.Errorf("error while loading metadata from cluster: %w", err)
749 }
750 > return svc.ClusterMetadata, svc.Persistence, nil fx.go
751 }
752
757 initialIndexSearchAttributes map[string]*persistencespb.IndexSearchAttributes,
758 logger log.Logger,
759 > ) error { fx.go
760 > var clusterId string
761 > currentClusterName := svc.ClusterMetadata.CurrentClusterName
762 > currentClusterInfo := svc.ClusterMetadata.ClusterInformation[currentClusterName]
763 > if uuid.Validate(currentClusterInfo.ClusterID) != nil {
764 > if currentClusterInfo.ClusterID != "" {
765 logger.Warn("Cluster Id in Cluster Metadata config is not a valid uuid. Generating a new Cluster Id")
766 }
767 > clusterId = uuid.NewString() fx.go
768 } else {
769 clusterId = currentClusterInfo.ClusterID
770 }
771
772 > applied, err := clusterMetadataManager.SaveClusterMetadata( fx.go
773 > ctx,
774 > &persistence.SaveClusterMetadataRequest{
775 > ClusterMetadata: &persistencespb.ClusterMetadata{
776 > HistoryShardCount: svc.Persistence.NumHistoryShards,
777 > ClusterName: currentClusterName,
778 > ClusterId: clusterId,
779 > ClusterAddress: currentClusterInfo.RPCAddress,
780 > HttpAddress: currentClusterInfo.HTTPAddress,
781 > FailoverVersionIncrement: svc.ClusterMetadata.FailoverVersionIncrement,
782 > InitialFailoverVersion: currentClusterInfo.InitialFailoverVersion,
783 > IsGlobalNamespaceEnabled: svc.ClusterMetadata.EnableGlobalNamespace,
784 > IsConnectionEnabled: currentClusterInfo.Enabled,
785 > UseClusterIdMembership: true, // Enable this for new cluster after 1.19. This is to prevent two clusters join into one ring.
786 > IndexSearchAttributes: initialIndexSearchAttributes,
787 > Tags: svc.ClusterMetadata.Tags,
788 > },
789 > })
790 > if err != nil {
791 logger.Warn("Failed to save cluster metadata.", tag.Error(err), tag.ClusterName(currentClusterName))
792 return err
793 }
794 > if !applied { fx.go
795 logger.Error("Failed to apply cluster metadata.", tag.ClusterName(currentClusterName))
796 return clusterMetadataInitErr
797 }
798 > return nil fx.go
799 }
800
916 }
917
918 > func PersistenceFactoryProvider() persistenceClient.FactoryProviderFn { fx.go
919 > return persistenceClient.FactoryProvider
920 > }
921
922 func ServerLifetimeHooks(
923 lc fx.Lifecycle,
924 svr *ServerImpl,
925 > ) { fx.go
926 > lc.Append(fx.StartStopHook(svr.Start, svr.Stop))
927 > }
928
929 func verifyPersistenceCompatibleVersion(
931 persistenceServiceResolver resolver.ServiceResolver,
932 logger log.Logger,
933 > ) error { fx.go
934 > // cassandra schema version validation
935 > if err := cassandra.VerifyCompatibleVersion(cfg, persistenceServiceResolver, logger); err != nil {
936 return fmt.Errorf("cassandra schema version compatibility check failed: %w", err)
937 }
938 // sql schema version validation
939 > if err := sql.VerifyCompatibleVersion(cfg, persistenceServiceResolver, logger); err != nil { fx.go
940 return fmt.Errorf("sql schema version compatibility check failed: %w", err)
941 }
942 > return nil fx.go
943 }
944
956 // - []go.opentelemetry.io/otel/sdk/trace.SpanExporter
957 var TraceExportModule = fx.Options(
958 > fx.Provide(func(inputs SpanExporterInputs) ([]otelsdktrace.SpanExporter, error) { fx.go
959 > var tracingReady atomic.Bool
960 > otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) {
961 if tracingReady.Load() { // ignore errors during startup
962 inputs.Logger.Warn("OTEL error", tag.Error(err), tag.ServiceErrorType(err))
965
966 // (1) Exporters from config.
967 > exportersByType := map[telemetry.SpanExporterType]otelsdktrace.SpanExporter{} fx.go
968 > if inputs.Config != nil {
969 > var err error
970 > exportersByType, err = inputs.Config.ExporterConfig.SpanExporters()
971 > if err != nil {
972 return nil, err
973 }
975
976 // (2) Exporters from env variables.
977 > exportersByTypeFromEnv, err := telemetry.SpanExportersFromEnv(os.LookupEnv) fx.go
978 > if err != nil {
979 return nil, err
980 }
981
982 // (3) Exporters from code (ie from testing).
983 > customExportersByType := inputs.Config.ExporterConfig.CustomExporters fx.go
984 >
985 > // Merge exporters.
986 > maps.Copy(exportersByType, exportersByTypeFromEnv) // env overrides config
987 > maps.Copy(exportersByType, customExportersByType) // custom overrides all
988 > exporters := expmaps.Values(exportersByType)
989 >
990 > // Configure exporters' lifecycle hooks.
991 > inputs.Lifecycyle.Append(fx.Hook{
992 > OnStart: func(ctx context.Context) error {
993 > err = startAll(exporters)(ctx)
994 > tracingReady.Store(true)
995 > return err
996 > },
997 OnStop: shutdownAll(exporters),
998 })
999 > return exporters, nil fx.go
1000 }),
1001 )
1020 fx.Provide(
1021 fx.Annotate(
1022 > func(exps []otelsdktrace.SpanExporter, opts []otelsdktrace.BatchSpanProcessorOption) []otelsdktrace.SpanProcessor { fx.go
1023 > sps := make([]otelsdktrace.SpanProcessor, 0, len(exps))
1024 > for _, exp := range exps {
1025 sps = append(sps, otelsdktrace.NewBatchSpanProcessor(exp, opts...))
1026 }
1027 > return sps fx.go
1028 },
1029 fx.ParamTags(`optional:"true"`, ``),
1032 fx.Provide(
1033 fx.Annotate(
1034 > func(rsn primitives.ServiceName, rsi resource.InstanceID) (*otelresource.Resource, error) { fx.go
1035 > attrs := []attribute.KeyValue{
1036 > semconv.ServiceNameKey.String(telemetry.ResourceServiceName(rsn, os.LookupEnv)),
1037 > semconv.ServiceVersionKey.String(headers.ServerVersion),
1038 > }
1039 > if rsi != "" {
1040 attrs = append(attrs, semconv.ServiceInstanceIDKey.String(string(rsi)))
1041 }
1042
1043 > return otelresource.New(context.Background(), fx.go
1044 > otelresource.WithProcess(),
1045 > otelresource.WithOS(),
1046 > otelresource.WithHost(),
1047 > otelresource.WithContainer(),
1048 > otelresource.WithAttributes(attrs...),
1049 > )
1050 },
1051 fx.ParamTags(``, `optional:"true"`),
1052 ),
1053 ),
1054 > fx.Provide(func(lc fx.Lifecycle, r *otelresource.Resource, sps []otelsdktrace.SpanProcessor) trace.TracerProvider { fx.go
1055 > if len(sps) == 0 {
1056 > return telemetry.NoopTracerProvider fx.go
1057 > }
1058 opts := make([]otelsdktrace.TracerProviderOption, 0, len(sps)+1)
1059 opts = append(opts, otelsdktrace.WithResource(r))
1082 }),
1083 // Haven't had use for baggage propagation yet
1084 > fx.Provide(func() propagation.TextMapPropagator { return propagation.TraceContext{} }), fx.go
1085 fx.Provide(telemetry.NewServerStatsHandler),
1086 fx.Provide(telemetry.NewClientStatsHandler),
1088 )
1089
1090 > func startAll(exporters []otelsdktrace.SpanExporter) func(ctx context.Context) error { fx.go
1091 > type starter interface{ Start(context.Context) error }
1092 > return func(ctx context.Context) error {
1093 > for _, e := range exporters {
1094 if starter, ok := e.(starter); ok {
1095 err := starter.Start(ctx)
1099 }
1100 }
1101 > return nil fx.go
1102 }
1103 }
1104
1105 > func shutdownAll(exporters []otelsdktrace.SpanExporter) func(ctx context.Context) error { fx.go
1106 > return func(ctx context.Context) error {
1107 > shutdownCtx, cancel := context.WithTimeout(context.Background(), 1*time.Second) fx.go
1108 > defer cancel()
1109 >
1110 > for _, e := range exporters {
1111 err := e.Shutdown(shutdownCtx)
1112 if errors.Is(err, context.DeadlineExceeded) {
1116 }
1117 }
1118 > return nil fx.go
1119 }
1120 }
1121
1122 > var FxLogAdapter = fx.WithLogger(func(logger log.Logger) fxevent.Logger { fx.go
1123 > return &fxLogAdapter{logger: logger}
1124 > })
1125
1126 type fxLogAdapter struct {
1128 }
1129
1130 > func (l *fxLogAdapter) LogEvent(e fxevent.Event) { fx.go
1131 > switch e := e.(type) {
1132 > case *fxevent.OnStartExecuting:
1133 > l.logger.Debug("OnStart hook executing",
1134 > tag.ComponentFX,
1135 > tag.String("callee", e.FunctionName),
1136 > tag.String("caller", e.CallerName),
1137 > )
1138 > case *fxevent.OnStartExecuted:
1139 > if e.Err != nil {
1140 l.logger.Error("OnStart hook failed",
1141 tag.ComponentFX,
1144 tag.Error(e.Err),
1145 )
1146 > } else { fx.go
1147 > l.logger.Debug("OnStart hook executed",
1148 > tag.ComponentFX,
1149 > tag.String("callee", e.FunctionName),
1150 > tag.String("caller", e.CallerName),
1151 > tag.Stringer("runtime", e.Runtime),
1152 > )
1153 > }
1154 > case *fxevent.OnStopExecuting: fx.go
1155 > l.logger.Debug("OnStop hook executing",
1156 > tag.ComponentFX,
1157 > tag.String("callee", e.FunctionName),
1158 > tag.String("caller", e.CallerName),
1159 > )
1160 > case *fxevent.OnStopExecuted:
1161 > if e.Err != nil {
1162 l.logger.Error("OnStop hook failed",
1163 tag.ComponentFX,
1166 tag.Error(e.Err),
1167 )
1168 > } else { fx.go
1169 > l.logger.Debug("OnStop hook executed",
1170 > tag.ComponentFX,
1171 > tag.String("callee", e.FunctionName),
1172 > tag.String("caller", e.CallerName),
1173 > tag.Stringer("runtime", e.Runtime),
1174 > )
1175 > }
1176 > case *fxevent.Supplied: fx.go
1177 > if e.Err != nil {
1178 l.logger.Error("supplied",
1179 tag.ComponentFX,
1182 tag.Error(e.Err))
1183 }
1184 > case *fxevent.Provided: fx.go
1185 > if e.Err != nil {
1186 l.logger.Error("error encountered while applying options",
1187 tag.ComponentFX,
1196 tag.Error(e.Err))
1197 }
1198 > case *fxevent.Decorated: fx.go
1199 > if e.Err != nil {
1200 l.logger.Error("error encountered while applying options",
1201 tag.ComponentFX,
1203 tag.Error(e.Err))
1204 }
1205 > case *fxevent.Run: fx.go
1206 > if e.Err != nil {
1207 l.logger.Error("error returned",
1208 tag.ComponentFX,
1213 )
1214 }
1215 > case *fxevent.Invoking: fx.go
1216 > // Do not log stack as it will make logs hard to read.
1217 > l.logger.Debug("invoking",
1218 > tag.ComponentFX,
1219 > tag.String("function", e.FunctionName),
1220 > tag.String("module", e.ModuleName),
1221 > )
1222 > case *fxevent.Invoked:
1223 > if e.Err != nil {
1224 l.logger.Error("invoke failed",
1225 tag.ComponentFX,
1234 tag.ComponentFX,
1235 tag.Stringer("signal", e.Signal))
1236 > case *fxevent.Stopped: fx.go
1237 > if e.Err != nil {
1238 l.logger.Error("stop failed", tag.ComponentFX, tag.Error(e.Err))
1239 }
1244 l.logger.Error("rollback failed", tag.ComponentFX, tag.Error(e.Err))
1245 }
1246 > case *fxevent.Started: fx.go
1247 > if e.Err != nil {
1248 l.logger.Error("start failed", tag.ComponentFX, tag.Error(e.Err))
1249 > } else { fx.go
1250 > l.logger.Debug("started", tag.ComponentFX)
1251 > }
1252 > case *fxevent.LoggerInitialized:
1253 > if e.Err != nil {
1254 l.logger.Error("custom logger initialization failed", tag.ComponentFX, tag.Error(e.Err))
1255 > } else { fx.go
1256 > l.logger.Debug("initialized custom fxevent.Logger",
1257 > tag.ComponentFX,
1258 > tag.String("function", e.ConstructorName))
1259 > }
1260 > case *fxevent.BeforeRun:
1261 > l.logger.Debug("before run",
1262 > tag.ComponentFX,
1263 > tag.String("name", e.Name),
1264 > tag.String("kind", e.Kind),
1265 > tag.String("module", e.ModuleName),
1266 > )
1267 default:
1268 l.logger.Warn("unknown fx log type, update fxLogAdapter",
go.temporal.io/server/service/frontend/workflow_handler.go 448 covered LOC · 111 ranges

Open complete file

339 workerDeploymentReadRateLimiter quotas.RequestRateLimiter,
340 validator *workflow.RequestValidator,
341 > ) *WorkflowHandler { workflow_handler.go
342 > handler := &WorkflowHandler{
343 > ActivityHandler: activityHandler,
344 > NexusOperationHandler: nexusOperationHandler,
345 > status: common.DaemonStatusInitialized,
346 > callbackValidator: callbackValidator,
347 > config: config,
348 > tokenSerializer: tasktoken.NewSerializer(),
349 > versionChecker: headers.NewDefaultVersionChecker(),
350 > namespaceHandler: newNamespaceHandler(
351 > logger,
352 > persistenceMetadataManager,
353 > namespaceRegistry,
354 > clusterMetadata,
355 > nsreplication.NewReplicator(namespaceReplicationQueue, logger),
356 > archivalMetadata,
357 > archiverProvider,
358 > timeSource,
359 > config,
360 > ),
361 > getDefaultWorkflowRetrySettings: config.DefaultWorkflowRetryPolicy,
362 > visibilityMgr: visibilityMgr,
363 > logger: logger,
364 > throttledLogger: throttledLogger,
365 > persistenceExecutionName: persistenceExecutionName,
366 > clusterMetadataManager: clusterMetadataManager,
367 > clusterMetadata: clusterMetadata,
368 > historyClient: historyClient,
369 > matchingClient: matchingClient,
370 > workerDeploymentClient: workerDeploymentClient,
371 > schedulerClient: schedulerClient,
372 > archiverProvider: archiverProvider,
373 > payloadSerializer: payloadSerializer,
374 > namespaceRegistry: namespaceRegistry,
375 > saProvider: saProvider,
376 > saMapperProvider: saMapperProvider,
377 > saValidator: saValidator,
378 > archivalMetadata: archivalMetadata,
379 > healthServer: healthServer,
380 > overrides: NewOverrides(),
381 > membershipMonitor: membershipMonitor,
382 > healthInterceptor: healthInterceptor,
383 > scheduleSpecBuilder: scheduleSpecBuilder,
384 > outstandingPollers: collection.NewSyncMap[string, collection.SyncMap[string, context.CancelFunc]](),
385 > httpEnabled: httpEnabled,
386 > registry: registry,
387 > workerDeploymentReadRateLimiter: workerDeploymentReadRateLimiter,
388 > validator: validator,
389 > }
390 >
391 > return handler
392 > }
393
394 // Start starts the handler
395 > func (wh *WorkflowHandler) Start() { workflow_handler.go
396 > if atomic.CompareAndSwapInt32(
397 > &wh.status,
398 > common.DaemonStatusInitialized,
399 > common.DaemonStatusStarted,
400 > ) {
401 > // Start in NOT_SERVING state and switch to SERVING after membership is ready
402 > wh.healthServer.SetServingStatus(WorkflowServiceName, healthpb.HealthCheckResponse_NOT_SERVING)
403 > go func() {
404 > _ = wh.membershipMonitor.WaitUntilInitialized(context.Background())
405 > wh.healthServer.SetServingStatus(WorkflowServiceName, healthpb.HealthCheckResponse_SERVING)
406 > wh.healthInterceptor.SetHealthy(true)
407 > wh.logger.Info("Frontend is now healthy")
408 > }()
409
410 > wh.namespaceRegistry.RegisterStateChangeCallback(wh, func(ns *namespace.Namespace, deletedFromDb bool) { workflow_handler.go
411 > if deletedFromDb {
412 return
413 }
414
415 > if ns.IsGlobalNamespace() && workflow_handler.go
416 > ns.ReplicationPolicy() == namespace.ReplicationPolicyMultiCluster &&
417 > //nolint:forbidigo // namespace state-change callback; cancels all pollers on ns deactivation
418 > !ns.ActiveInCluster(wh.clusterMetadata.GetCurrentClusterName()) {
419 pollers, ok := wh.outstandingPollers.Get(ns.ID().String())
420 if ok {
429
430 // Stop stops the handler
431 > func (wh *WorkflowHandler) Stop() { workflow_handler.go
432 > if atomic.CompareAndSwapInt32(
433 > &wh.status,
434 > common.DaemonStatusStarted,
435 > common.DaemonStatusStopped,
436 > ) {
437 > wh.namespaceRegistry.UnregisterStateChangeCallback(wh)
438 > wh.healthServer.SetServingStatus(WorkflowServiceName, healthpb.HealthCheckResponse_NOT_SERVING)
439 > wh.healthInterceptor.SetHealthy(false)
440 > }
441 }
442
450 // acts as a sandbox and provides isolation for all resources within the namespace. All resources belong to exactly one
451 // namespace.
452 > func (wh *WorkflowHandler) RegisterNamespace(ctx context.Context, request *workflowservice.RegisterNamespaceRequest) (_ *workflowservice.RegisterNamespaceResponse, retError error) { workflow_handler.go
453 > defer log.CapturePanic(wh.logger, &retError)
454 >
455 > if request == nil {
456 return nil, errRequestNotSet
457 }
458
459 > if err := wh.validateNamespace(request.GetNamespace()); err != nil { workflow_handler.go
460 return nil, err
461 }
462
463 > resp, err := wh.namespaceHandler.RegisterNamespace(ctx, request) workflow_handler.go
464 > if err != nil {
465 return nil, err
466 }
467
468 > return resp, nil workflow_handler.go
469 }
470
471 // DescribeNamespace returns the information and configuration for a registered namespace.
472 > func (wh *WorkflowHandler) DescribeNamespace(ctx context.Context, request *workflowservice.DescribeNamespaceRequest) (_ *workflowservice.DescribeNamespaceResponse, retError error) { workflow_handler.go
473 > defer log.CapturePanic(wh.logger, &retError)
474 >
475 > if request == nil {
476 return nil, errRequestNotSet
477 }
478
479 > resp, err := wh.namespaceHandler.DescribeNamespace(ctx, request) workflow_handler.go
480 > if err != nil {
481 return resp, err
482 }
483 > return resp, err workflow_handler.go
484 }
485
539 ctx context.Context,
540 request *workflowservice.StartWorkflowExecutionRequest,
541 > ) (_ *workflowservice.StartWorkflowExecutionResponse, retError error) { workflow_handler.go
542 > defer log.CapturePanic(wh.logger, &retError)
543 >
544 > var err error
545 > if request, err = wh.prepareStartWorkflowRequest(ctx, request); err != nil {
546 return nil, err
547 }
548
549 > wh.logger.Debug("Received StartWorkflowExecution.", tag.WorkflowID(request.GetWorkflowId()), tag.WorkflowType(request.GetWorkflowType().GetName())) workflow_handler.go
550 >
551 > namespaceName := namespace.Name(request.GetNamespace())
552 >
553 > wh.logger.Debug("Start workflow execution request namespace.", tag.WorkflowNamespace(namespaceName.String()))
554 > namespaceID, err := wh.namespaceRegistry.GetNamespaceID(namespaceName)
555 > if err != nil {
556 return nil, err
557 }
558 > wh.logger.Debug("Start workflow execution request namespaceID.", tag.WorkflowNamespaceID(namespaceID.String())) workflow_handler.go
559 >
560 > resp, err := wh.historyClient.StartWorkflowExecution(
561 > ctx,
562 > common.CreateHistoryStartWorkflowRequest(
563 > namespaceID.String(),
564 > request,
565 > nil,
566 > nil,
567 > time.Now().UTC(),
568 > ),
569 > )
570 > if err != nil {
571 > return nil, err workflow_handler.go
572 > }
573 > return wh.convertToStartWorkflowExecutionResponse(resp, namespaceName) workflow_handler.go
574 }
575
577 resp *historyservice.StartWorkflowExecutionResponse,
578 namespaceName namespace.Name,
579 > ) (*workflowservice.StartWorkflowExecutionResponse, error) { workflow_handler.go
580 > if resp.GetEagerWorkflowTask() != nil {
581 if err := api.ProcessOutgoingSearchAttributes(
582 wh.saProvider,
590 }
591
592 > return &workflowservice.StartWorkflowExecutionResponse{ workflow_handler.go
593 > RunId: resp.GetRunId(),
594 > FirstExecutionRunId: resp.GetFirstExecutionRunId(),
595 > Started: resp.Started,
596 > EagerWorkflowTask: resp.GetEagerWorkflowTask(),
597 > Link: resp.GetLink(),
598 > Status: resp.GetStatus(),
599 > }, nil
600 }
601
604 ctx context.Context,
605 request *workflowservice.StartWorkflowExecutionRequest,
606 > ) (*workflowservice.StartWorkflowExecutionRequest, error) { workflow_handler.go
607 > if request == nil {
608 return nil, errRequestNotSet
609 }
610
611 // Apply defaults before validation; must be first for idempotency on internal retries.
612 > enums.SetDefaultWorkflowIDPolicies( workflow_handler.go
613 > &request.WorkflowIdReusePolicy,
614 > &request.WorkflowIdConflictPolicy,
615 > enumspb.WORKFLOW_ID_CONFLICT_POLICY_FAIL,
616 > )
617 >
618 > if err := wh.validator.ValidateWorkflowID(request.GetWorkflowId()); err != nil {
619 return nil, err
620 }
621
622 > namespaceName := namespace.Name(request.GetNamespace()) workflow_handler.go
623 > if err := wh.validator.ValidateRetryPolicy(request.GetNamespace(), request.RetryPolicy); err != nil {
624 return nil, err
625 }
626
627 > if err := wh.validator.ValidateWorkflowStartDelay(request.GetCronSchedule(), request.WorkflowStartDelay); err != nil { workflow_handler.go
628 return nil, err
629 }
630
631 > if err := backoff.ValidateSchedule(request.GetCronSchedule()); err != nil { workflow_handler.go
632 return nil, err
633 }
634
635 > if request.WorkflowType == nil || request.WorkflowType.GetName() == "" { workflow_handler.go
636 return nil, errWorkflowTypeNotSet
637 }
638
639 > if len(request.WorkflowType.GetName()) > wh.config.MaxIDLengthLimit() { workflow_handler.go
640 return nil, errWorkflowTypeTooLong
641 }
642
643 > if err := tqid.NormalizeAndValidateUserDefined(request.TaskQueue, "", "", wh.config.MaxIDLengthLimit()); err != nil { workflow_handler.go
644 return nil, err
645 }
646
647 > if err := wh.validator.ValidateWorkflowTimeouts(request); err != nil { workflow_handler.go
648 return nil, err
649 }
650
651 > if err := validateRequestId(&request.RequestId, wh.config.MaxIDLengthLimit()); err != nil { workflow_handler.go
652 return nil, err
653 }
654
655 > if err := wh.validator.ValidateWorkflowIDReusePolicy( workflow_handler.go
656 > request.WorkflowIdReusePolicy,
657 > request.WorkflowIdConflictPolicy); err != nil {
658 return nil, err
659 }
660
661 > if err := wh.validateOnConflictOptions(request.OnConflictOptions); err != nil { workflow_handler.go
662 return nil, err
663 }
664
665 > sa, err := wh.validator.UnaliasedSearchAttributesFrom(request.GetSearchAttributes(), request.GetNamespace()) workflow_handler.go
666 > if err != nil {
667 return nil, err
668 }
669 > if sa != request.SearchAttributes { workflow_handler.go
670 // Since unaliasedSearchAttributesFrom is not idempotent, we need to clone the request so that
671 // in case of retries, the field is set to the original value.
674 }
675
676 > if err := priorities.Validate(request.Priority); err != nil { workflow_handler.go
677 return nil, err
678 }
679
680 > if cbs := request.GetCompletionCallbacks(); len(cbs) > 0 { workflow_handler.go
681 if err := wh.callbackValidator.Validate(ctx, namespaceName.String(), cbs); err != nil {
682 return nil, err
684 }
685
686 > request.Links = dedupLinksFromCallbacks(request.GetLinks(), request.GetCompletionCallbacks()) workflow_handler.go
687 >
688 > allLinks := make([]*commonpb.Link, 0, len(request.GetLinks())+len(request.GetCompletionCallbacks()))
689 > allLinks = append(allLinks, request.GetLinks()...)
690 > for _, cb := range request.GetCompletionCallbacks() {
691 allLinks = append(allLinks, cb.GetLinks()...)
692 }
693 > if err := commonlinks.Validate(allLinks, wh.config.MaxLinksPerRequest(namespaceName.String()), wh.config.LinkMaxSize(namespaceName.String())); err != nil { workflow_handler.go
694 return nil, err
695 }
696
697 > if err := wh.validateTimeSkippingConfig(request.GetTimeSkippingConfig(), namespaceName); err != nil { workflow_handler.go
698 return nil, err
699 }
700 > return request, nil workflow_handler.go
701 }
702
704 tsc *commonpb.TimeSkippingConfig,
705 ns namespace.Name,
706 > ) error { workflow_handler.go
707 > if tsc == nil {
708 > return nil workflow_handler.go
709 > }
710 // if this feature is not enabled, we don't allow setting any related config
711 if !wh.config.TimeSkippingEnabled(ns.String()) {
942 // GetWorkflowExecutionHistory returns the history of specified workflow execution. It fails with 'EntityNotExistError' if specified workflow
943 // execution in unknown to the service.
944 > func (wh *WorkflowHandler) GetWorkflowExecutionHistory(ctx context.Context, request *workflowservice.GetWorkflowExecutionHistoryRequest) (_ *workflowservice.GetWorkflowExecutionHistoryResponse, retError error) { workflow_handler.go
945 > defer log.CapturePanic(wh.logger, &retError)
946 >
947 > if request == nil {
948 return nil, errRequestNotSet
949 }
950
951 > if err := validateExecution(request.Execution); err != nil { workflow_handler.go
952 return nil, err
953 }
954
955 > if request.GetMaximumPageSize() <= 0 { workflow_handler.go
956 > request.MaximumPageSize = int32(wh.config.HistoryMaxPageSize(request.GetNamespace())) workflow_handler.go
957 > }
958
959 > enums.SetDefaultHistoryEventFilterType(&request.HistoryEventFilterType) workflow_handler.go
960 >
961 > namespaceID, err := wh.namespaceRegistry.GetNamespaceID(namespace.Name(request.GetNamespace()))
962 > if err != nil {
963 return nil, err
964 }
965
966 // force limit page size if exceed
967 > if request.GetMaximumPageSize() > primitives.GetHistoryMaxPageSize { workflow_handler.go
968 wh.throttledLogger.Warn("GetHistory page size is larger than threshold",
969 tag.WorkflowID(request.Execution.GetWorkflowId()),
973 }
974
975 > if !request.GetSkipArchival() { workflow_handler.go
976 enableArchivalRead := wh.archivalMetadata.GetHistoryConfig().ReadEnabled()
977 historyArchived := wh.historyArchived(ctx, request, namespaceID)
981 }
982
983 > response, err := wh.historyClient.GetWorkflowExecutionHistory(ctx, workflow_handler.go
984 > &historyservice.GetWorkflowExecutionHistoryRequest{
985 > NamespaceId: namespaceID.String(),
986 > Request: request,
987 > })
988 > if err != nil {
989 return nil, err
990 }
991
992 > isCloseEventOnly := request.HistoryEventFilterType == enumspb.HISTORY_EVENT_FILTER_TYPE_CLOSE_EVENT workflow_handler.go
993 > err = api.ProcessInternalRawHistory(
994 > ctx,
995 > wh.saProvider,
996 > wh.saMapperProvider,
997 > response,
998 > wh.visibilityMgr,
999 > wh.versionChecker,
1000 > namespace.Name(request.GetNamespace()),
1001 > isCloseEventOnly,
1002 > )
1003 > if err != nil {
1004 return nil, err
1005 }
1006 > return response.Response, nil workflow_handler.go
1007 }
1008
1054 // It will also create a 'WorkflowTaskStarted' event in the history for that session before handing off WorkflowTask to
1055 // application worker.
1056 > func (wh *WorkflowHandler) PollWorkflowTaskQueue(ctx context.Context, request *workflowservice.PollWorkflowTaskQueueRequest) (_ *workflowservice.PollWorkflowTaskQueueResponse, retError error) { workflow_handler.go
1057 > defer log.CapturePanic(wh.logger, &retError)
1058 > if request == nil {
1059 return nil, errRequestNotSet
1060 }
1061
1062 > wh.logger.Debug("Received PollWorkflowTaskQueue") workflow_handler.go
1063 > if err := common.ValidateLongPollContextTimeout(
1064 > ctx,
1065 > "PollWorkflowTaskQueue",
1066 > wh.throttledLogger,
1067 > ); err != nil {
1068 return nil, err
1069 }
1070
1071 > if len(request.GetIdentity()) > wh.config.MaxIDLengthLimit() { workflow_handler.go
1072 return nil, errIdentityTooLong
1073 }
1074
1075 //nolint:staticcheck // SA1019: worker versioning v0.31
1076 > if err := wh.validateVersioningInfo(request.Namespace, request.WorkerVersionCapabilities, request.DeploymentOptions, request.TaskQueue); err != nil { workflow_handler.go
1077 return nil, err
1078 }
1079
1080 > if request.TaskQueue.GetKind() == enumspb.TASK_QUEUE_KIND_UNSPECIFIED { workflow_handler.go
1081 wh.logger.Warn("Unspecified task queue kind",
1082 tag.WorkflowTaskQueueName(request.TaskQueue.GetName()),
1085 }
1086
1087 > if err := tqid.NormalizeAndValidate(request.TaskQueue, "", wh.config.MaxIDLengthLimit()); err != nil { workflow_handler.go
1088 return nil, err
1089 }
1090
1091 > callTime := time.Now().UTC() workflow_handler.go
1092 >
1093 > namespaceEntry, err := wh.namespaceRegistry.GetNamespace(namespace.Name(request.GetNamespace()))
1094 > if err != nil {
1095 return nil, err
1096 }
1097 > namespaceID := namespaceEntry.ID() workflow_handler.go
1098 >
1099 > wh.logger.Debug("Poll workflow task queue.", tag.WorkflowNamespace(namespaceEntry.Name().String()), tag.WorkflowNamespaceID(namespaceID.String()))
1100 > if err := wh.checkBadBinary(namespaceEntry, request.GetBinaryChecksum()); err != nil {
1101 return nil, err
1102 }
1103
1104 > if contextNearDeadline(ctx, longPollTailRoom) { workflow_handler.go
1105 return &workflowservice.PollWorkflowTaskQueueResponse{}, nil
1106 }
1107
1108 > pollerID := uuid.NewString() workflow_handler.go
1109 > childCtx := wh.registerOutstandingPollContext(ctx, pollerID, namespaceID.String())
1110 > defer wh.unregisterOutstandingPollContext(pollerID, namespaceID.String())
1111 >
1112 > matchingResp, err := wh.matchingClient.PollWorkflowTaskQueue(childCtx, &matchingservice.PollWorkflowTaskQueueRequest{
1113 > NamespaceId: namespaceID.String(),
1114 > PollerId: pollerID,
1115 > PollRequest: request,
1116 > })
1117 > if err != nil {
1118 > contextWasCanceled := wh.cancelOutstandingPoll(childCtx, namespaceID, enumspb.TASK_QUEUE_TYPE_WORKFLOW, request.TaskQueue, pollerID) workflow_handler.go
1119 > if contextWasCanceled {
1120 > // Clear error as we don't want to report context cancellation error to count against our SLA.
1121 > // It doesn't matter what to return here, client has already gone. But (nil,nil) is invalid gogo return pair.
1122 > return &workflowservice.PollWorkflowTaskQueueResponse{}, nil
1123 > }
1124
1125 // These errors are expected from some versioning situations. We should not log them, it'd be too noisy.
1150 // through to RawHistory field. The matching client auto-deserializes the repeated bytes into
1151 // a History message via gRPC wire compatibility.
1152 > history := matchingResp.History workflow_handler.go
1153 > if matchingResp.RawHistory != nil {
1154 history = matchingResp.RawHistory
1155 // Process search attributes for raw history since it bypasses the normal processing path.
1165 }
1166
1167 > return &workflowservice.PollWorkflowTaskQueueResponse{ workflow_handler.go
1168 > TaskToken: matchingResp.TaskToken,
1169 > WorkflowExecution: matchingResp.WorkflowExecution,
1170 > WorkflowType: matchingResp.WorkflowType,
1171 > PreviousStartedEventId: matchingResp.PreviousStartedEventId,
1172 > StartedEventId: matchingResp.StartedEventId,
1173 > Query: matchingResp.Query,
1174 > BacklogCountHint: matchingResp.BacklogCountHint,
1175 > Attempt: matchingResp.Attempt,
1176 > History: history,
1177 > NextPageToken: matchingResp.NextPageToken,
1178 > WorkflowExecutionTaskQueue: matchingResp.WorkflowExecutionTaskQueue,
1179 > ScheduledTime: matchingResp.ScheduledTime,
1180 > StartedTime: matchingResp.StartedTime,
1181 > Queries: matchingResp.Queries,
1182 > Messages: matchingResp.Messages,
1183 > PollerScalingDecision: matchingResp.PollerScalingDecision,
1184 > }, nil
1185 }
1186
1187 > func contextNearDeadline(ctx context.Context, tailroom time.Duration) bool { workflow_handler.go
1188 > if ctxDeadline, ok := ctx.Deadline(); ok {
1189 > return time.Now().Add(tailroom).After(ctxDeadline)
1190 > }
1191 return false
1192 }
1201 ctx context.Context,
1202 request *workflowservice.RespondWorkflowTaskCompletedRequest,
1203 > ) (_ *workflowservice.RespondWorkflowTaskCompletedResponse, retError error) { workflow_handler.go
1204 > defer log.CapturePanic(wh.logger, &retError)
1205 >
1206 > if request == nil {
1207 return nil, errRequestNotSet
1208 }
1209
1210 > if len(request.GetIdentity()) > wh.config.MaxIDLengthLimit() { workflow_handler.go
1211 return nil, errIdentityTooLong
1212 }
1213
1214 //nolint:staticcheck // SA1019: worker versioning v0.31
1215 > if err := wh.validateVersioningInfo( workflow_handler.go
1216 > request.Namespace,
1217 > request.WorkerVersionStamp,
1218 > request.DeploymentOptions,
1219 > request.StickyAttributes.GetWorkerTaskQueue(),
1220 > ); err != nil {
1221 return nil, err
1222 }
1223
1224 > wh.overrides.DisableEagerActivityDispatchForBuggyClients(ctx, request) workflow_handler.go
1225 >
1226 > namespaceID, err := wh.namespaceRegistry.GetNamespaceID(namespace.Name(request.GetNamespace()))
1227 > if err != nil {
1228 return nil, err
1229 }
1230
1231 > response, err := wh.historyClient.RespondWorkflowTaskCompleted(ctx, workflow_handler.go
1232 > &historyservice.RespondWorkflowTaskCompletedRequest{
1233 > NamespaceId: namespaceID.String(),
1234 > CompleteRequest: request,
1235 > },
1236 > )
1237 > if err != nil {
1238 return nil, err
1239 }
1240
1241 > return &workflowservice.RespondWorkflowTaskCompletedResponse{ workflow_handler.go
1242 > WorkflowTask: response.NewWorkflowTask,
1243 > ActivityTasks: response.ActivityTasks,
1244 > ResetHistoryEventId: response.ResetHistoryEventId,
1245 > }, nil
1246 }
1247
1321 // prevent the task from getting timed out. An event 'ActivityTaskStarted' event is also written to workflow execution
1322 // history before the ActivityTask is dispatched to application worker.
1323 > func (wh *WorkflowHandler) PollActivityTaskQueue(ctx context.Context, request *workflowservice.PollActivityTaskQueueRequest) (_ *workflowservice.PollActivityTaskQueueResponse, retError error) { workflow_handler.go
1324 > defer log.CapturePanic(wh.logger, &retError)
1325 >
1326 > callTime := time.Now().UTC()
1327 >
1328 > if request == nil {
1329 return nil, errRequestNotSet
1330 }
1331
1332 > wh.logger.Debug("Received PollActivityTaskQueue") workflow_handler.go
1333 > if err := common.ValidateLongPollContextTimeout(
1334 > ctx,
1335 > "PollActivityTaskQueue",
1336 > wh.throttledLogger,
1337 > ); err != nil {
1338 return nil, err
1339 }
1340
1341 > namespaceName := namespace.Name(request.GetNamespace()) workflow_handler.go
1342 > if err := tqid.NormalizeAndValidate(request.TaskQueue, "", wh.config.MaxIDLengthLimit()); err != nil {
1343 return nil, err
1344 }
1345 > if len(request.GetIdentity()) > wh.config.MaxIDLengthLimit() { workflow_handler.go
1346 return nil, errIdentityTooLong
1347 }
1348
1349 //nolint:staticcheck // SA1019: worker versioning v0.31
1350 > if err := wh.validateVersioningInfo(request.Namespace, request.WorkerVersionCapabilities, request.DeploymentOptions, request.TaskQueue); err != nil { workflow_handler.go
1351 return nil, err
1352 }
1353
1354 > namespaceID, err := wh.namespaceRegistry.GetNamespaceID(namespaceName) workflow_handler.go
1355 > if err != nil {
1356 return nil, err
1357 }
1358
1359 > if contextNearDeadline(ctx, longPollTailRoom) { workflow_handler.go
1360 return &workflowservice.PollActivityTaskQueueResponse{}, nil
1361 }
1362
1363 > pollerID := uuid.NewString() workflow_handler.go
1364 > childCtx := wh.registerOutstandingPollContext(ctx, pollerID, namespaceID.String())
1365 > defer wh.unregisterOutstandingPollContext(pollerID, namespaceID.String())
1366 > matchingResponse, err := wh.matchingClient.PollActivityTaskQueue(childCtx, &matchingservice.PollActivityTaskQueueRequest{
1367 > NamespaceId: namespaceID.String(),
1368 > PollerId: pollerID,
1369 > PollRequest: request,
1370 > })
1371 > if err != nil {
1372 > contextWasCanceled := wh.cancelOutstandingPoll(childCtx, namespaceID, enumspb.TASK_QUEUE_TYPE_ACTIVITY, request.TaskQueue, pollerID) workflow_handler.go
1373 > if contextWasCanceled {
1374 > // Clear error as we don't want to report context cancellation error to count against our SLA.
1375 > // It doesn't matter what to return here, client has already gone. But (nil,nil) is invalid gogo return pair.
1376 > return &workflowservice.PollActivityTaskQueueResponse{}, nil
1377 > }
1378
1379 // These errors are expected from some versioning situations. We should not log them, it'd be too noisy.
2995 }
2996
2997 > func (wh *WorkflowHandler) ShutdownWorker(ctx context.Context, request *workflowservice.ShutdownWorkerRequest) (_ *workflowservice.ShutdownWorkerResponse, retError error) { workflow_handler.go
2998 > defer log.CapturePanic(wh.logger, &retError)
2999 >
3000 > if request == nil {
3001 return nil, errRequestNotSet
3002 }
3003
3004 > namespaceID, err := wh.namespaceRegistry.GetNamespaceID(namespace.Name(request.GetNamespace())) workflow_handler.go
3005 > if err != nil {
3006 return nil, err
3007 }
3008
3009 // Run all shutdown operations concurrently to minimize latency.
3010 > var waitGroup sync.WaitGroup workflow_handler.go
3011 >
3012 > // Cancel outstanding polls (best-effort)
3013 > if wh.config.EnableCancelWorkerPollsOnShutdown(request.GetNamespace()) {
3014 waitGroup.Go(func() {
3015 if wh.config.EnableMatchingFanOutForPollCancellation(request.GetNamespace()) {
3022
3023 // Record final heartbeat (best-effort)
3024 > if request.WorkerHeartbeat != nil && wh.config.WorkerHeartbeatsEnabled(request.GetNamespace()) { workflow_handler.go
3025 > waitGroup.Go(func() { workflow_handler.go
3026 > _, err := wh.matchingClient.RecordWorkerHeartbeat(ctx, &matchingservice.RecordWorkerHeartbeatRequest{
3027 > NamespaceId: namespaceID.String(),
3028 > HeartbeartRequest: &workflowservice.RecordWorkerHeartbeatRequest{
3029 > Namespace: request.Namespace,
3030 > Identity: request.Identity,
3031 > WorkerHeartbeat: []*workerpb.WorkerHeartbeat{request.WorkerHeartbeat},
3032 > },
3033 > })
3034 > if err != nil {
3035 wh.logger.Error("Failed to record worker heartbeat during shutdown.",
3036 tag.WorkflowTaskQueueName(request.WorkerHeartbeat.GetTaskQueue()),
3042 // Unload sticky task queue (required - error fails shutdown)
3043 // TODO: update poller info to indicate poller was shut down (pass identity/reason along)
3044 > _, unloadError := wh.matchingClient.ForceUnloadTaskQueuePartition(ctx, &matchingservice.ForceUnloadTaskQueuePartitionRequest{ workflow_handler.go
3045 > NamespaceId: namespaceID.String(),
3046 > TaskQueuePartition: &taskqueuespb.TaskQueuePartition{
3047 > TaskQueue: request.GetStickyTaskQueue(),
3048 > TaskQueueType: enumspb.TASK_QUEUE_TYPE_WORKFLOW, // sticky task queues are always workflow queues
3049 > },
3050 > })
3051 >
3052 > waitGroup.Wait()
3053 >
3054 > if unloadError != nil {
3055 return nil, unloadError
3056 }
3057
3058 > return &workflowservice.ShutdownWorkerResponse{}, nil workflow_handler.go
3059 }
3060
3463
3464 // GetSystemInfo returns information about the Temporal system.
3465 > func (wh *WorkflowHandler) GetSystemInfo(ctx context.Context, request *workflowservice.GetSystemInfoRequest) (_ *workflowservice.GetSystemInfoResponse, retError error) { workflow_handler.go
3466 > defer log.CapturePanic(wh.logger, &retError)
3467 >
3468 > if request == nil {
3469 return nil, errRequestNotSet
3470 }
3471
3472 > return &workflowservice.GetSystemInfoResponse{ workflow_handler.go
3473 > ServerVersion: headers.ServerVersion,
3474 > // Capabilities should be added as needed. In many cases, capabilities are
3475 > // hardcoded boolean true values since older servers will respond with a
3476 > // form of this message without the field which is implied false.
3477 > Capabilities: &workflowservice.GetSystemInfoResponse_Capabilities{
3478 > SignalAndQueryHeader: true,
3479 > InternalErrorDifferentiation: true,
3480 > ActivityFailureIncludeHeartbeat: true,
3481 > SupportsSchedules: true,
3482 > EncodedFailureAttributes: true,
3483 > UpsertMemo: true,
3484 > EagerWorkflowStart: true,
3485 > SdkMetadata: true,
3486 > BuildIdBasedVersioning: true,
3487 > CountGroupByExecutionStatus: true,
3488 > Nexus: wh.httpEnabled,
3489 > ServerScaledDeployments: true,
3490 > },
3491 > }, nil
3492 }
3493
6470 }
6471
6472 > func (wh *WorkflowHandler) validateOnConflictOptions(opts *workflowpb.OnConflictOptions) error { workflow_handler.go
6473 > if opts == nil {
6474 > return nil
6475 > }
6476 if opts.AttachCompletionCallbacks && !opts.AttachRequestId {
6477 return serviceerror.NewInvalidArgument("attaching request ID is required for attaching completion callbacks")
6504 links []*commonpb.Link,
6505 callbacks []*commonpb.Callback,
6506 > ) []*commonpb.Link { workflow_handler.go
6507 > if len(links) == 0 {
6508 > return nil workflow_handler.go
6509 > }
6510 var res []*commonpb.Link
6511 callbacksLinks := make([]*commonpb.Link, 0, len(callbacks))
6536 }
6537
6538 > func (wh *WorkflowHandler) validateVersioningInfo(nsName string, id buildIdAndFlag, deploymentOptions *deploymentpb.WorkerDeploymentOptions, tq *taskqueuepb.TaskQueue) error { workflow_handler.go
6539 > // TODO: Deprecate old versioning checks
6540 > if id.GetUseVersioning() && !wh.config.EnableWorkerVersioningWorkflow(nsName) {
6541 return errWorkerVersioningWorkflowAPIsNotAllowed
6542 }
6543 > if tq.GetKind() == enumspb.TASK_QUEUE_KIND_STICKY && len(tq.GetNormalName()) == 0 { workflow_handler.go
6544 if id.GetUseVersioning() || deploymentOptions != nil {
6545 // Versioned pollers require a normal name to be set when polling on a sticky queue
6547 }
6548 }
6549 > if id.GetUseVersioning() && len(id.GetBuildId()) == 0 { workflow_handler.go
6550 return errUseVersioningWithoutBuildId
6551 }
6552 > if len(id.GetBuildId()) > wh.config.WorkerBuildIdSizeLimit() { workflow_handler.go
6553 return errBuildIdTooLong
6554 }
6555
6556 > return wh.validateDeploymentOptions(deploymentOptions) workflow_handler.go
6557 }
6558
6559 > func (wh *WorkflowHandler) validateDeploymentOptions(deploymentOptions *deploymentpb.WorkerDeploymentOptions) error { workflow_handler.go
6560 > if deploymentOptions == nil {
6561 > return nil
6562 > }
6563 if deploymentOptions.GetWorkerVersioningMode() != enumspb.WORKER_VERSIONING_MODE_VERSIONED {
6564 return nil // both deployment name and build ID fields are optional for unversioned workers
6708 taskQueue *taskqueuepb.TaskQueue,
6709 pollerID string,
6710 > ) bool { workflow_handler.go
6711 > // First check if this err is due to context cancellation. This means client connection to frontend is closed.
6712 > if !errors.Is(ctx.Err(), context.Canceled) {
6713 return false
6714 }
6716 // call to matching to notify this poller is gone to prevent any tasks being dispatched to zombie pollers.
6717 // TODO: specify a reasonable timeout for CancelOutstandingPoll.
6718 > _, err := wh.matchingClient.CancelOutstandingPoll( workflow_handler.go
6719 > rpc.CopyContextValues(context.TODO(), ctx),
6720 > &matchingservice.CancelOutstandingPollRequest{
6721 > NamespaceId: namespaceID.String(),
6722 > TaskQueueType: taskQueueType,
6723 > TaskQueue: taskQueue,
6724 > PollerId: pollerID,
6725 > },
6726 > )
6727 > // We can not do much if this call fails. Just log the error and move on.
6728 > if err != nil {
6729 wh.logger.Warn("Failed to cancel outstanding poller.",
6730 tag.WorkflowTaskQueueName(taskQueue.GetName()), tag.Error(err))
6731 }
6732
6733 > return true workflow_handler.go
6734 }
6735
6738 pollerID string,
6739 namespaceID string,
6740 > ) context.Context { workflow_handler.go
6741 >
6742 > if pollerID != "" {
6743 > nsPollers, ok := wh.outstandingPollers.Get(namespaceID)
6744 > if !ok {
6745 > nsPollers, _ = wh.outstandingPollers.GetOrSet(namespaceID, collection.NewSyncMap[string, context.CancelFunc]())
6746 > }
6747 > childCtx, cancel := context.WithCancel(ctx)
6748 > nsPollers.Set(pollerID, cancel)
6749 > return childCtx
6750 }
6751 return ctx
6755 pollerID string,
6756 namespaceID string,
6757 > ) { workflow_handler.go
6758 > nsPollers, ok := wh.outstandingPollers.Get(namespaceID)
6759 > if ok {
6760 > if cancel, exist := nsPollers.Pop(pollerID); exist {
6761 > cancel()
6762 > }
6763 }
6764 }
6765
6766 > func (wh *WorkflowHandler) checkBadBinary(namespaceEntry *namespace.Namespace, binaryChecksum string) error { workflow_handler.go
6767 > if err := namespaceEntry.VerifyBinaryChecksum(binaryChecksum); err != nil {
6768 return serviceerror.NewInvalidArgumentf("Binary %v already marked as bad deployment.", binaryChecksum)
6769 }
6770 > return nil workflow_handler.go
6771 }
6772
6773 > func validateRequestId(requestID *string, lenLimit int) error { workflow_handler.go
6774 > if requestID == nil {
6775 // should never happen, but just in case.
6776 return serviceerror.NewInvalidArgument("RequestId is nil")
6777 }
6778 > if *requestID == "" { workflow_handler.go
6779 // For easy direct API use, we default the request ID here but expect all
6780 // SDKs and other auto-retrying clients to set it
6795 func (wh *WorkflowHandler) validateNamespace(
6796 namespace string,
6797 > ) error { workflow_handler.go
6798 > if len(namespace) > wh.config.MaxIDLengthLimit() {
6799 return errNamespaceTooLong
6800 }
6801 > return nil workflow_handler.go
6802 }
6803
go.temporal.io/server/common/persistence/execution_manager.go 422 covered LOC · 109 ranges

Open complete file

48 transactionSizeLimit dynamicconfig.IntPropertyFn,
49 enableBestEffortDeleteTasksOnWorkflowUpdate dynamicconfig.BoolPropertyFn,
50 > ) ExecutionManager { execution_manager.go
51 > return &executionManagerImpl{
52 > serializer: serializer,
53 > eventBlobCache: eventBlobCache,
54 > persistence: persistence,
55 > logger: logger,
56 > pagingTokenSerializer: newJSONHistoryTokenSerializer(),
57 > transactionSizeLimit: transactionSizeLimit,
58 > enableBestEffortDeleteTasksOnWorkflowUpdate: enableBestEffortDeleteTasksOnWorkflowUpdate,
59 > }
60 > }
61
62 > func (m *executionManagerImpl) GetName() string { execution_manager.go
63 > return m.persistence.GetName()
64 > }
65
66 > func (m *executionManagerImpl) GetHistoryBranchUtil() HistoryBranchUtil { execution_manager.go
67 > return m.persistence.GetHistoryBranchUtil()
68 > }
69
70 // historySizeRollback records HistorySize increments applied to caller-owned ExecutionStats
85
86 // add applies sizeDiff to stats.HistorySize and remembers it so it can be reverted.
87 > func (r *historySizeRollback) add(stats *persistencespb.ExecutionStats, sizeDiff int) { execution_manager.go
88 > delta := int64(sizeDiff)
89 > stats.HistorySize += delta
90 > r.applied = append(r.applied, appliedHistorySize{stats: stats, delta: delta})
91 > }
92
93 // revertOnError undoes every applied increment if *err is non-nil. Intended to be deferred
94 // against a function's named return error.
95 > func (r *historySizeRollback) revertOnError(err *error) { execution_manager.go
96 > if *err == nil {
97 > return execution_manager.go
98 > }
99 for _, a := range r.applied {
100 a.stats.HistorySize -= a.delta
106 ctx context.Context,
107 request *CreateWorkflowExecutionRequest,
108 > ) (_ *CreateWorkflowExecutionResponse, retErr error) { execution_manager.go
109 >
110 > var rollback historySizeRollback
111 > defer rollback.revertOnError(&retErr)
112 >
113 > newSnapshot := request.NewWorkflowSnapshot
114 > newWorkflowXDCKVs, newWorkflowNewEvents, newHistoryDiff, err := m.serializeWorkflowEventBatches(
115 > ctx,
116 > request.ShardID,
117 > request.NewWorkflowSnapshot.ExecutionInfo,
118 > request.NewWorkflowEvents,
119 > )
120 > if err != nil {
121 return nil, err
122 }
123
124 > rollback.add(newSnapshot.ExecutionInfo.ExecutionStats, newHistoryDiff.SizeDiff) execution_manager.go
125 >
126 > if err := ValidateCreateWorkflowModeState(
127 > request.Mode,
128 > newSnapshot,
129 > ); err != nil {
130 return nil, err
131 }
132 > if err := ValidateCreateWorkflowStateStatus( execution_manager.go
133 > newSnapshot.ExecutionState.State,
134 > newSnapshot.ExecutionState.Status,
135 > ); err != nil {
136 return nil, err
137 }
138
139 > serializedNewWorkflowSnapshot, err := m.SerializeWorkflowSnapshot(&newSnapshot) execution_manager.go
140 > if err != nil {
141 return nil, err
142 }
143
144 > archetypeID, _ := m.assertAndConvertArchetypeID(request.ArchetypeID, "CreateWorkflowExecution") execution_manager.go
145 > newRequest := &InternalCreateWorkflowExecutionRequest{
146 > ShardID: request.ShardID,
147 > RangeID: request.RangeID,
148 > Mode: request.Mode,
149 > PreviousRunID: request.PreviousRunID,
150 > PreviousLastWriteVersion: request.PreviousLastWriteVersion,
151 > ArchetypeID: archetypeID,
152 > NewWorkflowSnapshot: *serializedNewWorkflowSnapshot,
153 > NewWorkflowNewEvents: newWorkflowNewEvents,
154 > }
155 >
156 > if _, err := m.persistence.CreateWorkflowExecution(ctx, newRequest); err != nil {
157 return nil, err
158 }
159 > m.addXDCCacheKV(newWorkflowXDCKVs) execution_manager.go
160 > return &CreateWorkflowExecutionResponse{
161 > NewMutableStateStats: *statusOfInternalWorkflowSnapshot(
162 > serializedNewWorkflowSnapshot,
163 > newHistoryDiff,
164 > ),
165 > }, nil
166 }
167
169 ctx context.Context,
170 request *UpdateWorkflowExecutionRequest,
171 > ) (_ *UpdateWorkflowExecutionResponse, retErr error) { execution_manager.go
172 >
173 > var rollback historySizeRollback
174 > defer rollback.revertOnError(&retErr)
175 >
176 > updateMutation := request.UpdateWorkflowMutation
177 > newSnapshot := request.NewWorkflowSnapshot
178 >
179 > updateWorkflowXDCKVs, updateWorkflowNewEvents, updateWorkflowHistoryDiff, err := m.serializeWorkflowEventBatches(
180 > ctx,
181 > request.ShardID,
182 > request.UpdateWorkflowMutation.ExecutionInfo,
183 > request.UpdateWorkflowEvents,
184 > )
185 > if err != nil {
186 return nil, err
187 }
188 > rollback.add(updateMutation.ExecutionInfo.ExecutionStats, updateWorkflowHistoryDiff.SizeDiff) execution_manager.go
189 >
190 > var newWorkflowXDCKVs map[XDCCacheKey]XDCCacheValue
191 > var newWorkflowNewEvents []*InternalAppendHistoryNodesRequest
192 > var newWorkflowHistoryDiff *HistoryStatistics
193 > if newSnapshot != nil {
194 newWorkflowXDCKVs, newWorkflowNewEvents, newWorkflowHistoryDiff, err = m.serializeWorkflowEventBatches(
195 ctx,
204 }
205
206 > if err := ValidateUpdateWorkflowModeState( execution_manager.go
207 > request.Mode,
208 > updateMutation,
209 > newSnapshot,
210 > ); err != nil {
211 return nil, err
212 }
213 > if err := ValidateUpdateWorkflowStateStatus( execution_manager.go
214 > updateMutation.ExecutionState.State,
215 > updateMutation.ExecutionState.Status,
216 > ); err != nil {
217 return nil, err
218 }
219
220 > serializedWorkflowMutation, err := m.SerializeWorkflowMutation(&updateMutation) execution_manager.go
221 > if err != nil {
222 return nil, err
223 }
224 > var serializedNewWorkflowSnapshot *InternalWorkflowSnapshot execution_manager.go
225 > if newSnapshot != nil {
226 serializedNewWorkflowSnapshot, err = m.SerializeWorkflowSnapshot(newSnapshot)
227 if err != nil {
230 }
231
232 > archetypeID, _ := m.assertAndConvertArchetypeID(request.ArchetypeID, "UpdateWorkflowExecution") execution_manager.go
233 > newRequest := &InternalUpdateWorkflowExecutionRequest{
234 > ShardID: request.ShardID,
235 > RangeID: request.RangeID,
236 >
237 > Mode: request.Mode,
238 >
239 > ArchetypeID: archetypeID,
240 >
241 > UpdateWorkflowMutation: *serializedWorkflowMutation,
242 > UpdateWorkflowNewEvents: updateWorkflowNewEvents,
243 > NewWorkflowSnapshot: serializedNewWorkflowSnapshot,
244 > NewWorkflowNewEvents: newWorkflowNewEvents,
245 > }
246 >
247 > err = m.persistence.UpdateWorkflowExecution(ctx, newRequest)
248 > switch err.(type) {
249 > case nil: execution_manager.go
250 > m.deleteHistoryTasks(ctx, request.ShardID, updateMutation.BestEffortDeleteTasks, updateMutation.ExecutionInfo.WorkflowId)
251 > m.addXDCCacheKV(updateWorkflowXDCKVs)
252 > m.addXDCCacheKV(newWorkflowXDCKVs)
253 > return &UpdateWorkflowExecutionResponse{
254 > UpdateMutableStateStats: *statusOfInternalWorkflowMutation(
255 > &newRequest.UpdateWorkflowMutation,
256 > updateWorkflowHistoryDiff,
257 > ),
258 > NewMutableStateStats: statusOfInternalWorkflowSnapshot(
259 > newRequest.NewWorkflowSnapshot,
260 > newWorkflowHistoryDiff,
261 > ),
262 > }, nil
263 case *CurrentWorkflowConditionFailedError,
264 *WorkflowConditionFailedError,
285 toDelete map[tasks.Category][]tasks.Key,
286 workflowID string,
288 > if !m.enableBestEffortDeleteTasksOnWorkflowUpdate() || len(toDelete) == 0 {
289 > return execution_manager.go
290 > }
291 for category, keys := range toDelete {
292 for _, key := range keys {
462 ctx context.Context,
463 request *GetWorkflowExecutionRequest,
464 > ) (*GetWorkflowExecutionResponse, error) { execution_manager.go
465 > if archetypeID, converted := m.assertAndConvertArchetypeID(request.ArchetypeID, "GetWorkflowExecution"); converted {
466 request = &GetWorkflowExecutionRequest{
467 ShardID: request.ShardID,
472 }
473 }
474 > response, respErr := m.persistence.GetWorkflowExecution(ctx, request) execution_manager.go
475 >
476 > var notFound *serviceerror.NotFound
477 > if errors.As(respErr, &notFound) {
478 // strip persistence-specific error message
479 respErr = serviceerror.NewNotFoundf(
480 "workflow execution not found for workflow ID %q and run ID %q", request.WorkflowID, request.RunID)
481 }
482 > if respErr != nil && response == nil { execution_manager.go
483 // try to utilize resp as much as possible, for RebuildMutableState API
484 return nil, respErr
485 }
486 > state, err := m.toWorkflowMutableState(response.State) execution_manager.go
487 > if err != nil {
488 return nil, err
489 }
490 > if state.ExecutionInfo.ExecutionStats == nil { execution_manager.go
491 state.ExecutionInfo.ExecutionStats = &persistencespb.ExecutionStats{
492 HistorySize: 0,
494 }
495
496 > newResponse := &GetWorkflowExecutionResponse{ execution_manager.go
497 > State: state,
498 > DBRecordVersion: response.DBRecordVersion,
499 > MutableStateStats: *statusOfInternalWorkflow(response.State, state, nil),
500 > }
501 > return newResponse, respErr
502 }
503
533 executionInfo *persistencespb.WorkflowExecutionInfo,
534 eventBatches []*WorkflowEvents,
535 > ) (map[XDCCacheKey]XDCCacheValue, []*InternalAppendHistoryNodesRequest, *HistoryStatistics, error) { execution_manager.go
536 > var historyStatistics HistoryStatistics
537 > if len(eventBatches) == 0 {
538 return nil, nil, &historyStatistics, nil
539 }
540
541 > xdcKVs := make(map[XDCCacheKey]XDCCacheValue, len(eventBatches)) execution_manager.go
542 > workflowNewEvents := make([]*InternalAppendHistoryNodesRequest, 0, len(eventBatches))
543 > for _, workflowEvents := range eventBatches {
544 > newEvents, err := m.serializeWorkflowEvents(shardID, workflowEvents)
545 > if err != nil {
546 return nil, nil, nil, err
547 }
548 > versionHistoryItems, _, baseWorkflowInfo, err := GetXDCCacheValue( execution_manager.go
549 > executionInfo,
550 > workflowEvents.Events[0].EventId,
551 > workflowEvents.Events[0].Version,
552 > )
553 > if err != nil {
554 return nil, nil, nil, err
555 }
556 > xdcKVs[NewXDCCacheKey( execution_manager.go
557 > definition.NewWorkflowKey(workflowEvents.NamespaceID, workflowEvents.WorkflowID, workflowEvents.RunID),
558 > workflowEvents.Events[0].EventId,
559 > workflowEvents.Events[0].Version,
560 > )] = NewXDCCacheValue(
561 > baseWorkflowInfo,
562 > versionHistoryItems,
563 > []*commonpb.DataBlob{newEvents.Node.Events},
564 > workflowEvents.Events[len(workflowEvents.Events)-1].EventId+1,
565 > )
566 > newEvents.ShardID = shardID
567 > workflowNewEvents = append(workflowNewEvents, newEvents)
568 > historyStatistics.SizeDiff += len(newEvents.Node.Events.Data)
569 > historyStatistics.CountDiff += len(workflowEvents.Events)
570 }
571 > return xdcKVs, workflowNewEvents, &historyStatistics, nil execution_manager.go
572 }
573
574 func (m *executionManagerImpl) addXDCCacheKV(
575 xdcKVs map[XDCCacheKey]XDCCacheValue,
577 > if m.eventBlobCache == nil {
578 return
579 }
580 > for k, v := range xdcKVs { execution_manager.go
581 > m.eventBlobCache.Put(k, v)
582 > }
583 }
584
585 func (m *executionManagerImpl) DeserializeBufferedEvents( // unexport
586 blobs []*commonpb.DataBlob,
587 > ) ([]*historypb.HistoryEvent, error) { execution_manager.go
588 >
589 > events := make([]*historypb.HistoryEvent, 0)
590 > for _, b := range blobs {
591 if b == nil {
592 // Should not happen, log and discard to prevent callers from consuming
601 events = append(events, history...)
602 }
603 > return events, nil execution_manager.go
604 }
605
607 shardID int32,
608 workflowEvents *WorkflowEvents,
609 > ) (*InternalAppendHistoryNodesRequest, error) { execution_manager.go
610 > if len(workflowEvents.Events) == 0 {
611 return nil, nil // allow update workflow without events
612 }
613
614 > request := &AppendHistoryNodesRequest{ execution_manager.go
615 > ShardID: shardID,
616 > BranchToken: workflowEvents.BranchToken,
617 > Events: workflowEvents.Events,
618 > PrevTransactionID: workflowEvents.PrevTxnID,
619 > TransactionID: workflowEvents.TxnID,
620 > }
621 >
622 > if workflowEvents.Events[0].EventId == common.FirstEventID {
623 > request.IsNewBranch = true execution_manager.go
624 > request.Info = BuildHistoryGarbageCleanupInfo(workflowEvents.NamespaceID, workflowEvents.WorkflowID, workflowEvents.RunID)
625 > }
626
627 > return m.serializeAppendHistoryNodesRequest(request) execution_manager.go
628 }
629
630 func (m *executionManagerImpl) SerializeWorkflowMutation( // unexport
631 input *WorkflowMutation,
632 > ) (*InternalWorkflowMutation, error) { execution_manager.go
633 >
634 > serializedTasks, err := serializeTasks(m.serializer, input.Tasks)
635 > if err != nil {
636 return nil, err
637 }
638
639 > result := &InternalWorkflowMutation{ execution_manager.go
640 > NamespaceID: input.ExecutionInfo.GetNamespaceId(),
641 > WorkflowID: input.ExecutionInfo.GetWorkflowId(),
642 > RunID: input.ExecutionState.GetRunId(),
643 >
644 > UpsertActivityInfos: make(map[int64]*commonpb.DataBlob, len(input.UpsertActivityInfos)),
645 > DeleteActivityInfos: input.DeleteActivityInfos,
646 >
647 > UpsertTimerInfos: make(map[string]*commonpb.DataBlob, len(input.UpsertTimerInfos)),
648 > DeleteTimerInfos: input.DeleteTimerInfos,
649 >
650 > UpsertChildExecutionInfos: make(map[int64]*commonpb.DataBlob, len(input.UpsertChildExecutionInfos)),
651 > DeleteChildExecutionInfos: input.DeleteChildExecutionInfos,
652 >
653 > UpsertRequestCancelInfos: make(map[int64]*commonpb.DataBlob, len(input.UpsertRequestCancelInfos)),
654 > DeleteRequestCancelInfos: input.DeleteRequestCancelInfos,
655 >
656 > UpsertSignalInfos: make(map[int64]*commonpb.DataBlob, len(input.UpsertSignalInfos)),
657 > DeleteSignalInfos: input.DeleteSignalInfos,
658 >
659 > UpsertChasmNodes: make(map[string]InternalChasmNode, len(input.UpsertChasmNodes)),
660 > DeleteChasmNodes: input.DeleteChasmNodes,
661 >
662 > UpsertSignalRequestedIDs: input.UpsertSignalRequestedIDs,
663 > DeleteSignalRequestedIDs: input.DeleteSignalRequestedIDs,
664 >
665 > NewBufferedEvents: nil,
666 > ClearBufferedEvents: input.ClearBufferedEvents,
667 >
668 > ExecutionInfo: input.ExecutionInfo,
669 > ExecutionState: input.ExecutionState,
670 >
671 > Tasks: serializedTasks,
672 >
673 > Condition: input.Condition,
674 > DBRecordVersion: input.DBRecordVersion,
675 > NextEventID: input.NextEventID,
676 > }
677 >
678 > result.ExecutionInfoBlob, err = m.serializer.WorkflowExecutionInfoToBlob(input.ExecutionInfo)
679 > if err != nil {
680 return nil, err
681 }
682 > result.ExecutionStateBlob, err = m.serializer.WorkflowExecutionStateToBlob(input.ExecutionState) execution_manager.go
683 > if err != nil {
684 return nil, err
685 }
686
687 > for key, info := range input.UpsertActivityInfos { execution_manager.go
688 blob, err := m.serializer.ActivityInfoToBlob(info)
689 if err != nil {
693 }
694
695 > for key, info := range input.UpsertTimerInfos { execution_manager.go
696 blob, err := m.serializer.TimerInfoToBlob(info)
697 if err != nil {
701 }
702
703 > for key, info := range input.UpsertChildExecutionInfos { execution_manager.go
704 blob, err := m.serializer.ChildExecutionInfoToBlob(info)
705 if err != nil {
709 }
710
711 > for key, info := range input.UpsertRequestCancelInfos { execution_manager.go
712 blob, err := m.serializer.RequestCancelInfoToBlob(info)
713 if err != nil {
717 }
718
719 > for key, info := range input.UpsertSignalInfos { execution_manager.go
720 blob, err := m.serializer.SignalInfoToBlob(info)
721 if err != nil {
725 }
726
727 > nodeMap, err := m.makeInternalChasmNodeMap(input.UpsertChasmNodes) execution_manager.go
728 > if err != nil {
729 return nil, err
730 }
731 > result.UpsertChasmNodes = nodeMap execution_manager.go
732 >
733 > if len(input.NewBufferedEvents) > 0 {
734 result.NewBufferedEvents, err = m.serializer.SerializeEvents(input.NewBufferedEvents)
735 if err != nil {
738 }
739
740 > result.LastWriteVersion, err = getCurrentBranchLastWriteVersion(input.ExecutionInfo.VersionHistories, input.ExecutionInfo.TransitionHistory) execution_manager.go
741 > if err != nil {
742 return nil, err
743 }
744 > result.Checksum, err = m.serializer.ChecksumToBlob(input.Checksum) execution_manager.go
745 > if err != nil {
746 return nil, err
747 }
748
749 > return result, nil execution_manager.go
750 }
751
752 func (m *executionManagerImpl) SerializeWorkflowSnapshot( // unexport
753 input *WorkflowSnapshot,
754 > ) (*InternalWorkflowSnapshot, error) { execution_manager.go
755 > serializedTasks, err := serializeTasks(m.serializer, input.Tasks)
756 > if err != nil {
757 return nil, err
758 }
759
760 > result := &InternalWorkflowSnapshot{ execution_manager.go
761 > NamespaceID: input.ExecutionInfo.GetNamespaceId(),
762 > WorkflowID: input.ExecutionInfo.GetWorkflowId(),
763 > RunID: input.ExecutionState.GetRunId(),
764 >
765 > ActivityInfos: make(map[int64]*commonpb.DataBlob, len(input.ActivityInfos)),
766 > TimerInfos: make(map[string]*commonpb.DataBlob, len(input.TimerInfos)),
767 > ChildExecutionInfos: make(map[int64]*commonpb.DataBlob, len(input.ChildExecutionInfos)),
768 > RequestCancelInfos: make(map[int64]*commonpb.DataBlob, len(input.RequestCancelInfos)),
769 > SignalInfos: make(map[int64]*commonpb.DataBlob, len(input.SignalInfos)),
770 > ChasmNodes: make(map[string]InternalChasmNode, len(input.ChasmNodes)),
771 >
772 > ExecutionInfo: input.ExecutionInfo,
773 > ExecutionState: input.ExecutionState,
774 > SignalRequestedIDs: make(map[string]struct{}),
775 >
776 > Tasks: serializedTasks,
777 >
778 > Condition: input.Condition,
779 > DBRecordVersion: input.DBRecordVersion,
780 > NextEventID: input.NextEventID,
781 > }
782 >
783 > result.ExecutionInfoBlob, err = m.serializer.WorkflowExecutionInfoToBlob(input.ExecutionInfo)
784 > if err != nil {
785 return nil, err
786 }
787 > result.ExecutionStateBlob, err = m.serializer.WorkflowExecutionStateToBlob(input.ExecutionState) execution_manager.go
788 > if err != nil {
789 return nil, err
790 }
791 > result.LastWriteVersion, err = getCurrentBranchLastWriteVersion(input.ExecutionInfo.VersionHistories, input.ExecutionInfo.TransitionHistory) execution_manager.go
792 > if err != nil {
793 return nil, err
794 }
795
796 > for key, info := range input.ActivityInfos { execution_manager.go
797 blob, err := m.serializer.ActivityInfoToBlob(info)
798 if err != nil {
801 result.ActivityInfos[key] = blob
802 }
803 > for key, info := range input.TimerInfos { execution_manager.go
804 blob, err := m.serializer.TimerInfoToBlob(info)
805 if err != nil {
808 result.TimerInfos[key] = blob
809 }
810 > for key, info := range input.ChildExecutionInfos { execution_manager.go
811 blob, err := m.serializer.ChildExecutionInfoToBlob(info)
812 if err != nil {
815 result.ChildExecutionInfos[key] = blob
816 }
817 > for key, info := range input.RequestCancelInfos { execution_manager.go
818 blob, err := m.serializer.RequestCancelInfoToBlob(info)
819 if err != nil {
822 result.RequestCancelInfos[key] = blob
823 }
824 > for key, info := range input.SignalInfos { execution_manager.go
825 blob, err := m.serializer.SignalInfoToBlob(info)
826 if err != nil {
829 result.SignalInfos[key] = blob
830 }
831 > for key := range input.SignalRequestedIDs { execution_manager.go
832 result.SignalRequestedIDs[key] = struct{}{}
833 }
834 > nodeMap, err := m.makeInternalChasmNodeMap(input.ChasmNodes) execution_manager.go
835 > if err != nil {
836 return nil, err
837 }
838 > result.ChasmNodes = nodeMap execution_manager.go
839 >
840 > result.Checksum, err = m.serializer.ChecksumToBlob(input.Checksum)
841 > if err != nil {
842 return nil, err
843 }
844
845 > return result, nil execution_manager.go
846 }
847
960 ctx context.Context,
961 request *GetHistoryTasksRequest,
962 > ) (*GetHistoryTasksResponse, error) { execution_manager.go
963 > if err := validateTaskRange(
964 > request.TaskCategory.Type(),
965 > request.InclusiveMinTaskKey,
966 > request.ExclusiveMaxTaskKey,
967 > ); err != nil {
968 return nil, err
969 }
970
971 > resp, err := m.persistence.GetHistoryTasks(ctx, request) execution_manager.go
972 > if err != nil {
973 return nil, err
974 }
975
976 > historyTasks := make([]tasks.Task, 0, len(resp.Tasks)) execution_manager.go
977 > for _, internalTask := range resp.Tasks {
978 > task, err := m.serializer.DeserializeTask(request.TaskCategory, internalTask.Blob) execution_manager.go
979 > if err != nil {
980 return nil, err
981 }
982
983 > if !internalTask.Key.FireTime.Equal(tasks.DefaultFireTime) { execution_manager.go
984 task.SetVisibilityTime(internalTask.Key.FireTime)
985 }
986 > task.SetTaskID(internalTask.Key.TaskID) execution_manager.go
987 >
988 > historyTasks = append(historyTasks, task)
989 }
990
991 > return &GetHistoryTasksResponse{ execution_manager.go
992 > Tasks: historyTasks,
993 > NextPageToken: resp.NextPageToken,
994 > }, nil
995 }
996
1077 }
1078
1079 > func (m *executionManagerImpl) Close() { execution_manager.go
1080 > m.persistence.Close()
1081 > }
1082
1083 func (m *executionManagerImpl) trimHistoryNode(
1142 }
1143
1144 > func (m *executionManagerImpl) toWorkflowMutableState(internState *InternalWorkflowMutableState) (*persistencespb.WorkflowMutableState, error) { execution_manager.go
1145 > state := &persistencespb.WorkflowMutableState{
1146 > ActivityInfos: make(map[int64]*persistencespb.ActivityInfo),
1147 > TimerInfos: make(map[string]*persistencespb.TimerInfo),
1148 > ChildExecutionInfos: make(map[int64]*persistencespb.ChildExecutionInfo),
1149 > RequestCancelInfos: make(map[int64]*persistencespb.RequestCancelInfo),
1150 > SignalInfos: make(map[int64]*persistencespb.SignalInfo),
1151 > ChasmNodes: make(map[string]*persistencespb.ChasmNode),
1152 > SignalRequestedIds: internState.SignalRequestedIDs,
1153 > NextEventId: internState.NextEventID,
1154 > BufferedEvents: make([]*historypb.HistoryEvent, len(internState.BufferedEvents)),
1155 > }
1156 > for key, blob := range internState.ActivityInfos {
1157 info, err := m.serializer.ActivityInfoFromBlob(blob)
1158 if err != nil {
1161 state.ActivityInfos[key] = info
1162 }
1163 > for key, blob := range internState.TimerInfos { execution_manager.go
1164 info, err := m.serializer.TimerInfoFromBlob(blob)
1165 if err != nil {
1168 state.TimerInfos[key] = info
1169 }
1170 > for key, blob := range internState.ChildExecutionInfos { execution_manager.go
1171 info, err := m.serializer.ChildExecutionInfoFromBlob(blob)
1172 if err != nil {
1175 state.ChildExecutionInfos[key] = info
1176 }
1177 > for key, blob := range internState.RequestCancelInfos { execution_manager.go
1178 info, err := m.serializer.RequestCancelInfoFromBlob(blob)
1179 if err != nil {
1182 state.RequestCancelInfos[key] = info
1183 }
1184 > for key, blob := range internState.SignalInfos { execution_manager.go
1185 info, err := m.serializer.SignalInfoFromBlob(blob)
1186 if err != nil {
1189 state.SignalInfos[key] = info
1190 }
1191 > for key, internal := range internState.ChasmNodes { execution_manager.go
1192 var node *persistencespb.ChasmNode
1193 var err error
1204 state.ChasmNodes[key] = node
1205 }
1206 > var err error execution_manager.go
1207 > state.ExecutionInfo, err = m.serializer.WorkflowExecutionInfoFromBlob(internState.ExecutionInfo)
1208 > if err != nil {
1209 return nil, err
1210 }
1211 > if state.ExecutionInfo.AutoResetPoints == nil { execution_manager.go
1212 > // TODO: check if we need this? execution_manager.go
1213 > state.ExecutionInfo.AutoResetPoints = &workflowpb.ResetPoints{}
1214 > }
1215 > state.ExecutionState, err = m.serializer.WorkflowExecutionStateFromBlob(internState.ExecutionState) execution_manager.go
1216 > if err != nil {
1217 return nil, err
1218 }
1219 > state.BufferedEvents, err = m.DeserializeBufferedEvents(internState.BufferedEvents) execution_manager.go
1220 > if err != nil {
1221 return nil, err
1222 }
1223 > if internState.Checksum != nil { execution_manager.go
1224 state.Checksum, err = m.serializer.ChecksumFromBlob(internState.Checksum)
1225 }
1226 > if err != nil { execution_manager.go
1227 return nil, err
1228 }
1229
1230 > return state, nil execution_manager.go
1231 }
1232
1234 archetypeID chasm.ArchetypeID,
1235 methodName string,
1236 > ) (chasm.ArchetypeID, bool) { execution_manager.go
1237 > if !softassert.That(
1238 > m.logger,
1239 > archetypeID != chasm.UnspecifiedArchetypeID,
1240 > "ArchetypeID not specified, defaulting to Workflow.",
1241 > tag.Operation(methodName),
1242 > ) {
1243 return chasm.WorkflowArchetypeID, true
1244 }
1245
1246 > return archetypeID, false execution_manager.go
1247 }
1248
1264 versionHistories *historyspb.VersionHistories,
1265 transitions []*persistencespb.VersionedTransition,
1266 > ) (int64, error) { execution_manager.go
1267 > // TODO remove this if check once legacy execution tests are removed
1268 > if versionHistories == nil {
1269 return common.EmptyVersion, nil
1270 }
1271 > versionHistory, err := versionhistory.GetCurrentVersionHistory(versionHistories) execution_manager.go
1272 > if err != nil {
1273 return 0, err
1274 }
1275
1276 > if !versionhistory.IsEmptyVersionHistory(versionHistory) { execution_manager.go
1277 > versionHistoryItem, err := versionhistory.GetLastVersionHistoryItem(versionHistory) execution_manager.go
1278 > if err != nil {
1279 return 0, err
1280 }
1281 > return versionHistoryItem.GetVersion(), nil execution_manager.go
1282 }
1283
1305 serializer serialization.Serializer,
1306 inputTasks map[tasks.Category][]tasks.Task,
1307 > ) (map[tasks.Category][]InternalHistoryTask, error) { execution_manager.go
1308 > outputTasks := make(map[tasks.Category][]InternalHistoryTask)
1309 > for category, tasks := range inputTasks {
1310 > serializedTasks := make([]InternalHistoryTask, 0, len(tasks)) execution_manager.go
1311 > for _, task := range tasks {
1312 > blob, err := serializer.SerializeTask(task) execution_manager.go
1313 > if err != nil {
1314 return nil, err
1315 }
1316 > serializedTasks = append(serializedTasks, InternalHistoryTask{ execution_manager.go
1317 > Key: task.GetKey(),
1318 > Blob: blob,
1319 > })
1320 }
1321 > outputTasks[category] = serializedTasks execution_manager.go
1322 }
1323 > return outputTasks, nil execution_manager.go
1324 }
1325
1328 minTaskKey tasks.Key,
1329 maxTaskKey tasks.Key,
1330 > ) error { execution_manager.go
1331 > minTaskIDSpecified := minTaskKey.TaskID != 0
1332 > minFireTimeSpecified := !minTaskKey.FireTime.IsZero() && !minTaskKey.FireTime.Equal(tasks.DefaultFireTime)
1333 > maxTaskIDSpecified := maxTaskKey.TaskID != 0
1334 > maxFireTimeSpecified := !maxTaskKey.FireTime.IsZero() && !maxTaskKey.FireTime.Equal(tasks.DefaultFireTime)
1335 >
1336 > switch taskCategoryType {
1337 > case tasks.CategoryTypeImmediate:
1338 > if !maxTaskIDSpecified {
1339 return serviceerror.NewInvalidArgument("invalid task range, max taskID must be specified for immediate task category")
1340 }
1341 > if minFireTimeSpecified || maxFireTimeSpecified { execution_manager.go
1342 return serviceerror.NewInvalidArgument("invalid task range, fireTime must be empty for immediate task category")
1343 }
1344 > case tasks.CategoryTypeScheduled: execution_manager.go
1345 > if !maxFireTimeSpecified {
1346 return serviceerror.NewInvalidArgument("invalid task range, max fire time must be specified for scheduled task category")
1347 }
1348 > if minTaskIDSpecified || maxTaskIDSpecified { execution_manager.go
1349 return serviceerror.NewInvalidArgument("invalid task range, taskID must be empty for scheduled task category")
1350 }
1353 }
1354
1355 > return nil execution_manager.go
1356 }
1357
1358 func (m *executionManagerImpl) makeInternalChasmNodeMap(
1359 nodes map[string]*persistencespb.ChasmNode,
1360 > ) (map[string]InternalChasmNode, error) { execution_manager.go
1361 > res := make(map[string]InternalChasmNode, len(nodes))
1362 > isCassandra := strings.Contains(m.GetName(), "cassandra")
1363 >
1364 > for path, node := range nodes {
1365 var internal InternalChasmNode
1366
go.temporal.io/server/common/persistence/sql/execution_util.go 407 covered LOC · 91 ranges

Open complete file

26 shardID int32,
27 workflowMutation *p.InternalWorkflowMutation,
28 > ) error { execution_util.go
29 > lastWriteVersion := workflowMutation.LastWriteVersion
30 > namespaceID := workflowMutation.NamespaceID
31 > workflowID := workflowMutation.WorkflowID
32 > runID := workflowMutation.ExecutionState.RunId
33 >
34 > namespaceIDBytes, err := primitives.ParseUUID(namespaceID)
35 > if err != nil {
36 return serviceerror.NewInternalf("uuid parse failed. Error: %v", err)
37 }
38
39 > runIDBytes, err := primitives.ParseUUID(runID) execution_util.go
40 > if err != nil {
41 return serviceerror.NewInternalf("uuid parse failed. Error: %v", err)
42 }
43
44 // TODO Remove me if UPDATE holds the lock to the end of a transaction
45 > if err := lockAndCheckExecution(ctx, execution_util.go
46 > tx,
47 > shardID,
48 > namespaceIDBytes,
49 > workflowID,
50 > runIDBytes,
51 > workflowMutation.Condition,
52 > workflowMutation.DBRecordVersion,
53 > ); err != nil {
54 switch err.(type) {
55 case *p.WorkflowConditionFailedError, *p.ConditionFailedError:
60 }
61
62 > if err := m.updateExecution(ctx, execution_util.go
63 > tx,
64 > namespaceID,
65 > workflowID,
66 > workflowMutation.ExecutionInfoBlob,
67 > workflowMutation.ExecutionState,
68 > workflowMutation.NextEventID,
69 > lastWriteVersion,
70 > workflowMutation.DBRecordVersion,
71 > shardID,
72 > ); err != nil {
73 return serviceerror.NewUnavailablef("applyWorkflowMutationTx failed. Failed to update executions row. Erorr: %v", err)
74 }
75
76 > if err := applyTasks(ctx, execution_util.go
77 > tx,
78 > shardID,
79 > workflowMutation.Tasks,
80 > ); err != nil {
81 return err
82 }
83
84 > if err := updateActivityInfos(ctx, execution_util.go
85 > tx,
86 > workflowMutation.UpsertActivityInfos,
87 > workflowMutation.DeleteActivityInfos,
88 > shardID,
89 > namespaceIDBytes,
90 > workflowID,
91 > runIDBytes,
92 > ); err != nil {
93 return serviceerror.NewUnavailablef("applyWorkflowMutationTx failed. Error: %v", err)
94 }
95
96 > if err := updateTimerInfos(ctx, execution_util.go
97 > tx,
98 > workflowMutation.UpsertTimerInfos,
99 > workflowMutation.DeleteTimerInfos,
100 > shardID,
101 > namespaceIDBytes,
102 > workflowID,
103 > runIDBytes,
104 > ); err != nil {
105 return serviceerror.NewUnavailablef("applyWorkflowMutationTx failed. Error: %v", err)
106 }
107
108 > if err := updateChildExecutionInfos(ctx, execution_util.go
109 > tx,
110 > workflowMutation.UpsertChildExecutionInfos,
111 > workflowMutation.DeleteChildExecutionInfos,
112 > shardID,
113 > namespaceIDBytes,
114 > workflowID,
115 > runIDBytes,
116 > ); err != nil {
117 return serviceerror.NewUnavailablef("applyWorkflowMutationTx failed. Error: %v", err)
118 }
119
120 > if err := updateRequestCancelInfos(ctx, execution_util.go
121 > tx,
122 > workflowMutation.UpsertRequestCancelInfos,
123 > workflowMutation.DeleteRequestCancelInfos,
124 > shardID,
125 > namespaceIDBytes,
126 > workflowID,
127 > runIDBytes,
128 > ); err != nil {
129 return serviceerror.NewUnavailablef("applyWorkflowMutationTx failed. Error: %v", err)
130 }
131
132 > if err := updateSignalInfos(ctx, execution_util.go
133 > tx,
134 > workflowMutation.UpsertSignalInfos,
135 > workflowMutation.DeleteSignalInfos,
136 > shardID,
137 > namespaceIDBytes,
138 > workflowID,
139 > runIDBytes,
140 > ); err != nil {
141 return serviceerror.NewUnavailablef("applyWorkflowMutationTx failed. Error: %v", err)
142 }
143
144 > if err := updateSignalsRequested(ctx, execution_util.go
145 > tx,
146 > workflowMutation.UpsertSignalRequestedIDs,
147 > workflowMutation.DeleteSignalRequestedIDs,
148 > shardID,
149 > namespaceIDBytes,
150 > workflowID,
151 > runIDBytes); err != nil {
152 return serviceerror.NewUnavailablef("applyWorkflowMutationTx failed. Error: %v", err)
153 }
154
155 > if workflowMutation.ClearBufferedEvents { execution_util.go
156 if err := deleteBufferedEvents(ctx,
157 tx,
165 }
166
167 > if err := updateBufferedEvents(ctx, execution_util.go
168 > tx,
169 > workflowMutation.NewBufferedEvents,
170 > shardID,
171 > namespaceIDBytes,
172 > workflowID,
173 > runIDBytes,
174 > ); err != nil {
175 return serviceerror.NewUnavailablef("applyWorkflowMutationTx failed. Error: %v", err)
176 }
177
178 > if err := updateChasmNodes(ctx, execution_util.go
179 > tx,
180 > workflowMutation.UpsertChasmNodes,
181 > workflowMutation.DeleteChasmNodes,
182 > shardID,
183 > namespaceIDBytes,
184 > workflowID,
185 > runIDBytes,
186 > ); err != nil {
187 return serviceerror.NewUnavailablef("applyWorkflowMutationTx failed. Error: %v", err)
188 }
189
190 > return nil execution_util.go
191 }
192
421 shardID int32,
422 workflowSnapshot *p.InternalWorkflowSnapshot,
423 > ) error { execution_util.go
424 >
425 > lastWriteVersion := workflowSnapshot.LastWriteVersion
426 > workflowID := workflowSnapshot.WorkflowID
427 > namespaceID := workflowSnapshot.NamespaceID
428 > runID := workflowSnapshot.ExecutionState.RunId
429 > namespaceIDBytes, err := primitives.ParseUUID(namespaceID)
430 > if err != nil {
431 return err
432 }
433 > runIDBytes, err := primitives.ParseUUID(runID) execution_util.go
434 > if err != nil {
435 return err
436 }
437
438 > if err := m.createExecution(ctx, execution_util.go
439 > tx,
440 > namespaceID,
441 > workflowID,
442 > workflowSnapshot.ExecutionInfoBlob,
443 > workflowSnapshot.ExecutionState,
444 > workflowSnapshot.NextEventID,
445 > lastWriteVersion,
446 > workflowSnapshot.DBRecordVersion,
447 > shardID,
448 > ); err != nil {
449 return err
450 }
451
452 > if err := applyTasks(ctx, execution_util.go
453 > tx,
454 > shardID,
455 > workflowSnapshot.Tasks,
456 > ); err != nil {
457 return err
458 }
459
460 > if err := updateActivityInfos(ctx, execution_util.go
461 > tx,
462 > workflowSnapshot.ActivityInfos,
463 > nil,
464 > shardID,
465 > namespaceIDBytes,
466 > workflowID,
467 > runIDBytes,
468 > ); err != nil {
469 return serviceerror.NewUnavailablef("applyWorkflowSnapshotTxAsNew failed. Failed to insert into activity info map after clearing. Error: %v", err)
470 }
471
472 > if err := updateTimerInfos(ctx, execution_util.go
473 > tx,
474 > workflowSnapshot.TimerInfos,
475 > nil,
476 > shardID,
477 > namespaceIDBytes,
478 > workflowID,
479 > runIDBytes,
480 > ); err != nil {
481 return serviceerror.NewUnavailablef("applyWorkflowSnapshotTxAsNew failed. Failed to insert into timer info map after clearing. Error: %v", err)
482 }
483
484 > if err := updateChildExecutionInfos(ctx, execution_util.go
485 > tx,
486 > workflowSnapshot.ChildExecutionInfos,
487 > nil,
488 > shardID,
489 > namespaceIDBytes,
490 > workflowID,
491 > runIDBytes,
492 > ); err != nil {
493 return serviceerror.NewUnavailablef("applyWorkflowSnapshotTxAsNew failed. Failed to insert into activity info map after clearing. Error: %v", err)
494 }
495
496 > if err := updateRequestCancelInfos(ctx, execution_util.go
497 > tx,
498 > workflowSnapshot.RequestCancelInfos,
499 > nil,
500 > shardID,
501 > namespaceIDBytes,
502 > workflowID,
503 > runIDBytes,
504 > ); err != nil {
505 return serviceerror.NewUnavailablef("applyWorkflowSnapshotTxAsNew failed. Failed to insert into request cancel info map after clearing. Error: %v", err)
506 }
507
508 > if err := updateSignalInfos(ctx, execution_util.go
509 > tx,
510 > workflowSnapshot.SignalInfos,
511 > nil,
512 > shardID,
513 > namespaceIDBytes,
514 > workflowID,
515 > runIDBytes,
516 > ); err != nil {
517 return serviceerror.NewUnavailablef("applyWorkflowSnapshotTxAsNew failed. Failed to insert into signal info map after clearing. Error: %v", err)
518 }
519
520 > if err := updateSignalsRequested(ctx, execution_util.go
521 > tx,
522 > workflowSnapshot.SignalRequestedIDs,
523 > nil,
524 > shardID,
525 > namespaceIDBytes,
526 > workflowID,
527 > runIDBytes,
528 > ); err != nil {
529 return serviceerror.NewUnavailablef("applyWorkflowSnapshotTxAsNew failed. Failed to insert into signals requested set after clearing. Error: %v", err)
530 }
531
532 > if err := updateChasmNodes(ctx, execution_util.go
533 > tx,
534 > workflowSnapshot.ChasmNodes,
535 > nil,
536 > shardID,
537 > namespaceIDBytes,
538 > workflowID,
539 > runIDBytes,
540 > ); err != nil {
541 return serviceerror.NewUnavailablef("applyWorkflowSnapshotTxAsNew failed. Failed to update CHASM nodes. Error: %v", err)
542 }
543
544 > return nil execution_util.go
545 }
546
550 shardID int32,
551 insertTasks map[tasks.Category][]p.InternalHistoryTask,
552 > ) error { execution_util.go
553 >
554 > var err error
555 > for category, tasksByCategory := range insertTasks {
556 > switch category.Type() {
557 > case tasks.CategoryTypeImmediate: execution_util.go
558 > err = createImmediateTasks(ctx, tx, shardID, category.ID(), tasksByCategory)
559 > case tasks.CategoryTypeScheduled: execution_util.go
560 > err = createScheduledTasks(ctx, tx, shardID, category.ID(), tasksByCategory)
561 default:
562 err = serviceerror.NewInternalf("Unknown task category type: %v", category)
563 }
564
565 > if err != nil { execution_util.go
566 return err
567 }
568 }
569
570 > return nil execution_util.go
571 }
572
580 workflowID string,
581 archetypeID chasm.ArchetypeID,
582 > ) (*sqlplugin.CurrentExecutionsRow, error) { execution_util.go
583 > rows, err := tx.LockCurrentExecutionsJoinExecutions(ctx, sqlplugin.CurrentExecutionsFilter{
584 > ShardID: shardID,
585 > NamespaceID: namespaceID,
586 > WorkflowID: workflowID,
587 > ArchetypeID: archetypeID,
588 > })
589 > if err != nil {
590 if err != sql.ErrNoRows {
591 return nil, serviceerror.NewUnavailablef("lockCurrentExecutionIfExists failed. Failed to get current_executions row for (shard,namespace,workflow) = (%v, %v, %v). Error: %v", shardID, namespaceID, workflowID, err)
592 }
593 }
594 > size := len(rows) execution_util.go
595 > if size > 1 {
596 return nil, serviceerror.NewUnavailablef("lockCurrentExecutionIfExists failed. Multiple current_executions rows for (shard,namespace,workflow) = (%v, %v, %v).", shardID, namespaceID, workflowID)
597 }
598 > if size == 0 { execution_util.go
599 > return nil, nil
600 > }
601 return &rows[0], nil
602 }
607 row sqlplugin.CurrentExecutionsRow,
608 createMode p.CreateWorkflowMode,
609 > ) error { execution_util.go
610 >
611 > switch createMode {
612 case p.CreateWorkflowModeUpdateCurrent:
613 if err := updateCurrentExecution(ctx, tx, row); err != nil {
614 return serviceerror.NewUnavailablef("createOrUpdateCurrentExecution failed. Failed to reuse workflow ID. Error: %v", err)
615 }
616 > case p.CreateWorkflowModeBrandNew: execution_util.go
617 > if _, err := tx.InsertIntoCurrentExecutions(ctx, &row); err != nil {
618 return serviceerror.NewUnavailablef("createOrUpdateCurrentExecution failed. Failed to insert into current_executions table. Error: %v", err)
619 }
636 condition int64,
637 dbRecordVersion int64,
638 > ) error { execution_util.go
639 >
640 > version, nextEventID, err := lockExecution(ctx, tx, shardID, namespaceID, workflowID, runID)
641 > if err != nil {
642 return err
643 }
644
645 > if dbRecordVersion == 0 { execution_util.go
646 if nextEventID != condition {
647 return &p.WorkflowConditionFailedError{
651 }
652 }
653 > } else { execution_util.go
654 > dbRecordVersion -= 1
655 > if version != dbRecordVersion {
656 return &p.WorkflowConditionFailedError{
657 Msg: fmt.Sprintf("lockAndCheckExecution failed. DBRecordVersion expected: %v, actually %v.", dbRecordVersion, version),
672 workflowID string,
673 runID primitives.UUID,
674 > ) (int64, int64, error) { execution_util.go
675 >
676 > dbRecordVersion, nextEventID, err := tx.WriteLockExecutions(ctx, sqlplugin.ExecutionsFilter{
677 > ShardID: shardID,
678 > NamespaceID: namespaceID,
679 > WorkflowID: workflowID,
680 > RunID: runID,
681 > })
682 > if err != nil {
683 if err == sql.ErrNoRows {
684 return 0, 0, &p.ConditionFailedError{
692 return 0, 0, serviceerror.NewUnavailablef("lockNextEventID failed. Error: %v", err)
693 }
694 > return dbRecordVersion, nextEventID, nil execution_util.go
695 }
696
701 categoryID int,
702 immedidateTasks []p.InternalHistoryTask,
703 > ) error { execution_util.go
704 > // This is for backward compatiblity.
705 > // These task categories exist before the general history_immediate_tasks table is created,
706 > // so they have their own tables.
707 > switch categoryID {
708 > case tasks.CategoryIDTransfer: execution_util.go
709 > return createTransferTasks(ctx, tx, shardID, immedidateTasks)
710 > case tasks.CategoryIDVisibility: execution_util.go
711 > return createVisibilityTasks(ctx, tx, shardID, immedidateTasks)
712 case tasks.CategoryIDReplication:
713 return createReplicationTasks(ctx, tx, shardID, immedidateTasks)
751 categoryID int,
752 scheduledTasks []p.InternalHistoryTask,
753 > ) error { execution_util.go
754 > // This is for backward compatiblity.
755 > // These task categories exists before the general history_scheduled_tasks table is created,
756 > // so they have their own tables.
757 > if categoryID == tasks.CategoryIDTimer {
758 > return createTimerTasks(ctx, tx, shardID, scheduledTasks) execution_util.go
759 > }
760
761 if len(scheduledTasks) == 0 {
795 shardID int32,
796 transferTasks []p.InternalHistoryTask,
797 > ) error { execution_util.go
798 >
799 > if len(transferTasks) == 0 {
800 return nil
801 }
802
803 > transferTasksRows := make([]sqlplugin.TransferTasksRow, 0, len(transferTasks)) execution_util.go
804 > for _, task := range transferTasks {
805 > transferTasksRows = append(transferTasksRows, sqlplugin.TransferTasksRow{
806 > ShardID: shardID,
807 > TaskID: task.Key.TaskID,
808 > Data: task.Blob.Data,
809 > DataEncoding: task.Blob.EncodingType.String(),
810 > })
811 > }
812
813 > result, err := tx.InsertIntoTransferTasks(ctx, transferTasksRows) execution_util.go
814 > if err != nil {
815 return serviceerror.NewUnavailablef("createTransferTasks failed. Error: %v", err)
816 }
817
818 > rowsAffected, err := result.RowsAffected() execution_util.go
819 > if err != nil {
820 return serviceerror.NewUnavailablef("createTransferTasks failed. Could not verify number of rows inserted. Error: %v", err)
821 }
822
823 > if int(rowsAffected) != len(transferTasks) { execution_util.go
824 return serviceerror.NewUnavailablef("createTransferTasks failed. Inserted %v instead of %v rows into transfer_tasks. Error: %v", rowsAffected, len(transferTasks), err)
825 }
826 > return nil execution_util.go
827 }
828
832 shardID int32,
833 timerTasks []p.InternalHistoryTask,
834 > ) error { execution_util.go
835 >
836 > if len(timerTasks) == 0 {
837 return nil
838 }
839
840 > timerTasksRows := make([]sqlplugin.TimerTasksRow, 0, len(timerTasks)) execution_util.go
841 > for _, task := range timerTasks {
842 > timerTasksRows = append(timerTasksRows, sqlplugin.TimerTasksRow{
843 > ShardID: shardID,
844 > VisibilityTimestamp: task.Key.FireTime,
845 > TaskID: task.Key.TaskID,
846 > Data: task.Blob.Data,
847 > DataEncoding: task.Blob.EncodingType.String(),
848 > })
849 > }
850
851 > result, err := tx.InsertIntoTimerTasks(ctx, timerTasksRows) execution_util.go
852 > if err != nil {
853 return serviceerror.NewUnavailablef("createTimerTasks failed. Error: %v", err)
854 }
855 > rowsAffected, err := result.RowsAffected() execution_util.go
856 > if err != nil {
857 return serviceerror.NewUnavailablef("createTimerTasks failed. Could not verify number of rows inserted. Error: %v", err)
858 }
859
860 > if int(rowsAffected) != len(timerTasks) { execution_util.go
861 return serviceerror.NewUnavailablef("createTimerTasks failed. Inserted %v instead of %v rows into timer_tasks. Error: %v", rowsAffected, len(timerTasks), err)
862 }
863 > return nil execution_util.go
864 }
865
906 shardID int32,
907 visibilityTasks []p.InternalHistoryTask,
908 > ) error { execution_util.go
909 >
910 > if len(visibilityTasks) == 0 {
911 return nil
912 }
913
914 > visibilityTasksRows := make([]sqlplugin.VisibilityTasksRow, 0, len(visibilityTasks)) execution_util.go
915 > for _, task := range visibilityTasks {
916 > visibilityTasksRows = append(visibilityTasksRows, sqlplugin.VisibilityTasksRow{
917 > ShardID: shardID,
918 > TaskID: task.Key.TaskID,
919 > Data: task.Blob.Data,
920 > DataEncoding: task.Blob.EncodingType.String(),
921 > })
922 > }
923
924 > result, err := tx.InsertIntoVisibilityTasks(ctx, visibilityTasksRows) execution_util.go
925 > if err != nil {
926 return serviceerror.NewUnavailablef("createTransferTasks failed. Error: %v", err)
927 }
928
929 > rowsAffected, err := result.RowsAffected() execution_util.go
930 > if err != nil {
931 return serviceerror.NewUnavailablef("createTransferTasks failed. Could not verify number of rows inserted. Error: %v", err)
932 }
933
934 > if int(rowsAffected) != len(visibilityTasksRows) { execution_util.go
935 return serviceerror.NewUnavailablef("createTransferTasks failed. Inserted %v instead of %v rows into transfer_tasks. Error: %v", rowsAffected, len(visibilityTasksRows), err)
936 }
937 > return nil execution_util.go
938 }
939
970 previousRunID primitives.UUID,
971 serializer serialization.Serializer,
972 > ) error { execution_util.go
973 >
974 > assertFn := func(currentRow *sqlplugin.CurrentExecutionsRow) error {
975 > if !bytes.Equal(currentRow.RunID, previousRunID) {
976 executionState, err := workflowExecutionStateFromCurrentExecutionsRow(serializer, currentRow)
977 if err != nil {
994 }
995 }
996 > return nil execution_util.go
997 }
998 > if err := assertCurrentExecution(ctx, execution_util.go
999 > tx,
1000 > row.ShardID,
1001 > row.NamespaceID,
1002 > row.WorkflowID,
1003 > row.ArchetypeID,
1004 > assertFn,
1005 > ); err != nil {
1006 return err
1007 }
1008
1009 > return updateCurrentExecution(ctx, tx, row) execution_util.go
1010 }
1011
1018 archetypeID chasm.ArchetypeID,
1019 assertFn func(currentRow *sqlplugin.CurrentExecutionsRow) error,
1020 > ) error { execution_util.go
1021 >
1022 > currentRow, err := tx.LockCurrentExecutions(ctx, sqlplugin.CurrentExecutionsFilter{
1023 > ShardID: shardID,
1024 > NamespaceID: namespaceID,
1025 > WorkflowID: workflowID,
1026 > ArchetypeID: archetypeID,
1027 > })
1028 > if err != nil {
1029 return serviceerror.NewUnavailablef("assertCurrentExecution failed. Unable to load current record. Error: %v", err)
1030 }
1031 > return assertFn(currentRow) execution_util.go
1032 }
1033
1064 tx sqlplugin.Tx,
1065 row sqlplugin.CurrentExecutionsRow,
1066 > ) error { execution_util.go
1067 > result, err := tx.UpdateCurrentExecutions(ctx, &row)
1068 > if err != nil {
1069 return serviceerror.NewUnavailablef("updateCurrentExecution failed. Error: %v", err)
1070 }
1071 > rowsAffected, err := result.RowsAffected() execution_util.go
1072 > if err != nil {
1073 return serviceerror.NewUnavailablef("updateCurrentExecution failed. Failed to check number of rows updated in current_executions table. Error: %v", err)
1074 }
1075 > if rowsAffected != 1 { execution_util.go
1076 return serviceerror.NewUnavailablef("updateCurrentExecution failed. %v rows of current_executions updated instead of 1.", rowsAffected)
1077 }
1078 > return nil execution_util.go
1079 }
1080
1088 dbRecordVersion int64,
1089 shardID int32,
1090 > ) (row *sqlplugin.ExecutionsRow, err error) { execution_util.go
1091 > // TODO: double encoding execution state? executionState could've been passed to the function as
1092 > // *commonpb.DataBlob like executionInfo
1093 > stateBlob, err := m.serializer.WorkflowExecutionStateToBlob(executionState)
1094 > if err != nil {
1095 return nil, err
1096 }
1097
1098 > nsBytes, err := primitives.ParseUUID(namespaceID) execution_util.go
1099 > if err != nil {
1100 return nil, err
1101 }
1102
1103 > ridBytes, err := primitives.ParseUUID(executionState.RunId) execution_util.go
1104 > if err != nil {
1105 return nil, err
1106 }
1107
1108 > return &sqlplugin.ExecutionsRow{ execution_util.go
1109 > ShardID: shardID,
1110 > NamespaceID: nsBytes,
1111 > WorkflowID: workflowID,
1112 > RunID: ridBytes,
1113 > NextEventID: nextEventID,
1114 > LastWriteVersion: lastWriteVersion,
1115 > Data: executionInfo.Data,
1116 > DataEncoding: executionInfo.EncodingType.String(),
1117 > State: stateBlob.Data,
1118 > StateEncoding: stateBlob.EncodingType.String(),
1119 > DBRecordVersion: dbRecordVersion,
1120 > }, nil
1121 }
1122
1132 dbRecordVersion int64,
1133 shardID int32,
1134 > ) error { execution_util.go
1135 >
1136 > row, err := m.buildExecutionRow(
1137 > namespaceID,
1138 > workflowID,
1139 > executionInfo,
1140 > executionState,
1141 > nextEventID,
1142 > lastWriteVersion,
1143 > dbRecordVersion,
1144 > shardID,
1145 > )
1146 > if err != nil {
1147 return err
1148 }
1149 > result, err := tx.InsertIntoExecutions(ctx, row) execution_util.go
1150 > if err != nil {
1151 if m.DB.IsDupEntryError(err) {
1152 return &p.WorkflowConditionFailedError{
1158 return serviceerror.NewUnavailablef("createExecution failed. Erorr: %v", err)
1159 }
1160 > rowsAffected, err := result.RowsAffected() execution_util.go
1161 > if err != nil {
1162 return serviceerror.NewUnavailablef("createExecution failed. Failed to verify number of rows affected. Erorr: %v", err)
1163 }
1164 > if rowsAffected != 1 { execution_util.go
1165 return serviceerror.NewNotFoundf("createExecution failed. Affected %v rows updated instead of 1.", rowsAffected)
1166 }
1167
1168 > return nil execution_util.go
1169 }
1170
1180 dbRecordVersion int64,
1181 shardID int32,
1182 > ) error { execution_util.go
1183 > row, err := m.buildExecutionRow(
1184 > namespaceID,
1185 > workflowID,
1186 > executionInfo,
1187 > executionState,
1188 > nextEventID,
1189 > lastWriteVersion,
1190 > dbRecordVersion,
1191 > shardID,
1192 > )
1193 > if err != nil {
1194 return err
1195 }
1196 > result, err := tx.UpdateExecutions(ctx, row) execution_util.go
1197 > if err != nil {
1198 return serviceerror.NewUnavailablef("updateExecution failed. Erorr: %v", err)
1199 }
1200 > rowsAffected, err := result.RowsAffected() execution_util.go
1201 > if err != nil {
1202 return serviceerror.NewUnavailablef("updateExecution failed. Failed to verify number of rows affected. Erorr: %v", err)
1203 }
1204 > if rowsAffected != 1 { execution_util.go
1205 return serviceerror.NewNotFoundf("updateExecution failed. Affected %v rows updated instead of 1.", rowsAffected)
1206 }
1207
1208 > return nil execution_util.go
1209 }
1210
go.temporal.io/server/common/persistence/persistence_metric_clients.go 400 covered LOC · 59 ranges

Open complete file

77
78 // NewShardPersistenceMetricsClient creates a client to manage shards
79 > func NewShardPersistenceMetricsClient(persistence ShardManager, metricsHandler metrics.Handler, healthSignals HealthSignalAggregator, logger log.Logger, enableDataLossMetrics dynamicconfig.BoolPropertyFn) ShardManager { persistence_metric_clients.go
80 > return &shardPersistenceClient{
81 > metricEmitter: metricEmitter{
82 > metricsHandler: metricsHandler,
83 > logger: logger,
84 > enableDataLossMetrics: enableDataLossMetrics,
85 > },
86 > healthSignals: healthSignals,
87 > persistence: persistence,
88 > }
89 > }
90
91 // NewExecutionPersistenceMetricsClient creates a client to manage executions
92 > func NewExecutionPersistenceMetricsClient(persistence ExecutionManager, metricsHandler metrics.Handler, healthSignals HealthSignalAggregator, logger log.Logger, enableDataLossMetrics dynamicconfig.BoolPropertyFn) ExecutionManager { persistence_metric_clients.go
93 > return &executionPersistenceClient{
94 > metricEmitter: metricEmitter{
95 > metricsHandler: metricsHandler,
96 > logger: logger,
97 > enableDataLossMetrics: enableDataLossMetrics,
98 > },
99 > healthSignals: healthSignals,
100 > persistence: persistence,
101 > }
102 > }
103
104 // NewTaskPersistenceMetricsClient creates a client to manage tasks
105 > func NewTaskPersistenceMetricsClient(persistence TaskManager, metricsHandler metrics.Handler, healthSignals HealthSignalAggregator, logger log.Logger, enableDataLossMetrics dynamicconfig.BoolPropertyFn) TaskManager { persistence_metric_clients.go
106 > return &taskPersistenceClient{
107 > metricEmitter: metricEmitter{
108 > metricsHandler: metricsHandler,
109 > logger: logger,
110 > enableDataLossMetrics: enableDataLossMetrics,
111 > },
112 > healthSignals: healthSignals,
113 > persistence: persistence,
114 > }
115 > }
116
117 // NewMetadataPersistenceMetricsClient creates a MetadataManager client to manage metadata
118 > func NewMetadataPersistenceMetricsClient(persistence MetadataManager, metricsHandler metrics.Handler, healthSignals HealthSignalAggregator, logger log.Logger, enableDataLossMetrics dynamicconfig.BoolPropertyFn) MetadataManager { persistence_metric_clients.go
119 > return &metadataPersistenceClient{
120 > metricEmitter: metricEmitter{
121 > metricsHandler: metricsHandler,
122 > logger: logger,
123 > enableDataLossMetrics: enableDataLossMetrics,
124 > },
125 > healthSignals: healthSignals,
126 > persistence: persistence,
127 > }
128 > }
129
130 // NewClusterMetadataPersistenceMetricsClient creates a ClusterMetadataManager client to manage cluster metadata
131 > func NewClusterMetadataPersistenceMetricsClient(persistence ClusterMetadataManager, metricsHandler metrics.Handler, healthSignals HealthSignalAggregator, logger log.Logger, enableDataLossMetrics dynamicconfig.BoolPropertyFn) ClusterMetadataManager { persistence_metric_clients.go
132 > return &clusterMetadataPersistenceClient{
133 > metricEmitter: metricEmitter{
134 > metricsHandler: metricsHandler,
135 > logger: logger,
136 > enableDataLossMetrics: enableDataLossMetrics,
137 > },
138 > healthSignals: healthSignals,
139 > persistence: persistence,
140 > }
141 > }
142
143 // NewQueuePersistenceMetricsClient creates a client to manage queue
144 > func NewQueuePersistenceMetricsClient(persistence Queue, metricsHandler metrics.Handler, healthSignals HealthSignalAggregator, logger log.Logger, enableDataLossMetrics dynamicconfig.BoolPropertyFn) Queue { persistence_metric_clients.go
145 > return &queuePersistenceClient{
146 > metricEmitter: metricEmitter{
147 > metricsHandler: metricsHandler,
148 > logger: logger,
149 > enableDataLossMetrics: enableDataLossMetrics,
150 > },
151 > healthSignals: healthSignals,
152 > persistence: persistence,
153 > }
154 > }
155
156 // NewNexusEndpointPersistenceMetricsClient creates a NexusEndpointManager to manage nexus endpoints
157 > func NewNexusEndpointPersistenceMetricsClient(persistence NexusEndpointManager, metricsHandler metrics.Handler, healthSignals HealthSignalAggregator, logger log.Logger, enableDataLossMetrics dynamicconfig.BoolPropertyFn) NexusEndpointManager { persistence_metric_clients.go
158 > return &nexusEndpointPersistenceClient{
159 > metricEmitter: metricEmitter{
160 > metricsHandler: metricsHandler,
161 > logger: logger,
162 > enableDataLossMetrics: enableDataLossMetrics,
163 > },
164 > healthSignals: healthSignals,
165 > persistence: persistence,
166 > }
167 > }
168
169 func (p *shardPersistenceClient) GetName() string {
174 ctx context.Context,
175 request *GetOrCreateShardRequest,
176 > ) (_ *GetOrCreateShardResponse, retErr error) { persistence_metric_clients.go
177 > caller := headers.GetCallerInfo(ctx).CallerName
178 > startTime := time.Now().UTC()
179 > defer func() {
180 > latency := time.Since(startTime)
181 > p.healthSignals.Record(request.ShardID, latency, retErr)
182 > p.recordRequestMetrics(metrics.PersistenceGetOrCreateShardScope, caller, latency, retErr)
183 > p.recordDataLossMetrics(metrics.PersistenceGetOrCreateShardScope, caller, retErr, "", "")
184 > }()
185 > return p.persistence.GetOrCreateShard(ctx, request)
186 }
187
189 ctx context.Context,
190 request *UpdateShardRequest,
191 > ) (retErr error) { persistence_metric_clients.go
192 > caller := headers.GetCallerInfo(ctx).CallerName
193 > startTime := time.Now().UTC()
194 > defer func() {
195 > p.healthSignals.Record(request.ShardInfo.GetShardId(), time.Since(startTime), retErr)
196 > p.recordRequestMetrics(metrics.PersistenceUpdateShardScope, caller, time.Since(startTime), retErr)
197 > p.recordDataLossMetrics(metrics.PersistenceUpdateShardScope, caller, retErr, "", "")
198 > }()
199 > return p.persistence.UpdateShard(ctx, request)
200 }
201
203 ctx context.Context,
204 request *AssertShardOwnershipRequest,
205 > ) (retErr error) { persistence_metric_clients.go
206 > caller := headers.GetCallerInfo(ctx).CallerName
207 > startTime := time.Now().UTC()
208 > defer func() {
209 > p.healthSignals.Record(request.ShardID, time.Since(startTime), retErr)
210 > p.recordRequestMetrics(metrics.PersistenceAssertShardOwnershipScope, caller, time.Since(startTime), retErr)
211 > p.recordDataLossMetrics(metrics.PersistenceAssertShardOwnershipScope, caller, retErr, "", "")
212 > }()
213 > return p.persistence.AssertShardOwnership(ctx, request)
214 }
215
216 > func (p *shardPersistenceClient) Close() { persistence_metric_clients.go
217 > p.persistence.Close()
218 > }
219
220 > func (p *executionPersistenceClient) GetName() string { persistence_metric_clients.go
221 > return p.persistence.GetName()
222 > }
223
224 > func (p *executionPersistenceClient) GetHistoryBranchUtil() HistoryBranchUtil { persistence_metric_clients.go
225 > return p.persistence.GetHistoryBranchUtil()
226 > }
227
228 func (p *executionPersistenceClient) CreateWorkflowExecution(
229 ctx context.Context,
230 request *CreateWorkflowExecutionRequest,
231 > ) (_ *CreateWorkflowExecutionResponse, retErr error) { persistence_metric_clients.go
232 > caller := headers.GetCallerInfo(ctx).CallerName
233 > startTime := time.Now().UTC()
234 > defer func() {
235 > p.healthSignals.Record(request.ShardID, time.Since(startTime), retErr)
236 > var workflowID, runID string
237 > if request != nil {
238 > if request.NewWorkflowSnapshot.ExecutionInfo != nil {
239 > workflowID = request.NewWorkflowSnapshot.ExecutionInfo.WorkflowId
240 > }
241 > if request.NewWorkflowSnapshot.ExecutionState != nil {
242 > runID = request.NewWorkflowSnapshot.ExecutionState.RunId
243 > }
244 }
245 > p.recordRequestMetrics(metrics.PersistenceCreateWorkflowExecutionScope, caller, time.Since(startTime), retErr) persistence_metric_clients.go
246 > p.recordDataLossMetrics(metrics.PersistenceCreateWorkflowExecutionScope, caller, retErr, workflowID, runID)
247 }()
248 > return p.persistence.CreateWorkflowExecution(ctx, request) persistence_metric_clients.go
249 }
250
252 ctx context.Context,
253 request *GetWorkflowExecutionRequest,
254 > ) (_ *GetWorkflowExecutionResponse, retErr error) { persistence_metric_clients.go
255 > caller := headers.GetCallerInfo(ctx).CallerName
256 > startTime := time.Now().UTC()
257 > defer func() {
258 > p.healthSignals.Record(request.ShardID, time.Since(startTime), retErr)
259 > var workflowID, runID string
260 > if request != nil {
261 > workflowID = request.WorkflowID
262 > runID = request.RunID
263 > }
264 > p.recordRequestMetrics(metrics.PersistenceGetWorkflowExecutionScope, caller, time.Since(startTime), retErr)
265 > p.recordDataLossMetrics(metrics.PersistenceGetWorkflowExecutionScope, caller, retErr, workflowID, runID)
266 }()
267 > return p.persistence.GetWorkflowExecution(ctx, request) persistence_metric_clients.go
268 }
269
294 ctx context.Context,
295 request *UpdateWorkflowExecutionRequest,
296 > ) (_ *UpdateWorkflowExecutionResponse, retErr error) { persistence_metric_clients.go
297 > caller := headers.GetCallerInfo(ctx).CallerName
298 > startTime := time.Now().UTC()
299 > defer func() {
300 > p.healthSignals.Record(request.ShardID, time.Since(startTime), retErr)
301 > var workflowID, runID string
302 > if request != nil {
303 > if request.UpdateWorkflowMutation.ExecutionInfo != nil {
304 > workflowID = request.UpdateWorkflowMutation.ExecutionInfo.WorkflowId
305 > }
306 > if request.UpdateWorkflowMutation.ExecutionState != nil {
307 > runID = request.UpdateWorkflowMutation.ExecutionState.RunId
308 > }
309 }
310 > p.recordRequestMetrics(metrics.PersistenceUpdateWorkflowExecutionScope, caller, time.Since(startTime), retErr) persistence_metric_clients.go
311 > p.recordDataLossMetrics(metrics.PersistenceUpdateWorkflowExecutionScope, caller, retErr, workflowID, runID)
312 }()
313 > return p.persistence.UpdateWorkflowExecution(ctx, request) persistence_metric_clients.go
314 }
315
419 ctx context.Context,
420 request *GetHistoryTasksRequest,
421 > ) (_ *GetHistoryTasksResponse, retErr error) { persistence_metric_clients.go
422 > var operation string
423 > switch request.TaskCategory.ID() {
424 > case tasks.CategoryIDTransfer:
425 > operation = metrics.PersistenceGetTransferTasksScope
426 > case tasks.CategoryIDTimer:
427 > operation = metrics.PersistenceGetTimerTasksScope
428 > case tasks.CategoryIDVisibility:
429 > operation = metrics.PersistenceGetVisibilityTasksScope
430 case tasks.CategoryIDReplication:
431 operation = metrics.PersistenceGetReplicationTasksScope
432 > case tasks.CategoryIDArchival: persistence_metric_clients.go
433 > operation = metrics.PersistenceGetArchivalTasksScope
434 > case tasks.CategoryIDOutbound: persistence_metric_clients.go
435 > operation = metrics.PersistenceGetOutboundTasksScope
436 default:
437 return nil, serviceerror.NewInternalf("unknown task category type: %v", request.TaskCategory)
438 }
439
440 > caller := headers.GetCallerInfo(ctx).CallerName persistence_metric_clients.go
441 > startTime := time.Now().UTC()
442 > defer func() {
443 > p.healthSignals.Record(request.ShardID, time.Since(startTime), retErr)
444 > p.recordRequestMetrics(operation, caller, time.Since(startTime), retErr)
445 > p.recordDataLossMetrics(operation, caller, retErr, "", "")
446 > }()
447 > return p.persistence.GetHistoryTasks(ctx, request)
448 }
449
587 }
588
589 > func (p *executionPersistenceClient) Close() { persistence_metric_clients.go
590 > p.persistence.Close()
591 > }
592
593 func (p *taskPersistenceClient) GetName() string {
598 ctx context.Context,
599 request *CreateTasksRequest,
600 > ) (_ *CreateTasksResponse, retErr error) { persistence_metric_clients.go
601 > caller := headers.GetCallerInfo(ctx).CallerName
602 > startTime := time.Now().UTC()
603 > defer func() {
604 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
605 > p.recordRequestMetrics(metrics.PersistenceCreateTasksScope, caller, time.Since(startTime), retErr)
606 > p.recordDataLossMetrics(metrics.PersistenceCreateTasksScope, caller, retErr, "", "")
607 > }()
608 > return p.persistence.CreateTasks(ctx, request)
609 }
610
612 ctx context.Context,
613 request *GetTasksRequest,
614 > ) (_ *GetTasksResponse, retErr error) { persistence_metric_clients.go
615 > caller := headers.GetCallerInfo(ctx).CallerName
616 > startTime := time.Now().UTC()
617 > defer func() {
618 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
619 > p.recordRequestMetrics(metrics.PersistenceGetTasksScope, caller, time.Since(startTime), retErr)
620 > p.recordDataLossMetrics(metrics.PersistenceGetTasksScope, caller, retErr, "", "")
621 > }()
622 > return p.persistence.GetTasks(ctx, request)
623 }
624
640 ctx context.Context,
641 request *CreateTaskQueueRequest,
642 > ) (_ *CreateTaskQueueResponse, retErr error) { persistence_metric_clients.go
643 > caller := headers.GetCallerInfo(ctx).CallerName
644 > startTime := time.Now().UTC()
645 > defer func() {
646 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
647 > p.recordRequestMetrics(metrics.PersistenceCreateTaskQueueScope, caller, time.Since(startTime), retErr)
648 > p.recordDataLossMetrics(metrics.PersistenceCreateTaskQueueScope, caller, retErr, "", "")
649 > }()
650 > return p.persistence.CreateTaskQueue(ctx, request)
651 }
652
654 ctx context.Context,
655 request *UpdateTaskQueueRequest,
656 > ) (_ *UpdateTaskQueueResponse, retErr error) { persistence_metric_clients.go
657 > caller := headers.GetCallerInfo(ctx).CallerName
658 > startTime := time.Now().UTC()
659 > defer func() {
660 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
661 > p.recordRequestMetrics(metrics.PersistenceUpdateTaskQueueScope, caller, time.Since(startTime), retErr)
662 > p.recordDataLossMetrics(metrics.PersistenceUpdateTaskQueueScope, caller, retErr, "", "")
663 > }()
664 > return p.persistence.UpdateTaskQueue(ctx, request)
665 }
666
668 ctx context.Context,
669 request *GetTaskQueueRequest,
670 > ) (_ *GetTaskQueueResponse, retErr error) { persistence_metric_clients.go
671 > caller := headers.GetCallerInfo(ctx).CallerName
672 > startTime := time.Now().UTC()
673 > defer func() {
674 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
675 > p.recordRequestMetrics(metrics.PersistenceGetTaskQueueScope, caller, time.Since(startTime), retErr)
676 > p.recordDataLossMetrics(metrics.PersistenceGetTaskQueueScope, caller, retErr, "", "")
677 > }()
678 > return p.persistence.GetTaskQueue(ctx, request)
679 }
680
710 ctx context.Context,
711 request *GetTaskQueueUserDataRequest,
712 > ) (_ *GetTaskQueueUserDataResponse, retErr error) { persistence_metric_clients.go
713 > caller := headers.GetCallerInfo(ctx).CallerName
714 > startTime := time.Now().UTC()
715 > defer func() {
716 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
717 > p.recordRequestMetrics(metrics.PersistenceGetTaskQueueUserDataScope, caller, time.Since(startTime), retErr)
718 > p.recordDataLossMetrics(metrics.PersistenceGetTaskQueueUserDataScope, caller, retErr, "", "")
719 > }()
720 > return p.persistence.GetTaskQueueUserData(ctx, request)
721 }
722
771 }
772
773 > func (p *taskPersistenceClient) Close() { persistence_metric_clients.go
774 > p.persistence.Close()
775 > }
776
777 func (p *metadataPersistenceClient) GetName() string {
782 ctx context.Context,
783 request *CreateNamespaceRequest,
784 > ) (_ *CreateNamespaceResponse, retErr error) { persistence_metric_clients.go
785 > caller := headers.GetCallerInfo(ctx).CallerName
786 > startTime := time.Now().UTC()
787 > defer func() {
788 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
789 > p.recordRequestMetrics(metrics.PersistenceCreateNamespaceScope, caller, time.Since(startTime), retErr)
790 > p.recordDataLossMetrics(metrics.PersistenceCreateNamespaceScope, caller, retErr, "", "")
791 > }()
792 > return p.persistence.CreateNamespace(ctx, request)
793 }
794
796 ctx context.Context,
797 request *GetNamespaceRequest,
798 > ) (_ *GetNamespaceResponse, retErr error) { persistence_metric_clients.go
799 > caller := headers.GetCallerInfo(ctx).CallerName
800 > startTime := time.Now().UTC()
801 > defer func() {
802 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
803 > p.recordRequestMetrics(metrics.PersistenceGetNamespaceScope, caller, time.Since(startTime), retErr)
804 > p.recordDataLossMetrics(metrics.PersistenceGetNamespaceScope, caller, retErr, "", "")
805 > }()
806 > return p.persistence.GetNamespace(ctx, request)
807 }
808
866 ctx context.Context,
867 request *ListNamespacesRequest,
868 > ) (_ *ListNamespacesResponse, retErr error) { persistence_metric_clients.go
869 > caller := headers.GetCallerInfo(ctx).CallerName
870 > startTime := time.Now().UTC()
871 > defer func() {
872 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
873 > p.recordRequestMetrics(metrics.PersistenceListNamespacesScope, caller, time.Since(startTime), retErr)
874 > p.recordDataLossMetrics(metrics.PersistenceListNamespacesScope, caller, retErr, "", "")
875 > }()
876 > return p.persistence.ListNamespaces(ctx, request)
877 }
878
890 }
891
892 > func (p *metadataPersistenceClient) WatchNamespaces(ctx context.Context) (_ <-chan *NamespaceWatchEvent, retErr error) { persistence_metric_clients.go
893 > caller := headers.GetCallerInfo(ctx).CallerName
894 > startTime := time.Now().UTC()
895 > defer func() {
896 > metricErr := retErr
897 > // WatchNotSupported isn't really a persistence error. It's just a signal that persistence doesn't support watching.
898 > if errors.Is(metricErr, ErrWatchNotSupported) {
899 > metricErr = nil
900 > }
901 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), metricErr)
902 > p.recordRequestMetrics(metrics.PersistenceWatchNamespacesScope, caller, time.Since(startTime), metricErr)
903 > p.recordDataLossMetrics(metrics.PersistenceWatchNamespacesScope, caller, metricErr, "", "")
904 }()
905 > return p.persistence.WatchNamespaces(ctx) persistence_metric_clients.go
906 }
907
908 > func (p *metadataPersistenceClient) Close() { persistence_metric_clients.go
909 > p.persistence.Close()
910 > }
911
912 // AppendHistoryNodes add a node to history node table
944 ctx context.Context,
945 request *ReadHistoryBranchRequest,
946 > ) (_ *ReadHistoryBranchResponse, retErr error) { persistence_metric_clients.go
947 > caller := headers.GetCallerInfo(ctx).CallerName
948 > startTime := time.Now().UTC()
949 > defer func() {
950 > p.recordRequestMetrics(metrics.PersistenceReadHistoryBranchScope, caller, time.Since(startTime), retErr)
951 > p.recordDataLossMetrics(metrics.PersistenceReadHistoryBranchScope, caller, retErr, "", "")
952 > }()
953 > return p.persistence.ReadHistoryBranch(ctx, request)
954 }
955
1055 ctx context.Context,
1056 blob *commonpb.DataBlob,
1058 > return p.persistence.Init(ctx, blob)
1059 > }
1060
1061 func (p *queuePersistenceClient) EnqueueMessage(
1216 }
1217
1218 > func (p *queuePersistenceClient) Close() { persistence_metric_clients.go
1219 > p.persistence.Close()
1220 > }
1221
1222 > func (p *clusterMetadataPersistenceClient) Close() { persistence_metric_clients.go
1223 > p.persistence.Close()
1224 > }
1225
1226 func (p *clusterMetadataPersistenceClient) ListClusterMetadata(
1227 ctx context.Context,
1228 request *ListClusterMetadataRequest,
1229 > ) (_ *ListClusterMetadataResponse, retErr error) { persistence_metric_clients.go
1230 > caller := headers.GetCallerInfo(ctx).CallerName
1231 > startTime := time.Now().UTC()
1232 > defer func() {
1233 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1234 > p.recordRequestMetrics(metrics.PersistenceListClusterMetadataScope, caller, time.Since(startTime), retErr)
1235 > p.recordDataLossMetrics(metrics.PersistenceListClusterMetadataScope, caller, retErr, "", "")
1236 > }()
1237 > return p.persistence.ListClusterMetadata(ctx, request)
1238 }
1239
1240 func (p *clusterMetadataPersistenceClient) GetCurrentClusterMetadata(
1241 ctx context.Context,
1242 > ) (_ *GetClusterMetadataResponse, retErr error) { persistence_metric_clients.go
1243 > caller := headers.GetCallerInfo(ctx).CallerName
1244 > startTime := time.Now().UTC()
1245 > defer func() {
1246 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1247 > p.recordRequestMetrics(metrics.PersistenceGetCurrentClusterMetadataScope, caller, time.Since(startTime), retErr)
1248 > p.recordDataLossMetrics(metrics.PersistenceGetCurrentClusterMetadataScope, caller, retErr, "", "")
1249 > }()
1250 > return p.persistence.GetCurrentClusterMetadata(ctx)
1251 }
1252
1254 ctx context.Context,
1255 request *GetClusterMetadataRequest,
1256 > ) (_ *GetClusterMetadataResponse, retErr error) { persistence_metric_clients.go
1257 > caller := headers.GetCallerInfo(ctx).CallerName
1258 > startTime := time.Now().UTC()
1259 > defer func() {
1260 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1261 > p.recordRequestMetrics(metrics.PersistenceGetClusterMetadataScope, caller, time.Since(startTime), retErr)
1262 > p.recordDataLossMetrics(metrics.PersistenceGetClusterMetadataScope, caller, retErr, "", "")
1263 > }()
1264 > return p.persistence.GetClusterMetadata(ctx, request)
1265 }
1266
1268 ctx context.Context,
1269 request *SaveClusterMetadataRequest,
1270 > ) (_ bool, retErr error) { persistence_metric_clients.go
1271 > caller := headers.GetCallerInfo(ctx).CallerName
1272 > startTime := time.Now().UTC()
1273 > defer func() {
1274 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1275 > p.recordRequestMetrics(metrics.PersistenceSaveClusterMetadataScope, caller, time.Since(startTime), retErr)
1276 > p.recordDataLossMetrics(metrics.PersistenceSaveClusterMetadataScope, caller, retErr, "", "")
1277 > }()
1278 > return p.persistence.SaveClusterMetadata(ctx, request)
1279 }
1280
1300 ctx context.Context,
1301 request *GetClusterMembersRequest,
1302 > ) (_ *GetClusterMembersResponse, retErr error) { persistence_metric_clients.go
1303 > caller := headers.GetCallerInfo(ctx).CallerName
1304 > startTime := time.Now().UTC()
1305 > defer func() {
1306 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1307 > p.recordRequestMetrics(metrics.PersistenceGetClusterMembersScope, caller, time.Since(startTime), retErr)
1308 > p.recordDataLossMetrics(metrics.PersistenceGetClusterMembersScope, caller, retErr, "", "")
1309 > }()
1310 > return p.persistence.GetClusterMembers(ctx, request)
1311 }
1312
1314 ctx context.Context,
1315 request *UpsertClusterMembershipRequest,
1316 > ) (retErr error) { persistence_metric_clients.go
1317 > caller := headers.GetCallerInfo(ctx).CallerName
1318 > startTime := time.Now().UTC()
1319 > defer func() {
1320 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1321 > p.recordRequestMetrics(metrics.PersistenceUpsertClusterMembershipScope, caller, time.Since(startTime), retErr)
1322 > p.recordDataLossMetrics(metrics.PersistenceUpsertClusterMembershipScope, caller, retErr, "", "")
1323 > }()
1324 > return p.persistence.UpsertClusterMembership(ctx, request)
1325 }
1326
1328 ctx context.Context,
1329 request *PruneClusterMembershipRequest,
1330 > ) (retErr error) { persistence_metric_clients.go
1331 > caller := headers.GetCallerInfo(ctx).CallerName
1332 > startTime := time.Now().UTC()
1333 > defer func() {
1334 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1335 > p.recordRequestMetrics(metrics.PersistencePruneClusterMembershipScope, caller, time.Since(startTime), retErr)
1336 > p.recordDataLossMetrics(metrics.PersistencePruneClusterMembershipScope, caller, retErr, "", "")
1337 > }()
1338 > return p.persistence.PruneClusterMembership(ctx, request)
1339 }
1340
1342 ctx context.Context,
1343 currentClusterName string,
1344 > ) (retErr error) { persistence_metric_clients.go
1345 > caller := headers.GetCallerInfo(ctx).CallerName
1346 > startTime := time.Now().UTC()
1347 > defer func() {
1348 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1349 > p.recordRequestMetrics(metrics.PersistenceInitializeSystemNamespaceScope, caller, time.Since(startTime), retErr)
1350 > p.recordDataLossMetrics(metrics.PersistenceInitializeSystemNamespaceScope, caller, retErr, "", "")
1351 > }()
1352 > return p.persistence.InitializeSystemNamespaces(ctx, currentClusterName)
1353 }
1354
1357 }
1358
1359 > func (p *nexusEndpointPersistenceClient) Close() { persistence_metric_clients.go
1360 > p.persistence.Close()
1361 > }
1362
1363 func (p *nexusEndpointPersistenceClient) GetNexusEndpoint(
1378 ctx context.Context,
1379 request *ListNexusEndpointsRequest,
1380 > ) (_ *ListNexusEndpointsResponse, retErr error) { persistence_metric_clients.go
1381 > caller := headers.GetCallerInfo(ctx).CallerName
1382 > startTime := time.Now().UTC()
1383 > defer func() {
1384 > p.healthSignals.Record(CallerSegmentMissing, time.Since(startTime), retErr)
1385 > p.recordRequestMetrics(metrics.PersistenceListNexusEndpointsScope, caller, time.Since(startTime), retErr)
1386 > p.recordDataLossMetrics(metrics.PersistenceListNexusEndpointsScope, caller, retErr, "", "")
1387 > }()
1388 > return p.persistence.ListNexusEndpoints(ctx, request)
1389 }
1390
1417 }
1418
1419 > func (p *metricEmitter) recordRequestMetrics(operation string, caller string, latency time.Duration, err error) { persistence_metric_clients.go
1420 > handler := p.metricsHandler.WithTags(metrics.OperationTag(operation), metrics.NamespaceTag(caller))
1421 > metrics.PersistenceRequests.With(handler).Record(1)
1422 > metrics.PersistenceLatency.With(handler).Record(latency)
1423 > updateErrorMetric(handler, p.logger, operation, err)
1424 > }
1425
1426 > func (p *metricEmitter) recordDataLossMetrics(operation string, caller string, err error, workflowID, runID string) { persistence_metric_clients.go
1427 > // Emit data loss metrics if enabled and error is DataLoss
1428 > var dataLoss *serviceerror.DataLoss
1429 > if errors.As(err, &dataLoss) {
1430 if p.enableDataLossMetrics() {
1431 EmitDataLossMetric(p.metricsHandler, caller, workflowID, runID, operation, err)
1434 }
1435
1436 > func updateErrorMetric(handler metrics.Handler, logger log.Logger, operation string, err error) { persistence_metric_clients.go
1437 > if err != nil {
1438 > metrics.PersistenceErrorWithType.With(handler).Record(1, metrics.ServiceErrorTypeTag(err)) persistence_metric_clients.go
1439 > if common.IsContextCanceledErr(err) {
1440 // no-op
1441 return
1442 }
1443 > switch err := err.(type) { persistence_metric_clients.go
1444 case *ShardAlreadyExistError,
1445 *ShardOwnershipLostError,
1452 *serviceerror.NamespaceAlreadyExists,
1453 *serviceerror.NotFound,
1454 > *serviceerror.NamespaceNotFound: persistence_metric_clients.go
1455 // no-op
1456
go.temporal.io/server/service/history/configs/config.go 395 covered LOC · 2 ranges

Open complete file

445 dc *dynamicconfig.Collection,
446 numberOfShards int32,
447 > ) *Config { config.go
448 > cfg := &Config{
449 > NumberOfShards: numberOfShards,
450 >
451 > EnableReplicationStream: dynamicconfig.EnableReplicationStream.Get(dc),
452 > EmitReplicationLifecycleEvents: dynamicconfig.EmitReplicationLifecycleEvents.Get(dc),
453 > EnableCloseInboundReplicationStreamOnShutdown: dynamicconfig.EnableCloseInboundReplicationStreamOnShutdown.Get(dc),
454 > EnableSeparateReplicationEnableFlag: dynamicconfig.EnableSeparateReplicationEnableFlag.Get(dc),
455 > HistoryReplicationDLQV2: dynamicconfig.EnableHistoryReplicationDLQV2.Get(dc),
456 >
457 > RPS: dynamicconfig.HistoryRPS.Get(dc),
458 > NamespaceRPS: dynamicconfig.HistoryNamespaceRPS.Get(dc),
459 > OperatorRPSRatio: dynamicconfig.OperatorRPSRatio.Get(dc),
460 > MaxIDLengthLimit: dynamicconfig.MaxIDLengthLimit.Get(dc),
461 > PersistenceMaxQPS: dynamicconfig.HistoryPersistenceMaxQPS.Get(dc),
462 > PersistenceGlobalMaxQPS: dynamicconfig.HistoryPersistenceGlobalMaxQPS.Get(dc),
463 > PersistenceNamespaceMaxQPS: dynamicconfig.HistoryPersistenceNamespaceMaxQPS.Get(dc),
464 > PersistenceGlobalNamespaceMaxQPS: dynamicconfig.HistoryPersistenceGlobalNamespaceMaxQPS.Get(dc),
465 > PersistencePerShardNamespaceMaxQPS: dynamicconfig.HistoryPersistencePerShardNamespaceMaxQPS.Get(dc),
466 > PersistenceDynamicRateLimitingParams: dynamicconfig.HistoryPersistenceDynamicRateLimitingParams.Get(dc),
467 > PersistenceQPSBurstRatio: dynamicconfig.PersistenceQPSBurstRatio.Get(dc),
468 > AlignMembershipChange: dynamicconfig.HistoryAlignMembershipChange.Get(dc),
469 > ShutdownDrainDuration: dynamicconfig.HistoryShutdownDrainDuration.Get(dc),
470 > StartupMembershipJoinDelay: dynamicconfig.HistoryStartupMembershipJoinDelay.Get(dc),
471 > AllowResetWithPendingChildren: dynamicconfig.AllowResetWithPendingChildren.Get(dc),
472 > MaxAutoResetPoints: dynamicconfig.HistoryMaxAutoResetPoints.Get(dc),
473 > DefaultWorkflowTaskTimeout: dynamicconfig.DefaultWorkflowTaskTimeout.Get(dc),
474 >
475 > MaxLocalParentWorkflowVerificationDuration: dynamicconfig.MaxLocalParentWorkflowVerificationDuration.Get(dc),
476 >
477 > VisibilityPersistenceMaxReadQPS: dynamicconfig.VisibilityPersistenceMaxReadQPS.Get(dc),
478 > VisibilityPersistenceMaxWriteQPS: dynamicconfig.VisibilityPersistenceMaxWriteQPS.Get(dc),
479 > VisibilityPersistenceSlowQueryThreshold: dynamicconfig.VisibilityPersistenceSlowQueryThreshold.Get(dc),
480 > EnableReadFromSecondaryVisibility: dynamicconfig.EnableReadFromSecondaryVisibility.Get(dc),
481 > VisibilityEnableShadowReadMode: dynamicconfig.VisibilityEnableShadowReadMode.Get(dc),
482 > SecondaryVisibilityWritingMode: dynamicconfig.SecondaryVisibilityWritingMode.Get(dc),
483 > VisibilityDisableOrderByClause: dynamicconfig.VisibilityDisableOrderByClause.Get(dc),
484 > VisibilityEnableManualPagination: dynamicconfig.VisibilityEnableManualPagination.Get(dc),
485 > VisibilityEnableUnifiedQueryConverter: dynamicconfig.VisibilityEnableUnifiedQueryConverter.Get(dc),
486 > VisibilityAllowList: dynamicconfig.VisibilityAllowList.Get(dc),
487 > SuppressErrorSetSystemSearchAttribute: dynamicconfig.SuppressErrorSetSystemSearchAttribute.Get(dc),
488 >
489 > EmitShardLagLog: dynamicconfig.EmitShardLagLog.Get(dc),
490 > EnableDataLossMetrics: dynamicconfig.EnableDataLossMetrics.Get(dc),
491 > // HistoryCacheLimitSizeBased should not change during runtime.
492 > HistoryCacheLimitSizeBased: dynamicconfig.HistoryCacheSizeBasedLimit.Get(dc)(),
493 > HistoryHostLevelCacheMaxSize: dynamicconfig.HistoryCacheHostLevelMaxSize.Get(dc),
494 > HistoryHostLevelCacheMaxSizeBytes: dynamicconfig.HistoryCacheHostLevelMaxSizeBytes.Get(dc),
495 > HistoryCacheTTL: dynamicconfig.HistoryCacheTTL.Get(dc),
496 > HistoryCacheNonUserContextLockTimeout: dynamicconfig.HistoryCacheNonUserContextLockTimeout.Get(dc),
497 > HistoryCacheBackgroundEvict: dynamicconfig.HistoryCacheBackgroundEvict.Get(dc),
498 > EnableWorkflowExecutionTimeoutTimer: dynamicconfig.EnableWorkflowExecutionTimeoutTimer.Get(dc),
499 > EnableUpdateWorkflowModeIgnoreCurrent: dynamicconfig.EnableUpdateWorkflowModeIgnoreCurrent.Get(dc),
500 > EnableTransitionHistory: dynamicconfig.EnableTransitionHistory.Get(dc),
501 > MaxCallbacksPerWorkflow: dynamicconfig.MaxCallbacksPerWorkflow.Get(dc),
502 > MaxCallbacksPerExecution: callback.MaxPerExecution.Get(dc),
503 > MaxCallbacksPerUpdateID: dynamicconfig.MaxCallbacksPerUpdateID.Get(dc),
504 > EnableChasm: dynamicconfig.EnableChasm.Get(dc),
505 > EnableChasmNexusWorkflowOperations: nexusoperation.EnableChasmWorkflowOperations.Get(dc),
506 > ChasmMaxInMemoryPureTasks: dynamicconfig.ChasmMaxInMemoryPureTasks.Get(dc),
507 >
508 > EnableCHASMSchedulerCreation: dynamicconfig.EnableCHASMSchedulerCreation.Get(dc),
509 > EnableCHASMSchedulerMigration: dynamicconfig.EnableCHASMSchedulerMigration.Get(dc),
510 >
511 > EnableCHASMCallbacks: dynamicconfig.EnableCHASMCallbacks.Get(dc),
512 > EnableCHASMSignalBacklinks: dynamicconfig.EnableCHASMSignalBacklinks.Get(dc),
513 > ExternalPayloadsEnabled: dynamicconfig.ExternalPayloadsEnabled.Get(dc),
514 > EnableWorkflowUpdateCallbacks: dynamicconfig.EnableWorkflowUpdateCallbacks.Get(dc),
515 >
516 > EventsShardLevelCacheMaxSizeBytes: dynamicconfig.EventsCacheMaxSizeBytes.Get(dc), // 512KB
517 > EventsHostLevelCacheMaxSizeBytes: dynamicconfig.EventsHostLevelCacheMaxSizeBytes.Get(dc), // 256MB
518 > EventsCacheTTL: dynamicconfig.EventsCacheTTL.Get(dc),
519 > EnableHostLevelEventsCache: dynamicconfig.EnableHostLevelEventsCache.Get(dc),
520 >
521 > RangeSizeBits: 20, // 20 bits for sequencer, 2^20 sequence number for any range
522 >
523 > AcquireShardInterval: dynamicconfig.AcquireShardInterval.Get(dc),
524 > AcquireShardConcurrency: dynamicconfig.AcquireShardConcurrency.Get(dc),
525 > ShardIOConcurrency: dynamicconfig.ShardIOConcurrency.Get(dc),
526 > ShardIOTimeout: dynamicconfig.ShardIOTimeout.Get(dc),
527 > ShardLingerOwnershipCheckQPS: dynamicconfig.ShardLingerOwnershipCheckQPS.Get(dc),
528 > ShardLingerTimeLimit: dynamicconfig.ShardLingerTimeLimit.Get(dc),
529 > ShardFinalizerTimeout: dynamicconfig.ShardFinalizerTimeout.Get(dc),
530 >
531 > HistoryClientOwnershipCachingEnabled: dynamicconfig.HistoryClientOwnershipCachingEnabled.Get(dc),
532 >
533 > StandbyClusterDelay: dynamicconfig.StandbyClusterDelay.Get(dc),
534 > StandbyTaskMissingEventsResendDelay: dynamicconfig.StandbyTaskMissingEventsResendDelay.Get(dc),
535 > StandbyTaskMissingEventsDiscardDelay: dynamicconfig.StandbyTaskMissingEventsDiscardDelay.Get(dc),
536 > ChasmStandbyTaskDiscardDelay: dynamicconfig.ChasmStandbyTaskDiscardDelay.Get(dc),
537 >
538 > QueuePendingTaskCriticalCount: dynamicconfig.QueuePendingTaskCriticalCount.Get(dc),
539 > QueueReaderStuckCriticalAttempts: dynamicconfig.QueueReaderStuckCriticalAttempts.Get(dc),
540 > QueueCriticalSlicesCount: dynamicconfig.QueueCriticalSlicesCount.Get(dc),
541 > QueuePendingTaskMaxCount: dynamicconfig.QueuePendingTaskMaxCount.Get(dc),
542 > QueueMaxPredicateSize: dynamicconfig.QueueMaxPredicateSize.Get(dc),
543 > QueueShrinkPredicateMaxPendingKeys: dynamicconfig.QueueShrinkPredicateMaxPendingKeys.Get(dc),
544 > QueueMoveGroupTaskCountBase: dynamicconfig.QueueMoveGroupTaskCountBase.Get(dc),
545 > QueueMoveGroupTaskCountMultiplier: dynamicconfig.QueueMoveGroupTaskCountMultiplier.Get(dc),
546 >
547 > TaskDLQEnabled: dynamicconfig.HistoryTaskDLQEnabled.Get(dc),
548 > TaskDLQUnexpectedErrorAttempts: dynamicconfig.HistoryTaskDLQUnexpectedErrorAttempts.Get(dc),
549 > TaskDLQInternalErrors: dynamicconfig.HistoryTaskDLQInternalErrors.Get(dc),
550 > TaskDLQErrorPattern: dynamicconfig.HistoryTaskDLQErrorPattern.Get(dc),
551 >
552 > TaskSchedulerEnableRateLimiter: dynamicconfig.TaskSchedulerEnableRateLimiter.Get(dc),
553 > TaskSchedulerEnableRateLimiterShadowMode: dynamicconfig.TaskSchedulerEnableRateLimiterShadowMode.Get(dc),
554 > TaskSchedulerRateLimiterStartupDelay: dynamicconfig.TaskSchedulerRateLimiterStartupDelay.Get(dc),
555 > TaskSchedulerGlobalMaxQPS: dynamicconfig.TaskSchedulerGlobalMaxQPS.Get(dc),
556 > TaskSchedulerMaxQPS: dynamicconfig.TaskSchedulerMaxQPS.Get(dc),
557 > TaskSchedulerNamespaceMaxQPS: dynamicconfig.TaskSchedulerNamespaceMaxQPS.Get(dc),
558 > TaskSchedulerGlobalNamespaceMaxQPS: dynamicconfig.TaskSchedulerGlobalNamespaceMaxQPS.Get(dc),
559 > TaskSchedulerInactiveChannelDeletionDelay: dynamicconfig.TaskSchedulerInactiveChannelDeletionDelay.Get(dc),
560 > TaskSchedulerEnableExecutionQueueScheduler: dynamicconfig.TaskSchedulerEnableExecutionQueueScheduler.Get(dc),
561 > TaskSchedulerExecutionQueueSchedulerMaxQueues: dynamicconfig.TaskSchedulerExecutionQueueSchedulerMaxQueues.Get(dc),
562 > TaskSchedulerExecutionQueueSchedulerQueueTTL: dynamicconfig.TaskSchedulerExecutionQueueSchedulerQueueTTL.Get(dc),
563 > TaskSchedulerExecutionQueueSchedulerQueueConcurrency: dynamicconfig.TaskSchedulerExecutionQueueSchedulerQueueConcurrency.Get(dc),
564 >
565 > TimerTaskBatchSize: dynamicconfig.TimerTaskBatchSize.Get(dc),
566 > TimerProcessorSchedulerWorkerCount: dynamicconfig.TimerProcessorSchedulerWorkerCount.Subscribe(dc),
567 > TimerProcessorSchedulerActiveRoundRobinWeights: dynamicconfig.TimerProcessorSchedulerActiveRoundRobinWeights.WithDefault(ConvertWeightsToDynamicConfigValue(DefaultActiveTaskPriorityWeight)).Get(dc),
568 > TimerProcessorSchedulerStandbyRoundRobinWeights: dynamicconfig.TimerProcessorSchedulerStandbyRoundRobinWeights.WithDefault(ConvertWeightsToDynamicConfigValue(DefaultStandbyTaskPriorityWeight)).Get(dc),
569 > TimerProcessorUpdateAckInterval: dynamicconfig.TimerProcessorUpdateAckInterval.Get(dc),
570 > TimerProcessorUpdateAckIntervalJitterCoefficient: dynamicconfig.TimerProcessorUpdateAckIntervalJitterCoefficient.Get(dc),
571 > TimerProcessorMaxPollRPS: dynamicconfig.TimerProcessorMaxPollRPS.Get(dc),
572 > TimerProcessorMaxPollHostRPS: dynamicconfig.TimerProcessorMaxPollHostRPS.Get(dc),
573 > TimerProcessorMaxPollInterval: dynamicconfig.TimerProcessorMaxPollInterval.Get(dc),
574 > TimerProcessorMaxPollIntervalJitterCoefficient: dynamicconfig.TimerProcessorMaxPollIntervalJitterCoefficient.Get(dc),
575 > TimerProcessorPollBackoffInterval: dynamicconfig.TimerProcessorPollBackoffInterval.Get(dc),
576 > TimerProcessorMaxTimeShift: dynamicconfig.TimerProcessorMaxTimeShift.Get(dc),
577 > TransferQueueMaxReaderCount: dynamicconfig.TransferQueueMaxReaderCount.Get(dc),
578 > RetentionTimerJitterDuration: dynamicconfig.RetentionTimerJitterDuration.Get(dc),
579 >
580 > MemoryTimerProcessorSchedulerWorkerCount: dynamicconfig.MemoryTimerProcessorSchedulerWorkerCount.Subscribe(dc),
581 >
582 > TransferTaskBatchSize: dynamicconfig.TransferTaskBatchSize.Get(dc),
583 > TransferProcessorSchedulerWorkerCount: dynamicconfig.TransferProcessorSchedulerWorkerCount.Subscribe(dc),
584 > TransferProcessorSchedulerActiveRoundRobinWeights: dynamicconfig.TransferProcessorSchedulerActiveRoundRobinWeights.WithDefault(ConvertWeightsToDynamicConfigValue(DefaultActiveTaskPriorityWeight)).Get(dc),
585 > TransferProcessorSchedulerStandbyRoundRobinWeights: dynamicconfig.TransferProcessorSchedulerStandbyRoundRobinWeights.WithDefault(ConvertWeightsToDynamicConfigValue(DefaultStandbyTaskPriorityWeight)).Get(dc),
586 > TransferProcessorMaxPollRPS: dynamicconfig.TransferProcessorMaxPollRPS.Get(dc),
587 > TransferProcessorMaxPollHostRPS: dynamicconfig.TransferProcessorMaxPollHostRPS.Get(dc),
588 > TransferProcessorMaxPollInterval: dynamicconfig.TransferProcessorMaxPollInterval.Get(dc),
589 > TransferProcessorMaxPollIntervalJitterCoefficient: dynamicconfig.TransferProcessorMaxPollIntervalJitterCoefficient.Get(dc),
590 > TransferProcessorUpdateAckInterval: dynamicconfig.TransferProcessorUpdateAckInterval.Get(dc),
591 > TransferProcessorUpdateAckIntervalJitterCoefficient: dynamicconfig.TransferProcessorUpdateAckIntervalJitterCoefficient.Get(dc),
592 > TransferProcessorPollBackoffInterval: dynamicconfig.TransferProcessorPollBackoffInterval.Get(dc),
593 > TransferProcessorEnsureCloseBeforeDelete: dynamicconfig.TransferProcessorEnsureCloseBeforeDelete.Get(dc),
594 > TimerQueueMaxReaderCount: dynamicconfig.TimerQueueMaxReaderCount.Get(dc),
595 >
596 > OutboundTaskBatchSize: dynamicconfig.OutboundTaskBatchSize.Get(dc),
597 > OutboundProcessorMaxPollRPS: dynamicconfig.OutboundProcessorMaxPollRPS.Get(dc),
598 > OutboundProcessorMaxPollHostRPS: dynamicconfig.OutboundProcessorMaxPollHostRPS.Get(dc),
599 > OutboundProcessorMaxPollInterval: dynamicconfig.OutboundProcessorMaxPollInterval.Get(dc),
600 > OutboundProcessorMaxPollIntervalJitterCoefficient: dynamicconfig.OutboundProcessorMaxPollIntervalJitterCoefficient.Get(dc),
601 > OutboundProcessorUpdateAckInterval: dynamicconfig.OutboundProcessorUpdateAckInterval.Get(dc),
602 > OutboundProcessorUpdateAckIntervalJitterCoefficient: dynamicconfig.OutboundProcessorUpdateAckIntervalJitterCoefficient.Get(dc),
603 > OutboundProcessorPollBackoffInterval: dynamicconfig.OutboundProcessorPollBackoffInterval.Get(dc),
604 > OutboundQueuePendingTaskCriticalCount: dynamicconfig.OutboundQueuePendingTaskCriticalCount.Get(dc),
605 > OutboundQueuePendingTaskMaxCount: dynamicconfig.OutboundQueuePendingTaskMaxCount.Get(dc),
606 > OutboundQueueMaxPredicateSize: dynamicconfig.OutboundQueueMaxPredicateSize.Get(dc),
607 > OutboundQueueMaxReaderCount: dynamicconfig.OutboundQueueMaxReaderCount.Get(dc),
608 > OutboundQueueGroupLimiterBufferSize: dynamicconfig.OutboundQueueGroupLimiterBufferSize.Get(dc),
609 > OutboundQueueGroupLimiterConcurrency: dynamicconfig.OutboundQueueGroupLimiterConcurrency.Get(dc),
610 > OutboundQueueHostSchedulerMaxTaskRPS: dynamicconfig.OutboundQueueHostSchedulerMaxTaskRPS.Get(dc),
611 > OutboundQueueCircuitBreakerSettings: dynamicconfig.OutboundQueueCircuitBreakerSettings.Subscribe(dc),
612 > OutboundStandbyTaskMissingEventsDestinationDownErr: dynamicconfig.OutboundStandbyTaskMissingEventsDestinationDownErr.Get(dc),
613 > OutboundStandbyTaskMissingEventsDiscardDelay: dynamicconfig.OutboundStandbyTaskMissingEventsDiscardDelay.Get(dc),
614 >
615 > ReplicatorProcessorMaxPollInterval: dynamicconfig.ReplicatorProcessorMaxPollInterval.Get(dc),
616 > ReplicatorProcessorMaxPollIntervalJitterCoefficient: dynamicconfig.ReplicatorProcessorMaxPollIntervalJitterCoefficient.Get(dc),
617 > ReplicatorProcessorFetchTasksBatchSize: dynamicconfig.ReplicatorTaskBatchSize.Get(dc),
618 > ReplicatorProcessorMaxSkipTaskCount: dynamicconfig.ReplicatorMaxSkipTaskCount.Get(dc),
619 > ReplicationTaskProcessorHostQPS: dynamicconfig.ReplicationTaskProcessorHostQPS.Get(dc),
620 > ReplicationTaskProcessorShardQPS: dynamicconfig.ReplicationTaskProcessorShardQPS.Get(dc),
621 > ReplicationEnableDLQMetrics: dynamicconfig.ReplicationEnableDLQMetrics.Get(dc),
622 > ReplicationEnableUpdateWithNewTaskMerge: dynamicconfig.ReplicationEnableUpdateWithNewTaskMerge.Get(dc),
623 > ReplicationStreamSyncStatusDuration: dynamicconfig.ReplicationStreamSyncStatusDuration.Get(dc),
624 > ReplicationProcessorSchedulerQueueSize: dynamicconfig.ReplicationProcessorSchedulerQueueSize.Get(dc),
625 > ReplicationProcessorSchedulerWorkerCount: dynamicconfig.ReplicationProcessorSchedulerWorkerCount.Subscribe(dc),
626 > ReplicationLowPriorityProcessorSchedulerWorkerCount: dynamicconfig.ReplicationLowPriorityProcessorSchedulerWorkerCount.Subscribe(dc),
627 > ReplicationLowPriorityTaskParallelism: dynamicconfig.ReplicationLowPriorityTaskParallelism.Get(dc),
628 > EnableReplicationTaskBatching: dynamicconfig.EnableReplicationTaskBatching.Get(dc),
629 > EnableReplicationTaskTieredProcessing: dynamicconfig.EnableReplicationTaskTieredProcessing.Get(dc),
630 > ReplicationStreamSenderHighPriorityQPS: dynamicconfig.ReplicationStreamSenderHighPriorityQPS.Get(dc),
631 > ReplicationStreamSenderLowPriorityQPS: dynamicconfig.ReplicationStreamSenderLowPriorityQPS.Get(dc),
632 > ReplicationStreamEventLoopRetryMaxAttempts: dynamicconfig.ReplicationStreamEventLoopRetryMaxAttempts.Get(dc),
633 > ReplicationReceiverMaxOutstandingTaskCount: dynamicconfig.ReplicationReceiverMaxOutstandingTaskCount.Get(dc),
634 > ReplicationReceiverSlowSubmissionLatencyThreshold: dynamicconfig.ReplicationReceiverSlowSubmissionLatencyThreshold.Get(dc),
635 > ReplicationReceiverSlowSubmissionWindow: dynamicconfig.ReplicationReceiverSlowSubmissionWindow.Get(dc),
636 > EnableReplicationReceiverSlowSubmissionFlowControl: dynamicconfig.EnableReplicationReceiverSlowSubmissionFlowControl.Get(dc),
637 > ReplicationResendMaxBatchCount: dynamicconfig.ReplicationResendMaxBatchCount.Get(dc),
638 > ReplicationProgressCacheMaxSize: dynamicconfig.ReplicationProgressCacheMaxSize.Get(dc),
639 > ReplicationProgressCacheTTL: dynamicconfig.ReplicationProgressCacheTTL.Get(dc),
640 > ReplicationEnableRateLimit: dynamicconfig.ReplicationEnableRateLimit.Get(dc),
641 > ReplicationEnableRateLimitShadowMode: dynamicconfig.ReplicationEnableRateLimitShadowMode.Get(dc),
642 > ReplicationStreamSendEmptyTaskDuration: dynamicconfig.ReplicationStreamSendEmptyTaskDuration.Get(dc),
643 > ReplicationStreamReceiverLivenessMultiplier: dynamicconfig.ReplicationStreamReceiverLivenessMultiplier.Get(dc),
644 > ReplicationStreamSenderLivenessMultiplier: dynamicconfig.ReplicationStreamSenderLivenessMultiplier.Get(dc),
645 > EnableHistoryReplicationRateLimiter: dynamicconfig.EnableHistoryReplicationRateLimiter.Get(dc),
646 >
647 > MaximumBufferedEventsBatch: dynamicconfig.MaximumBufferedEventsBatch.Get(dc),
648 > MaximumBufferedEventsSizeInBytes: dynamicconfig.MaximumBufferedEventsSizeInBytes.Get(dc),
649 > MaximumSignalsPerExecution: dynamicconfig.MaximumSignalsPerExecution.Get(dc),
650 > MaximumEventBatchSizeInBytes: dynamicconfig.MaximumEventBatchSizeInBytes.Get(dc),
651 > ShardUpdateMinInterval: dynamicconfig.ShardUpdateMinInterval.Get(dc),
652 > ShardFirstUpdateInterval: dynamicconfig.ShardFirstUpdateInterval.Get(dc),
653 > ShardUpdateMinTasksCompleted: dynamicconfig.ShardUpdateMinTasksCompleted.Get(dc),
654 > ShardSyncMinInterval: dynamicconfig.ShardSyncMinInterval.Get(dc),
655 > ShardSyncTimerJitterCoefficient: dynamicconfig.TransferProcessorMaxPollIntervalJitterCoefficient.Get(dc),
656 >
657 > // history client: client/history/client.go set the client timeout 30s
658 > // TODO: Return this value to the client: go.temporal.io/server/issues/294
659 > LongPollExpirationInterval: dynamicconfig.HistoryLongPollExpirationInterval.Get(dc),
660 > EnableParentClosePolicy: dynamicconfig.EnableParentClosePolicy.Get(dc),
661 > NumParentClosePolicySystemWorkflows: dynamicconfig.NumParentClosePolicySystemWorkflows.Get(dc),
662 > EnableParentClosePolicyWorker: dynamicconfig.EnableParentClosePolicyWorker.Get(dc),
663 > ParentClosePolicyThreshold: dynamicconfig.ParentClosePolicyThreshold.Get(dc),
664 >
665 > BlobSizeLimitError: dynamicconfig.BlobSizeLimitError.Get(dc),
666 > BlobSizeLimitWarn: dynamicconfig.BlobSizeLimitWarn.Get(dc),
667 > MemoSizeLimitError: dynamicconfig.MemoSizeLimitError.Get(dc),
668 > MemoSizeLimitWarn: dynamicconfig.MemoSizeLimitWarn.Get(dc),
669 > NumPendingChildExecutionsLimit: dynamicconfig.NumPendingChildExecutionsLimitError.Get(dc),
670 > NumPendingActivitiesLimit: dynamicconfig.NumPendingActivitiesLimitError.Get(dc),
671 > NumPendingSignalsLimit: dynamicconfig.NumPendingSignalsLimitError.Get(dc),
672 > NumPendingCancelsRequestLimit: dynamicconfig.NumPendingCancelRequestsLimitError.Get(dc),
673 > HistorySizeLimitError: dynamicconfig.HistorySizeLimitError.Get(dc),
674 > HistorySizeLimitWarn: dynamicconfig.HistorySizeLimitWarn.Get(dc),
675 > HistorySizeSuggestContinueAsNew: dynamicconfig.HistorySizeSuggestContinueAsNew.Get(dc),
676 > HistoryCountLimitError: dynamicconfig.HistoryCountLimitError.Get(dc),
677 > HistoryCountLimitWarn: dynamicconfig.HistoryCountLimitWarn.Get(dc),
678 > HistoryCountSuggestContinueAsNew: dynamicconfig.HistoryCountSuggestContinueAsNew.Get(dc),
679 > HistoryMaxPageSize: dynamicconfig.HistoryMaxPageSize.Get(dc),
680 > MutableStateActivityFailureSizeLimitError: dynamicconfig.MutableStateActivityFailureSizeLimitError.Get(dc),
681 > MutableStateActivityFailureSizeLimitWarn: dynamicconfig.MutableStateActivityFailureSizeLimitWarn.Get(dc),
682 > MutableStateSizeLimitError: dynamicconfig.MutableStateSizeLimitError.Get(dc),
683 > MutableStateSizeLimitWarn: dynamicconfig.MutableStateSizeLimitWarn.Get(dc),
684 > MutableStateTombstoneCountLimit: dynamicconfig.MutableStateTombstoneCountLimit.Get(dc),
685 >
686 > ThrottledLogRPS: dynamicconfig.HistoryThrottledLogRPS.Get(dc),
687 > EnableStickyQuery: dynamicconfig.EnableStickyQuery.Get(dc),
688 >
689 > DefaultActivityRetryPolicy: dynamicconfig.DefaultActivityRetryPolicy.Get(dc),
690 > DefaultWorkflowRetryPolicy: dynamicconfig.DefaultWorkflowRetryPolicy.Get(dc),
691 > WorkflowTaskHeartbeatTimeout: dynamicconfig.WorkflowTaskHeartbeatTimeout.Get(dc),
692 > WorkflowTaskCriticalAttempts: dynamicconfig.WorkflowTaskCriticalAttempts.Get(dc),
693 > WorkflowTaskRetryMaxInterval: dynamicconfig.WorkflowTaskRetryMaxInterval.Get(dc),
694 > EnableWorkflowTaskStampIncrementOnFailure: dynamicconfig.EnableWorkflowTaskStampIncrementOnFailure.Get(dc),
695 > DiscardSpeculativeWorkflowTaskMaximumEventsCount: dynamicconfig.DiscardSpeculativeWorkflowTaskMaximumEventsCount.Get(dc),
696 > EnableDropRepeatedWorkflowTaskFailures: dynamicconfig.EnableDropRepeatedWorkflowTaskFailures.Get(dc),
697 > SendTransientOrSpeculativeWorkflowTaskEvents: dynamicconfig.SendTransientOrSpeculativeWorkflowTaskEvents.Get(dc),
698 >
699 > ReplicationTaskApplyTimeout: dynamicconfig.ReplicationTaskApplyTimeout.Get(dc),
700 > ReplicationTaskFetcherParallelism: dynamicconfig.ReplicationTaskFetcherParallelism.Get(dc),
701 > ReplicationTaskFetcherAggregationInterval: dynamicconfig.ReplicationTaskFetcherAggregationInterval.Get(dc),
702 > ReplicationTaskFetcherTimerJitterCoefficient: dynamicconfig.ReplicationTaskFetcherTimerJitterCoefficient.Get(dc),
703 > ReplicationTaskFetcherErrorRetryWait: dynamicconfig.ReplicationTaskFetcherErrorRetryWait.Get(dc),
704 >
705 > ReplicationTaskProcessorErrorRetryWait: dynamicconfig.ReplicationTaskProcessorErrorRetryWait.Get(dc),
706 > ReplicationTaskProcessorErrorRetryBackoffCoefficient: dynamicconfig.ReplicationTaskProcessorErrorRetryBackoffCoefficient.Get(dc),
707 > ReplicationTaskProcessorErrorRetryMaxInterval: dynamicconfig.ReplicationTaskProcessorErrorRetryMaxInterval.Get(dc),
708 > ReplicationTaskProcessorErrorRetryMaxAttempts: dynamicconfig.ReplicationTaskProcessorErrorRetryMaxAttempts.Get(dc),
709 > ReplicationTaskProcessorErrorRetryExpiration: dynamicconfig.ReplicationTaskProcessorErrorRetryExpiration.Get(dc),
710 > ReplicationTaskProcessorNoTaskRetryWait: dynamicconfig.ReplicationTaskProcessorNoTaskInitialWait.Get(dc),
711 > ReplicationTaskProcessorCleanupInterval: dynamicconfig.ReplicationTaskProcessorCleanupInterval.Get(dc),
712 > ReplicationTaskProcessorCleanupJitterCoefficient: dynamicconfig.ReplicationTaskProcessorCleanupJitterCoefficient.Get(dc),
713 > ReplicationMultipleBatches: dynamicconfig.ReplicationMultipleBatches.Get(dc),
714 >
715 > ReplicationStreamSenderErrorRetryWait: dynamicconfig.ReplicationStreamSenderErrorRetryWait.Get(dc),
716 > ReplicationStreamSenderErrorRetryBackoffCoefficient: dynamicconfig.ReplicationStreamSenderErrorRetryBackoffCoefficient.Get(dc),
717 > ReplicationStreamSenderErrorRetryMaxInterval: dynamicconfig.ReplicationStreamSenderErrorRetryMaxInterval.Get(dc),
718 > ReplicationStreamSenderErrorRetryMaxAttempts: dynamicconfig.ReplicationStreamSenderErrorRetryMaxAttempts.Get(dc),
719 > ReplicationStreamSenderErrorRetryExpiration: dynamicconfig.ReplicationStreamSenderErrorRetryExpiration.Get(dc),
720 >
721 > ReplicationExecutableTaskErrorRetryWait: dynamicconfig.ReplicationExecutableTaskErrorRetryWait.Get(dc),
722 > ReplicationExecutableTaskErrorRetryBackoffCoefficient: dynamicconfig.ReplicationExecutableTaskErrorRetryBackoffCoefficient.Get(dc),
723 > ReplicationExecutableTaskErrorRetryMaxInterval: dynamicconfig.ReplicationExecutableTaskErrorRetryMaxInterval.Get(dc),
724 > ReplicationExecutableTaskErrorRetryMaxAttempts: dynamicconfig.ReplicationExecutableTaskErrorRetryMaxAttempts.Get(dc),
725 > ReplicationExecutableTaskErrorRetryExpiration: dynamicconfig.ReplicationExecutableTaskErrorRetryExpiration.Get(dc),
726 >
727 > MaxBufferedQueryCount: dynamicconfig.MaxBufferedQueryCount.Get(dc),
728 > MutableStateChecksumGenProbability: dynamicconfig.MutableStateChecksumGenProbability.Get(dc),
729 > MutableStateChecksumVerifyProbability: dynamicconfig.MutableStateChecksumVerifyProbability.Get(dc),
730 > MutableStateChecksumInvalidateBefore: dynamicconfig.MutableStateChecksumInvalidateBefore.Get(dc),
731 >
732 > StandbyTaskReReplicationContextTimeout: dynamicconfig.StandbyTaskReReplicationContextTimeout.Get(dc),
733 >
734 > SkipReapplicationByNamespaceID: dynamicconfig.SkipReapplicationByNamespaceID.Get(dc),
735 >
736 > // ===== Visibility related =====
737 > VisibilityTaskBatchSize: dynamicconfig.VisibilityTaskBatchSize.Get(dc),
738 > VisibilityProcessorMaxPollRPS: dynamicconfig.VisibilityProcessorMaxPollRPS.Get(dc),
739 > VisibilityProcessorMaxPollHostRPS: dynamicconfig.VisibilityProcessorMaxPollHostRPS.Get(dc),
740 > VisibilityProcessorSchedulerWorkerCount: dynamicconfig.VisibilityProcessorSchedulerWorkerCount.Subscribe(dc),
741 > VisibilityProcessorSchedulerActiveRoundRobinWeights: dynamicconfig.VisibilityProcessorSchedulerActiveRoundRobinWeights.WithDefault(ConvertWeightsToDynamicConfigValue(DefaultActiveTaskPriorityWeight)).Get(dc),
742 > VisibilityProcessorSchedulerStandbyRoundRobinWeights: dynamicconfig.VisibilityProcessorSchedulerStandbyRoundRobinWeights.WithDefault(ConvertWeightsToDynamicConfigValue(DefaultStandbyTaskPriorityWeight)).Get(dc),
743 > VisibilityProcessorMaxPollInterval: dynamicconfig.VisibilityProcessorMaxPollInterval.Get(dc),
744 > VisibilityProcessorMaxPollIntervalJitterCoefficient: dynamicconfig.VisibilityProcessorMaxPollIntervalJitterCoefficient.Get(dc),
745 > VisibilityProcessorUpdateAckInterval: dynamicconfig.VisibilityProcessorUpdateAckInterval.Get(dc),
746 > VisibilityProcessorUpdateAckIntervalJitterCoefficient: dynamicconfig.VisibilityProcessorUpdateAckIntervalJitterCoefficient.Get(dc),
747 > VisibilityProcessorPollBackoffInterval: dynamicconfig.VisibilityProcessorPollBackoffInterval.Get(dc),
748 > VisibilityProcessorEnsureCloseBeforeDelete: dynamicconfig.VisibilityProcessorEnsureCloseBeforeDelete.Get(dc),
749 > VisibilityProcessorEnableCloseWorkflowCleanup: dynamicconfig.VisibilityProcessorEnableCloseWorkflowCleanup.Get(dc),
750 > VisibilityProcessorRelocateAttributesMinBlobSize: dynamicconfig.VisibilityProcessorRelocateAttributesMinBlobSize.Get(dc),
751 > VisibilityQueueMaxReaderCount: dynamicconfig.VisibilityQueueMaxReaderCount.Get(dc),
752 >
753 > DisableFetchRelocatableAttributesFromVisibility: dynamicconfig.DisableFetchRelocatableAttributesFromVisibility.Get(dc),
754 >
755 > SearchAttributesNumberOfKeysLimit: dynamicconfig.SearchAttributesNumberOfKeysLimit.Get(dc),
756 > SearchAttributesSizeOfValueLimit: dynamicconfig.SearchAttributesSizeOfValueLimit.Get(dc),
757 > SearchAttributesTotalSizeLimit: dynamicconfig.SearchAttributesTotalSizeLimit.Get(dc),
758 > IndexerConcurrency: dynamicconfig.WorkerIndexerConcurrency.Get(dc),
759 > ESProcessorNumOfWorkers: dynamicconfig.WorkerESProcessorNumOfWorkers.Get(dc),
760 > // Should not be greater than number of visibility task queue workers VisibilityProcessorSchedulerWorkerCount (default 512)
761 > // Otherwise, visibility queue processors won't be able to fill up bulk with documents (even under heavy load) and bulk will flush due to interval, not number of actions.
762 > ESProcessorBulkActions: dynamicconfig.WorkerESProcessorBulkActions.Get(dc),
763 > // 16MB - just a sanity check. With ES document size ~1Kb it should never be reached.
764 > ESProcessorBulkSize: dynamicconfig.WorkerESProcessorBulkSize.Get(dc),
765 > // Bulk processor will flush every this interval regardless of last flush due to bulk actions.
766 > ESProcessorFlushInterval: dynamicconfig.WorkerESProcessorFlushInterval.Get(dc),
767 > ESProcessorAckTimeout: dynamicconfig.WorkerESProcessorAckTimeout.Get(dc),
768 >
769 > EnableCrossNamespaceCommands: dynamicconfig.EnableCrossNamespaceCommands.Get(dc),
770 > EnableActivityEagerExecution: dynamicconfig.EnableActivityEagerExecution.Get(dc),
771 > EnableActivityRetryStampIncrement: dynamicconfig.EnableActivityRetryStampIncrement.Get(dc),
772 > EnableCancelActivityWorkerCommand: dynamicconfig.EnableCancelActivityWorkerCommand.Get(dc),
773 > EnableEagerWorkflowStart: dynamicconfig.EnableEagerWorkflowStart.Get(dc),
774 > NamespaceCacheRefreshInterval: dynamicconfig.NamespaceCacheRefreshInterval.Get(dc),
775 >
776 > // Archival related
777 > ArchivalTaskBatchSize: dynamicconfig.ArchivalTaskBatchSize.Get(dc),
778 > ArchivalProcessorMaxPollRPS: dynamicconfig.ArchivalProcessorMaxPollRPS.Get(dc),
779 > ArchivalProcessorMaxPollHostRPS: dynamicconfig.ArchivalProcessorMaxPollHostRPS.Get(dc),
780 > ArchivalProcessorSchedulerWorkerCount: dynamicconfig.ArchivalProcessorSchedulerWorkerCount.Subscribe(dc),
781 > ArchivalProcessorMaxPollInterval: dynamicconfig.ArchivalProcessorMaxPollInterval.Get(dc),
782 > ArchivalProcessorMaxPollIntervalJitterCoefficient: dynamicconfig.ArchivalProcessorMaxPollIntervalJitterCoefficient.Get(dc),
783 > ArchivalProcessorUpdateAckInterval: dynamicconfig.ArchivalProcessorUpdateAckInterval.Get(dc),
784 > ArchivalProcessorUpdateAckIntervalJitterCoefficient: dynamicconfig.ArchivalProcessorUpdateAckIntervalJitterCoefficient.Get(dc),
785 > ArchivalProcessorPollBackoffInterval: dynamicconfig.ArchivalProcessorPollBackoffInterval.Get(dc),
786 > ArchivalProcessorArchiveDelay: dynamicconfig.ArchivalProcessorArchiveDelay.Get(dc),
787 > ArchivalBackendMaxRPS: dynamicconfig.ArchivalBackendMaxRPS.Get(dc),
788 > ArchivalQueueMaxReaderCount: dynamicconfig.ArchivalQueueMaxReaderCount.Get(dc),
789 >
790 > // workflow update related
791 > WorkflowExecutionMaxInFlightUpdates: dynamicconfig.WorkflowExecutionMaxInFlightUpdates.Get(dc),
792 > WorkflowExecutionMaxInFlightUpdatePayloads: dynamicconfig.WorkflowExecutionMaxInFlightUpdatePayloads.Get(dc),
793 > WorkflowExecutionMaxTotalUpdates: dynamicconfig.WorkflowExecutionMaxTotalUpdates.Get(dc),
794 > WorkflowExecutionMaxTotalUpdatesSuggestContinueAsNewThreshold: dynamicconfig.WorkflowExecutionMaxTotalUpdatesSuggestContinueAsNewThreshold.Get(dc),
795 > EnableUpdateWithStartRetryOnClosedWorkflowAbort: dynamicconfig.EnableUpdateWithStartRetryOnClosedWorkflowAbort.Get(dc),
796 > EnableUpdateWithStartRetryableErrorOnClosedWorkflowAbort: dynamicconfig.EnableUpdateWithStartRetryableErrorOnClosedWorkflowAbort.Get(dc),
797 >
798 > SendRawHistoryBetweenInternalServices: dynamicconfig.SendRawHistoryBetweenInternalServices.Get(dc),
799 > SendRawHistoryBytesToMatchingService: dynamicconfig.SendRawHistoryBytesToMatchingService.Get(dc),
800 > SendRawWorkflowHistory: dynamicconfig.SendRawWorkflowHistory.Get(dc),
801 > WorkflowIdReuseMinimalInterval: dynamicconfig.WorkflowIdReuseMinimalInterval.Get(dc),
802 > EnableWorkflowIdReuseStartTimeValidation: dynamicconfig.EnableWorkflowIdReuseStartTimeValidation.Get(dc),
803 > BusinessIDReuseRate: dynamicconfig.BusinessIDReuseRate.Get(dc),
804 > BusinessIDReuseBurstRatio: dynamicconfig.BusinessIDReuseBurstRatio.Get(dc),
805 > BusinessIDReuseLimiterCacheSize: dynamicconfig.BusinessIDReuseLimiterCacheSize.Get(dc),
806 > BusinessIDReuseLimiterCacheTTL: dynamicconfig.BusinessIDReuseLimiterCacheTTL.Get(dc),
807 >
808 > HealthPersistenceLatencyFailure: dynamicconfig.HealthPersistenceLatencyFailure.Get(dc),
809 > HealthPersistenceLatencyPercentiles: dynamicconfig.PersistenceHealthSignalPercentileLatencySettings.Get(dc),
810 > HealthPersistenceErrorRatio: dynamicconfig.HealthPersistenceErrorRatio.Get(dc),
811 > HealthRPCLatencyFailure: dynamicconfig.HealthRPCLatencyFailure.Get(dc),
812 > HealthRPCLatencyPercentiles: dynamicconfig.HistoryHealthSignalPercentileLatencySettings.Get(dc),
813 > HealthRPCErrorRatio: dynamicconfig.HealthRPCErrorRatio.Get(dc),
814 > HealthHistoryInitializationTime: dynamicconfig.HealthHistoryInitializationTime.Get(dc),
815 >
816 > BreakdownMetricsByTaskQueue: dynamicconfig.MetricsBreakdownByTaskQueue.Get(dc),
817 >
818 > LogAllReqErrors: dynamicconfig.LogAllReqErrors.Get(dc),
819 >
820 > NumConsecutiveWorkflowTaskProblemsToTriggerSearchAttribute: dynamicconfig.NumConsecutiveWorkflowTaskProblemsToTriggerSearchAttribute.Get(dc),
821 >
822 > // Worker-Versioning related
823 > UseRevisionNumberForWorkerVersioning: dynamicconfig.UseRevisionNumberForWorkerVersioning.Get(dc),
824 > EnableSuggestCaNOnNewTargetVersion: dynamicconfig.EnableSuggestCaNOnNewTargetVersion.Get(dc),
825 > EnableSendTargetVersionChanged: dynamicconfig.EnableSendTargetVersionChanged.Get(dc),
826 > VersionMembershipCacheTTL: dynamicconfig.VersionMembershipCacheTTL.Get(dc),
827 > VersionMembershipCacheMaxSize: dynamicconfig.VersionMembershipCacheMaxSize.Get(dc),
828 > EnableVersionReactivationSignals: dynamicconfig.EnableVersionReactivationSignals.Get(dc),
829 > RoutingInfoCacheTTL: dynamicconfig.RoutingInfoCacheTTL.Get(dc),
830 > RoutingInfoCacheMaxSize: dynamicconfig.RoutingInfoCacheMaxSize.Get(dc),
831 >
832 > // Workflow task completion pagination
833 > EnableWorkflowTaskCompletionPagination: dynamicconfig.EnableWorkflowTaskCompletionPagination.Get(dc),
834 > WorkflowTaskCompletionBufferSizeLimit: dynamicconfig.WorkflowTaskCompletionBufferSizeLimit.Get(dc),
835 > }
836 >
837 > return cfg
838 > }
839
840 // GetShardID return the corresponding shard ID for a given namespaceID and workflowID pair
841 > func (config *Config) GetShardID(namespaceID namespace.ID, workflowID string) int32 { config.go
842 > return common.WorkflowIDToHistoryShard(namespaceID.String(), workflowID, config.NumberOfShards)
843 > }
go.temporal.io/server/api/matchingservice/v1/request_response.pb.go 392 covered LOC · 66 ranges

Open complete file

54 }
55
56 > func (x *PollWorkflowTaskQueueRequest) Reset() { request_response.pb.go
57 > *x = PollWorkflowTaskQueueRequest{}
58 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[0]
59 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
60 > ms.StoreMessageInfo(mi)
61 > }
62
63 func (x *PollWorkflowTaskQueueRequest) String() string {
67 func (*PollWorkflowTaskQueueRequest) ProtoMessage() {}
68
69 > func (x *PollWorkflowTaskQueueRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
70 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[0]
71 > if x != nil {
72 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
73 > if ms.LoadMessageInfo() == nil {
74 > ms.StoreMessageInfo(mi)
75 > }
76 > return ms
77 }
78 return mi.MessageOf(x)
84 }
85
86 > func (x *PollWorkflowTaskQueueRequest) GetNamespaceId() string { request_response.pb.go
87 > if x != nil {
88 > return x.NamespaceId
89 > }
90 return ""
91 }
92
93 > func (x *PollWorkflowTaskQueueRequest) GetPollerId() string { request_response.pb.go
94 > if x != nil {
95 > return x.PollerId
96 > }
97 return ""
98 }
99
100 > func (x *PollWorkflowTaskQueueRequest) GetPollRequest() *v1.PollWorkflowTaskQueueRequest { request_response.pb.go
101 > if x != nil {
102 > return x.PollRequest
103 > }
104 return nil
105 }
106
107 > func (x *PollWorkflowTaskQueueRequest) GetForwardedSource() string { request_response.pb.go
108 > if x != nil {
109 > return x.ForwardedSource
110 > }
111 return ""
112 }
151 }
152
153 > func (x *PollWorkflowTaskQueueResponse) Reset() { request_response.pb.go
154 > *x = PollWorkflowTaskQueueResponse{}
155 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[1]
156 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
157 > ms.StoreMessageInfo(mi)
158 > }
159
160 func (x *PollWorkflowTaskQueueResponse) String() string {
164 func (*PollWorkflowTaskQueueResponse) ProtoMessage() {}
165
166 > func (x *PollWorkflowTaskQueueResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
167 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[1]
168 > if x != nil {
169 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
170 > if ms.LoadMessageInfo() == nil {
171 > ms.StoreMessageInfo(mi)
172 > }
173 > return ms
174 }
175 return mi.MessageOf(x)
393 func (*PollWorkflowTaskQueueResponseWithRawHistory) ProtoMessage() {}
394
395 > func (x *PollWorkflowTaskQueueResponseWithRawHistory) ProtoReflect() protoreflect.Message { request_response.pb.go
396 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[2]
397 > if x != nil {
398 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
399 > if ms.LoadMessageInfo() == nil {
400 > ms.StoreMessageInfo(mi)
401 > }
402 > return ms
403 }
404 return mi.MessageOf(x)
569 }
570
571 > func (x *PollActivityTaskQueueRequest) Reset() { request_response.pb.go
572 > *x = PollActivityTaskQueueRequest{}
573 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[3]
574 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
575 > ms.StoreMessageInfo(mi)
576 > }
577
578 func (x *PollActivityTaskQueueRequest) String() string {
582 func (*PollActivityTaskQueueRequest) ProtoMessage() {}
583
584 > func (x *PollActivityTaskQueueRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
585 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[3]
586 > if x != nil {
587 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
588 > if ms.LoadMessageInfo() == nil {
589 > ms.StoreMessageInfo(mi)
590 > }
591 > return ms
592 }
593 return mi.MessageOf(x)
599 }
600
601 > func (x *PollActivityTaskQueueRequest) GetNamespaceId() string { request_response.pb.go
602 > if x != nil {
603 > return x.NamespaceId
604 > }
605 return ""
606 }
607
608 > func (x *PollActivityTaskQueueRequest) GetPollerId() string { request_response.pb.go
609 > if x != nil {
610 > return x.PollerId
611 > }
612 return ""
613 }
614
615 > func (x *PollActivityTaskQueueRequest) GetPollRequest() *v1.PollActivityTaskQueueRequest { request_response.pb.go
616 > if x != nil {
617 > return x.PollRequest
618 > }
619 return nil
620 }
621
622 > func (x *PollActivityTaskQueueRequest) GetForwardedSource() string { request_response.pb.go
623 > if x != nil {
624 > return x.ForwardedSource
625 > }
626 return ""
627 }
680 func (*PollActivityTaskQueueResponse) ProtoMessage() {}
681
682 > func (x *PollActivityTaskQueueResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
683 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[4]
684 > if x != nil {
685 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
686 > if ms.LoadMessageInfo() == nil {
687 > ms.StoreMessageInfo(mi)
688 > }
689 > return ms
690 }
691 return mi.MessageOf(x)
859 }
860
861 > func (x *AddWorkflowTaskRequest) Reset() { request_response.pb.go
862 > *x = AddWorkflowTaskRequest{}
863 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[5]
864 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
865 > ms.StoreMessageInfo(mi)
866 > }
867
868 func (x *AddWorkflowTaskRequest) String() string {
872 func (*AddWorkflowTaskRequest) ProtoMessage() {}
873
874 > func (x *AddWorkflowTaskRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
875 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[5]
876 > if x != nil {
877 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
878 > if ms.LoadMessageInfo() == nil {
879 > ms.StoreMessageInfo(mi)
880 > }
881 > return ms
882 }
883 return mi.MessageOf(x)
889 }
890
891 > func (x *AddWorkflowTaskRequest) GetNamespaceId() string { request_response.pb.go
892 > if x != nil {
893 > return x.NamespaceId
894 > }
895 return ""
896 }
903 }
904
905 > func (x *AddWorkflowTaskRequest) GetTaskQueue() *v14.TaskQueue { request_response.pb.go
906 > if x != nil {
907 > return x.TaskQueue
908 > }
909 return nil
910 }
911
912 > func (x *AddWorkflowTaskRequest) GetScheduledEventId() int64 { request_response.pb.go
913 > if x != nil {
914 > return x.ScheduledEventId
915 > }
916 return 0
917 }
918
919 > func (x *AddWorkflowTaskRequest) GetScheduleToStartTimeout() *durationpb.Duration { request_response.pb.go
920 > if x != nil {
921 > return x.ScheduleToStartTimeout
922 > }
923 return nil
924 }
925
926 > func (x *AddWorkflowTaskRequest) GetClock() *v17.VectorClock { request_response.pb.go
927 > if x != nil {
928 > return x.Clock
929 > }
930 return nil
931 }
938 }
939
940 > func (x *AddWorkflowTaskRequest) GetForwardInfo() *v18.TaskForwardInfo { request_response.pb.go
941 > if x != nil {
942 > return x.ForwardInfo
943 > }
944 return nil
945 }
968 }
969
970 > func (x *AddWorkflowTaskResponse) Reset() { request_response.pb.go
971 > *x = AddWorkflowTaskResponse{}
972 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[6]
973 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
974 > ms.StoreMessageInfo(mi)
975 > }
976
977 func (x *AddWorkflowTaskResponse) String() string {
981 func (*AddWorkflowTaskResponse) ProtoMessage() {}
982
983 > func (x *AddWorkflowTaskResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
984 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[6]
985 > if x != nil {
986 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
987 > if ms.LoadMessageInfo() == nil {
988 > ms.StoreMessageInfo(mi)
989 > }
990 > return ms
991 }
992 return mi.MessageOf(x)
1435 }
1436
1437 > func (x *CancelOutstandingPollRequest) Reset() { request_response.pb.go
1438 > *x = CancelOutstandingPollRequest{}
1439 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[13]
1440 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1441 > ms.StoreMessageInfo(mi)
1442 > }
1443
1444 func (x *CancelOutstandingPollRequest) String() string {
1448 func (*CancelOutstandingPollRequest) ProtoMessage() {}
1449
1450 > func (x *CancelOutstandingPollRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
1451 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[13]
1452 > if x != nil {
1453 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1454 > if ms.LoadMessageInfo() == nil {
1455 > ms.StoreMessageInfo(mi)
1456 > }
1457 > return ms
1458 }
1459 return mi.MessageOf(x)
1465 }
1466
1467 > func (x *CancelOutstandingPollRequest) GetNamespaceId() string { request_response.pb.go
1468 > if x != nil {
1469 > return x.NamespaceId
1470 > }
1471 return ""
1472 }
1473
1474 > func (x *CancelOutstandingPollRequest) GetTaskQueueType() v19.TaskQueueType { request_response.pb.go
1475 > if x != nil {
1476 > return x.TaskQueueType
1477 > }
1478 return v19.TaskQueueType(0)
1479 }
1480
1481 > func (x *CancelOutstandingPollRequest) GetTaskQueue() *v14.TaskQueue { request_response.pb.go
1482 > if x != nil {
1483 > return x.TaskQueue
1484 > }
1485 return nil
1486 }
1499 }
1500
1501 > func (x *CancelOutstandingPollResponse) Reset() { request_response.pb.go
1502 > *x = CancelOutstandingPollResponse{}
1503 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[14]
1504 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1505 > ms.StoreMessageInfo(mi)
1506 > }
1507
1508 func (x *CancelOutstandingPollResponse) String() string {
1512 func (*CancelOutstandingPollResponse) ProtoMessage() {}
1513
1514 > func (x *CancelOutstandingPollResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
1515 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[14]
1516 > if x != nil {
1517 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1518 > if ms.LoadMessageInfo() == nil {
1519 > ms.StoreMessageInfo(mi)
1520 > }
1521 > return ms
1522 }
1523 return mi.MessageOf(x)
2123 }
2124
2125 > func (x *DescribeTaskQueuePartitionResponse) GetVersionsInfoInternal() map[string]*v18.TaskQueueVersionInfoInternal { request_response.pb.go
2126 > if x != nil {
2127 > return x.VersionsInfoInternal
2128 > }
2129 return nil
2130 }
2789 }
2790
2791 > func (x *GetTaskQueueUserDataRequest) Reset() { request_response.pb.go
2792 > *x = GetTaskQueueUserDataRequest{}
2793 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[35]
2794 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2795 > ms.StoreMessageInfo(mi)
2796 > }
2797
2798 func (x *GetTaskQueueUserDataRequest) String() string {
2802 func (*GetTaskQueueUserDataRequest) ProtoMessage() {}
2803
2804 > func (x *GetTaskQueueUserDataRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
2805 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[35]
2806 > if x != nil {
2807 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2808 > if ms.LoadMessageInfo() == nil {
2809 > ms.StoreMessageInfo(mi)
2810 > }
2811 > return ms
2812 }
2813 return mi.MessageOf(x)
2819 }
2820
2821 > func (x *GetTaskQueueUserDataRequest) GetNamespaceId() string { request_response.pb.go
2822 > if x != nil {
2823 > return x.NamespaceId
2824 > }
2825 return ""
2826 }
2827
2828 > func (x *GetTaskQueueUserDataRequest) GetTaskQueue() string { request_response.pb.go
2829 > if x != nil {
2830 > return x.TaskQueue
2831 > }
2832 return ""
2833 }
2834
2835 > func (x *GetTaskQueueUserDataRequest) GetTaskQueueType() v19.TaskQueueType { request_response.pb.go
2836 > if x != nil {
2837 > return x.TaskQueueType
2838 > }
2839 return v19.TaskQueueType(0)
2840 }
2841
2842 > func (x *GetTaskQueueUserDataRequest) GetLastKnownUserDataVersion() int64 { request_response.pb.go
2843 > if x != nil {
2844 > return x.LastKnownUserDataVersion
2845 > }
2846 return 0
2847 }
2848
2849 > func (x *GetTaskQueueUserDataRequest) GetLastKnownEphemeralDataVersion() int64 { request_response.pb.go
2850 > if x != nil {
2851 > return x.LastKnownEphemeralDataVersion
2852 > }
2853 return 0
2854 }
2878 }
2879
2880 > func (x *GetTaskQueueUserDataResponse) Reset() { request_response.pb.go
2881 > *x = GetTaskQueueUserDataResponse{}
2882 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[36]
2883 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2884 > ms.StoreMessageInfo(mi)
2885 > }
2886
2887 func (x *GetTaskQueueUserDataResponse) String() string {
2891 func (*GetTaskQueueUserDataResponse) ProtoMessage() {}
2892
2893 > func (x *GetTaskQueueUserDataResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
2894 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[36]
2895 > if x != nil {
2896 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2897 > if ms.LoadMessageInfo() == nil {
2898 > ms.StoreMessageInfo(mi)
2899 > }
2900 > return ms
2901 }
2902 return mi.MessageOf(x)
2908 }
2909
2910 > func (x *GetTaskQueueUserDataResponse) GetUserData() *v111.VersionedTaskQueueUserData { request_response.pb.go
2911 > if x != nil {
2912 > return x.UserData
2913 > }
2914 return nil
2915 }
2916
2917 > func (x *GetTaskQueueUserDataResponse) GetEphemeralData() *v18.VersionedEphemeralData { request_response.pb.go
2918 > if x != nil {
2919 > return x.EphemeralData
2920 > }
2921 return nil
2922 }
3539 }
3540
3541 > func (x *ForceUnloadTaskQueuePartitionRequest) Reset() { request_response.pb.go
3542 > *x = ForceUnloadTaskQueuePartitionRequest{}
3543 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[47]
3544 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3545 > ms.StoreMessageInfo(mi)
3546 > }
3547
3548 func (x *ForceUnloadTaskQueuePartitionRequest) String() string {
3552 func (*ForceUnloadTaskQueuePartitionRequest) ProtoMessage() {}
3553
3554 > func (x *ForceUnloadTaskQueuePartitionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
3555 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[47]
3556 > if x != nil {
3557 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3558 > if ms.LoadMessageInfo() == nil {
3559 > ms.StoreMessageInfo(mi)
3560 > }
3561 > return ms
3562 }
3563 return mi.MessageOf(x)
3569 }
3570
3571 > func (x *ForceUnloadTaskQueuePartitionRequest) GetNamespaceId() string { request_response.pb.go
3572 > if x != nil {
3573 > return x.NamespaceId
3574 > }
3575 return ""
3576 }
3577
3578 > func (x *ForceUnloadTaskQueuePartitionRequest) GetTaskQueuePartition() *v18.TaskQueuePartition { request_response.pb.go
3579 > if x != nil {
3580 > return x.TaskQueuePartition
3581 > }
3582 return nil
3583 }
3590 }
3591
3592 > func (x *ForceUnloadTaskQueuePartitionResponse) Reset() { request_response.pb.go
3593 > *x = ForceUnloadTaskQueuePartitionResponse{}
3594 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[48]
3595 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3596 > ms.StoreMessageInfo(mi)
3597 > }
3598
3599 func (x *ForceUnloadTaskQueuePartitionResponse) String() string {
3603 func (*ForceUnloadTaskQueuePartitionResponse) ProtoMessage() {}
3604
3605 > func (x *ForceUnloadTaskQueuePartitionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
3606 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[48]
3607 > if x != nil {
3608 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3609 > if ms.LoadMessageInfo() == nil {
3610 > ms.StoreMessageInfo(mi)
3611 > }
3612 > return ms
3613 }
3614 return mi.MessageOf(x)
4790 }
4791
4792 > func (x *ListNexusEndpointsRequest) Reset() { request_response.pb.go
4793 > *x = ListNexusEndpointsRequest{}
4794 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[69]
4795 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4796 > ms.StoreMessageInfo(mi)
4797 > }
4798
4799 func (x *ListNexusEndpointsRequest) String() string {
4803 func (*ListNexusEndpointsRequest) ProtoMessage() {}
4804
4805 > func (x *ListNexusEndpointsRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
4806 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[69]
4807 > if x != nil {
4808 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4809 > if ms.LoadMessageInfo() == nil {
4810 > ms.StoreMessageInfo(mi)
4811 > }
4812 > return ms
4813 }
4814 return mi.MessageOf(x)
4858 }
4859
4860 > func (x *ListNexusEndpointsResponse) Reset() { request_response.pb.go
4861 > *x = ListNexusEndpointsResponse{}
4862 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[70]
4863 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4864 > ms.StoreMessageInfo(mi)
4865 > }
4866
4867 func (x *ListNexusEndpointsResponse) String() string {
4871 func (*ListNexusEndpointsResponse) ProtoMessage() {}
4872
4873 > func (x *ListNexusEndpointsResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
4874 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[70]
4875 > if x != nil {
4876 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4877 > if ms.LoadMessageInfo() == nil {
4878 > ms.StoreMessageInfo(mi)
4879 > }
4880 > return ms
4881 }
4882 return mi.MessageOf(x)
4917 }
4918
4919 > func (x *RecordWorkerHeartbeatRequest) Reset() { request_response.pb.go
4920 > *x = RecordWorkerHeartbeatRequest{}
4921 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[71]
4922 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4923 > ms.StoreMessageInfo(mi)
4924 > }
4925
4926 func (x *RecordWorkerHeartbeatRequest) String() string {
4930 func (*RecordWorkerHeartbeatRequest) ProtoMessage() {}
4931
4932 > func (x *RecordWorkerHeartbeatRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
4933 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[71]
4934 > if x != nil {
4935 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4936 > if ms.LoadMessageInfo() == nil {
4937 > ms.StoreMessageInfo(mi)
4938 > }
4939 > return ms
4940 }
4941 return mi.MessageOf(x)
4947 }
4948
4949 > func (x *RecordWorkerHeartbeatRequest) GetNamespaceId() string { request_response.pb.go
4950 > if x != nil {
4951 > return x.NamespaceId
4952 > }
4953 return ""
4954 }
4955
4956 > func (x *RecordWorkerHeartbeatRequest) GetHeartbeartRequest() *v1.RecordWorkerHeartbeatRequest { request_response.pb.go
4957 > if x != nil {
4958 > return x.HeartbeartRequest
4959 > }
4960 return nil
4961 }
4967 }
4968
4969 > func (x *RecordWorkerHeartbeatResponse) Reset() { request_response.pb.go
4970 > *x = RecordWorkerHeartbeatResponse{}
4971 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[72]
4972 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4973 > ms.StoreMessageInfo(mi)
4974 > }
4975
4976 func (x *RecordWorkerHeartbeatResponse) String() string {
4980 func (*RecordWorkerHeartbeatResponse) ProtoMessage() {}
4981
4982 > func (x *RecordWorkerHeartbeatResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
4983 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[72]
4984 > if x != nil {
4985 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4986 > if ms.LoadMessageInfo() == nil {
4987 > ms.StoreMessageInfo(mi)
4988 > }
4989 > return ms
4990 }
4991 return mi.MessageOf(x)
5698 func (*PollConditions) ProtoMessage() {}
5699
5700 > func (x *PollConditions) ProtoReflect() protoreflect.Message { request_response.pb.go
5701 > mi := &file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[85]
5702 > if x != nil {
5703 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
5704 if ms.LoadMessageInfo() == nil {
6833 }
6834
6835 > func init() { file_temporal_server_api_matchingservice_v1_request_response_proto_init() } request_response.pb.go
6836 > func file_temporal_server_api_matchingservice_v1_request_response_proto_init() {
6837 > if File_temporal_server_api_matchingservice_v1_request_response_proto != nil {
6838 > return
6839 > }
6840 > file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[27].OneofWrappers = []any{
6841 > (*UpdateWorkerBuildIdCompatibilityRequest_ApplyPublicRequest_)(nil),
6842 > (*UpdateWorkerBuildIdCompatibilityRequest_RemoveBuildIds_)(nil),
6843 > (*UpdateWorkerBuildIdCompatibilityRequest_PersistUnknownBuildId)(nil),
6844 > }
6845 > file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[29].OneofWrappers = []any{
6846 > (*GetWorkerVersioningRulesRequest_Request)(nil),
6847 > }
6848 > file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[31].OneofWrappers = []any{
6849 > (*UpdateWorkerVersioningRulesRequest_Request)(nil),
6850 > }
6851 > file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[37].OneofWrappers = []any{
6852 > (*SyncDeploymentUserDataRequest_UpdateVersionData)(nil),
6853 > (*SyncDeploymentUserDataRequest_ForgetVersion)(nil),
6854 > }
6855 > file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes[56].OneofWrappers = []any{
6856 > (*DispatchNexusTaskResponse_HandlerError)(nil),
6857 > (*DispatchNexusTaskResponse_Response)(nil),
6858 > (*DispatchNexusTaskResponse_RequestTimeout)(nil),
6859 > (*DispatchNexusTaskResponse_Failure)(nil),
6860 > }
6861 > type x struct{}
6862 > out := protoimpl.TypeBuilder{
6863 > File: protoimpl.DescBuilder{
6864 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
6865 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_matchingservice_v1_request_response_proto_rawDesc), len(file_temporal_server_api_matchingservice_v1_request_response_proto_rawDesc)),
6866 > NumEnums: 0,
6867 > NumMessages: 97,
6868 > NumExtensions: 0,
6869 > NumServices: 0,
6870 > },
6871 > GoTypes: file_temporal_server_api_matchingservice_v1_request_response_proto_goTypes,
6872 > DependencyIndexes: file_temporal_server_api_matchingservice_v1_request_response_proto_depIdxs,
6873 > MessageInfos: file_temporal_server_api_matchingservice_v1_request_response_proto_msgTypes,
6874 > }.Build()
6875 > File_temporal_server_api_matchingservice_v1_request_response_proto = out.File
6876 > file_temporal_server_api_matchingservice_v1_request_response_proto_goTypes = nil
6877 > file_temporal_server_api_matchingservice_v1_request_response_proto_depIdxs = nil
6878 }
go.temporal.io/server/common/dynamicconfig/setting_gen.go 377 covered LOC · 81 ranges

Open complete file

26 type GlobalBoolConstrainedDefaultSetting = GlobalTypedConstrainedDefaultSetting[bool]
27
28 > func NewGlobalBoolSetting(key string, def bool, description string) GlobalBoolSetting { setting_gen.go
29 > return NewGlobalTypedSettingWithConverter[bool](key, convertBool, def, description)
30 > }
31
32 func NewGlobalBoolSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[bool], description string) GlobalBoolConstrainedDefaultSetting {
43 type NamespaceBoolConstrainedDefaultSetting = NamespaceTypedConstrainedDefaultSetting[bool]
44
45 > func NewNamespaceBoolSetting(key string, def bool, description string) NamespaceBoolSetting { setting_gen.go
46 > return NewNamespaceTypedSettingWithConverter[bool](key, convertBool, def, description)
47 > }
48
49 func NewNamespaceBoolSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[bool], description string) NamespaceBoolConstrainedDefaultSetting {
53 type BoolPropertyFnWithNamespaceFilter = TypedPropertyFnWithNamespaceFilter[bool]
54
55 > func GetBoolPropertyFnFilteredByNamespace(value bool) BoolPropertyFnWithNamespaceFilter { setting_gen.go
56 > return GetTypedPropertyFnFilteredByNamespace(value)
57 > }
58
59 type NamespaceIDBoolSetting = NamespaceIDTypedSetting[bool]
60 type NamespaceIDBoolConstrainedDefaultSetting = NamespaceIDTypedConstrainedDefaultSetting[bool]
61
62 > func NewNamespaceIDBoolSetting(key string, def bool, description string) NamespaceIDBoolSetting { setting_gen.go
63 > return NewNamespaceIDTypedSettingWithConverter[bool](key, convertBool, def, description)
64 > }
65
66 func NewNamespaceIDBoolSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[bool], description string) NamespaceIDBoolConstrainedDefaultSetting {
77 type TaskQueueBoolConstrainedDefaultSetting = TaskQueueTypedConstrainedDefaultSetting[bool]
78
79 > func NewTaskQueueBoolSetting(key string, def bool, description string) TaskQueueBoolSetting { setting_gen.go
80 > return NewTaskQueueTypedSettingWithConverter[bool](key, convertBool, def, description)
81 > }
82
83 func NewTaskQueueBoolSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[bool], description string) TaskQueueBoolConstrainedDefaultSetting {
128 type DestinationBoolConstrainedDefaultSetting = DestinationTypedConstrainedDefaultSetting[bool]
129
130 > func NewDestinationBoolSetting(key string, def bool, description string) DestinationBoolSetting { setting_gen.go
131 > return NewDestinationTypedSettingWithConverter[bool](key, convertBool, def, description)
132 > }
133
134 func NewDestinationBoolSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[bool], description string) DestinationBoolConstrainedDefaultSetting {
162 type GlobalIntConstrainedDefaultSetting = GlobalTypedConstrainedDefaultSetting[int]
163
164 > func NewGlobalIntSetting(key string, def int, description string) GlobalIntSetting { setting_gen.go
165 > return NewGlobalTypedSettingWithConverter[int](key, convertInt, def, description)
166 > }
167
168 func NewGlobalIntSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[int], description string) GlobalIntConstrainedDefaultSetting {
179 type NamespaceIntConstrainedDefaultSetting = NamespaceTypedConstrainedDefaultSetting[int]
180
181 > func NewNamespaceIntSetting(key string, def int, description string) NamespaceIntSetting { setting_gen.go
182 > return NewNamespaceTypedSettingWithConverter[int](key, convertInt, def, description)
183 > }
184
185 func NewNamespaceIntSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[int], description string) NamespaceIntConstrainedDefaultSetting {
189 type IntPropertyFnWithNamespaceFilter = TypedPropertyFnWithNamespaceFilter[int]
190
191 > func GetIntPropertyFnFilteredByNamespace(value int) IntPropertyFnWithNamespaceFilter { setting_gen.go
192 > return GetTypedPropertyFnFilteredByNamespace(value)
193 > }
194
195 type NamespaceIDIntSetting = NamespaceIDTypedSetting[int]
213 type TaskQueueIntConstrainedDefaultSetting = TaskQueueTypedConstrainedDefaultSetting[int]
214
215 > func NewTaskQueueIntSetting(key string, def int, description string) TaskQueueIntSetting { setting_gen.go
216 > return NewTaskQueueTypedSettingWithConverter[int](key, convertInt, def, description)
217 > }
218
219 > func NewTaskQueueIntSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[int], description string) TaskQueueIntConstrainedDefaultSetting { setting_gen.go
220 > return NewTaskQueueTypedSettingWithConstrainedDefault[int](key, convertInt, cdef, description)
221 > }
222
223 type IntPropertyFnWithTaskQueueFilter = TypedPropertyFnWithTaskQueueFilter[int]
230 type ShardIDIntConstrainedDefaultSetting = ShardIDTypedConstrainedDefaultSetting[int]
231
232 > func NewShardIDIntSetting(key string, def int, description string) ShardIDIntSetting { setting_gen.go
233 > return NewShardIDTypedSettingWithConverter[int](key, convertInt, def, description)
234 > }
235
236 func NewShardIDIntSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[int], description string) ShardIDIntConstrainedDefaultSetting {
264 type DestinationIntConstrainedDefaultSetting = DestinationTypedConstrainedDefaultSetting[int]
265
266 > func NewDestinationIntSetting(key string, def int, description string) DestinationIntSetting { setting_gen.go
267 > return NewDestinationTypedSettingWithConverter[int](key, convertInt, def, description)
268 > }
269
270 func NewDestinationIntSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[int], description string) DestinationIntConstrainedDefaultSetting {
298 type GlobalFloatConstrainedDefaultSetting = GlobalTypedConstrainedDefaultSetting[float64]
299
300 > func NewGlobalFloatSetting(key string, def float64, description string) GlobalFloatSetting { setting_gen.go
301 > return NewGlobalTypedSettingWithConverter[float64](key, convertFloat, def, description)
302 > }
303
304 func NewGlobalFloatSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[float64], description string) GlobalFloatConstrainedDefaultSetting {
315 type NamespaceFloatConstrainedDefaultSetting = NamespaceTypedConstrainedDefaultSetting[float64]
316
317 > func NewNamespaceFloatSetting(key string, def float64, description string) NamespaceFloatSetting { setting_gen.go
318 > return NewNamespaceTypedSettingWithConverter[float64](key, convertFloat, def, description)
319 > }
320
321 func NewNamespaceFloatSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[float64], description string) NamespaceFloatConstrainedDefaultSetting {
349 type TaskQueueFloatConstrainedDefaultSetting = TaskQueueTypedConstrainedDefaultSetting[float64]
350
351 > func NewTaskQueueFloatSetting(key string, def float64, description string) TaskQueueFloatSetting { setting_gen.go
352 > return NewTaskQueueTypedSettingWithConverter[float64](key, convertFloat, def, description)
353 > }
354
355 func NewTaskQueueFloatSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[float64], description string) TaskQueueFloatConstrainedDefaultSetting {
366 type ShardIDFloatConstrainedDefaultSetting = ShardIDTypedConstrainedDefaultSetting[float64]
367
368 > func NewShardIDFloatSetting(key string, def float64, description string) ShardIDFloatSetting { setting_gen.go
369 > return NewShardIDTypedSettingWithConverter[float64](key, convertFloat, def, description)
370 > }
371
372 func NewShardIDFloatSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[float64], description string) ShardIDFloatConstrainedDefaultSetting {
400 type DestinationFloatConstrainedDefaultSetting = DestinationTypedConstrainedDefaultSetting[float64]
401
402 > func NewDestinationFloatSetting(key string, def float64, description string) DestinationFloatSetting { setting_gen.go
403 > return NewDestinationTypedSettingWithConverter[float64](key, convertFloat, def, description)
404 > }
405
406 func NewDestinationFloatSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[float64], description string) DestinationFloatConstrainedDefaultSetting {
434 type GlobalStringConstrainedDefaultSetting = GlobalTypedConstrainedDefaultSetting[string]
435
436 > func NewGlobalStringSetting(key string, def string, description string) GlobalStringSetting { setting_gen.go
437 > return NewGlobalTypedSettingWithConverter[string](key, convertString, def, description)
438 > }
439
440 func NewGlobalStringSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[string], description string) GlobalStringConstrainedDefaultSetting {
444 type StringPropertyFn = TypedPropertyFn[string]
445
446 > func GetStringPropertyFn(value string) StringPropertyFn { setting_gen.go
447 > return GetTypedPropertyFn(value)
448 > }
449
450 type NamespaceStringSetting = NamespaceTypedSetting[string]
570 type GlobalDurationConstrainedDefaultSetting = GlobalTypedConstrainedDefaultSetting[time.Duration]
571
572 > func NewGlobalDurationSetting(key string, def time.Duration, description string) GlobalDurationSetting { setting_gen.go
573 > return NewGlobalTypedSettingWithConverter[time.Duration](key, convertDuration, def, description)
574 > }
575
576 func NewGlobalDurationSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[time.Duration], description string) GlobalDurationConstrainedDefaultSetting {
587 type NamespaceDurationConstrainedDefaultSetting = NamespaceTypedConstrainedDefaultSetting[time.Duration]
588
589 > func NewNamespaceDurationSetting(key string, def time.Duration, description string) NamespaceDurationSetting { setting_gen.go
590 > return NewNamespaceTypedSettingWithConverter[time.Duration](key, convertDuration, def, description)
591 > }
592
593 func NewNamespaceDurationSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[time.Duration], description string) NamespaceDurationConstrainedDefaultSetting {
604 type NamespaceIDDurationConstrainedDefaultSetting = NamespaceIDTypedConstrainedDefaultSetting[time.Duration]
605
606 > func NewNamespaceIDDurationSetting(key string, def time.Duration, description string) NamespaceIDDurationSetting { setting_gen.go
607 > return NewNamespaceIDTypedSettingWithConverter[time.Duration](key, convertDuration, def, description)
608 > }
609
610 func NewNamespaceIDDurationSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[time.Duration], description string) NamespaceIDDurationConstrainedDefaultSetting {
621 type TaskQueueDurationConstrainedDefaultSetting = TaskQueueTypedConstrainedDefaultSetting[time.Duration]
622
623 > func NewTaskQueueDurationSetting(key string, def time.Duration, description string) TaskQueueDurationSetting { setting_gen.go
624 > return NewTaskQueueTypedSettingWithConverter[time.Duration](key, convertDuration, def, description)
625 > }
626
627 > func NewTaskQueueDurationSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[time.Duration], description string) TaskQueueDurationConstrainedDefaultSetting { setting_gen.go
628 > return NewTaskQueueTypedSettingWithConstrainedDefault[time.Duration](key, convertDuration, cdef, description)
629 > }
630
631 type DurationPropertyFnWithTaskQueueFilter = TypedPropertyFnWithTaskQueueFilter[time.Duration]
638 type ShardIDDurationConstrainedDefaultSetting = ShardIDTypedConstrainedDefaultSetting[time.Duration]
639
640 > func NewShardIDDurationSetting(key string, def time.Duration, description string) ShardIDDurationSetting { setting_gen.go
641 > return NewShardIDTypedSettingWithConverter[time.Duration](key, convertDuration, def, description)
642 > }
643
644 func NewShardIDDurationSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[time.Duration], description string) ShardIDDurationConstrainedDefaultSetting {
655 type TaskTypeDurationConstrainedDefaultSetting = TaskTypeTypedConstrainedDefaultSetting[time.Duration]
656
657 > func NewTaskTypeDurationSetting(key string, def time.Duration, description string) TaskTypeDurationSetting { setting_gen.go
658 > return NewTaskTypeTypedSettingWithConverter[time.Duration](key, convertDuration, def, description)
659 > }
660
661 func NewTaskTypeDurationSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[time.Duration], description string) TaskTypeDurationConstrainedDefaultSetting {
672 type DestinationDurationConstrainedDefaultSetting = DestinationTypedConstrainedDefaultSetting[time.Duration]
673
674 > func NewDestinationDurationSetting(key string, def time.Duration, description string) DestinationDurationSetting { setting_gen.go
675 > return NewDestinationTypedSettingWithConverter[time.Duration](key, convertDuration, def, description)
676 > }
677
678 func NewDestinationDurationSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[time.Duration], description string) DestinationDurationConstrainedDefaultSetting {
689 type ChasmTaskTypeDurationConstrainedDefaultSetting = ChasmTaskTypeTypedConstrainedDefaultSetting[time.Duration]
690
691 > func NewChasmTaskTypeDurationSetting(key string, def time.Duration, description string) ChasmTaskTypeDurationSetting { setting_gen.go
692 > return NewChasmTaskTypeTypedSettingWithConverter[time.Duration](key, convertDuration, def, description)
693 > }
694
695 func NewChasmTaskTypeDurationSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[time.Duration], description string) ChasmTaskTypeDurationConstrainedDefaultSetting {
723 type NamespaceMapConstrainedDefaultSetting = NamespaceTypedConstrainedDefaultSetting[map[string]any]
724
725 > func NewNamespaceMapSetting(key string, def map[string]any, description string) NamespaceMapSetting { setting_gen.go
726 > return NewNamespaceTypedSettingWithConverter[map[string]any](key, convertMap, def, description)
727 > }
728
729 func NewNamespaceMapSettingWithConstrainedDefault(key string, cdef []TypedConstrainedValue[map[string]any], description string) NamespaceMapConstrainedDefaultSetting {
733 type MapPropertyFnWithNamespaceFilter = TypedPropertyFnWithNamespaceFilter[map[string]any]
734
735 > func GetMapPropertyFnFilteredByNamespace(value map[string]any) MapPropertyFnWithNamespaceFilter { setting_gen.go
736 > return GetTypedPropertyFnFilteredByNamespace(value)
737 > }
738
739 type NamespaceIDMapSetting = NamespaceIDTypedSetting[map[string]any]
845 // values. The value from dynamic config will be _merged_ over a deep copy of 'def'. Be very careful
846 // when using non-empty maps or slices as defaults, the result may not be what you want.
847 > func NewGlobalTypedSetting[T any](key string, def T, description string) GlobalTypedSetting[T] { setting_gen.go
848 > // Warn on any shared structure used with ConvertStructure, even though we handle it by deep copying.
849 > warnDefaultSharedStructure(key, def)
850 > // If even deep copy won't even work, we should panic early. Do that by calling deep copy once here.
851 > _ = deepCopyForMapstructure(def)
852 >
853 > s := GlobalTypedSetting[T]{
854 > key: MakeKey(key),
855 > def: def,
856 > convert: ConvertStructure[T](def),
857 > description: description,
858 > }
859 > register(s)
860 > return s
861 > }
862
863 // NewGlobalTypedSettingWithConverter creates a setting with a custom converter function.
864 > func NewGlobalTypedSettingWithConverter[T any](key string, convert func(any) (T, error), def T, description string) GlobalTypedSetting[T] { setting_gen.go
865 > s := GlobalTypedSetting[T]{
866 > key: MakeKey(key),
867 > def: def,
868 > convert: convert,
869 > description: description,
870 > }
871 > register(s)
872 > return s
873 > }
874
875 // NewGlobalTypedSettingWithConstrainedDefault creates a setting with a compound default value.
885 }
886
887 > func (s GlobalTypedSetting[T]) Key() Key { return s.key } setting_gen.go
888 func (s GlobalTypedSetting[T]) Precedence() Precedence { return PrecedenceGlobal }
889 func (s GlobalTypedSetting[T]) Validate(v any) error {
899 }
900
901 > func (s GlobalTypedSetting[T]) WithDefault(v T) GlobalTypedSetting[T] { setting_gen.go
902 > newS := s
903 > newS.def = v
904 > return newS
905 > }
906
907 type TypedPropertyFn[T any] func() T
908
909 > func (s GlobalTypedSetting[T]) Get(c *Collection) TypedPropertyFn[T] { setting_gen.go
910 > return func() T {
911 > prec := []Constraints{{}} setting_gen.go
912 > return matchAndConvert(
913 > c,
914 > s.key,
915 > s.def,
916 > s.convert,
917 > prec,
918 > )
919 > }
920 }
921
935 type TypedSubscribable[T any] func(callback func(T)) (v T, cancel func())
936
937 > func (s GlobalTypedSetting[T]) Subscribe(c *Collection) TypedSubscribable[T] { setting_gen.go
938 > return func(callback func(T)) (T, func()) {
939 > prec := []Constraints{{}} setting_gen.go
940 > return subscribe(c, s.key, s.def, s.convert, prec, callback)
941 > }
942 }
943
969 }
970
971 > func GetTypedPropertyFn[T any](value T) TypedPropertyFn[T] { setting_gen.go
972 > return func() T {
973 return value
974 }
981 // values. The value from dynamic config will be _merged_ over a deep copy of 'def'. Be very careful
982 // when using non-empty maps or slices as defaults, the result may not be what you want.
983 > func NewNamespaceTypedSetting[T any](key string, def T, description string) NamespaceTypedSetting[T] { setting_gen.go
984 > // Warn on any shared structure used with ConvertStructure, even though we handle it by deep copying.
985 > warnDefaultSharedStructure(key, def)
986 > // If even deep copy won't even work, we should panic early. Do that by calling deep copy once here.
987 > _ = deepCopyForMapstructure(def)
988 >
989 > s := NamespaceTypedSetting[T]{
990 > key: MakeKey(key),
991 > def: def,
992 > convert: ConvertStructure[T](def),
993 > description: description,
994 > }
995 > register(s)
996 > return s
997 > }
998
999 // NewNamespaceTypedSettingWithConverter creates a setting with a custom converter function.
1000 > func NewNamespaceTypedSettingWithConverter[T any](key string, convert func(any) (T, error), def T, description string) NamespaceTypedSetting[T] { setting_gen.go
1001 > s := NamespaceTypedSetting[T]{
1002 > key: MakeKey(key),
1003 > def: def,
1004 > convert: convert,
1005 > description: description,
1006 > }
1007 > register(s)
1008 > return s
1009 > }
1010
1011 // NewNamespaceTypedSettingWithConstrainedDefault creates a setting with a compound default value.
1021 }
1022
1023 > func (s NamespaceTypedSetting[T]) Key() Key { return s.key } setting_gen.go
1024 func (s NamespaceTypedSetting[T]) Precedence() Precedence { return PrecedenceNamespace }
1025 func (s NamespaceTypedSetting[T]) Validate(v any) error {
1035 }
1036
1037 > func (s NamespaceTypedSetting[T]) WithDefault(v T) NamespaceTypedSetting[T] { setting_gen.go
1038 > newS := s
1039 > newS.def = v
1040 > return newS
1041 > }
1042
1043 type TypedPropertyFnWithNamespaceFilter[T any] func(namespace string) T
1044
1045 > func (s NamespaceTypedSetting[T]) Get(c *Collection) TypedPropertyFnWithNamespaceFilter[T] { setting_gen.go
1046 > return func(namespace string) T {
1047 > prec := []Constraints{{Namespace: namespace}, {}} setting_gen.go
1048 > return matchAndConvert(
1049 > c,
1050 > s.key,
1051 > s.def,
1052 > s.convert,
1053 > prec,
1054 > )
1055 > }
1056 }
1057
1071 type TypedSubscribableWithNamespaceFilter[T any] func(namespace string, callback func(T)) (v T, cancel func())
1072
1073 > func (s NamespaceTypedSetting[T]) Subscribe(c *Collection) TypedSubscribableWithNamespaceFilter[T] { setting_gen.go
1074 > return func(namespace string, callback func(T)) (T, func()) {
1075 > prec := []Constraints{{Namespace: namespace}, {}} setting_gen.go
1076 > return subscribe(c, s.key, s.def, s.convert, prec, callback)
1077 > }
1078 }
1079
1105 }
1106
1107 > func GetTypedPropertyFnFilteredByNamespace[T any](value T) TypedPropertyFnWithNamespaceFilter[T] { setting_gen.go
1108 > return func(namespace string) T {
1109 > return value setting_gen.go
1110 > }
1111 }
1112
1134
1135 // NewNamespaceIDTypedSettingWithConverter creates a setting with a custom converter function.
1136 > func NewNamespaceIDTypedSettingWithConverter[T any](key string, convert func(any) (T, error), def T, description string) NamespaceIDTypedSetting[T] { setting_gen.go
1137 > s := NamespaceIDTypedSetting[T]{
1138 > key: MakeKey(key),
1139 > def: def,
1140 > convert: convert,
1141 > description: description,
1142 > }
1143 > register(s)
1144 > return s
1145 > }
1146
1147 // NewNamespaceIDTypedSettingWithConstrainedDefault creates a setting with a compound default value.
1157 }
1158
1159 > func (s NamespaceIDTypedSetting[T]) Key() Key { return s.key } setting_gen.go
1160 func (s NamespaceIDTypedSetting[T]) Precedence() Precedence { return PrecedenceNamespaceID }
1161 func (s NamespaceIDTypedSetting[T]) Validate(v any) error {
1179 type TypedPropertyFnWithNamespaceIDFilter[T any] func(namespaceID namespace.ID) T
1180
1181 > func (s NamespaceIDTypedSetting[T]) Get(c *Collection) TypedPropertyFnWithNamespaceIDFilter[T] { setting_gen.go
1182 > return func(namespaceID namespace.ID) T {
1183 prec := []Constraints{{NamespaceID: namespaceID.String()}, {}}
1184 return matchAndConvert(
1253 // values. The value from dynamic config will be _merged_ over a deep copy of 'def'. Be very careful
1254 // when using non-empty maps or slices as defaults, the result may not be what you want.
1255 > func NewTaskQueueTypedSetting[T any](key string, def T, description string) TaskQueueTypedSetting[T] { setting_gen.go
1256 > // Warn on any shared structure used with ConvertStructure, even though we handle it by deep copying.
1257 > warnDefaultSharedStructure(key, def)
1258 > // If even deep copy won't even work, we should panic early. Do that by calling deep copy once here.
1259 > _ = deepCopyForMapstructure(def)
1260 >
1261 > s := TaskQueueTypedSetting[T]{
1262 > key: MakeKey(key),
1263 > def: def,
1264 > convert: ConvertStructure[T](def),
1265 > description: description,
1266 > }
1267 > register(s)
1268 > return s
1269 > }
1270
1271 // NewTaskQueueTypedSettingWithConverter creates a setting with a custom converter function.
1272 > func NewTaskQueueTypedSettingWithConverter[T any](key string, convert func(any) (T, error), def T, description string) TaskQueueTypedSetting[T] { setting_gen.go
1273 > s := TaskQueueTypedSetting[T]{
1274 > key: MakeKey(key),
1275 > def: def,
1276 > convert: convert,
1277 > description: description,
1278 > }
1279 > register(s)
1280 > return s
1281 > }
1282
1283 // NewTaskQueueTypedSettingWithConstrainedDefault creates a setting with a compound default value.
1284 > func NewTaskQueueTypedSettingWithConstrainedDefault[T any](key string, convert func(any) (T, error), cdef []TypedConstrainedValue[T], description string) TaskQueueTypedConstrainedDefaultSetting[T] { setting_gen.go
1285 > s := TaskQueueTypedConstrainedDefaultSetting[T]{
1286 > key: MakeKey(key),
1287 > cdef: cdef,
1288 > convert: convert,
1289 > description: description,
1290 > }
1291 > register(s)
1292 > return s
1293 > }
1294
1295 > func (s TaskQueueTypedSetting[T]) Key() Key { return s.key } setting_gen.go
1296 func (s TaskQueueTypedSetting[T]) Precedence() Precedence { return PrecedenceTaskQueue }
1297 func (s TaskQueueTypedSetting[T]) Validate(v any) error {
1300 }
1301
1302 > func (s TaskQueueTypedConstrainedDefaultSetting[T]) Key() Key { return s.key } setting_gen.go
1303 func (s TaskQueueTypedConstrainedDefaultSetting[T]) Precedence() Precedence { return PrecedenceTaskQueue }
1304 func (s TaskQueueTypedConstrainedDefaultSetting[T]) Validate(v any) error {
1315 type TypedPropertyFnWithTaskQueueFilter[T any] func(namespace string, taskQueue string, taskQueueType enumspb.TaskQueueType) T
1316
1317 > func (s TaskQueueTypedSetting[T]) Get(c *Collection) TypedPropertyFnWithTaskQueueFilter[T] { setting_gen.go
1318 > return func(namespace string, taskQueue string, taskQueueType enumspb.TaskQueueType) T {
1319 > prec := []Constraints{ setting_gen.go
1320 > {Namespace: namespace, TaskQueueName: taskQueue, TaskQueueType: taskQueueType},
1321 > {Namespace: namespace, TaskQueueName: taskQueue},
1322 > {TaskQueueName: taskQueue},
1323 > {Namespace: namespace},
1324 > {},
1325 > }
1326 > return matchAndConvert(
1327 > c,
1328 > s.key,
1329 > s.def,
1330 > s.convert,
1331 > prec,
1332 > )
1333 > }
1334 }
1335
1336 > func (s TaskQueueTypedConstrainedDefaultSetting[T]) Get(c *Collection) TypedPropertyFnWithTaskQueueFilter[T] { setting_gen.go
1337 > return func(namespace string, taskQueue string, taskQueueType enumspb.TaskQueueType) T {
1338 > prec := []Constraints{ setting_gen.go
1339 > {Namespace: namespace, TaskQueueName: taskQueue, TaskQueueType: taskQueueType},
1340 > {Namespace: namespace, TaskQueueName: taskQueue},
1341 > {TaskQueueName: taskQueue},
1342 > {Namespace: namespace},
1343 > {},
1344 > }
1345 > return matchAndConvertWithConstrainedDefault(
1346 > c,
1347 > s.key,
1348 > s.cdef,
1349 > s.convert,
1350 > prec,
1351 > )
1352 > }
1353 }
1354
1355 type TypedSubscribableWithTaskQueueFilter[T any] func(namespace string, taskQueue string, taskQueueType enumspb.TaskQueueType, callback func(T)) (v T, cancel func())
1356
1357 > func (s TaskQueueTypedSetting[T]) Subscribe(c *Collection) TypedSubscribableWithTaskQueueFilter[T] { setting_gen.go
1358 > return func(namespace string, taskQueue string, taskQueueType enumspb.TaskQueueType, callback func(T)) (T, func()) {
1359 > prec := []Constraints{ setting_gen.go
1360 > {Namespace: namespace, TaskQueueName: taskQueue, TaskQueueType: taskQueueType},
1361 > {Namespace: namespace, TaskQueueName: taskQueue},
1362 > {TaskQueueName: taskQueue},
1363 > {Namespace: namespace},
1364 > {},
1365 > }
1366 > return subscribe(c, s.key, s.def, s.convert, prec, callback)
1367 > }
1368 }
1369
1378 }
1379
1380 > func (s TaskQueueTypedConstrainedDefaultSetting[T]) Subscribe(c *Collection) TypedSubscribableWithTaskQueueFilter[T] { setting_gen.go
1381 > return func(namespace string, taskQueue string, taskQueueType enumspb.TaskQueueType, callback func(T)) (T, func()) {
1382 > prec := []Constraints{ setting_gen.go
1383 > {Namespace: namespace, TaskQueueName: taskQueue, TaskQueueType: taskQueueType},
1384 > {Namespace: namespace, TaskQueueName: taskQueue},
1385 > {TaskQueueName: taskQueue},
1386 > {Namespace: namespace},
1387 > {},
1388 > }
1389 > return subscribeWithConstrainedDefault(c, s.key, s.cdef, s.convert, prec, callback)
1390 > }
1391 }
1392
1430
1431 // NewShardIDTypedSettingWithConverter creates a setting with a custom converter function.
1432 > func NewShardIDTypedSettingWithConverter[T any](key string, convert func(any) (T, error), def T, description string) ShardIDTypedSetting[T] { setting_gen.go
1433 > s := ShardIDTypedSetting[T]{
1434 > key: MakeKey(key),
1435 > def: def,
1436 > convert: convert,
1437 > description: description,
1438 > }
1439 > register(s)
1440 > return s
1441 > }
1442
1443 // NewShardIDTypedSettingWithConstrainedDefault creates a setting with a compound default value.
1453 }
1454
1455 > func (s ShardIDTypedSetting[T]) Key() Key { return s.key } setting_gen.go
1456 func (s ShardIDTypedSetting[T]) Precedence() Precedence { return PrecedenceShardID }
1457 func (s ShardIDTypedSetting[T]) Validate(v any) error {
1475 type TypedPropertyFnWithShardIDFilter[T any] func(shardID int32) T
1476
1477 > func (s ShardIDTypedSetting[T]) Get(c *Collection) TypedPropertyFnWithShardIDFilter[T] { setting_gen.go
1478 > return func(shardID int32) T {
1479 > prec := []Constraints{{ShardID: shardID}, {}} setting_gen.go
1480 > return matchAndConvert(
1481 > c,
1482 > s.key,
1483 > s.def,
1484 > s.convert,
1485 > prec,
1486 > )
1487 > }
1488 }
1489
1566
1567 // NewTaskTypeTypedSettingWithConverter creates a setting with a custom converter function.
1568 > func NewTaskTypeTypedSettingWithConverter[T any](key string, convert func(any) (T, error), def T, description string) TaskTypeTypedSetting[T] { setting_gen.go
1569 > s := TaskTypeTypedSetting[T]{
1570 > key: MakeKey(key),
1571 > def: def,
1572 > convert: convert,
1573 > description: description,
1574 > }
1575 > register(s)
1576 > return s
1577 > }
1578
1579 // NewTaskTypeTypedSettingWithConstrainedDefault creates a setting with a compound default value.
1589 }
1590
1591 > func (s TaskTypeTypedSetting[T]) Key() Key { return s.key } setting_gen.go
1592 func (s TaskTypeTypedSetting[T]) Precedence() Precedence { return PrecedenceTaskType }
1593 func (s TaskTypeTypedSetting[T]) Validate(v any) error {
1611 type TypedPropertyFnWithTaskTypeFilter[T any] func(taskType enumsspb.TaskType) T
1612
1613 > func (s TaskTypeTypedSetting[T]) Get(c *Collection) TypedPropertyFnWithTaskTypeFilter[T] { setting_gen.go
1614 > return func(taskType enumsspb.TaskType) T {
1615 prec := []Constraints{{TaskType: taskType}, {}}
1616 return matchAndConvert(
1685 // values. The value from dynamic config will be _merged_ over a deep copy of 'def'. Be very careful
1686 // when using non-empty maps or slices as defaults, the result may not be what you want.
1687 > func NewDestinationTypedSetting[T any](key string, def T, description string) DestinationTypedSetting[T] { setting_gen.go
1688 > // Warn on any shared structure used with ConvertStructure, even though we handle it by deep copying.
1689 > warnDefaultSharedStructure(key, def)
1690 > // If even deep copy won't even work, we should panic early. Do that by calling deep copy once here.
1691 > _ = deepCopyForMapstructure(def)
1692 >
1693 > s := DestinationTypedSetting[T]{
1694 > key: MakeKey(key),
1695 > def: def,
1696 > convert: ConvertStructure[T](def),
1697 > description: description,
1698 > }
1699 > register(s)
1700 > return s
1701 > }
1702
1703 // NewDestinationTypedSettingWithConverter creates a setting with a custom converter function.
1704 > func NewDestinationTypedSettingWithConverter[T any](key string, convert func(any) (T, error), def T, description string) DestinationTypedSetting[T] { setting_gen.go
1705 > s := DestinationTypedSetting[T]{
1706 > key: MakeKey(key),
1707 > def: def,
1708 > convert: convert,
1709 > description: description,
1710 > }
1711 > register(s)
1712 > return s
1713 > }
1714
1715 // NewDestinationTypedSettingWithConstrainedDefault creates a setting with a compound default value.
1725 }
1726
1727 > func (s DestinationTypedSetting[T]) Key() Key { return s.key } setting_gen.go
1728 func (s DestinationTypedSetting[T]) Precedence() Precedence { return PrecedenceDestination }
1729 func (s DestinationTypedSetting[T]) Validate(v any) error {
1747 type TypedPropertyFnWithDestinationFilter[T any] func(namespace string, destination string) T
1748
1749 > func (s DestinationTypedSetting[T]) Get(c *Collection) TypedPropertyFnWithDestinationFilter[T] { setting_gen.go
1750 > return func(namespace string, destination string) T {
1751 prec := []Constraints{
1752 {Namespace: namespace, Destination: destination},
1785 type TypedSubscribableWithDestinationFilter[T any] func(namespace string, destination string, callback func(T)) (v T, cancel func())
1786
1787 > func (s DestinationTypedSetting[T]) Subscribe(c *Collection) TypedSubscribableWithDestinationFilter[T] { setting_gen.go
1788 > return func(namespace string, destination string, callback func(T)) (T, func()) {
1789 prec := []Constraints{
1790 {Namespace: namespace, Destination: destination},
1858
1859 // NewChasmTaskTypeTypedSettingWithConverter creates a setting with a custom converter function.
1860 > func NewChasmTaskTypeTypedSettingWithConverter[T any](key string, convert func(any) (T, error), def T, description string) ChasmTaskTypeTypedSetting[T] { setting_gen.go
1861 > s := ChasmTaskTypeTypedSetting[T]{
1862 > key: MakeKey(key),
1863 > def: def,
1864 > convert: convert,
1865 > description: description,
1866 > }
1867 > register(s)
1868 > return s
1869 > }
1870
1871 // NewChasmTaskTypeTypedSettingWithConstrainedDefault creates a setting with a compound default value.
1881 }
1882
1883 > func (s ChasmTaskTypeTypedSetting[T]) Key() Key { return s.key } setting_gen.go
1884 func (s ChasmTaskTypeTypedSetting[T]) Precedence() Precedence { return PrecedenceChasmTaskType }
1885 func (s ChasmTaskTypeTypedSetting[T]) Validate(v any) error {
1903 type TypedPropertyFnWithChasmTaskTypeFilter[T any] func(chasmTaskType string) T
1904
1905 > func (s ChasmTaskTypeTypedSetting[T]) Get(c *Collection) TypedPropertyFnWithChasmTaskTypeFilter[T] { setting_gen.go
1906 > return func(chasmTaskType string) T {
1907 prec := []Constraints{{ChasmTaskType: chasmTaskType}, {}}
1908 return matchAndConvert(
go.temporal.io/server/common/namespace/nsregistry/registry.go 349 covered LOC · 96 ranges

Open complete file

160 replicationResolverFactory namespace.ReplicationResolverFactory,
161 namespaceStateChangedFn namespace.NamespaceStateChangedFn,
162 > ) *registry { registry.go
163 > return &registry{
164 > persistence: aPersistence,
165 > globalNamespacesEnabled: enableGlobalNamespaces,
166 > currentClusterName: currentClusterName,
167 > clock: clock.NewRealTimeSource(),
168 > metricsHandler: metricsHandler.WithTags(metrics.OperationTag(metrics.NamespaceCacheScope)),
169 > logger: logger,
170 > nameToID: make(map[namespace.Name]namespace.ID),
171 > idToNamespace: make(map[namespace.ID]*namespace.Namespace),
172 > refreshInterval: refreshInterval,
173 > readthroughNotFoundCache: cache.New(readthroughCacheSize, &readthroughNotFoundCacheOpts),
174 >
175 > forceSearchAttributesCacheRefreshOnRead: forceSearchAttributesCacheRefreshOnRead,
176 > replicationResolverFactory: replicationResolverFactory,
177 > namespaceStateChangedFn: namespaceStateChangedFn,
178 > }
179 > }
180
181 // DefaultNamespaceStateChanged is the default implementation that checks whether a namespace
182 // state change is significant enough to trigger callbacks.
183 > func DefaultNamespaceStateChanged(currentClusterName string, oldNS *namespace.Namespace, newNS *namespace.Namespace) bool { registry.go
184 > return oldNS == nil ||
185 > oldNS.State() != newNS.State() ||
186 > oldNS.Name() != newNS.Name() ||
187 > oldNS.IsGlobalNamespace() != newNS.IsGlobalNamespace() ||
188 > //nolint:forbidigo // ns-wide state diff for cache invalidation.
189 > oldNS.ActiveInCluster(currentClusterName) != newNS.ActiveInCluster(currentClusterName) ||
190 > oldNS.ReplicationState("") != newNS.ReplicationState("")
191 > }
192
193 // GetRegistrySize observes the size of the by-name and by-ID maps.
215 // arrive. If not supported, falls back to periodic polling. Start blocks until the initial namespace refresh completes.
216 // The initial refresh must succeed or the function will fatal.
217 > func (r *registry) Start() { registry.go
218 > ctx := headers.SetCallerInfo(
219 > context.Background(),
220 > headers.SystemBackgroundHighCallerInfo,
221 > )
222 >
223 > watchStarted := false
224 > r.refresher, watchStarted = r.runWatchLoop(ctx)
225 > if watchStarted {
226 // Watch started successfully
227 return
228 }
229
230 > if err := r.refresher.Err(); !errors.Is(err, persistence.ErrWatchNotSupported) { registry.go
231 // Watch failed to start for a reason other than ErrWatchNotSupported
232 metrics.NamespaceRegistryWatchStartFailures.With(r.metricsHandler).Record(1)
233 r.logger.Warn("Unable to start namespace watch - falling back to polling", tag.Error(err))
234 > } else { registry.go
235 > r.logger.Info("Watch not supported by persistence, namespace registry will use polling")
236 > }
237
238 // Fall back to polling
239 > if err := r.refreshNamespaces(ctx); err != nil { registry.go
240 r.logger.Fatal("Unable to initialize namespace registry", tag.Error(err))
241 }
242 > r.refresher = goro.NewHandle(ctx).Go(r.runPollingLoop) registry.go
243 }
244
245 // Stop ends background refresh. Should only be invoked by fx lifecycle hook.
246 // Should not be called multiple times or concurrently with Start().
247 > func (r *registry) Stop() { registry.go
248 > // refresher may be nil if watch failed to start and we're shutting down.
249 > if r.refresher != nil {
250 > r.refresher.Cancel()
251 > <-r.refresher.Done()
252 > }
253 }
254
255 > func (r *registry) GetPingChecks() []pingable.Check { registry.go
256 > return []pingable.Check{
257 > {
258 > Name: "namespace registry lock",
259 > // we don't do any persistence ops, this shouldn't be blocked
260 > Timeout: 10 * time.Second,
261 > Ping: func() []pingable.Pingable {
262 > // just checking if we can acquire the lock
263 > r.nsMapsLock.Lock()
264 > // nolint:staticcheck
265 > r.nsMapsLock.Unlock()
266 > return nil
267 > },
268 MetricsName: metrics.DDNamespaceRegistryLockLatency.Name(),
269 },
271 }
272
273 > func (r *registry) GetAllNamespaces() []*namespace.Namespace { registry.go
274 > r.nsMapsLock.RLock()
275 > defer r.nsMapsLock.RUnlock()
276 > return expmaps.Values(r.idToNamespace)
277 > }
278
279 > func (r *registry) RegisterStateChangeCallback(key any, cb namespace.StateChangeCallbackFn) { registry.go
280 > // Store callback first to avoid race where watch events arrive between reading the namespace snapshot and storing the
281 > // callback. This ensures no events are missed, but introduces a different trade-off: The callback may receive duplicate
282 > // calls for the same namespace if a watch event arrives while we're iterating through the catch-up loop below. For
283 > // example:
284 > // 1. Callback is stored in stateChangeCallbacks
285 > // 2. Watch event arrives for namespace X, callback is invoked
286 > // 3. Catch-up loop reaches namespace X, callback is invoked again
287 > //
288 > // This is acceptable because callbacks are rarely added (so unlikely to trigger this) and callbacks should be idempotent anyway.
289 > callbackWithTiming := func(ns *namespace.Namespace, deletedFromDb bool) {
290 > // Track callback duration so we can identify slow callbacks
291 > start := time.Now()
292 > defer func() {
293 > duration := time.Since(start)
294 > if duration > slowCallbackDuration {
295 metrics.NamespaceRegistrySlowCallbacks.With(r.metricsHandler).Record(1)
296 r.logger.Warn(
302 }()
303
304 > cb(ns, deletedFromDb) registry.go
305 }
306
307 > r.stateChangeCallbacks.Store(key, namespace.StateChangeCallbackFn(callbackWithTiming)) registry.go
308 >
309 > r.nsMapsLock.RLock()
310 > allNamespaces := expmaps.Values(r.idToNamespace)
311 > r.nsMapsLock.RUnlock()
312 >
313 > // call once for each namespace already in the registry
314 > for _, ns := range allNamespaces {
315 > callbackWithTiming(ns, false) registry.go
316 > }
317 }
318
319 > func (r *registry) UnregisterStateChangeCallback(key any) { registry.go
320 > r.stateChangeCallbacks.Delete(key)
321 > }
322
323 // GetNamespace retrieves the information from the internal maps if it exists, otherwise retrieves the information from metadata
324 // store and update internal entries with an expiry before returning back
325 > func (r *registry) GetNamespace(name namespace.Name) (*namespace.Namespace, error) { registry.go
326 > if name == "" {
327 return nil, serviceerror.NewInvalidArgument("Namespace is empty.")
328 }
329 > return r.getOrReadthroughNamespace(name) registry.go
330 }
331
343 // GetNamespaceByID retrieves the information from the cache if it exists, otherwise retrieves the information from metadata
344 // store and writes it to the cache with an expiry before returning back
345 > func (r *registry) GetNamespaceByID(id namespace.ID) (*namespace.Namespace, error) { registry.go
346 > if id == "" {
347 return nil, serviceerror.NewInvalidArgument("NamespaceID is empty.")
348 }
349 > return r.getOrReadthroughNamespaceByID(id) registry.go
350 }
351
364 func (r *registry) GetNamespaceID(
365 name namespace.Name,
366 > ) (namespace.ID, error) { registry.go
367 >
368 > ns, err := r.GetNamespace(name)
369 > if err != nil {
370 return "", err
371 }
372 > return ns.ID(), nil registry.go
373 }
374
376 func (r *registry) GetNamespaceName(
377 id namespace.ID,
378 > ) (namespace.Name, error) { registry.go
379 >
380 > ns, err := r.getOrReadthroughNamespaceByID(id)
381 > if err != nil {
382 return "", err
383 }
384 > return ns.Name(), nil registry.go
385 }
386
387 // GetCustomSearchAttributesMapper is a temporary solution to be able to get search attributes
388 // with from persistence if forceSearchAttributesCacheRefreshOnRead is true.
389 > func (r *registry) GetCustomSearchAttributesMapper(name namespace.Name) (namespace.CustomSearchAttributesMapper, error) { registry.go
390 > var ns *namespace.Namespace
391 > var err error
392 > if r.forceSearchAttributesCacheRefreshOnRead() {
393 r.readthroughLock.Lock()
394 defer r.readthroughLock.Unlock()
395 ns, err = r.getNamespaceByNamePersistence(name)
396 > } else { registry.go
397 > ns, err = r.GetNamespace(name) registry.go
398 > }
399 > if err != nil { registry.go
400 return namespace.CustomSearchAttributesMapper{}, err
401 }
402 > return ns.CustomSearchAttributesMapper(), nil registry.go
403 }
404
433 // On initial startup (initialWatch=true), retries are limited to avoid blocking server startup indefinitely.
434 // On reconnection after a previous success (initialWatch=false), retries continue indefinitely.
435 > func watchStartRetryPolicy(initialWatch bool) backoff.RetryPolicy { registry.go
436 > policy := backoff.NewExponentialRetryPolicy(CacheRefreshFailureRetryInterval)
437 > if initialWatch {
438 > return policy.WithMaximumAttempts(startWatchMaxAttempts)
439 > }
440 return policy.WithExpirationInterval(backoff.NoInterval)
441 }
447 // Uses ShutdownOnce to track whether the watch has ever started successfully, which affects retry behavior: limited
448 // retries on initial startup, unlimited on reconnection.
449 > func (r *registry) runWatchLoop(ctx context.Context) (*goro.Handle, bool) { registry.go
450 > // watchStartedOnce tracks whether the watch has ever started successfully.
451 > // Used to determine retry policy and signal to the caller when watch is ready.
452 > watchStartedOnce := channel.NewShutdownOnce()
453 >
454 > handle := goro.NewHandle(ctx).Go(
455 > func(ctx context.Context) error {
456 > // Outer loop handles watch restarts after connection failures.
457 > for {
458 > select {
459 case <-ctx.Done():
460 return nil
461 > default: registry.go
462 }
463
464 > result, err := r.startWatch(ctx, !watchStartedOnce.IsShutdown()) registry.go
465 > if err != nil {
466 > return err registry.go
467 > }
468
469 watchStartedOnce.Shutdown()
476 // Wait for either the watch to start successfully, or the goroutine to exit (due to error
477 // or because watch is not supported). Return true only if watch started successfully.
478 > select { registry.go
479 case <-watchStartedOnce.Channel():
480 return handle, true
481 > case <-handle.Done(): registry.go
482 > return handle, false
483 }
484 }
486 // startWatch attempts to establish a namespace watch with retries.
487 // Returns the watch channel and context on success.
488 > func (r *registry) startWatch(ctx context.Context, initialWatch bool) (watchStartResult, error) { registry.go
489 > return backoff.ThrottleRetryContextWithReturn(
490 > ctx,
491 > func(ctx context.Context) (startResult watchStartResult, err error) {
492 > // Create fresh watch context for this attempt
493 > watchCtx, watchCancel := context.WithCancel(ctx)
494 > defer func() {
495 > if err != nil {
496 > // Cancel attempt's watch context to clean up any partial watch state registry.go
497 > watchCancel()
498 > }
499 }()
500
501 > startResult.watchCtx = watchCtx registry.go
502 > startResult.watchCancel = watchCancel
503 >
504 > if startResult.eventCh, err = r.persistence.WatchNamespaces(watchCtx); err != nil {
505 > if !errors.Is(err, persistence.ErrWatchNotSupported) { registry.go
506 r.logger.Error("Error starting namespace watch", tag.Error(err))
507 }
508 > return registry.go
509 }
510
521 },
522 watchStartRetryPolicy(initialWatch),
523 > func(err error) bool { registry.go
524 > return !errors.Is(err, persistence.ErrWatchNotSupported)
525 > },
526 )
527 }
529 // runPollingLoop periodically refreshes the namespace cache.
530 // Used as fallback when namespace watches are not supported.
531 > func (r *registry) runPollingLoop(ctx context.Context) error { registry.go
532 > timer := time.NewTimer(r.refreshInterval())
533 >
534 > for {
535 > select {
536 > case <-ctx.Done(): registry.go
537 > return nil
538
539 > case <-timer.C: registry.go
540 > err := r.refreshNamespaces(ctx)
541 > for err != nil {
542 r.logger.Error("Error refreshing namespace cache", tag.Error(err))
543 timerFailureRetry := time.NewTimer(CacheRefreshFailureRetryInterval)
550 }
551 }
552 > timer.Reset(r.refreshInterval()) registry.go
553 }
554 }
555
556 > func (r *registry) refreshNamespaces(ctx context.Context) (err error) { registry.go
557 > start := time.Now()
558 > defer func() {
559 > if err != nil {
560 metrics.NamespaceRegistryRefreshFailures.With(r.metricsHandler).Record(1)
561 }
562 > metrics.NamespaceRegistryRefreshLatency.With(r.metricsHandler).Record(time.Since(start)) registry.go
563 }()
564
565 > request := &persistence.ListNamespacesRequest{ registry.go
566 > PageSize: CacheRefreshPageSize,
567 > IncludeDeleted: true,
568 > }
569 > var namespacesDb namespace.Namespaces
570 > namespaceIDsDb := make(map[namespace.ID]struct{})
571 >
572 > for {
573 > // TODO: consider adding a timeout and/or retries here - long ListNamespaces
574 > // calls could delay watch reconnection or block shutdown
575 > response, err := r.persistence.ListNamespaces(ctx, request)
576 > if err != nil {
577 return err
578 }
579 > for _, namespaceDb := range response.Namespaces { registry.go
580 > ns, err := namespace.FromPersistentState( registry.go
581 > namespaceDb.Namespace,
582 > r.replicationResolverFactory(namespaceDb.Namespace),
583 > namespace.WithGlobalFlag(namespaceDb.IsGlobalNamespace),
584 > namespace.WithNotificationVersion(namespaceDb.NotificationVersion),
585 > )
586 > if err != nil {
587 return err
588 }
589 > namespacesDb = append(namespacesDb, ns) registry.go
590 > namespaceIDsDb[namespace.ID(namespaceDb.Namespace.Info.Id)] = struct{}{}
591 }
592 > if len(response.NextPageToken) == 0 { registry.go
593 > break
594 }
595 request.NextPageToken = response.NextPageToken
597
598 // Make a copy of the existing namespace maps (excluding deleted), so we can calculate diff and do atomic swap.
599 > newNameToID := make(map[namespace.Name]namespace.ID) registry.go
600 > newIDToNamespace := make(map[namespace.ID]*namespace.Namespace)
601 >
602 > var deletedEntries []*namespace.Namespace
603 > for _, ns := range r.GetAllNamespaces() {
604 > if _, namespaceExistsDb := namespaceIDsDb[ns.ID()]; !namespaceExistsDb { registry.go
605 deletedEntries = append(deletedEntries, ns)
606 continue
607 }
608 > newNameToID[ns.Name()] = ns.ID() registry.go
609 > newIDToNamespace[ns.ID()] = ns
610 }
611
612 > var stateChanged []*namespace.Namespace registry.go
613 > for _, aNamespace := range namespacesDb {
614 > oldNS := r.updateIDToNamespace(newIDToNamespace, aNamespace.ID(), aNamespace) registry.go
615 > // If namespace was renamed, remove entry for the old name
616 > if oldNS != nil && oldNS.Name() != aNamespace.Name() {
617 delete(newNameToID, oldNS.Name())
618 }
619 > newNameToID[aNamespace.Name()] = aNamespace.ID() registry.go
620 >
621 > if r.namespaceStateChanged(oldNS, aNamespace) {
622 > stateChanged = append(stateChanged, aNamespace)
623 > }
624 }
625
626 > r.nsMapsLock.Lock() registry.go
627 > totalNamespaceCount := len(newIDToNamespace) // record metric value within lock boundary
628 > r.idToNamespace = newIDToNamespace
629 > r.nameToID = newNameToID
630 > stateChanged = append(stateChanged, r.stateChangedDuringReadthrough...)
631 > r.stateChangedDuringReadthrough = nil
632 > r.nsMapsLock.Unlock()
633 >
634 > metrics.TotalNamespaces.With(r.metricsHandler).Record(float64(totalNamespaceCount))
635 >
636 > r.stateChangeCallbacks.Range(
637 > func(_, value any) bool {
638 > //revive:disable-next-line:unchecked-type-assertion registry.go
639 > cb := value.(namespace.StateChangeCallbackFn)
640 >
641 > for _, ns := range deletedEntries {
642 cb(ns, true)
643 }
644 > for _, ns := range stateChanged { registry.go
645 > cb(ns, false) registry.go
646 > }
647
648 > return true registry.go
649 })
650
651 > return nil registry.go
652 }
653
714 id namespace.ID,
715 newNS *namespace.Namespace,
716 > ) *namespace.Namespace { registry.go
717 > oldNS := iDToNamespace[id]
718 > iDToNamespace[id] = newNS
719 > return oldNS
720 > }
721
722 // getNamespace retrieves the information from the cache if it exists
723 > func (r *registry) getNamespace(name namespace.Name) (*namespace.Namespace, error) { registry.go
724 > r.nsMapsLock.RLock()
725 > defer r.nsMapsLock.RUnlock()
726 > if id, ok := r.nameToID[name]; ok {
727 > return r.getNamespaceByIDLocked(id) registry.go
728 > }
729 > return nil, serviceerror.NewNamespaceNotFound(name.String()) registry.go
730 }
731
732 // getNamespaceByID retrieves the information from the cache if it exists.
733 > func (r *registry) getNamespaceByID(id namespace.ID) (*namespace.Namespace, error) { registry.go
734 > r.nsMapsLock.RLock()
735 > defer r.nsMapsLock.RUnlock()
736 > return r.getNamespaceByIDLocked(id)
737 > }
738
739 > func (r *registry) getNamespaceByIDLocked(id namespace.ID) (*namespace.Namespace, error) { registry.go
740 > if ns, ok := r.idToNamespace[id]; ok {
741 > return ns, nil registry.go
742 > }
743 > return nil, serviceerror.NewNamespaceNotFound(id.String()) registry.go
744 }
745
746 // getOrReadthroughNamespace returns namespace information if it exists or reads through
747 // to the persistence layer and updates internal entry if it doesn't
748 > func (r *registry) getOrReadthroughNamespace(name namespace.Name) (*namespace.Namespace, error) { registry.go
749 > // check main caches
750 > ns, err := r.getNamespace(name)
751 > if err == nil {
752 > return ns, nil registry.go
753 > }
754
755 > r.readthroughLock.Lock() registry.go
756 > defer r.readthroughLock.Unlock()
757 >
758 > // check again in case there was an update while waiting
759 > ns, err = r.getNamespace(name)
760 > if err == nil {
761 return ns, nil
762 }
763
764 // check readthrough cache
765 > if r.readthroughNotFoundCache.Get(name.String()) != nil { registry.go
766 return nil, serviceerror.NewNamespaceNotFound(name.String())
767 }
768
769 // readthrough to persistence layer and update readthrough cache if not found
770 > ns, err = r.getNamespaceByNamePersistence(name) registry.go
771 > if err != nil {
772 return nil, err
773 }
774
775 // update main entry if found
776 > r.updateSingleNamespace(ns, false) registry.go
777 >
778 > return ns, nil
779 }
780
781 // getOrReadthroughNamespaceByID retrieves the namespace information if it exists or reads through
782 // to the persistence layer and updates internal entry if it doesn't
783 > func (r *registry) getOrReadthroughNamespaceByID(id namespace.ID) (*namespace.Namespace, error) { registry.go
784 > // check main caches
785 > ns, err := r.getNamespaceByID(id)
786 > if err == nil {
787 > return ns, nil registry.go
788 > }
789
790 > r.readthroughLock.Lock() registry.go
791 > defer r.readthroughLock.Unlock()
792 >
793 > // check again in case there was an update while waiting
794 > ns, err = r.getNamespaceByID(id)
795 > if err == nil {
796 return ns, nil
797 }
798
799 // check readthrough cache
800 > if r.readthroughNotFoundCache.Get(id.String()) != nil { registry.go
801 return nil, serviceerror.NewNamespaceNotFound(id.String())
802 }
803
804 // readthrough to persistence layer and update readthrough cache if not found
805 > ns, err = r.getNamespaceByIDPersistence(id) registry.go
806 > if err != nil {
807 return nil, err
808 }
809
810 // update main entry if found
811 > r.updateSingleNamespace(ns, false) registry.go
812 >
813 > return ns, nil
814 }
815
818 // When updatedViaWatch is true, we skip adding to stateChangedDuringReadthrough since watch events
819 // trigger callbacks immediately and don't need to be queued for later delivery.
820 > func (r *registry) updateSingleNamespace(ns *namespace.Namespace, updatedViaWatch bool) bool { registry.go
821 > r.nsMapsLock.Lock()
822 > defer r.nsMapsLock.Unlock()
823 >
824 > if curEntry, ok := r.idToNamespace[ns.ID()]; ok {
825 if curEntry.NotificationVersion() >= ns.NotificationVersion() {
826 // More up-to-date version already stored
829 }
830
831 > oldNS := r.updateIDToNamespace(r.idToNamespace, ns.ID(), ns) registry.go
832 > // If namespace was renamed, remove entry for the old name
833 > if oldNS != nil && oldNS.Name() != ns.Name() {
834 delete(r.nameToID, oldNS.Name())
835 }
836 > r.nameToID[ns.Name()] = ns.ID() registry.go
837 >
838 > changed := r.namespaceStateChanged(oldNS, ns)
839 > if changed && !updatedViaWatch {
840 > r.stateChangedDuringReadthrough = append(r.stateChangedDuringReadthrough, ns) registry.go
841 > }
842
843 > return changed registry.go
844 }
845
846 > func (r *registry) getNamespaceByNamePersistence(name namespace.Name) (*namespace.Namespace, error) { registry.go
847 > request := &persistence.GetNamespaceRequest{
848 > Name: name.String(),
849 > }
850 >
851 > ns, err := r.getNamespacePersistence(request)
852 > if err != nil {
853 if _, ok := err.(*serviceerror.NamespaceNotFound); ok {
854 r.readthroughNotFoundCache.Put(name.String(), struct{}{})
857 return nil, serviceerror.NewNamespaceNotFound(name.String())
858 }
859 > return ns, nil registry.go
860 }
861
862 > func (r *registry) getNamespaceByIDPersistence(id namespace.ID) (*namespace.Namespace, error) { registry.go
863 > request := &persistence.GetNamespaceRequest{
864 > ID: id.String(),
865 > }
866 >
867 > ns, err := r.getNamespacePersistence(request)
868 > if err != nil {
869 if _, ok := err.(*serviceerror.NamespaceNotFound); ok {
870 r.readthroughNotFoundCache.Put(id.String(), struct{}{})
873 return nil, serviceerror.NewNamespaceNotFound(id.String())
874 }
875 > return ns, nil registry.go
876 }
877
878 > func (r *registry) getNamespacePersistence(request *persistence.GetNamespaceRequest) (*namespace.Namespace, error) { registry.go
879 > ctx, cancel := context.WithTimeout(context.Background(), readthroughTimeout)
880 > defer cancel()
881 > ctx = headers.SetCallerType(ctx, headers.CallerTypeAPI)
882 > ctx = headers.SetCallerName(ctx, headers.CallerNameSystem)
883 >
884 > response, err := r.persistence.GetNamespace(ctx, request)
885 > if err != nil {
886 return nil, err
887 }
888 > return namespace.FromPersistentState( registry.go
889 > response.Namespace,
890 > r.replicationResolverFactory(response.Namespace),
891 > namespace.WithGlobalFlag(response.IsGlobalNamespace),
892 > namespace.WithNotificationVersion(response.NotificationVersion),
893 > )
894 }
895
896 > func (r *registry) namespaceStateChanged(oldNS *namespace.Namespace, newNS *namespace.Namespace) bool { registry.go
897 > return r.namespaceStateChangedFn(r.currentClusterName, oldNS, newNS)
898 > }
go.temporal.io/server/service/matching/db.go 323 covered LOC · 64 ranges

Open complete file

101 metricsHandler metrics.Handler,
102 isDraining bool,
103 > ) *taskQueueDB { db.go
104 > return &taskQueueDB{
105 > config: config,
106 > queue: queue,
107 > isDraining: isDraining,
108 > store: store,
109 > logger: logger,
110 > metricsHandler: metricsHandler,
111 > }
112 > }
113
114 // RangeID returns the current persistence view of rangeID
120
121 // GetMaxReadLevel returns the current maxReadLevel
122 > func (db *taskQueueDB) GetMaxReadLevel(subqueue subqueueIndex) int64 { db.go
123 > db.Lock()
124 > defer db.Unlock()
125 > return db.getMaxReadLevelLocked(subqueue)
126 > }
127
128 > func (db *taskQueueDB) getMaxReadLevelLocked(subqueue subqueueIndex) int64 { db.go
129 > return db.subqueues[subqueue].maxReadLevel
130 > }
131
132 // GetMaxReadLevel returns the current maxReadLevel
152 func (db *taskQueueDB) RenewLease(
153 ctx context.Context,
154 > ) (taskQueueState, error) { db.go
155 > db.Lock()
156 > defer db.Unlock()
157 >
158 > if db.rangeID == 0 {
159 > if err := db.takeOverTaskQueueLocked(ctx); err != nil {
160 return taskQueueState{}, err
161 }
165 }
166 }
167 > return taskQueueState{ db.go
168 > rangeID: db.rangeID,
169 > ackLevel: db.subqueues[subqueueZero].AckLevel, // TODO(pri): cleanup, only used by old backlog manager
170 > subqueues: db.cloneSubqueues(),
171 > otherHasTasks: !db.isDraining && db.otherHasTasks,
172 > scaleState: db.scaleState,
173 > }, nil
174 }
175
176 func (db *taskQueueDB) takeOverTaskQueueLocked(
177 ctx context.Context,
178 > ) error { db.go
179 > response, err := db.store.GetTaskQueue(ctx, &persistence.GetTaskQueueRequest{
180 > NamespaceID: db.queue.NamespaceId(),
181 > TaskQueue: db.queue.PersistenceName(),
182 > TaskType: db.queue.TaskType(),
183 > })
184 > switch err.(type) {
185 case nil:
186 db.rangeID = response.RangeID
208 return nil
209
210 > case *serviceerror.NotFound: db.go
211 > db.rangeID = initialRangeID
212 > db.subqueues = db.ensureDefaultSubqueuesLocked(nil, 0, 0)
213 >
214 > // If we are the draining one, then assume the other has tasks, so we can migrate
215 > // backwards safely. Also assume other has tasks if the config allows for migration
216 > // (and the partition supports fairness) since we may have just turned on fairness and need to migrate.
217 > canMigrate := (db.config.NewMatcher || db.config.EnableFairness) && db.queue.Partition().SupportsFairness()
218 > db.otherHasTasks = canMigrate || db.isDraining
219 >
220 > if _, err := db.store.CreateTaskQueue(ctx, &persistence.CreateTaskQueueRequest{
221 > RangeID: db.rangeID,
222 > TaskQueueInfo: db.cachedQueueInfo(),
223 > }); err != nil {
224 db.rangeID = 0
225 return err
226 }
227 > db.lastWrite = time.Now() db.go
228 > // In this case, ensureDefaultSubqueuesLocked already initialized subqueue 0 to have
229 > // ackLevel and maxReadLevel 0, so we don't need to initialize them.
230 > softassert.That(db.logger, db.subqueues[0].maxReadLevel == 0, "should have maxReadLevel 0 here")
231 > softassert.That(db.logger, db.subqueues[0].FairMaxReadLevel == nil, "should have maxReadLevel 0 here")
232 > softassert.That(db.logger, db.subqueues[0].AckLevel == 0, "should have ackLevel 0 here")
233 > softassert.That(db.logger, db.subqueues[0].FairAckLevel == nil, "should have ackLevel 0 here")
234 > return nil
235
236 default:
239 }
240
241 > func (db *taskQueueDB) updateTaskQueueLocked(ctx context.Context, incrementRangeId bool) error { db.go
242 > newRangeID := db.rangeID
243 > if incrementRangeId {
244 newRangeID++
245 }
246 > if _, err := db.store.UpdateTaskQueue(ctx, &persistence.UpdateTaskQueueRequest{ db.go
247 > RangeID: newRangeID,
248 > TaskQueueInfo: db.cachedQueueInfo(),
249 > PrevRangeID: db.rangeID,
250 > }); err != nil {
251 return err
252 }
253 > db.lastWrite = time.Now() db.go
254 > db.rangeID = newRangeID
255 > return nil
256 }
257
291 // reasonably fresh. When the interval is zero, metadata is updated on every append
292 // (previous behavior). Caller must hold db.Mutex.
293 > func (db *taskQueueDB) shouldUpdateMetadataOnAppendLocked() bool { db.go
294 > interval := db.config.MetadataUpdateOnAppendInterval()
295 > return interval <= 0 || time.Since(db.lastWrite) >= interval
296 > }
297
298 > func (db *taskQueueDB) SyncState(ctx context.Context) error { db.go
299 > db.Lock()
300 > defer db.Unlock()
301 > defer db.emitPhysicalBacklogGaugesLocked()
302 >
303 > // We only need to write if something changed, or if we're past half of the persistence TTL.
304 > // Cap at 24h so that the scavenger (which looks for metadata not updated in 48h) doesn't
305 > // mistake the queue for idle, even if a future partition kind has a longer TTL.
306 > ttl := min(24*time.Hour, cmp.Or(db.queue.Partition().PersistenceTTL(), 24*time.Hour))
307 > needWrite := db.lastChange.After(db.lastWrite) || time.Since(db.lastWrite) > ttl/2
308 > if !needWrite {
309 > // If we don't write, though, we wouldn't know if someone else has stolen ownership db.go
310 > // momentarily (this could happen due to eventual consistency of membership updates).
311 > // So instead, do a (cheaper) read to just check the range id.
312 > return db.verifyOwnershipLocked(ctx)
313 > }
314
315 > return db.updateTaskQueueLocked(ctx, false) db.go
316 }
317
318 > func (db *taskQueueDB) verifyOwnershipLocked(ctx context.Context) error { db.go
319 > response, err := db.store.GetTaskQueue(ctx, &persistence.GetTaskQueueRequest{
320 > NamespaceID: db.queue.NamespaceId(),
321 > TaskQueue: db.queue.PersistenceName(),
322 > TaskType: db.queue.TaskType(),
323 > })
324 > if err != nil {
325 return err
326 }
327 > if response.RangeID != db.rangeID { db.go
328 return &persistence.ConditionFailedError{
329 Msg: fmt.Sprintf("task queue ownership lost: stored rangeID %d, in-memory rangeID %d",
331 }
332 }
333 > return nil db.go
334 }
335
336 > func (db *taskQueueDB) updateAckLevelAndBacklogStats(subqueue subqueueIndex, newAckLevel int64, countDelta int64, oldestTime time.Time) { db.go
337 > db.Lock()
338 > defer db.Unlock()
339 >
340 > dbQueue := db.subqueues[subqueue]
341 > if newAckLevel < dbQueue.AckLevel {
342 softassert.Fail(db.logger,
343 "ack level in subqueue should not move backwards",
346 tag.Any("new-ack-level", newAckLevel))
347 }
348 > if dbQueue.AckLevel != newAckLevel { db.go
349 > db.lastChange = time.Now() db.go
350 > dbQueue.AckLevel = newAckLevel
351 > }
352
353 > if newAckLevel == db.getMaxReadLevelLocked(subqueue) { db.go
354 > // Reset approximateBacklogCount to fix the count divergence issue db.go
355 > if dbQueue.ApproximateBacklogCount != 0 || !dbQueue.oldestTime.Equal(oldestTime) {
356 > db.lastChange = time.Now() db.go
357 > dbQueue.ApproximateBacklogCount = 0
358 > dbQueue.oldestTime = oldestTime
359 > }
360 } else if countDelta != 0 {
361 db.lastChange = time.Now()
364 }
365
366 > func (db *taskQueueDB) updateFairAckLevel(subqueue subqueueIndex, newAckLevel fairLevel, countDelta, knownCount int64, oldestTime time.Time) { db.go
367 > db.Lock()
368 > defer db.Unlock()
369 >
370 > db.lastChange = time.Now()
371 > dbQueue := db.subqueues[subqueue]
372 > if prev := fairLevelFromProto(dbQueue.FairAckLevel); newAckLevel.less(prev) {
373 softassert.Fail(db.logger,
374 "ack level in subqueue should not move backwards",
377 tag.Any("new-ack-level", newAckLevel))
378 }
379 > dbQueue.FairAckLevel = newAckLevel.toProto() db.go
380 >
381 > if knownCount >= 0 {
382 // Reset approximateBacklogCount to fix the count divergence issue
383 dbQueue.ApproximateBacklogCount = knownCount
384 dbQueue.oldestTime = oldestTime
385 > } else if countDelta != 0 { db.go
386 db.updateBacklogStatsLocked(subqueue, countDelta, oldestTime)
387 }
390 // Use this to reset ApproximateBacklogCount when the backlog count is known, e.g. when you're
391 // read to the end of the backlog.
392 > func (db *taskQueueDB) setKnownFairBacklogCount(subqueue subqueueIndex, count int64) { db.go
393 > db.Lock()
394 > defer db.Unlock()
395 >
396 > if db.subqueues[subqueue].ApproximateBacklogCount != count {
397 db.lastChange = time.Now()
398 db.subqueues[subqueue].ApproximateBacklogCount = count
456 // getApproximateBacklogCountsBySubqueue return the approximate backlog count for each subqueue.
457 // The index corresponds to the subqueue id.
458 > func (db *taskQueueDB) getApproximateBacklogCountsBySubqueue() []int64 { db.go
459 > db.Lock()
460 > defer db.Unlock()
461 >
462 > result := make([]int64, len(db.subqueues))
463 > for id, s := range db.subqueues {
464 > result[id] = s.ApproximateBacklogCount
465 > }
466 > return result
467 }
468
516 ctx context.Context,
517 reqs []*writeTaskRequest,
518 > ) (createTasksResponse, error) { db.go
519 > if db.isDraining {
520 return createTasksResponse{}, softassert.UnexpectedInternalErr(db.logger, "CreateTasks can't be used in draining mode", nil)
521 }
522
523 > db.Lock() db.go
524 > defer db.Unlock()
525 >
526 > if len(reqs) == 0 {
527 return createTasksResponse{}, nil
528 }
529
530 > updates := make(map[subqueueIndex]subqueueCreateTasksResponse) db.go
531 > allTasks := make([]*persistencespb.AllocatedTaskInfo, len(reqs))
532 > allSubqueues := make([]int, len(reqs))
533 > for i, req := range reqs {
534 > task := &persistencespb.AllocatedTaskInfo{
535 > TaskId: req.id,
536 > Data: req.taskInfo,
537 > }
538 > allTasks[i] = task
539 > allSubqueues[i] = int(req.subqueue)
540 >
541 > u := updates[req.subqueue]
542 > updates[req.subqueue] = subqueueCreateTasksResponse{
543 > tasks: append(u.tasks, task),
544 > maxReadLevelBefore: db.getMaxReadLevelLocked(req.subqueue),
545 > maxReadLevelAfter: task.TaskId, // task ids are in order so this is the max
546 > }
547 > }
548
549 > for sq, update := range updates { db.go
550 > db.subqueues[sq].ApproximateBacklogCount += int64(len(update.tasks))
551 > }
552
553 // Decide whether to include metadata in the write. We always need the LWT for the
554 // range ID check, but updating the full metadata blob on every append has extra cost.
555 // We piggyback the metadata update if enough time has passed since the last write.
556 > updateMetadata := db.shouldUpdateMetadataOnAppendLocked() db.go
557 >
558 > resp, err := db.store.CreateTasks(
559 > ctx,
560 > &persistence.CreateTasksRequest{
561 > TaskQueueInfo: &persistence.PersistedTaskQueueInfo{
562 > Data: db.cachedQueueInfo(),
563 > RangeID: db.rangeID,
564 > },
565 > Tasks: allTasks,
566 > Subqueues: allSubqueues,
567 > UpdateMetadata: updateMetadata,
568 > })
569 >
570 > // Update the maxReadLevel after the writes are completed, but before we send the response,
571 > // so that taskReader is guaranteed to see the new read level when SpoolTask wakes it up.
572 > // Do this even if the write fails, we won't reuse the task ids.
573 > for sq, update := range updates {
574 > db.subqueues[sq].maxReadLevel = update.maxReadLevelAfter
575 > }
576
577 > if err == nil { db.go
578 > // Only update lastWrite for persistence implementations that update metadata on CreateTasks, db.go
579 > // otherwise we have a change to ApproximateBacklogCount we need to write.
580 > if resp.UpdatedMetadata {
581 db.lastWrite = time.Now()
582 > } else { db.go
583 > db.lastChange = time.Now() db.go
584 > }
585 } else if writeDefinitelyFailed(err) {
586 // tasks definitely were not created, restore the counter. For other errors tasks may or may not be created.
590 }
591 }
592 > return createTasksResponse{bySubqueue: updates}, err db.go
593 }
594
717 inclusiveMinLevel fairLevel,
718 batchSize int,
719 > ) (*persistence.GetTasksResponse, error) { db.go
720 > return db.store.GetTasks(ctx, &persistence.GetTasksRequest{
721 > NamespaceID: db.queue.NamespaceId(),
722 > TaskQueue: db.queue.PersistenceName(),
723 > TaskType: db.queue.TaskType(),
724 > InclusiveMinPass: inclusiveMinLevel.pass,
725 > InclusiveMinTaskID: inclusiveMinLevel.id,
726 > ExclusiveMaxTaskID: math.MaxInt64,
727 > Subqueue: int(subqueue),
728 > PageSize: batchSize,
729 > UseLimit: true,
730 > })
731 > }
732
733 // CompleteTasksLessThan deletes of tasks less than the given taskID. Limit is
814 }
815
816 > func (db *taskQueueDB) expiryTime() *timestamppb.Timestamp { db.go
817 > if ttl := db.queue.Partition().PersistenceTTL(); ttl > 0 {
818 > return timestamppb.New(time.Now().Add(ttl)) db.go
819 > }
820 > return nil db.go
821 }
822
823 > func (db *taskQueueDB) cachedQueueInfo() *persistencespb.TaskQueueInfo { db.go
824 > infos := make([]*persistencespb.SubqueueInfo, len(db.subqueues))
825 > for i := range db.subqueues {
826 > infos[i] = &db.subqueues[i].SubqueueInfo
827 > }
828 > return &persistencespb.TaskQueueInfo{
829 > NamespaceId: db.queue.NamespaceId(),
830 > Name: db.queue.PersistenceName(),
831 > TaskType: db.queue.TaskType(),
832 > Kind: db.queue.Partition().Kind(),
833 > AckLevel: db.subqueues[subqueueZero].AckLevel, // backwards compatibility
834 > ExpiryTime: db.expiryTime(),
835 > LastUpdateTime: timestamp.TimeNowPtrUtc(),
836 > ApproximateBacklogCount: db.subqueues[subqueueZero].ApproximateBacklogCount, // backwards compatibility
837 > Subqueues: infos,
838 > OtherHasTasks: db.otherHasTasks,
839 > PartitionScaleState: db.scaleState,
840 > }
841 }
842
853 // to emitting the original approximate_backlog_count and approximate_backlog_age_seconds for
854 // all queues (including versioned queues when BreakdownMetricsByBuildID is enabled).
855 > func (db *taskQueueDB) emitPhysicalBacklogGaugesLocked() { db.go
856 > if !db.config.BreakdownMetricsByTaskQueue() || !db.config.BreakdownMetricsByPartition() {
857 return
858 }
859
860 > attributionEnabled := db.config.BacklogMetricsEmitInterval() > 0 db.go
861 >
862 > if attributionEnabled {
863 > if db.queue.IsVersioned() {
864 return
865 }
870 }
871
872 > var totalLag int64 db.go
873 > var oldestTime time.Time
874 > counts := make(map[int32]int64)
875 > for _, s := range db.subqueues {
876 > counts[s.Key.Priority] += s.ApproximateBacklogCount
877 > oldestTime = minNonZeroTime(oldestTime, s.oldestTime)
878 > // note: this metric is only an estimation for the lag.
879 > // taskID in DB may not be continuous, especially when task list ownership changes.
880 > if s.FairMaxReadLevel != nil && s.FairAckLevel != nil {
881 // TODO(fairness): this is not a good estimate of anything, we should probably just
882 // get rid of this metric.
883 totalLag += s.FairMaxReadLevel.TaskId - s.FairAckLevel.TaskId
884 > } else { db.go
885 > totalLag += s.maxReadLevel - s.AckLevel db.go
886 > }
887 }
888
889 > backlogCountGauge := metrics.ApproximateBacklogCount db.go
890 > backlogAgeGauge := metrics.ApproximateBacklogAgeSeconds
891 > if attributionEnabled {
892 > backlogCountGauge = metrics.PhysicalApproximateBacklogCount
893 > backlogAgeGauge = metrics.PhysicalApproximateBacklogAgeSeconds
894 > }
895
896 > for priority, count := range counts { db.go
897 > backlogCountGauge.With(db.metricsHandler).Record(float64(count), metrics.MatchingTaskPriorityTag(priority))
898 > }
899 > if oldestTime.IsZero() {
900 > backlogAgeGauge.With(db.metricsHandler).Record(0) db.go
901 > } else { db.go
902 backlogAgeGauge.With(db.metricsHandler).Record(time.Since(oldestTime).Seconds())
903 }
904 > metrics.TaskLagPerTaskQueueGauge.With(db.metricsHandler).Record(float64(totalLag)) db.go
905 }
906
909 initAckLevel int64,
910 initApproxCount int64,
911 > ) []*dbSubqueue { db.go
912 > // convert+copy protos to []*dbSubqueue
913 > subqueues := make([]*dbSubqueue, len(infos))
914 > for i, info := range infos {
915 subqueues[i] = &dbSubqueue{}
916 proto.Merge(&subqueues[i].SubqueueInfo, info)
918
919 // check for default priority and add if not present (this may be initializing subqueue 0)
920 > defKey := &persistencespb.SubqueueKey{ db.go
921 > Priority: int32(db.config.DefaultPriorityKey),
922 > }
923 > hasDefault := slices.ContainsFunc(subqueues, func(s *dbSubqueue) bool {
924 return proto.Equal(s.Key, defKey)
925 })
926 > if !hasDefault { db.go
927 > subqueues = append(subqueues, db.newSubqueueLocked(defKey))
928 > // If we are transitioning from no-subqueues to subqueues, initialize subqueue 0 with
929 > // the ack level and approx count from TaskQueueInfo.
930 > if len(subqueues) == 1 {
931 > subqueues[subqueueZero].AckLevel = initAckLevel
932 > subqueues[subqueueZero].ApproximateBacklogCount = initApproxCount
933 > }
934 }
935 > return subqueues db.go
936 }
937
938 > func (db *taskQueueDB) newSubqueueLocked(key *persistencespb.SubqueueKey) *dbSubqueue { db.go
939 > // For fifo queues: start ack level + max read level just before the current block.
940 > // For fair queues: ack level and max read level don't matter here.
941 > initAckLevel := rangeIDToTaskIDBlock(db.rangeID, db.config.RangeSize).start - 1
942 > softassert.That(db.logger, initAckLevel >= 0, "initAckLevel should not be negative")
943 >
944 > s := &dbSubqueue{maxReadLevel: initAckLevel}
945 > s.Key = key
946 > s.AckLevel = initAckLevel
947 > return s
948 > }
949
950 // clone db.subqueues so we can return it outside our lock
951 > func (db *taskQueueDB) cloneSubqueues() []persistencespb.SubqueueInfo { db.go
952 > infos := make([]persistencespb.SubqueueInfo, len(db.subqueues))
953 > for i := range db.subqueues {
954 > proto.Merge(&infos[i], &db.subqueues[i].SubqueueInfo)
955 > }
956 > return infos
957 }
958
959 > func (db *taskQueueDB) emitZeroPhysicalBacklogGauges() { db.go
960 > if !db.config.BreakdownMetricsByTaskQueue() || !db.config.BreakdownMetricsByPartition() {
961 return
962 }
963
964 > attributionEnabled := db.config.BacklogMetricsEmitInterval() > 0 db.go
965 >
966 > if attributionEnabled {
967 > if db.queue.IsVersioned() {
968 return
969 }
974 }
975
976 > priorities := make(map[int32]struct{}) db.go
977 > db.Lock()
978 > for _, s := range db.subqueues {
979 > priorities[s.Key.Priority] = struct{}{}
980 > }
981 > db.Unlock()
982 >
983 > backlogCountGauge := metrics.ApproximateBacklogCount
984 > backlogAgeGauge := metrics.ApproximateBacklogAgeSeconds
985 > if attributionEnabled {
986 > backlogCountGauge = metrics.PhysicalApproximateBacklogCount
987 > backlogAgeGauge = metrics.PhysicalApproximateBacklogAgeSeconds
988 > }
989
990 > for k := range priorities { db.go
991 > backlogCountGauge.With(db.metricsHandler).Record(0, metrics.MatchingTaskPriorityTag(k))
992 > }
993 > backlogAgeGauge.With(db.metricsHandler).Record(0)
994 > metrics.TaskLagPerTaskQueueGauge.With(db.metricsHandler).Record(0)
995 }
go.temporal.io/server/service/history/workflow/context.go 321 covered LOC · 90 ranges

Open complete file

88 throttledLogger log.ThrottledLogger,
89 metricsHandler metrics.Handler,
90 > ) *ContextImpl { context.go
91 > tags := func() []tag.Tag {
92 > return []tag.Tag{ context.go
93 > tag.WorkflowNamespaceID(workflowKey.NamespaceID),
94 > tag.WorkflowID(workflowKey.WorkflowID),
95 > tag.WorkflowRunID(workflowKey.RunID),
96 > }
97 > }
98 > contextImpl := &ContextImpl{ context.go
99 > workflowKey: workflowKey,
100 > archetypeID: archetypeID,
101 > logger: log.NewLazyLogger(logger, tags),
102 > throttledLogger: log.NewLazyLogger(throttledLogger, tags),
103 > metricsHandler: metricsHandler.WithTags(metrics.OperationTag(metrics.WorkflowContextScope)),
104 > config: config,
105 > lock: locks.NewPrioritySemaphore(1),
106 > }
107 > softassert.That(
108 > contextImpl.throttledLogger,
109 > contextImpl.archetypeID != chasm.UnspecifiedArchetypeID,
110 > "Creating execution context with unspecified archetype ID",
111 > )
112 >
113 > return contextImpl
114 }
115
117 ctx context.Context,
118 lockPriority locks.Priority,
119 > ) error { context.go
120 > return c.lock.Acquire(ctx, lockPriority, 1)
121 > }
122
123 > func (c *ContextImpl) Unlock() { context.go
124 > c.lock.Release(1)
125 > }
126
127 > func (c *ContextImpl) IsDirty() bool { context.go
128 > if c.MutableState == nil {
129 return false
130 }
131 > return c.MutableState.IsDirty() context.go
132 }
133
134 > func (c *ContextImpl) Clear() { context.go
135 > metrics.WorkflowContextCleared.With(c.metricsHandler).Record(1)
136 > if c.MutableState != nil {
137 > c.MutableState.GetQueryRegistry().Clear() context.go
138 > c.MutableState.RemoveSpeculativeWorkflowTaskTimeoutTask()
139 > c.MutableState = nil
140 > }
141 > if c.updateRegistry != nil { context.go
142 > c.updateRegistry.Clear() context.go
143 > c.updateRegistry = nil
144 > }
145 > c.clearTaskCompletionBuffer() context.go
146 }
147
148 // clearTaskCompletionBuffer drops the in-progress buffer
149 > func (c *ContextImpl) clearTaskCompletionBuffer() { context.go
150 > if c.taskCompletionBuffer == nil {
151 > return context.go
152 > }
153 c.taskCompletionBuffer = nil
154 }
177 // task is no longer in flight (timed out, failed, completed, or the workflow
178 // closed) and its buffer can never be consumed
179 > func (c *ContextImpl) reconcileTaskCompletionBuffer() { context.go
180 > if c.taskCompletionBuffer == nil || c.MutableState == nil {
181 > return context.go
182 > }
183 if c.startedWorkflowTaskIdentity() != c.taskCompletionBuffer.identity {
184 c.clearTaskCompletionBuffer()
319 }
320
321 > func (c *ContextImpl) GetWorkflowKey() definition.WorkflowKey { context.go
322 > return c.workflowKey
323 > }
324
325 > func (c *ContextImpl) GetNamespace(shardContext historyi.ShardContext) namespace.Name { context.go
326 > namespaceEntry, err := shardContext.GetNamespaceRegistry().GetNamespaceByID(
327 > namespace.ID(c.workflowKey.NamespaceID),
328 > )
329 > if err != nil {
330 return ""
331 }
332 > return namespaceEntry.Name() context.go
333 }
334
341 }
342
343 > func (c *ContextImpl) LoadMutableState(ctx context.Context, shardContext historyi.ShardContext) (historyi.MutableState, error) { context.go
344 > namespaceEntry, err := shardContext.GetNamespaceRegistry().GetNamespaceByID(
345 > namespace.ID(c.workflowKey.NamespaceID),
346 > )
347 > if err != nil {
348 return nil, err
349 }
350
351 > if c.MutableState == nil { context.go
352 > response, err := getWorkflowExecution(ctx, shardContext, &persistence.GetWorkflowExecutionRequest{ context.go
353 > ShardID: shardContext.GetShardID(),
354 > NamespaceID: c.workflowKey.NamespaceID,
355 > WorkflowID: c.workflowKey.WorkflowID,
356 > RunID: c.workflowKey.RunID,
357 > ArchetypeID: c.archetypeID,
358 > })
359 > if err != nil {
360 return nil, err
361 }
362
363 > mutableState, err := NewMutableStateFromDB( context.go
364 > shardContext,
365 > shardContext.GetEventsCache(),
366 > c.logger,
367 > namespaceEntry,
368 > response.State,
369 > response.DBRecordVersion,
370 > )
371 > if err != nil {
372 return nil, err
373 }
378 // returned by NewMutableStateFromDB().
379 // Thus causing NPE (e.g. when calling c.Clear()) or other unexpected behavior.
380 > c.MutableState = mutableState context.go
381 }
382
383 > mutableStateArchetypeID := c.MutableState.ChasmTree().ArchetypeID() context.go
384 > if c.archetypeID != chasm.UnspecifiedArchetypeID && c.archetypeID != mutableStateArchetypeID {
385 chasmRegistry := shardContext.ChasmRegistry()
386 contextArchetype, ok := chasmRegistry.ComponentFqnByID(c.archetypeID)
405 )
406 }
407 > c.archetypeID = mutableStateArchetypeID context.go
408 >
409 > flushBeforeReady, err := c.MutableState.StartTransaction(namespaceEntry)
410 > if err != nil {
411 return nil, err
412 }
413 > if !flushBeforeReady { context.go
414 > return c.MutableState, nil
415 > }
416
417 if err = c.UpdateWorkflowExecutionAsActive(
451 newWorkflowEvents []*persistence.WorkflowEvents,
452 transactionPolicy historyi.TransactionPolicy,
453 > ) (retError error) { context.go
454 >
455 > if transactionPolicy == historyi.TransactionPolicyActive {
456 > if rl := shardContext.BusinessIDReuseRateLimiter(
457 > namespace.ID(c.workflowKey.NamespaceID),
458 > c.workflowKey.WorkflowID,
459 > c.archetypeID,
460 > ); rl != nil && !rl.Allow() {
461 archetypeName, _ := shardContext.ChasmRegistry().ArchetypeDisplayName(c.archetypeID)
462 metrics.BusinessIDReuseRateLimited.With(shardContext.GetMetricsHandler()).Record(
470 }
471
472 > defer func() { context.go
473 > if retError != nil {
474 c.Clear()
475 }
476 }()
477
478 > createRequest := &persistence.CreateWorkflowExecutionRequest{ context.go
479 > ShardID: shardContext.GetShardID(),
480 > // workflow create mode & prev run ID & version
481 > Mode: createMode,
482 > PreviousRunID: prevRunID,
483 > PreviousLastWriteVersion: prevLastWriteVersion,
484 >
485 > ArchetypeID: c.archetypeID,
486 >
487 > NewWorkflowSnapshot: *newWorkflow,
488 > NewWorkflowEvents: newWorkflowEvents,
489 > }
490 >
491 > _, err := createWorkflowExecution(
492 > ctx,
493 > shardContext,
494 > newMutableState.GetCurrentVersion(),
495 > createRequest,
496 > newMutableState.IsWorkflow(),
497 > )
498 > if err != nil {
499 return err
500 }
501
502 > engine, err := shardContext.GetEngine(ctx) context.go
503 > if err != nil {
504 return err
505 }
506 > NotifyOnExecutionSnapshot(engine, newWorkflow) context.go
507 > emitStateTransitionCount(c.metricsHandler, shardContext.GetClusterMetadata(), newMutableState)
508 >
509 > return nil
510 }
511
631 ctx context.Context,
632 shardContext historyi.ShardContext,
633 > ) error { context.go
634 >
635 > // We only perform this check on active cluster for the namespace
636 > historySizeForceTerminate, err := c.enforceHistorySizeCheck(ctx, shardContext)
637 > if err != nil {
638 return err
639 }
640 > historyCountForceTerminate := false context.go
641 > if !historySizeForceTerminate {
642 > historyCountForceTerminate, err = c.enforceHistoryCountCheck(ctx, shardContext)
643 > if err != nil {
644 return err
645 }
646 }
647 > msForceTerminate := false context.go
648 > if !historySizeForceTerminate && !historyCountForceTerminate {
649 > msForceTerminate, err = c.enforceMutableStateSizeCheck(ctx, shardContext)
650 > if err != nil {
651 return err
652 }
653 }
654
655 > updateMode, err := c.updateWorkflowMode() context.go
656 > if err != nil {
657 return err
658 }
659
660 > err = c.UpdateWorkflowExecutionWithNew( context.go
661 > ctx,
662 > shardContext,
663 > updateMode,
664 > nil,
665 > nil,
666 > historyi.TransactionPolicyActive,
667 > nil,
668 > )
669 > if err != nil {
670 return err
671 }
674 // Retrying the operation will give appropriate semantics operation should expect in the case of workflow
675 // execution being closed.
676 > if historySizeForceTerminate { context.go
677 return consts.ErrHistorySizeExceedsLimit
678 }
679 > if historyCountForceTerminate { context.go
680 return consts.ErrHistoryCountExceedsLimit
681 }
682 > if msForceTerminate { context.go
683 return consts.ErrMutableStateSizeExceedsLimit
684 }
685
686 > return nil context.go
687 }
688
752 updateWorkflowTransactionPolicy historyi.TransactionPolicy,
753 newWorkflowTransactionPolicy *historyi.TransactionPolicy,
754 > ) (retError error) { context.go
755 >
756 > defer func() {
757 > if retError != nil {
758 c.Clear()
759 }
760 }()
761
762 > if newContext != nil && newMutableState != nil && newWorkflowTransactionPolicy != nil { context.go
763 if *newWorkflowTransactionPolicy == historyi.TransactionPolicyActive {
764 execInfo := newMutableState.GetExecutionInfo()
784 // reconcileTaskCompletionBuffer drops an orphaned buffer for the pagination of
785 // RespondWorkflowTaskCompleted requests.
786 > c.reconcileTaskCompletionBuffer() context.go
787 >
788 > updateWorkflow, updateWorkflowEventsSeq, err := c.MutableState.CloseTransactionAsMutation(
789 > ctx,
790 > updateWorkflowTransactionPolicy,
791 > )
792 > if err != nil {
793 return err
794 }
795
796 > var newWorkflow *persistence.WorkflowSnapshot context.go
797 > var newWorkflowEventsSeq []*persistence.WorkflowEvents
798 > if newContext != nil && newMutableState != nil && newWorkflowTransactionPolicy != nil {
799 defer func() {
800 if retError != nil {
812 }
813
814 > if updateWorkflow == nil { context.go
815 if newWorkflow != nil || len(newWorkflowEventsSeq) != 0 {
816 return serviceerror.NewInternal("current workflow mutation skipped with new workflow snapshot")
819 }
820
821 > if err := c.mergeUpdateWithNewReplicationTasks( context.go
822 > updateWorkflow,
823 > newWorkflow,
824 > ); err != nil {
825 return err
826 }
827
828 > eventsToReapply := updateWorkflowEventsSeq context.go
829 > if len(updateWorkflowEventsSeq) == 0 {
830 if reapplyCandidateEvents := c.MutableState.GetReapplyCandidateEvents(); len(reapplyCandidateEvents) != 0 {
831 eventsToReapply = []*persistence.WorkflowEvents{
840 }
841
842 > if err := c.updateWorkflowExecutionEventReapply( context.go
843 > ctx,
844 > shardContext,
845 > updateMode,
846 > eventsToReapply,
847 > // The new run is created by applying events so the history builder in newMutableState contains the events be re-applied.
848 > // So we can use newWorkflowEventsSeq directly to reapply events.
849 > newWorkflowEventsSeq,
850 > ); err != nil {
851 return err
852 }
853
854 > if _, _, err := NewTransaction(shardContext).UpdateWorkflowExecution( context.go
855 > ctx,
856 > updateMode,
857 > c.archetypeID,
858 > c.MutableState.GetCurrentVersion(),
859 > updateWorkflow,
860 > updateWorkflowEventsSeq,
861 > MutableStateFailoverVersion(newMutableState),
862 > newWorkflow,
863 > newWorkflowEventsSeq,
864 > c.MutableState.IsWorkflow(),
865 > ); err != nil {
866 return err
867 }
868
869 > emitStateTransitionCount(c.metricsHandler, shardContext.GetClusterMetadata(), c.MutableState) context.go
870 > emitStateTransitionCount(c.metricsHandler, shardContext.GetClusterMetadata(), newMutableState)
871 >
872 > // finally emit session stats
873 > emitWorkflowHistoryStats(
874 > c.metricsHandler,
875 > c.GetNamespace(shardContext),
876 > c.MutableState.GetExecutionState().State,
877 > int(c.MutableState.GetExecutionInfo().ExecutionStats.HistorySize),
878 > int(c.MutableState.GetNextEventID()-1),
879 > )
880 >
881 > return nil
882 }
883
926 currentWorkflowMutation *persistence.WorkflowMutation,
927 newWorkflowSnapshot *persistence.WorkflowSnapshot,
928 > ) error { context.go
929 >
930 > if newWorkflowSnapshot == nil {
931 > return nil context.go
932 > }
933
934 if currentWorkflowMutation.ExecutionState.Status != enumspb.WORKFLOW_EXECUTION_STATUS_CONTINUED_AS_NEW &&
1043 eventBatch1 []*persistence.WorkflowEvents,
1044 eventBatch2 []*persistence.WorkflowEvents,
1045 > ) error { context.go
1046 > if updateMode == persistence.UpdateWorkflowModeIgnoreCurrent {
1047 if len(eventBatch1) != 0 || len(eventBatch2) != 0 {
1048 return serviceerror.NewInternal("encountered events reapplication without knowing if workflow is current. Events generated for a close workflow?")
1051 }
1052
1053 > if updateMode != persistence.UpdateWorkflowModeBypassCurrent { context.go
1054 > return nil context.go
1055 > }
1056
1057 var eventBatches []*persistence.WorkflowEvents
1079 }
1080
1081 > func (c *ContextImpl) updateWorkflowMode() (persistence.UpdateWorkflowMode, error) { context.go
1082 > if !c.config.EnableUpdateWorkflowModeIgnoreCurrent() {
1083 return persistence.UpdateWorkflowModeUpdateCurrent, nil
1084 }
1085
1086 > if c.MutableState.IsCurrentWorkflowGuaranteed() { context.go
1087 > return persistence.UpdateWorkflowModeUpdateCurrent, nil context.go
1088 > }
1089
1090 guaranteed, err := c.MutableState.IsNonCurrentWorkflowGuaranteed()
1216 }
1217
1218 > func (c *ContextImpl) UpdateRegistry(ctx context.Context) update.Registry { context.go
1219 > if c.updateRegistry != nil && c.updateRegistry.FailoverVersion() != c.MutableState.GetCurrentVersion() {
1220 c.updateRegistry.Clear()
1221 c.updateRegistry = nil
1222 }
1223
1224 > if c.updateRegistry == nil { context.go
1225 > nsName := c.MutableState.GetNamespaceEntry().Name().String()
1226 >
1227 > c.updateRegistry = update.NewRegistry(
1228 > c.MutableState,
1229 > update.WithNamespace(nsName),
1230 > update.WithLogger(c.logger),
1231 > update.WithMetrics(c.metricsHandler),
1232 > update.WithTracerProvider(trace.SpanFromContext(ctx).TracerProvider()),
1233 > update.WithInFlightLimit(
1234 > func() int {
1235 return c.config.WorkflowExecutionMaxInFlightUpdates(nsName)
1236 },
1242 ),
1243 update.WithTotalLimit(
1244 > func() int { context.go
1245 > return c.config.WorkflowExecutionMaxTotalUpdates(nsName)
1246 > },
1247 ),
1248 update.WithTotalLimitSuggestCAN(
1249 > func() float64 { context.go
1250 > return c.config.WorkflowExecutionMaxTotalUpdatesSuggestContinueAsNewThreshold(nsName)
1251 > },
1252 ),
1253 )
1254 }
1255 > return c.updateRegistry context.go
1256 }
1257
1260 ctx context.Context,
1261 shardContext historyi.ShardContext,
1262 > ) (bool, error) { context.go
1263 > // Hard terminate workflow if still running and breached history size limit
1264 > if c.maxHistorySizeExceeded(shardContext) {
1265 if err := c.forceTerminateWorkflow(ctx, shardContext, common.FailureReasonHistorySizeExceedsLimit); err != nil {
1266 return false, err
1269 return true, nil
1270 }
1271 > return false, nil context.go
1272 }
1273
1274 // Returns true if the workflow is running and history size should trigger a forced termination
1275 // Prints a log message if history size is over the error or warn limits
1276 > func (c *ContextImpl) maxHistorySizeExceeded(shardContext historyi.ShardContext) bool { context.go
1277 > namespaceName := c.GetNamespace(shardContext).String()
1278 > historySizeLimitWarn := c.config.HistorySizeLimitWarn(namespaceName)
1279 > historySizeLimitError := c.config.HistorySizeLimitError(namespaceName)
1280 > historySize := int(c.MutableState.GetExecutionInfo().ExecutionStats.HistorySize)
1281 >
1282 > if historySize > historySizeLimitError && c.MutableState.IsWorkflowExecutionRunning() {
1283 c.logger.Warn("history size exceeds error limit.",
1284 tag.WorkflowHistorySize(historySize))
1287 }
1288
1289 > if historySize > historySizeLimitWarn { context.go
1290 c.throttledLogger.Warn("history size exceeds warn limit.",
1291 tag.WorkflowHistorySize(historySize))
1292 }
1293
1294 > return false context.go
1295 }
1296
1298 ctx context.Context,
1299 shardContext historyi.ShardContext,
1300 > ) (bool, error) { context.go
1301 > // Hard terminate workflow if still running and breached history count limit
1302 > if c.maxHistoryCountExceeded(shardContext) {
1303 if err := c.forceTerminateWorkflow(ctx, shardContext, common.FailureReasonHistoryCountExceedsLimit); err != nil {
1304 return false, err
1307 return true, nil
1308 }
1309 > return false, nil context.go
1310 }
1311
1312 // Returns true if the workflow is running and history event count should trigger a forced termination
1313 // Prints a log message if history event count is over the error or warn limits
1314 > func (c *ContextImpl) maxHistoryCountExceeded(shardContext historyi.ShardContext) bool { context.go
1315 > namespaceName := c.GetNamespace(shardContext).String()
1316 > historyCountLimitWarn := c.config.HistoryCountLimitWarn(namespaceName)
1317 > historyCountLimitError := c.config.HistoryCountLimitError(namespaceName)
1318 > historyCount := int(c.MutableState.GetNextEventID() - 1)
1319 >
1320 > if historyCount > historyCountLimitError && c.MutableState.IsWorkflowExecutionRunning() {
1321 c.logger.Warn("history count exceeds error limit.",
1322 tag.WorkflowEventCount(historyCount))
1325 }
1326
1327 > if historyCount > historyCountLimitWarn { context.go
1328 c.throttledLogger.Warn("history count exceeds warn limit.",
1329 tag.WorkflowEventCount(historyCount))
1330 }
1331
1332 > return false context.go
1333 }
1334
1335 // Returns true if execution is forced terminated
1336 // TODO: ideally this check should be after closing mutable state tx, but that would require a large refactor
1337 > func (c *ContextImpl) enforceMutableStateSizeCheck(ctx context.Context, shardContext historyi.ShardContext) (bool, error) { context.go
1338 > if c.maxMutableStateSizeExceeded(shardContext.ChasmRegistry()) {
1339 if err := c.forceTerminateWorkflow(ctx, shardContext, common.FailureReasonMutableStateSizeExceedsLimit); err != nil {
1340 return false, err
1343 return true, nil
1344 }
1345 > return false, nil context.go
1346 }
1347
1348 // Returns true if the workflow is running and mutable state size should trigger a forced termination
1349 // Prints a log message if mutable state size is over the error or warn limits
1350 > func (c *ContextImpl) maxMutableStateSizeExceeded(chasmRegistry *chasm.Registry) bool { context.go
1351 > mutableStateSizeLimitError := c.config.MutableStateSizeLimitError()
1352 > mutableStateSizeLimitWarn := c.config.MutableStateSizeLimitWarn()
1353 >
1354 > mutableStateSize := c.MutableState.GetApproximatePersistedSize()
1355 > metricsHandler := c.metricsHandler
1356 > if archetypeTag, ok := getArchetypeMetricTag(chasmRegistry, c.MutableState.ChasmTree().ArchetypeID()); ok {
1357 > metricsHandler = metricsHandler.WithTags(archetypeTag)
1358 > }
1359 > metrics.PersistedMutableStateSize.With(metricsHandler).Record(int64(mutableStateSize))
1360 >
1361 > if mutableStateSize > mutableStateSizeLimitError {
1362 c.logger.Warn("mutable state size exceeds error limit.",
1363 tag.WorkflowMutableStateSize(mutableStateSize))
1366 }
1367
1368 > if mutableStateSize > mutableStateSizeLimitWarn { context.go
1369 c.throttledLogger.Warn("mutable state size exceeds warn limit.",
1370 tag.WorkflowMutableStateSize(mutableStateSize))
1371 }
1372
1373 > return false context.go
1374 }
1375
1418 // CacheSize estimates the in-memory size of the object for cache limits. For proto objects, it uses proto.Size()
1419 // which returns the serialized size. Note: In-memory size will be slightly larger than the serialized size.
1420 > func (c *ContextImpl) CacheSize() int { context.go
1421 > if !c.config.HistoryCacheLimitSizeBased {
1422 > return 1 context.go
1423 > }
1424 size := len(c.workflowKey.WorkflowID) + len(c.workflowKey.RunID) + len(c.workflowKey.NamespaceID)
1425 if c.MutableState != nil {
1436 clusterMetadata cluster.Metadata,
1437 mutableState historyi.MutableState,
1438 > ) { context.go
1439 > if mutableState == nil {
1440 > return context.go
1441 > }
1442 > namespaceEntry := mutableState.GetNamespaceEntry() context.go
1443 > metrics.StateTransitionCount.With(metricsHandler).Record(
1444 > mutableState.GetExecutionInfo().StateTransitionCount,
1445 > metrics.NamespaceTag(namespaceEntry.Name().String()),
1446 > metrics.NamespaceStateTag(namespaceState(clusterMetadata, new(mutableState.GetCurrentVersion()))),
1447 > )
1448 }
1449
1451 clusterMetadata cluster.Metadata,
1452 mutableStateCurrentVersion *int64,
1453 > ) string { context.go
1454 >
1455 > if mutableStateCurrentVersion == nil {
1456 > return metrics.UnknownNamespaceStateTagValue context.go
1457 > }
1458
1459 // default value, need to special handle
1460 > if *mutableStateCurrentVersion == 0 { context.go
1461 > return metrics.ActiveNamespaceStateTagValue context.go
1462 > }
1463
1464 if clusterMetadata.IsVersionFromSameCluster(
1473 func MutableStateFailoverVersion(
1474 mutableState historyi.MutableState,
1475 > ) *int64 { context.go
1476 > if mutableState == nil {
1477 > return nil context.go
1478 > }
1479 return new(mutableState.GetCurrentVersion())
1480 }
go.temporal.io/server/service/matching/physical_task_queue_manager.go 313 covered LOC · 71 ranges

Open complete file

130 partitionMgr *taskQueuePartitionManagerImpl,
131 queue *PhysicalTaskQueueKey,
132 > ) (*physicalTaskQueueManagerImpl, error) { physical_task_queue_manager.go
133 > e := partitionMgr.engine
134 > config := partitionMgr.config
135 > versionTagValue := queue.Version().MetricsTagValue()
136 > buildIDTag := tag.WorkerVersion(versionTagValue)
137 > taggedMetricsHandler := partitionMgr.metricsHandler.WithTags(
138 > metrics.OperationTag(metrics.MatchingTaskQueueMgrScope),
139 > metrics.WorkerVersionTag(versionTagValue, config.BreakdownMetricsByBuildID()),
140 > metrics.WorkerDeploymentNameTag(queue.Version().Deployment().GetSeriesName(), config.BreakdownMetricsByBuildID()),
141 > metrics.WorkerDeploymentBuildIDTag(queue.Version().Deployment().GetBuildId(), config.BreakdownMetricsByBuildID()),
142 > )
143 >
144 > tqCtx, tqCancel := context.WithCancel(partitionMgr.callerInfoContext(context.Background()))
145 >
146 > // We multiply by a big number so that we can later divide it by the number of pollers when grabbing permits,
147 > // to allow us to make more decisions per second when there are more pollers.
148 > pollerScalingRateLimitFn := func() float64 {
149 > return config.PollerScalingDecisionsPerSecond() * 1e6
150 > }
151 > pqMgr := &physicalTaskQueueManagerImpl{
152 > status: common.DaemonStatusInitialized,
153 > partitionMgr: partitionMgr,
154 > queue: queue,
155 > config: config,
156 > tqCtx: tqCtx,
157 > tqCtxCancel: tqCancel,
158 > namespaceRegistry: e.namespaceRegistry,
159 > matchingClient: e.matchingRawClient,
160 > clusterMeta: e.clusterMeta,
161 > metricsHandler: taggedMetricsHandler,
162 > tasksAdded: make(map[priorityKey]*taskTracker),
163 > tasksDispatched: make(map[priorityKey]*taskTracker),
164 > tasksRateLimited: e.newTaskTracker(),
165 > pollerScalingRateLimiter: quotas.NewDefaultOutgoingRateLimiter(pollerScalingRateLimitFn),
166 > deploymentRegistrationCh: make(chan struct{}, 1),
167 > }
168 > pqMgr.deploymentRegistrationCh <- struct{}{} // seed
169 >
170 > pqMgr.pollerHistory = newPollerHistory(partitionMgr.config.PollerHistoryTTL())
171 >
172 > pqMgr.liveness = newLiveness(
173 > clock.NewRealTimeSource(),
174 > config.MaxTaskQueueIdleTime,
175 > func() { pqMgr.UnloadFromPartitionManager(unloadCauseIdle) },
176 )
177
178 > pqMgr.taskValidator = newTaskValidator( physical_task_queue_manager.go
179 > tqCtx,
180 > pqMgr.clusterMeta,
181 > pqMgr.namespaceRegistry,
182 > pqMgr.partitionMgr.engine.historyClient,
183 > )
184 >
185 > switch {
186 case config.EnableFairness:
187 pqMgr.logger = log.With(partitionMgr.logger, buildIDTag, backlogTagFairness)
225 return pqMgr, nil
226
227 > case config.NewMatcher: physical_task_queue_manager.go
228 > pqMgr.logger = log.With(partitionMgr.logger, buildIDTag, backlogTagPriority)
229 > pqMgr.throttledLogger = log.With(partitionMgr.throttledLogger, buildIDTag, backlogTagPriority)
230 >
231 > pqMgr.backlogMgr = newPriBacklogManager(
232 > tqCtx,
233 > pqMgr,
234 > config,
235 > e.taskManager,
236 > pqMgr.logger,
237 > pqMgr.throttledLogger,
238 > e.matchingRawClient,
239 > newPriMetricsHandler(taggedMetricsHandler),
240 > false,
241 > )
242 > var fwdr *priForwarder
243 > var err error
244 > if queue.Partition().IsChild() {
245 // Every DB Queue needs its own forwarder so that the throttles do not interfere
246 fwdr, err = newPriForwarder(&config.forwarderConfig, queue, e.matchingRawClient, e.testHooks)
249 }
250 }
251 > pqMgr.priMatcher = newPriTaskMatcher( physical_task_queue_manager.go
252 > tqCtx,
253 > config,
254 > queue.partition,
255 > fwdr,
256 > pqMgr.matchingClient,
257 > pqMgr.taskValidator,
258 > pqMgr.logger,
259 > newPriMetricsHandler(taggedMetricsHandler),
260 > partitionMgr.rateLimitManager,
261 > pqMgr.onRateLimited,
262 > pqMgr.MarkAlive,
263 > )
264 > pqMgr.matcher = pqMgr.priMatcher
265 > return pqMgr, nil
266 default:
267 pqMgr.logger = log.With(partitionMgr.logger, buildIDTag, backlogTagClassic)
293 }
294
295 > func (c *physicalTaskQueueManagerImpl) Start() { physical_task_queue_manager.go
296 > if !atomic.CompareAndSwapInt32(
297 > &c.status,
298 > common.DaemonStatusInitialized,
299 > common.DaemonStatusStarted,
300 > ) {
301 return
302 }
303 > c.liveness.Start() physical_task_queue_manager.go
304 > c.backlogMgr.Start()
305 > c.matcher.Start()
306 > c.logger.Info("Started physicalTaskQueueManager", tag.LifeCycleStarted, tag.Cause(c.config.loadCause.String()))
307 > c.metricsHandler.Counter(metrics.TaskQueueStartedCounter.Name()).Record(1)
308 > c.partitionMgr.engine.updatePhysicalTaskQueueGauge(c.partitionMgr.ns, c.partitionMgr.partition, c.queue.version, 1)
309 }
310
311 // Stop does not unload the queue from its partition. It is intended to be called by the partition manager when
312 // unloading a queues. For stopping and unloading a queue call UnloadFromPartitionManager instead.
313 > func (c *physicalTaskQueueManagerImpl) Stop(unloadCause unloadCause) { physical_task_queue_manager.go
314 > if !atomic.CompareAndSwapInt32(
315 > &c.status,
316 > common.DaemonStatusStarted,
317 > common.DaemonStatusStopped,
318 > ) {
319 return
320 }
321 // this may attempt to write one final ack update, do this before canceling tqCtx
322 > c.backlogMgr.Stop() physical_task_queue_manager.go
323 > if m := c.getDrainBacklogMgr(); m != nil {
325 > }
326 > c.matcher.Stop() physical_task_queue_manager.go
327 > c.liveness.Stop()
328 > c.tqCtxCancel()
329 >
330 > // Emitting zero values for backlog gauges to prevent stale values persisting after a partition is unloaded.
331 > // The call is placed here instead of backlogMgr.Stop() since there could be a race condition where a task is
332 > // added to the backlog after we have emitted the zero values inside of the backlogMgr.Stop() call. This happens
333 > // since task reader's and writer's contexts are cancelled after the backlogMgr.Stop() call.
334 > c.backlogMgr.getDB().emitZeroPhysicalBacklogGauges()
335 > c.logger.Info("Stopped physicalTaskQueueManager", tag.LifeCycleStopped, tag.Cause(unloadCause.String()))
336 > c.metricsHandler.Counter(metrics.TaskQueueStoppedCounter.Name()).Record(1)
337 > c.partitionMgr.engine.updatePhysicalTaskQueueGauge(c.partitionMgr.ns, c.partitionMgr.partition, c.queue.version, -1)
338 }
339
340 // getDrainBacklogMgr returns the draining backlog manager, or nil if none.
341 > func (c *physicalTaskQueueManagerImpl) getDrainBacklogMgr() backlogManager { physical_task_queue_manager.go
342 > c.drainBacklogMgrLock.Lock()
343 > defer c.drainBacklogMgrLock.Unlock()
344 > return c.drainBacklogMgr
345 > }
346
347 > func (c *physicalTaskQueueManagerImpl) WaitUntilInitialized(ctx context.Context) error { physical_task_queue_manager.go
348 > err := c.backlogMgr.WaitUntilInitialized(ctx)
349 > if err == nil {
350 > // If we're also draining another, then we need to wait for that also to write.
351 > // TODO: we could try to optimize this so we can _dispatch_ before loading the other
352 > // but still block on writing.
353 > if m := c.getDrainBacklogMgr(); m != nil {
354 > err = m.WaitUntilInitialized(ctx) physical_task_queue_manager.go
355 > }
356 }
358 }
359
360 // StartScaleManager is called by backlog manager after it's loaded metadata from the default queue. (New matcher only.)
361 > func (c *physicalTaskQueueManagerImpl) StartScaleManager(scaleState *persistencespb.PartitionScaleState) { physical_task_queue_manager.go
362 > c.partitionMgr.StartScaleManager(scaleState)
363 > }
364
365 func (c *physicalTaskQueueManagerImpl) UpdateScaleState(scaleState *persistencespb.PartitionScaleState, syncToDB bool) error {
375 // Must be called by the active backlog manager before it sets itself initialized.
376 // Must only be called when using new matcher.
377 > func (c *physicalTaskQueueManagerImpl) SetupDraining() { physical_task_queue_manager.go
378 > if !softassert.That(c.logger, c.priMatcher != nil, "SetupDraining called with old matcher") {
379 return
380 }
381
382 > if !c.config.EnableMigration() { physical_task_queue_manager.go
383 return
384 }
385
386 > var drainBacklogMgr backlogManager physical_task_queue_manager.go
387 > var logger log.Logger
388 > switch c.backlogMgr.(type) {
389 case *fairBacklogManagerImpl:
390 logger = log.With(c.logger, backlogTagPriorityDrain)
400 true,
401 )
402 > case *priBacklogManagerImpl: physical_task_queue_manager.go
403 > logger = log.With(c.logger, backlogTagFairnessDrain)
404 > drainBacklogMgr = newFairBacklogManager(
405 > c.tqCtx,
406 > c,
407 > c.config,
408 > c.partitionMgr.engine.fairTaskManager,
409 > logger,
410 > log.With(c.throttledLogger, backlogTagFairnessDrain),
411 > c.partitionMgr.engine.matchingRawClient,
412 > newFairMetricsHandler(c.metricsHandler),
413 > c.counterFactory,
414 > true,
415 > )
416 default:
417 softassert.Fail(c.logger, "SetupDraining called with unknown backlogMgr type")
419 }
420
421 > c.drainBacklogMgrLock.Lock() physical_task_queue_manager.go
422 > prev := c.drainBacklogMgr
423 > c.drainBacklogMgr = drainBacklogMgr
424 > c.drainBacklogMgrLock.Unlock()
425 > if !softassert.That(c.logger, prev == nil, "SetupDraining called twice") {
426 return
427 }
428 > logger.Info("Starting draining") physical_task_queue_manager.go
429 > drainBacklogMgr.Start()
430 }
431
466 }
467
468 > func (c *physicalTaskQueueManagerImpl) SpoolTask(taskInfo *persistencespb.TaskInfo) error { physical_task_queue_manager.go
469 > c.liveness.markAlive()
470 > return c.backlogMgr.SpoolTask(taskInfo)
471 > }
472
473 > func (c *physicalTaskQueueManagerImpl) RecordTaskAdd(result string, forwarded bool, behavior enumspb.VersioningBehavior) { physical_task_queue_manager.go
474 > c.metricsHandler.Counter(metrics.TasksAddedCounter.Name()).Record(
475 > 1,
476 > metrics.TaskAddResultTag(result),
477 > metrics.ForwardedTag(forwarded),
478 > metrics.VersioningBehaviorTag(behavior),
479 > )
480 > }
481
482 // PollTask blocks waiting for a task.
487 ctx context.Context,
488 pollMetadata *pollMetadata,
489 > ) (*internalTask, error) { physical_task_queue_manager.go
490 > c.liveness.markAlive()
491 >
492 > metrics.PendingPolls.With(c.metricsHandler).Record(float64(c.currentPolls.Add(1)))
493 > defer func() {
494 > metrics.PendingPolls.With(c.metricsHandler).Record(float64(c.currentPolls.Add(-1)))
495 > }()
496
497 > namespaceId := namespace.ID(c.queue.NamespaceId()) physical_task_queue_manager.go
498 > namespaceEntry, err := c.namespaceRegistry.GetNamespaceByID(namespaceId)
499 > if err != nil {
500 return nil, err
501 }
502
503 > if c.partitionMgr.engine.config.EnableDeploymentVersions(namespaceEntry.Name().String()) { physical_task_queue_manager.go
504 > if err = c.ensureRegisteredInDeploymentVersion(ctx, namespaceEntry, pollMetadata); err != nil { physical_task_queue_manager.go
505 return nil, err
506 }
508
509 //nolint:forbidigo // physical task queue lifecycle is namespace-scoped
510 > if !namespaceEntry.ActiveInCluster(c.clusterMeta.GetCurrentClusterName()) { physical_task_queue_manager.go
511 return c.matcher.PollForQuery(ctx, pollMetadata)
512 }
513
515 > task, err := c.matcher.Poll(ctx, pollMetadata)
516 > if err != nil {
517 > return nil, err physical_task_queue_manager.go
518 > }
519
520 // It's possible to get an expired task here: taskReader checks for expiration when
524 // If we didn't do this, the task would be rejected when we call RecordXTaskStarted on
525 // history, but this is more efficient.
526 > if task.event != nil && IsTaskExpired(task.event.AllocatedTaskInfo) { physical_task_queue_manager.go
527 // task is expired while polling
528 task.finish(taskFinishResult{dropReason: dropReasonExpiredMemory})
530 }
531
532 > task.namespace = c.partitionMgr.ns.Name() physical_task_queue_manager.go
533 > task.backlogCountHint = c.backlogCountHint
534 >
535 > if pollMetadata.forwardedFrom == "" { // track the task on the child, not where a poll was forwarded to
536 > c.incTaskTracker(c.tasksDispatched, priorityKey(task.getPriority().GetPriorityKey()), 1)
537 > }
538 > return task, nil
539 }
540 }
541
542 > func (c *physicalTaskQueueManagerImpl) backlogCountHint() int64 { physical_task_queue_manager.go
543 > n := c.backlogMgr.BacklogCountHint()
544 > if m := c.getDrainBacklogMgr(); m != nil {
545 > n += m.BacklogCountHint() physical_task_queue_manager.go
546 > }
548 }
549
550 > func (c *physicalTaskQueueManagerImpl) MarkAlive() { physical_task_queue_manager.go
551 > c.liveness.markAlive()
552 > }
553
554 // onRateLimited records a rate-limit event.
591 }
592
593 > func (c *physicalTaskQueueManagerImpl) AddSpooledTask(task *internalTask) error { physical_task_queue_manager.go
594 > return c.partitionMgr.AddSpooledTask(c.tqCtx, task, c.queue)
595 > }
596
597 > func (c *physicalTaskQueueManagerImpl) AddSpooledTaskToMatcher(task *internalTask) error { physical_task_queue_manager.go
598 > if c.priMatcher == nil {
599 softassert.Fail(c.logger, "AddSpooledTaskToMatcher called on old matcher")
600 return errInternalMatchError
601 }
602 > return c.priMatcher.AddTask(task) physical_task_queue_manager.go
603 }
604
605 > func (c *physicalTaskQueueManagerImpl) UserDataChanged() { physical_task_queue_manager.go
606 > c.matcher.ReprocessAllTasks()
607 > }
608
609 // DispatchQueryTask will dispatch query to local or remote poller. If forwarded then result or error is returned,
629 }
630
631 > func (c *physicalTaskQueueManagerImpl) UpdatePollerInfo(id pollerIdentity, pollMetadata *pollMetadata) { physical_task_queue_manager.go
632 > c.pollerHistory.updatePollerInfo(id, pollMetadata)
633 > }
634
635 func (c *physicalTaskQueueManagerImpl) RemovePoller(id pollerIdentity) {
679 }
680
681 > func (c *physicalTaskQueueManagerImpl) GetStatsByPriority(includeRates bool) map[int32]*taskqueuepb.TaskQueueStats { physical_task_queue_manager.go
682 > stats := c.backlogMgr.BacklogStatsByPriority()
683 >
684 > if m := c.getDrainBacklogMgr(); m != nil {
685 > drainStats := m.BacklogStatsByPriority() physical_task_queue_manager.go
686 > for pri, tqs := range drainStats {
687 > taskqueue.MergeStats(util.GetOrSetNew(stats, pri), tqs)
688 > }
689 }
690
691 > if includeRates { physical_task_queue_manager.go
692 > c.taskTrackerLock.Lock() physical_task_queue_manager.go
693 > for pri, tt := range c.tasksAdded {
694 > util.GetOrSetNew(stats, int32(pri)).TasksAddRate = tt.rate() physical_task_queue_manager.go
695 > }
696 > for pri, tt := range c.tasksDispatched { physical_task_queue_manager.go
697 > util.GetOrSetNew(stats, int32(pri)).TasksDispatchRate = tt.rate() physical_task_queue_manager.go
698 > }
699 > rateLimitingActive := c.tasksRateLimited.rate() > 0 physical_task_queue_manager.go
700 > c.taskTrackerLock.Unlock()
701 >
702 > for _, s := range stats {
703 > s.RateLimitingActive = rateLimitingActive
704 > }
705 }
706
707 > return stats physical_task_queue_manager.go
708 }
709
720 }
721
722 > func (c *physicalTaskQueueManagerImpl) TrySyncMatch(ctx context.Context, task *internalTask) (syncMatchOutcome, error) { physical_task_queue_manager.go
723 > if !task.isForwarded() {
724 > // request sent by history service physical_task_queue_manager.go
725 > c.liveness.markAlive()
726 > c.incTaskTracker(c.tasksAdded, priorityKey(task.getPriority().GetPriorityKey()), 1)
727 > if disable, _ := testhooks.Get(c.partitionMgr.engine.testHooks, testhooks.MatchingDisableSyncMatch, c.partitionMgr.ns.ID()); disable {
728 return syncMatchNoPoller, nil
729 }
730 }
731
732 > if c.priMatcher != nil { physical_task_queue_manager.go
733 > return c.priMatcher.Offer(ctx, task) physical_task_queue_manager.go
734 > }
735
736 childCtx, cancel := contextutil.WithDeadlineBuffer(ctx, c.config.SyncMatchWaitDuration(), time.Second)
748 namespaceEntry *namespace.Namespace,
749 pollMetadata *pollMetadata,
751 > workerDeployment, err := worker_versioning.DeploymentFromCapabilities(pollMetadata.workerVersionCapabilities, pollMetadata.deploymentOptions)
752 > if err != nil {
753 return err
754 }
755 > if workerDeployment == nil { physical_task_queue_manager.go
756 > return nil
757 > }
758 if !c.partitionMgr.engine.config.EnableDeploymentVersions(namespaceEntry.Name().String()) {
759 return errMissingDeploymentVersion
865 }
866
867 > func (c *physicalTaskQueueManagerImpl) QueueKey() *PhysicalTaskQueueKey { physical_task_queue_manager.go
868 > return c.queue
869 > }
870
871 func (c *physicalTaskQueueManagerImpl) UnloadFromPartitionManager(unloadCause unloadCause) {
884 func (c *physicalTaskQueueManagerImpl) MakePollerScalingDecision(
885 ctx context.Context,
886 > pollStartTime time.Time) *taskqueuepb.PollerScalingDecision { physical_task_queue_manager.go
887 > return c.makePollerScalingDecisionImpl(pollStartTime, func() *taskqueuepb.TaskQueueStats {
888 > return c.partitionMgr.GetPhysicalQueueAdjustedStats(ctx, c) physical_task_queue_manager.go
889 > })
890 }
891
893 pollStartTime time.Time,
894 statsFn func() *taskqueuepb.TaskQueueStats,
895 > ) *taskqueuepb.PollerScalingDecision { physical_task_queue_manager.go
896 > pollWaitTime := c.partitionMgr.engine.timeSource.Since(pollStartTime)
897 > // If a poller has waited around a while, we can always suggest a decrease.
898 > if pollWaitTime >= c.partitionMgr.config.PollerScalingWaitTime() {
899 // Decrease if any poll matched after sitting idle for some configured period
900 c.recordPollerScaleDecision(metrics.PollerScaleDecisionDown, metrics.PollerScaleReasonIdle)
906 // Avoid spiking pollers crazy fast by limiting how frequently change decisions are issued. Be more permissive when
907 // there are more recent pollers.
908 > numPollers := c.pollerHistory.history.Size() physical_task_queue_manager.go
909 > if numPollers == 0 {
910 numPollers = 1
911 }
912 > if !c.pollerScalingRateLimiter.AllowN(time.Now(), 1e6/numPollers) { physical_task_queue_manager.go
913 c.recordPollerScaleDecision(metrics.PollerScaleDecisionHold, metrics.PollerScaleReasonRateLimited)
914 return nil
915 }
916
917 > delta := int32(0) physical_task_queue_manager.go
918 > var reason metrics.ReasonString
919 > stats := statsFn()
920 > if stats.GetApproximateBacklogCount() > 0 &&
921 > stats.GetApproximateBacklogAge().AsDuration() > c.partitionMgr.config.PollerScalingBacklogAgeScaleUp() {
922 // Always increase when there is a backlog, even if we're a partition. It's also important to increase for
923 // sticky queues.
924 delta = 1
925 reason = metrics.PollerScaleReasonBacklog
926 > } else if c.queue.Partition().Kind() != enumspb.TASK_QUEUE_KIND_STICKY && !c.queue.Partition().IsRoot() { physical_task_queue_manager.go
927 // Non-root partitions don't have an appropriate view of the data to make decisions beyond backlog.
928 // Sticky queues are exempt: they aren't considered root but do have a complete view of their data,
929 // as they have only 1 partition.
930 return nil
932 > if float64(stats.GetTasksAddRate())/float64(stats.GetTasksDispatchRate()) > c.partitionMgr.config.PollerScalingTaskAddToDispatchRatio() {
933 // Increase if we're adding tasks faster than we're dispatching them. Particularly useful for Nexus tasks,
934 // since those (currently) don't get backlogged.
969 priorityKey priorityKey,
970 n int,
972 > // priorityKey could be zero here if we're tracking dispatched tasks (i.e. called from PollTask)
973 > // and the poll was forwarded so we have a "started" task. We don't return the priority with the
974 > // started task info so it's not available here. Use the default priority to avoid confusion
975 > // even though it may not be accurate.
976 > // TODO: either return priority with the started task, or do this tracking on the node where the
977 > // match happened, so we have the right value here.
978 > if priorityKey == 0 {
979 > priorityKey = c.config.DefaultPriorityKey physical_task_queue_manager.go
980 > }
981
982 > c.taskTrackerLock.Lock() physical_task_queue_manager.go
983 > defer c.taskTrackerLock.Unlock()
984 >
985 > tracker, ok := intervals[priorityKey]
986 > if !ok {
987 > // Initialize all task trackers together; or the timeframes won't line up.
988 > c.tasksAdded[priorityKey] = c.partitionMgr.engine.newTaskTracker()
989 > c.tasksDispatched[priorityKey] = c.partitionMgr.engine.newTaskTracker()
990 > tracker = intervals[priorityKey]
991 > }
992 > tracker.inc(n)
993 }
994
995 > func aggregateStats(stats map[int32]*taskqueuepb.TaskQueueStats) *taskqueuepb.TaskQueueStats { physical_task_queue_manager.go
996 > result := &taskqueuepb.TaskQueueStats{ApproximateBacklogAge: durationpb.New(0)}
997 > for _, s := range stats {
998 > taskqueue.MergeStats(result, s)
999 > }
1000 > return result
1001 }
go.temporal.io/server/api/persistence/v1/executions.pb.go 311 covered LOC · 76 ranges

Open complete file

53 }
54
55 > func (x *ShardInfo) Reset() { executions.pb.go
56 > *x = ShardInfo{}
57 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[0]
58 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
59 > ms.StoreMessageInfo(mi)
60 > }
61
62 func (x *ShardInfo) String() string {
66 func (*ShardInfo) ProtoMessage() {}
67
68 > func (x *ShardInfo) ProtoReflect() protoreflect.Message { executions.pb.go
69 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[0]
70 > if x != nil {
71 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) executions.pb.go
72 > if ms.LoadMessageInfo() == nil {
73 > ms.StoreMessageInfo(mi)
74 > }
75 > return ms
76 }
77 > return mi.MessageOf(x) executions.pb.go
78 }
79
83 }
84
85 > func (x *ShardInfo) GetShardId() int32 { executions.pb.go
86 > if x != nil {
87 > return x.ShardId
88 > }
89 return 0
90 }
91
92 > func (x *ShardInfo) GetRangeId() int64 { executions.pb.go
93 > if x != nil {
94 > return x.RangeId
95 > }
96 return 0
97 }
98
99 > func (x *ShardInfo) GetOwner() string { executions.pb.go
100 > if x != nil {
101 > return x.Owner
102 > }
103 return ""
104 }
118 }
119
120 > func (x *ShardInfo) GetReplicationDlqAckLevel() map[string]int64 { executions.pb.go
121 > if x != nil {
122 > return x.ReplicationDlqAckLevel
123 > }
124 return nil
125 }
126
127 > func (x *ShardInfo) GetQueueStates() map[int32]*QueueState { executions.pb.go
128 > if x != nil {
129 > return x.QueueStates
130 > }
131 return nil
132 }
380 }
381
382 > func (x *WorkflowExecutionInfo) Reset() { executions.pb.go
383 > *x = WorkflowExecutionInfo{}
384 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[1]
385 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
386 > ms.StoreMessageInfo(mi)
387 > }
388
389 func (x *WorkflowExecutionInfo) String() string {
393 func (*WorkflowExecutionInfo) ProtoMessage() {}
394
395 > func (x *WorkflowExecutionInfo) ProtoReflect() protoreflect.Message { executions.pb.go
396 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[1]
397 > if x != nil {
398 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) executions.pb.go
399 > if ms.LoadMessageInfo() == nil {
400 > ms.StoreMessageInfo(mi)
401 > }
402 > return ms
403 }
404 return mi.MessageOf(x)
410 }
411
412 > func (x *WorkflowExecutionInfo) GetNamespaceId() string { executions.pb.go
413 > if x != nil {
414 > return x.NamespaceId
415 > }
416 return ""
417 }
418
419 > func (x *WorkflowExecutionInfo) GetWorkflowId() string { executions.pb.go
420 > if x != nil {
421 > return x.WorkflowId
422 > }
423 return ""
424 }
508 }
509
510 > func (x *WorkflowExecutionInfo) GetLastCompletedWorkflowTaskStartedEventId() int64 { executions.pb.go
511 > if x != nil {
512 > return x.LastCompletedWorkflowTaskStartedEventId
513 > }
514 return 0
515 }
634 }
635
636 > func (x *WorkflowExecutionInfo) GetWorkflowTaskStamp() int32 { executions.pb.go
637 > if x != nil {
638 > return x.WorkflowTaskStamp
639 > }
640 return 0
641 }
809 }
810
811 > func (x *WorkflowExecutionInfo) GetVersionHistories() *v14.VersionHistories { executions.pb.go
812 > if x != nil {
813 > return x.VersionHistories
814 > }
815 return nil
816 }
823 }
824
825 > func (x *WorkflowExecutionInfo) GetExecutionStats() *ExecutionStats { executions.pb.go
826 > if x != nil {
827 > return x.ExecutionStats
828 > }
829 return nil
830 }
844 }
845
846 > func (x *WorkflowExecutionInfo) GetStateTransitionCount() int64 { executions.pb.go
847 > if x != nil {
848 > return x.StateTransitionCount
849 > }
850 return 0
851 }
852
853 > func (x *WorkflowExecutionInfo) GetExecutionTime() *timestamppb.Timestamp { executions.pb.go
854 > if x != nil {
855 > return x.ExecutionTime
856 > }
857 return nil
858 }
914 }
915
916 > func (x *WorkflowExecutionInfo) GetMostRecentWorkerVersionStamp() *v13.WorkerVersionStamp { executions.pb.go
917 > if x != nil {
918 > return x.MostRecentWorkerVersionStamp
919 > }
920 return nil
921 }
942 }
943
944 > func (x *WorkflowExecutionInfo) GetUpdateInfos() map[string]*UpdateInfo { executions.pb.go
945 > if x != nil {
946 > return x.UpdateInfos
947 > }
948 return nil
949 }
950
951 > func (x *WorkflowExecutionInfo) GetTransitionHistory() []*VersionedTransition { executions.pb.go
952 > if x != nil {
953 > return x.TransitionHistory
954 > }
955 return nil
956 }
1026 }
1027
1028 > func (x *WorkflowExecutionInfo) GetWorkflowWasReset() bool { executions.pb.go
1029 > if x != nil {
1030 > return x.WorkflowWasReset
1031 > }
1032 return false
1033 }
1034
1035 > func (x *WorkflowExecutionInfo) GetResetRunId() string { executions.pb.go
1036 > if x != nil {
1037 > return x.ResetRunId
1038 > }
1039 return ""
1040 }
1041
1042 > func (x *WorkflowExecutionInfo) GetVersioningInfo() *v12.WorkflowExecutionVersioningInfo { executions.pb.go
1043 > if x != nil {
1044 > return x.VersioningInfo
1045 > }
1046 return nil
1047 }
1075 }
1076
1077 > func (x *WorkflowExecutionInfo) GetWorkerDeploymentName() string { executions.pb.go
1078 > if x != nil {
1079 > return x.WorkerDeploymentName
1080 > }
1081 return ""
1082 }
1142 }
1143
1144 > func (x *WorkflowExecutionInfo) GetTimeSkippingInfo() *TimeSkippingInfo { executions.pb.go
1145 > if x != nil {
1146 > return x.TimeSkippingInfo
1147 > }
1148 return nil
1149 }
1199 func (*TimeSkippingInfo) ProtoMessage() {}
1200
1201 > func (x *TimeSkippingInfo) ProtoReflect() protoreflect.Message { executions.pb.go
1202 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[2]
1203 > if x != nil {
1204 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1205 if ms.LoadMessageInfo() == nil {
1208 return ms
1209 }
1210 > return mi.MessageOf(x) executions.pb.go
1211 }
1212
1216 }
1217
1218 > func (x *TimeSkippingInfo) GetConfig() *v13.TimeSkippingConfig { executions.pb.go
1219 > if x != nil {
1220 return x.Config
1221 }
1222 > return nil executions.pb.go
1223 }
1224
1225 > func (x *TimeSkippingInfo) GetAccumulatedSkippedDuration() *durationpb.Duration { executions.pb.go
1226 > if x != nil {
1227 return x.AccumulatedSkippedDuration
1228 }
1229 > return nil executions.pb.go
1230 }
1231
1333 func (*LastNotifiedTargetVersion) ProtoMessage() {}
1334
1335 > func (x *LastNotifiedTargetVersion) ProtoReflect() protoreflect.Message { executions.pb.go
1336 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[4]
1337 > if x != nil {
1338 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1339 if ms.LoadMessageInfo() == nil {
1342 return ms
1343 }
1344 > return mi.MessageOf(x) executions.pb.go
1345 }
1346
1390 func (*ExecutionStats) ProtoMessage() {}
1391
1392 > func (x *ExecutionStats) ProtoReflect() protoreflect.Message { executions.pb.go
1393 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[5]
1394 > if x != nil {
1395 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) executions.pb.go
1396 > if ms.LoadMessageInfo() == nil {
1397 > ms.StoreMessageInfo(mi)
1398 > }
1399 > return ms
1400 }
1401 > return mi.MessageOf(x) executions.pb.go
1402 }
1403
1407 }
1408
1409 > func (x *ExecutionStats) GetHistorySize() int64 { executions.pb.go
1410 > if x != nil {
1411 > return x.HistorySize executions.pb.go
1412 > }
1413 return 0
1414 }
1415
1416 > func (x *ExecutionStats) GetExternalPayloadSize() int64 { executions.pb.go
1417 > if x != nil {
1418 > return x.ExternalPayloadSize executions.pb.go
1419 > }
1420 return 0
1421 }
1422
1423 > func (x *ExecutionStats) GetExternalPayloadCount() int64 { executions.pb.go
1424 > if x != nil {
1425 > return x.ExternalPayloadCount executions.pb.go
1426 > }
1427 return 0
1428 }
1450 }
1451
1452 > func (x *WorkflowExecutionState) Reset() { executions.pb.go
1453 > *x = WorkflowExecutionState{}
1454 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[6]
1455 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1456 > ms.StoreMessageInfo(mi)
1457 > }
1458
1459 func (x *WorkflowExecutionState) String() string {
1463 func (*WorkflowExecutionState) ProtoMessage() {}
1464
1465 > func (x *WorkflowExecutionState) ProtoReflect() protoreflect.Message { executions.pb.go
1466 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[6]
1467 > if x != nil {
1468 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) executions.pb.go
1469 > if ms.LoadMessageInfo() == nil {
1470 > ms.StoreMessageInfo(mi)
1471 > }
1472 > return ms
1473 }
1474 return mi.MessageOf(x)
1487 }
1488
1489 > func (x *WorkflowExecutionState) GetRunId() string { executions.pb.go
1490 > if x != nil {
1491 > return x.RunId executions.pb.go
1492 > }
1493 return ""
1494 }
1495
1496 > func (x *WorkflowExecutionState) GetState() v1.WorkflowExecutionState { executions.pb.go
1497 > if x != nil {
1498 > return x.State executions.pb.go
1499 > }
1500 return v1.WorkflowExecutionState(0)
1501 }
1502
1503 > func (x *WorkflowExecutionState) GetStatus() v11.WorkflowExecutionStatus { executions.pb.go
1504 > if x != nil {
1505 > return x.Status executions.pb.go
1506 > }
1507 return v11.WorkflowExecutionStatus(0)
1508 }
1515 }
1516
1517 > func (x *WorkflowExecutionState) GetStartTime() *timestamppb.Timestamp { executions.pb.go
1518 > if x != nil {
1519 > return x.StartTime executions.pb.go
1520 > }
1521 return nil
1522 }
1557 func (*RequestIDInfo) ProtoMessage() {}
1558
1559 > func (x *RequestIDInfo) ProtoReflect() protoreflect.Message { executions.pb.go
1560 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[7]
1561 > if x != nil {
1562 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) executions.pb.go
1563 > if ms.LoadMessageInfo() == nil {
1564 > ms.StoreMessageInfo(mi)
1565 > }
1566 > return ms
1567 }
1568 > return mi.MessageOf(x) executions.pb.go
1569 }
1570
1621 }
1622
1623 > func (x *TransferTaskInfo) Reset() { executions.pb.go
1624 > *x = TransferTaskInfo{}
1625 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[8]
1626 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1627 > ms.StoreMessageInfo(mi)
1628 > }
1629
1630 func (x *TransferTaskInfo) String() string {
1634 func (*TransferTaskInfo) ProtoMessage() {}
1635
1636 > func (x *TransferTaskInfo) ProtoReflect() protoreflect.Message { executions.pb.go
1637 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[8]
1638 > if x != nil {
1639 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1640 > if ms.LoadMessageInfo() == nil {
1641 > ms.StoreMessageInfo(mi)
1642 > }
1643 > return ms
1644 }
1645 return mi.MessageOf(x)
2030 }
2031
2032 > func (x *VisibilityTaskInfo) Reset() { executions.pb.go
2033 > *x = VisibilityTaskInfo{}
2034 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[10]
2035 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2036 > ms.StoreMessageInfo(mi)
2037 > }
2038
2039 func (x *VisibilityTaskInfo) String() string {
2043 func (*VisibilityTaskInfo) ProtoMessage() {}
2044
2045 > func (x *VisibilityTaskInfo) ProtoReflect() protoreflect.Message { executions.pb.go
2046 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[10]
2047 > if x != nil {
2048 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2049 > if ms.LoadMessageInfo() == nil {
2050 > ms.StoreMessageInfo(mi)
2051 > }
2052 > return ms
2053 }
2054 return mi.MessageOf(x)
2216 func (*TimerTaskInfo) ProtoMessage() {}
2217
2218 > func (x *TimerTaskInfo) ProtoReflect() protoreflect.Message { executions.pb.go
2219 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[11]
2220 > if x != nil {
2221 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
2222 > if ms.LoadMessageInfo() == nil {
2223 > ms.StoreMessageInfo(mi)
2224 > }
2225 > return ms
2226 }
2227 return mi.MessageOf(x)
3695 func (*Checksum) ProtoMessage() {}
3696
3697 > func (x *Checksum) ProtoReflect() protoreflect.Message { executions.pb.go
3698 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[22]
3699 > if x != nil {
3700 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) executions.pb.go
3701 > if ms.LoadMessageInfo() == nil {
3702 > ms.StoreMessageInfo(mi)
3703 > }
3704 > return ms
3705 }
3706 return mi.MessageOf(x)
3726 }
3727
3728 > func (x *Checksum) GetValue() []byte { executions.pb.go
3729 > if x != nil {
3730 return x.Value
3731 }
3732 > return nil executions.pb.go
3733 }
3734
4336 func (*ResetChildInfo) ProtoMessage() {}
4337
4338 > func (x *ResetChildInfo) ProtoReflect() protoreflect.Message { executions.pb.go
4339 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[28]
4340 > if x != nil {
4341 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4342 if ms.LoadMessageInfo() == nil {
4345 return ms
4346 }
4347 > return mi.MessageOf(x) executions.pb.go
4348 }
4349
4387 func (*WorkflowPauseInfo) ProtoMessage() {}
4388
4389 > func (x *WorkflowPauseInfo) ProtoReflect() protoreflect.Message { executions.pb.go
4390 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[29]
4391 > if x != nil {
4392 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
4393 if ms.LoadMessageInfo() == nil {
4396 return ms
4397 }
4398 > return mi.MessageOf(x) executions.pb.go
4399 }
4400
4454 func (*TransferTaskInfo_CloseExecutionTaskDetails) ProtoMessage() {}
4455
4456 > func (x *TransferTaskInfo_CloseExecutionTaskDetails) ProtoReflect() protoreflect.Message { executions.pb.go
4457 > mi := &file_temporal_server_api_persistence_v1_executions_proto_msgTypes[38]
4458 > if x != nil {
4459 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) executions.pb.go
4460 > if ms.LoadMessageInfo() == nil {
4461 > ms.StoreMessageInfo(mi)
4462 > }
4463 > return ms
4464 }
4465 > return mi.MessageOf(x) executions.pb.go
4466 }
4467
5706 }
5707
5708 > func init() { file_temporal_server_api_persistence_v1_executions_proto_init() } executions.pb.go
5709 > func file_temporal_server_api_persistence_v1_executions_proto_init() {
5710 > if File_temporal_server_api_persistence_v1_executions_proto != nil {
5711 > return
5712 > }
5713 > file_temporal_server_api_persistence_v1_chasm_proto_init()
5714 > file_temporal_server_api_persistence_v1_hsm_proto_init()
5715 > file_temporal_server_api_persistence_v1_queues_proto_init()
5716 > file_temporal_server_api_persistence_v1_update_proto_init()
5717 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[1].OneofWrappers = []any{
5718 > (*WorkflowExecutionInfo_LastWorkflowTaskFailureCause)(nil),
5719 > (*WorkflowExecutionInfo_LastWorkflowTaskTimedOutType)(nil),
5720 > }
5721 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[8].OneofWrappers = []any{
5722 > (*TransferTaskInfo_CloseExecutionTaskDetails_)(nil),
5723 > (*TransferTaskInfo_ChasmTaskInfo)(nil),
5724 > }
5725 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[10].OneofWrappers = []any{
5726 > (*VisibilityTaskInfo_ChasmTaskInfo)(nil),
5727 > }
5728 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[11].OneofWrappers = []any{
5729 > (*TimerTaskInfo_ChasmTaskInfo)(nil),
5730 > }
5731 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[13].OneofWrappers = []any{
5732 > (*OutboundTaskInfo_StateMachineInfo)(nil),
5733 > (*OutboundTaskInfo_ChasmTaskInfo)(nil),
5734 > (*OutboundTaskInfo_WorkerCommandsTask)(nil),
5735 > }
5736 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[17].OneofWrappers = []any{
5737 > (*ActivityInfo_UseWorkflowBuildIdInfo_)(nil),
5738 > (*ActivityInfo_LastIndependentlyAssignedBuildId)(nil),
5739 > }
5740 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[23].OneofWrappers = []any{
5741 > (*Callback_Nexus_)(nil),
5742 > (*Callback_Hsm)(nil),
5743 > }
5744 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[40].OneofWrappers = []any{
5745 > (*ActivityInfo_PauseInfo_Manual_)(nil),
5746 > (*ActivityInfo_PauseInfo_RuleId)(nil),
5747 > }
5748 > file_temporal_server_api_persistence_v1_executions_proto_msgTypes[46].OneofWrappers = []any{
5749 > (*CallbackInfo_Trigger_WorkflowClosed)(nil),
5750 > }
5751 > type x struct{}
5752 > out := protoimpl.TypeBuilder{
5753 > File: protoimpl.DescBuilder{
5754 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
5755 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_executions_proto_rawDesc), len(file_temporal_server_api_persistence_v1_executions_proto_rawDesc)),
5756 > NumEnums: 0,
5757 > NumMessages: 47,
5758 > NumExtensions: 0,
5759 > NumServices: 0,
5760 > },
5761 > GoTypes: file_temporal_server_api_persistence_v1_executions_proto_goTypes,
5762 > DependencyIndexes: file_temporal_server_api_persistence_v1_executions_proto_depIdxs,
5763 > MessageInfos: file_temporal_server_api_persistence_v1_executions_proto_msgTypes,
5764 > }.Build()
5765 > File_temporal_server_api_persistence_v1_executions_proto = out.File
5766 > file_temporal_server_api_persistence_v1_executions_proto_goTypes = nil
5767 > file_temporal_server_api_persistence_v1_executions_proto_depIdxs = nil
5768 }
go.temporal.io/server/common/persistence/persistence_retryable_clients.go 304 covered LOC · 71 ranges

Open complete file

66 policy backoff.RetryPolicy,
67 isRetryable backoff.IsRetryable,
68 > ) ShardManager { persistence_retryable_clients.go
69 > return &shardRetryablePersistenceClient{
70 > persistence: persistence,
71 > policy: policy,
72 > isRetryable: isRetryable,
73 > }
74 > }
75
76 // NewExecutionPersistenceRetryableClient creates a client to manage executions
79 policy backoff.RetryPolicy,
80 isRetryable backoff.IsRetryable,
81 > ) ExecutionManager { persistence_retryable_clients.go
82 > return &executionRetryablePersistenceClient{
83 > persistence: persistence,
84 > policy: policy,
85 > isRetryable: isRetryable,
86 > }
87 > }
88
89 // NewTaskPersistenceRetryableClient creates a client to manage tasks
92 policy backoff.RetryPolicy,
93 isRetryable backoff.IsRetryable,
94 > ) TaskManager { persistence_retryable_clients.go
95 > return &taskRetryablePersistenceClient{
96 > persistence: persistence,
97 > policy: policy,
98 > isRetryable: isRetryable,
99 > }
100 > }
101
102 // NewMetadataPersistenceRetryableClient creates a MetadataManager client to manage metadata
105 policy backoff.RetryPolicy,
106 isRetryable backoff.IsRetryable,
107 > ) MetadataManager { persistence_retryable_clients.go
108 > return &metadataRetryablePersistenceClient{
109 > persistence: persistence,
110 > policy: policy,
111 > isRetryable: isRetryable,
112 > }
113 > }
114
115 // NewClusterMetadataPersistenceRetryableClient creates a ClusterMetadataManager client to manage cluster metadata
118 policy backoff.RetryPolicy,
119 isRetryable backoff.IsRetryable,
120 > ) ClusterMetadataManager { persistence_retryable_clients.go
121 > return &clusterMetadataRetryablePersistenceClient{
122 > persistence: persistence,
123 > policy: policy,
124 > isRetryable: isRetryable,
125 > }
126 > }
127
128 // NewQueuePersistenceRetryableClient creates a client to manage queue
131 policy backoff.RetryPolicy,
132 isRetryable backoff.IsRetryable,
134 > return &queueRetryablePersistenceClient{
135 > persistence: persistence,
136 > policy: policy,
137 > isRetryable: isRetryable,
138 > }
139 > }
140
141 // NewNexusEndpointPersistenceRetryableClient creates a NexusEndpointManager client to manage nexus endpoints
144 policy backoff.RetryPolicy,
145 isRetryable backoff.IsRetryable,
146 > ) NexusEndpointManager { persistence_retryable_clients.go
147 > return &nexusEndpointRetryablePersistenceClient{
148 > persistence: persistence,
149 > policy: policy,
150 > isRetryable: isRetryable,
151 > }
152 > }
153
154 func (p *shardRetryablePersistenceClient) GetName() string {
159 ctx context.Context,
160 request *GetOrCreateShardRequest,
161 > ) (*GetOrCreateShardResponse, error) { persistence_retryable_clients.go
162 > var response *GetOrCreateShardResponse
163 > op := func(ctx context.Context) error {
164 > var err error
165 > response, err = p.persistence.GetOrCreateShard(ctx, request)
166 > return err
167 > }
168
169 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
170 > return response, err
171 }
172
174 ctx context.Context,
175 request *UpdateShardRequest,
177 > op := func(ctx context.Context) error {
178 > return p.persistence.UpdateShard(ctx, request)
179 > }
180
181 > return backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
182 }
183
185 ctx context.Context,
186 request *AssertShardOwnershipRequest,
188 > op := func(ctx context.Context) error {
189 > return p.persistence.AssertShardOwnership(ctx, request)
190 > }
191
192 > return backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
193 }
194
195 > func (p *shardRetryablePersistenceClient) Close() { persistence_retryable_clients.go
196 > p.persistence.Close()
197 > }
198
199 > func (p *executionRetryablePersistenceClient) GetName() string { persistence_retryable_clients.go
200 > return p.persistence.GetName()
201 > }
202
203 > func (p *executionRetryablePersistenceClient) GetHistoryBranchUtil() HistoryBranchUtil { persistence_retryable_clients.go
204 > return p.persistence.GetHistoryBranchUtil()
205 > }
206
207 func (p *executionRetryablePersistenceClient) CreateWorkflowExecution(
208 ctx context.Context,
209 request *CreateWorkflowExecutionRequest,
210 > ) (*CreateWorkflowExecutionResponse, error) { persistence_retryable_clients.go
211 > var response *CreateWorkflowExecutionResponse
212 > op := func(ctx context.Context) error {
213 > var err error
214 > response, err = p.persistence.CreateWorkflowExecution(ctx, request)
215 > return err
216 > }
217
218 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
219 > return response, err
220 }
221
223 ctx context.Context,
224 request *GetWorkflowExecutionRequest,
225 > ) (*GetWorkflowExecutionResponse, error) { persistence_retryable_clients.go
226 > var response *GetWorkflowExecutionResponse
227 > op := func(ctx context.Context) error {
228 > var err error
229 > response, err = p.persistence.GetWorkflowExecution(ctx, request)
230 > return err
231 > }
232
233 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
234 > return response, err
235 }
236
253 ctx context.Context,
254 request *UpdateWorkflowExecutionRequest,
255 > ) (*UpdateWorkflowExecutionResponse, error) { persistence_retryable_clients.go
256 > var response *UpdateWorkflowExecutionResponse
257 > op := func(ctx context.Context) error {
258 > var err error
259 > response, err = p.persistence.UpdateWorkflowExecution(ctx, request)
260 > return err
261 > }
262
263 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
264 > return response, err
265 }
266
346 ctx context.Context,
347 request *GetHistoryTasksRequest,
348 > ) (*GetHistoryTasksResponse, error) { persistence_retryable_clients.go
349 > var response *GetHistoryTasksResponse
350 > op := func(ctx context.Context) error {
351 > var err error
352 > response, err = p.persistence.GetHistoryTasks(ctx, request)
353 > return err
354 > }
355
356 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
357 > return response, err
358 }
359
479 ctx context.Context,
480 request *ReadHistoryBranchRequest,
481 > ) (*ReadHistoryBranchResponse, error) { persistence_retryable_clients.go
482 > var response *ReadHistoryBranchResponse
483 > op := func(ctx context.Context) error {
484 > var err error
485 > response, err = p.persistence.ReadHistoryBranch(ctx, request)
486 > return err
487 > }
488
489 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
490 > return response, err
491 }
492
598 }
599
600 > func (p *executionRetryablePersistenceClient) Close() { persistence_retryable_clients.go
601 > p.persistence.Close()
602 > }
603
604 func (p *taskRetryablePersistenceClient) GetName() string {
609 ctx context.Context,
610 request *CreateTasksRequest,
611 > ) (*CreateTasksResponse, error) { persistence_retryable_clients.go
612 > var response *CreateTasksResponse
613 > op := func(ctx context.Context) error {
614 > var err error
615 > response, err = p.persistence.CreateTasks(ctx, request)
616 > return err
617 > }
618
619 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
620 > return response, err
621 }
622
624 ctx context.Context,
625 request *GetTasksRequest,
626 > ) (*GetTasksResponse, error) { persistence_retryable_clients.go
627 > var response *GetTasksResponse
628 > op := func(ctx context.Context) error {
629 > var err error
630 > response, err = p.persistence.GetTasks(ctx, request)
631 > return err
632 > }
633
634 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
635 > return response, err
636 }
637
654 ctx context.Context,
655 request *CreateTaskQueueRequest,
656 > ) (*CreateTaskQueueResponse, error) { persistence_retryable_clients.go
657 > var response *CreateTaskQueueResponse
658 > op := func(ctx context.Context) error {
659 > var err error
660 > response, err = p.persistence.CreateTaskQueue(ctx, request)
661 > return err
662 > }
663
664 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
665 > return response, err
666 }
667
669 ctx context.Context,
670 request *UpdateTaskQueueRequest,
671 > ) (*UpdateTaskQueueResponse, error) { persistence_retryable_clients.go
672 > var response *UpdateTaskQueueResponse
673 > op := func(ctx context.Context) error {
674 > var err error
675 > response, err = p.persistence.UpdateTaskQueue(ctx, request)
676 > return err
677 > }
678
679 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
680 > return response, err
681 }
682
684 ctx context.Context,
685 request *GetTaskQueueRequest,
686 > ) (*GetTaskQueueResponse, error) { persistence_retryable_clients.go
687 > var response *GetTaskQueueResponse
688 > op := func(ctx context.Context) error {
689 > var err error
690 > response, err = p.persistence.GetTaskQueue(ctx, request)
691 > return err
692 > }
693
694 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
695 > return response, err
696 }
697
725 ctx context.Context,
726 request *GetTaskQueueUserDataRequest,
727 > ) (*GetTaskQueueUserDataResponse, error) { persistence_retryable_clients.go
728 > var response *GetTaskQueueUserDataResponse
729 > op := func(ctx context.Context) error {
730 > var err error
731 > response, err = p.persistence.GetTaskQueueUserData(ctx, request)
732 > return err
733 > }
734
735 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
736 > return response, err
737 }
738
788 }
789
790 > func (p *taskRetryablePersistenceClient) Close() { persistence_retryable_clients.go
791 > p.persistence.Close()
792 > }
793
794 func (p *metadataRetryablePersistenceClient) GetName() string {
799 ctx context.Context,
800 request *CreateNamespaceRequest,
801 > ) (*CreateNamespaceResponse, error) { persistence_retryable_clients.go
802 > var response *CreateNamespaceResponse
803 > op := func(ctx context.Context) error {
804 > var err error
805 > response, err = p.persistence.CreateNamespace(ctx, request)
806 > return err
807 > }
808
809 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
810 > return response, err
811 }
812
814 ctx context.Context,
815 request *GetNamespaceRequest,
816 > ) (*GetNamespaceResponse, error) { persistence_retryable_clients.go
817 > var response *GetNamespaceResponse
818 > op := func(ctx context.Context) error {
819 > var err error
820 > response, err = p.persistence.GetNamespace(ctx, request)
821 > return err
822 > }
823
824 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
825 > return response, err
826 }
827
873 ctx context.Context,
874 request *ListNamespacesRequest,
875 > ) (*ListNamespacesResponse, error) { persistence_retryable_clients.go
876 > var response *ListNamespacesResponse
877 > op := func(ctx context.Context) error {
878 > var err error
879 > response, err = p.persistence.ListNamespaces(ctx, request)
880 > return err
881 > }
882
883 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
884 > return response, err
885 }
886
902 ctx context.Context,
903 currentClusterName string,
905 > op := func(ctx context.Context) error {
906 > return p.persistence.InitializeSystemNamespaces(ctx, currentClusterName)
907 > }
908
909 > return backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
910 }
911
912 func (p *metadataRetryablePersistenceClient) WatchNamespaces(
913 ctx context.Context,
914 > ) (<-chan *NamespaceWatchEvent, error) { persistence_retryable_clients.go
915 > var watchCh <-chan *NamespaceWatchEvent
916 > op := func(ctx context.Context) error {
917 > var err error
918 > watchCh, err = p.persistence.WatchNamespaces(ctx)
919 > return err
920 > }
921
922 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
923 > return watchCh, err
924 }
925
926 > func (p *metadataRetryablePersistenceClient) Close() { persistence_retryable_clients.go
927 > p.persistence.Close()
928 > }
929
930 func (p *clusterMetadataRetryablePersistenceClient) GetName() string {
935 ctx context.Context,
936 request *GetClusterMembersRequest,
937 > ) (*GetClusterMembersResponse, error) { persistence_retryable_clients.go
938 > var response *GetClusterMembersResponse
939 > op := func(ctx context.Context) error {
940 > var err error
941 > response, err = p.persistence.GetClusterMembers(ctx, request)
942 > return err
943 > }
944
945 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
946 > return response, err
947 }
948
950 ctx context.Context,
951 request *UpsertClusterMembershipRequest,
953 > op := func(ctx context.Context) error {
954 > return p.persistence.UpsertClusterMembership(ctx, request)
955 > }
956
957 > return backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
958 }
959
961 ctx context.Context,
962 request *PruneClusterMembershipRequest,
964 > op := func(ctx context.Context) error {
965 > return p.persistence.PruneClusterMembership(ctx, request)
966 > }
967
968 > return backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
969 }
970
972 ctx context.Context,
973 request *ListClusterMetadataRequest,
974 > ) (*ListClusterMetadataResponse, error) { persistence_retryable_clients.go
975 > var response *ListClusterMetadataResponse
976 > op := func(ctx context.Context) error {
977 > var err error
978 > response, err = p.persistence.ListClusterMetadata(ctx, request)
979 > return err
980 > }
981
982 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
983 > return response, err
984 }
985
986 func (p *clusterMetadataRetryablePersistenceClient) GetCurrentClusterMetadata(
987 ctx context.Context,
988 > ) (*GetClusterMetadataResponse, error) { persistence_retryable_clients.go
989 > var response *GetClusterMetadataResponse
990 > op := func(ctx context.Context) error {
991 > var err error
992 > response, err = p.persistence.GetCurrentClusterMetadata(ctx)
993 > return err
994 > }
995
996 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
997 > return response, err
998 }
999
1001 ctx context.Context,
1002 request *GetClusterMetadataRequest,
1003 > ) (*GetClusterMetadataResponse, error) { persistence_retryable_clients.go
1004 > var response *GetClusterMetadataResponse
1005 > op := func(ctx context.Context) error {
1006 > var err error
1007 > response, err = p.persistence.GetClusterMetadata(ctx, request)
1008 > return err
1009 > }
1010
1011 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
1012 > return response, err
1013 }
1014
1016 ctx context.Context,
1017 request *SaveClusterMetadataRequest,
1018 > ) (bool, error) { persistence_retryable_clients.go
1019 > var response bool
1020 > op := func(ctx context.Context) error {
1021 > var err error
1022 > response, err = p.persistence.SaveClusterMetadata(ctx, request)
1023 > return err
1024 > }
1025
1026 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
1027 > return response, err
1028 }
1029
1039 }
1040
1041 > func (p *clusterMetadataRetryablePersistenceClient) Close() { persistence_retryable_clients.go
1042 > p.persistence.Close()
1043 > }
1044
1045 func (p *queueRetryablePersistenceClient) Init(
1046 ctx context.Context,
1047 blob *commonpb.DataBlob,
1049 > op := func(ctx context.Context) error {
1050 > return p.persistence.Init(ctx, blob)
1051 > }
1052
1053 > return backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable) persistence_retryable_clients.go
1054 }
1055
1198 }
1199
1200 > func (p *queueRetryablePersistenceClient) Close() { persistence_retryable_clients.go
1201 > p.persistence.Close()
1202 > }
1203
1204 func (p *nexusEndpointRetryablePersistenceClient) GetName() string {
1206 }
1207
1208 > func (p *nexusEndpointRetryablePersistenceClient) Close() { persistence_retryable_clients.go
1209 > p.persistence.Close()
1210 > }
1211
1212 func (p *nexusEndpointRetryablePersistenceClient) GetNexusEndpoint(
1227 ctx context.Context,
1228 request *ListNexusEndpointsRequest,
1229 > ) (*ListNexusEndpointsResponse, error) { persistence_retryable_clients.go
1230 > var response *ListNexusEndpointsResponse
1231 > op := func(ctx context.Context) error {
1232 > var err error
1233 > response, err = p.persistence.ListNexusEndpoints(ctx, request)
1234 > return err
1235 > }
1236 > err := backoff.ThrottleRetryContext(ctx, op, p.policy, p.isRetryable)
1237 > return response, err
1238 }
1239
go.temporal.io/server/chasm/tree.go 297 covered LOC · 93 ranges

Open complete file

270 logger log.Logger,
271 metricsHandler metrics.Handler,
272 > ) (*Node, error) { tree.go
273 > if len(serializedNodes) == 0 {
274 > root := NewEmptyTree(registry, timeSource, backend, pathEncoder, logger, metricsHandler) tree.go
275 > // NewEmptyTree initializes the serializedNode to an empty component node,
276 > root.serializedNode.Metadata.GetComponentAttributes().TypeId = WorkflowArchetypeID
277 > return root, nil
278 > }
279
280 root := newTreeHelper(registry, timeSource, backend, pathEncoder, logger, metricsHandler)
301 logger log.Logger,
302 metricsHandler metrics.Handler,
303 > ) *Node { tree.go
304 > root := newTreeHelper(registry, timeSource, backend, pathEncoder, logger, metricsHandler)
305 >
306 > // If serializedNodes is empty, it means that this new tree.
307 > // Initialize empty serializedNode.
308 > root.initSerializedNode(fieldTypeComponent)
309 > // Default to Workflow archetype as empty tree is created for workflow as well.
310 > root.serializedNode.Metadata.GetComponentAttributes().TypeId = WorkflowArchetypeID
311 > // Although both value and serializedNode.Data are nil, they are considered NOT synced
312 > // because value has no type and serializedNode does.
313 > // deserialize method should set value when called.
314 > root.setValueState(valueStateNeedDeserialize)
315 > return root
316 > }
317
318 func newTreeHelper(
323 logger log.Logger,
324 metricsHandler metrics.Handler,
325 > ) *Node { tree.go
326 > base := &nodeBase{
327 > registry: registry,
328 > timeSource: timeSource,
329 > backend: backend,
330 > pathEncoder: pathEncoder,
331 > logger: logger,
332 > metricsHandler: metricsHandler,
333 >
334 > mutation: NodesMutation{
335 > UpdatedNodes: make(map[string]*persistencespb.ChasmNode),
336 > DeletedNodes: make(map[string]struct{}),
337 > },
338 > systemMutation: NodesMutation{
339 > UpdatedNodes: make(map[string]*persistencespb.ChasmNode),
340 > DeletedNodes: make(map[string]struct{}),
341 > },
342 > newTasks: make(map[any][]taskWithAttributes),
343 > immediatePureTasks: make(map[any][]taskWithAttributes),
344 > pendingRequestLinks: make(map[any]map[string][]*commonpb.Link),
345 > pendingUserMetadata: make(map[any]*sdkpb.UserMetadata),
346 > valueToNode: make(map[any]*Node),
347 > taskValueCache: make(map[*commonpb.DataBlob]reflect.Value),
348 > needsPointerResolution: false,
349 > }
350 >
351 > return newNode(base, nil, "")
352 > }
353
354 func newTreeInitSearchAttributesAndMemo(
400 // If the node is a component or data node, the index from node value to node (valueToNode)
401 // is also updated.
402 > func (n *Node) setValue(value any) { tree.go
403 > if !n.isComponent() && !n.isData() {
404 n.value = value
405 return
406 }
407
408 > if n.value != nil { tree.go
409 delete(n.valueToNode, n.value)
410 }
411
412 > n.value = value tree.go
413 >
414 > if value != nil {
415 > n.valueToNode[value] = n
416 > }
417 }
418
419 > func (n *Node) setValueState(state valueState) { tree.go
420 > n.valueState = state
421 > if state >= valueStateNeedSerialize {
422 n.markSubtreeDirty()
423 }
598 func (n *Node) prepareComponentValue(
599 chasmContext Context,
600 > ) error { tree.go
601 > if n.valueState == valueStateNeedDeserialize {
602 > metadata := n.serializedNode.Metadata tree.go
603 > componentAttr := metadata.GetComponentAttributes()
604 > if componentAttr == nil {
605 return softassert.UnexpectedInternalErr(
606 n.logger,
609 }
610
611 > registrableComponent, ok := n.registry.ComponentByID(componentAttr.GetTypeId()) tree.go
612 > if !ok {
613 return softassert.UnexpectedInternalErr(
614 n.logger,
617 }
618
619 > if err := n.deserialize(registrableComponent.goType); err != nil { tree.go
620 return fmt.Errorf("failed to deserialize component: %w", err)
621 }
624 // For now, we assume if a node is accessed with a MutableContext,
625 // its value will be mutated and no longer in sync with the serializedNode.
626 > _, componentCanBeMutated := chasmContext.(MutableContext) tree.go
627 > if componentCanBeMutated {
628 n.setValueState(valueStateNeedSyncStructure)
629 }
630
631 > return nil tree.go
632 }
633
680 }
681
682 > func (n *Node) isComponent() bool { tree.go
683 > return n.serializedNode.GetMetadata().GetComponentAttributes() != nil
684 > }
685
686 func (n *Node) isData() bool {
733 }
734
735 > func assertStructPointer(t reflect.Type) error { tree.go
736 > if t == nil {
737 return nil
738 }
739
740 > if t.Kind() != reflect.Pointer || t.Elem().Kind() != reflect.Struct { tree.go
741 return serviceerror.NewInternalf("only pointer to struct is supported for tree node value: got %s", t.String())
742 }
743 > return nil tree.go
744 }
745
746 > func (n *Node) initSerializedNode(ft fieldType) { tree.go
747 > switch ft {
748 case fieldTypeData:
749 n.serializedNode = &persistencespb.ChasmNode{
758 },
759 }
760 > case fieldTypeComponent: tree.go
761 > n.serializedNode = &persistencespb.ChasmNode{
762 > Metadata: &persistencespb.ChasmNodeMetadata{
763 > InitialVersionedTransition: &persistencespb.VersionedTransition{
764 > TransitionCount: n.backend.NextTransitionCount(),
765 > NamespaceFailoverVersion: n.backend.GetCurrentVersion(),
766 > },
767 > Attributes: &persistencespb.ChasmNodeMetadata_ComponentAttributes{
768 > ComponentAttributes: &persistencespb.ChasmComponentAttributes{},
769 > },
770 > },
771 > }
772 case fieldTypePointer, fieldTypeDeferredPointer:
773 // A deferred pointer will be resolved to a regular pointer before persistence.
915 //
916 // nolint:revive,cognitive-complexity
917 > func (n *Node) syncSubComponents() error { tree.go
918 > if n.valueState < valueStateNeedSyncStructure {
919 > for _, childNode := range n.children { tree.go
920 err := childNode.syncSubComponents()
921 if err != nil {
923 }
924 }
925 > return nil tree.go
926 }
927
1292 func (n *Node) deserialize(
1293 valueT reflect.Type,
1294 > ) error { tree.go
1295 > if err := assertStructPointer(valueT); err != nil {
1296 return err
1297 }
1298
1299 > if n.valueState != valueStateNeedDeserialize && reflect.TypeOf(n.value) == valueT { tree.go
1300 return nil
1301 }
1302
1303 > switch n.serializedNode.GetMetadata().GetAttributes().(type) { tree.go
1304 > case *persistencespb.ChasmNodeMetadata_ComponentAttributes:
1305 > return n.deserializeComponentNode(valueT)
1306 case *persistencespb.ChasmNodeMetadata_DataAttributes:
1307 return n.deserializeDataNode(valueT)
1318 func (n *Node) deserializeComponentNode(
1319 valueT reflect.Type,
1320 > ) error { tree.go
1321 > // valueT is guaranteed to be a pointer to the struct because it was already validated by the assertStructPointer method.
1322 > valueV := reflect.New(valueT.Elem())
1323 >
1324 > for field := range fieldsOf(valueV) {
1325 > if field.err != nil {
1326 return field.err
1327 }
1328
1329 > switch field.kind { tree.go
1330 case fieldKindUnspecified:
1331 softassert.Fail(
1333 "field.kind can be unspecified only if err is not nil, and there is a check for it above",
1334 tag.String("node name", n.nodeName))
1335 > case fieldKindData: tree.go
1336 > value, err := unmarshalProto(n.serializedNode.GetData(), field.typ)
1337 > if err != nil {
1338 return err
1339 }
1340 > field.val.Set(value) tree.go
1341 case fieldKindSubField:
1342 if childNode, found := n.children[field.name]; found {
1346 field.val.Set(chasmFieldV)
1347 }
1348 > case fieldKindSubMap: tree.go
1349 > if collectionNode, found := n.children[field.name]; found {
1350 mapFieldV := field.val
1351 if mapFieldV.IsNil() {
1365 mapFieldV.SetMapIndex(mapKeyV, chasmFieldV)
1366 }
1367 > } else if field.val.IsNil() { tree.go
1368 > field.val.Set(reflect.MakeMap(field.typ))
1369 > }
1370 > case fieldKindMutableState:
1371 > field.val.Set(reflect.ValueOf(NewMSPointer(n.backend)))
1372 case fieldKindParentPtr:
1373 parentPtrV := reflect.New(field.typ).Elem()
1379 }
1380
1381 > n.setValue(valueV.Interface()) tree.go
1382 > n.setValueState(valueStateSynced)
1383 > return nil
1384 }
1385
1407 dataBlob *commonpb.DataBlob,
1408 valueT reflect.Type,
1409 > ) (reflect.Value, error) { tree.go
1410 > if !valueT.AssignableTo(protoMessageT) {
1411 return reflect.Value{}, serviceerror.NewInternal("only support proto.Message as chasm data")
1412 }
1413
1414 > value := reflect.New(valueT.Elem()) tree.go
1415 >
1416 > if dataBlob == nil || len(dataBlob.Data) == 0 {
1417 > // If the original data is the zero value of its type, the dataBlob loaded from persistence layer will be nil. tree.go
1418 > // But we know for component & data nodes, they won't get persisted in the first place if there's no data,
1419 > // so it must be a zero value.
1420 > dataBlob = &commonpb.DataBlob{
1421 > EncodingType: enumspb.ENCODING_TYPE_PROTO3,
1422 > Data: []byte{},
1423 > }
1424 > }
1425
1426 > if err := serialization.Decode(dataBlob, value.Interface().(proto.Message)); err != nil { tree.go
1427 return reflect.Value{}, err
1428 }
1429
1430 > return value, nil tree.go
1431 }
1432
1560 // reference a component that was never registered as a node are dropped and
1561 // logged at warn level to surface caller misuse.
1562 > func (n *Node) closeTransactionApplyPendingComponentMetadata() error { tree.go
1563 > if len(n.pendingRequestLinks) == 0 && len(n.pendingUserMetadata) == 0 {
1564 > return nil
1565 > }
1566 for _, node := range n.andAllChildren() {
1567 if !node.applyPendingComponentMetadata() {
1663 func (n *Node) Now(
1664 _ Component,
1665 > ) time.Time { tree.go
1666 > // TODO: Now() could be different for components after we support Pause for CHASM components.
1667 > return n.timeSource.Now()
1668 > }
1669
1670 // AddTask implements the CHASM MutableContext interface
1692 // CloseTransaction is used by MutableState to close the transaction and
1693 // track changes made in the current transaction.
1694 > func (n *Node) CloseTransaction() (NodesMutation, error) { tree.go
1695 > defer n.cleanupTransaction()
1696 >
1697 > if err := n.executeImmediatePureTasks(); err != nil {
1698 return NodesMutation{}, err
1699 }
1700
1701 > if err := n.syncSubComponents(); err != nil { tree.go
1702 return NodesMutation{}, err
1703 }
1704
1705 > if n.needsPointerResolution { tree.go
1706 if err := n.resolveDeferredPointers(); err != nil {
1707 return NodesMutation{}, err
1709 }
1710
1711 > nextVersionedTransition := &persistencespb.VersionedTransition{ tree.go
1712 > NamespaceFailoverVersion: n.backend.GetCurrentVersion(),
1713 > TransitionCount: n.backend.NextTransitionCount(),
1714 > }
1715 >
1716 > immutableContext := NewContext(context.TODO(), n)
1717 > rootLifecycleChanged, err := n.closeTransactionHandleRootLifecycleChange(immutableContext)
1718 > if err != nil {
1719 return NodesMutation{}, err
1720 }
1721
1722 > if n.subtreeIsDirty { tree.go
1723 if err := n.closeTransactionForceUpdateVisibility(immutableContext, rootLifecycleChanged); err != nil {
1724 return NodesMutation{}, err
1726 }
1727
1728 > if err := n.closeTransactionSerializeNodes(); err != nil { tree.go
1729 return NodesMutation{}, err
1730 }
1731
1732 > if err := n.closeTransactionUpdateComponentTasks(nextVersionedTransition); err != nil { tree.go
1733 return NodesMutation{}, err
1734 }
1735
1736 > if err := n.closeTransactionApplyPendingComponentMetadata(); err != nil { tree.go
1737 return NodesMutation{}, err
1738 }
1739
1740 // Both user & system data mutation need to be returned and persisted.
1741 > maps.Copy(n.mutation.UpdatedNodes, n.systemMutation.UpdatedNodes) tree.go
1742 > maps.Copy(n.mutation.DeletedNodes, n.systemMutation.DeletedNodes)
1743 >
1744 > return n.mutation, nil
1745 }
1746
1747 > func (n *Node) executeImmediatePureTasks() error { tree.go
1748 >
1749 > // We must sync structure before running any tasks here because,
1750 > // those tasks might be for a newly created component which doesn't even have a node yet.
1751 > // And we want to make sure we only run tasks for components that are still part of the tree.
1752 > syncStructure := true
1753 > var err error
1754 >
1755 > for len(n.immediatePureTasks) != 0 {
1756 // Create a map in case more immediate pure tasks get
1757 // added while existing ones are executed.
1786 }
1787
1788 > return nil tree.go
1789 }
1790
1791 func (n *Node) closeTransactionHandleRootLifecycleChange(
1792 immutableContext Context,
1793 > ) (bool, error) { tree.go
1794 > if n.backend.IsWorkflow() {
1795 > // Workflow manages its lifecycle directly in mutable state. tree.go
1796 > return false, nil
1797 > }
1798
1799 if n.valueState != valueStateNeedSerialize {
1933 }
1934
1935 > func (n *Node) closeTransactionSerializeNodes() error { tree.go
1936 > for nodePath, node := range n.andAllChildren() {
1937 > if node.valueState > valueStateNeedSerialize {
1938 return serviceerror.NewInternalf("invalid valueState for serializing: %v", node.valueState)
1939 }
1940
1941 > if node.valueState < valueStateNeedSerialize { tree.go
1942 > continue tree.go
1943 }
1944
1992 }
1993
1994 > return nil tree.go
1995 }
1996
1997 func (n *Node) closeTransactionUpdateComponentTasks(
1998 nextVersionedTransition *persistencespb.VersionedTransition,
1999 > ) error { tree.go
2000 > taskOffset := int64(1)
2001 > taskValidationContext := NewContext(newContextWithOperationIntent(context.Background(), OperationIntentProgress), n)
2002 >
2003 > archetypeID := n.ArchetypeID()
2004 >
2005 > var firstPureTask *persistencespb.ChasmComponentAttributes_Task
2006 > var firstPureTaskNode *Node
2007 >
2008 > for nodePath, node := range n.andAllChildren() {
2009 > // no-op if node is not a component
2010 > componentAttr := node.serializedNode.Metadata.GetComponentAttributes()
2011 > if componentAttr == nil {
2012 continue
2013 }
2021 // markSubtreeDirty propagates to both ancestors and descendants at mutation time,
2022 // so we skip validation only for nodes with no dirty node anywhere in their lineage.
2023 > if node.subtreeIsDirty { tree.go
2024 // Ensure this node's component value is hydrated before cleaning up tasks.
2025 if err := node.prepareComponentValue(taskValidationContext); err != nil {
2054 // This method is called after the closeTransactionSerializeNodes which sets valueState
2055 // to valueStateSynced.
2056 > if transitionhistory.Compare( tree.go
2057 > node.serializedNode.GetMetadata().LastUpdateVersionedTransition,
2058 > nextVersionedTransition,
2059 > ) == 0 && node.valueState != valueStateNeedDeserialize {
2060 if err := node.closeTransactionHandleNewTasks(
2061 nextVersionedTransition,
2067 }
2068
2069 > sideEffectTasks := componentAttr.GetSideEffectTasks() tree.go
2070 > for idx := len(sideEffectTasks) - 1; idx >= 0; idx-- {
2071 sideEffectTask := sideEffectTasks[idx]
2072 if sideEffectTask.PhysicalTaskStatus == physicalTaskStatusCreated {
2083 // Find the first pure task in the entire tree,
2084 // regardless if the pure task is newly added or existing.
2085 > pureTasks := componentAttr.GetPureTasks() tree.go
2086 > if len(pureTasks) == 0 {
2087 > continue tree.go
2088 }
2089
2101 // task, and that component get deleted by the second task.
2102
2103 > return n.closeTransactionGeneratePhysicalPureTask( tree.go
2104 > firstPureTask,
2105 > firstPureTaskNode,
2106 > archetypeID,
2107 > )
2108 }
2109
2346 firstTaskNode *Node,
2347 archetypeID ArchetypeID,
2348 > ) error { tree.go
2349 > if firstPureTask == nil {
2350 > n.backend.DeleteCHASMPureTasks(tasks.MaximumKey.FireTime) tree.go
2351 > return nil
2352 > }
2353
2354 firstPureTaskScheduledTime := firstPureTask.ScheduledTime.AsTime()
2445 // andAllChildren returns a sequence of all nodes in the tree starting from n, including n itself.
2446 // The sequence is depth-first, pre-order traversal.
2447 > func (n *Node) andAllChildren() iter.Seq2[[]string, *Node] { tree.go
2448 > return func(yield func([]string, *Node) bool) {
2449 > var walk func([]string, *Node) bool
2450 > walk = func(path []string, node *Node) bool {
2451 > if node == nil {
2452 return true
2453 }
2454 > if !yield(path, node) { tree.go
2455 return false
2456 }
2457 > for _, child := range node.children { tree.go
2458 childPath := make([]string, len(path)+1)
2459 copy(childPath, path)
2463 }
2464 }
2465 > return true tree.go
2466 }
2467 > walk(nil, n) tree.go
2468 }
2469 }
2470
2471 > func (n *Node) cleanupTransaction() { tree.go
2472 > n.mutation = NodesMutation{
2473 > UpdatedNodes: make(map[string]*persistencespb.ChasmNode),
2474 > DeletedNodes: make(map[string]struct{}),
2475 > }
2476 >
2477 > // System mutation are most likely to be empty, so we reuse existing ones if possible.
2478 > if len(n.systemMutation.UpdatedNodes) != 0 {
2479 n.systemMutation.UpdatedNodes = make(map[string]*persistencespb.ChasmNode)
2480 }
2481 > if len(n.systemMutation.DeletedNodes) != 0 { tree.go
2482 n.systemMutation.DeletedNodes = make(map[string]struct{})
2483 }
2484
2485 > n.newTasks = make(map[any][]taskWithAttributes) tree.go
2486 > if len(n.immediatePureTasks) != 0 {
2487 // n.immediatePureTasks should already be empty after executeImmediatePureTasks()
2488 // unless there's an error.
2490 }
2491
2492 > if len(n.pendingRequestLinks) != 0 { tree.go
2493 n.pendingRequestLinks = make(map[any]map[string][]*commonpb.Link)
2494 }
2495 > if len(n.pendingUserMetadata) != 0 { tree.go
2496 n.pendingUserMetadata = make(map[any]*sdkpb.UserMetadata)
2497 }
2498
2499 > n.needsPointerResolution = false tree.go
2500 >
2501 > // Reset per-node subtreeIsDirty on all nodes in the tree.
2502 > for _, node := range n.andAllChildren() {
2503 > node.subtreeIsDirty = false
2504 > }
2505 }
2506
2510 func (n *Node) Snapshot(
2511 exclusiveMinVT *persistencespb.VersionedTransition,
2512 > ) NodesSnapshot { tree.go
2513 > if !softassert.That(n.logger, n.parent == nil, "chasm.Snapshot() should only be called on the root node") {
2514 panic(fmt.Sprintf("chasm.Snapshot() called on child node: %+v", n))
2515 }
2517 // TODO: add assertion on IsDirty() once implemented
2518
2519 > nodes := make(map[string]*persistencespb.ChasmNode) tree.go
2520 > n.snapshotInternal(exclusiveMinVT, nodes)
2521 >
2522 > return NodesSnapshot{
2523 > Nodes: nodes,
2524 > }
2525 }
2526
2528 exclusiveMinVT *persistencespb.VersionedTransition,
2529 nodes map[string]*persistencespb.ChasmNode,
2530 > ) { tree.go
2531 > if n == nil {
2532 return
2533 }
2534
2535 > if transitionhistory.Compare(n.serializedNode.Metadata.LastUpdateVersionedTransition, exclusiveMinVT) > 0 { tree.go
2536 encodedPath, err := n.getEncodedPath()
2537 if !softassert.That(n.logger, err == nil, "chasm path encoding should always succeed on clean tree") {
2541 }
2542
2543 > for _, childNode := range n.children { tree.go
2544 childNode.snapshotInternal(
2545 exclusiveMinVT,
2952 func (n *Node) findNode(
2953 path []string,
2954 > ) (*Node, bool) { tree.go
2955 > if len(path) == 0 {
2956 > return n, true
2957 > }
2958
2959 childName := path[0]
3042 // and need to be persisted in DB.
3043 // The result will be reset to false after a call to CloseTransaction().
3044 > func (n *Node) IsDirty() bool { tree.go
3045 > if n.IsStateDirty() {
3046 return true
3047 }
3048
3049 > return len(n.systemMutation.UpdatedNodes) > 0 || len(n.systemMutation.DeletedNodes) > 0 tree.go
3050 }
3051
3053 // which need to be persisted to DB AND replicated to other clusters.
3054 // The result will be reset to false after a call to CloseTransaction().
3055 > func (n *Node) IsStateDirty() bool { tree.go
3056 > return n.subtreeIsDirty ||
3057 > len(n.mutation.UpdatedNodes) > 0 ||
3058 > len(n.mutation.DeletedNodes) > 0
3059 > }
3060
3061 func (n *Node) IsStale(
3115
3116 // ArchetypeID returns the framework's internal ID for the root component's fully qualified name.
3117 > func (n *Node) ArchetypeID() ArchetypeID { tree.go
3118 > // Root must be a component.
3119 > return n.root().serializedNode.Metadata.GetComponentAttributes().GetTypeId()
3120 > }
3121
3122 // Archetype returns the root component's fully qualified name.
3136 }
3137
3138 > func (n *Node) root() *Node { tree.go
3139 > if n.parent == nil {
3140 > return n
3141 > }
3142 return n.parent.root()
3143 }
3261 parent *Node,
3262 nodeName string,
3263 > ) *Node { tree.go
3264 > return &Node{
3265 > nodeBase: base,
3266 > parent: parent,
3267 > children: make(map[string]*Node),
3268 > nodeName: nodeName,
3269 > }
3270 > }
3271
3272 func compareSideEffectTasks(a, b *persistencespb.ChasmComponentAttributes_Task) int {
3806 chasmContext Context,
3807 path []string,
3808 > ) (Component, error) { tree.go
3809 > node, ok := n.findNode(path)
3810 > if !ok {
3811 return nil, errComponentNotFound
3812 }
3813
3814 > if err := node.prepareComponentValue(chasmContext); err != nil { tree.go
3815 return nil, err
3816 }
3817
3818 > componentValue, ok := node.value.(Component) tree.go
3819 > if !ok {
3820 return nil, softassert.UnexpectedInternalErr(
3821 n.logger,
3824 }
3825
3826 > return componentValue, nil tree.go
3827 }
3828
go.temporal.io/server/common/persistence/size.go 292 covered LOC · 11 ranges

Open complete file

10 state *persistencespb.WorkflowMutableState,
11 historyStatistics *HistoryStatistics,
12 > ) *MutableStateStatistics { size.go
13 > if internalState == nil {
14 return nil
15 }
16
17 > executionInfoSize := sizeOfBlob(internalState.ExecutionInfo) size.go
18 > executionStateSize := sizeOfBlob(internalState.ExecutionState)
19 >
20 > totalActivityCount := state.ExecutionInfo.ActivityCount
21 > activityInfoCount := len(internalState.ActivityInfos)
22 > activityInfoSize := sizeOfInt64BlobMap(internalState.ActivityInfos)
23 >
24 > totalUserTimerCount := state.ExecutionInfo.UserTimerCount
25 > timerInfoCount := len(internalState.TimerInfos)
26 > timerInfoSize := sizeOfStringBlobMap(internalState.TimerInfos)
27 >
28 > totalChildExecutionCount := state.ExecutionInfo.ChildExecutionCount
29 > childExecutionInfoCount := len(internalState.ChildExecutionInfos)
30 > childExecutionInfoSize := sizeOfInt64BlobMap(internalState.ChildExecutionInfos)
31 >
32 > totalRequestCancelExternalCount := state.ExecutionInfo.RequestCancelExternalCount
33 > requestCancelInfoCount := len(internalState.RequestCancelInfos)
34 > requestCancelInfoSize := sizeOfInt64BlobMap(internalState.RequestCancelInfos)
35 >
36 > totalSignalExternalCount := state.ExecutionInfo.SignalExternalCount
37 > signalInfoCount := len(internalState.SignalInfos)
38 > signalInfoSize := sizeOfInt64BlobMap(internalState.SignalInfos)
39 >
40 > totalSignalCount := state.ExecutionInfo.SignalCount
41 > signalRequestIDCount := len(internalState.SignalRequestedIDs)
42 > signalRequestIDSize := sizeOfStringSlice(internalState.SignalRequestedIDs)
43 >
44 > bufferedEventsCount := len(internalState.BufferedEvents)
45 > bufferedEventsSize := sizeOfBlobSlice(internalState.BufferedEvents)
46 >
47 > totalUpdateCount := state.ExecutionInfo.UpdateCount
48 > updateInfoCount := len(state.ExecutionInfo.UpdateInfos)
49 >
50 > chasmTotalSize := sizeOfChasmNodeMap(internalState.ChasmNodes)
51 >
52 > totalSize := executionInfoSize
53 > totalSize += executionStateSize
54 > totalSize += activityInfoSize
55 > totalSize += timerInfoSize
56 > totalSize += childExecutionInfoSize
57 > totalSize += requestCancelInfoSize
58 > totalSize += signalInfoSize
59 > totalSize += signalRequestIDSize
60 > totalSize += bufferedEventsSize
61 > totalSize += chasmTotalSize
62 >
63 > return &MutableStateStatistics{
64 > TotalSize: totalSize,
65 > HistoryStatistics: historyStatistics,
66 >
67 > ExecutionInfoSize: executionInfoSize,
68 > ExecutionStateSize: executionStateSize,
69 >
70 > ActivityInfoSize: activityInfoSize,
71 > ActivityInfoCount: activityInfoCount,
72 > TotalActivityCount: totalActivityCount,
73 >
74 > TimerInfoSize: timerInfoSize,
75 > TimerInfoCount: timerInfoCount,
76 > TotalUserTimerCount: totalUserTimerCount,
77 >
78 > ChildInfoSize: childExecutionInfoSize,
79 > ChildInfoCount: childExecutionInfoCount,
80 > TotalChildExecutionCount: totalChildExecutionCount,
81 >
82 > RequestCancelInfoSize: requestCancelInfoSize,
83 > RequestCancelInfoCount: requestCancelInfoCount,
84 > TotalRequestCancelExternalCount: totalRequestCancelExternalCount,
85 >
86 > SignalInfoSize: signalInfoSize,
87 > SignalInfoCount: signalInfoCount,
88 > TotalSignalExternalCount: totalSignalExternalCount,
89 >
90 > SignalRequestIDSize: signalRequestIDSize,
91 > SignalRequestIDCount: signalRequestIDCount,
92 > TotalSignalCount: totalSignalCount,
93 >
94 > BufferedEventsSize: bufferedEventsSize,
95 > BufferedEventsCount: bufferedEventsCount,
96 >
97 > UpdateInfoCount: updateInfoCount,
98 > TotalUpdateCount: totalUpdateCount,
99 >
100 > ChasmTotalSize: chasmTotalSize,
101 > }
102 }
103
105 mutation *InternalWorkflowMutation,
106 historyStatistics *HistoryStatistics,
107 > ) *MutableStateStatistics { size.go
108 > if mutation == nil {
109 return nil
110 }
111
112 > executionInfoSize := sizeOfBlob(mutation.ExecutionInfoBlob) size.go
113 > executionStateSize := sizeOfBlob(mutation.ExecutionStateBlob)
114 >
115 > totalActivityCount := mutation.ExecutionInfo.ActivityCount
116 > activityInfoCount := len(mutation.UpsertActivityInfos)
117 > activityInfoCount += len(mutation.DeleteActivityInfos)
118 > activityInfoSize := sizeOfInt64BlobMap(mutation.UpsertActivityInfos)
119 > activityInfoSize += sizeOfInt64Set(mutation.DeleteActivityInfos)
120 >
121 > totalUserTimerCount := mutation.ExecutionInfo.UserTimerCount
122 > timerInfoCount := len(mutation.UpsertTimerInfos)
123 > timerInfoCount += len(mutation.DeleteTimerInfos)
124 > timerInfoSize := sizeOfStringBlobMap(mutation.UpsertTimerInfos)
125 > timerInfoSize += sizeOfStringSet(mutation.DeleteTimerInfos)
126 >
127 > totalChildExecutionCount := mutation.ExecutionInfo.ChildExecutionCount
128 > childExecutionInfoCount := len(mutation.UpsertChildExecutionInfos)
129 > childExecutionInfoCount += len(mutation.DeleteChildExecutionInfos)
130 > childExecutionInfoSize := sizeOfInt64BlobMap(mutation.UpsertChildExecutionInfos)
131 > childExecutionInfoSize += sizeOfInt64Set(mutation.DeleteChildExecutionInfos)
132 >
133 > totalRequestCancelExternalCount := mutation.ExecutionInfo.RequestCancelExternalCount
134 > requestCancelInfoCount := len(mutation.UpsertRequestCancelInfos)
135 > requestCancelInfoCount += len(mutation.DeleteRequestCancelInfos)
136 > requestCancelInfoSize := sizeOfInt64BlobMap(mutation.UpsertRequestCancelInfos)
137 > requestCancelInfoSize += sizeOfInt64Set(mutation.DeleteRequestCancelInfos)
138 >
139 > totalSignalExternalCount := mutation.ExecutionInfo.SignalExternalCount
140 > signalInfoCount := len(mutation.UpsertSignalInfos)
141 > signalInfoCount += len(mutation.DeleteSignalInfos)
142 > signalInfoSize := sizeOfInt64BlobMap(mutation.UpsertSignalInfos)
143 > signalInfoSize += sizeOfInt64Set(mutation.DeleteSignalInfos)
144 >
145 > totalSignalCount := mutation.ExecutionInfo.SignalCount
146 > signalRequestIDCount := len(mutation.UpsertSignalRequestedIDs)
147 > signalRequestIDCount += len(mutation.DeleteSignalRequestedIDs)
148 > signalRequestIDSize := sizeOfStringSet(mutation.UpsertSignalRequestedIDs)
149 > signalRequestIDSize += sizeOfStringSet(mutation.DeleteSignalRequestedIDs)
150 >
151 > totalUpdateCount := mutation.ExecutionInfo.UpdateCount
152 > updateInfoCount := len(mutation.ExecutionInfo.UpdateInfos)
153 >
154 > bufferedEventsCount := 0
155 > bufferedEventsSize := 0
156 > if mutation.NewBufferedEvents != nil {
157 bufferedEventsCount = 1
158 bufferedEventsSize = mutation.NewBufferedEvents.Size()
159 }
160
161 > taskCountByCategory := taskCountsByCategory(&mutation.Tasks) size.go
162 >
163 > chasmTotalSize := sizeOfChasmNodeMap(mutation.UpsertChasmNodes)
164 > chasmTotalSize += sizeOfStringSet(mutation.DeleteChasmNodes)
165 >
166 > // TODO what about checksum?
167 >
168 > totalSize := executionInfoSize
169 > totalSize += executionStateSize
170 > totalSize += activityInfoSize
171 > totalSize += timerInfoSize
172 > totalSize += childExecutionInfoSize
173 > totalSize += requestCancelInfoSize
174 > totalSize += signalInfoSize
175 > totalSize += signalRequestIDSize
176 > totalSize += bufferedEventsSize
177 > totalSize += chasmTotalSize
178 >
179 > return &MutableStateStatistics{
180 > TotalSize: totalSize,
181 > HistoryStatistics: historyStatistics,
182 >
183 > ExecutionInfoSize: executionInfoSize,
184 > ExecutionStateSize: executionStateSize,
185 >
186 > ActivityInfoSize: activityInfoSize,
187 > ActivityInfoCount: activityInfoCount,
188 > TotalActivityCount: totalActivityCount,
189 >
190 > TimerInfoSize: timerInfoSize,
191 > TimerInfoCount: timerInfoCount,
192 > TotalUserTimerCount: totalUserTimerCount,
193 >
194 > ChildInfoSize: childExecutionInfoSize,
195 > ChildInfoCount: childExecutionInfoCount,
196 > TotalChildExecutionCount: totalChildExecutionCount,
197 >
198 > RequestCancelInfoSize: requestCancelInfoSize,
199 > RequestCancelInfoCount: requestCancelInfoCount,
200 > TotalRequestCancelExternalCount: totalRequestCancelExternalCount,
201 >
202 > SignalInfoSize: signalInfoSize,
203 > SignalInfoCount: signalInfoCount,
204 > TotalSignalExternalCount: totalSignalExternalCount,
205 >
206 > SignalRequestIDSize: signalRequestIDSize,
207 > SignalRequestIDCount: signalRequestIDCount,
208 > TotalSignalCount: totalSignalCount,
209 >
210 > BufferedEventsSize: bufferedEventsSize,
211 > BufferedEventsCount: bufferedEventsCount,
212 >
213 > TaskCountByCategory: taskCountByCategory,
214 >
215 > TotalUpdateCount: totalUpdateCount,
216 > UpdateInfoCount: updateInfoCount,
217 >
218 > ChasmTotalSize: chasmTotalSize,
219 > }
220 }
221
222 > func taskCountsByCategory(t *map[tasks.Category][]InternalHistoryTask) map[string]int { size.go
223 > counts := make(map[string]int)
224 > for category, tasks := range *t {
225 > counts[category.Name()] = len(tasks) size.go
226 > }
227 > return counts size.go
228 }
229
231 snapshot *InternalWorkflowSnapshot,
232 historyStatistics *HistoryStatistics,
233 > ) *MutableStateStatistics { size.go
234 > if snapshot == nil {
235 > return nil size.go
236 > }
237
238 > executionInfoSize := sizeOfBlob(snapshot.ExecutionInfoBlob) size.go
239 > executionStateSize := sizeOfBlob(snapshot.ExecutionStateBlob)
240 >
241 > totalActivityCount := snapshot.ExecutionInfo.ActivityCount
242 > activityInfoCount := len(snapshot.ActivityInfos)
243 > activityInfoSize := sizeOfInt64BlobMap(snapshot.ActivityInfos)
244 >
245 > totalUserTimerCount := snapshot.ExecutionInfo.UserTimerCount
246 > timerInfoCount := len(snapshot.TimerInfos)
247 > timerInfoSize := sizeOfStringBlobMap(snapshot.TimerInfos)
248 >
249 > totalChildExecutionCount := snapshot.ExecutionInfo.ChildExecutionCount
250 > childExecutionInfoCount := len(snapshot.ChildExecutionInfos)
251 > childExecutionInfoSize := sizeOfInt64BlobMap(snapshot.ChildExecutionInfos)
252 >
253 > totalRequestCancelExternalCount := snapshot.ExecutionInfo.RequestCancelExternalCount
254 > requestCancelInfoCount := len(snapshot.RequestCancelInfos)
255 > requestCancelInfoSize := sizeOfInt64BlobMap(snapshot.RequestCancelInfos)
256 >
257 > totalSignalExternalCount := snapshot.ExecutionInfo.SignalExternalCount
258 > signalInfoCount := len(snapshot.SignalInfos)
259 > signalInfoSize := sizeOfInt64BlobMap(snapshot.SignalInfos)
260 >
261 > totalSignalCount := snapshot.ExecutionInfo.SignalCount
262 > signalRequestIDCount := len(snapshot.SignalRequestedIDs)
263 > signalRequestIDSize := sizeOfStringSet(snapshot.SignalRequestedIDs)
264 >
265 > totalUpdateCount := snapshot.ExecutionInfo.UpdateCount
266 > updateInfoCount := len(snapshot.ExecutionInfo.UpdateInfos)
267 >
268 > bufferedEventsCount := 0
269 > bufferedEventsSize := 0
270 >
271 > chasmTotalSize := sizeOfChasmNodeMap(snapshot.ChasmNodes)
272 >
273 > totalSize := executionInfoSize
274 > totalSize += executionStateSize
275 > totalSize += activityInfoSize
276 > totalSize += timerInfoSize
277 > totalSize += childExecutionInfoSize
278 > totalSize += requestCancelInfoSize
279 > totalSize += signalInfoSize
280 > totalSize += signalRequestIDSize
281 > totalSize += bufferedEventsSize
282 > totalSize += chasmTotalSize
283 >
284 > taskCountByCategory := taskCountsByCategory(&snapshot.Tasks)
285 >
286 > return &MutableStateStatistics{
287 > TotalSize: totalSize,
288 > HistoryStatistics: historyStatistics,
289 >
290 > ExecutionInfoSize: executionInfoSize,
291 > ExecutionStateSize: executionStateSize,
292 >
293 > ActivityInfoSize: activityInfoSize,
294 > ActivityInfoCount: activityInfoCount,
295 > TotalActivityCount: totalActivityCount,
296 >
297 > TimerInfoSize: timerInfoSize,
298 > TimerInfoCount: timerInfoCount,
299 > TotalUserTimerCount: totalUserTimerCount,
300 >
301 > ChildInfoSize: childExecutionInfoSize,
302 > ChildInfoCount: childExecutionInfoCount,
303 > TotalChildExecutionCount: totalChildExecutionCount,
304 >
305 > RequestCancelInfoSize: requestCancelInfoSize,
306 > RequestCancelInfoCount: requestCancelInfoCount,
307 > TotalRequestCancelExternalCount: totalRequestCancelExternalCount,
308 >
309 > SignalInfoSize: signalInfoSize,
310 > SignalInfoCount: signalInfoCount,
311 > TotalSignalExternalCount: totalSignalExternalCount,
312 >
313 > SignalRequestIDSize: signalRequestIDSize,
314 > SignalRequestIDCount: signalRequestIDCount,
315 > TotalSignalCount: totalSignalCount,
316 >
317 > BufferedEventsSize: bufferedEventsSize,
318 > BufferedEventsCount: bufferedEventsCount,
319 >
320 > TaskCountByCategory: taskCountByCategory,
321 >
322 > TotalUpdateCount: totalUpdateCount,
323 > UpdateInfoCount: updateInfoCount,
324 >
325 > ChasmTotalSize: chasmTotalSize,
326 > }
327 }
go.temporal.io/server/service/history/api/respondworkflowtaskcompleted/api.go 288 covered LOC · 57 ranges

Open complete file

81 matchingClient matchingservice.MatchingServiceClient,
82 versionCache worker_versioning.VersionMembershipAndReactivationStatusCache,
83 > ) *WorkflowTaskCompletedHandler { api.go
84 > return &WorkflowTaskCompletedHandler{
85 > config: shardContext.GetConfig(),
86 > shardContext: shardContext,
87 > workflowConsistencyChecker: workflowConsistencyChecker,
88 > timeSource: shardContext.GetTimeSource(),
89 > namespaceRegistry: shardContext.GetNamespaceRegistry(),
90 > eventNotifier: eventNotifier,
91 > tokenSerializer: tokenSerializer,
92 > metricsHandler: shardContext.GetMetricsHandler(),
93 > logger: shardContext.GetLogger(),
94 > throttledLogger: shardContext.GetThrottledLogger(),
95 > commandAttrValidator: api.NewCommandAttrValidator(
96 > shardContext.GetNamespaceRegistry(),
97 > shardContext.GetConfig(),
98 > searchAttributesValidator,
99 > ),
100 > searchAttributesMapperProvider: shardContext.GetSearchAttributesMapperProvider(),
101 > searchAttributesValidator: searchAttributesValidator,
102 > persistenceVisibilityMgr: visibilityManager,
103 > commandHandlerRegistry: commandHandlerRegistry,
104 > chasmWorkflowRegistry: chasmWorkflowRegistry,
105 > matchingClient: matchingClient,
106 > versionCache: versionCache,
107 > }
108 > }
109
110 //nolint:revive // cyclomatic complexity
112 ctx context.Context,
113 req *historyservice.RespondWorkflowTaskCompletedRequest,
114 > ) (_ *historyservice.RespondWorkflowTaskCompletedResponse, retError error) { api.go
115 > // By default, retError is passed to workflow lease release method in deferred function.
116 > // If error is passed, then workflow context and mutable state are cleared.
117 > // If no changes to mutable state are made or changes already persisted (in memory version corresponds to the database),
118 > // then the lease is released without an error, i.e. workflow context and mutable state are NOT cleared.
119 > releaseLeaseWithError := true
120 >
121 > request := req.CompleteRequest
122 > token, err0 := handler.tokenSerializer.Deserialize(request.TaskToken)
123 > if err0 != nil {
124 return nil, consts.ErrDeserializingToken
125 }
126
127 > namespaceEntry, err := api.GetActiveNamespace(handler.shardContext, namespace.ID(req.GetNamespaceId()), token.WorkflowId) api.go
128 > if err != nil {
129 return nil, err
130 }
131
132 > workflowLease, err := handler.workflowConsistencyChecker.GetWorkflowLeaseWithConsistencyCheck( api.go
133 > ctx,
134 > token.Clock,
135 > func(mutableState historyi.MutableState) bool {
136 > workflowTask := mutableState.GetWorkflowTaskByID(token.GetScheduledEventId()) api.go
137 > if workflowTask == nil && token.GetScheduledEventId() >= mutableState.GetNextEventID() {
138 metrics.StaleMutableStateCounter.With(handler.metricsHandler).Record(
139 1,
141 return false
142 }
143 > return true api.go
144 },
145 definition.NewWorkflowKey(
150 locks.PriorityHigh,
151 )
152 > if err != nil { api.go
153 return nil, err
154 }
155 > weContext := workflowLease.GetContext() api.go
156 > ms := workflowLease.GetMutableState()
157 > currentWorkflowTask := ms.GetWorkflowTaskByID(token.GetScheduledEventId())
158 >
159 > if len(request.Commands) == 0 {
160 // Context metadata is automatically set during mutable state transaction close. For RespondWorkflowTaskCompleted
161 // with no commands (e.g., workflow task heartbeat or only readonly messages like `update.Rejection`), the transaction
164 }
165
166 > defer func() { api.go
167 > var errForRelease error
168 > if releaseLeaseWithError {
169 > // If the workflow context needs to be cleared, operation error passed to Release func (default). api.go
170 > // Otherwise, leave it nil here to avoid clearing the workflow context (but still return error to the caller).
171 > errForRelease = retError
172 > }
173 > if retError != nil && currentWorkflowTask != nil && currentWorkflowTask.Type == enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE && ms.IsStickyTaskQueueSet() { api.go
174 // If, while completing WFT, error is occurred and returned to the worker then worker will clear its cache.
175 // New WFT will also be created on sticky task queue and sent to worker.
197 }
198
199 > workflowLease.GetReleaseFn()(errForRelease) api.go
200 }()
201
202 > if !ms.IsWorkflowExecutionRunning() || api.go
203 > currentWorkflowTask == nil ||
204 > currentWorkflowTask.StartedEventID == common.EmptyEventID ||
205 > (token.StartedEventId != common.EmptyEventID && token.StartedEventId != currentWorkflowTask.StartedEventID) ||
206 > (token.StartedTime != nil && !currentWorkflowTask.StartedTime.IsZero() && !token.StartedTime.AsTime().Equal(currentWorkflowTask.StartedTime)) ||
207 > currentWorkflowTask.Attempt != token.Attempt ||
208 > (token.Version != common.EmptyVersion && token.Version != currentWorkflowTask.Version) {
209 // Mutable state wasn't changed yet and doesn't have to be cleared.
210 releaseLeaseWithError = false
213
214 // We don't accept the request to create a new workflow task if the workflow is paused.
215 > if ms.IsWorkflowExecutionStatusPaused() && request.GetForceCreateNewWorkflowTask() { api.go
216 // Mutable state wasn't changed yet and doesn't have to be cleared.
217 releaseLeaseWithError = false
219 }
220
221 > behavior := request.GetVersioningBehavior() api.go
222 > deployment := worker_versioning.DeploymentFromDeploymentVersion(worker_versioning.DeploymentVersionFromOptions(request.GetDeploymentOptions()))
223 > //nolint:staticcheck // SA1019 deprecated Deployment will clean up later
224 > if behavior != enumspb.VERSIONING_BEHAVIOR_UNSPECIFIED && request.GetDeployment() == nil &&
225 > (request.GetDeploymentOptions() == nil || request.GetDeploymentOptions().GetWorkerVersioningMode() != enumspb.WORKER_VERSIONING_MODE_VERSIONED) {
226 // Mutable state wasn't changed yet and doesn't have to be cleared.
227 releaseLeaseWithError = false
229 }
230
231 > assignedBuildId := ms.GetAssignedBuildId() api.go
232 > wftCompletedBuildId := request.GetWorkerVersionStamp().GetBuildId()
233 > if assignedBuildId != "" && !ms.IsStickyTaskQueueSet() {
234 // Worker versioning is used, make sure the task was completed by the right build ID, unless we're using a
235 // sticky queue in which case Matching will not send the build ID until old versioning is cleaned up
243 }
244
245 > var effects effect.Buffer api.go
246 > defer func() {
247 > // `effects` are canceled immediately on WFT failure or persistence errors.
248 > // This `defer` handles rare cases where an error is returned but the cancellation didn't happen.
249 > if retError != nil {
250 cancelled := effects.Cancel(ctx)
251 if cancelled {
261 // TODO(carlydf): change condition when deprecating versionstamp
262 // It's an error if the workflow has used versioning in the past but this task has no versioning info.
263 > if ms.GetMostRecentWorkerVersionStamp().GetUseVersioning() && api.go
264 > //nolint:staticcheck // SA1019 deprecated stamp will clean up later
265 > !request.GetWorkerVersionStamp().GetUseVersioning() &&
266 > request.GetDeploymentOptions().GetWorkerVersioningMode() != enumspb.WORKER_VERSIONING_MODE_VERSIONED &&
267 > // This check is not needed for V3 versioning
268 > ms.GetEffectiveVersioningBehavior() == enumspb.VERSIONING_BEHAVIOR_UNSPECIFIED {
269 // Mutable state wasn't changed yet and doesn't have to be cleared.
270 releaseLeaseWithError = false
272 }
273
274 > nsName := namespaceEntry.Name().String() api.go
275 >
276 > // When pagination is enabled, buffer intermediate pages and merge them into the final page
277 > // before continuing through the normal workflow task completion path.
278 > paginationResp, mergedCommands, err := handler.applyTaskCompletionPagination(weContext, token, request, nsName)
279 > // In case of a buffer overflow fall through and fail the workflow task below
280 > paginationOverflow := errors.Is(err, workflow.ErrTaskCompletionBufferSizeExceeded)
281 > if !paginationOverflow && (paginationResp != nil || err != nil) {
282 releaseLeaseWithError = false
283 return paginationResp, err
286 // `commands` is the effective list of commands to execute including ones from
287 // paginated requests. `request.Commands` is left unchanged.
288 > commands := request.Commands api.go
289 > if len(mergedCommands) > 0 {
290 commands = append(mergedCommands, request.Commands...)
291 }
292
293 > limits := historyi.WorkflowTaskCompletionLimits{ api.go
294 > MaxResetPoints: handler.config.MaxAutoResetPoints(nsName),
295 > MaxSearchAttributeValueSize: handler.config.SearchAttributesSizeOfValueLimit(nsName),
296 > }
297 > // TODO: this metric is inaccurate, it should only be emitted if a new binary checksum (or build ID) is added in this completion.
298 > if ms.GetExecutionInfo().AutoResetPoints != nil && limits.MaxResetPoints == len(ms.GetExecutionInfo().AutoResetPoints.Points) {
299 metrics.AutoResetPointsLimitExceededCounter.With(handler.metricsHandler).Record(
300 1,
302 }
303
304 > var wtHeartbeatTimedOut bool api.go
305 > var completedEvent *historypb.HistoryEvent
306 >
307 > // SDKs set ForceCreateNewWorkflowTask flag to true when they are doing WT heartbeats.
308 > // In a mean time, there might be pending commands and messages on the worker side.
309 > // If those commands/messages are sent on the heartbeat WT it means that WF is making progress.
310 > // WT heartbeat timeout is applicable only when WF doesn't make any progress and does heartbeats only.
311 > checkWTHeartbeatTimeout := request.GetForceCreateNewWorkflowTask() && len(commands) == 0 && len(request.Messages) == 0
312 >
313 > if checkWTHeartbeatTimeout {
314 // WorkflowTaskHeartbeatTimeout is a total duration for which workflow is allowed to send continuous heartbeats.
315 // Default is 30 minutes.
336 }
337 // WT wasn't timed out (due to too many heartbeats), therefore WTCompleted event should be created.
338 > if !wtHeartbeatTimedOut { api.go
339 > completedEvent, err = ms.AddWorkflowTaskCompletedEvent(currentWorkflowTask, request, limits) api.go
340 > if err != nil {
341 return nil, err
342 }
345 // See workflowTaskStateMachine.skipWorkflowTaskCompletedEvent for more details.
346
347 > if request.StickyAttributes == nil || request.StickyAttributes.WorkerTaskQueue == nil { api.go
348 metrics.CompleteWorkflowTaskWithStickyDisabledCounter.With(handler.metricsHandler).Record(
349 1,
350 metrics.OperationTag(metrics.HistoryRespondWorkflowTaskCompletedScope))
351 ms.ClearStickyTaskQueue()
352 > } else { api.go
353 > metrics.CompleteWorkflowTaskWithStickyEnabledCounter.With(handler.metricsHandler).Record( api.go
354 > 1,
355 > metrics.OperationTag(metrics.HistoryRespondWorkflowTaskCompletedScope))
356 > if (assignedBuildId == "" || assignedBuildId == wftCompletedBuildId) &&
357 > (ms.GetDeploymentTransition() == nil || ms.GetDeploymentTransition().GetDeployment().Equal(deployment)) {
358 > // TODO: clean up. this is not applicable to V3
359 > // For versioned workflows, only set sticky queue if the WFT is completed by the WF's current build ID.
360 > // It is possible that the WF has been redirected to another build ID since this WFT started, in that case
361 > // we should not set sticky queue of the old build ID and keep the normal queue to let Matching send the
362 > // next WFT to the right build ID.
363 > ms.SetStickyTaskQueue(request.StickyAttributes.WorkerTaskQueue.GetName(), request.StickyAttributes.GetScheduleToStartTimeout())
364 > }
365 }
366
367 > var ( api.go
368 > wtFailedCause *workflowTaskFailedCause
369 > activityNotStartedCancelled bool
370 > newMutableState historyi.MutableState
371 > responseMutations []workflowTaskResponseMutation
372 > )
373 > updateRegistry := weContext.UpdateRegistry(ctx)
374 > // hasBufferedEventsOrMessages indicates if there are any buffered events
375 > // or admitted updates which should generate a new workflow task.
376 >
377 > // TODO: HasOutgoingMessages call (=check for admitted updates) is comment out
378 > // because non-durable admitted updates can't block WF from closing,
379 > // because everytime WFT is failing, WF context is cleared together with update registry
380 > // and admitted updates are lost. Uncomment this check when durable admitted is implemented
381 > // or updates stay in the registry after WFT is failed.
382 > hasBufferedEventsOrMessages := ms.HasBufferedEvents() // || updateRegistry.HasOutgoingMessages(false)
383 > if paginationOverflow {
384 // Per-workflow completion buffer overflowed: terminate the workflow
385 wtFailedCause = newWorkflowTaskFailedCause(
388 "workflow task completion buffer size exceeds the per-workflow limit"),
389 true)
390 > } else if err := namespaceEntry.VerifyBinaryChecksum(request.GetBinaryChecksum()); err != nil { //nolint:staticcheck // SA1019 deprecated stamp will clean up later api.go
391 wtFailedCause = newWorkflowTaskFailedCause(
392 enumspb.WORKFLOW_TASK_FAILED_CAUSE_BAD_BINARY,
396 request.GetBinaryChecksum()),
397 false)
398 > } else { api.go
399 > namespace := namespaceEntry.Name() api.go
400 > workflowSizeChecker := newWorkflowSizeChecker(
401 > workflowSizeLimits{
402 > blobSizeLimitWarn: handler.config.BlobSizeLimitWarn(namespace.String()),
403 > blobSizeLimitError: handler.config.BlobSizeLimitError(namespace.String()),
404 > memoSizeLimitWarn: handler.config.MemoSizeLimitWarn(namespace.String()),
405 > memoSizeLimitError: handler.config.MemoSizeLimitError(namespace.String()),
406 > numPendingChildExecutionsLimit: handler.config.NumPendingChildExecutionsLimit(namespace.String()),
407 > numPendingActivitiesLimit: handler.config.NumPendingActivitiesLimit(namespace.String()),
408 > numPendingSignalsLimit: handler.config.NumPendingSignalsLimit(namespace.String()),
409 > numPendingCancelsRequestLimit: handler.config.NumPendingCancelsRequestLimit(namespace.String()),
410 > },
411 > ms,
412 > handler.searchAttributesValidator,
413 > handler.metricsHandler.WithTags(
414 > metrics.OperationTag(metrics.HistoryRespondWorkflowTaskCompletedScope),
415 > metrics.NamespaceTag(namespace.String()),
416 > ),
417 > handler.throttledLogger,
418 > )
419 >
420 > workflowTaskHandler := newWorkflowTaskCompletedHandler(
421 > request.GetIdentity(),
422 > request.GetWorkerControlTaskQueue(),
423 > completedEvent.GetEventId(), // If completedEvent is nil, then GetEventId() returns 0 and this value shouldn't be used in workflowTaskHandler.
424 > ms,
425 > updateRegistry,
426 > &effects,
427 > handler.commandAttrValidator,
428 > workflowSizeChecker,
429 > handler.logger,
430 > handler.namespaceRegistry,
431 > handler.metricsHandler,
432 > handler.config,
433 > handler.shardContext,
434 > handler.searchAttributesMapperProvider,
435 > hasBufferedEventsOrMessages,
436 > handler.commandHandlerRegistry,
437 > handler.chasmWorkflowRegistry,
438 > handler.matchingClient,
439 > handler.versionCache,
440 > )
441 >
442 > if responseMutations, err = workflowTaskHandler.handleCommands(
443 > ctx,
444 > commands,
445 > collection.NewIndexedTakeList(
446 > request.Messages,
447 > func(msg *protocolpb.Message) string { return msg.Id },
448 ),
449 ); err != nil {
455 // If worker ignored the update request (old SDK or SDK bug), then server rejects this update.
456 // Otherwise, this update will be delivered (and new WT created) again and again.
457 > workflowTaskHandler.rejectUnprocessedUpdates( api.go
458 > ctx,
459 > currentWorkflowTask.ScheduledEventID,
460 > request.GetForceCreateNewWorkflowTask(),
461 > weContext.GetWorkflowKey(),
462 > request.GetIdentity(),
463 > )
464 >
465 > // If the Workflow completed itself, but there are still accepted
466 > // (but not completed) Updates, they need to be aborted.
467 > // Reason is always "WorkflowCompleted" because accepted Updates
468 > // are not moving to continuing runs (if any).
469 > if !ms.IsWorkflowExecutionRunning() {
470 > updateRegistry.AbortAccepted(update.AbortReasonWorkflowCompleted, &effects) api.go
471 > }
472
473 // set the vars used by following logic
474 // further refactor should also clean up the vars used below
475 > wtFailedCause = workflowTaskHandler.workflowTaskFailedCause api.go
476 >
477 > // failMessage is not used by workflowTaskHandlerCallbacks
478 > activityNotStartedCancelled = workflowTaskHandler.activityNotStartedCancelled
479 > // continueAsNewTimerTasks is not used by workflowTaskHandlerCallbacks
480 >
481 > newMutableState = workflowTaskHandler.newMutableState
482 >
483 > hasBufferedEventsOrMessages = workflowTaskHandler.hasBufferedEventsOrMessages
484 }
485
486 > wtFailedShouldCreateNewTask := false api.go
487 > if wtFailedCause != nil {
488 effects.Cancel(ctx)
489
539 }
540
541 > newWorkflowTaskType := enumsspb.WORKFLOW_TASK_TYPE_UNSPECIFIED api.go
542 > // Do not schedule a new workflow task if the workflow is paused. Accepting the in-flight
543 > // WT completion is intentional (see HistoryBuilder buffering of WORKFLOW_EXECUTION_PAUSED),
544 > // but scheduling a follow-up WT would call ApplyWorkflowTaskScheduledEvent, which resets
545 > // Status to RUNNING while leaving executionInfo.PauseInfo set — desyncing pause state.
546 > // Mirrors the gate in closeTransactionHandleWorkflowTaskScheduling.
547 > if ms.IsWorkflowExecutionRunning() && !ms.IsWorkflowExecutionStatusPaused() {
548 if request.GetForceCreateNewWorkflowTask() || // Heartbeat WT is always of Normal type.
549 wtFailedShouldCreateNewTask ||
565 }
566
567 > bypassTaskGeneration := request.GetReturnNewWorkflowTask() && wtFailedCause == nil api.go
568 > // TODO (alex-update): All current SDKs always set ReturnNewWorkflowTask to true
569 > // which means that server always bypass task generation if WFT didn't fail.
570 > // ReturnNewWorkflowTask flag needs to be removed.
571 >
572 > if newWorkflowTaskType == enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE && !bypassTaskGeneration {
573 // If task generation can't be bypassed (i.e. WFT has failed),
574 // WFT must be created as Normal because speculative WFT by nature skips task generation.
576 }
577
578 > var newWorkflowTask *historyi.WorkflowTaskInfo api.go
579 >
580 > // Speculative workflow task will be created after mutable state is persisted.
581 > if newWorkflowTaskType == enumsspb.WORKFLOW_TASK_TYPE_NORMAL {
582 versioningStamp := request.WorkerVersionStamp
583 if versioningStamp.GetUseVersioning() {
640 }
641
642 > var updateErr error api.go
643 > if newMutableState != nil {
644 newWorkflowExecutionInfo := newMutableState.GetExecutionInfo()
645 newWorkflowExecutionState := newMutableState.GetExecutionState()
661 newMutableState,
662 )
663 > } else { api.go
664 > // If completedEvent is not nil (which means that this WT wasn't speculative)
665 > // OR new WT is normal, then mutable state needs to be persisted.
666 > // Otherwise, (both current and new WT are speculative) mutable state is updated in memory only but not persisted.
667 > if completedEvent != nil || newWorkflowTaskType == enumsspb.WORKFLOW_TASK_TYPE_NORMAL {
668 > updateErr = weContext.UpdateWorkflowExecutionAsActive(ctx, handler.shardContext) api.go
669 > }
670 }
671
672 > if updateErr != nil { api.go
673 effects.Cancel(ctx)
674 if persistence.IsConflictErr(updateErr) {
712 // If mutable state was persisted successfully (or persistence was skipped),
713 // then effects needs to be applied immediately to keep registry and mutable state in sync.
714 > effects.Apply(ctx) api.go
715 >
716 > if !ms.IsWorkflowExecutionRunning() {
717 > // NOTE: It is important to call this *after* applying effects to be sure there are no api.go
718 > // Updates in ProvisionallyCompleted state.
719 >
720 > // Because:
721 > // (1) all unprocessed Updates were already rejected
722 > // (2) all accepted Updates were aborted
723 > // the registry only has: Updates received while this WFT was running (new Updates).
724 > hasNewRun := newMutableState != nil
725 > if hasNewRun {
726 // If a new run was created (e.g. ContinueAsNew, Retry, Cron), then Updates that were
727 // received while this WFT was running are aborted with a retryable error.
728 // Then, the SDK will retry the API call and the Update will land on the new run.
729 updateRegistry.Abort(update.AbortReasonWorkflowContinuing)
730 > } else { api.go
731 > // If the Workflow completed itself via one of the completion commands without
732 > // creating a new run, abort all Updates with a non-retryable error.
733 > updateRegistry.Abort(update.AbortReasonWorkflowCompleted)
734 > }
735 }
736
737 // Create speculative workflow task after mutable state is persisted.
738 > if newWorkflowTaskType == enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE { api.go
739 newWorkflowTask, err = ms.AddWorkflowTaskScheduledEvent(bypassTaskGeneration, newWorkflowTaskType)
740 if err != nil {
765 }
766
767 > handler.handleBufferedQueries(ms, req.GetCompleteRequest().GetQueryResults(), newWorkflowTask != nil, namespaceEntry) api.go
768 >
769 > if wtHeartbeatTimedOut {
770 // Mutable state was already persisted and doesn't need to be cleared although error is returned to the worker.
771 releaseLeaseWithError = false
773 }
774
775 > if wtFailedCause != nil { api.go
776 // Mutable state was already persisted and doesn't need to be cleared although error is returned to the worker.
777 releaseLeaseWithError = false
779 }
780
781 > resp := &historyservice.RespondWorkflowTaskCompletedResponse{} api.go
782 > //nolint:staticcheck
783 > if newWorkflowTask != nil && bypassTaskGeneration {
784 resp.StartedResponse, err = recordworkflowtaskstarted.CreateRecordWorkflowTaskStartedResponse(
785 ctx,
806 // SDK needs to know where to roll back its history event pointer, i.e. after what event all other events needs to be dropped.
807 // SDK uses WorkflowTaskStartedEventID to do that.
808 > if completedEvent == nil { api.go
809 resp.ResetHistoryEventId = ms.GetExecutionInfo().LastCompletedWorkflowTaskStartedEventId
810 }
811
812 > for _, mutation := range responseMutations { api.go
813 if err := mutation(resp); err != nil {
814 return nil, err
816 }
817
818 > return resp, nil api.go
819 }
820
829 request *workflowservice.RespondWorkflowTaskCompletedRequest,
830 nsName string,
831 > ) (resp *historyservice.RespondWorkflowTaskCompletedResponse, mergedCommands []*commandpb.Command, err error) { api.go
832 > if !handler.config.EnableWorkflowTaskCompletionPagination(nsName) {
833 > if request.GetIntermediatePage() || request.GetPageNumber() > 0 { api.go
834 return nil, nil, serviceerror.NewFailedPreconditionf(
835 "workflow task completion pagination is disabled for this namespace %s",
837 )
838 }
839 > return nil, nil, nil api.go
840 }
841
1020 createNewWorkflowTask bool,
1021 namespaceEntry *namespace.Namespace,
1022 > ) { api.go
1023 > queryRegistry := ms.GetQueryRegistry()
1024 > if !queryRegistry.HasBufferedQuery() {
1025 > return api.go
1026 > }
1027
1028 namespaceName := namespaceEntry.Name()
go.temporal.io/server/service/history/fx.go 266 covered LOC · 40 ranges

Open complete file

108 chasmRegistry *chasm.Registry,
109 testHooks testhooks.TestHooks,
110 > ) { fx.go
111 > if hook, ok := testhooks.Get(
112 > testHooks,
113 > testhooks.HistoryChasmRuntimeProvider,
114 > testhooks.GlobalScope,
115 > ); ok {
116 hook(chasmEngine, chasmVisibilityManager, chasmRegistry)
117 }
129 )
130
131 > func ServerProvider(grpcServerOptions []grpc.ServerOption) *grpc.Server { fx.go
132 > return grpc.NewServer(grpcServerOptions...)
133 > }
134
135 > func HistoryServiceServerProvider(handler *Handler) historyservice.HistoryServiceServer { fx.go
136 > return handler
137 > }
138
139 func ServiceResolverProvider(
140 membershipMonitor membership.Monitor,
141 > ) (membership.ServiceResolver, error) { fx.go
142 > return membershipMonitor.GetResolver(primitives.HistoryService)
143 > }
144
145 > func HandlerProvider(args NewHandlerArgs, lc fx.Lifecycle) (*Handler, error) { fx.go
146 > handler := &Handler{
147 > status: common.DaemonStatusInitialized,
148 > config: args.Config,
149 > nexusCompletionHandler: args.NexusCompletionHandler,
150 > tokenSerializer: tasktoken.NewSerializer(),
151 > deepHealthCheckHandler: deepHealthCheckHandler{
152 > healthServer: args.HealthServer,
153 > metricsHandler: args.MetricsHandler,
154 > config: args.Config,
155 > historyHealthSignal: args.HistoryHealthSignal,
156 > persistenceHealthSignal: args.PersistenceHealthSignal,
157 > startupTime: time.Now(),
158 > },
159 > logger: args.Logger,
160 > throttledLogger: args.ThrottledLogger,
161 > persistenceExecutionManager: args.PersistenceExecutionManager,
162 > persistenceShardManager: args.PersistenceShardManager,
163 > persistenceVisibilityManager: args.PersistenceVisibilityManager,
164 > historyServiceResolver: args.HistoryServiceResolver,
165 > metricsHandler: args.MetricsHandler,
166 > payloadSerializer: args.PayloadSerializer,
167 > timeSource: args.TimeSource,
168 > namespaceRegistry: args.NamespaceRegistry,
169 > saProvider: args.SaProvider,
170 > clusterMetadata: args.ClusterMetadata,
171 > archivalMetadata: args.ArchivalMetadata,
172 > hostInfoProvider: args.HostInfoProvider,
173 > controller: args.ShardController,
174 > eventNotifier: args.EventNotifier,
175 > tracer: args.TracerProvider.Tracer(consts.LibraryName),
176 > taskQueueManager: args.TaskQueueManager,
177 > taskCategoryRegistry: args.TaskCategoryRegistry,
178 > dlqMetricsEmitter: args.DLQMetricsEmitter,
179 > chasmEngine: args.ChasmEngine,
180 > chasmRegistry: args.ChasmRegistry,
181 > testHooks: args.TestHooks,
182 >
183 > replicationTaskFetcherFactory: args.ReplicationTaskFetcherFactory,
184 > replicationTaskConverterProvider: args.ReplicationTaskConverterFactory,
185 > streamReceiverMonitor: args.StreamReceiverMonitor,
186 > replicationServerRateLimiter: args.ReplicationServerRateLimiter,
187 > }
188 >
189 > // Build the Nexus handler in OnStart rather than here so that it runs after all
190 > // fx.Invoke functions have completed. If we built it eagerly, the dependency chain
191 > //
192 > // activity.HistoryModule (fx.Invoke)
193 > // → *library → *handler → historyservice.HistoryServiceServer
194 > // → HistoryServiceServerProvider → HandlerProvider (this function)
195 > //
196 > // would force HandlerProvider to run before modules like chasmtests.Module have had
197 > // a chance to register their nexus services via their own fx.Invoke calls. As a
198 > // result, buildNexusHandler would snapshot an empty registry and h.nexusHandler
199 > // would remain nil, causing all StartNexusOperation calls to the system endpoint to
200 > // return "no nexus services registered". OnStart hooks run after ALL invokes are
201 > // done, so the registry is fully populated by the time we call buildNexusHandler.
202 > lc.Append(fx.Hook{
203 > OnStart: func(_ context.Context) error {
204 > h, err := buildNexusHandler(args.ChasmRegistry) fx.go
205 > if err != nil {
206 return err
207 }
208 > handler.nexusHandler = h fx.go
209 > return nil
210 },
211 })
212
213 > return handler, nil fx.go
214 }
215
216 > func buildNexusHandler(chasmRegistry *chasm.Registry) (nexus.Handler, error) { fx.go
217 > nexusServices := chasmRegistry.NexusServices()
218 > if len(nexusServices) == 0 {
219 return nil, nil
220 }
221 > serviceRegistry := nexus.NewServiceRegistry() fx.go
222 > for _, svc := range nexusServices {
223 > // No chance of collision here since the registry would have errored out earlier.
224 > serviceRegistry.MustRegister(svc)
225 > }
226
227 > return serviceRegistry.NewHandler() fx.go
228 }
229
230 func HistoryEngineFactoryProvider(
231 params HistoryEngineFactoryParams,
232 > ) shard.EngineFactory { fx.go
233 > return &historyEngineFactory{
234 > HistoryEngineFactoryParams: params,
235 > }
236 > }
237
238 func ConfigProvider(
239 dc *dynamicconfig.Collection,
240 persistenceConfig config.Persistence,
241 > ) *configs.Config { fx.go
242 > return configs.NewConfig(
243 > dc,
244 > persistenceConfig.NumHistoryShards,
245 > )
246 > }
247
248 func ServiceErrorInterceptorProvider(
249 dc *dynamicconfig.Collection,
250 > ) *interceptor.ServiceErrorInterceptor { fx.go
251 > return interceptor.NewServiceErrorInterceptor(
252 > dynamicconfig.MaxServiceErrorMessageLength.Get(dc),
253 > )
254 > }
255
256 > func ThrottledLoggerRpsFnProvider(serviceConfig *configs.Config) resource.ThrottledLoggerRpsFn { fx.go
257 > return func() float64 { return float64(serviceConfig.ThrottledLogRPS()) }
258 }
259
260 > func RetryableInterceptorProvider() *interceptor.RetryableInterceptor { fx.go
261 > return interceptor.NewRetryableInterceptor(
262 > common.CreateHistoryHandlerRetryPolicy(),
263 > api.IsRetryableError,
264 > )
265 > }
266
267 func ErrorHandlerProvider(
268 logger log.Logger,
269 serviceConfig *configs.Config,
270 > ) *interceptor.RequestErrorHandler { fx.go
271 > return interceptor.NewRequestErrorHandler(
272 > logger,
273 > serviceConfig.LogAllReqErrors,
274 > )
275 > }
276
277 func TelemetryInterceptorProvider(
281 serviceConfig *configs.Config,
282 requestErrorHandler *interceptor.RequestErrorHandler,
283 > ) *interceptor.TelemetryInterceptor { fx.go
284 > return interceptor.NewTelemetryInterceptor(
285 > namespaceRegistry,
286 > metricsHandler,
287 > logger,
288 > serviceConfig.LogAllReqErrors,
289 > requestErrorHandler,
290 > )
291 > }
292
293 func HealthSignalAggregatorProvider(
294 dynamicCollection *dynamicconfig.Collection,
295 logger log.ThrottledLogger,
296 > ) interceptor.HealthSignalAggregator { fx.go
297 > return interceptor.NewHealthSignalAggregator(
298 > logger,
299 > dynamicconfig.HistoryHealthSignalMetricsEnabled.Get(dynamicCollection),
300 > dynamicconfig.HistoryHealthSignalUsePercentiles.Get(dynamicCollection),
301 > dynamicconfig.PersistenceHealthSignalWindowSize.Get(dynamicCollection)(),
302 > dynamicconfig.PersistenceHealthSignalBufferSize.Get(dynamicCollection)(),
303 > dynamicconfig.HistoryHealthSignalLatencyWindowSize.Get(dynamicCollection)(),
304 > dynamicconfig.HistoryHealthSignalLatencyWindowCount.Get(dynamicCollection)(),
305 > )
306 > }
307
308 func HealthCheckInterceptorProvider(
309 healthSignalAggregator interceptor.HealthSignalAggregator,
310 > ) *interceptor.HealthCheckInterceptor { fx.go
311 > return interceptor.NewHealthCheckInterceptor(
312 > healthSignalAggregator,
313 > )
314 > }
315
316 > func ContextMetadataInterceptorProvider(logger log.Logger) *interceptor.ContextMetadataInterceptor { fx.go
317 > return interceptor.NewContextMetadataInterceptor(true, logger)
318 > }
319
320 func HistoryAdditionalInterceptorsProvider(
322 chasmRequestEngineInterceptor *chasm.ChasmEngineInterceptor,
323 chasmRequestVisibilityInterceptor *chasm.ChasmVisibilityInterceptor,
324 > ) []grpc.UnaryServerInterceptor { fx.go
325 > return []grpc.UnaryServerInterceptor{
326 > healthCheckInterceptor.UnaryIntercept,
327 > chasmRequestEngineInterceptor.Intercept,
328 > chasmRequestVisibilityInterceptor.Intercept,
329 > }
330 > }
331
332 func NamespaceRateLimitInterceptorProvider(
334 namespaceRegistry namespace.Registry,
335 metricsHandler metrics.Handler,
336 > ) interceptor.NamespaceRateLimitInterceptor { fx.go
337 >
338 > namespaceRateFn := func(namespaceName string) float64 {
339 > if namespaceRPS := serviceConfig.NamespaceRPS(namespaceName); namespaceRPS > 0 { fx.go
340 return float64(namespaceRPS)
341 }
342 // This fallback to host level rps limit when NamespaceRPS is not configured (i.e. 0)
343 > return float64(serviceConfig.RPS()) fx.go
344 }
345
346 > return interceptor.NewNamespaceRateLimitInterceptor( fx.go
347 > namespaceRegistry,
348 > configs.NewNamespaceRateLimiter(
349 > namespaceRateFn,
350 > serviceConfig.OperatorRPSRatio,
351 > ),
352 > map[string]int{}, // no token overrides
353 > map[string]struct{}{}, // no long polls on history service
354 > dynamicconfig.GetBoolPropertyFnFilteredByNamespace(false), // no long poll methods
355 > metricsHandler,
356 > )
357 }
358
359 func RateLimitInterceptorProvider(
360 serviceConfig *configs.Config,
361 > ) *interceptor.RateLimitInterceptor { fx.go
362 > return interceptor.NewRateLimitInterceptor(
363 > configs.NewPriorityRateLimiter(func() float64 { return float64(serviceConfig.RPS()) }, serviceConfig.OperatorRPSRatio),
364 map[string]int{
365 healthpb.Health_Check_FullMethodName: 0, // exclude health check requests from rate limiting.
371 func ESProcessorConfigProvider(
372 serviceConfig *configs.Config,
373 > ) *elasticsearch.ProcessorConfig { fx.go
374 > return &elasticsearch.ProcessorConfig{
375 > IndexerConcurrency: serviceConfig.IndexerConcurrency,
376 > ESProcessorNumOfWorkers: serviceConfig.ESProcessorNumOfWorkers,
377 > ESProcessorBulkActions: serviceConfig.ESProcessorBulkActions,
378 > ESProcessorBulkSize: serviceConfig.ESProcessorBulkSize,
379 > ESProcessorFlushInterval: serviceConfig.ESProcessorFlushInterval,
380 > ESProcessorAckTimeout: serviceConfig.ESProcessorAckTimeout,
381 > }
382 > }
383
384 func PersistenceRateLimitingParamsProvider(
387 ownershipBasedQuotaScaler shard.LazyLoadedOwnershipBasedQuotaScaler,
388 logger log.SnTaggedLogger,
389 > ) service.PersistenceRateLimitingParams { fx.go
390 > hostCalculator := calculator.NewLoggedCalculator(
391 > shard.NewOwnershipAwareQuotaCalculator(
392 > ownershipBasedQuotaScaler,
393 > persistenceLazyLoadedServiceResolver,
394 > serviceConfig.PersistenceMaxQPS,
395 > serviceConfig.PersistenceGlobalMaxQPS,
396 > ),
397 > log.With(logger, tag.ComponentPersistence, tag.ScopeHost),
398 > )
399 > namespaceCalculator := calculator.NewLoggedNamespaceCalculator(
400 > shard.NewOwnershipAwareNamespaceQuotaCalculator(
401 > ownershipBasedQuotaScaler,
402 > persistenceLazyLoadedServiceResolver,
403 > serviceConfig.PersistenceNamespaceMaxQPS,
404 > serviceConfig.PersistenceGlobalNamespaceMaxQPS,
405 > ),
406 > log.With(logger, tag.ComponentPersistence, tag.ScopeNamespace),
407 > )
408 > return service.PersistenceRateLimitingParams{
409 > PersistenceMaxQps: func() int {
410 > return int(hostCalculator.GetQuota())
411 > },
412 > PersistenceNamespaceMaxQps: func(namespace string) int { fx.go
413 > return int(namespaceCalculator.GetQuota(namespace))
414 > },
415 PersistencePerShardNamespaceMaxQPS: persistenceClient.PersistencePerShardNamespaceMaxQPS(serviceConfig.PersistencePerShardNamespaceMaxQPS),
416 OperatorRPSRatio: persistenceClient.OperatorRPSRatio(serviceConfig.OperatorRPSRatio),
433 chasmRegistry *chasm.Registry,
434 serializer serialization.Serializer,
435 > ) (manager.VisibilityManager, error) { fx.go
436 > return visibility.NewManager(
437 > *persistenceConfig,
438 > persistenceServiceResolver,
439 > customVisibilityStoreFactory,
440 > esProcessorConfig,
441 > saProvider,
442 > searchAttributesMapperProvider,
443 > namespaceRegistry,
444 > chasmRegistry,
445 > serviceConfig.VisibilityPersistenceMaxReadQPS,
446 > serviceConfig.VisibilityPersistenceMaxWriteQPS,
447 > serviceConfig.OperatorRPSRatio,
448 > serviceConfig.VisibilityPersistenceSlowQueryThreshold,
449 > serviceConfig.EnableReadFromSecondaryVisibility,
450 > serviceConfig.VisibilityEnableShadowReadMode,
451 > serviceConfig.SecondaryVisibilityWritingMode,
452 > serviceConfig.VisibilityDisableOrderByClause,
453 > serviceConfig.VisibilityEnableManualPagination,
454 > serviceConfig.VisibilityEnableUnifiedQueryConverter,
455 > metricsHandler,
456 > logger,
457 > serializer,
458 > )
459 > }
460
461 func ChasmVisibilityManagerProvider(
475 metricsHandler metrics.Handler,
476 config *configs.Config,
477 > ) events.Notifier { fx.go
478 > return events.NewNotifier(
479 > timeSource,
480 > metricsHandler,
481 > config.GetShardID,
482 > )
483 > }
484
485 > func ServiceLifetimeHooks(lc fx.Lifecycle, svc *Service) { fx.go
486 > lc.Append(fx.StartStopHook(svc.Start, svc.Stop))
487 > }
488
489 func ReplicationProgressCacheProvider(
491 logger log.Logger,
492 handler metrics.Handler,
493 > ) replication.ProgressCache { fx.go
494 > return replication.NewProgressCache(serviceConfig, logger, handler)
495 > }
496
497 func VersionMembershipCacheProvider(
499 serviceConfig *configs.Config,
500 metricsHandler metrics.Handler,
501 > ) worker_versioning.VersionMembershipAndReactivationStatusCache { fx.go
502 > c := commoncache.New(serviceConfig.VersionMembershipCacheMaxSize(), &commoncache.Options{
503 > TTL: max(1*time.Second, serviceConfig.VersionMembershipCacheTTL()),
504 > })
505 > lc.Append(fx.Hook{
506 > OnStop: func(context.Context) error {
507 > c.Stop() fx.go
508 > return nil
509 > },
510 })
511 > return worker_versioning.NewVersionMembershipAndReactivationStatusCache(c, metricsHandler) fx.go
512 }
513
516 serviceConfig *configs.Config,
517 metricsHandler metrics.Handler,
518 > ) worker_versioning.RoutingInfoCache { fx.go
519 > c := commoncache.New(serviceConfig.RoutingInfoCacheMaxSize(), &commoncache.Options{
520 > TTL: max(1*time.Second, serviceConfig.RoutingInfoCacheTTL()),
521 > })
522 > lc.Append(fx.Hook{
523 > OnStop: func(context.Context) error {
524 > c.Stop() fx.go
525 > return nil
526 > },
527 })
528 > return worker_versioning.NewRoutingInfoCache(c, metricsHandler) fx.go
529 }
go.temporal.io/server/service/matching/matcher_data.go 259 covered LOC · 75 ranges

Open complete file

68
69 // implements heap.Interface
70 > func (p *pollerPQ) Len() int { matcher_data.go
71 > return len(p.heap)
72 > }
73
74 // implements heap.Interface, do not call directly
75 > func (p *pollerPQ) Less(i int, j int) bool { matcher_data.go
76 > a, b := p.heap[i], p.heap[j]
77 > // task forwarders/validators have lower priority than local polls
78 > aIsForwarder := a.taskForwarderType != notTaskForwarder
79 > bIsForwarder := b.taskForwarderType != notTaskForwarder
80 > if !aIsForwarder && bIsForwarder {
81 > return true matcher_data.go
82 > } else if aIsForwarder && !bIsForwarder { matcher_data.go
83 > return false matcher_data.go
84 > }
85 > return a.startTime.Before(b.startTime) matcher_data.go
86 }
87
88 > func (p *pollerPQ) Add(poller *waitingPoller) { matcher_data.go
89 > heap.Push(p, poller)
90 > }
91
92 > func (p *pollerPQ) Remove(poller *waitingPoller) { matcher_data.go
93 > heap.Remove(p, poller.matchHeapIndex)
94 > }
95
96 // implements heap.Interface, do not call directly
97 > func (p *pollerPQ) Swap(i int, j int) { matcher_data.go
98 > p.heap[i], p.heap[j] = p.heap[j], p.heap[i]
99 > p.heap[i].matchHeapIndex = i
100 > p.heap[j].matchHeapIndex = j
101 > }
102
103 // implements heap.Interface, do not call directly
104 > func (p *pollerPQ) Push(x any) { matcher_data.go
105 > poller := x.(*waitingPoller) // nolint:revive
106 > poller.matchHeapIndex = len(p.heap)
107 > p.heap = append(p.heap, poller)
108 > }
109
110 // implements heap.Interface, do not call directly
111 > func (p *pollerPQ) Pop() any { matcher_data.go
112 > last := len(p.heap) - 1
113 > poller := p.heap[last]
114 > p.heap = p.heap[:last]
115 > poller.matchHeapIndex = invalidHeapIndex
116 > return poller
117 > }
118
119 // taskBTree is a priority-ordered collection of tasks backed by a B-tree.
127 }
128
129 > func taskBTreeLess(a, b *internalTask) bool { matcher_data.go
130 > if a.effectivePriority != b.effectivePriority {
131 return a.effectivePriority < b.effectivePriority
132 }
133 > afl := taskFairLevel(a) matcher_data.go
134 > bfl := taskFairLevel(b)
135 > if afl != bfl {
136 return afl.less(bfl)
137 }
141 // would treat colliding tasks as one key and overwrite (losing a task), and btree.Delete
142 // could not identify which task to remove. See TestTaskBTreeNeedsPointerTiebreaker.
143 > return uintptr(unsafe.Pointer(a)) < uintptr(unsafe.Pointer(b)) matcher_data.go
144 }
145
146 // taskFairLevel returns the fair level for a task, or the zero fairLevel for tasks with no
147 // event (query, nexus, and poll-forwarder tasks).
148 > func taskFairLevel(task *internalTask) fairLevel { matcher_data.go
149 > if task.event == nil {
150 return fairLevel{}
151 }
152 > return fairLevelFromAllocatedTask(task.event.AllocatedTaskInfo) matcher_data.go
153 }
154
155 > func newTaskBTree() taskBTree { matcher_data.go
156 > return taskBTree{
157 > // NoLocks: matcherData does its own synchronization via matcherData.lock.
158 > tree: *btree.NewBTreeGOptions(taskBTreeLess, btree.Options{NoLocks: true}),
159 > ages: newBacklogAgeTracker(),
160 > }
161 > }
162
163 > func (b *taskBTree) Add(task *internalTask) { matcher_data.go
164 > task.matchHeapIndex = 0 // non-negative: signals "in queue"
165 > b.tree.Set(task)
166 > if task.source == enumsspb.TASK_SOURCE_DB_BACKLOG && task.forwardInfo == nil {
167 > b.ages.record(task.event.Data.CreateTime, 1) matcher_data.go
168 > }
169 }
170
171 > func (b *taskBTree) Remove(task *internalTask) { matcher_data.go
172 > b.tree.Delete(task)
173 > task.matchHeapIndex = invalidHeapIndex
174 > if task.source == enumsspb.TASK_SOURCE_DB_BACKLOG && task.forwardInfo == nil {
175 > b.ages.record(task.event.Data.CreateTime, -1) matcher_data.go
176 > }
177 }
178
179 > func (b *taskBTree) Len() int { matcher_data.go
180 > return b.tree.Len()
181 > }
182
183 // ForEachTask calls pred on each non-forwarder task. If pred returns true, calls post
184 // and removes the task. pred and post must not call back into taskBTree.
185 > func (b *taskBTree) ForEachTask(pred func(*internalTask) bool, post func(*internalTask)) { matcher_data.go
186 > // Collect first, then delete: we must not mutate the tree mid-iteration.
187 > var toRemove []*internalTask
188 > b.tree.Scan(func(task *internalTask) bool {
189 if !task.isPollForwarder() && pred(task) {
190 toRemove = append(toRemove, task)
192 return true
193 })
194 > for _, task := range toRemove { matcher_data.go
195 b.tree.Delete(task)
196 task.matchHeapIndex = invalidHeapIndex
228 // newMatcherData creates a new matcherData. onRateLimited is called each time a dispatch
229 // is blocked by the rate limiter (whole-queue or per-key).
230 > func newMatcherData(config *taskQueueConfig, logger log.Logger, timeSource clock.TimeSource, canForward bool, rateLimitManager *rateLimitManager, onRateLimited func()) matcherData { matcher_data.go
231 > return matcherData{
232 > config: config,
233 > logger: logger,
234 > timeSource: timeSource,
235 > canForward: canForward,
236 > rateLimitManager: rateLimitManager,
237 > onRateLimited: onRateLimited,
238 > tasks: newTaskBTree(),
239 > }
240 > }
241
242 > func (d *matcherData) Stop() { matcher_data.go
243 > d.lock.Lock()
244 > defer d.lock.Unlock()
245 >
246 > d.stopped = true
247 > }
248
249 > func (d *matcherData) EnqueueTaskNoWait(task *internalTask) error { matcher_data.go
250 > d.lock.Lock()
251 > defer d.lock.Unlock()
252 >
253 > if d.stopped {
254 return errMatcherStopped
255 }
256
257 > task.initMatch(d) matcher_data.go
258 > d.tasks.Add(task)
259 > d.findAndWakeMatches()
260 > return nil
261 }
262
311 }
312
313 > func (d *matcherData) EnqueuePollerAndWait(ctxs []context.Context, poller *waitingPoller) *matchResult { matcher_data.go
314 > d.lock.Lock()
315 > defer d.lock.Unlock()
316 >
317 > // update this for timeSinceLastPoll
318 > d.lastPoller = util.MaxTime(d.lastPoller, poller.startTime)
319 >
320 > // add and look for match
321 > poller.initMatch(d)
322 > d.pollers.Add(poller)
323 > d.findAndWakeMatches()
324 >
325 > // if already matched, return
326 > if poller.matchResult != nil {
327 > return poller.matchResult matcher_data.go
328 > }
329
330 // arrange to wake up on context close
331 > for i, ctx := range ctxs { matcher_data.go
332 > stop := context.AfterFunc(ctx, func() { matcher_data.go
333 > d.lock.Lock() matcher_data.go
334 > defer d.lock.Unlock()
335 >
336 > if poller.matchResult == nil {
337 > // if poll was being forwarded, it would be absent from heap even though
338 > // matchResult == nil
339 > if poller.matchHeapIndex >= 0 {
340 > d.pollers.Remove(poller) matcher_data.go
341 > }
342 > poller.wake(d.logger, &matchResult{ctxErr: ctx.Err(), ctxErrIdx: i}) matcher_data.go
343 }
344 })
345 > defer stop() // nolint:revive // there's only ever a small number of contexts matcher_data.go
346 }
347
348 > return poller.waitForMatch() matcher_data.go
349 }
350
351 // MatchTaskImmediately attempts a non-blocking sync match.
352 > func (d *matcherData) MatchTaskImmediately(task *internalTask) syncMatchOutcome { matcher_data.go
353 > d.lock.Lock()
354 > defer d.lock.Unlock()
355 >
356 > if !d.isBacklogNegligible() {
357 // To ensure better dispatch ordering, we block sync match when a significant backlog is present.
358 // Note that this check does not make a noticeable difference for history tasks, as they do not wait for a
363 }
364
365 > task.initMatch(d) matcher_data.go
366 > d.tasks.Add(task)
367 > rateLimited := d.findAndWakeMatches()
368 > // don't wait, check if match() picked this one already
369 > if task.matchResult != nil {
370 return syncMatchSuccess
371 }
372 > d.tasks.Remove(task) matcher_data.go
373 > if rateLimited {
374 return syncMatchRateLimited
375 }
376 > return syncMatchNoPoller matcher_data.go
377 }
378
392 }
393
394 > func (d *matcherData) ReprocessTasks(pred func(*internalTask) bool) []*internalTask { matcher_data.go
395 > d.lock.Lock()
396 > defer d.lock.Unlock()
397 >
398 > reprocess := make([]*internalTask, 0, d.tasks.Len())
399 > d.tasks.ForEachTask(
400 > pred,
401 > func(task *internalTask) {
402 // for sync tasks: wake up waiters with a fake context error
403 // for backlog tasks: the caller should call finish()
414 // call with lock held
415 // nolint:revive // will improve later
416 > func (d *matcherData) findMatch(allowForwarding bool, now int64) (matchedTask *internalTask, matchedPoller *waitingPoller, minDelay time.Duration) { matcher_data.go
417 > // TODO(pri): optimize so it's not O(d*n) worst case
418 > // Scan keeps its callback on the stack, so this walk does not allocate; the equivalent
419 > // tree.Iter() cursor escapes to the heap.
420 >
421 > // Without a per-key limit the whole-queue ready time is the same for every task, so one
422 > // check suffices and we avoid locking readyTimeForTask per task in the scan below. Only
423 > // short-circuit when a match is actually possible (tasks and pollers both present) so we
424 > // don't arm the rate-limit timer in cases where the full scan would have found nothing.
425 > // TODO: reaching into the rate limiter's state like this breaks its encapsulation;
426 > // refactor the rate limit logic so findMatch doesn't need to know about it.
427 > wholeQueueReady, perKeyLimited := d.rateLimitManager.rateLimitState()
428 > if !perKeyLimited && d.tasks.Len() > 0 && d.pollers.Len() > 0 {
429 > if delay := wholeQueueReady.delay(now); delay > 0 { matcher_data.go
430 return nil, nil, delay
431 }
432 }
433
434 > d.tasks.tree.Scan(func(task *internalTask) bool { matcher_data.go
435 > // disallow normal poll forwarding when allowForwarding is false, but allow the matcher_data.go
436 > // "priority backlog poll forwarders".
437 > if !allowForwarding && task.pollForwarderType == parentPollForwarder {
438 return true
439 }
440
441 > var matched *waitingPoller matcher_data.go
442 > for _, poller := range d.pollers.heap {
443 > // can't match cases: matcher_data.go
444 > if poller.queryOnly && !task.isQuery() && !task.isPollForwarder() {
445 // query-only poll only matches with query (but can match poll forwarder)
446 continue
447 > } else if task.isPollForwarder() && poller.forwardCtx == nil { matcher_data.go
448 // poll forwarder only matches polls that have a forwardCtx
449 continue
450 > } else if poller.taskForwarderType == parentTaskForwarder && !allowForwarding { matcher_data.go
451 // task forwarder only matches when forwarding is allowed
452 continue
453 > } else if poller.taskForwarderType == validatorTaskForwarder && task.forwardCtx != nil { matcher_data.go
454 > // validator (root only) only matches local backlog tasks matcher_data.go
455 > continue
456 > } else if mp := poller.minPriority(); mp > 0 && task.effectivePriority > effectivePriorityFactor*mp { matcher_data.go
457 // Note the ">" above: "min" priority is a numeric max.
458 // Also note: this condition will be false for draining tasks since we artifically boost
460 continue
461 }
462 > matched = poller matcher_data.go
463 > break
464 }
465 > if matched == nil { matcher_data.go
466 > // no compatible poller for this task; keep scanning later tasks matcher_data.go
467 > return true
468 > }
469
470 // skip per-key rate-limited tasks, tracking the minimum delay so the caller
471 // knows when the soonest one becomes ready
472 > if perKeyLimited { matcher_data.go
473 delay := d.rateLimitManager.readyTimeForTask(task).delay(now)
474 if delay > 0 {
520
521 // call with lock held. Returns true if a match was found but blocked by rate limiting.
522 > func (d *matcherData) findAndWakeMatches() (rateLimited bool) { matcher_data.go
523 > allowForwarding := d.canForward && d.allowForwarding()
524 >
525 > now := d.timeSource.Now().UnixNano()
526 >
527 > for {
528 > // search for highest-priority ready match; skip per-key rate-limited tasks
529 > task, poller, minDelay := d.findMatch(allowForwarding, now)
530 > if task == nil || poller == nil {
531 > if minDelay > 0 {
532 d.rateLimitTimer.set(d.timeSource, d.rematchAfterTimer, minDelay)
533 d.onRateLimited()
535 }
536 // no more current matches, stop rate limit timer if was running
537 > d.rateLimitTimer.unset() matcher_data.go
538 > return false
539 }
540
541 // ready to signal match
542 > d.tasks.Remove(task) matcher_data.go
543 > d.pollers.Remove(poller)
544 >
545 > // TODO(pri): maybe we can allow tasks to have costs other than 1
546 > d.rateLimitManager.consumeTokens(now, task, 1)
547 > task.recycleToken = d.recycleToken
548 >
549 > res := &matchResult{task: task, poller: poller}
550 > task.wake(d.logger, res)
551 > // for poll forwarder: skip waking poller, forwarder will call finishMatchAfterPollForward
552 > if !task.isPollForwarder() {
553 > poller.wake(d.logger, res) matcher_data.go
554 > }
555 // TODO(pri): consider having task forwarding work the same way, with a half-match,
556 // instead of full match and then pass forward result on response channel?
587 // isBacklogNegligible returns true if the age of the task backlog is less than the threshold.
588 // call with lock held.
589 > func (d *matcherData) isBacklogNegligible() bool { matcher_data.go
590 > t := d.tasks.ages.oldestTime()
591 > return t.IsZero() || time.Since(t) < d.config.BacklogNegligibleAge()
592 > }
593
594 func (d *matcherData) TimeSinceLastPoll() time.Duration {
621 }
622
623 > func (w *waitableMatchResult) initMatch(d *matcherData) { matcher_data.go
624 > w.matchCond.L = &d.lock
625 > w.matchResult = nil
626 > }
627
628 // call with matcherData.lock held.
629 // w.matchResult must be nil (can't call wake twice).
630 // w must not be in queues anymore.
631 > func (w *waitableMatchResult) wake(logger log.Logger, res *matchResult) { matcher_data.go
632 > softassert.That(logger, w.matchResult == nil, "wake called twice")
633 > softassert.That(logger, w.matchHeapIndex < 0, "wake called but still in heap")
634 > w.matchResult = res
635 > w.matchCond.Signal()
636 > }
637
638 // call with matcherData.lock held
639 > func (w *waitableMatchResult) waitForMatch() *matchResult { matcher_data.go
640 > for w.matchResult == nil {
641 > w.matchCond.Wait()
642 > }
643 > return w.matchResult matcher_data.go
644 }
645
662
663 // unset stops the timer.
664 > func (rt *resettableTimer) unset() { matcher_data.go
665 > if rt.timer != nil {
666 rt.timer.Stop()
667 rt.timer = nil
696 }
697
698 > func (p simpleLimiterParams) never() bool { return p.interval < 0 } matcher_data.go
699 > func (p simpleLimiterParams) limited() bool { return p.interval > 0 } matcher_data.go
700
701 // delay returns the time until the limiter is ready.
702 // If the return value is <= 0 then the limiter can go now.
703 > func (ready simpleLimiter) delay(now int64) time.Duration { matcher_data.go
704 > return time.Duration(int64(ready) - now)
705 > }
706
707 // consume updates ready based on the current time and number of new tokens consumed.
708 > func (ready simpleLimiter) consume(p simpleLimiterParams, now int64, tokens int64) simpleLimiter { matcher_data.go
709 > // This is a slight variation of the normal GCRA: instead of tracking the end of the
710 > // allowed interval (the theoretical arrival time), ready tracks the beginning of it, and
711 > // the end is ready + burst. To find the next ready time:
712 > // - Add ready+burst to find the next theoretical arrival time.
713 > // - If that's in the past, clip it at the current time.
714 > // - Subtract burst to turn it back into a ready time.
715 > // - Finally add the tokens we used.
716 > //
717 > // For intuition, consider that if if now is > ready by only a tiny amount, i.e. we're
718 > // bursting, then the max takes ready+burst and we push up the ready time by the full
719 > // interval. We can do this burst/interval times before it catches up and we're no longer
720 > // ready.
721 > //
722 > // Alternatively, if now is > ready by more than burst, then we end up subtracting the full
723 > // burst from now and adding one interval.
724 > if p.never() {
725 return simpleLimiterNever
726 }
727 > clippedReady := max(now, int64(ready)+p.burst.Nanoseconds()) - p.burst.Nanoseconds() matcher_data.go
728 > return simpleLimiter(clippedReady + tokens*p.interval.Nanoseconds())
729 }
730
go.temporal.io/server/service/worker/pernamespaceworker.go 252 covered LOC · 54 ranges

Open complete file

112 components []workercommon.PerNSWorkerComponent,
113 taskQueueName string,
114 > ) *PerNamespaceWorkerManager { pernamespaceworker.go
115 > return &PerNamespaceWorkerManager{
116 > logger: log.With(logger, tag.ComponentPerNSWorkerManager),
117 > sdkClientFactory: sdkClientFactory,
118 > namespaceRegistry: namespaceRegistry,
119 > hostName: hostName,
120 > taskQueueName: taskQueueName,
121 > config: config,
122 > components: components,
123 > initialRetry: 1 * time.Second,
124 > thisClusterName: clusterMetadata.GetCurrentClusterName(),
125 > startLimiter: quotas.NewDefaultOutgoingRateLimiter(quotas.RateFn(config.PerNamespaceWorkerStartRate)),
126 > membershipChangedCh: make(chan *membership.ChangedEvent),
127 > workers: make(map[namespace.ID]*perNamespaceWorker),
128 > }
129 > }
130
131 > func (wm *PerNamespaceWorkerManager) Running() bool { pernamespaceworker.go
132 > return atomic.LoadInt32(&wm.status) == common.DaemonStatusStarted
133 > }
134
135 func (wm *PerNamespaceWorkerManager) Start(
136 self membership.HostInfo,
137 serviceResolver membership.ServiceResolver,
139 > if !atomic.CompareAndSwapInt32(
140 > &wm.status,
141 > common.DaemonStatusInitialized,
142 > common.DaemonStatusStarted,
143 > ) {
144 return
145 }
146
147 > wm.self = self pernamespaceworker.go
148 > wm.serviceResolver = serviceResolver
149 >
150 > wm.logger.Info("", tag.LifeCycleStarting)
151 >
152 > // this will call namespaceCallback with current namespaces
153 > wm.namespaceRegistry.RegisterStateChangeCallback(wm, wm.namespaceCallback)
154 >
155 > err := wm.serviceResolver.AddListener(fmt.Sprintf("%p", wm), wm.membershipChangedCh)
156 > if err != nil {
157 wm.logger.Fatal("Unable to register membership listener", tag.Error(err))
158 }
159 > wm.backgroundLoops.Go(wm.membershipChangedListener) pernamespaceworker.go
160 > wm.backgroundLoops.Go(wm.periodicRefreshLoop)
161 >
162 > wm.logger.Info("", tag.LifeCycleStarted)
163 }
164
165 > func (wm *PerNamespaceWorkerManager) Stop() { pernamespaceworker.go
166 > if !atomic.CompareAndSwapInt32(
167 > &wm.status,
168 > common.DaemonStatusStarted,
169 > common.DaemonStatusStopped,
170 > ) {
171 return
172 }
173
174 > wm.logger.Info("", tag.LifeCycleStopping) pernamespaceworker.go
175 >
176 > wm.namespaceRegistry.UnregisterStateChangeCallback(wm)
177 > err := wm.serviceResolver.RemoveListener(fmt.Sprintf("%p", wm))
178 > if err != nil {
179 wm.logger.Error("Unable to unregister membership listener", tag.Error(err))
180 }
181 > wm.backgroundLoops.Cancel() pernamespaceworker.go
182 > wm.backgroundLoops.Wait()
183 >
184 > wm.lock.Lock()
185 > workers := expmaps.Values(wm.workers)
186 > maps.DeleteFunc(wm.workers, func(_ namespace.ID, _ *perNamespaceWorker) bool { return true })
187 > wm.lock.Unlock()
188 >
189 > for _, worker := range workers {
190 > worker.stopWorkerAndResetTimer() pernamespaceworker.go
191 > worker.cancel()
192 > }
193
194 > wm.logger.Info("", tag.LifeCycleStopped) pernamespaceworker.go
195 }
196
197 > func (wm *PerNamespaceWorkerManager) namespaceCallback(ns *namespace.Namespace, nsDeleted bool) { pernamespaceworker.go
198 > go wm.getWorkerByNamespace(ns).update(ns, nsDeleted, nil, nil)
199 > }
200
201 func (wm *PerNamespaceWorkerManager) refreshAll() {
207 }
208
209 > func (wm *PerNamespaceWorkerManager) membershipChangedListener(ctx context.Context) error { pernamespaceworker.go
210 > for {
211 > select {
212 > case <-ctx.Done(): pernamespaceworker.go
213 > return nil
214 case <-wm.membershipChangedCh:
215 wm.refreshAll()
218 }
219
220 > func (wm *PerNamespaceWorkerManager) periodicRefreshLoop(ctx context.Context) error { pernamespaceworker.go
221 > ticker := time.NewTicker(refreshInterval)
222 > defer ticker.Stop()
223 >
224 > for {
225 > select {
226 > case <-ctx.Done(): pernamespaceworker.go
227 > return nil
228 case <-ticker.C:
229 wm.refreshAll()
232 }
233
234 > func (wm *PerNamespaceWorkerManager) getWorkerByNamespace(ns *namespace.Namespace) *perNamespaceWorker { pernamespaceworker.go
235 > wm.lock.Lock()
236 > defer wm.lock.Unlock()
237 >
238 > if worker, ok := wm.workers[ns.ID()]; ok {
239 return worker
240 }
241
242 > worker := &perNamespaceWorker{ pernamespaceworker.go
243 > wm: wm,
244 > logger: log.With(wm.logger, tag.WorkflowNamespace(ns.Name().String())),
245 > retrier: backoff.NewRetrier(backoff.NewExponentialRetryPolicy(wm.initialRetry), clock.NewRealTimeSource()),
246 > }
247 > count, c1 := wm.config.PerNamespaceWorkerCount(ns.Name().String(), worker.setWorkerCount)
248 > opts, c2 := wm.config.PerNamespaceWorkerOptions(ns.Name().String(), worker.setWorkerOptions)
249 > worker.ns = ns
250 > worker.count = count
251 > worker.opts = opts
252 > worker.cancel = func() { c1(); c2() }
253
254 > wm.workers[ns.ID()] = worker pernamespaceworker.go
255 > return worker
256 }
257
266 }
267
268 > func (w *perNamespaceWorker) getWorkerAllocation(args refreshArgs) (workerAllocation, error) { pernamespaceworker.go
269 > if args.count < 0 {
270 return workerAllocation{}, errInvalidConfiguration
271 > } else if args.count == 0 { pernamespaceworker.go
272 return workerAllocation{0, 0}, nil
273 }
274 > localCount, err := w.getLocallyDesiredWorkers(args) pernamespaceworker.go
275 > if err != nil {
276 return workerAllocation{}, err
277 }
278 > return workerAllocation{total: args.count, local: localCount}, nil pernamespaceworker.go
279 }
280
281 > func (w *perNamespaceWorker) getLocallyDesiredWorkers(args refreshArgs) (int, error) { pernamespaceworker.go
282 > key := args.ns.ID().String()
283 > availableHosts := w.wm.serviceResolver.LookupN(key, args.count)
284 > hostsCount := len(availableHosts)
285 > if hostsCount == 0 {
286 return 0, membership.ErrInsufficientHosts
287 }
288 > maxWorkersPerHost := args.count/hostsCount + 1 pernamespaceworker.go
289 > desiredDistribution := util.RepeatSlice(availableHosts, maxWorkersPerHost)[:args.count]
290 >
291 > isLocal := func(info membership.HostInfo) bool { return info.Identity() == w.wm.self.Identity() }
292 > result := len(util.FilterSlice(desiredDistribution, isLocal))
293 > return result, nil
294 }
295
303
304 // called on namespace state change callback, membership change, and dynamic config change
305 > func (w *perNamespaceWorker) update(ns *namespace.Namespace, nsDeleted bool, newCount *int, newOpts *sdkworker.Options) { pernamespaceworker.go
306 > w.lock.Lock()
307 >
308 > if ns != nil {
309 > w.ns = ns
310 > // The name inside of *ns, which was used to initialize the logger, can change, but
311 > // don't update w.logger here, otherwise we'd have to hold w.lock just to log.
312 > }
313 > if newCount != nil {
314 w.count = *newCount
315 }
316 > if newOpts != nil { pernamespaceworker.go
317 w.opts = *newOpts
318 }
319
320 > refreshArgs := w.refreshArgs // copy before releasing lock pernamespaceworker.go
321 > isRetrying := w.retryTimer != nil
322 > w.lock.Unlock()
323 >
324 > if nsDeleted {
325 w.stopWorkerAndResetTimer()
326 // if namespace is fully deleted from db, we can remove from our map also
329 }
330
331 > if !isRetrying { pernamespaceworker.go
332 > w.refresh(refreshArgs)
333 > }
334 }
335
336 // handleError should be called on errors from worker creation or run. it will attempt to
337 // refresh the worker again at a later time.
338 > func (w *perNamespaceWorker) handleError(err error) { pernamespaceworker.go
339 > if err == nil {
340 > return pernamespaceworker.go
341 > }
342 if errors.Is(err, errNoWorkerNeeded) {
343 w.stopWorkerAndResetTimer()
379 // Returning an error from here means that we should retry creating/starting the worker.
380 // Returning noWorkerNeeded means any existing worker should be stopped.
381 > func (w *perNamespaceWorker) refresh(args refreshArgs) (retErr error) { pernamespaceworker.go
382 > defer func() {
383 > w.handleError(retErr)
384 > }()
385
386 // note w.lock is not locked until we're about to start/stop a worker
387
388 > if !w.wm.Running() || pernamespaceworker.go
389 > args.ns.State() == enumspb.NAMESPACE_STATE_DELETED ||
390 > //nolint:forbidigo // per-namespace worker lifecycle, no workflow context
391 > !args.ns.ActiveInCluster(w.wm.thisClusterName) {
392
393 return errNoWorkerNeeded
395
396 // figure out which components are enabled at all for this namespace
397 > var enabledComponents []workercommon.PerNSWorkerComponent pernamespaceworker.go
398 > var componentSet strings.Builder
399 > for _, cmp := range w.wm.components {
400 > options := cmp.DedicatedWorkerOptions(args.ns)
401 > if options.Enabled {
402 > enabledComponents = append(enabledComponents, cmp) pernamespaceworker.go
403 > fmt.Fprintf(&componentSet, "%p,", cmp)
404 > }
405 }
406
407 > if len(enabledComponents) == 0 { pernamespaceworker.go
408 // no components enabled, we don't need a worker
409 return errNoWorkerNeeded
411
412 // check if we are responsible for this namespace at all
413 > workerAllocation, err := w.getWorkerAllocation(args) pernamespaceworker.go
414 > if err != nil {
415 w.logger.Error("Failed to look up hosts", tag.Error(err))
416 // TODO: add metric also
417 return err
418 }
419 > if workerAllocation.local == 0 { pernamespaceworker.go
420 // not ours, don't need a worker
421 return errNoWorkerNeeded
422 }
423 // ensure this changes if multiplicity changes
424 > fmt.Fprintf(&componentSet, "%d,", workerAllocation.local) pernamespaceworker.go
425 >
426 > // get sdk worker options
427 > fmt.Fprintf(&componentSet, "%+v,", w.opts)
428 >
429 > // we do need a worker, but maybe we have one already
430 > w.lock.Lock()
431 > defer w.lock.Unlock()
432 >
433 > if args.ns != w.ns {
434 // stale refresh goroutine, do nothing
435 return nil
436 }
437
438 > if componentSet.String() == w.componentSet { pernamespaceworker.go
439 // no change in set of components enabled, leave existing running
440 return nil
442
443 // ask rate limiter if we can start now
444 > if !w.reserved { pernamespaceworker.go
445 > w.reserved = true
446 > if delay := w.wm.startLimiter.Reserve().Delay(); delay > 0 {
447 return errRetryAfter(delay)
448 }
450
451 // set of components changed, need to recreate worker. first stop old one
452 > w.stopWorkerLocked() pernamespaceworker.go
453 >
454 > // create new one. note that even before startWorker returns, the worker may have started
455 > // and already called the fatal error handler. we need to set w.client+worker+componentSet
456 > // before releasing the lock to keep our state consistent.
457 > client, worker, err := w.startWorker(enabledComponents, workerAllocation)
458 > if err != nil {
459 // TODO: add metric also
460 w.stopWorkerLocked() // for calling cleanup
462 }
463
464 > w.client = client pernamespaceworker.go
465 > w.worker = worker
466 > w.componentSet = componentSet.String()
467 > return nil
468 }
469
471 components []workercommon.PerNSWorkerComponent,
472 allocation workerAllocation,
473 > ) (sdkclient.Client, sdkworker.Worker, error) { pernamespaceworker.go
474 > nsName := w.ns.Name().String()
475 > // this should not block because it uses an existing grpc connection
476 > client := w.wm.sdkClientFactory.NewClient(sdkclient.Options{
477 > Namespace: nsName,
478 > DataConverter: sdk.PreferProtoDataConverter,
479 > })
480 >
481 > var sdkoptions sdkworker.Options
482 >
483 > // copy from dynamic config. apply explicit defaults for some instead of using the sdk
484 > // defaults so that we can multiply below.
485 > sdkoptions.MaxConcurrentActivityExecutionSize = cmp.Or(w.opts.MaxConcurrentActivityExecutionSize, 1000)
486 > sdkoptions.WorkerActivitiesPerSecond = w.opts.WorkerActivitiesPerSecond
487 > sdkoptions.MaxConcurrentLocalActivityExecutionSize = cmp.Or(w.opts.MaxConcurrentLocalActivityExecutionSize, 1000)
488 > sdkoptions.WorkerLocalActivitiesPerSecond = w.opts.WorkerLocalActivitiesPerSecond
489 > sdkoptions.MaxConcurrentActivityTaskPollers = max(cmp.Or(w.opts.MaxConcurrentActivityTaskPollers, 2), 2)
490 > sdkoptions.MaxConcurrentWorkflowTaskExecutionSize = cmp.Or(w.opts.MaxConcurrentWorkflowTaskExecutionSize, 1000)
491 > sdkoptions.MaxConcurrentWorkflowTaskPollers = max(cmp.Or(w.opts.MaxConcurrentWorkflowTaskPollers, 2), 2)
492 > sdkoptions.StickyScheduleToStartTimeout = w.opts.StickyScheduleToStartTimeout
493 >
494 > sdkoptions.BackgroundActivityContext = headers.SetCallerInfo(context.Background(), headers.NewBackgroundHighCallerInfo(nsName))
495 > sdkoptions.Identity = fmt.Sprintf("temporal-system@%s@%s", w.wm.hostName, nsName)
496 > // increase these if we're supposed to run with more allocation
497 > sdkoptions.MaxConcurrentWorkflowTaskPollers *= allocation.local
498 > sdkoptions.MaxConcurrentActivityTaskPollers *= allocation.local
499 > sdkoptions.MaxConcurrentLocalActivityExecutionSize *= allocation.local
500 > sdkoptions.MaxConcurrentWorkflowTaskExecutionSize *= allocation.local
501 > sdkoptions.MaxConcurrentActivityExecutionSize *= allocation.local
502 > sdkoptions.OnFatalError = w.onFatalError
503 >
504 > // this should not block because the client already has server capabilities
505 > worker := w.wm.sdkClientFactory.NewWorker(client, w.wm.taskQueueName, sdkoptions)
506 > details := workercommon.RegistrationDetails{
507 > TotalWorkers: allocation.total,
508 > Multiplicity: allocation.local,
509 > }
510 > for _, cmp := range components {
511 > cleanup := cmp.Register(worker, w.ns, details)
512 > if cleanup != nil {
513 > w.cleanup = append(w.cleanup, cleanup) pernamespaceworker.go
514 > }
515 }
516
517 // this blocks by calling DescribeNamespace a few times (with a 10s timeout)
518 > err := worker.Start() pernamespaceworker.go
519 > if err != nil {
520 client.Close()
521 return nil, nil, err
522 }
523
524 > return client, worker, nil pernamespaceworker.go
525 }
526
548 }
549
550 > func (w *perNamespaceWorker) stopWorkerAndResetTimer() { pernamespaceworker.go
551 > w.lock.Lock()
552 > defer w.lock.Unlock()
553 >
554 > w.stopWorkerLocked()
555 > w.retrier.Reset()
556 > // Note that we only reset reserved here, not in stopWorkerLocked: if we did it there, we
557 > // would take a rate limiter token on each retry after failure. Failure to start the worker
558 > // means we probably didn't do any polls yet, which is the main reason for the rate limit,
559 > // so this it's okay to use only the backoff timer in that case.
560 > w.reserved = false
561 > if w.retryTimer != nil {
562 w.retryTimer.Stop()
563 w.retryTimer = nil
565 }
566
567 > func (w *perNamespaceWorker) stopWorkerLocked() { pernamespaceworker.go
568 > for _, cleanup := range w.cleanup {
569 > cleanup() pernamespaceworker.go
570 > }
571 > w.cleanup = nil pernamespaceworker.go
572 > if w.worker != nil {
573 > w.worker.Stop() pernamespaceworker.go
574 > w.worker = nil
575 > }
576 > if w.client != nil { pernamespaceworker.go
577 > w.client.Close() pernamespaceworker.go
578 > w.client = nil
579 > }
580 > w.componentSet = "" pernamespaceworker.go
581 }
582
go.temporal.io/server/common/resource/fx.go 250 covered LOC · 47 ranges

Open complete file

89 fx.Provide(SearchAttributeManagerProvider),
90 fx.Provide(NamespaceRegistryProvider),
91 > fx.Provide(func() namespace.NamespaceStateChangedFn { return nsregistry.DefaultNamespaceStateChanged }), fx.go
92 nsregistry.RegistryLifetimeHooksModule,
93 fx.Provide(fx.Annotate(
94 > func(p namespace.Registry) pingable.Pingable { return p }, fx.go
95 fx.ResultTags(`group:"deadlockDetectorRoots"`),
96 )),
127 )
128
129 > func DefaultSnTaggedLoggerProvider(logger log.Logger, sn primitives.ServiceName) log.SnTaggedLogger { fx.go
130 > return log.With(logger, tag.Service(sn))
131 > }
132
133 func ThrottledLoggerProvider(
134 logger log.SnTaggedLogger,
135 fn ThrottledLoggerRpsFn,
136 > ) log.ThrottledLogger { fx.go
137 > return log.NewThrottledLogger(
138 > logger,
139 > quotas.RateFn(fn),
140 > )
141 > }
142
143 > func GrpcListenerProvider(factory common.RPCFactory) net.Listener { fx.go
144 > return factory.GetGRPCListener()
145 > }
146
147 > func HostNameProvider() (HostName, error) { fx.go
148 > hn, err := os.Hostname()
149 > return HostName(hn), err
150 > }
151
152 > func TimeSourceProvider() clock.TimeSource { fx.go
153 > return clock.NewRealTimeSource()
154 > }
155
156 func SearchAttributeMapperProviderProvider(
159 searchAttributeProvider searchattribute.Provider,
160 persistenceConfig *config.Persistence,
161 > ) searchattribute.MapperProvider { fx.go
162 > primaryVisibilityStoreConfig := persistenceConfig.GetVisibilityStoreConfig()
163 > return searchattribute.NewMapperProvider(
164 > saMapper,
165 > namespaceRegistry,
166 > searchAttributeProvider,
167 > primaryVisibilityStoreConfig.GetIndexName(),
168 > )
169 > }
170
171 func SearchAttributeProviderProvider(
174 cmMgr persistence.ClusterMetadataManager,
175 dynamicCollection *dynamicconfig.Collection,
176 > ) searchattribute.Provider { fx.go
177 > return searchattribute.NewManager(
178 > timeSource,
179 > cmMgr,
180 > logger,
181 > dynamicconfig.ForceSearchAttributesCacheRefreshOnRead.Get(dynamicCollection))
182 > }
183
184 func SearchAttributeManagerProvider(
187 cmMgr persistence.ClusterMetadataManager,
188 dynamicCollection *dynamicconfig.Collection,
189 > ) searchattribute.Manager { fx.go
190 > return searchattribute.NewManager(
191 > timeSource,
192 > cmMgr,
193 > logger,
194 > dynamicconfig.ForceSearchAttributesCacheRefreshOnRead.Get(dynamicCollection))
195 > }
196
197 // SearchAttributeValidatorProvider creates a new search attribute validator with the given dependencies. It configures
205 metricsHandler metrics.Handler,
206 logger log.Logger,
207 > ) *searchattribute.Validator { fx.go
208 > return searchattribute.NewValidator(
209 > saProvider,
210 > saMapperProvider,
211 > dynamicconfig.SearchAttributesNumberOfKeysLimit.Get(dynamicCollection),
212 > dynamicconfig.SearchAttributesSizeOfValueLimit.Get(dynamicCollection),
213 > dynamicconfig.SearchAttributesTotalSizeLimit.Get(dynamicCollection),
214 > visibilityMgr,
215 > visibility.AllowListForValidation(
216 > visibilityMgr.GetStoreNames(),
217 > dynamicconfig.VisibilityAllowList.Get(dynamicCollection),
218 > ),
219 > dynamicconfig.SuppressErrorSetSystemSearchAttribute.Get(dynamicCollection),
220 > metricsHandler,
221 > logger,
222 > )
223 > }
224
225 type NamespaceRegistryParams struct {
235 }
236
237 > func NamespaceRegistryProvider(params NamespaceRegistryParams) namespace.Registry { fx.go
238 > return nsregistry.NewRegistry(
239 > params.MetadataManager,
240 > params.ClusterMetadata.IsGlobalNamespaceEnabled(),
241 > params.ClusterMetadata.GetCurrentClusterName(),
242 > dynamicconfig.NamespaceCacheRefreshInterval.Get(params.DynamicCollection),
243 > dynamicconfig.ForceSearchAttributesCacheRefreshOnRead.Get(params.DynamicCollection),
244 > params.MetricsHandler,
245 > params.Logger,
246 > params.ReplicationResolverFactory,
247 > params.NamespaceStateChangedFn,
248 > )
249 > }
250
251 func ClientFactoryProvider(
259 logger log.SnTaggedLogger,
260 throttledLogger log.ThrottledLogger,
261 > ) client.Factory { fx.go
262 > return factoryProvider.NewFactory(
263 > rpcFactory,
264 > membershipMonitor,
265 > metricsHandler,
266 > dynamicCollection,
267 > testHooks,
268 > persistenceConfig.NumHistoryShards,
269 > logger,
270 > throttledLogger,
271 > )
272 > }
273
274 func ClientBeanProvider(
276 clientFactory client.Factory,
277 clusterMetadata cluster.Metadata,
278 > ) (client.Bean, error) { fx.go
279 > bean, err := client.NewClientBean(
280 > clientFactory,
281 > clusterMetadata,
282 > )
283 > if err != nil {
284 return nil, err
285 }
286 // Deterministically release the bean's clients (daemon goroutines and
287 // cached gRPC connections) on shutdown.
288 > lc.Append(fx.StopHook(bean.Close)) fx.go
289 > return bean, nil
290 }
291
292 > func FrontendClientProvider(clientBean client.Bean) workflowservice.WorkflowServiceClient { fx.go
293 > frontendRawClient := clientBean.GetFrontendClient()
294 > return frontend.NewRetryableClient(
295 > frontendRawClient,
296 > common.CreateFrontendClientRetryPolicy(),
297 > common.IsServiceClientTransientError,
298 > )
299 > }
300
301 > func AdminClientProvider(clientBean client.Bean, clusterMetadata cluster.Metadata) (adminservice.AdminServiceClient, error) { fx.go
302 > adminRawClient, err := clientBean.GetRemoteAdminClient(clusterMetadata.GetCurrentClusterName())
303 > if err != nil {
304 return nil, err
305 }
306 > return admin.NewRetryableClient( fx.go
307 > adminRawClient,
308 > common.CreateFrontendClientRetryPolicy(),
309 > common.IsServiceClientTransientError,
310 > ), nil
311 }
312
313 func RuntimeMetricsReporterProvider(
314 params RuntimeMetricsReporterParams,
315 > ) *metrics.RuntimeMetricsReporter { fx.go
316 > return metrics.NewRuntimeMetricsReporter(
317 > params.MetricHandler,
318 > time.Minute,
319 > params.Logger,
320 > string(params.InstanceID),
321 > )
322 > }
323
324 > func HistoryRawClientProvider(clientBean client.Bean) HistoryRawClient { fx.go
325 > return clientBean.GetHistoryClient()
326 > }
327
328 > func HistoryClientProvider(historyRawClient HistoryRawClient, dc *dynamicconfig.Collection) HistoryClient { fx.go
329 > return history.NewRetryableClient(
330 > historyRawClient,
331 > common.CreateHistoryClientRetryPolicy(dynamicconfig.RetryUnboundedOnSystemResourceExhausted.Get(dc)),
332 > common.IsServiceClientTransientError,
333 > )
334 > }
335
336 func MatchingRawClientProvider(
337 clientBean client.Bean,
338 namespaceRegistry namespace.Registry,
339 > ) (MatchingRawClient, error) { fx.go
340 > return clientBean.GetMatchingClient(namespaceRegistry.GetNamespaceName)
341 > }
342
343 > func MatchingClientProvider(matchingRawClient MatchingRawClient, dc *dynamicconfig.Collection) MatchingClient { fx.go
344 > return matching.NewRetryableClient(
345 > matchingRawClient,
346 > common.CreateMatchingClientRetryPolicy(dynamicconfig.RetryUnboundedOnSystemResourceExhausted.Get(dc)),
347 > common.CreateMatchingClientLongPollRetryPolicy(),
348 > common.IsServiceClientTransientError,
349 > )
350 > }
351
352 > func PersistenceConfigProvider(persistenceConfig config.Persistence, dc *dynamicconfig.Collection) *config.Persistence { fx.go
353 > persistenceConfig.TransactionSizeLimit = dynamicconfig.TransactionSizeLimit.Get(dc)
354 > return &persistenceConfig
355 > }
356
357 > func ArchivalMetadataProvider(dc *dynamicconfig.Collection, cfg *config.Config) archiver.ArchivalMetadata { fx.go
358 > return archiver.NewArchivalMetadata(
359 > dc,
360 > cfg.Archival.History.State,
361 > cfg.Archival.History.EnableRead,
362 > cfg.Archival.Visibility.State,
363 > cfg.Archival.Visibility.EnableRead,
364 > &cfg.NamespaceDefaults.Archival,
365 > )
366 > }
367
368 func ArchiverProviderProvider(
373 logger log.SnTaggedLogger,
374 metricsHandler metrics.Handler,
375 > ) provider.ArchiverProvider { fx.go
376 > return provider.NewArchiverProvider(
377 > cfg.Archival.History.Provider,
378 > cfg.Archival.Visibility.Provider,
379 > customHistoryArchiverFactory,
380 > customVisibilityArchiverFactory,
381 > persistenceExecutionManager,
382 > logger,
383 > metricsHandler,
384 > )
385 > }
386
387 func SdkClientFactoryProvider(
392 resolver *membership.GRPCResolver,
393 dc *dynamicconfig.Collection,
394 > ) (sdk.ClientFactory, error) { fx.go
395 > frontendURL, _, _, frontendTLSConfig, err := getFrontendConnectionDetails(cfg, tlsConfigProvider, resolver)
396 > if err != nil {
397 return nil, err
398 }
399 > return sdk.NewClientFactory( fx.go
400 > frontendURL,
401 > frontendTLSConfig,
402 > metricsHandler,
403 > logger,
404 > dynamicconfig.WorkerStickyCacheSize.Get(dc),
405 > ), nil
406 }
407
408 > func DCRedirectionPolicyProvider(cfg *config.Config) config.DCRedirectionPolicy { fx.go
409 > return cfg.DCRedirectionPolicy
410 > }
411
412 func PerServiceDialOptionsProvider(
413 logger log.SnTaggedLogger,
414 > ) map[primitives.ServiceName][]grpc.DialOption { fx.go
415 > trailerInterceptor := interceptor.TrailerToContextMetadataInterceptor(logger)
416 > dialOpt := grpc.WithChainUnaryInterceptor(trailerInterceptor)
417 > return map[primitives.ServiceName][]grpc.DialOption{
418 > primitives.HistoryService: {dialOpt},
419 > primitives.MatchingService: {dialOpt},
420 > }
421 > }
422
423 func RPCFactoryProvider(
433 dc *dynamicconfig.Collection,
434 tokenProvider auth.TokenProvider,
435 > ) (common.RPCFactory, error) { fx.go
436 > frontendURL, frontendHTTPURL, frontendHTTPPort, frontendTLSConfig, err := getFrontendConnectionDetails(cfg, tlsConfigProvider, resolver)
437 > if err != nil {
438 return nil, err
439 }
440
441 > var options []grpc.DialOption fx.go
442 > if tracingStatsHandler != nil {
443 options = append(options, grpc.WithStatsHandler(tracingStatsHandler))
444 }
445 > enableServerKeepalive := dynamicconfig.EnableInternodeServerKeepAlive.Get(dc)() fx.go
446 > enableClientKeepalive := dynamicconfig.EnableInternodeClientKeepAlive.Get(dc)()
447 > factory := rpc.NewFactory(
448 > cfg,
449 > svcName,
450 > logger,
451 > metricsHandler,
452 > tlsConfigProvider,
453 > frontendURL,
454 > frontendHTTPURL,
455 > frontendHTTPPort,
456 > frontendTLSConfig,
457 > options,
458 > perServiceDialOptions,
459 > monitor,
460 > tokenProvider,
461 > )
462 > factory.EnableInternodeServerKeepalive = enableServerKeepalive
463 > factory.EnableInternodeClientKeepalive = enableClientKeepalive
464 > logger.Debug(fmt.Sprintf("RPC factory created. enableServerKeepalive: %v, enableClientKeepalive: %v", enableServerKeepalive, enableClientKeepalive))
465 > return factory, nil
466 }
467
469 metadata cluster.Metadata,
470 tlsConfigProvider encryption.TLSConfigProvider,
471 > ) *cluster.FrontendHTTPClientCache { fx.go
472 > return cluster.NewFrontendHTTPClientCache(metadata, tlsConfigProvider)
473 > }
474
475 func getFrontendConnectionDetails(
477 tlsConfigProvider encryption.TLSConfigProvider,
478 resolver *membership.GRPCResolver,
479 > ) (string, string, int, *tls.Config, error) { fx.go
480 > // To simplify the static config, we switch default values based on whether the config
481 > // defines an "internal-frontend" service. The default for TLS config can be overridden
482 > // with publicClient.forceTLSConfig.
483 > _, hasIFE := cfg.Services[string(primitives.InternalFrontendService)]
484 >
485 > forceTLS := cfg.PublicClient.ForceTLSConfig
486 > if forceTLS == config.ForceTLSConfigAuto {
487 > if hasIFE {
488 forceTLS = config.ForceTLSConfigInternode
489 > } else { fx.go
490 > forceTLS = config.ForceTLSConfigFrontend
491 > }
492 }
493
494 > var frontendTLSConfig *tls.Config fx.go
495 > var err error
496 > switch forceTLS {
497 case config.ForceTLSConfigInternode:
498 frontendTLSConfig, err = tlsConfigProvider.GetInternodeClientConfig()
499 > case config.ForceTLSConfigFrontend: fx.go
500 > frontendTLSConfig, err = tlsConfigProvider.GetFrontendClientConfig()
501 default:
502 err = fmt.Errorf("invalid forceTLSConfig")
503 }
504 > if err != nil { fx.go
505 return "", "", 0, nil, fmt.Errorf("unable to load TLS configuration: %w", err)
506 }
507
508 > frontendURL := cfg.PublicClient.HostPort fx.go
509 > if frontendURL == "" {
510 > if hasIFE { fx.go
511 frontendURL = resolver.MakeURL(primitives.InternalFrontendService)
512 > } else { fx.go
513 > frontendURL = resolver.MakeURL(primitives.FrontendService)
514 > }
515 }
516 > frontendHTTPURL := cfg.PublicClient.HTTPHostPort fx.go
517 > if frontendHTTPURL == "" {
518 > if hasIFE {
519 frontendHTTPURL = resolver.MakeURL(primitives.InternalFrontendService)
520 > } else { fx.go
521 > frontendHTTPURL = resolver.MakeURL(primitives.FrontendService)
522 > }
523 }
524
525 > var frontendHTTPPort int fx.go
526 > if hasIFE {
527 frontendHTTPPort = cfg.Services[string(primitives.InternalFrontendService)].RPC.HTTPPort
528 > } else { fx.go
529 > frontendHTTPPort = cfg.Services[string(primitives.FrontendService)].RPC.HTTPPort
530 > }
531
532 > return frontendURL, frontendHTTPURL, frontendHTTPPort, frontendTLSConfig, nil fx.go
533 }
go.temporal.io/server/service/matching/config.go 250 covered LOC · 41 ranges

Open complete file

278 func NewConfig(
279 dc *dynamicconfig.Collection,
280 > ) *Config { config.go
281 > return &Config{
282 > PersistenceMaxQPS: dynamicconfig.MatchingPersistenceMaxQPS.Get(dc),
283 > PersistenceGlobalMaxQPS: dynamicconfig.MatchingPersistenceGlobalMaxQPS.Get(dc),
284 > PersistenceNamespaceMaxQPS: dynamicconfig.MatchingPersistenceNamespaceMaxQPS.Get(dc),
285 > PersistenceGlobalNamespaceMaxQPS: dynamicconfig.MatchingPersistenceGlobalNamespaceMaxQPS.Get(dc),
286 > PersistencePerShardNamespaceMaxQPS: dynamicconfig.DefaultPerShardNamespaceRPSMax,
287 > PersistenceDynamicRateLimitingParams: dynamicconfig.MatchingPersistenceDynamicRateLimitingParams.Get(dc),
288 > PersistenceQPSBurstRatio: dynamicconfig.PersistenceQPSBurstRatio.Get(dc),
289 > SyncMatchWaitDuration: dynamicconfig.MatchingSyncMatchWaitDuration.Get(dc),
290 > HistoryMaxPageSize: dynamicconfig.MatchingHistoryMaxPageSize.Get(dc),
291 > EnableDeployments: dynamicconfig.EnableDeployments.Get(dc), // [cleanup-wv-pre-release]
292 > EnableDeploymentVersions: dynamicconfig.EnableDeploymentVersions.Get(dc),
293 > UseRevisionNumberForWorkerVersioning: dynamicconfig.UseRevisionNumberForWorkerVersioning.Get(dc),
294 > MaxTaskQueuesInDeployment: dynamicconfig.MatchingMaxTaskQueuesInDeployment.Get(dc),
295 > MaxVersionsInTaskQueue: dynamicconfig.MatchingMaxVersionsInTaskQueue.Get(dc),
296 > RPS: dynamicconfig.MatchingRPS.Get(dc),
297 > NamespaceRPS: dynamicconfig.MatchingNamespaceRPS.Get(dc),
298 > OperatorRPSRatio: dynamicconfig.OperatorRPSRatio.Get(dc),
299 > PollWaitForNamespaceRateLimitToken: dynamicconfig.PollWaitForNamespaceRateLimitToken.Get(dc),
300 > RangeSize: 100000,
301 > NewMatcherSub: dynamicconfig.MatchingUseNewMatcher.Subscribe(dc),
302 > EnableFairnessSub: dynamicconfig.MatchingEnableFairness.Subscribe(dc),
303 > EnableMigration: dynamicconfig.MatchingEnableMigration.Get(dc),
304 > AutoEnableV2Sub: dynamicconfig.MatchingAutoEnableV2.Subscribe(dc),
305 > GetTasksBatchSize: dynamicconfig.MatchingGetTasksBatchSize.Get(dc),
306 > GetTasksReloadAt: dynamicconfig.MatchingGetTasksReloadAt.Get(dc),
307 > ForceReadTasksOnWrite: dynamicconfig.MatchingForceReadTasksOnWrite.Get(dc),
308 > UpdateAckInterval: dynamicconfig.MatchingUpdateAckInterval.Get(dc),
309 > MetadataUpdateOnAppendInterval: dynamicconfig.MatchingMetadataUpdateOnAppendInterval.Get(dc),
310 > MaxTaskQueueIdleTime: dynamicconfig.MatchingMaxTaskQueueIdleTime.Get(dc),
311 > LongPollExpirationInterval: dynamicconfig.MatchingLongPollExpirationInterval.Get(dc),
312 > BacklogTaskForwardTimeout: dynamicconfig.MatchingBacklogTaskForwardTimeout.Get(dc),
313 > ForwardPollRetryMaxInterval: dynamicconfig.MatchingForwardPollRetryMaxInterval.Get(dc),
314 > MinTaskThrottlingBurstSize: dynamicconfig.MatchingMinTaskThrottlingBurstSize.Get(dc),
315 > MaxTaskDeleteBatchSize: dynamicconfig.MatchingMaxTaskDeleteBatchSize.Get(dc),
316 > TaskDeleteInterval: dynamicconfig.MatchingTaskDeleteInterval.Get(dc),
317 > OutstandingTaskAppendsThreshold: dynamicconfig.MatchingOutstandingTaskAppendsThreshold.Get(dc),
318 > MaxTaskBatchSize: dynamicconfig.MatchingMaxTaskBatchSize.Get(dc),
319 > ThrottledLogRPS: dynamicconfig.MatchingThrottledLogRPS.Get(dc),
320 > NumTaskqueueWritePartitions: dynamicconfig.MatchingNumTaskqueueWritePartitions.Get(dc),
321 > NumTaskqueueReadPartitions: dynamicconfig.MatchingNumTaskqueueReadPartitions.Get(dc),
322 > NumTaskqueueReadPartitionsSub: dynamicconfig.MatchingNumTaskqueueReadPartitions.Subscribe(dc),
323 > BreakdownMetricsByTaskQueue: dynamicconfig.MetricsBreakdownByTaskQueue.Get(dc),
324 > BreakdownMetricsByPartition: dynamicconfig.MetricsBreakdownByPartition.Get(dc),
325 > BreakdownMetricsByBuildID: dynamicconfig.MetricsBreakdownByBuildID.Get(dc),
326 > EnableWorkerPluginMetrics: dynamicconfig.MatchingEnableWorkerPluginMetrics.Get(dc),
327 > EnablePollerAutoscalingMetrics: dynamicconfig.MatchingEnablePollerAutoscalingMetrics.Get(dc),
328 > ExternalPayloadsEnabled: dynamicconfig.ExternalPayloadsEnabled.Get(dc),
329 > WorkerRegistryNumBuckets: dynamicconfig.MatchingWorkerRegistryNumBuckets.Get(dc),
330 > WorkerRegistryEntryTTL: dynamicconfig.MatchingWorkerRegistryEntryTTL.Get(dc),
331 > WorkerRegistryMinEvictAge: dynamicconfig.MatchingWorkerRegistryMinEvictAge.Get(dc),
332 > WorkerRegistryMaxEntries: dynamicconfig.MatchingWorkerRegistryMaxEntries.Get(dc),
333 > WorkerRegistryEvictionInterval: dynamicconfig.MatchingWorkerRegistryEvictionInterval.Get(dc),
334 > ForwarderMaxOutstandingPolls: dynamicconfig.MatchingForwarderMaxOutstandingPolls.Get(dc),
335 > ForwarderMaxOutstandingTasks: dynamicconfig.MatchingForwarderMaxOutstandingTasks.Get(dc),
336 > ForwarderMaxRatePerSecond: dynamicconfig.MatchingForwarderMaxRatePerSecond.Get(dc),
337 > ForwarderMaxChildrenPerNode: dynamicconfig.MatchingForwarderMaxChildrenPerNode.Get(dc),
338 > AlignMembershipChange: dynamicconfig.MatchingAlignMembershipChange.Get(dc),
339 > ShutdownDrainDuration: dynamicconfig.MatchingShutdownDrainDuration.Get(dc),
340 > VersionCompatibleSetLimitPerQueue: dynamicconfig.VersionCompatibleSetLimitPerQueue.Get(dc),
341 > VersionBuildIdLimitPerQueue: dynamicconfig.VersionBuildIdLimitPerQueue.Get(dc),
342 > AssignmentRuleLimitPerQueue: dynamicconfig.AssignmentRuleLimitPerQueue.Get(dc),
343 > RedirectRuleLimitPerQueue: dynamicconfig.RedirectRuleLimitPerQueue.Get(dc),
344 > RedirectRuleMaxUpstreamBuildIDsPerQueue: dynamicconfig.RedirectRuleMaxUpstreamBuildIDsPerQueue.Get(dc),
345 > DeletedRuleRetentionTime: dynamicconfig.MatchingDeletedRuleRetentionTime.Get(dc),
346 > PollerHistoryTTL: dynamicconfig.PollerHistoryTTL.Get(dc),
347 > EnableMatchingFanOutForPollCancellation: dynamicconfig.EnableMatchingFanOutForPollCancellation.Get(dc),
348 > ReachabilityBuildIdVisibilityGracePeriod: dynamicconfig.ReachabilityBuildIdVisibilityGracePeriod.Get(dc),
349 > ReachabilityCacheOpenWFsTTL: dynamicconfig.ReachabilityCacheOpenWFsTTL.Get(dc),
350 > ReachabilityCacheClosedWFsTTL: dynamicconfig.ReachabilityCacheClosedWFsTTL.Get(dc),
351 > TaskQueueLimitPerBuildId: dynamicconfig.TaskQueuesPerBuildIdLimit.Get(dc),
352 > GetUserDataLongPollTimeout: dynamicconfig.MatchingGetUserDataLongPollTimeout.Get(dc), // Use -10 seconds so that we send back empty response instead of timeout
353 > GetUserDataRefresh: dynamicconfig.MatchingGetUserDataRefresh.Get(dc),
354 > EphemeralDataUpdateInterval: dynamicconfig.MatchingEphemeralDataUpdateInterval.Get(dc),
355 > BacklogMetricsEmitInterval: dynamicconfig.MatchingBacklogMetricsEmitInterval.Get(dc),
356 > PriorityBacklogForwarding: dynamicconfig.MatchingPriorityBacklogForwarding.Get(dc),
357 > BacklogNegligibleAge: dynamicconfig.MatchingBacklogNegligibleAge.Get(dc),
358 > MaxWaitForPollerBeforeFwd: dynamicconfig.MatchingMaxWaitForPollerBeforeFwd.Get(dc),
359 > QueryPollerUnavailableWindow: dynamicconfig.QueryPollerUnavailableWindow.Get(dc),
360 > WorkerControllerNoPollerHookWindow: dynamicconfig.WorkerControllerNoPollerHookWindow.Get(dc),
361 > EmitTaskDispatchLatencyAtPoll: dynamicconfig.MatchingEmitTaskDispatchLatencyAtPoll.Get(dc),
362 > QueryWorkflowTaskTimeoutLogRate: dynamicconfig.MatchingQueryWorkflowTaskTimeoutLogRate.Get(dc),
363 > MembershipUnloadDelay: dynamicconfig.MatchingMembershipUnloadDelay.Get(dc),
364 > TaskQueueInfoByBuildIdTTL: dynamicconfig.TaskQueueInfoByBuildIdTTL.Get(dc),
365 > PriorityLevels: dynamicconfig.MatchingPriorityLevels.Get(dc),
366 > RateLimiterRefreshInterval: time.Minute,
367 > FairnessKeyRateLimitCacheSize: dynamicconfig.MatchingFairnessKeyRateLimitCacheSize.Get(dc),
368 > MaxFairnessKeyWeightOverrides: dynamicconfig.MatchingMaxFairnessKeyWeightOverrides.Get(dc),
369 > MaxIDLengthLimit: dynamicconfig.MaxIDLengthLimit.Get(dc),
370 >
371 > AdminNamespaceToPartitionDispatchRate: dynamicconfig.AdminMatchingNamespaceToPartitionDispatchRate.Get(dc),
372 > AdminNamespaceToPartitionRateSub: dynamicconfig.AdminMatchingNamespaceToPartitionDispatchRate.Subscribe(dc),
373 > AdminNamespaceTaskqueueToPartitionDispatchRate: dynamicconfig.AdminMatchingNamespaceTaskqueueToPartitionDispatchRate.Get(dc),
374 > AdminNamespaceTaskqueueToPartitionRateSub: dynamicconfig.AdminMatchingNamespaceTaskqueueToPartitionDispatchRate.Subscribe(dc),
375 >
376 > VisibilityPersistenceMaxReadQPS: dynamicconfig.VisibilityPersistenceMaxReadQPS.Get(dc),
377 > VisibilityPersistenceMaxWriteQPS: dynamicconfig.VisibilityPersistenceMaxWriteQPS.Get(dc),
378 > VisibilityPersistenceSlowQueryThreshold: dynamicconfig.VisibilityPersistenceSlowQueryThreshold.Get(dc),
379 > EnableReadFromSecondaryVisibility: dynamicconfig.EnableReadFromSecondaryVisibility.Get(dc),
380 > VisibilityEnableShadowReadMode: dynamicconfig.VisibilityEnableShadowReadMode.Get(dc),
381 > VisibilityDisableOrderByClause: dynamicconfig.VisibilityDisableOrderByClause.Get(dc),
382 > VisibilityEnableManualPagination: dynamicconfig.VisibilityEnableManualPagination.Get(dc),
383 > VisibilityEnableUnifiedQueryConverter: dynamicconfig.VisibilityEnableUnifiedQueryConverter.Get(dc),
384 >
385 > ListNexusEndpointsLongPollTimeout: dynamicconfig.MatchingListNexusEndpointsLongPollTimeout.Get(dc),
386 > NexusEndpointsRefreshInterval: dynamicconfig.MatchingNexusEndpointsRefreshInterval.Get(dc),
387 > MinDispatchTaskTimeout: nexusoperations.MinDispatchTaskTimeout.Get(dc),
388 >
389 > PollerScalingBacklogAgeScaleUp: dynamicconfig.MatchingPollerScalingBacklogAgeScaleUp.Get(dc),
390 > PollerScalingWaitTime: dynamicconfig.MatchingPollerScalingWaitTime.Get(dc),
391 > PollerScalingDecisionsPerSecond: dynamicconfig.MatchingPollerScalingDecisionsPerSecond.Get(dc),
392 > PollerScalingTaskAddToDispatchRatio: dynamicconfig.MatchingPollerScalingTaskAddToDispatchRatio.Get(dc),
393 > EnablePollerScalingDecisionMetrics: dynamicconfig.MatchingEnablePollerScalingDecisionMetrics.Get(dc),
394 >
395 > FairnessCounter: dynamicconfig.MatchingFairnessCounter.Get(dc),
396 > FairnessPassDither: dynamicconfig.MatchingFairnessPassDither.Get(dc),
397 > PartitionScaleAllowedDrift: dynamicconfig.MatchingPartitionScaleAllowedDrift.Get(dc),
398 > PartitionScaleManagerSettings: dynamicconfig.MatchingPartitionScaleManager.Get(dc),
399 >
400 > LogAllReqErrors: dynamicconfig.LogAllReqErrors.Get(dc),
401 >
402 > RateLimitFractionProvider: defaultTaskQueueRateLimitFractionProvider,
403 > }
404 > }
405
406 > func newTaskQueueConfig(tq *tqid.TaskQueue, config *Config, ns namespace.Name) *taskQueueConfig { config.go
407 > taskQueueName := tq.Name()
408 > taskType := tq.TaskType()
409 > priorityLevels := priorityKey(config.PriorityLevels(ns.String(), taskQueueName, taskType))
410 > priorityLevels = max(priorityLevels, min(priorityLevels, maxPriorityLevels), 1)
411 > defaultPriorityKey := (priorityLevels + 1) / 2
412 >
413 > return &taskQueueConfig{
414 > RangeSize: config.RangeSize,
415 > NewMatcherSub: func(cb func(dynamicconfig.GradualChange[bool])) (dynamicconfig.GradualChange[bool], func()) {
416 > return config.NewMatcherSub(ns.String(), taskQueueName, taskType, cb) config.go
417 > },
418 > EnableFairnessSub: func(cb func(dynamicconfig.GradualChange[bool])) (dynamicconfig.GradualChange[bool], func()) {
419 > return config.EnableFairnessSub(ns.String(), taskQueueName, taskType, cb)
420 > },
421 > EnableMigration: func() bool { config.go
422 > return config.EnableMigration(ns.String(), taskQueueName, taskType)
423 > },
424 AutoEnableV2: func() bool {
425 v, _ := config.AutoEnableV2Sub(ns.String(), taskQueueName, taskType, nil)
426 return v
427 },
428 > AutoEnableV2Sub: func(cb func(bool)) (bool, func()) { config.go
429 > return config.AutoEnableV2Sub(ns.String(), taskQueueName, taskType, cb)
430 > },
431 > GetTasksBatchSize: func() int { config.go
432 > return config.GetTasksBatchSize(ns.String(), taskQueueName, taskType)
433 > },
434 > GetTasksReloadAt: func() int { config.go
435 > return config.GetTasksReloadAt(ns.String(), taskQueueName, taskType)
436 > },
437 ForceReadTasksOnWrite: func() bool {
438 return config.ForceReadTasksOnWrite(ns.String(), taskQueueName, taskType)
439 },
440 > UpdateAckInterval: func() time.Duration { config.go
441 > return config.UpdateAckInterval(ns.String(), taskQueueName, taskType)
442 > },
443 > MetadataUpdateOnAppendInterval: func() time.Duration { config.go
444 > return config.MetadataUpdateOnAppendInterval(ns.String(), taskQueueName, taskType)
445 > },
446 > MaxTaskQueueIdleTime: func() time.Duration { config.go
447 > return config.MaxTaskQueueIdleTime(ns.String(), taskQueueName, taskType)
448 > },
449 MinTaskThrottlingBurstSize: func() int {
450 return config.MinTaskThrottlingBurstSize(ns.String(), taskQueueName, taskType)
453 return config.SyncMatchWaitDuration(ns.String(), taskQueueName, taskType)
454 },
455 > EphemeralDataUpdateInterval: func() time.Duration { config.go
456 > return config.EphemeralDataUpdateInterval(ns.String(), taskQueueName, taskType)
457 > },
458 > BacklogMetricsEmitInterval: func() time.Duration { config.go
459 > return config.BacklogMetricsEmitInterval(ns.String(), taskQueueName, taskType)
460 > },
461 PriorityBacklogForwarding: func() bool {
462 return config.PriorityBacklogForwarding(ns.String(), taskQueueName, taskType)
473 return config.EmitTaskDispatchLatencyAtPoll(ns.String(), taskQueueName, taskType)
474 },
475 > LongPollExpirationInterval: func() time.Duration { config.go
476 > return config.LongPollExpirationInterval(ns.String(), taskQueueName, taskType)
477 > },
478 > BacklogTaskForwardTimeout: func() time.Duration { config.go
479 > return config.BacklogTaskForwardTimeout(ns.String(), taskQueueName, taskType)
480 > },
481 ForwardPollRetryMaxInterval: func() time.Duration {
482 return config.ForwardPollRetryMaxInterval(ns.String(), taskQueueName, taskType)
483 },
484 > MaxTaskDeleteBatchSize: func() int { config.go
485 > return config.MaxTaskDeleteBatchSize(ns.String(), taskQueueName, taskType)
486 > },
487 > TaskDeleteInterval: func() time.Duration { config.go
488 > return config.TaskDeleteInterval(ns.String(), taskQueueName, taskType)
489 > },
490 PriorityLevels: priorityLevels,
491 DefaultPriorityKey: defaultPriorityKey,
495 GetUserDataInitialRefresh: ioTimeout,
496 GetUserDataRefresh: config.GetUserDataRefresh,
497 > OutstandingTaskAppendsThreshold: func() int { config.go
498 > return config.OutstandingTaskAppendsThreshold(ns.String(), taskQueueName, taskType)
499 > },
500 > MaxTaskBatchSize: func() int { config.go
501 > return config.MaxTaskBatchSize(ns.String(), taskQueueName, taskType)
502 > },
503 > NumWritePartitions: func() int { config.go
504 > return max(1, config.NumTaskqueueWritePartitions(ns.String(), taskQueueName, taskType))
505 > },
506 > NumReadPartitions: func() int { config.go
507 > return max(1, config.NumTaskqueueReadPartitions(ns.String(), taskQueueName, taskType))
508 > },
509 > NumReadPartitionsSub: func(cb func(int)) (int, func()) { config.go
510 > return config.NumTaskqueueReadPartitionsSub(ns.String(), taskQueueName, taskType, cb)
511 > },
512 > BreakdownMetricsByTaskQueue: func() bool { config.go
513 > return config.BreakdownMetricsByTaskQueue(ns.String(), taskQueueName, taskType)
514 > },
515 > BreakdownMetricsByPartition: func() bool { config.go
516 > return config.BreakdownMetricsByPartition(ns.String(), taskQueueName, taskType)
517 > },
518 > BreakdownMetricsByBuildID: func() bool { config.go
519 > return config.BreakdownMetricsByBuildID(ns.String(), taskQueueName, taskType)
520 > },
521 AdminNamespaceToPartitionDispatchRate: func() float64 {
522 return config.AdminNamespaceToPartitionDispatchRate(ns.String())
523 },
524 > AdminNamespaceToPartitionRateSub: func(cb func(float64)) (float64, func()) { config.go
525 > return config.AdminNamespaceToPartitionRateSub(ns.String(), cb)
526 > },
527 AdminNamespaceTaskQueueToPartitionDispatchRate: func() float64 {
528 return config.AdminNamespaceTaskqueueToPartitionDispatchRate(ns.String(), taskQueueName, taskType)
529 },
530 > AdminNamespaceTaskQueueToPartitionRateSub: func(cb func(float64)) (float64, func()) { config.go
531 > return config.AdminNamespaceTaskqueueToPartitionRateSub(ns.String(), taskQueueName, taskType, cb)
532 > },
533 forwarderConfig: forwarderConfig{
534 ForwarderMaxOutstandingPolls: func() int {
538 return config.ForwarderMaxOutstandingTasks(ns.String(), taskQueueName, taskType)
539 },
540 > ForwarderMaxRatePerSecond: func() float64 { config.go
541 > return config.ForwarderMaxRatePerSecond(ns.String(), taskQueueName, taskType)
542 > },
543 ForwarderMaxChildrenPerNode: func() int {
544 return max(1, config.ForwarderMaxChildrenPerNode(ns.String(), taskQueueName, taskType))
546 },
547 GetUserDataRetryPolicy: backoff.NewExponentialRetryPolicy(1 * time.Second).WithMaximumInterval(5 * time.Minute).WithExpirationInterval(backoff.NoInterval),
548 > TaskQueueInfoByBuildIdTTL: func() time.Duration { config.go
549 > return config.TaskQueueInfoByBuildIdTTL(ns.String(), taskQueueName, taskType)
550 > },
551 > RateLimitFraction: func() float64 { config.go
552 > return config.RateLimitFractionProvider.GetRateLimitFraction(ns, taskQueueName, taskType)
553 > },
554 RateLimiterRefreshInterval: config.RateLimiterRefreshInterval,
555 > FairnessKeyRateLimitCacheSize: func() int { config.go
556 > return config.FairnessKeyRateLimitCacheSize(ns.String(), taskQueueName, taskType)
557 > },
558 MaxFairnessKeyWeightOverrides: func() int {
559 return config.MaxFairnessKeyWeightOverrides(ns.String(), taskQueueName, taskType)
560 },
561 > PollerHistoryTTL: func() time.Duration { config.go
562 > return config.PollerHistoryTTL(ns.String())
563 > },
564 > PollerScalingBacklogAgeScaleUp: func() time.Duration { config.go
565 > return config.PollerScalingBacklogAgeScaleUp(ns.String(), taskQueueName, taskType)
566 > },
567 > PollerScalingWaitTime: func() time.Duration { config.go
568 > return config.PollerScalingWaitTime(ns.String(), taskQueueName, taskType)
569 > },
570 > PollerScalingDecisionsPerSecond: func() float64 { config.go
571 > return config.PollerScalingDecisionsPerSecond(ns.String(), taskQueueName, taskType)
572 > },
573 > PollerScalingTaskAddToDispatchRatio: func() float64 { config.go
574 > return config.PollerScalingTaskAddToDispatchRatio(ns.String(), taskQueueName, taskType)
575 > },
576 EnablePollerScalingDecisionMetrics: func() bool {
577 return config.EnablePollerScalingDecisionMetrics(ns.String(), taskQueueName, taskType)
586 return config.PartitionScaleAllowedDrift(ns.String(), taskQueueName, taskType)
587 },
588 > PartitionScaleManagerSettings: func() dynamicconfig.PartitionScaleManagerSettings { config.go
589 > return config.PartitionScaleManagerSettings(ns.String(), taskQueueName, taskType)
590 > },
591 MaxVersionsInTaskQueue: func() int { return config.MaxVersionsInTaskQueue(ns.String()) },
592 }
593 }
594
595 > func (c *taskQueueConfig) clipPriority(priority priorityKey) priorityKey { config.go
596 > if priority == 0 {
597 > priority = c.DefaultPriorityKey config.go
598 > }
599 > priority = max(priority, 1) config.go
600 > priority = min(priority, c.PriorityLevels)
601 > return priority
602 }
603
604 > func (c *taskQueueConfig) setDefaultPriority(task *internalTask) { config.go
605 > if task.effectivePriority == 0 {
606 > task.effectivePriority = effectivePriorityFactor * c.DefaultPriorityKey config.go
607 > }
608 }
go.temporal.io/server/common/membership/ringpop/service_resolver.go 245 covered LOC · 61 ranges

Open complete file

99 replicaPoints int,
100 logger log.Logger,
101 > ) *serviceResolver { service_resolver.go
102 > resolver := &serviceResolver{
103 > service: service,
104 > port: port,
105 > rp: rp,
106 > replicaPoints: replicaPoints,
107 > refreshChan: make(chan struct{}),
108 > shutdownCh: make(chan struct{}),
109 > logger: log.With(logger, tag.ComponentServiceResolver, tag.Service(service)),
110 > scheduledRefreshMap: make(map[int64]*time.Timer),
111 > listeners: make(map[string]chan<- *membership.ChangedEvent),
112 > }
113 > resolver.ringAndHosts.Store(ringAndHosts{
114 > ring: newHashRing(replicaPoints),
115 > hosts: make(map[string]*hostInfo),
116 > })
117 > return resolver
118 > }
119
120 > func newHashRing(replicaPoints int) *hashring.HashRing { service_resolver.go
121 > return hashring.New(farm.Fingerprint32, replicaPoints)
122 > }
123
124 // Start starts the oracle
125 > func (r *serviceResolver) Start() { service_resolver.go
126 > r.rp.AddListener(r)
127 > if err := r.refresh(refreshModeAlways); err != nil {
128 r.logger.Fatal("unable to start ring pop service resolver", tag.Error(err))
129 }
130
131 > r.shutdownWG.Add(1) service_resolver.go
132 > go r.refreshRingWorker()
133 }
134
135 // Stop stops the resolver
136 > func (r *serviceResolver) Stop() { service_resolver.go
137 > r.listenerLock.Lock()
138 > defer r.listenerLock.Unlock()
139 > r.rp.RemoveListener(r)
140 > r.ringAndHosts.Store(ringAndHosts{
141 > ring: newHashRing(r.replicaPoints),
142 > hosts: nil,
143 > })
144 > r.listeners = make(map[string]chan<- *membership.ChangedEvent)
145 > close(r.shutdownCh)
146 >
147 > if success := common.AwaitWaitGroup(&r.shutdownWG, time.Minute); !success {
148 r.logger.Warn("service resolver timed out on shutdown.")
149 }
150 }
151
152 > func (r *serviceResolver) RequestRefresh() { service_resolver.go
153 > select {
154 > case r.refreshChan <- struct{}{}: service_resolver.go
155 > default: service_resolver.go
156 }
157 }
158
159 // Lookup finds the host in the ring responsible for serving the given key
160 > func (r *serviceResolver) Lookup(key string) (membership.HostInfo, error) { service_resolver.go
161 > ring, hosts := r.ring()
162 > addr, found := ring.Lookup(key)
163 > if !found {
164 > r.RequestRefresh() service_resolver.go
165 > return nil, membership.ErrInsufficientHosts
166 > }
167 > return hosts[addr], nil service_resolver.go
168 }
169
170 > func (r *serviceResolver) LookupN(key string, n int) []membership.HostInfo { service_resolver.go
171 > if n <= 0 {
172 return nil
173 }
174 > ring, hosts := r.ring() service_resolver.go
175 > addrs := ring.LookupN(key, n)
176 > if len(addrs) == 0 {
177 > r.RequestRefresh() service_resolver.go
178 > return nil
179 > }
180 > return util.MapSlice(addrs, func(addr string) membership.HostInfo { return hosts[addr] }) service_resolver.go
181 }
182
184 name string,
185 notifyChannel chan<- *membership.ChangedEvent,
186 > ) error { service_resolver.go
187 > r.listenerLock.Lock()
188 > defer r.listenerLock.Unlock()
189 > _, ok := r.listeners[name]
190 > if ok {
191 return membership.ErrListenerAlreadyExist
192 }
193 > r.listeners[name] = notifyChannel service_resolver.go
194 > return nil
195 }
196
197 func (r *serviceResolver) RemoveListener(
198 name string,
199 > ) error { service_resolver.go
200 > r.listenerLock.Lock()
201 > defer r.listenerLock.Unlock()
202 > _, ok := r.listeners[name]
203 > if !ok {
204 return nil
205 }
206 > delete(r.listeners, name) service_resolver.go
207 > return nil
208 }
209
213 }
214
215 > func (r *serviceResolver) AvailableMemberCount() int { service_resolver.go
216 > _, hosts := r.ring()
217 > n := 0
218 > for _, host := range hosts {
219 > if !isDraining(host) {
220 > n++
221 > }
222 }
223 > return n service_resolver.go
224 }
225
233 }
234
235 > func (r *serviceResolver) AvailableMembers() []membership.HostInfo { service_resolver.go
236 > _, hosts := r.ring()
237 > var servers []membership.HostInfo
238 > for _, host := range hosts {
239 > if !isDraining(host) {
240 > servers = append(servers, host)
241 > }
242 }
243 > return servers service_resolver.go
244 }
245
247 func (r *serviceResolver) HandleEvent(
248 event events.Event,
250 > // We only about membership.ChangeEvent. Normally ringpop converts membership.ChangeEvent
251 > // into events.RingChangedEvent when its internal hash ring changes, but since we construct
252 > // our own hash rings with filtering, we have to handle the lower-level event ourselves.
253 > if _, ok := event.(rpmembership.ChangeEvent); ok {
254 > r.logger.Debug("Received a ring changed event")
255 > // Note that we receive events asynchronously, possibly out of order.
256 > // We cannot rely on the content of the event, rather we load everything
257 > // from ringpop when we get a notification that something changed.
258 > if err := r.refresh(refreshModeAlways); err != nil {
259 r.logger.Error("error refreshing ring when receiving a ring changed event", tag.Error(err))
260 }
262 }
263
264 > func (r *serviceResolver) refresh(mode refreshMode) error { service_resolver.go
265 > var event *membership.ChangedEvent
266 > var err error
267 > defer func() {
268 > if event != nil {
269 > r.emitEvent(event)
270 > }
271 }()
272
273 > r.refreshLock.Lock() service_resolver.go
274 > defer r.refreshLock.Unlock()
275 >
276 > if mode == refreshModeLazy && r.lastRefreshTime.After(time.Now().UTC().Add(-minRefreshInternal)) {
277 > return nil // refreshed too recently service_resolver.go
278 > }
279
280 > event, err = r.refreshLocked() service_resolver.go
281 > return err
282 }
283
284 > func (r *serviceResolver) refreshLocked() (*membership.ChangedEvent, error) { service_resolver.go
285 > hosts, nextEvent, err := r.getReachableMembers()
286 > if err != nil {
287 return nil, err
288 }
289
290 // if we found an add/remove event, schedule another refresh right at that time
291 > r.scheduleRefresh(nextEvent) service_resolver.go
292 >
293 > newMembersMap, changedEvent := r.compareMembers(hosts)
294 > if changedEvent == nil {
295 > return nil, nil
296 > }
297
298 > ring := newHashRing(r.replicaPoints) service_resolver.go
299 > ring.AddMembers(util.MapSlice(hosts, func(h *hostInfo) rpmembership.Member { return h })...)
300
301 > r.lastRefreshTime = time.Now().UTC() service_resolver.go
302 > r.ringAndHosts.Store(ringAndHosts{
303 > ring: ring,
304 > hosts: newMembersMap,
305 > })
306 >
307 > addrs := util.MapSlice(hosts, func(h *hostInfo) string { return h.summary() })
308 > slices.Sort(addrs)
309 > r.logger.Info("Current reachable members", tag.Addresses(addrs))
310 >
311 > return changedEvent, nil
312 }
313
314 > func (r *serviceResolver) scheduleRefresh(nextEvent int64) { service_resolver.go
315 > if nextEvent == 0 {
316 > return
317 > }
318 if _, ok := r.scheduledRefreshMap[nextEvent]; ok {
319 return // already have a timer scheduled for this time
333 }
334
335 > func (r *serviceResolver) getReachableMembers() ([]*hostInfo, int64, error) { service_resolver.go
336 > members, err := r.rp.GetReachableMemberObjects(swim.MemberWithLabelAndValue(roleKey, string(r.service)))
337 > if err != nil {
338 return nil, 0, err
339 }
342 // need to keep track of one event since we'll refresh at that time and find the next one.
343 // Note that nextEvent is mutated by the filter functions below.
344 > nowUnix := time.Now().Unix() service_resolver.go
345 > nextEvent := int64(math.MaxInt64)
346 >
347 > // Filter by startAt
348 > members = slices.DeleteFunc(members, func(member swim.Member) bool {
349 > startAt, err := parseIntLabel(member, startAtKey)
350 > if err != nil {
351 > return false // ignore label if missing or can't parse
352 > } else if startAt <= nowUnix {
353 return false // start time is in the past
354 }
359
360 // Filter by stopAt
361 > members = slices.DeleteFunc(members, func(member swim.Member) bool { service_resolver.go
362 > stopAt, err := parseIntLabel(member, stopAtKey)
363 > if err != nil {
364 > return false // ignore label if missing or can't parse
365 > } else if stopAt > nowUnix {
366 // stop time is in the future: schedule refresh at that time
367 nextEvent = min(nextEvent, stopAt)
372
373 // Turn swim.Members into hostInfo
374 > hosts := make([]*hostInfo, len(members)) service_resolver.go
375 > for i, member := range members {
376 > servicePort := r.port
377 >
378 > // Each temporal service in the ring should advertise which port it has its gRPC listener
379 > // on via a service label. If we cannot find the label, we will assume that the
380 > // temporal service is listening on the same port that this node is listening on.
381 > servicePortLabel, ok := member.Label(portKey)
382 > if ok {
383 > servicePort, err = strconv.Atoi(servicePortLabel)
384 > if err != nil {
385 return nil, 0, err
386 }
389 }
390
391 > hostPort, err := replaceServicePort(member.Address, servicePort) service_resolver.go
392 > if err != nil {
393 return nil, 0, err
394 }
395
396 // We can share member.Labels without copying since we never modify it.
397 > hosts[i] = newHostInfo(hostPort, member.Labels) service_resolver.go
398 }
399
400 > if nextEvent == math.MaxInt64 { service_resolver.go
401 > nextEvent = 0
402 > }
403 > return hosts, nextEvent, nil
404 }
405
406 > func (r *serviceResolver) emitEvent(event *membership.ChangedEvent) { service_resolver.go
407 > // Notify listeners
408 > r.listenerLock.RLock()
409 > defer r.listenerLock.RUnlock()
410 >
411 > for name, ch := range r.listeners {
412 > select { service_resolver.go
413 > case ch <- event:
414 default:
415 r.logger.Error("Failed to send listener notification, channel full", tag.ListenerName(name))
418 }
419
420 > func (r *serviceResolver) refreshRingWorker() { service_resolver.go
421 > defer r.shutdownWG.Done()
422 >
423 > refreshTicker := time.NewTicker(defaultRefreshInterval)
424 > defer refreshTicker.Stop()
425 >
426 > for {
427 > select {
428 > case <-r.shutdownCh: service_resolver.go
429 > return
430 > case <-r.refreshChan: service_resolver.go
431 > if err := r.refresh(refreshModeLazy); err != nil {
432 r.logger.Error("error refreshing ring by request", tag.Error(err))
433 }
440 }
441
442 > func (r *serviceResolver) ring() (*hashring.HashRing, map[string]*hostInfo) { service_resolver.go
443 > ring := r.ringAndHosts.Load().(ringAndHosts)
444 > return ring.ring, ring.hosts
445 > }
446
447 > func (r *serviceResolver) compareMembers(hosts []*hostInfo) (map[string]*hostInfo, *membership.ChangedEvent) { service_resolver.go
448 > event := &membership.ChangedEvent{}
449 > changed := false
450 > _, prevHosts := r.ring() // note that this is always called with refreshLock so we can't miss an update here
451 > newMembersMap := make(map[string]*hostInfo, len(hosts))
452 > for _, host := range hosts {
453 > newMembersMap[host.GetAddress()] = host
454 > if prev, ok := prevHosts[host.GetAddress()]; !ok {
455 > event.HostsAdded = append(event.HostsAdded, host) service_resolver.go
456 > changed = true
457 > } else if prev.labelsChecksum != host.labelsChecksum { service_resolver.go
458 > event.HostsChanged = append(event.HostsChanged, host) service_resolver.go
459 > changed = true
460 > }
461 }
462 > for addr, prev := range prevHosts { service_resolver.go
463 > if _, ok := newMembersMap[addr]; !ok {
464 > event.HostsRemoved = append(event.HostsRemoved, prev) service_resolver.go
465 > changed = true
466 > }
467 }
468 > if changed { service_resolver.go
469 > return newMembersMap, event
470 > }
471 > return newMembersMap, nil service_resolver.go
472 }
473
474 // buildBroadcastHostPort return the listener hostport from an existing tchannel
475 // and overrides the address with broadcastAddress if specified
476 > func buildBroadcastHostPort(listenerPeerInfo tchannel.LocalPeerInfo, broadcastAddress string) (string, error) { service_resolver.go
477 > // Ephemeral port check copied from ringpop-go/ringpop.go/channelAddressResolver
478 > // Check that TChannel is listening on a real hostport. By default,
479 > // TChannel listens on an ephemeral host/port. The real port is then
480 > // assigned by the OS when ListenAndServe is called. If the hostport is
481 > // ephemeral, it means TChannel is not yet listening and the hostport
482 > // cannot be resolved.
483 > if listenerPeerInfo.IsEphemeralHostPort() {
484 return "", ringpop.ErrEphemeralAddress
485 }
486
487 // Parse listener hostport
488 > listenerIPString, port, err := net.SplitHostPort(listenerPeerInfo.HostPort) service_resolver.go
489 > if err != nil {
490 return "", err
491 }
492
493 // Broadcast IP override
494 > if broadcastAddress != "" { service_resolver.go
495 > // Parse supplied broadcastAddress override
496 > ip := net.ParseIP(broadcastAddress)
497 > if ip == nil {
498 return "", errors.New("broadcastAddress set but unknown failure encountered while parsing")
499 }
500
501 // If no errors, use the parsed IP with the port from our listener
502 > return net.JoinHostPort(ip.String(), port), nil service_resolver.go
503 }
504
516
517 // parseIntLabel returns the value of the given label as an integer.
518 > func parseIntLabel(member swim.Member, label string) (int64, error) { service_resolver.go
519 > str, ok := member.Label(label)
520 > if !ok {
521 > return 0, errMissingLabel
522 > }
523 return strconv.ParseInt(str, 10, 64)
524 }
525
526 > func isDraining(host *hostInfo) bool { service_resolver.go
527 > if drainingStr, ok := host.Label(drainingKey); ok {
528 if draining, err := strconv.ParseBool(drainingStr); err == nil {
529 return draining
530 }
531 }
532 > return false service_resolver.go
533 }
go.temporal.io/server/service/frontend/service.go 245 covered LOC · 13 ranges

Open complete file

267 dc *dynamicconfig.Collection,
268 numHistoryShards int32,
269 > ) *Config { service.go
270 > return &Config{
271 > NumHistoryShards: numHistoryShards,
272 > PersistenceMaxQPS: dynamicconfig.FrontendPersistenceMaxQPS.Get(dc),
273 > PersistenceGlobalMaxQPS: dynamicconfig.FrontendPersistenceGlobalMaxQPS.Get(dc),
274 > PersistenceNamespaceMaxQPS: dynamicconfig.FrontendPersistenceNamespaceMaxQPS.Get(dc),
275 > PersistenceGlobalNamespaceMaxQPS: dynamicconfig.FrontendPersistenceGlobalNamespaceMaxQPS.Get(dc),
276 > PersistencePerShardNamespaceMaxQPS: dynamicconfig.DefaultPerShardNamespaceRPSMax,
277 > PersistenceDynamicRateLimitingParams: dynamicconfig.FrontendPersistenceDynamicRateLimitingParams.Get(dc),
278 > PersistenceQPSBurstRatio: dynamicconfig.PersistenceQPSBurstRatio.Get(dc),
279 >
280 > VisibilityPersistenceMaxReadQPS: dynamicconfig.VisibilityPersistenceMaxReadQPS.Get(dc),
281 > VisibilityPersistenceMaxWriteQPS: dynamicconfig.VisibilityPersistenceMaxWriteQPS.Get(dc),
282 > VisibilityPersistenceSlowQueryThreshold: dynamicconfig.VisibilityPersistenceSlowQueryThreshold.Get(dc),
283 > VisibilityMaxPageSize: dynamicconfig.FrontendVisibilityMaxPageSize.Get(dc),
284 > EnableReadFromSecondaryVisibility: dynamicconfig.EnableReadFromSecondaryVisibility.Get(dc),
285 > VisibilityEnableShadowReadMode: dynamicconfig.VisibilityEnableShadowReadMode.Get(dc),
286 > VisibilityDisableOrderByClause: dynamicconfig.VisibilityDisableOrderByClause.Get(dc),
287 > VisibilityEnableManualPagination: dynamicconfig.VisibilityEnableManualPagination.Get(dc),
288 > VisibilityEnableUnifiedQueryConverter: dynamicconfig.VisibilityEnableUnifiedQueryConverter.Get(dc),
289 > VisibilityAllowList: dynamicconfig.VisibilityAllowList.Get(dc),
290 > SuppressErrorSetSystemSearchAttribute: dynamicconfig.SuppressErrorSetSystemSearchAttribute.Get(dc),
291 >
292 > HistoryMaxPageSize: dynamicconfig.FrontendHistoryMaxPageSize.Get(dc),
293 > RPS: dynamicconfig.FrontendRPS.Get(dc),
294 > GlobalRPS: dynamicconfig.FrontendGlobalRPS.Get(dc),
295 > OperatorRPSRatio: dynamicconfig.OperatorRPSRatio.Get(dc),
296 > NamespaceReplicationInducingAPIsRPS: dynamicconfig.FrontendNamespaceReplicationInducingAPIsRPS.Get(dc),
297 >
298 > MaxNamespaceRPSPerInstance: dynamicconfig.FrontendMaxNamespaceRPSPerInstance.Get(dc),
299 > MaxNamespaceBurstRatioPerInstance: dynamicconfig.FrontendMaxNamespaceBurstRatioPerInstance.Get(dc),
300 > MaxConcurrentLongRunningRequestsPerInstance: dynamicconfig.FrontendMaxConcurrentLongRunningRequestsPerInstance.Get(dc),
301 > MaxGlobalConcurrentLongRunningRequests: dynamicconfig.FrontendGlobalMaxConcurrentLongRunningRequests.Get(dc),
302 > PollWaitForNamespaceRateLimitToken: dynamicconfig.PollWaitForNamespaceRateLimitToken.Get(dc),
303 > MaxNamespaceVisibilityRPSPerInstance: dynamicconfig.FrontendMaxNamespaceVisibilityRPSPerInstance.Get(dc),
304 > MaxNamespaceVisibilityBurstRatioPerInstance: dynamicconfig.FrontendMaxNamespaceVisibilityBurstRatioPerInstance.Get(dc),
305 > MaxNamespaceNamespaceReplicationInducingAPIsRPSPerInstance: dynamicconfig.FrontendMaxNamespaceNamespaceReplicationInducingAPIsRPSPerInstance.Get(dc),
306 > MaxNamespaceNamespaceReplicationInducingAPIsBurstRatioPerInstance: dynamicconfig.FrontendMaxNamespaceNamespaceReplicationInducingAPIsBurstRatioPerInstance.Get(dc),
307 > GlobalWorkerDeploymentReadRPS: dynamicconfig.FrontendGlobalWorkerDeploymentReadRPS.Get(dc),
308 > GlobalWorkerDeploymentReadBurstRatio: dynamicconfig.FrontendGlobalWorkerDeploymentReadBurstRatio.Get(dc),
309 >
310 > GlobalNamespaceRPS: dynamicconfig.FrontendGlobalNamespaceRPS.Get(dc),
311 > InternalFEGlobalNamespaceRPS: dynamicconfig.InternalFrontendGlobalNamespaceRPS.Get(dc),
312 > GlobalNamespaceVisibilityRPS: dynamicconfig.FrontendGlobalNamespaceVisibilityRPS.Get(dc),
313 > InternalFEGlobalNamespaceVisibilityRPS: dynamicconfig.InternalFrontendGlobalNamespaceVisibilityRPS.Get(dc),
314 > // Overshoot since these low rate limits don't work well in an uncoordinated global limiter.
315 > GlobalNamespaceNamespaceReplicationInducingAPIsRPS: dynamicconfig.FrontendGlobalNamespaceNamespaceReplicationInducingAPIsRPS.Get(dc),
316 >
317 > MaxIDLengthLimit: dynamicconfig.MaxIDLengthLimit.Get(dc),
318 > WorkerBuildIdSizeLimit: dynamicconfig.WorkerBuildIdSizeLimit.Get(dc),
319 > ReachabilityTaskQueueScanLimit: dynamicconfig.ReachabilityTaskQueueScanLimit.Get(dc),
320 > ReachabilityQueryBuildIdLimit: dynamicconfig.ReachabilityQueryBuildIdLimit.Get(dc),
321 > ReachabilityCacheOpenWFsTTL: dynamicconfig.ReachabilityCacheOpenWFsTTL.Get(dc),
322 > ReachabilityCacheClosedWFsTTL: dynamicconfig.ReachabilityCacheClosedWFsTTL.Get(dc),
323 > ReachabilityQuerySetDurationSinceDefault: dynamicconfig.ReachabilityQuerySetDurationSinceDefault.Get(dc),
324 > MaxBadBinaries: dynamicconfig.FrontendMaxBadBinaries.Get(dc),
325 > DisableListVisibilityByFilter: dynamicconfig.DisableListVisibilityByFilter.Get(dc),
326 > BlobSizeLimitError: dynamicconfig.BlobSizeLimitError.Get(dc),
327 > BlobSizeLimitWarn: dynamicconfig.BlobSizeLimitWarn.Get(dc),
328 > MemoSizeLimitError: dynamicconfig.MemoSizeLimitError.Get(dc),
329 > ThrottledLogRPS: dynamicconfig.FrontendThrottledLogRPS.Get(dc),
330 > ShutdownDrainDuration: dynamicconfig.FrontendShutdownDrainDuration.Get(dc),
331 > ShutdownFailHealthCheckDuration: dynamicconfig.FrontendShutdownFailHealthCheckDuration.Get(dc),
332 > EnableNamespaceNotActiveAutoForwarding: dynamicconfig.EnableNamespaceNotActiveAutoForwarding.Get(dc),
333 > ForceNamespaceSelectedAPIAutoForwarding: dynamicconfig.ForceNamespaceSelectedAPIAutoForwarding.Get(dc),
334 > NamespaceMinRetentionLocal: dynamicconfig.NamespaceMinRetentionLocal.Get(dc),
335 > NamespaceMinRetentionGlobal: dynamicconfig.NamespaceMinRetentionGlobal.Get(dc),
336 > SearchAttributesNumberOfKeysLimit: dynamicconfig.SearchAttributesNumberOfKeysLimit.Get(dc),
337 > SearchAttributesSizeOfValueLimit: dynamicconfig.SearchAttributesSizeOfValueLimit.Get(dc),
338 > SearchAttributesTotalSizeLimit: dynamicconfig.SearchAttributesTotalSizeLimit.Get(dc),
339 > VisibilityArchivalQueryMaxPageSize: dynamicconfig.VisibilityArchivalQueryMaxPageSize.Get(dc),
340 > DisallowQuery: dynamicconfig.DisallowQuery.Get(dc),
341 > SendRawWorkflowHistory: dynamicconfig.SendRawWorkflowHistory.Get(dc),
342 > DefaultWorkflowRetryPolicy: dynamicconfig.DefaultWorkflowRetryPolicy.Get(dc),
343 > DefaultWorkflowTaskTimeout: dynamicconfig.DefaultWorkflowTaskTimeout.Get(dc),
344 > EnableServerVersionCheck: dynamicconfig.EnableServerVersionCheck.Get(dc),
345 > EnableTokenNamespaceEnforcement: dynamicconfig.EnableTokenNamespaceEnforcement.Get(dc),
346 > ExposeAuthorizerErrors: dynamicconfig.ExposeAuthorizerErrors.Get(dc),
347 > KeepAliveMinTime: dynamicconfig.KeepAliveMinTime.Get(dc),
348 > KeepAlivePermitWithoutStream: dynamicconfig.KeepAlivePermitWithoutStream.Get(dc),
349 > KeepAliveMaxConnectionIdle: dynamicconfig.KeepAliveMaxConnectionIdle.Get(dc),
350 > KeepAliveMaxConnectionAge: dynamicconfig.KeepAliveMaxConnectionAge.Get(dc),
351 > KeepAliveMaxConnectionAgeGrace: dynamicconfig.KeepAliveMaxConnectionAgeGrace.Get(dc),
352 > KeepAliveTime: dynamicconfig.KeepAliveTime.Get(dc),
353 > KeepAliveTimeout: dynamicconfig.KeepAliveTimeout.Get(dc),
354 >
355 > DeleteNamespaceDeleteActivityRPS: dynamicconfig.DeleteNamespaceDeleteActivityRPS.Get(dc),
356 > DeleteNamespacePageSize: dynamicconfig.DeleteNamespacePageSize.Get(dc),
357 > DeleteNamespacePagesPerExecution: dynamicconfig.DeleteNamespacePagesPerExecution.Get(dc),
358 > DeleteNamespaceConcurrentDeleteExecutionsActivities: dynamicconfig.DeleteNamespaceConcurrentDeleteExecutionsActivities.Get(dc),
359 > DeleteNamespaceNamespaceDeleteDelay: dynamicconfig.DeleteNamespaceNamespaceDeleteDelay.Get(dc),
360 >
361 > MaxFairnessWeightOverrideConfigLimit: dynamicconfig.MatchingMaxFairnessKeyWeightOverrides.Get(dc),
362 >
363 > EnableSchedules: dynamicconfig.FrontendEnableSchedules.Get(dc),
364 > EnableChasm: dynamicconfig.EnableChasm.Get(dc),
365 > EnableCHASMSchedulerCreation: dynamicconfig.EnableCHASMSchedulerCreation.Get(dc),
366 > CHASMSchedulerCreationRolloutPercent: dynamicconfig.CHASMSchedulerCreationRolloutPercent.Get(dc),
367 > EnableCHASMSchedulerRouting: dynamicconfig.EnableCHASMSchedulerRouting.Get(dc),
368 > EnableCHASMSchedulerSentinels: dynamicconfig.EnableCHASMSchedulerSentinels.Get(dc),
369 >
370 > // [cleanup-wv-pre-release]
371 > EnableDeployments: dynamicconfig.EnableDeployments.Get(dc),
372 > EnableDeploymentVersions: dynamicconfig.EnableDeploymentVersions.Get(dc),
373 >
374 > EnableBatcher: dynamicconfig.FrontendEnableBatcher.Get(dc),
375 > MaxConcurrentBatchOperation: dynamicconfig.FrontendMaxConcurrentBatchOperationPerNamespace.Get(dc),
376 > MaxExecutionCountBatchOperation: dynamicconfig.FrontendMaxExecutionCountBatchOperationPerNamespace.Get(dc),
377 > MaxConcurrentAdminBatchOperation: dynamicconfig.FrontendMaxConcurrentAdminBatchOperationPerNamespace.Get(dc),
378 > EnableBatchOperationsForStandaloneActivities: dynamicconfig.FrontendEnableBatchOperationsForStandaloneActivities.Get(dc),
379 >
380 > EnableUpdateWorkflowExecution: dynamicconfig.FrontendEnableUpdateWorkflowExecution.Get(dc),
381 > EnableUpdateWorkflowExecutionAsyncAccepted: dynamicconfig.FrontendEnableUpdateWorkflowExecutionAsyncAccepted.Get(dc),
382 > EnableWorkflowUpdateCallbacks: dynamicconfig.EnableWorkflowUpdateCallbacks.Get(dc),
383 > NumConsecutiveWorkflowTaskProblemsToTriggerSearchAttribute: dynamicconfig.NumConsecutiveWorkflowTaskProblemsToTriggerSearchAttribute.Get(dc),
384 >
385 > EnableWorkerVersioningData: dynamicconfig.FrontendEnableWorkerVersioningDataAPIs.Get(dc),
386 > EnableWorkerVersioningWorkflow: dynamicconfig.FrontendEnableWorkerVersioningWorkflowAPIs.Get(dc),
387 > EnableWorkerVersioningRules: dynamicconfig.FrontendEnableWorkerVersioningRuleAPIs.Get(dc),
388 >
389 > CallbackURLMaxLength: dynamicconfig.FrontendCallbackURLMaxLength.Get(dc),
390 > CallbackHeaderMaxSize: dynamicconfig.FrontendCallbackHeaderMaxSize.Get(dc),
391 > MaxCallbacksPerWorkflow: dynamicconfig.MaxCallbacksPerWorkflow.Get(dc),
392 > MaxNexusOperationTokenLength: nexusoperations.MaxOperationTokenLength.Get(dc),
393 > NexusRequestHeadersBlacklist: dynamicconfig.FrontendNexusRequestHeadersBlacklist.Get(dc),
394 > NexusForwardRequestUseEndpoint: dynamicconfig.FrontendNexusForwardRequestUseEndpointDispatch.Get(dc),
395 > NexusOperationsMetricTagConfig: nexusoperations.MetricTagConfiguration.Get(dc),
396 >
397 > LinkMaxSize: dynamicconfig.FrontendLinkMaxSize.Get(dc),
398 > MaxLinksPerRequest: dynamicconfig.FrontendMaxLinksPerRequest.Get(dc),
399 >
400 > CallbackEndpointConfigs: callback.AllowedAddresses.Get(dc),
401 > AdminEnableListHistoryTasks: dynamicconfig.AdminEnableListHistoryTasks.Get(dc),
402 >
403 > MaskInternalErrorDetails: dynamicconfig.FrontendMaskInternalErrorDetails.Get(dc),
404 >
405 > HistoryHostErrorPercentage: dynamicconfig.HistoryHostErrorPercentage.Get(dc),
406 > HistoryHostSelfErrorProportion: dynamicconfig.HistoryHostSelfErrorProportion.Get(dc),
407 > LogAllReqErrors: dynamicconfig.LogAllReqErrors.Get(dc),
408 > EnableEagerWorkflowStart: dynamicconfig.EnableEagerWorkflowStart.Get(dc),
409 > WorkflowRulesAPIsEnabled: dynamicconfig.WorkflowRulesAPIsEnabled.Get(dc),
410 > MaxWorkflowRulesPerNamespace: dynamicconfig.MaxWorkflowRulesPerNamespace.Get(dc),
411 > WorkerHeartbeatsEnabled: dynamicconfig.WorkerHeartbeatsEnabled.Get(dc),
412 > EnableCancelWorkerPollsOnShutdown: dynamicconfig.EnableCancelWorkerPollsOnShutdown.Get(dc),
413 > EnableMatchingFanOutForPollCancellation: dynamicconfig.EnableMatchingFanOutForPollCancellation.Get(dc),
414 > NumTaskQueueReadPartitions: dynamicconfig.MatchingNumTaskqueueReadPartitions.Get(dc),
415 > WorkerCommandsEnabled: dynamicconfig.WorkerCommandsEnabled.Get(dc),
416 > PollerAutoscalingAutoEnroll: dynamicconfig.PollerAutoscalingAutoEnroll.Get(dc),
417 > WorkflowPauseEnabled: dynamicconfig.WorkflowPauseEnabled.Get(dc),
418 > TimeSkippingEnabled: dynamicconfig.TimeSkippingEnabled.Get(dc),
419 > StandaloneNexusOperationsEnabled: chasmnexus.Enabled.Get(dc),
420 > EnableWorkflowTaskCompletionPagination: dynamicconfig.EnableWorkflowTaskCompletionPagination.Get(dc),
421 >
422 > HTTPAllowedHosts: dynamicconfig.FrontendHTTPAllowedHosts.Get(dc),
423 > AllowedExperiments: dynamicconfig.FrontendAllowedExperiments.Get(dc),
424 >
425 > Activity: activity.ConfigProvider(dc),
426 > }
427 > }
428
429 // Service represents the frontend service
460 metricsHandler metrics.Handler,
461 membershipMonitor membership.Monitor,
462 > ) *Service { service.go
463 > return &Service{
464 > config: serviceConfig,
465 > server: server,
466 > healthServer: healthServer,
467 > httpAPIServer: httpAPIServer,
468 > handler: handler,
469 > adminHandler: adminHandler,
470 > operatorHandler: operatorHandler,
471 > versionChecker: versionChecker,
472 > visibilityManager: visibilityMgr,
473 > logger: logger,
474 > grpcListener: grpcListener,
475 > metricsHandler: metricsHandler,
476 > membershipMonitor: membershipMonitor,
477 > }
478 > }
479
480 // Start starts the service
481 > func (s *Service) Start() { service.go
482 > s.logger.Info("frontend starting")
483 >
484 > healthpb.RegisterHealthServer(s.server, s.healthServer)
485 > workflowservice.RegisterWorkflowServiceServer(s.server, s.handler)
486 > adminservice.RegisterAdminServiceServer(s.server, s.adminHandler)
487 > operatorservice.RegisterOperatorServiceServer(s.server, s.operatorHandler)
488 >
489 > reflection.Register(s.server)
490 >
491 > // must start resource first
492 > metrics.RestartCount.With(s.metricsHandler).Record(1)
493 >
494 > s.versionChecker.Start()
495 > s.adminHandler.Start()
496 > s.operatorHandler.Start()
497 > s.handler.Start()
498 >
499 > go func() {
500 > s.logger.Info("Starting to serve on frontend listener")
501 > if err := s.server.Serve(s.grpcListener); err != nil {
502 s.logger.Fatal("Failed to serve on frontend listener", tag.Error(err))
503 }
504 }()
505
506 > if s.httpAPIServer != nil { service.go
507 > go func() { service.go
508 > if err := s.httpAPIServer.Serve(); err != nil {
509 s.logger.Fatal("Failed to serve HTTP API server", tag.Error(err))
510 }
515 }
516
517 > go s.membershipMonitor.Start() service.go
518 }
519
520 // Stop stops the service
521 > func (s *Service) Stop() { service.go
522 > // initiate graceful shutdown:
523 > // 1. Fail rpc health check, this will cause client side load balancer to stop forwarding requests to this node
524 > // 2. wait for failure detection time
525 > // 3. stop taking new requests by returning InternalServiceError
526 > // 4. Wait for X second
527 > // 5. Stop everything forcefully and return
528 >
529 > requestDrainTime := max(time.Second, s.config.ShutdownDrainDuration())
530 > failureDetectionTime := max(0, s.config.ShutdownFailHealthCheckDuration())
531 >
532 > s.logger.Info("ShutdownHandler: Updating gRPC health status to ShuttingDown")
533 > s.healthServer.Shutdown()
534 > s.membershipMonitor.SetDraining(true)
535 >
536 > s.logger.Info("ShutdownHandler: Waiting for others to discover I am unhealthy")
537 > time.Sleep(failureDetectionTime)
538 >
539 > s.handler.Stop()
540 > s.operatorHandler.Stop()
541 > s.adminHandler.Stop()
542 > s.versionChecker.Stop()
543 > s.visibilityManager.Close()
544 >
545 > s.logger.Info("ShutdownHandler: Draining traffic")
546 > // Gracefully stop gRPC server and HTTP API server concurrently
547 > var wg sync.WaitGroup
548 > wg.Go(func() {
549 > t := time.AfterFunc(requestDrainTime, func() {
550 > s.logger.Info("ShutdownHandler: Drain time expired, stopping all traffic") service.go
551 > s.server.Stop()
552 > })
553 > s.server.GracefulStop() service.go
554 > t.Stop()
555 })
556 > if s.httpAPIServer != nil { service.go
557 > wg.Go(func() { service.go
558 > s.httpAPIServer.GracefulStop(requestDrainTime)
559 > })
560 }
561 > wg.Wait() service.go
562 >
563 > if s.metricsHandler != nil {
564 > s.metricsHandler.Stop(s.logger)
565 > }
566
567 > s.logger.Info("frontend stopped") service.go
568 }
go.temporal.io/server/service/matching/user_data_manager.go 241 covered LOC · 65 ranges

Open complete file

147 logger log.Logger,
148 registry namespace.Registry,
149 > ) *userDataManagerImpl { user_data_manager.go
150 > m := &userDataManagerImpl{
151 > onFatalErr: onFatalErr,
152 > onUserDataChanged: onUserDataChanged,
153 > onEphemeralDataChanged: onEphemeralDataChanged,
154 > partition: partition,
155 > userDataChanged: make(chan struct{}),
156 > config: config,
157 > namespaceRegistry: registry,
158 > logger: logger,
159 > matchingClient: matchingClient,
160 > userDataReady: future.NewFuture[struct{}](),
161 > ephemeralDataChanged: make(chan struct{}),
162 > }
163 >
164 > if partition.IsRoot() && partition.TaskType() == enumspb.TASK_QUEUE_TYPE_WORKFLOW {
165 > m.store = store user_data_manager.go
166 > }
167
168 > return m user_data_manager.go
169 }
170
171 > func (m *userDataManagerImpl) Start() { user_data_manager.go
172 > if m.store != nil {
173 > m.goroGroup.Go(m.loadUserData) user_data_manager.go
174 > } else { user_data_manager.go
175 > m.goroGroup.Go(m.fetchUserData) user_data_manager.go
176 > }
177 }
178
179 > func (m *userDataManagerImpl) WaitUntilInitialized(ctx context.Context) error { user_data_manager.go
180 > _, err := m.userDataReady.Get(ctx)
181 > return err
182 > }
183
184 > func (m *userDataManagerImpl) Stop() { user_data_manager.go
185 > m.goroGroup.Cancel()
186 > // Set user data state on stop to wake up anyone blocked on the user data changed channel.
187 > m.setUserDataState(userDataClosed, nil)
188 > }
189
190 // GetUserData returns the user data for this task queue and a channel that signals when the data has been updated.
191 // Do not mutate the returned pointer, as doing so will cause cache inconsistency.
192 // If there is no user data, this can return a nil value with no error.
193 > func (m *userDataManagerImpl) GetUserData() (*persistencespb.VersionedTaskQueueUserData, chan struct{}, error) { user_data_manager.go
194 > m.lock.Lock()
195 > defer m.lock.Unlock()
196 > return m.getUserDataLocked()
197 > }
198
199 > func (m *userDataManagerImpl) getUserDataLocked() (*persistencespb.VersionedTaskQueueUserData, chan struct{}, error) { user_data_manager.go
200 > switch m.userDataState {
201 > case userDataEnabled:
202 > return m.userData, m.userDataChanged, nil
203 > case userDataClosed: user_data_manager.go
204 > return nil, nil, errTaskQueueClosed
205 default:
206 // shouldn't happen
209 }
210
211 > func (m *userDataManagerImpl) setUserDataLocked(userData *persistencespb.VersionedTaskQueueUserData) { user_data_manager.go
212 > m.userData = userData
213 > close(m.userDataChanged)
214 > m.userDataChanged = make(chan struct{})
215 > if m.onUserDataChanged != nil {
216 > go m.onUserDataChanged(m.userData) user_data_manager.go
217 > }
218 }
219
222 // futureError is the error to set on the ready future. If this is non-nil, the task queue will
223 // be unloaded.
224 > func (m *userDataManagerImpl) setUserDataState(userDataState userDataState, futureError error) { user_data_manager.go
225 > m.lock.Lock()
226 > defer m.lock.Unlock()
227 >
228 > if userDataState != m.userDataState && m.userDataState != userDataClosed {
229 > m.userDataState = userDataState user_data_manager.go
230 > close(m.userDataChanged)
231 > m.userDataChanged = make(chan struct{})
232 > }
233
234 > _ = m.userDataReady.SetIfNotReady(struct{}{}, futureError) user_data_manager.go
235 }
236
237 > func (m *userDataManagerImpl) loadUserData(ctx context.Context) error { user_data_manager.go
238 > ctx = m.callerInfoContext(ctx)
239 > err := m.loadUserDataFromDB(ctx)
240 > m.setUserDataState(userDataEnabled, err)
241 >
242 > // At this point, it's possible that an old owner has updated user data after we read it.
243 > // We should re-read it after a few seconds and then periodically after that to ensure that
244 > // we notice if someone else has snuck in a write.
245 > util.InterruptibleSleep(ctx, backoff.Jitter(m.config.GetUserDataInitialRefresh, 0.1))
246 >
247 > for ctx.Err() == nil {
248 if err = m.refreshUserDataFromDB(ctx); errors.Is(err, errUserDataVersionMismatch) {
249 m.onFatalErr(unloadCauseConflict)
253 }
254
255 > return ctx.Err() user_data_manager.go
256 }
257
258 > func (m *userDataManagerImpl) userDataFetchSource() (*tqid.NormalPartition, error) { user_data_manager.go
259 > switch p := m.partition.(type) {
260 > case *tqid.NormalPartition: user_data_manager.go
261 > if p.IsRoot() {
262 > if p.TaskType() == enumspb.TASK_QUEUE_TYPE_WORKFLOW { user_data_manager.go
263 // we shouldn't get here since the root workflow queue should read from the db
264 return nil, tqid.ErrNoParent
265 }
266 // root of other queue types goes to root workflow queue
267 > return p.TaskQueue().Family().TaskQueue(enumspb.TASK_QUEUE_TYPE_WORKFLOW).RootPartition(), nil user_data_manager.go
268 }
269 // go to parent of the same type
274 }
275 return parent, nil
276 > default: user_data_manager.go
277 > normalQ := p.TaskQueue()
278 > // Sticky queues get data from their corresponding normal queue
279 > if normalQ.Name() == "" {
280 // Older SDKs don't send the normal name. That's okay, they just can't use versioning.
281 return nil, errMissingNormalQueueName
283 // sticky queue can only be of workflow type as of now. but to be future-proof, we make sure
284 // change to workflow task queue here
285 > wfTQ := normalQ.Family().TaskQueue(enumspb.TASK_QUEUE_TYPE_WORKFLOW) user_data_manager.go
286 > // use hash of the sticky queue name to pick a consistent "parent"
287 > partitions := m.config.NumReadPartitions()
288 > partition := int(farm.Fingerprint32([]byte(p.RpcName()))) % partitions
289 > return wfTQ.NormalPartition(partition), nil
290 }
291
292 }
293
294 > func (m *userDataManagerImpl) fetchUserData(ctx context.Context) error { user_data_manager.go
295 > ctx = m.callerInfoContext(ctx)
296 >
297 > // fetch from parent partition
298 > fetchSource, err := m.userDataFetchSource()
299 > if err != nil {
300 if err == errMissingNormalQueueName {
301 // pretend we have no user data. this is a sticky queue so the only effect is that we can't
308 // hasFetchedUserData is true if we have gotten a successful reply to GetTaskQueueUserData.
309 // It's used to control whether we do a long poll or a simple get.
310 > hasFetchedUserData := false user_data_manager.go
311 > userDataVersionChanged := false
312 >
313 > op := func(ctx context.Context) error {
314 > knownUserData, _, _ := m.GetUserData()
315 > userDataVersionChanged = false
316 >
317 > callCtx, cancel := context.WithTimeout(ctx, m.config.GetUserDataLongPollTimeout())
318 > defer cancel()
319 >
320 > res, err := m.matchingClient.GetTaskQueueUserData(callCtx, &matchingservice.GetTaskQueueUserDataRequest{
321 > NamespaceId: m.partition.NamespaceId(),
322 > TaskQueue: fetchSource.RpcName(),
323 > TaskQueueType: fetchSource.TaskType(),
324 > LastKnownUserDataVersion: knownUserData.GetVersion(),
325 > LastKnownEphemeralDataVersion: m.getIncomingEphemeralDataVersion(),
326 > WaitNewData: hasFetchedUserData,
327 > })
328 > if err != nil {
329 > // don't log on context canceled, produces too much log spam at shutdown user_data_manager.go
330 > if !common.IsContextCanceledErr(err) {
331 > m.logger.Error("error fetching user data from parent", tag.Error(err)) user_data_manager.go
332 > }
333 > var unimplErr *serviceerror.Unimplemented user_data_manager.go
334 > if errors.As(err, &unimplErr) {
335 // This might happen during a deployment. The older version couldn't have had any user data,
336 // so we act as if it just returned an empty response and set ourselves ready.
339 m.setUserDataState(userDataEnabled, nil)
340 }
341 > return err user_data_manager.go
342 }
343 // If the root partition returns nil here, then that means our data matched, and we don't need to update.
345 // It can't be nil due to removing versions, as that would result in a non-nil container with
346 // nil inner fields.
347 > if res.GetUserData() != nil { user_data_manager.go
348 m.setUserDataForNonOwningPartition(res.GetUserData())
349 userDataVersionChanged = res.GetUserData().GetVersion() != knownUserData.GetVersion()
350 m.logNewUserData("fetched user data from parent", res.GetUserData())
351 > } else { user_data_manager.go
352 > m.logger.Debug("fetched user data from parent, no change") user_data_manager.go
353 > }
354 > if res.GetEphemeralData() != nil { user_data_manager.go
355 m.gotIncomingEphemeralData(res.EphemeralData)
356 }
357 > hasFetchedUserData = true user_data_manager.go
358 > m.setUserDataState(userDataEnabled, nil)
359 > return nil
360 }
361
362 > fastResponseCounter := 0 user_data_manager.go
363 > minWaitTime := m.config.GetUserDataMinWaitTime
364 >
365 > for ctx.Err() == nil {
366 > start := time.Now()
367 > _ = backoff.ThrottleRetryContext(ctx, op, m.config.GetUserDataRetryPolicy, nil)
368 > elapsed := time.Since(start)
369 >
370 > // In general, we want to start a new call immediately on completion of the previous
371 > // one. But if the remote is broken and returns success immediately, we might end up
372 > // spinning. So enforce a minimum wait time that increases as long as we keep getting
373 > // very fast replies.
374 > // If the user data version changed it means new data was received so we skip this check.
375 > if !userDataVersionChanged && elapsed < m.config.GetUserDataMinWaitTime {
376 > if fastResponseCounter >= maxFastUserDataFetches { user_data_manager.go
377 // maxFastUserDataFetches or more consecutive fast responses, let's throttle!
378 util.InterruptibleSleep(ctx, minWaitTime-elapsed)
380 // between a fast reply and a timeout.
381 minWaitTime = min(minWaitTime*2, m.config.GetUserDataLongPollTimeout()/2)
382 > } else { user_data_manager.go
383 > // Not yet maxFastUserDataFetches consecutive fast responses. A few rapid refreshes for versioned queues
384 > // is expected when the first poller arrives. We do not want to slow down the queue
385 > // for that.
386 > fastResponseCounter++
387 > }
388 > } else { user_data_manager.go
389 > fastResponseCounter = 0
390 > minWaitTime = m.config.GetUserDataMinWaitTime
391 > }
392 }
393
394 > return ctx.Err() user_data_manager.go
395 }
396
397 // Loads user data from db (called only on initialization of taskQueuePartitionManager).
398 > func (m *userDataManagerImpl) loadUserDataFromDB(ctx context.Context) error { user_data_manager.go
399 > response, err := m.store.GetTaskQueueUserData(ctx, &persistence.GetTaskQueueUserDataRequest{
400 > NamespaceID: m.partition.NamespaceId(),
401 > TaskQueue: m.partition.TaskQueue().Name(),
402 > })
403 > if common.IsNotFoundError(err) {
404 > // not all task queues have user data user_data_manager.go
405 > response, err = &persistence.GetTaskQueueUserDataResponse{}, nil
406 > }
407 > if err != nil { user_data_manager.go
408 return err
409 }
410
411 > m.lock.Lock() user_data_manager.go
412 > defer m.lock.Unlock()
413 > m.setUserDataLocked(response.UserData)
414 > m.logNewUserData("loaded user data from db", response.UserData)
415 >
416 > return nil
417 }
418
580 ctx context.Context,
581 req *matchingservice.GetTaskQueueUserDataRequest,
582 > ) (*matchingservice.GetTaskQueueUserDataResponse, error) { user_data_manager.go
583 > lastVersion := req.GetLastKnownUserDataVersion()
584 > if lastVersion < 0 {
585 return nil, serviceerror.NewInvalidArgument("last_known_user_data_version must not be negative")
586 }
587 > lastEphVersion := req.GetLastKnownEphemeralDataVersion() user_data_manager.go
588 >
589 > if req.WaitNewData {
590 > var cancel context.CancelFunc user_data_manager.go
591 > ctx, cancel = contextutil.WithDeadlineBuffer(ctx, m.config.GetUserDataLongPollTimeout(), m.config.GetUserDataReturnBudget)
592 > defer cancel()
593 > }
594
595 > for { user_data_manager.go
596 > userData, userDataChanged, err := m.GetUserData()
597 > ephData, ephDataChanged := m.getMergedEphemeralData()
598 > if errors.Is(err, errTaskQueueClosed) {
599 > // If we're closing, return a success with no data, as if the request expired. We shouldn't user_data_manager.go
600 > // close due to idleness (because of the MarkAlive above), so we're probably closing due to a
601 > // change of ownership. The caller will retry and be redirected to the new owner.
602 > m.logger.Debug("returning empty user data (closing)", tag.Bool("long-poll", req.WaitNewData))
603 > return &matchingservice.GetTaskQueueUserDataResponse{}, nil
604 > } else if err != nil { user_data_manager.go
605 return nil, err
606 }
607 > newUserData := userData.GetVersion() > lastVersion user_data_manager.go
608 > // noEphemeralDataVersion means the caller does not want ephemeral data
609 > newEphData := lastEphVersion != noEphemeralDataVersion && ephData.GetVersion() > lastEphVersion
610 > if newUserData || newEphData {
611 m.logger.Debug("returning user data",
612 tag.Bool("long-poll", req.WaitNewData),
624 }
625 return &res, nil
626 > } else if userData != nil && userData.Version < lastVersion && m.store != nil { user_data_manager.go
627 // When m.store == nil it means this is a non-owner partition, so it is possible
628 // for the requested version to be greater than the known version if there are
642 // have newer data. Note that "version" is a timestamp.
643
644 > if !req.WaitNewData { user_data_manager.go
645 > m.logger.Debug("returning empty user data (no data or no change)") user_data_manager.go
646 > return &matchingservice.GetTaskQueueUserDataResponse{}, nil
647 > }
648
649 // long-poll: wait for data to change/appear
650 > select { user_data_manager.go
651 > case <-ctx.Done(): user_data_manager.go
652 > m.logger.Debug("returning empty user data (expired)",
653 > tag.Int64("request-known-version", lastVersion),
654 > tag.UserDataVersion(userData.GetVersion()),
655 > )
656 > return &matchingservice.GetTaskQueueUserDataResponse{}, nil
657 > case <-userDataChanged: user_data_manager.go
658 > m.logger.Debug("user data changed while blocked in long poll")
659 case <-ephDataChanged:
660 m.logger.Debug("ephemeral data changed while blocked in long poll")
775
776 // PartitionScale gets the current partition scale state.
777 > func (m *userDataManagerImpl) PartitionScale() *taskqueuespb.PartitionScaleInfo { user_data_manager.go
778 > m.lock.Lock()
779 > defer m.lock.Unlock()
780 > return m.mergedEphemeralData.GetData().GetScale()
781 > }
782
783 func (m *userDataManagerImpl) gotIncomingEphemeralData(eph *taskqueuespb.VersionedEphemeralData) {
815 }
816
817 > func (m *userDataManagerImpl) getMergedEphemeralData() (*taskqueuespb.VersionedEphemeralData, chan struct{}) { user_data_manager.go
818 > m.lock.Lock()
819 > defer m.lock.Unlock()
820 >
821 > return m.mergedEphemeralData, m.ephemeralDataChanged
822 > }
823
824 > func (m *userDataManagerImpl) getIncomingEphemeralDataVersion() int64 { user_data_manager.go
825 > if m.partition.IsRoot() {
826 > // The root activity/nexus partition should not fetch ephemeral data from the root user_data_manager.go
827 > // workflow partition.
828 > return noEphemeralDataVersion
829 > }
830
831 > m.lock.Lock() user_data_manager.go
832 > defer m.lock.Unlock()
833 >
834 > return m.incomingEphemeralData.GetVersion()
835 }
836
865 }
866
867 > func (m *userDataManagerImpl) callerInfoContext(ctx context.Context) context.Context { user_data_manager.go
868 > ns, _ := m.namespaceRegistry.GetNamespaceName(namespace.ID(m.partition.NamespaceId()))
869 > return headers.SetCallerInfo(ctx, headers.NewBackgroundHighCallerInfo(ns.String()))
870 > }
871
872 > func (m *userDataManagerImpl) logNewUserData(message string, data *persistencespb.VersionedTaskQueueUserData, tags ...tag.Tag) { user_data_manager.go
873 > m.logger.Info(message,
874 > append(tags,
875 > tag.UserDataVersion(data.GetVersion()),
876 > tag.Timestamp(hybrid_logical_clock.UTC(data.GetData().GetClock())),
877 > )...)
878 > }
go.temporal.io/server/service/history/shard/controller_impl.go 238 covered LOC · 60 ranges

Open complete file

75 hostInfoProvider membership.HostInfoProvider,
76 contextFactory ContextFactory,
77 > ) *ControllerImpl { controller_impl.go
78 > hostIdentity := hostInfoProvider.HostInfo().Identity()
79 > contextTaggedLogger := log.With(logger, tag.ComponentShardController, tag.Address(hostIdentity))
80 > taggedMetricsHandler := metricsHandler.WithTags(metrics.OperationTag(metrics.HistoryShardControllerScope))
81 >
82 > ownership := newOwnership(
83 > config,
84 > historyServiceResolver,
85 > hostInfoProvider,
86 > contextTaggedLogger,
87 > taggedMetricsHandler,
88 > )
89 >
90 > c := &ControllerImpl{
91 > config: config,
92 > contextFactory: contextFactory,
93 > contextTaggedLogger: contextTaggedLogger,
94 > historyShards: make(map[int32]historyi.ControllableContext),
95 > hostInfoProvider: hostInfoProvider,
96 > ownership: ownership,
97 > taggedMetricsHandler: taggedMetricsHandler,
98 > shardCountSubscriptions: map[*shardCountSubscription]struct{}{},
99 > initialShardsAcquired: future.NewFuture[struct{}](),
100 > }
101 > c.lingerState.shards = make(map[historyi.ControllableContext]struct{})
102 > return c
103 > }
104
105 > func (c *ControllerImpl) Start() { controller_impl.go
106 > if !atomic.CompareAndSwapInt32(
107 > &c.status,
108 > common.DaemonStatusInitialized,
109 > common.DaemonStatusStarted,
110 > ) {
111 return
112 }
113
114 > c.ownership.start(c) controller_impl.go
115 >
116 > c.contextTaggedLogger.Info("", tag.LifeCycleStarted)
117 }
118
119 > func (c *ControllerImpl) Stop() { controller_impl.go
120 > if !atomic.CompareAndSwapInt32(
121 > &c.status,
122 > common.DaemonStatusStarted,
123 > common.DaemonStatusStopped,
124 > ) {
125 return
126 }
127
128 > c.initialShardsAcquired.SetIfNotReady(struct{}{}, context.Canceled) controller_impl.go
129 >
130 > c.ownership.stop()
131 >
132 > c.doShutdown()
133 >
134 > c.contextTaggedLogger.Info("", tag.LifeCycleStopped)
135 }
136
137 > func (c *ControllerImpl) GetPingChecks() []pingable.Check { controller_impl.go
138 > return []pingable.Check{{
139 > Name: "shard controller",
140 > Timeout: 10 * time.Second,
141 > Ping: func() []pingable.Pingable {
142 > // we only need to read but get write lock to make sure we can
143 > c.Lock()
144 > defer c.Unlock()
145 > out := make([]pingable.Pingable, 0, len(c.historyShards))
146 > for _, shard := range c.historyShards {
147 > out = append(out, shard)
148 > }
149 > return out
150 },
151 MetricsName: metrics.DDShardControllerLockLatency.Name(),
157 }
158
159 > func (c *ControllerImpl) InitialShardsAcquired(ctx context.Context) error { controller_impl.go
160 > _, err := c.initialShardsAcquired.Get(ctx)
161 > return err
162 > }
163
164 // GetShardByNamespaceWorkflow returns a shard context for the given namespace and workflow.
168 namespaceID namespace.ID,
169 workflowID string,
170 > ) (historyi.ShardContext, error) { controller_impl.go
171 > shardID := c.config.GetShardID(namespaceID, workflowID)
172 > return c.GetShardByID(shardID)
173 > }
174
175 // GetShardByID returns a shard context for the given shard id.
178 func (c *ControllerImpl) GetShardByID(
179 shardID int32,
180 > ) (historyi.ShardContext, error) { controller_impl.go
181 > startTime := time.Now().UTC()
182 > defer func() {
183 > metrics.GetEngineForShardLatency.With(c.taggedMetricsHandler).Record(time.Since(startTime))
184 > }()
185
186 > return c.getOrCreateShardContext(shardID) controller_impl.go
187 }
188
201 }
202
203 > func (c *ControllerImpl) ShardIDs() []int32 { controller_impl.go
204 > c.RLock()
205 > defer c.RUnlock()
206 >
207 > ids := make([]int32, 0, len(c.historyShards))
208 > for id := range c.historyShards {
209 > ids = append(ids, id) controller_impl.go
210 > }
211 > return ids controller_impl.go
212 }
213
228 // if necessary. If a shard context is created, it will initialize in the background.
229 // This function won't block on rangeid lease acquisition.
230 > func (c *ControllerImpl) getOrCreateShardContext(shardID int32) (historyi.ControllableContext, error) { controller_impl.go
231 > if err := c.validateShardId(shardID); err != nil {
232 return nil, err
233 }
234 > c.RLock() controller_impl.go
235 > if shard, ok := c.historyShards[shardID]; ok {
236 > if shard.IsValid() { controller_impl.go
237 > c.RUnlock()
238 > return shard, nil
239 > }
240 // if shard not valid then proceed to create a new one
241 }
242 > c.RUnlock() controller_impl.go
243 >
244 > c.Lock()
245 > defer c.Unlock()
246 >
247 > // Check again with exclusive lock
248 > if shard, ok := c.historyShards[shardID]; ok {
249 if shard.IsValid() {
250 return shard, nil
256 }
257
258 > if err := c.ownership.verifyOwnership(shardID); err != nil { controller_impl.go
259 return nil, err
260 }
261
262 > if atomic.LoadInt32(&c.status) == common.DaemonStatusStopped { controller_impl.go
263 hostInfo := c.hostInfoProvider.HostInfo()
264 return nil, fmt.Errorf("ControllerImpl for host '%v' shutting down", hostInfo.Identity())
265 }
266
267 > shard, err := c.contextFactory.CreateContext(shardID, c.shardRemoveAndStop) controller_impl.go
268 > if err != nil {
269 return nil, err
270 }
271 > c.historyShards[shardID] = shard controller_impl.go
272 > metrics.ShardContextCreatedCounter.With(c.taggedMetricsHandler).Record(1)
273 > c.contextTaggedLogger.Info("", numShardsTag(len(c.historyShards)))
274 >
275 > return shard, nil
276 }
277
381 }
382
383 > func (c *ControllerImpl) acquireShards(ctx context.Context) { controller_impl.go
384 > metrics.AcquireShardsCounter.With(c.taggedMetricsHandler).Record(1)
385 > startTime := time.Now().UTC()
386 > defer func() {
387 > metrics.AcquireShardsLatency.With(c.taggedMetricsHandler).Record(time.Since(startTime))
388 > }()
389
390 > ctx = headers.SetCallerInfo(ctx, headers.SystemBackgroundHighCallerInfo) controller_impl.go
391 >
392 > // Readiness check: if we haven't marked readiness yet, then we need to set up a context to
393 > // run the readiness check on owned shards.
394 > var readinessCtx context.Context
395 > var readinessCancel context.CancelFunc
396 > if !c.initialShardsAcquired.Ready() {
397 > readinessCtx, readinessCancel = context.WithCancel(ctx)
398 > } else {
399 > readinessCancel = func() {} // we need a non-nil func for Swap controller_impl.go
400 }
401 // Cancel previous readiness check to ensure that the readiness check is always running on
402 // the most recent set of owned shards (e.g. after a membership change).
403 > if prevCancel := c.shardReadinessCancel.Swap(readinessCancel); prevCancel != nil { controller_impl.go
404 > prevCancel.(context.CancelFunc)() controller_impl.go
405 > }
406
407 > var ownedShardsLock sync.Mutex controller_impl.go
408 > var ownedShards []int32 // only populated if we are doing a readiness check
409 >
410 > tryAcquire := func(shardID int32) {
411 > if err := c.ownership.verifyOwnership(shardID); err != nil {
412 > if IsShardOwnershipLostError(err) { controller_impl.go
413 // current host is not owner of shard, unload it if it is already loaded.
414 if c.config.ShardLingerTimeLimit() > 0 {
418 }
419 }
420 > return controller_impl.go
421 }
422
423 > if readinessCtx != nil { controller_impl.go
424 > ownedShardsLock.Lock()
425 > ownedShards = append(ownedShards, shardID)
426 > ownedShardsLock.Unlock()
427 > }
428
429 > shard, err := c.GetShardByID(shardID) controller_impl.go
430 > if err != nil {
431 metrics.GetEngineForShardErrorCounter.With(c.taggedMetricsHandler).Record(1)
432 c.contextTaggedLogger.Error("Unable to create history shard context", tag.Error(err), tag.OperationFailed, tag.ShardID(shardID))
436 // Wait up to 1s for the shard to acquire the rangeid lock.
437 // After 1s we will move on but the shard will continue trying in the background.
438 > engineCtx, engineCancel := context.WithTimeout(ctx, 1*time.Second) controller_impl.go
439 > defer engineCancel()
440 > _, _ = shard.GetEngine(engineCtx)
441 }
442
443 > concurrency := int64(max(c.config.AcquireShardConcurrency(), 1)) controller_impl.go
444 > sem := semaphore.NewWeighted(concurrency)
445 > numShards := c.config.NumberOfShards
446 > randomStartOffset := rand.Int31n(numShards)
447 > for index := range numShards {
448 > shardID := (index+randomStartOffset)%numShards + 1
449 > if err := sem.Acquire(ctx, 1); err != nil {
450 break
451 }
452 > go func() { controller_impl.go
453 > defer sem.Release(1)
454 > tryAcquire(shardID)
455 > }()
456 }
457 > _ = sem.Acquire(ctx, concurrency) controller_impl.go
458 >
459 > c.RLock()
460 > // note that this count includes lingering shards
461 > numOfOwnedShards := len(c.historyShards)
462 > c.RUnlock()
463 > metrics.NumShardsGauge.With(c.taggedMetricsHandler).Record(float64(numOfOwnedShards))
464 > c.publishShardCountUpdate(numOfOwnedShards)
465 >
466 > // Readiness check: We should set initialShardsAcquired when:
467 > // 1. It's not already set.
468 > // 2. We should own at least one shard (i.e. not before we join membership).
469 > // 3. We have ownership of all the shards we're supposed to own.
470 > if readinessCtx != nil {
471 > if len(ownedShards) > 0 {
472 > go func() { controller_impl.go
473 > defer readinessCancel()
474 > if c.checkShardReadiness(readinessCtx, ownedShards) {
475 > c.initialShardsAcquired.SetIfNotReady(struct{}{}, nil) controller_impl.go
476 > }
477 }()
478 } else {
485 ctx context.Context,
486 shards []int32,
487 > ) bool { controller_impl.go
488 > concurrency := int64(max(c.config.AcquireShardConcurrency(), 1))
489 > sem := semaphore.NewWeighted(concurrency)
490 > var ready atomic.Int32
491 > for _, shardID := range shards {
492 > if sem.Acquire(ctx, 1) != nil {
493 return false
494 }
495 > go func() { controller_impl.go
496 > defer sem.Release(1)
497 > // Note that AssertOwnership uses a detached context for the actual persistence
498 > // op so we can't cancel it. If context is canceled, the final Acquire will
499 > // fail and we won't do anything.
500 > if shard, err := c.GetShardByID(shardID); err != nil {
501 return
502 > } else if _, err := shard.GetEngine(ctx); err != nil { controller_impl.go
503 return
504 > } else if shard.AssertOwnership(ctx) != nil { controller_impl.go
505 return
506 }
507 > ready.Add(1) controller_impl.go
508 }()
509 }
510 > if sem.Acquire(ctx, concurrency) != nil { controller_impl.go
511 return false
512 }
513
514 > if ready.Load() != int32(len(shards)) { controller_impl.go
515 c.contextTaggedLogger.Info("initial shards not ready",
516 tag.Int32("ready", ready.Load()), tag.Int("total", len(shards)))
517 return false
518 }
519 > c.contextTaggedLogger.Info("initial shards ready", tag.Int("total", len(shards))) controller_impl.go
520 > return true
521 }
522
523 // publishShardCountUpdate publishes the current number of shards that this controller owns to all shard count
524 // subscribers in a non-blocking manner.
525 > func (c *ControllerImpl) publishShardCountUpdate(shardCount int) { controller_impl.go
526 > c.RLock()
527 > defer c.RUnlock()
528 > for sub := range c.shardCountSubscriptions {
529 > select { controller_impl.go
530 > case sub.ch <- shardCount:
531 default:
532 }
534 }
535
536 > func (c *ControllerImpl) doShutdown() { controller_impl.go
537 > c.contextTaggedLogger.Info("", tag.LifeCycleStopping)
538 > c.Lock()
539 > defer c.Unlock()
540 > for _, shard := range c.historyShards {
541 > shard.FinishStop() controller_impl.go
542 > }
543 > c.historyShards = nil controller_impl.go
544 }
545
546 > func (c *ControllerImpl) validateShardId(shardID int32) error { controller_impl.go
547 > if shardID <= 0 {
548 return invalidShardIdLowerBound
549 }
550 > if shardID > c.config.NumberOfShards { controller_impl.go
551 return invalidShardIdUpperBound
552 }
553 > return nil controller_impl.go
554 }
555
556 // SubscribeShardCount returns a subscription to shard count updates with a 1-buffered channel. This method is thread-safe.
557 > func (c *ControllerImpl) SubscribeShardCount() ShardCountSubscription { controller_impl.go
558 > c.Lock()
559 > defer c.Unlock()
560 > sub := &shardCountSubscription{
561 > controller: c,
562 > ch: make(chan int, 1), // buffered because we do a non-blocking send
563 > }
564 > c.shardCountSubscriptions[sub] = struct{}{}
565 > return sub
566 > }
567
568 // ShardCount returns a channel that receives the current shard count. This channel will be closed when the subscription
569 // is canceled.
570 > func (s *shardCountSubscription) ShardCount() <-chan int { controller_impl.go
571 > return s.ch
572 > }
573
574 // Unsubscribe removes the subscription from the controller's list of subscriptions.
575 > func (s *shardCountSubscription) Unsubscribe() { controller_impl.go
576 > s.controller.Lock()
577 > defer s.controller.Unlock()
578 > if _, ok := s.controller.shardCountSubscriptions[s]; !ok {
579 return
580 }
581 > delete(s.controller.shardCountSubscriptions, s) controller_impl.go
582 > close(s.ch)
583 }
584
585 > func IsShardOwnershipLostError(err error) bool { controller_impl.go
586 > switch err.(type) {
587 case *persistence.ShardOwnershipLostError:
588 return true
go.temporal.io/server/service/history/workflow/transaction_impl.go 228 covered LOC · 37 ranges

Open complete file

40 func NewTransaction(
41 shardContext historyi.ShardContext,
42 > ) *TransactionImpl { transaction_impl.go
43 > return &TransactionImpl{
44 > shard: shardContext,
45 > logger: shardContext.GetLogger(),
46 > }
47 > }
48
49 func (t *TransactionImpl) CreateWorkflowExecution(
172 newWorkflowEventsSeq []*persistence.WorkflowEvents,
173 isWorkflow bool,
174 > ) (int64, int64, error) { transaction_impl.go
175 >
176 > engine, err := t.shard.GetEngine(ctx)
177 > if err != nil {
178 return 0, 0, err
179 }
180 > resp, err := updateWorkflowExecution( transaction_impl.go
181 > ctx,
182 > t.shard,
183 > currentWorkflowFailoverVersion,
184 > newWorkflowFailoverVersion,
185 > &persistence.UpdateWorkflowExecutionRequest{
186 > ShardID: t.shard.GetShardID(),
187 > // RangeID , this is set by shard context
188 > Mode: updateMode,
189 > ArchetypeID: archetypeID,
190 > UpdateWorkflowMutation: *currentWorkflowMutation,
191 > UpdateWorkflowEvents: currentWorkflowEventsSeq,
192 > NewWorkflowSnapshot: newWorkflowSnapshot,
193 > NewWorkflowEvents: newWorkflowEventsSeq,
194 > },
195 > isWorkflow,
196 > )
197 > if persistence.OperationPossiblySucceeded(err) {
198 > NotifyOnExecutionMutation(engine, currentWorkflowMutation) transaction_impl.go
199 > NotifyOnExecutionSnapshot(engine, newWorkflowSnapshot)
200 > }
201 > if err != nil { transaction_impl.go
202 return 0, 0, err
203 }
204
205 > if err := NotifyNewHistoryMutationEvent(engine, currentWorkflowMutation); err != nil { transaction_impl.go
206 t.logger.Error("unable to notify workflow mutation", tag.Error(err))
207 }
208 > if err := NotifyNewHistorySnapshotEvent(engine, newWorkflowSnapshot); err != nil { transaction_impl.go
209 t.logger.Error("unable to notify workflow creation", tag.Error(err))
210 }
211 > updateHistorySizeDiff := int64(resp.UpdateMutableStateStats.HistoryStatistics.SizeDiff) transaction_impl.go
212 > newHistorySizeDiff := int64(0)
213 > if resp.NewMutableStateStats != nil {
214 newHistorySizeDiff = int64(resp.NewMutableStateStats.HistoryStatistics.SizeDiff)
215 }
216 > return updateHistorySizeDiff, newHistorySizeDiff, nil transaction_impl.go
217 }
218
362 request *persistence.CreateWorkflowExecutionRequest,
363 isWorkflow bool,
364 > ) (*persistence.CreateWorkflowExecutionResponse, error) { transaction_impl.go
365 >
366 > resp, err := shardContext.CreateWorkflowExecution(ctx, request)
367 > if err != nil {
368 switch err.(type) {
369 case *persistence.CurrentWorkflowConditionFailedError,
387 }
388
389 > if namespaceEntry, err := shardContext.GetNamespaceRegistry().GetNamespaceByID( transaction_impl.go
390 > namespace.ID(request.NewWorkflowSnapshot.ExecutionInfo.NamespaceId),
391 > ); err == nil {
392 > emitMutationMetrics(
393 > shardContext,
394 > namespaceEntry,
395 > request.ArchetypeID,
396 > &resp.NewMutableStateStats,
397 > )
398 > emitCompletionMetrics(
399 > shardContext,
400 > namespaceEntry,
401 > snapshotToCompletionMetric(
402 > namespaceState(shardContext.GetClusterMetadata(), &mutableStateFailoverVersion),
403 > &request.NewWorkflowSnapshot,
404 > request.NewWorkflowEvents,
405 > isWorkflow,
406 > ),
407 > )
408 > }
409 > return resp, nil
410 }
411
474 shardContext historyi.ShardContext,
475 request *persistence.GetWorkflowExecutionRequest,
476 > ) (*persistence.GetWorkflowExecutionResponse, error) { transaction_impl.go
477 >
478 > resp, err := shardContext.GetWorkflowExecution(ctx, request)
479 > if err != nil {
480 switch err.(type) {
481 case *serviceerror.NotFound:
495 }
496
497 > if namespaceEntry, err := shardContext.GetNamespaceRegistry().GetNamespaceByID( transaction_impl.go
498 > namespace.ID(resp.State.ExecutionInfo.NamespaceId),
499 > ); err == nil {
500 > emitGetMetrics(
501 > shardContext,
502 > namespaceEntry,
503 > request.ArchetypeID,
504 > &resp.MutableStateStats,
505 > )
506 > }
507 > return resp, nil
508 }
509
515 request *persistence.UpdateWorkflowExecutionRequest,
516 isWorkflow bool,
517 > ) (*persistence.UpdateWorkflowExecutionResponse, error) { transaction_impl.go
518 >
519 > resp, err := shardContext.UpdateWorkflowExecution(ctx, request)
520 > if err != nil {
521 shardContext.GetLogger().Error(
522 "Update workflow execution operation failed.",
530 }
531
532 > if namespaceEntry, err := shardContext.GetNamespaceRegistry().GetNamespaceByID( transaction_impl.go
533 > namespace.ID(request.UpdateWorkflowMutation.ExecutionInfo.NamespaceId),
534 > ); err == nil {
535 > emitMutationMetrics(
536 > shardContext,
537 > namespaceEntry,
538 > request.ArchetypeID,
539 > &resp.UpdateMutableStateStats,
540 > resp.NewMutableStateStats,
541 > )
542 >
543 > emitCompletionMetrics(
544 > shardContext,
545 > namespaceEntry,
546 > mutationToCompletionMetric(
547 > namespaceState(shardContext.GetClusterMetadata(), &updateWorkflowFailoverVersion),
548 > &request.UpdateWorkflowMutation,
549 > request.UpdateWorkflowEvents,
550 > isWorkflow,
551 > ),
552 > snapshotToCompletionMetric(
553 > namespaceState(shardContext.GetClusterMetadata(), newWorkflowFailoverVersion),
554 > request.NewWorkflowSnapshot,
555 > request.NewWorkflowEvents,
556 > isWorkflow,
557 > ),
558 > )
559 > }
560
561 > return resp, nil transaction_impl.go
562 }
563
586 engine historyi.Engine,
587 workflowSnapshot *persistence.WorkflowSnapshot,
589 > if workflowSnapshot == nil {
590 > return transaction_impl.go
591 > }
592 > engine.NotifyNewTasks(workflowSnapshot.Tasks) transaction_impl.go
593 > if len(workflowSnapshot.ChasmNodes) > 0 {
594 engine.NotifyChasmExecution(chasm.ExecutionKey{
595 NamespaceID: workflowSnapshot.ExecutionInfo.NamespaceId,
603 engine historyi.Engine,
604 workflowMutation *persistence.WorkflowMutation,
606 > if workflowMutation == nil {
607 return
608 }
609 > engine.NotifyNewTasks(workflowMutation.Tasks) transaction_impl.go
610 > if len(workflowMutation.UpsertChasmNodes) > 0 ||
611 > len(workflowMutation.DeleteChasmNodes) > 0 {
612 engine.NotifyChasmExecution(chasm.ExecutionKey{
613 NamespaceID: workflowMutation.ExecutionInfo.NamespaceId,
621 engine historyi.Engine,
622 workflowSnapshot *persistence.WorkflowSnapshot,
623 > ) error { transaction_impl.go
624 >
625 > if workflowSnapshot == nil {
626 > return nil transaction_impl.go
627 > }
628
629 executionInfo := workflowSnapshot.ExecutionInfo
661 engine historyi.Engine,
662 workflowMutation *persistence.WorkflowMutation,
663 > ) error { transaction_impl.go
664 >
665 > if workflowMutation == nil {
666 return nil
667 }
668
669 > executionInfo := workflowMutation.ExecutionInfo transaction_impl.go
670 > executionState := workflowMutation.ExecutionState
671 >
672 > namespaceID := executionInfo.NamespaceId
673 > workflowID := executionInfo.WorkflowId
674 > runID := executionState.RunId
675 > workflowState := executionState.State
676 > workflowStatus := executionState.Status
677 > lastFirstEventID := executionInfo.LastFirstEventId
678 > lastFirstEventTxnID := executionInfo.LastFirstEventTxnId
679 > lastWorkflowTaskStartEventID := executionInfo.LastCompletedWorkflowTaskStartedEventId
680 > nextEventID := workflowMutation.NextEventID
681 >
682 > engine.NotifyNewHistoryEvent(events.NewNotification(
683 > namespaceID,
684 > &commonpb.WorkflowExecution{
685 > WorkflowId: workflowID,
686 > RunId: runID,
687 > },
688 > lastFirstEventID,
689 > lastFirstEventTxnID,
690 > nextEventID,
691 > lastWorkflowTaskStartEventID,
692 > workflowState,
693 > workflowStatus,
694 > executionInfo.VersionHistories,
695 > executionInfo.TransitionHistory,
696 > ))
697 > return nil
698 }
699
703 archetypeID chasm.ArchetypeID,
704 stats ...*persistence.MutableStateStatistics,
706 > metricsHandler := shardContext.GetMetricsHandler()
707 > chasmRegistry := shardContext.ChasmRegistry()
708 > namespaceName := namespace.Name()
709 > for _, stat := range stats {
710 > emitMutableStateStatus(
711 > metricsHandler.WithTags(metrics.OperationTag(metrics.SessionStatsScope), metrics.NamespaceTag(namespaceName.String())),
712 > chasmRegistry,
713 > archetypeID,
714 > stat,
715 > )
716 > }
717 }
718
722 archetypeID chasm.ArchetypeID,
723 stats ...*persistence.MutableStateStatistics,
725 > metricsHandler := shardContext.GetMetricsHandler()
726 > chasmRegistry := shardContext.ChasmRegistry()
727 > namespaceName := namespace.Name()
728 > for _, stat := range stats {
729 > emitMutableStateStatus(
730 > metricsHandler.WithTags(metrics.OperationTag(metrics.ExecutionStatsScope), metrics.NamespaceTag(namespaceName.String())),
731 > chasmRegistry,
732 > archetypeID,
733 > stat,
734 > )
735 > }
736 }
737
738 // wroteEvents reports whether the run wrote any history events in this transaction.
739 > func wroteEvents(eventsSeq []*persistence.WorkflowEvents) bool { transaction_impl.go
740 > for _, batch := range eventsSeq {
741 > if len(batch.Events) > 0 { transaction_impl.go
742 > return true
743 > }
744 }
745 return false
751 eventsSeq []*persistence.WorkflowEvents,
752 isWorkflow bool,
753 > ) completionMetric { transaction_impl.go
754 > if workflowSnapshot == nil {
755 > return completionMetric{shouldRecord: false} transaction_impl.go
756 > }
757
758 > return completionMetric{ transaction_impl.go
759 > // Record a completion only when the run wrote events (closed) in this transaction.
760 > shouldRecord: wroteEvents(eventsSeq),
761 > isWorkflow: isWorkflow,
762 > taskQueue: workflowSnapshot.ExecutionInfo.TaskQueue,
763 > namespaceState: namespaceState,
764 > workflowTypeName: workflowSnapshot.ExecutionInfo.WorkflowTypeName,
765 > status: workflowSnapshot.ExecutionState.Status,
766 > startTime: workflowSnapshot.ExecutionState.StartTime,
767 > closeTime: workflowSnapshot.ExecutionInfo.CloseTime,
768 > }
769 }
770
774 eventsSeq []*persistence.WorkflowEvents,
775 isWorkflow bool,
776 > ) completionMetric { transaction_impl.go
777 > if workflowMutation == nil {
778 return completionMetric{shouldRecord: false}
779 }
780
781 > return completionMetric{ transaction_impl.go
782 > shouldRecord: wroteEvents(eventsSeq),
783 > isWorkflow: isWorkflow,
784 > taskQueue: workflowMutation.ExecutionInfo.TaskQueue,
785 > namespaceState: namespaceState,
786 > workflowTypeName: workflowMutation.ExecutionInfo.WorkflowTypeName,
787 > status: workflowMutation.ExecutionState.Status,
788 > startTime: workflowMutation.ExecutionState.StartTime,
789 > closeTime: workflowMutation.ExecutionInfo.CloseTime,
790 > }
791 }
792
795 namespace *namespace.Namespace,
796 completionMetrics ...completionMetric,
798 > metricsHandler := shardContext.GetMetricsHandler()
799 > namespaceName := namespace.Name()
800 >
801 > for _, completionMetric := range completionMetrics {
802 > if !completionMetric.shouldRecord {
803 > continue transaction_impl.go
804 }
805
806 > emitWorkflowCompletionStats( transaction_impl.go
807 > metricsHandler,
808 > namespaceName,
809 > completionMetric,
810 > shardContext.GetConfig(),
811 > )
812 }
813 }
go.temporal.io/server/service/frontend/namespace_handler.go 225 covered LOC · 41 ranges

Open complete file

77 timeSource clock.TimeSource,
78 config *Config,
79 > ) *namespaceHandler { namespace_handler.go
80 > return &namespaceHandler{
81 > logger: logger,
82 > metadataMgr: metadataMgr,
83 > namespaceRegistry: namespaceRegistry,
84 > clusterMetadata: clusterMetadata,
85 > namespaceReplicator: namespaceReplicator,
86 > namespaceAttrValidator: nsmanager.NewValidator(clusterMetadata),
87 > archivalMetadata: archivalMetadata,
88 > archiverProvider: archiverProvider,
89 > timeSource: timeSource,
90 > config: config,
91 > }
92 > }
93
94 // RegisterNamespace register a new namespace
98 ctx context.Context,
99 registerRequest *workflowservice.RegisterNamespaceRequest,
100 > ) (*workflowservice.RegisterNamespaceResponse, error) { namespace_handler.go
101 >
102 > if !d.clusterMetadata.IsGlobalNamespaceEnabled() {
103 > if registerRequest.GetIsGlobalNamespace() { namespace_handler.go
104 return nil, serviceerror.NewInvalidArgument("Cannot register global namespace when not enabled")
105 }
106
107 > registerRequest.IsGlobalNamespace = false namespace_handler.go
108 } else {
109 // cluster global namespace enabled
113 }
114
115 > if err := d.validateRetentionDuration( namespace_handler.go
116 > registerRequest.WorkflowExecutionRetentionPeriod,
117 > registerRequest.IsGlobalNamespace,
118 > ); err != nil {
119 return nil, err
120 }
121
122 // first check if the name is already registered as the local namespace
123 > _, err := d.metadataMgr.GetNamespace(ctx, &persistence.GetNamespaceRequest{Name: registerRequest.GetNamespace()}) namespace_handler.go
124 > switch err.(type) {
125 case nil:
126 // namespace already exists, cannot proceed
127 return nil, serviceerror.NewNamespaceAlreadyExistsf("Namespace %q already exists", registerRequest.GetNamespace())
128 > case *serviceerror.NamespaceNotFound: namespace_handler.go
129 // namespace does not exists, proceeds
130 default:
133 }
134
135 > var activeClusterName string namespace_handler.go
136 > // input validation on cluster names
137 > if registerRequest.GetActiveClusterName() != "" {
138 activeClusterName = registerRequest.GetActiveClusterName()
139 > } else { namespace_handler.go
140 > activeClusterName = d.clusterMetadata.GetCurrentClusterName() namespace_handler.go
141 > }
142 > var clusters []string namespace_handler.go
143 > for _, clusterConfig := range registerRequest.Clusters {
144 clusterName := clusterConfig.GetClusterName()
145 clusters = append(clusters, clusterName)
146 }
147 > clusters = persistence.GetOrUseDefaultClusters(activeClusterName, clusters) namespace_handler.go
148 >
149 > currentHistoryArchivalState := namespace.NeverEnabledState()
150 > nextHistoryArchivalState := currentHistoryArchivalState
151 > clusterHistoryArchivalConfig := d.archivalMetadata.GetHistoryConfig()
152 > if clusterHistoryArchivalConfig.ClusterConfiguredForArchival() {
153 > archivalEvent, err := d.toArchivalRegisterEvent( namespace_handler.go
154 > registerRequest.HistoryArchivalState,
155 > registerRequest.GetHistoryArchivalUri(),
156 > clusterHistoryArchivalConfig.GetNamespaceDefaultState(),
157 > clusterHistoryArchivalConfig.GetNamespaceDefaultURI(),
158 > )
159 > if err != nil {
160 return nil, err
161 }
162
163 > nextHistoryArchivalState, _, err = currentHistoryArchivalState.GetNextState(archivalEvent, d.validateHistoryArchivalURI) namespace_handler.go
164 > if err != nil {
165 return nil, err
166 }
167 }
168
169 > currentVisibilityArchivalState := namespace.NeverEnabledState() namespace_handler.go
170 > nextVisibilityArchivalState := currentVisibilityArchivalState
171 > clusterVisibilityArchivalConfig := d.archivalMetadata.GetVisibilityConfig()
172 > if clusterVisibilityArchivalConfig.ClusterConfiguredForArchival() {
173 > archivalEvent, err := d.toArchivalRegisterEvent( namespace_handler.go
174 > registerRequest.VisibilityArchivalState,
175 > registerRequest.GetVisibilityArchivalUri(),
176 > clusterVisibilityArchivalConfig.GetNamespaceDefaultState(),
177 > clusterVisibilityArchivalConfig.GetNamespaceDefaultURI(),
178 > )
179 > if err != nil {
180 return nil, err
181 }
182
183 > nextVisibilityArchivalState, _, err = currentVisibilityArchivalState.GetNextState(archivalEvent, d.validateVisibilityArchivalURI) namespace_handler.go
184 > if err != nil {
185 return nil, err
186 }
187 }
188
189 > info := &persistencespb.NamespaceInfo{ namespace_handler.go
190 > Id: uuid.NewString(),
191 > Name: registerRequest.GetNamespace(),
192 > State: enumspb.NAMESPACE_STATE_REGISTERED,
193 > Owner: registerRequest.GetOwnerEmail(),
194 > Description: registerRequest.GetDescription(),
195 > Data: registerRequest.Data,
196 > }
197 > config := &persistencespb.NamespaceConfig{
198 > Retention: registerRequest.GetWorkflowExecutionRetentionPeriod(),
199 > HistoryArchivalState: nextHistoryArchivalState.State,
200 > HistoryArchivalUri: nextHistoryArchivalState.URI,
201 > VisibilityArchivalState: nextVisibilityArchivalState.State,
202 > VisibilityArchivalUri: nextVisibilityArchivalState.URI,
203 > BadBinaries: &namespacepb.BadBinaries{Binaries: map[string]*namespacepb.BadBinaryInfo{}},
204 > CustomSearchAttributeAliases: nil,
205 > }
206 > replicationConfig := &persistencespb.NamespaceReplicationConfig{
207 > ActiveClusterName: activeClusterName,
208 > Clusters: clusters,
209 > State: enumspb.REPLICATION_STATE_NORMAL,
210 > }
211 > isGlobalNamespace := registerRequest.GetIsGlobalNamespace()
212 >
213 > if err := d.namespaceAttrValidator.ValidateNamespaceConfig(config); err != nil {
214 return nil, err
215 }
216 > if isGlobalNamespace { namespace_handler.go
217 if err := d.namespaceAttrValidator.ValidateNamespaceReplicationConfigForGlobalNamespace(
218 replicationConfig,
220 return nil, err
221 }
222 > } else { namespace_handler.go
223 > if err := d.namespaceAttrValidator.ValidateNamespaceReplicationConfigForLocalNamespace(
224 > replicationConfig,
225 > ); err != nil {
226 return nil, err
227 }
228 }
229
230 > failoverVersion := common.EmptyVersion namespace_handler.go
231 > if registerRequest.GetIsGlobalNamespace() {
232 failoverVersion = d.clusterMetadata.GetNextFailoverVersion(activeClusterName, 0)
233 }
234
235 > namespaceRequest := &persistence.CreateNamespaceRequest{ namespace_handler.go
236 > Namespace: &persistencespb.NamespaceDetail{
237 > Info: info,
238 > Config: config,
239 > ReplicationConfig: replicationConfig,
240 > ConfigVersion: 0,
241 > FailoverVersion: failoverVersion,
242 > },
243 > IsGlobalNamespace: isGlobalNamespace,
244 > }
245 >
246 > namespaceResponse, err := d.metadataMgr.CreateNamespace(ctx, namespaceRequest)
247 > if err != nil {
248 return nil, err
249 }
250
251 > err = d.namespaceReplicator.HandleTransmissionTask( namespace_handler.go
252 > ctx,
253 > enumsspb.NAMESPACE_OPERATION_CREATE,
254 > namespaceRequest.Namespace.Info,
255 > namespaceRequest.Namespace.Config,
256 > namespaceRequest.Namespace.ReplicationConfig,
257 > false,
258 > namespaceRequest.Namespace.ConfigVersion,
259 > namespaceRequest.Namespace.FailoverVersion,
260 > namespaceRequest.IsGlobalNamespace,
261 > nil,
262 > false, // forceReplicate
263 > )
264 > if err != nil {
265 return nil, err
266 }
267
268 > d.logger.Info("Register namespace succeeded", namespace_handler.go
269 > tag.WorkflowNamespace(registerRequest.GetNamespace()),
270 > tag.WorkflowNamespaceID(namespaceResponse.ID),
271 > )
272 >
273 > return &workflowservice.RegisterNamespaceResponse{}, nil
274 }
275
321 ctx context.Context,
322 describeRequest *workflowservice.DescribeNamespaceRequest,
323 > ) (*workflowservice.DescribeNamespaceResponse, error) { namespace_handler.go
324 >
325 > if describeRequest.GetWeakConsistency() {
326 return d.describeNamespaceFromRegistry(describeRequest)
327 }
328
329 // TODO, we should migrate the non global namespace to new table, see #773
330 > req := &persistence.GetNamespaceRequest{ namespace_handler.go
331 > Name: describeRequest.GetNamespace(),
332 > ID: describeRequest.GetId(),
333 > }
334 > resp, err := d.metadataMgr.GetNamespace(ctx, req)
335 > if err != nil {
336 return nil, err
337 }
338
339 > response := &workflowservice.DescribeNamespaceResponse{ namespace_handler.go
340 > IsGlobalNamespace: resp.IsGlobalNamespace,
341 > FailoverVersion: resp.Namespace.FailoverVersion,
342 > }
343 > response.NamespaceInfo, response.Config, response.ReplicationConfig, response.FailoverHistory =
344 > d.createResponse(resp.Namespace.Info, resp.Namespace.Config, resp.Namespace.ReplicationConfig)
345 > return response, nil
346 }
347
885 config *persistencespb.NamespaceConfig,
886 replicationConfig *persistencespb.NamespaceReplicationConfig,
887 > ) (*namespacepb.NamespaceInfo, *namespacepb.NamespaceConfig, *replicationpb.NamespaceReplicationConfig, []*replicationpb.FailoverStatus) { namespace_handler.go
888 >
889 > numConsecutiveWorkflowTaskProblemsToTriggerSearchAttribute := d.config.NumConsecutiveWorkflowTaskProblemsToTriggerSearchAttribute(info.Name)
890 >
891 > infoResult := &namespacepb.NamespaceInfo{
892 > Name: info.Name,
893 > State: info.State,
894 > Description: info.Description,
895 > OwnerEmail: info.Owner,
896 > Data: info.Data,
897 > Id: info.Id,
898 >
899 > Capabilities: &namespacepb.NamespaceInfo_Capabilities{
900 > EagerWorkflowStart: d.config.EnableEagerWorkflowStart(info.Name),
901 > SyncUpdate: d.config.EnableUpdateWorkflowExecution(info.Name),
902 > AsyncUpdate: d.config.EnableUpdateWorkflowExecutionAsyncAccepted(info.Name),
903 > ReportedProblemsSearchAttribute: numConsecutiveWorkflowTaskProblemsToTriggerSearchAttribute > 0,
904 > WorkerHeartbeats: d.config.WorkerHeartbeatsEnabled(info.Name),
905 > WorkflowPause: d.config.WorkflowPauseEnabled(info.Name),
906 > StandaloneActivities: d.config.Activity.Enabled(info.Name),
907 > StandaloneActivityStartDelay: d.config.Activity.Enabled(info.Name) && d.config.Activity.StartDelayEnabled(info.Name),
908 > StandaloneNexusOperation: d.config.EnableChasm(info.Name) && d.config.StandaloneNexusOperationsEnabled(info.Name),
909 > WorkerPollCompleteOnShutdown: d.config.EnableCancelWorkerPollsOnShutdown(info.Name),
910 > WorkerCommands: d.config.WorkerCommandsEnabled(info.Name),
911 > WorkflowUpdateCallbacks: d.config.EnableWorkflowUpdateCallbacks(info.Name),
912 > PollerAutoscaling: true,
913 > PollerAutoscalingAutoEnroll: d.config.PollerAutoscalingAutoEnroll(info.Name),
914 > WorkflowTaskCompletionPagination: d.config.EnableWorkflowTaskCompletionPagination(info.Name),
915 > },
916 > Limits: &namespacepb.NamespaceInfo_Limits{
917 > BlobSizeLimitError: int64(d.config.BlobSizeLimitError(info.Name)),
918 > MemoSizeLimitError: int64(d.config.MemoSizeLimitError(info.Name)),
919 > },
920 > SupportsSchedules: d.config.EnableSchedules(info.Name),
921 > }
922 >
923 > configResult := &namespacepb.NamespaceConfig{
924 > WorkflowExecutionRetentionTtl: config.Retention,
925 > HistoryArchivalState: config.HistoryArchivalState,
926 > HistoryArchivalUri: config.HistoryArchivalUri,
927 > VisibilityArchivalState: config.VisibilityArchivalState,
928 > VisibilityArchivalUri: config.VisibilityArchivalUri,
929 > BadBinaries: config.BadBinaries,
930 > CustomSearchAttributeAliases: config.CustomSearchAttributeAliases,
931 > }
932 >
933 > var clusters []*replicationpb.ClusterReplicationConfig
934 > for _, cluster := range replicationConfig.Clusters {
935 > clusters = append(clusters, &replicationpb.ClusterReplicationConfig{ namespace_handler.go
936 > ClusterName: cluster,
937 > })
938 > }
939 > replicationConfigResult := &replicationpb.NamespaceReplicationConfig{ namespace_handler.go
940 > ActiveClusterName: replicationConfig.ActiveClusterName,
941 > Clusters: clusters,
942 > State: replicationConfig.GetState(),
943 > }
944 >
945 > var failoverHistory []*replicationpb.FailoverStatus
946 > for _, entry := range replicationConfig.GetFailoverHistory() {
947 failoverHistory = append(failoverHistory, &replicationpb.FailoverStatus{
948 FailoverTime: entry.GetFailoverTime(),
951 }
952
953 > return infoResult, configResult, replicationConfigResult, failoverHistory namespace_handler.go
954 }
955
1012 defaultState enumspb.ArchivalState,
1013 defaultURI string,
1014 > ) (*namespace.ArchivalConfigEvent, error) { namespace_handler.go
1015 >
1016 > event := &namespace.ArchivalConfigEvent{
1017 > State: state,
1018 > URI: URI,
1019 > DefaultURI: defaultURI,
1020 > }
1021 > if event.State == enumspb.ARCHIVAL_STATE_UNSPECIFIED {
1022 > event.State = defaultState namespace_handler.go
1023 > }
1024 > if err := event.Validate(); err != nil { namespace_handler.go
1025 return nil, err
1026 }
1027 > return event, nil namespace_handler.go
1028 }
1029
1111
1112 // validateRetentionDuration ensures that retention duration can't be set below a sane minimum.
1113 > func (d *namespaceHandler) validateRetentionDuration(retention *durationpb.Duration, isGlobalNamespace bool) error { namespace_handler.go
1114 > if err := timestamp.ValidateAndCapProtoDuration(retention); err != nil {
1115 return errInvalidRetentionPeriod
1116 }
1117
1118 > var minRetention time.Duration namespace_handler.go
1119 > if isGlobalNamespace {
1120 minRetention = d.config.NamespaceMinRetentionGlobal()
1121 > } else { namespace_handler.go
1122 > minRetention = d.config.NamespaceMinRetentionLocal() namespace_handler.go
1123 > }
1124
1125 > if timestamp.DurationValue(retention) < minRetention { namespace_handler.go
1126 return errInvalidRetentionPeriod
1127 }
1128 > return nil namespace_handler.go
1129 }
1130
go.temporal.io/server/common/persistence/serialization/task_serializers.go 220 covered LOC · 34 ranges

Open complete file

18 encoder Encoder,
19 task tasks.Task,
20 > ) (*commonpb.DataBlob, error) { task_serializers.go
21 > var transferTask *persistencespb.TransferTaskInfo
22 > switch task := task.(type) {
23 > case *tasks.WorkflowTask: task_serializers.go
24 > transferTask = transferWorkflowTaskToProto(task)
25 case *tasks.ActivityTask:
26 transferTask = transferActivityTaskToProto(task)
31 case *tasks.StartChildExecutionTask:
32 transferTask = transferChildWorkflowTaskToProto(task)
33 > case *tasks.CloseExecutionTask: task_serializers.go
34 > transferTask = transferCloseTaskToProto(task)
35 case *tasks.ResetWorkflowTask:
36 transferTask = transferResetTaskToProto(task)
42 return nil, serviceerror.NewInternalf("Unknown transfer task type: %v", task)
43 }
44 > return encoder.TransferTaskInfoToBlob(transferTask) task_serializers.go
45 }
46
62 decoder Decoder,
63 blob *commonpb.DataBlob,
64 > ) (tasks.Task, error) { task_serializers.go
65 > transferTask, err := decoder.TransferTaskInfoFromBlob(blob)
66 > if err != nil {
67 return nil, err
68 }
69 > var task tasks.Task task_serializers.go
70 > switch transferTask.TaskType {
71 > case enumsspb.TASK_TYPE_TRANSFER_WORKFLOW_TASK: task_serializers.go
72 > task = transferWorkflowTaskFromProto(transferTask)
73 case enumsspb.TASK_TYPE_TRANSFER_ACTIVITY_TASK:
74 task = transferActivityTaskFromProto(transferTask)
79 case enumsspb.TASK_TYPE_TRANSFER_START_CHILD_EXECUTION:
80 task = transferChildWorkflowTaskFromProto(transferTask)
81 > case enumsspb.TASK_TYPE_TRANSFER_CLOSE_EXECUTION: task_serializers.go
82 > task = transferCloseTaskFromProto(transferTask)
83 case enumsspb.TASK_TYPE_TRANSFER_RESET_WORKFLOW:
84 task = transferResetTaskFromProto(transferTask)
90 return nil, serviceerror.NewInternalf("Unknown transfer task type: %v", transferTask.TaskType)
91 }
92 > return task, nil task_serializers.go
93 }
94
110 encoder Encoder,
111 task tasks.Task,
112 > ) (*commonpb.DataBlob, error) { task_serializers.go
113 > var timerTask *persistencespb.TimerTaskInfo
114 > switch task := task.(type) {
115 > case *tasks.WorkflowTaskTimeoutTask: task_serializers.go
116 > timerTask = timerWorkflowTaskToProto(task)
117 > case *tasks.WorkflowBackoffTimerTask: task_serializers.go
118 > timerTask = timerWorkflowDelayTaskToProto(task)
119 case *tasks.ActivityTimeoutTask:
120 timerTask = timerActivityTaskToProto(task)
127 case *tasks.WorkflowExecutionTimeoutTask:
128 timerTask = timerWorkflowExecutionToProto(task)
129 > case *tasks.DeleteHistoryEventTask: task_serializers.go
130 > timerTask = timerWorkflowCleanupTaskToProto(task)
131 case *tasks.StateMachineTimerTask:
132 timerTask = stateMachineTimerTaskToProto(task)
140 return nil, serviceerror.NewInternalf("Unknown timer task type: %v", task)
141 }
142 > return encoder.TimerTaskInfoToBlob(timerTask) task_serializers.go
143 }
144
274 encoder Encoder,
275 task tasks.Task,
276 > ) (*commonpb.DataBlob, error) { task_serializers.go
277 > var visibilityTask *persistencespb.VisibilityTaskInfo
278 > switch task := task.(type) {
279 > case *tasks.StartExecutionVisibilityTask: task_serializers.go
280 > visibilityTask = visibilityStartTaskToProto(task)
281 case *tasks.UpsertExecutionVisibilityTask:
282 visibilityTask = visibilityUpsertTaskToProto(task)
283 > case *tasks.CloseExecutionVisibilityTask: task_serializers.go
284 > visibilityTask = visibilityCloseTaskToProto(task)
285 case *tasks.DeleteExecutionVisibilityTask:
286 visibilityTask = visibilityDeleteTaskToProto(task)
290 return nil, serviceerror.NewInternalf("Unknown visibility task type: %v", task)
291 }
292 > return encoder.VisibilityTaskInfoToBlob(visibilityTask) task_serializers.go
293 }
294
296 decoder Decoder,
297 blob *commonpb.DataBlob,
298 > ) (tasks.Task, error) { task_serializers.go
299 > visibilityTask, err := decoder.VisibilityTaskInfoFromBlob(blob)
300 > if err != nil {
301 return nil, err
302 }
303 > var visibility tasks.Task task_serializers.go
304 > switch visibilityTask.TaskType {
305 > case enumsspb.TASK_TYPE_VISIBILITY_START_EXECUTION: task_serializers.go
306 > visibility = visibilityStartTaskFromProto(visibilityTask)
307 case enumsspb.TASK_TYPE_VISIBILITY_UPSERT_EXECUTION:
308 visibility = visibilityUpsertTaskFromProto(visibilityTask)
309 > case enumsspb.TASK_TYPE_VISIBILITY_CLOSE_EXECUTION: task_serializers.go
310 > visibility = visibilityCloseTaskFromProto(visibilityTask)
311 case enumsspb.TASK_TYPE_VISIBILITY_DELETE_EXECUTION:
312 visibility = visibilityDeleteTaskFromProto(visibilityTask)
316 return nil, serviceerror.NewInternalf("Unknown visibility task type: %v", visibilityTask.TaskType)
317 }
318 > return visibility, nil task_serializers.go
319 }
320
455 func transferWorkflowTaskToProto(
456 workflowTask *tasks.WorkflowTask,
457 > ) *persistencespb.TransferTaskInfo { task_serializers.go
458 > return &persistencespb.TransferTaskInfo{
459 > NamespaceId: workflowTask.NamespaceID,
460 > WorkflowId: workflowTask.WorkflowID,
461 > RunId: workflowTask.RunID,
462 > TaskType: enumsspb.TASK_TYPE_TRANSFER_WORKFLOW_TASK,
463 > TargetNamespaceId: workflowTask.NamespaceID,
464 > TargetWorkflowId: "",
465 > TargetRunId: "",
466 > TargetChildWorkflowOnly: false,
467 > TaskQueue: workflowTask.TaskQueue,
468 > ScheduledEventId: workflowTask.ScheduledEventID,
469 > Version: workflowTask.Version,
470 > TaskId: workflowTask.TaskID,
471 > VisibilityTime: timestamppb.New(workflowTask.VisibilityTimestamp),
472 > Stamp: workflowTask.Stamp,
473 > }
474 > }
475
476 func transferWorkflowTaskFromProto(
477 workflowTask *persistencespb.TransferTaskInfo,
478 > ) *tasks.WorkflowTask { task_serializers.go
479 > return &tasks.WorkflowTask{
480 > WorkflowKey: definition.NewWorkflowKey(
481 > workflowTask.NamespaceId,
482 > workflowTask.WorkflowId,
483 > workflowTask.RunId,
484 > ),
485 > VisibilityTimestamp: workflowTask.VisibilityTime.AsTime(),
486 > TaskID: workflowTask.TaskId,
487 > TaskQueue: workflowTask.TaskQueue,
488 > ScheduledEventID: workflowTask.ScheduledEventId,
489 > Version: workflowTask.Version,
490 > Stamp: workflowTask.Stamp,
491 > }
492 > }
493
494 func transferRequestCancelTaskToProto(
612 func transferCloseTaskToProto(
613 closeTask *tasks.CloseExecutionTask,
614 > ) *persistencespb.TransferTaskInfo { task_serializers.go
615 > return &persistencespb.TransferTaskInfo{
616 > NamespaceId: closeTask.NamespaceID,
617 > WorkflowId: closeTask.WorkflowID,
618 > RunId: closeTask.RunID,
619 > TaskType: enumsspb.TASK_TYPE_TRANSFER_CLOSE_EXECUTION,
620 > TargetNamespaceId: "",
621 > TargetWorkflowId: "",
622 > TargetRunId: "",
623 > TargetChildWorkflowOnly: false,
624 > TaskQueue: "",
625 > ScheduledEventId: 0,
626 > Version: closeTask.Version,
627 > TaskId: closeTask.TaskID,
628 > VisibilityTime: timestamppb.New(closeTask.VisibilityTimestamp),
629 > DeleteAfterClose: closeTask.DeleteAfterClose,
630 > TaskDetails: &persistencespb.TransferTaskInfo_CloseExecutionTaskDetails_{
631 > CloseExecutionTaskDetails: &persistencespb.TransferTaskInfo_CloseExecutionTaskDetails{
632 > // We set this to true even though it's no longer checked in case someone downgrades to a version that
633 > // still checks this field.
634 > CanSkipVisibilityArchival: true,
635 > },
636 > },
637 > }
638 > }
639
640 func transferCloseTaskFromProto(
641 closeTask *persistencespb.TransferTaskInfo,
642 > ) *tasks.CloseExecutionTask { task_serializers.go
643 > return &tasks.CloseExecutionTask{
644 > WorkflowKey: definition.NewWorkflowKey(
645 > closeTask.NamespaceId,
646 > closeTask.WorkflowId,
647 > closeTask.RunId,
648 > ),
649 > VisibilityTimestamp: closeTask.VisibilityTime.AsTime(),
650 > TaskID: closeTask.TaskId,
651 > Version: closeTask.Version,
652 > DeleteAfterClose: closeTask.DeleteAfterClose,
653 > // Delete workflow task process stage is not persisted. It is only for in memory retries.
654 > DeleteProcessStage: tasks.DeleteWorkflowExecutionStageNone,
655 > }
656 > }
657
658 func transferResetTaskToProto(
728 func timerWorkflowTaskToProto(
729 workflowTimer *tasks.WorkflowTaskTimeoutTask,
730 > ) *persistencespb.TimerTaskInfo { task_serializers.go
731 > return &persistencespb.TimerTaskInfo{
732 > NamespaceId: workflowTimer.NamespaceID,
733 > WorkflowId: workflowTimer.WorkflowID,
734 > RunId: workflowTimer.RunID,
735 > TaskType: enumsspb.TASK_TYPE_WORKFLOW_TASK_TIMEOUT,
736 > TimeoutType: workflowTimer.TimeoutType,
737 > WorkflowBackoffType: enumsspb.WORKFLOW_BACKOFF_TYPE_UNSPECIFIED,
738 > Version: workflowTimer.Version,
739 > ScheduleAttempt: workflowTimer.ScheduleAttempt,
740 > EventId: workflowTimer.EventID,
741 > TaskId: workflowTimer.TaskID,
742 > VisibilityTime: timestamppb.New(workflowTimer.VisibilityTimestamp),
743 > Stamp: workflowTimer.Stamp,
744 > }
745 > }
746
747 func timerWorkflowTaskFromProto(
766 func timerWorkflowDelayTaskToProto(
767 workflowDelayTimer *tasks.WorkflowBackoffTimerTask,
768 > ) *persistencespb.TimerTaskInfo { task_serializers.go
769 > return &persistencespb.TimerTaskInfo{
770 > NamespaceId: workflowDelayTimer.NamespaceID,
771 > WorkflowId: workflowDelayTimer.WorkflowID,
772 > RunId: workflowDelayTimer.RunID,
773 > TaskType: enumsspb.TASK_TYPE_WORKFLOW_BACKOFF_TIMER,
774 > TimeoutType: enumspb.TIMEOUT_TYPE_UNSPECIFIED,
775 > WorkflowBackoffType: workflowDelayTimer.WorkflowBackoffType,
776 > Version: workflowDelayTimer.Version,
777 > ScheduleAttempt: 0,
778 > EventId: 0,
779 > TaskId: workflowDelayTimer.TaskID,
780 > VisibilityTime: timestamppb.New(workflowDelayTimer.VisibilityTimestamp),
781 > }
782 > }
783
784 func timerWorkflowDelayTaskFromProto(
969 func timerWorkflowCleanupTaskToProto(
970 workflowCleanupTimer *tasks.DeleteHistoryEventTask,
971 > ) *persistencespb.TimerTaskInfo { task_serializers.go
972 > return &persistencespb.TimerTaskInfo{
973 > NamespaceId: workflowCleanupTimer.NamespaceID,
974 > WorkflowId: workflowCleanupTimer.WorkflowID,
975 > RunId: workflowCleanupTimer.RunID,
976 > TaskType: enumsspb.TASK_TYPE_DELETE_HISTORY_EVENT,
977 > TimeoutType: enumspb.TIMEOUT_TYPE_UNSPECIFIED,
978 > WorkflowBackoffType: enumsspb.WORKFLOW_BACKOFF_TYPE_UNSPECIFIED,
979 > Version: workflowCleanupTimer.Version,
980 > ScheduleAttempt: 0,
981 > EventId: 0,
982 > TaskId: workflowCleanupTimer.TaskID,
983 > VisibilityTime: timestamppb.New(workflowCleanupTimer.VisibilityTimestamp),
984 > BranchToken: workflowCleanupTimer.BranchToken,
985 > // We set this to true even though it's no longer checked in case someone downgrades to a version that still
986 > // checks this field.
987 > AlreadyArchived: true,
988 > TaskDetails: &persistencespb.TimerTaskInfo_ChasmTaskInfo{
989 > ChasmTaskInfo: &persistencespb.ChasmTaskInfo{
990 > ArchetypeId: workflowCleanupTimer.ArchetypeID,
991 > },
992 > },
993 > }
994 > }
995
996 func stateMachineTimerTaskToProto(task *tasks.StateMachineTimerTask) *persistencespb.TimerTaskInfo {
1040 func visibilityStartTaskToProto(
1041 startVisibilityTask *tasks.StartExecutionVisibilityTask,
1042 > ) *persistencespb.VisibilityTaskInfo { task_serializers.go
1043 > return &persistencespb.VisibilityTaskInfo{
1044 > NamespaceId: startVisibilityTask.NamespaceID,
1045 > WorkflowId: startVisibilityTask.WorkflowID,
1046 > RunId: startVisibilityTask.RunID,
1047 > TaskType: enumsspb.TASK_TYPE_VISIBILITY_START_EXECUTION,
1048 > Version: startVisibilityTask.Version,
1049 > TaskId: startVisibilityTask.TaskID,
1050 > VisibilityTime: timestamppb.New(startVisibilityTask.VisibilityTimestamp),
1051 > }
1052 > }
1053
1054 func visibilityStartTaskFromProto(
1055 startVisibilityTask *persistencespb.VisibilityTaskInfo,
1056 > ) *tasks.StartExecutionVisibilityTask { task_serializers.go
1057 > return &tasks.StartExecutionVisibilityTask{
1058 > WorkflowKey: definition.NewWorkflowKey(
1059 > startVisibilityTask.NamespaceId,
1060 > startVisibilityTask.WorkflowId,
1061 > startVisibilityTask.RunId,
1062 > ),
1063 > VisibilityTimestamp: startVisibilityTask.VisibilityTime.AsTime(),
1064 > TaskID: startVisibilityTask.TaskId,
1065 > Version: startVisibilityTask.Version,
1066 > }
1067 > }
1068
1069 func visibilityUpsertTaskToProto(
1096 func visibilityCloseTaskToProto(
1097 closetVisibilityTask *tasks.CloseExecutionVisibilityTask,
1098 > ) *persistencespb.VisibilityTaskInfo { task_serializers.go
1099 > return &persistencespb.VisibilityTaskInfo{
1100 > NamespaceId: closetVisibilityTask.NamespaceID,
1101 > WorkflowId: closetVisibilityTask.WorkflowID,
1102 > RunId: closetVisibilityTask.RunID,
1103 > TaskType: enumsspb.TASK_TYPE_VISIBILITY_CLOSE_EXECUTION,
1104 > Version: closetVisibilityTask.Version,
1105 > TaskId: closetVisibilityTask.TaskID,
1106 > VisibilityTime: timestamppb.New(closetVisibilityTask.VisibilityTimestamp),
1107 > }
1108 > }
1109
1110 func visibilityCloseTaskFromProto(
1111 closeVisibilityTask *persistencespb.VisibilityTaskInfo,
1112 > ) *tasks.CloseExecutionVisibilityTask { task_serializers.go
1113 > return &tasks.CloseExecutionVisibilityTask{
1114 > WorkflowKey: definition.NewWorkflowKey(
1115 > closeVisibilityTask.NamespaceId,
1116 > closeVisibilityTask.WorkflowId,
1117 > closeVisibilityTask.RunId,
1118 > ),
1119 > VisibilityTimestamp: closeVisibilityTask.VisibilityTime.AsTime(),
1120 > TaskID: closeVisibilityTask.TaskId,
1121 > Version: closeVisibilityTask.Version,
1122 > }
1123 > }
1124
1125 func visibilityDeleteTaskToProto(
go.temporal.io/server/common/util.go 215 covered LOC · 56 ranges

Open complete file

135 // Returns true if the Wait() call succeeded before the timeout
136 // Returns false if the Wait() did not return before the timeout
137 > func AwaitWaitGroup(wg *sync.WaitGroup, timeout time.Duration) bool { util.go
138 > return BlockWithTimeout(wg.Wait, timeout)
139 > }
140
141 // BlockWithTimeout invokes fn and waits for it to complete until the timeout.
142 // Returns true if the call completed before the timeout, otherwise returns false.
143 // fn is expected to be a blocking call and will continue to occupy a goroutine until it finally completes.
144 > func BlockWithTimeout(fn func(), timeout time.Duration) bool { util.go
145 > doneC := make(chan struct{})
146 >
147 > go func() {
148 > fn()
149 > close(doneC)
150 > }()
151
152 > timer := time.NewTimer(timeout) util.go
153 > defer timer.Stop()
154 > select {
155 > case <-doneC:
156 > return true
157 case <-timer.C:
158 return false
161
162 // CreatePersistenceClientRetryPolicy creates a retry policy for calls to persistence
163 > func CreatePersistenceClientRetryPolicy() backoff.RetryPolicy { util.go
164 > return backoff.NewExponentialRetryPolicy(persistenceClientRetryInitialInterval).
165 > WithMaximumAttempts(persistenceClientRetryMaxAttempts)
166 > }
167
168 // CreateFrontendClientRetryPolicy creates a retry policy for calls to frontend service
169 > func CreateFrontendClientRetryPolicy() backoff.RetryPolicy { util.go
170 > return backoff.NewExponentialRetryPolicy(frontendClientRetryInitialInterval).
171 > WithMaximumAttempts(frontendClientRetryMaxAttempts)
172 > }
173
174 // CreateHistoryClientRetryPolicy creates a retry policy for calls to history service.
177 // default 1-minute expiration interval and the caller's context. Other errors (and all
178 // errors when the flag is off) follow the standard cap.
179 > func CreateHistoryClientRetryPolicy(retryUnboundedOnSystemResourceExhausted func() bool) backoff.RetryPolicy { util.go
180 > return newClientRetryPolicy(historyClientRetryInitialInterval, historyClientRetryMaxAttempts, retryUnboundedOnSystemResourceExhausted)
181 > }
182
183 // CreateMatchingClientRetryPolicy creates a retry policy for calls to matching service.
186 // default 1-minute expiration interval and the caller's context. Other errors (and all
187 // errors when the flag is off) follow the standard cap.
188 > func CreateMatchingClientRetryPolicy(retryUnboundedOnSystemResourceExhausted func() bool) backoff.RetryPolicy { util.go
189 > return newClientRetryPolicy(matchingClientRetryInitialInterval, matchingClientRetryMaxAttempts, retryUnboundedOnSystemResourceExhausted)
190 > }
191
192 > func newClientRetryPolicy(initialInterval time.Duration, maxAttempts int, retryUnboundedOnSystemResourceExhausted func() bool) backoff.RetryPolicy { util.go
193 > capped := backoff.NewExponentialRetryPolicy(initialInterval).
194 > WithMaximumAttempts(maxAttempts)
195 > // No max-attempts cap; bounded by the default 1-minute expiration interval
196 > // and the caller's context.
197 > extended := backoff.NewExponentialRetryPolicy(initialInterval)
198 > predicate := func(err error) bool {
199 > return retryUnboundedOnSystemResourceExhausted() && isSystemResourceExhausted(err)
200 > }
201 > return backoff.NewConditionalRetryPolicy(predicate, extended, capped)
202 }
203
204 > func isSystemResourceExhausted(err error) bool { util.go
205 > if re, ok := err.(*serviceerror.ResourceExhausted); ok {
206 return re.Scope == enumspb.RESOURCE_EXHAUSTED_SCOPE_SYSTEM
207 }
208 > return false util.go
209 }
210
211 // CreateMatchingClientLongPollRetryPolicy creates a retry policy for poll calls to matching service
212 > func CreateMatchingClientLongPollRetryPolicy() backoff.RetryPolicy { util.go
213 > // no maximum attempts, using default expiration interval of 1 minute
214 > return backoff.NewExponentialRetryPolicy(matchingClientRetryInitialInterval)
215 > }
216
217 // CreateFrontendHandlerRetryPolicy creates a retry policy for calls to frontend service
218 > func CreateFrontendHandlerRetryPolicy() backoff.RetryPolicy { util.go
219 > return backoff.NewExponentialRetryPolicy(frontendHandlerRetryInitialInterval).
220 > WithMaximumInterval(frontendHandlerRetryMaxInterval).
221 > WithMaximumAttempts(frontendHandlerRetryMaxAttempts)
222 > }
223
224 // CreateHistoryHandlerRetryPolicy creates a retry policy for calls to history service
225 > func CreateHistoryHandlerRetryPolicy() backoff.RetryPolicy { util.go
226 > return backoff.NewExponentialRetryPolicy(historyHandlerRetryInitialInterval).
227 > WithMaximumAttempts(historyHandlerRetryMaxAttempts)
228 > }
229
230 // CreateMatchingHandlerRetryPolicy creates a retry policy for calls to matching service
231 > func CreateMatchingHandlerRetryPolicy() backoff.RetryPolicy { util.go
232 > return backoff.NewExponentialRetryPolicy(matchingHandlerRetryInitialInterval).
233 > WithMaximumAttempts(matchingHandlerRetryMaxAttempts)
234 > }
235
236 // CreateReadTaskRetryPolicy creates a retry policy for loading background tasks
237 > func CreateReadTaskRetryPolicy() backoff.RetryPolicy { util.go
238 > return backoff.NewExponentialRetryPolicy(readTaskRetryInitialInterval).
239 > WithMaximumInterval(readTaskRetryMaxInterval).
240 > WithExpirationInterval(readTaskRetryExpirationInterval)
241 > }
242
243 // CreateCompleteTaskRetryPolicy creates a retry policy for completing background tasks
249
250 // CreateTaskReschedulePolicy creates a retry policy for rescheduling task with errors not equal to ErrTaskRetry
251 > func CreateTaskReschedulePolicy() backoff.RetryPolicy { util.go
252 > return backoff.NewExponentialRetryPolicy(taskRescheduleInitialInterval).
253 > WithBackoffCoefficient(taskRescheduleBackoffCoefficient).
254 > WithMaximumInterval(taskRescheduleMaxInterval).
255 > WithExpirationInterval(backoff.NoInterval)
256 > }
257
258 // CreateDependencyTaskNotCompletedReschedulePolicy creates a retry policy for rescheduling task with
259 // ErrDependencyTaskNotCompleted
260 > func CreateDependencyTaskNotCompletedReschedulePolicy() backoff.RetryPolicy { util.go
261 > return backoff.NewExponentialRetryPolicy(dependencyTaskNotCompletedRescheduleInitialInterval).
262 > WithBackoffCoefficient(dependencyTaskNotCompletedRescheduleBackoffCoefficient).
263 > WithMaximumInterval(dependencyTaskNotCompletedRescheduleMaxInterval).
264 > WithExpirationInterval(backoff.NoInterval)
265 > }
266
267 // CreateTaskNotReadyReschedulePolicy creates a retry policy for rescheduling task with ErrTaskRetry
268 > func CreateTaskNotReadyReschedulePolicy() backoff.RetryPolicy { util.go
269 > return backoff.NewExponentialRetryPolicy(taskNotReadyRescheduleInitialInterval).
270 > WithBackoffCoefficient(taskNotReadyRescheduleBackoffCoefficient).
271 > WithMaximumInterval(taskNotReadyRescheduleMaxInterval).
272 > WithExpirationInterval(backoff.NoInterval)
273 > }
274
275 // CreateTaskResourceExhaustedReschedulePolicy creates a retry policy for rescheduling task with resource exhausted error
276 > func CreateTaskResourceExhaustedReschedulePolicy() backoff.RetryPolicy { util.go
277 > return backoff.NewExponentialRetryPolicy(taskResourceExhaustedRescheduleInitialInterval).
278 > WithBackoffCoefficient(taskResourceExhaustedRescheduleBackoffCoefficient).
279 > WithMaximumInterval(taskResourceExhaustedRescheduleMaxInterval).
280 > WithExpirationInterval(backoff.NoInterval)
281 > }
282
283 // CreateSdkClientFactoryRetryPolicy creates a retry policy to handle SdkClientFactory NewClient when frontend service is not ready
284 > func CreateSdkClientFactoryRetryPolicy() backoff.RetryPolicy { util.go
285 > return backoff.NewExponentialRetryPolicy(sdkClientFactoryRetryInitialInterval).
286 > WithMaximumInterval(sdkClientFactoryRetryMaxInterval).
287 > WithExpirationInterval(sdkClientFactoryRetryExpirationInterval)
288 > }
289
290 // IsPersistenceTransientError checks if the error is a transient persistence error
322
323 // IsContextDeadlineExceededErr checks if the error is context.DeadlineExceeded or serviceerror.DeadlineExceeded error
324 > func IsContextDeadlineExceededErr(err error) bool { util.go
325 > var deadlineExceededSvcErr *serviceerror.DeadlineExceeded
326 > return errors.Is(err, context.DeadlineExceeded) ||
327 > errors.As(err, &deadlineExceededSvcErr)
328 > }
329
330 // IsContextCanceledErr checks if the error is context.Canceled or serviceerror.Canceled error
331 > func IsContextCanceledErr(err error) bool { util.go
332 > var canceledSvcErr *serviceerror.Canceled
333 > return errors.Is(err, context.Canceled) ||
334 > errors.As(err, &canceledSvcErr)
335 > }
336
337 // IsServiceClientTransientError checks if the error is a transient error.
338 > func IsServiceClientTransientError(err error) bool { util.go
339 > if IsServiceHandlerRetryableError(err) {
340 > return true util.go
341 > }
342
343 > if isSystemResourceExhausted(err) { util.go
344 return true
345 }
346
347 > switch err.(type) { util.go
348 case *serviceerrors.ShardOwnershipLost,
349 *serviceerrors.StalePartitionCounts:
351 }
352
353 > return false util.go
354 }
355
356 > func IsServiceHandlerRetryableError(err error) bool { util.go
357 > if IsNamespaceHandoverError(err) {
358 return false
359 }
360
361 > switch err := err.(type) { util.go
362 case *serviceerror.Internal,
363 > *serviceerror.Unavailable: util.go
364 > return true
365 case *serviceerror.MultiOperationExecution:
366 for _, opErr := range err.OperationErrors() {
371 }
372
373 > return false util.go
374 }
375
376 > func IsNamespaceHandoverError(err error) bool { util.go
377 > return err.Error() == ErrNamespaceHandover.Error()
378 > }
379
380 func IsStickyWorkerUnavailable(err error) bool {
387
388 // IsResourceExhausted checks if the error is a service busy error.
389 > func IsResourceExhausted(err error) bool { util.go
390 > switch err.(type) {
391 case *serviceerror.ResourceExhausted:
392 return true
393 }
394 > return false util.go
395 }
396
402
403 // IsNotFoundError checks if the error is a not found error.
404 > func IsNotFoundError(err error) bool { util.go
405 > var notFoundErr *serviceerror.NotFound
406 > return errors.As(err, &notFoundErr)
407 > }
408
409 func ErrorHash(err error) string {
420 workflowID string,
421 numberOfShards int32,
422 > ) int32 { util.go
423 > idBytes := []byte(namespaceID + "_" + workflowID)
424 > hash := farm.Fingerprint32(idBytes)
425 > return int32(hash%uint32(numberOfShards)) + 1 // ShardID starts with 1
426 > }
427
428 func MapShardID(
500 // Returns nil if the context is still valid. Otherwise, returns the result of
501 // ctx.Err()
502 > func IsValidContext(ctx context.Context) error { util.go
503 > ch := ctx.Done()
504 > if ch != nil {
505 > select { util.go
506 case <-ch:
507 return ctx.Err()
508 > default: util.go
509 > return nil
510 }
511 }
518
519 // GenerateRandomString is used for generate test string
520 > func GenerateRandomString(n int) string { util.go
521 > letterRunes := []rune("random")
522 > b := make([]rune, n)
523 > for i := range b {
524 > b[i] = letterRunes[rand.Intn(len(letterRunes))]
525 > }
526 > return string(b)
527 }
528
529 // CreateMatchingPollWorkflowTaskQueueResponse create response for matching's PollWorkflowTaskQueue
530 > func CreateMatchingPollWorkflowTaskQueueResponse(historyResponse *historyservice.RecordWorkflowTaskStartedResponse, workflowExecution *commonpb.WorkflowExecution, token []byte) *matchingservice.PollWorkflowTaskQueueResponseWithRawHistory { util.go
531 > matchingResp := &matchingservice.PollWorkflowTaskQueueResponseWithRawHistory{
532 > TaskToken: token,
533 > WorkflowExecution: workflowExecution,
534 > WorkflowType: historyResponse.WorkflowType,
535 > PreviousStartedEventId: historyResponse.PreviousStartedEventId,
536 > StartedEventId: historyResponse.StartedEventId,
537 > Attempt: historyResponse.GetAttempt(),
538 > NextEventId: historyResponse.NextEventId,
539 > StickyExecutionEnabled: historyResponse.StickyExecutionEnabled,
540 > TransientWorkflowTask: historyResponse.TransientWorkflowTask,
541 > WorkflowExecutionTaskQueue: historyResponse.WorkflowExecutionTaskQueue,
542 > BranchToken: historyResponse.BranchToken,
543 > ScheduledTime: historyResponse.ScheduledTime,
544 > StartedTime: historyResponse.StartedTime,
545 > Queries: historyResponse.Queries,
546 > Messages: historyResponse.Messages,
547 > History: historyResponse.History,
548 > NextPageToken: historyResponse.NextPageToken,
549 > RawHistory: historyResponse.RawHistoryBytes,
550 > }
551 >
552 > return matchingResp
553 > }
554
555 // CreateHistoryStartWorkflowRequest create a start workflow request for history.
561 rootExecutionInfo *workflowspb.RootExecutionInfo,
562 now time.Time,
563 > ) *historyservice.StartWorkflowExecutionRequest { util.go
564 > // We include the original startRequest in the forwarded request to History, but
565 > // we don't want to send workflow payloads twice. We deep copy to a new struct,
566 > // rather than mutate the request, to accommodate internal retries.
567 > if startRequest.ContinuedFailure != nil || startRequest.LastCompletionResult != nil {
568 startRequest = CloneProto(startRequest)
569 }
570 > histRequest := &historyservice.StartWorkflowExecutionRequest{ util.go
571 > NamespaceId: namespaceID,
572 > StartRequest: startRequest,
573 > ContinueAsNewInitiator: enumspb.CONTINUE_AS_NEW_INITIATOR_UNSPECIFIED,
574 > Attempt: 1,
575 > ParentExecutionInfo: parentExecutionInfo,
576 > FirstWorkflowTaskBackoff: durationpb.New(backoff.GetBackoffForNextScheduleNonNegative(startRequest.GetCronSchedule(), now, now)),
577 > ContinuedFailure: startRequest.ContinuedFailure,
578 > LastCompletionResult: startRequest.LastCompletionResult,
579 > RootExecutionInfo: rootExecutionInfo,
580 > VersioningOverride: startRequest.GetVersioningOverride(),
581 > }
582 > startRequest.ContinuedFailure = nil
583 > startRequest.LastCompletionResult = nil
584 >
585 > if timestamp.DurationValue(startRequest.GetWorkflowExecutionTimeout()) > 0 {
586 deadline := now.Add(timestamp.DurationValue(startRequest.GetWorkflowExecutionTimeout()))
587 histRequest.WorkflowExecutionExpirationTime = timestamppb.New(deadline.Round(time.Millisecond))
589
590 // CronSchedule and WorkflowStartDelay should not both be set on the same request
591 > if len(startRequest.CronSchedule) != 0 { util.go
592 > histRequest.ContinueAsNewInitiator = enumspb.CONTINUE_AS_NEW_INITIATOR_CRON_SCHEDULE util.go
593 > }
594
595 > if timestamp.DurationValue(startRequest.GetWorkflowStartDelay()) > 0 { util.go
596 histRequest.FirstWorkflowTaskBackoff = startRequest.GetWorkflowStartDelay()
597 }
598
599 > return histRequest util.go
600 }
601
612 logger log.Logger,
613 operation string,
614 > ) error { util.go
615 >
616 > metrics.EventBlobSize.With(metricsHandler).Record(int64(actualSize), metrics.OperationTag(operation))
617 > if actualSize > warnLimit {
618 if logger != nil {
619 logger.Warn("Blob data size exceeds the warning limit.",
630 }
631 }
632 > return nil util.go
633 }
634
640 handlerName string,
641 logger log.Logger,
642 > ) error { util.go
643 >
644 > deadline, err := ValidateLongPollContextTimeoutIsSet(ctx, handlerName, logger)
645 > if err != nil {
646 return err
647 }
648 > timeout := time.Until(deadline) util.go
649 > if timeout < MinLongPollTimeout {
650 err := ErrContextTimeoutTooShort
651 logger.Error("Context timeout is too short for long poll API.",
653 return err
654 }
655 > if timeout < CriticalLongPollTimeout { util.go
656 logger.Warn("Context timeout is lower than critical value for long poll API.",
657 tag.WorkflowHandlerName(handlerName), tag.WorkflowPollContextTimeout(timeout))
658 }
659 > return nil util.go
660 }
661
665 handlerName string,
666 logger log.Logger,
667 > ) (time.Time, error) { util.go
668 >
669 > deadline, ok := ctx.Deadline()
670 > if !ok {
671 err := ErrContextTimeoutNotSet
672 logger.Error("Context timeout not set for long poll API.",
674 return deadline, err
675 }
676 > return deadline, nil util.go
677 }
678
688
689 // CloneProto is a generic typed version of proto.Clone from proto.
690 > func CloneProto[T proto.Message](v T) T { util.go
691 > return proto.Clone(v).(T)
692 > }
693
694 func CloneProtoMap[K comparable, T proto.Message](src map[K]T) map[K]T {
go.temporal.io/server/common/persistence/sql/execution.go 214 covered LOC · 38 ranges

Open complete file

30 logger log.Logger,
31 serializer serialization.Serializer,
32 > ) (p.ExecutionStore, error) { execution.go
33 > return &sqlExecutionStore{
34 > SqlStore: NewSQLStore(db, logger, serializer),
35 > HistoryBranchUtil: p.NewHistoryBranchUtil(serializer),
36 > }, nil
37 > }
38
39 // txExecuteShardLocked executes f under transaction and with read lock on shard row
44 rangeID int64,
45 fn func(tx sqlplugin.Tx) error,
46 > ) error { execution.go
47 >
48 > return m.txExecute(ctx, operation, func(tx sqlplugin.Tx) error {
49 > if err := readLockShard(ctx, tx, shardID, rangeID); err != nil {
50 return err
51 }
52 > err := fn(tx) execution.go
53 > if err != nil {
54 return err
55 }
56 > return nil execution.go
57 })
58 }
61 ctx context.Context,
62 request *p.InternalCreateWorkflowExecutionRequest,
63 > ) (response *p.InternalCreateWorkflowExecutionResponse, err error) { execution.go
64 > for _, req := range request.NewWorkflowNewEvents {
65 > if err := m.AppendHistoryNodes(ctx, req); err != nil { execution.go
66 return nil, err
67 }
68 }
69
70 > err = m.txExecuteShardLocked(ctx, execution.go
71 > "CreateWorkflowExecution",
72 > request.ShardID,
73 > request.RangeID,
74 > func(tx sqlplugin.Tx) error {
75 > response, err = m.createWorkflowExecutionTx(ctx, tx, request)
76 > return err
77 > })
78 > return
79 }
80
83 tx sqlplugin.Tx,
84 request *p.InternalCreateWorkflowExecutionRequest,
85 > ) (*p.InternalCreateWorkflowExecutionResponse, error) { execution.go
86 >
87 > newWorkflow := request.NewWorkflowSnapshot
88 > lastWriteVersion := newWorkflow.LastWriteVersion
89 > shardID := request.ShardID
90 > namespaceID := primitives.MustParseUUID(newWorkflow.NamespaceID)
91 > workflowID := newWorkflow.WorkflowID
92 > runID := primitives.MustParseUUID(newWorkflow.RunID)
93 >
94 > var err error
95 > var currentRow *sqlplugin.CurrentExecutionsRow
96 > if currentRow, err = lockCurrentExecutionIfExists(ctx,
97 > tx,
98 > shardID,
99 > namespaceID,
100 > workflowID,
101 > request.ArchetypeID,
102 > ); err != nil {
103 return nil, err
104 }
105
106 // current run ID, last write version, current workflow state check
107 > switch request.Mode { execution.go
108 > case p.CreateWorkflowModeBrandNew: execution.go
109 > if currentRow == nil {
110 > // current row does not exists, suits the create mode
111 > } else {
112 if currentRow.RunID.String() != request.PreviousRunID {
113 return nil, m.extractCurrentWorkflowConflictError(
178 }
179
180 > row := sqlplugin.CurrentExecutionsRow{ execution.go
181 > ShardID: shardID,
182 > NamespaceID: namespaceID,
183 > WorkflowID: workflowID,
184 > RunID: runID,
185 > ArchetypeID: request.ArchetypeID,
186 > CreateRequestID: newWorkflow.ExecutionState.CreateRequestId,
187 > State: newWorkflow.ExecutionState.State,
188 > Status: newWorkflow.ExecutionState.Status,
189 > LastWriteVersion: lastWriteVersion,
190 > StartTime: getStartTimeFromState(newWorkflow.ExecutionState),
191 > Data: newWorkflow.ExecutionStateBlob.Data,
192 > DataEncoding: newWorkflow.ExecutionStateBlob.EncodingType.String(),
193 > }
194 >
195 > if err := createOrUpdateCurrentExecution(ctx, tx, row, request.Mode); err != nil {
196 return nil, err
197 }
198
199 > if err := m.applyWorkflowSnapshotTxAsNew(ctx, execution.go
200 > tx,
201 > shardID,
202 > &request.NewWorkflowSnapshot,
203 > ); err != nil {
204 return nil, err
205 }
206
207 > return &p.InternalCreateWorkflowExecutionResponse{}, nil execution.go
208 }
209
211 ctx context.Context,
212 request *p.GetWorkflowExecutionRequest,
213 > ) (*p.InternalGetWorkflowExecutionResponse, error) { execution.go
214 > namespaceID := primitives.MustParseUUID(request.NamespaceID)
215 > workflowID := request.WorkflowID
216 > runID := primitives.MustParseUUID(request.RunID)
217 > executionsRow, err := m.DB.SelectFromExecutions(ctx, sqlplugin.ExecutionsFilter{
218 > ShardID: request.ShardID,
219 > NamespaceID: namespaceID,
220 > WorkflowID: workflowID,
221 > RunID: runID,
222 > })
223 > switch err {
224 > case nil: execution.go
225 // noop
226 case sql.ErrNoRows:
230 }
231
232 > state := &p.InternalWorkflowMutableState{ execution.go
233 > ExecutionInfo: p.NewDataBlob(executionsRow.Data, executionsRow.DataEncoding),
234 > ExecutionState: p.NewDataBlob(executionsRow.State, executionsRow.StateEncoding),
235 > NextEventID: executionsRow.NextEventID,
236 >
237 > DBRecordVersion: executionsRow.DBRecordVersion,
238 > }
239 >
240 > state.ActivityInfos, err = getActivityInfoMap(ctx,
241 > m.DB,
242 > request.ShardID,
243 > namespaceID,
244 > workflowID,
245 > runID,
246 > )
247 > if err != nil {
248 return nil, serviceerror.NewUnavailablef("GetWorkflowExecution: failed to get activity info. Error: %v", err)
249 }
250
251 > state.TimerInfos, err = getTimerInfoMap(ctx, execution.go
252 > m.DB,
253 > request.ShardID,
254 > namespaceID,
255 > workflowID,
256 > runID,
257 > )
258 > if err != nil {
259 return nil, serviceerror.NewUnavailablef("GetWorkflowExecution: failed to get timer info. Error: %v", err)
260 }
261
262 > state.ChildExecutionInfos, err = getChildExecutionInfoMap(ctx, execution.go
263 > m.DB,
264 > request.ShardID,
265 > namespaceID,
266 > workflowID,
267 > runID,
268 > )
269 > if err != nil {
270 return nil, serviceerror.NewUnavailablef("GetWorkflowExecution: failed to get child executionsRow info. Error: %v", err)
271 }
272
273 > state.RequestCancelInfos, err = getRequestCancelInfoMap(ctx, execution.go
274 > m.DB,
275 > request.ShardID,
276 > namespaceID,
277 > workflowID,
278 > runID,
279 > )
280 > if err != nil {
281 return nil, serviceerror.NewUnavailablef("GetWorkflowExecution: failed to get request cancel info. Error: %v", err)
282 }
283
284 > state.SignalInfos, err = getSignalInfoMap(ctx, execution.go
285 > m.DB,
286 > request.ShardID,
287 > namespaceID,
288 > workflowID,
289 > runID,
290 > )
291 > if err != nil {
292 return nil, serviceerror.NewUnavailablef("GetWorkflowExecution: failed to get signal info. Error: %v", err)
293 }
294
295 > state.BufferedEvents, err = getBufferedEvents(ctx, execution.go
296 > m.DB,
297 > request.ShardID,
298 > namespaceID,
299 > workflowID,
300 > runID,
301 > )
302 > if err != nil {
303 return nil, serviceerror.NewUnavailablef("GetWorkflowExecution: failed to get buffered events. Error: %v", err)
304 }
305
306 > state.ChasmNodes, err = getChasmNodeMap(ctx, execution.go
307 > m.DB,
308 > request.ShardID,
309 > namespaceID,
310 > workflowID,
311 > runID,
312 > )
313 > if err != nil {
314 return nil, serviceerror.NewUnavailablef("GetWorkflowExecution: failed to get CHASM nodes. Error: %v", err)
315 }
316
317 > state.SignalRequestedIDs, err = getSignalsRequested(ctx, execution.go
318 > m.DB,
319 > request.ShardID,
320 > namespaceID,
321 > workflowID,
322 > runID,
323 > )
324 > if err != nil {
325 return nil, serviceerror.NewUnavailablef("GetWorkflowExecution: failed to get signals requested. Error: %v", err)
326 }
327
328 > return &p.InternalGetWorkflowExecutionResponse{ execution.go
329 > State: state,
330 > DBRecordVersion: executionsRow.DBRecordVersion,
331 > }, nil
332 }
333
335 ctx context.Context,
336 request *p.InternalUpdateWorkflowExecutionRequest,
337 > ) error { execution.go
338 > // first append history
339 > for _, req := range request.UpdateWorkflowNewEvents {
340 > if err := m.AppendHistoryNodes(ctx, req); err != nil { execution.go
341 return err
342 }
343 }
344 > for _, req := range request.NewWorkflowNewEvents { execution.go
345 if err := m.AppendHistoryNodes(ctx, req); err != nil {
346 return err
349
350 // then update mutable state
351 > return m.txExecuteShardLocked(ctx, execution.go
352 > "UpdateWorkflowExecution",
353 > request.ShardID,
354 > request.RangeID,
355 > func(tx sqlplugin.Tx) error {
356 > return m.updateWorkflowExecutionTx(ctx, tx, request)
357 > })
358 }
359
362 tx sqlplugin.Tx,
363 request *p.InternalUpdateWorkflowExecutionRequest,
364 > ) error { execution.go
365 >
366 > updateWorkflow := request.UpdateWorkflowMutation
367 > newWorkflow := request.NewWorkflowSnapshot
368 >
369 > namespaceID := primitives.MustParseUUID(updateWorkflow.NamespaceID)
370 > workflowID := updateWorkflow.WorkflowID
371 > runID := primitives.MustParseUUID(updateWorkflow.ExecutionState.RunId)
372 >
373 > shardID := request.ShardID
374 >
375 > switch request.Mode {
376 case p.UpdateWorkflowModeIgnoreCurrent:
377 // noop
390 }
391
392 > case p.UpdateWorkflowModeUpdateCurrent: execution.go
393 > row := sqlplugin.CurrentExecutionsRow{
394 > ShardID: shardID,
395 > NamespaceID: namespaceID,
396 > WorkflowID: workflowID,
397 > ArchetypeID: request.ArchetypeID,
398 > StartTime: nil,
399 > }
400 >
401 > if newWorkflow != nil {
402 row.CreateRequestID = newWorkflow.ExecutionState.CreateRequestId
403 row.State = newWorkflow.ExecutionState.State
413 return serviceerror.NewUnavailable("UpdateWorkflowExecution: cannot continue as new to another namespace")
414 }
415 > } else { execution.go
416 > row.CreateRequestID = updateWorkflow.ExecutionState.CreateRequestId
417 > row.State = updateWorkflow.ExecutionState.State
418 > row.Status = updateWorkflow.ExecutionState.Status
419 > row.LastWriteVersion = updateWorkflow.LastWriteVersion
420 > row.RunID = runID
421 > row.StartTime = getStartTimeFromState(updateWorkflow.ExecutionState)
422 > row.Data = updateWorkflow.ExecutionStateBlob.Data
423 > row.DataEncoding = updateWorkflow.ExecutionStateBlob.EncodingType.String()
424 > // we still call update only to update the current record
425 > }
426 > if err := assertRunIDAndUpdateCurrentExecution(ctx, tx, row, runID, m.serializer); err != nil { execution.go
427 return err
428 }
432 }
433
434 > if err := m.applyWorkflowMutationTx(ctx, tx, shardID, &updateWorkflow); err != nil { execution.go
435 return err
436 }
437
438 > if newWorkflow != nil { execution.go
439 if err := m.applyWorkflowSnapshotTxAsNew(ctx, tx, shardID, newWorkflow); err != nil {
440 return err
441 }
442 }
443 > return nil execution.go
444 }
445
741 }
742
743 > func (m *sqlExecutionStore) GetHistoryBranchUtil() p.HistoryBranchUtil { execution.go
744 > return m.HistoryBranchUtil
745 > }
746
747 > func getStartTimeFromState(state *persistencespb.WorkflowExecutionState) *time.Time { execution.go
748 > if state == nil || state.StartTime == nil {
749 return nil
750 }
751 > startTime := state.StartTime.AsTime() execution.go
752 > return &startTime
753 }
go.temporal.io/server/common/membership/ringpop/monitor.go 212 covered LOC · 49 ranges

Open complete file

84 joinTime time.Time,
85 replicaPoints int,
86 > ) *monitor { monitor.go
87 > lifecycleCtx, lifecycleCancel := context.WithCancel(context.Background())
88 > lifecycleCtx = headers.SetCallerInfo(
89 > lifecycleCtx,
90 > headers.SystemBackgroundHighCallerInfo,
91 > )
92 > hostID, _ := uuid.New().MarshalBinary()
93 > // MarshalBinary should never error.
94 >
95 > rpo := &monitor{
96 > status: common.DaemonStatusInitialized,
97 >
98 > lifecycleCtx: lifecycleCtx,
99 > lifecycleCancel: lifecycleCancel,
100 >
101 > serviceName: serviceName,
102 > services: services,
103 > rp: rp,
104 > rings: make(map[primitives.ServiceName]*serviceResolver),
105 > replicaPoints: replicaPoints,
106 > logger: logger,
107 > metadataManager: metadataManager,
108 > broadcastHostPortResolver: broadcastHostPortResolver,
109 > hostID: hostID,
110 > initialized: future.NewFuture[struct{}](),
111 > maxJoinDuration: maxJoinDuration,
112 > propagationTime: propagationTime,
113 > joinTime: joinTime,
114 > }
115 > for service, port := range services {
116 > rpo.rings[service] = newServiceResolver(service, port, rp, replicaPoints, logger)
117 > }
118 > return rpo
119 }
120
122 // it's safe for Stop() to run, which is at any point when we are neither updating the status field nor
123 // starting rings
124 > func (rpo *monitor) Start() { monitor.go
125 > rpo.stateLock.Lock()
126 > if rpo.status != common.DaemonStatusInitialized {
127 rpo.stateLock.Unlock()
128 return
129 }
130 > rpo.status = common.DaemonStatusStarted monitor.go
131 > rpo.stateLock.Unlock()
132 >
133 > broadcastAddress, err := rpo.broadcastHostPortResolver()
134 > if err != nil {
135 rpo.logger.Fatal("unable to resolve broadcast address", tag.Error(err))
136 }
140 // we must know our seed nodes before bootstrapping
141
142 > if err = rpo.startHeartbeat(broadcastAddress); err != nil { monitor.go
143 rpo.logger.Fatal("unable to initialize membership heartbeats", tag.Error(err))
144 }
145
146 > if err = rpo.bootstrapRingPop(); err != nil { monitor.go
147 // Stop() called during Start()'s execution. This is ok
148 if strings.Contains(err.Error(), "destroyed while attempting to join") {
152 }
153
154 > labels, err := rpo.rp.Labels() monitor.go
155 > if err != nil {
156 rpo.logger.Fatal("unable to get ringpop labels", tag.Error(err))
157 }
158
159 > if until := time.Until(rpo.joinTime); until > 0 && until.Seconds() < maxScheduledEventTimeSeconds { monitor.go
160 if err = labels.Set(startAtKey, strconv.FormatInt(rpo.joinTime.Unix(), 10)); err != nil {
161 rpo.logger.Fatal("unable to set ringpop label", tag.Error(err), tag.Key(startAtKey))
168 }
169
170 > if err = labels.Set(portKey, strconv.Itoa(rpo.services[rpo.serviceName])); err != nil { monitor.go
171 rpo.logger.Fatal("unable to set ringpop label", tag.Error(err), tag.Key(portKey))
172 }
173
174 // This label should be set last, it's used as the prediciate for finding members for rings.
175 > if err = labels.Set(roleKey, string(rpo.serviceName)); err != nil { monitor.go
176 rpo.logger.Fatal("unable to set ringpop label", tag.Error(err), tag.Key(roleKey))
177 }
178
179 // Our individual rings may not support concurrent start/stop calls so we reacquire the state lock while acting upon them
180 > rpo.stateLock.Lock() monitor.go
181 > for _, ring := range rpo.rings {
182 > ring.Start()
183 > }
184 > rpo.stateLock.Unlock()
185 >
186 > rpo.initialized.Set(struct{}{}, nil)
187 }
188
189 // bootstrap ring pop service by discovering the bootstrap hosts and joining the ring pop cluster
190 > func (rpo *monitor) bootstrapRingPop() error { monitor.go
191 > policy := backoff.NewExponentialRetryPolicy(healthyHostLastHeartbeatCutoff / 2).
192 > WithBackoffCoefficient(1).
193 > WithMaximumAttempts(maxBootstrapRetries)
194 > op := func() error {
195 > hostPorts, err := rpo.fetchCurrentBootstrapHostports()
196 > if err != nil {
197 return err
198 }
199
200 > bootParams := &swim.BootstrapOptions{ monitor.go
201 > ParallelismFactor: 10,
202 > JoinSize: 1,
203 > MaxJoinDuration: rpo.maxJoinDuration,
204 > DiscoverProvider: statichosts.New(hostPorts...),
205 > }
206 >
207 > _, err = rpo.rp.Bootstrap(bootParams)
208 > if err != nil {
209 rpo.logger.Warn("unable to bootstrap ringpop. retrying", tag.Error(err))
210 }
211 > return err monitor.go
212 }
213
214 > if err := backoff.ThrottleRetry(op, policy, nil); err != nil { monitor.go
215 return fmt.Errorf("exhausted all retries: %w", err)
216 }
217 > return nil monitor.go
218 }
219
226 }
227
228 > func (rpo *monitor) WaitUntilInitialized(ctx context.Context) error { monitor.go
229 > _, err := rpo.initialized.Get(ctx)
230 > return err
231 > }
232
233 func (rpo *monitor) upsertMyMembership(
234 ctx context.Context,
235 request *persistence.UpsertClusterMembershipRequest,
236 > ) error { monitor.go
237 > err := rpo.metadataManager.UpsertClusterMembership(ctx, request)
238 >
239 > if err == nil {
240 > hostID, err := uuid.FromBytes(request.HostID)
241 > if err != nil {
242 return err
243 }
244 > rpo.logger.Debug("Membership heartbeat upserted successfully", monitor.go
245 > tag.Address(request.RPCAddress.String()),
246 > tag.Port(int(request.RPCPort)),
247 > tag.HostID(hostID.String()))
248 }
249
250 > return err monitor.go
251 }
252
253 // splitHostPortTyped expands upon net.SplitHostPort by providing type parsing.
254 > func splitHostPortTyped(hostPort string) (net.IP, uint16, error) { monitor.go
255 > ipstr, portstr, err := net.SplitHostPort(hostPort)
256 > if err != nil {
257 return nil, 0, err
258 }
259
260 > broadcastAddress := net.ParseIP(ipstr) monitor.go
261 > broadcastPort, err := strconv.ParseUint(portstr, 10, 16)
262 > if err != nil {
263 return nil, 0, err
264 }
265
266 > return broadcastAddress, uint16(broadcastPort), nil monitor.go
267 }
268
269 > func (rpo *monitor) startHeartbeat(broadcastHostport string) error { monitor.go
270 > // Start by cleaning up expired records to avoid growth
271 > err := rpo.metadataManager.PruneClusterMembership(rpo.lifecycleCtx, &persistence.PruneClusterMembershipRequest{MaxRecordsPruned: 10})
272 > if err != nil {
273 return err
274 }
275
276 > sessionStarted := time.Now().UTC() monitor.go
277 >
278 > // Parse and validate broadcast hostport
279 > broadcastAddress, broadcastPort, err := splitHostPortTyped(broadcastHostport)
280 > if err != nil {
281 return err
282 }
283
284 // Parse and validate existing service name
285 > role, err := serviceNameToServiceTypeEnum(rpo.serviceName) monitor.go
286 > if err != nil {
287 return err
288 }
289
290 > req := &persistence.UpsertClusterMembershipRequest{ monitor.go
291 > Role: role,
292 > RPCAddress: broadcastAddress,
293 > RPCPort: broadcastPort,
294 > SessionStart: sessionStarted,
295 > RecordExpiry: upsertMembershipRecordExpiryDefault,
296 > HostID: rpo.hostID,
297 > }
298 >
299 > // Upsert before fetching bootstrap hosts.
300 > // This makes us discoverable by other Temporal cluster members
301 > // Expire in 48 hours to allow for inspection of table by humans for debug scenarios.
302 > // For bootstrapping, we filter to a much shorter duration on the
303 > // read side by filtering on the last time a heartbeat was seen.
304 > err = rpo.upsertMyMembership(rpo.lifecycleCtx, req)
305 > if err == nil {
306 > hostID, err := uuid.FromBytes(rpo.hostID)
307 > if err != nil {
308 return err
309 }
310 > rpo.logger.Info("Membership heartbeat upserted successfully", monitor.go
311 > tag.Address(broadcastAddress.String()),
312 > tag.Port(int(broadcastPort)),
313 > tag.HostID(hostID.String()))
314 >
315 > rpo.startHeartbeatUpsertLoop(req)
316 }
317
318 > return err monitor.go
319 }
320
321 > func (rpo *monitor) fetchCurrentBootstrapHostports() ([]string, error) { monitor.go
322 > pageSize := 1000
323 > set := make(map[string]struct{})
324 >
325 > var nextPageToken []byte
326 >
327 > for {
328 > resp, err := rpo.metadataManager.GetClusterMembers(
329 > rpo.lifecycleCtx,
330 > &persistence.GetClusterMembersRequest{
331 > LastHeartbeatWithin: healthyHostLastHeartbeatCutoff,
332 > PageSize: pageSize,
333 > NextPageToken: nextPageToken,
334 > })
335 > if err != nil {
336 return nil, err
337 }
338
339 // Dedupe on hostport
340 > for _, host := range resp.ActiveMembers { monitor.go
341 > set[net.JoinHostPort(host.RPCAddress.String(), convert.Uint16ToString(host.RPCPort))] = struct{}{}
342 > }
343 > nextPageToken = resp.NextPageToken
344 >
345 > // Stop iterating once we have either 500 unique ip:port combos or there is no more results.
346 > if len(nextPageToken) == 0 || len(set) >= 500 {
347 > bootstrapHostPorts := make([]string, 0, len(set))
348 > for k := range set {
349 > bootstrapHostPorts = append(bootstrapHostPorts, k)
350 > }
351
352 > rpo.logger.Info("bootstrap hosts fetched", tag.BootstrapHostPorts(strings.Join(bootstrapHostPorts, ","))) monitor.go
353 > return bootstrapHostPorts, nil
354 }
355 }
356 }
357
358 > func (rpo *monitor) startHeartbeatUpsertLoop(request *persistence.UpsertClusterMembershipRequest) { monitor.go
359 > loopUpsertMembership := func() {
360 > for {
361 > select {
362 case <-rpo.lifecycleCtx.Done():
363 return
364 > default: monitor.go
365 }
366 > err := rpo.upsertMyMembership(rpo.lifecycleCtx, request) monitor.go
367 > if err != nil {
368 rpo.logger.Error("Membership upsert failed.", tag.Error(err))
369 }
370
371 > jitter := math.Round(rand.Float64() * 5) monitor.go
372 > time.Sleep(time.Second * time.Duration(10+jitter))
373 }
374 }
375
376 > go loopUpsertMembership() monitor.go
377 }
378
380 // for the entire call as the individual ring Start/Stop functions may not be safe to
381 // call concurrently
382 > func (rpo *monitor) Stop() { monitor.go
383 > rpo.stateLock.Lock()
384 > defer rpo.stateLock.Unlock()
385 > if rpo.status != common.DaemonStatusStarted {
386 return
387 }
388 > rpo.status = common.DaemonStatusStopped monitor.go
389 >
390 > rpo.lifecycleCancel()
391 >
392 > for _, ring := range rpo.rings {
393 > ring.Stop()
394 > }
395
396 > rpo.rp.Destroy() monitor.go
397 }
398
399 > func (rpo *monitor) EvictSelf() error { monitor.go
400 > return rpo.rp.SelfEvict()
401 > }
402
403 func (rpo *monitor) EvictSelfAt(asOf time.Time) (time.Duration, error) {
425 }
426
427 > func (rpo *monitor) GetResolver(service primitives.ServiceName) (membership.ServiceResolver, error) { monitor.go
428 > ring, found := rpo.rings[service]
429 > if !found {
430 return nil, membership.ErrUnknownService
431 }
432 > return ring, nil monitor.go
433 }
434
437 }
438
439 > func (rpo *monitor) SetDraining(draining bool) error { monitor.go
440 > labels, err := rpo.rp.Labels()
441 > if err != nil {
442 // This only happens if ringpop is not bootstrapped yet.
443 return err
444 }
445 > return labels.Set(drainingKey, strconv.FormatBool(draining)) monitor.go
446 }
447
450 }
451
452 > func replaceServicePort(address string, servicePort int) (string, error) { monitor.go
453 > host, _, err := net.SplitHostPort(address)
454 > if err != nil {
455 return "", membership.ErrIncorrectAddressFormat
456 }
457 > return net.JoinHostPort(host, convert.IntToString(servicePort)), nil monitor.go
458 }
459
463
464 // RegisterServiceNameToServiceTypeEnum must be called from a static init().
465 > func RegisterServiceNameToServiceTypeEnum(serviceName primitives.ServiceName, serviceType persistence.ServiceType) { monitor.go
466 > serviceNameToServiceTypeEnumMap[serviceName] = serviceType
467 > }
468
469 > func init() { monitor.go
470 > RegisterServiceNameToServiceTypeEnum(primitives.AllServices, persistence.All)
471 > RegisterServiceNameToServiceTypeEnum(primitives.FrontendService, persistence.Frontend)
472 > RegisterServiceNameToServiceTypeEnum(primitives.InternalFrontendService, persistence.InternalFrontend)
473 > RegisterServiceNameToServiceTypeEnum(primitives.HistoryService, persistence.History)
474 > RegisterServiceNameToServiceTypeEnum(primitives.MatchingService, persistence.Matching)
475 > RegisterServiceNameToServiceTypeEnum(primitives.WorkerService, persistence.Worker)
476 > }
477
478 > func serviceNameToServiceTypeEnum(name primitives.ServiceName) (persistence.ServiceType, error) { monitor.go
479 > if serviceType, ok := serviceNameToServiceTypeEnumMap[name]; ok {
480 > return serviceType, nil
481 > }
482
483 return persistence.All, fmt.Errorf("unable to parse servicename '%s'", name)
go.temporal.io/server/common/persistence/history_manager.go 211 covered LOC · 47 ranges

Open complete file

324 func (m *executionManagerImpl) serializeAppendHistoryNodesRequest(
325 request *AppendHistoryNodesRequest,
326 > ) (*InternalAppendHistoryNodesRequest, error) { history_manager.go
327 > branch, err := m.GetHistoryBranchUtil().ParseHistoryBranchInfo(request.BranchToken)
328 > if err != nil {
329 return nil, serviceerror.NewInvalidArgument(fmt.Sprintf("unable to parse branch token: %v", err))
330 }
331
332 > if len(request.Events) == 0 { history_manager.go
333 return nil, &InvalidPersistenceRequestError{
334 Msg: "events to be appended cannot be empty",
335 }
336 }
337 > sortAncestors(branch.Ancestors) history_manager.go
338 >
339 > version := request.Events[0].Version
340 > nodeID := request.Events[0].EventId
341 > lastID := nodeID - 1
342 >
343 > if nodeID <= 0 {
344 return nil, &InvalidPersistenceRequestError{
345 Msg: "eventID cannot be less than 1",
346 }
347 }
348 > for _, e := range request.Events { history_manager.go
349 > if e.Version != version {
350 return nil, &InvalidPersistenceRequestError{
351 Msg: "event version must be the same inside a batch",
352 }
353 }
354 > if e.EventId != lastID+1 { history_manager.go
355 return nil, &InvalidPersistenceRequestError{
356 Msg: "event ID must be continous",
357 }
358 }
359 > lastID++ history_manager.go
360 }
361
362 // nodeID will be the first eventID
363 > blob, err := m.serializer.SerializeEvents(request.Events) history_manager.go
364 > if err != nil {
365 return nil, err
366 }
367 > size := len(blob.Data) history_manager.go
368 > sizeLimit := m.transactionSizeLimit()
369 > if size > sizeLimit {
370 return nil, &TransactionSizeLimitError{
371 Msg: fmt.Sprintf("transaction size of %v bytes exceeds limit of %v bytes", size, sizeLimit),
373 }
374
375 > req := &InternalAppendHistoryNodesRequest{ history_manager.go
376 > BranchToken: request.BranchToken,
377 > IsNewBranch: request.IsNewBranch,
378 > Info: request.Info,
379 > BranchInfo: branch,
380 > Node: InternalHistoryNode{
381 > NodeID: nodeID,
382 > Events: blob,
383 > PrevTransactionID: request.PrevTransactionID,
384 > TransactionID: request.TransactionID,
385 > },
386 > ShardID: request.ShardID,
387 > }
388 >
389 > if req.IsNewBranch {
390 > // TreeInfo is only needed for new branch history_manager.go
391 > treeInfoBlob, err := m.serializer.HistoryTreeInfoToBlob(&persistencespb.HistoryTreeInfo{
392 > BranchToken: request.BranchToken, // NOTE: this is redundant but double-writing until 1 minor release later
393 > BranchInfo: branch,
394 > ForkTime: timestamp.TimeNowPtrUtc(),
395 > Info: request.Info,
396 > })
397 > if err != nil {
398 return nil, err
399 }
400 > req.TreeInfo = treeInfoBlob history_manager.go
401 }
402
403 > if nodeID < GetBeginNodeID(branch) { history_manager.go
404 return nil, &InvalidPersistenceRequestError{
405 Msg: "cannot append to ancestors' nodes",
532 ctx context.Context,
533 request *ReadHistoryBranchRequest,
534 > ) (*ReadHistoryBranchResponse, error) { history_manager.go
535 >
536 > resp := &ReadHistoryBranchResponse{}
537 > var err error
538 > resp.HistoryEvents, _, _, resp.NextPageToken, resp.Size, err = m.readHistoryBranch(ctx, false, request)
539 > return resp, err
540 > }
541
542 // ReadRawHistoryBranch returns raw history binary data for a branch
616 pageSize int,
617 metadataOnly bool,
618 > ) ([]InternalHistoryNode, *historyPagingToken, error) { history_manager.go
619 >
620 > if token.CurrentRangeIndex == notStartedIndex {
621 > for idx, br := range branchAncestors {
622 > // this range won't contain any nodes needed
623 > if minNodeID >= br.GetEndNodeId() {
624 continue
625 }
626 // similarly, the ranges and the rest won't contain any nodes needed,
627 > if maxNodeID <= br.GetBeginNodeId() { history_manager.go
628 break
629 }
630
631 > if token.CurrentRangeIndex == notStartedIndex { history_manager.go
632 > token.CurrentRangeIndex = idx
633 > }
634 > token.FinalRangeIndex = idx
635 }
636
637 > if token.CurrentRangeIndex == notStartedIndex { history_manager.go
638 return nil, nil, softassert.UnexpectedDataLoss(m.logger, "branchRange is corrupted", nil)
639 }
640 }
641
642 > currentBranch := branchAncestors[token.CurrentRangeIndex] history_manager.go
643 > // minNodeID remains the same, since caller can read from the middle
644 > // maxNodeID need to be shortened since this branch can contain additional history nodes
645 > if currentBranch.GetEndNodeId() < maxNodeID {
646 maxNodeID = currentBranch.GetEndNodeId()
647 }
648 > branchID := currentBranch.GetBranchId() history_manager.go
649 > resp, err := m.persistence.ReadHistoryBranch(ctx, &InternalReadHistoryBranchRequest{
650 > BranchToken: branchToken,
651 > ShardID: shardID,
652 > BranchID: branchID,
653 > MinNodeID: minNodeID,
654 > MaxNodeID: maxNodeID,
655 > NextPageToken: token.StoreToken,
656 > PageSize: pageSize,
657 > MetadataOnly: metadataOnly,
658 > })
659 > if err != nil {
660 return nil, nil, err
661 }
662 > token.StoreToken = resp.NextPageToken history_manager.go
663 > return resp.Nodes, token, nil
664 }
665
728 ctx context.Context,
729 request *ReadHistoryBranchRequest,
730 > ) ([]*commonpb.DataBlob, []int64, []int64, *historyPagingToken, int, error) { history_manager.go
731 >
732 > shardID := request.ShardID
733 > branchToken := request.BranchToken
734 > minNodeID := request.MinEventID
735 > maxNodeID := request.MaxEventID
736 >
737 > branch, err := m.GetHistoryBranchUtil().ParseHistoryBranchInfo(branchToken)
738 > if err != nil {
739 return nil, nil, nil, nil, 0, serviceerror.NewInvalidArgument(fmt.Sprintf("unable to parse branch token: %v", err))
740 }
741 > branchID := branch.BranchId history_manager.go
742 > branchAncestors := branch.Ancestors
743 >
744 > // merge tree ID & branch ID into branch ancestors so the processing logic is simple
745 > beginNodeID := common.FirstEventID
746 > if len(branch.Ancestors) > 0 {
747 beginNodeID = branch.Ancestors[len(branch.Ancestors)-1].GetEndNodeId()
748 }
749 > branchAncestors = append(branchAncestors, &persistencespb.HistoryBranchRange{ history_manager.go
750 > BranchId: branchID,
751 > BeginNodeId: beginNodeID,
752 > EndNodeId: maxNodeID,
753 > })
754 >
755 > token, err := m.deserializeToken(
756 > request.NextPageToken,
757 > request.MinEventID-1,
758 > defaultLastTransactionID,
759 > )
760 > if err != nil {
761 return nil, nil, nil, nil, 0, err
762 }
763
764 > nodes, token, err := m.readRawHistoryBranch( history_manager.go
765 > ctx,
766 > branchToken,
767 > shardID,
768 > branchAncestors,
769 > minNodeID,
770 > maxNodeID,
771 > token,
772 > request.PageSize,
773 > false,
774 > )
775 > if err != nil {
776 return nil, nil, nil, nil, 0, err
777 }
778 > if len(nodes) == 0 && len(request.NextPageToken) == 0 { history_manager.go
779 return nil, nil, nil, nil, 0, serviceerror.NewNotFound("Workflow execution history not found.")
780 }
781
782 > nodes, err = m.filterHistoryNodes( history_manager.go
783 > token.LastNodeID,
784 > token.LastTransactionID,
785 > nodes,
786 > )
787 > if err != nil {
788 return nil, nil, nil, nil, 0, err
789 }
790
791 > var dataBlobs []*commonpb.DataBlob history_manager.go
792 > transactionIDs := make([]int64, 0, len(nodes))
793 > nodeIDs := make([]int64, 0, len(nodes))
794 > dataSize := 0
795 > if len(nodes) > 0 {
796 > dataBlobs = make([]*commonpb.DataBlob, len(nodes))
797 > for index, node := range nodes {
798 > dataBlobs[index] = node.Events
799 > if node.Events == nil {
800 return nil, nil, nil, nil, 0, softassert.UnexpectedDataLoss(m.logger, "no events in history node", nil)
801 }
802 > dataSize += len(node.Events.Data) history_manager.go
803 > transactionIDs = append(transactionIDs, node.TransactionID)
804 > nodeIDs = append(nodeIDs, node.NodeID)
805 }
806 > lastNode := nodes[len(nodes)-1] history_manager.go
807 > token.LastNodeID = lastNode.NodeID
808 > token.LastTransactionID = lastNode.TransactionID
809 }
810 > return dataBlobs, transactionIDs, nodeIDs, token, dataSize, nil history_manager.go
811 }
812
904 byBatch bool,
905 request *ReadHistoryBranchRequest,
906 > ) ([]*historypb.HistoryEvent, []*historypb.History, []int64, []byte, int, error) { history_manager.go
907 >
908 > dataBlobs, transactionIDs, _, token, dataSize, err := m.readRawHistoryBranchAndFilter(ctx, request)
909 > if err != nil {
910 return nil, nil, nil, nil, 0, err
911 }
912
913 > historyEvents := make([]*historypb.HistoryEvent, 0, request.PageSize) history_manager.go
914 > historyEventBatches := make([]*historypb.History, 0, request.PageSize)
915 >
916 > var firstEvent, lastEvent *historypb.HistoryEvent
917 > var eventCount int
918 >
919 > dataLossTags := func(cause error) []tag.Tag {
920 return []tag.Tag{
921 tag.Cause(cause.Error()),
931 }
932
933 > for _, batch := range dataBlobs { history_manager.go
934 > events, err := m.serializer.DeserializeEvents(batch)
935 > if err != nil {
936 return nil, nil, nil, nil, dataSize, err
937 }
938 > if len(events) == 0 { history_manager.go
939 return nil, nil, nil, nil, dataSize, softassert.UnexpectedDataLoss(m.logger, dataLossMsg, errEmptyEvents, dataLossTags(errEmptyEvents)...)
940 }
941
942 > firstEvent = events[0] history_manager.go
943 > eventCount = len(events)
944 > lastEvent = events[eventCount-1]
945 >
946 > if firstEvent.GetVersion() != lastEvent.GetVersion() || firstEvent.GetEventId()+int64(eventCount-1) != lastEvent.GetEventId() {
947 // in a single batch, version should be the same, and ID should be contiguous
948 return historyEvents, historyEventBatches, transactionIDs, nil, dataSize, softassert.UnexpectedDataLoss(m.logger, dataLossMsg, errWrongVersion, dataLossTags(errWrongVersion)...)
949 }
950 > if firstEvent.GetEventId() != token.LastEventID+1 { history_manager.go
951 return historyEvents, historyEventBatches, transactionIDs, nil, dataSize, softassert.UnexpectedDataLoss(m.logger, dataLossMsg, errNonContiguousEventID, dataLossTags(errNonContiguousEventID)...)
952 }
953
954 > if byBatch { history_manager.go
955 historyEventBatches = append(historyEventBatches, &historypb.History{Events: events})
956 > } else { history_manager.go
957 > historyEvents = append(historyEvents, events...)
958 > }
959 > token.LastEventID = lastEvent.GetEventId()
960 }
961
962 > nextPageToken, err := m.serializeToken(token, false) history_manager.go
963 > if err != nil {
964 return nil, nil, nil, nil, 0, err
965 }
966 > return historyEvents, historyEventBatches, transactionIDs, nextPageToken, dataSize, nil history_manager.go
967 }
968
1040 lastTransactionID int64,
1041 nodes []InternalHistoryNode,
1042 > ) ([]InternalHistoryNode, error) { history_manager.go
1043 > var result []InternalHistoryNode
1044 > for _, node := range nodes {
1045 > // assuming that business logic layer is correct and transaction ID only increase
1046 > // thus, valid event batch will come with increasing transaction ID
1047 >
1048 > // event batches with smaller node ID
1049 > // -> should not be possible since records are already sorted
1050 > // event batches with same node ID
1051 > // -> batch with higher transaction ID is valid
1052 > // event batches with larger node ID
1053 > // -> batch with lower transaction ID is invalid (happens before)
1054 > // -> batch with higher transaction ID is valid
1055 > if node.TransactionID < lastTransactionID {
1056 continue
1057 }
1058
1059 > switch { history_manager.go
1060 case node.NodeID < lastNodeID:
1061 return nil, softassert.UnexpectedDataLoss(m.logger, "corrupted data, nodeID cannot decrease", nil)
1062 case node.NodeID == lastNodeID:
1063 return nil, softassert.UnexpectedDataLoss(m.logger, "corrupted data, same nodeID must have smaller txnID", nil)
1064 > default: // row.NodeID > lastNodeID: history_manager.go
1065 > // NOTE: when row.nodeID > lastNodeID, we expect the one with largest txnID comes first
1066 > lastTransactionID = node.TransactionID
1067 > lastNodeID = node.NodeID
1068 > result = append(result, node)
1069 }
1070 }
1071 > return result, nil history_manager.go
1072 }
1073
1106 defaultLastEventID int64,
1107 lastTransactionId int64,
1108 > ) (*historyPagingToken, error) { history_manager.go
1109 >
1110 > return m.pagingTokenSerializer.Deserialize(
1111 > token,
1112 > defaultLastEventID,
1113 > defaultLastNodeID,
1114 > lastTransactionId,
1115 > )
1116 > }
1117
1118 func (m *executionManagerImpl) serializeToken(
1119 pagingToken *historyPagingToken,
1120 reverseOrder bool,
1121 > ) ([]byte, error) { history_manager.go
1122 >
1123 > if len(pagingToken.StoreToken) == 0 {
1124 > if pagingToken.CurrentRangeIndex == pagingToken.FinalRangeIndex {
1125 > // this means that we have reached the final page of final branchRange
1126 > return nil, nil
1127 > }
1128
1129 if reverseOrder {
go.temporal.io/server/service/history/history_engine.go 211 covered LOC · 22 ranges

Open complete file

182 testHooks testhooks.TestHooks,
183 chasmEngine chasm.Engine,
184 > ) historyi.Engine { history_engine.go
185 > currentClusterName := shard.GetClusterMetadata().GetCurrentClusterName()
186 >
187 > logger := shard.GetLogger()
188 > executionManager := shard.GetExecutionManager()
189 >
190 > workflowDeleteManager := deletemanager.NewDeleteManager(
191 > shard,
192 > workflowCache,
193 > config,
194 > shard.GetTimeSource(),
195 > persistenceVisibilityMgr,
196 > )
197 > syncStateRetriever := replication.NewSyncStateRetriever(
198 > shard,
199 > workflowCache,
200 > workflowConsistencyChecker,
201 > eventBlobCache,
202 > shard.GetLogger(),
203 > )
204 >
205 > historyEngImpl := &historyEngineImpl{
206 > status: common.DaemonStatusInitialized,
207 > currentClusterName: currentClusterName,
208 > shardContext: shard,
209 > clusterMetadata: shard.GetClusterMetadata(),
210 > timeSource: shard.GetTimeSource(),
211 > executionManager: executionManager,
212 > tokenSerializer: tasktoken.NewSerializer(),
213 > logger: log.With(logger, tag.ComponentHistoryEngine),
214 > throttledLogger: log.With(shard.GetThrottledLogger(), tag.ComponentHistoryEngine),
215 > metricsHandler: shard.GetMetricsHandler(),
216 > eventNotifier: eventNotifier,
217 > config: config,
218 > sdkClientFactory: sdkClientFactory,
219 > matchingClient: matchingClient,
220 > rawMatchingClient: rawMatchingClient,
221 > persistenceVisibilityMgr: persistenceVisibilityMgr,
222 > workflowDeleteManager: workflowDeleteManager,
223 > serializer: serializer,
224 > workflowConsistencyChecker: workflowConsistencyChecker,
225 > versionChecker: headers.NewDefaultVersionChecker(),
226 > tracer: tracerProvider.Tracer(consts.LibraryName),
227 > taskCategoryRegistry: taskCategoryRegistry,
228 > commandHandlerRegistry: commandHandlerRegistry,
229 > chasmWorkflowRegistry: chasmWorkflowRegistry,
230 > workflowCache: workflowCache,
231 > replicationProgressCache: replicationProgressCache,
232 > syncStateRetriever: syncStateRetriever,
233 > outboundQueueCBPool: outboundQueueCBPool,
234 > testHooks: testHooks,
235 > chasmEngine: chasmEngine,
236 > versionCache: versionCache,
237 > workerDeploymentClient: workerDeploymentClient,
238 > routingInfoCache: routingInfoCache,
239 > }
240 >
241 > historyEngImpl.queueProcessors = make(map[tasks.Category]queues.Queue)
242 > for _, factory := range queueProcessorFactories {
243 > processor := factory.CreateQueue(shard)
244 > historyEngImpl.queueProcessors[processor.Category()] = processor
245 > }
246
247 > historyEngImpl.eventsReapplier = ndc.NewEventsReapplier(shard.StateMachineRegistry(), shard.ChasmWorkflowRegistry(), shard.GetMetricsHandler(), logger) history_engine.go
248 >
249 > if shard.GetClusterMetadata().IsGlobalNamespaceEnabled() {
250 historyEngImpl.replicationAckMgr = replication.NewAckManager(
251 shard,
289 )
290 }
291 > historyEngImpl.workflowRebuilder = NewWorkflowRebuilder( history_engine.go
292 > shard,
293 > workflowCache,
294 > logger,
295 > )
296 > historyEngImpl.workflowResetter = ndc.NewWorkflowResetter(
297 > shard,
298 > workflowCache,
299 > logger,
300 > )
301 >
302 > historyEngImpl.searchAttributesValidator = searchattribute.NewValidator(
303 > shard.GetSearchAttributesProvider(),
304 > shard.GetSearchAttributesMapperProvider(),
305 > config.SearchAttributesNumberOfKeysLimit,
306 > config.SearchAttributesSizeOfValueLimit,
307 > config.SearchAttributesTotalSizeLimit,
308 > persistenceVisibilityMgr,
309 > visibility.AllowListForValidation(
310 > persistenceVisibilityMgr.GetStoreNames(),
311 > config.VisibilityAllowList,
312 > ),
313 > config.SuppressErrorSetSystemSearchAttribute,
314 > shard.GetMetricsHandler(),
315 > logger,
316 > )
317 >
318 > historyEngImpl.replicationDLQHandler = replication.NewLazyDLQHandler(
319 > shard,
320 > workflowDeleteManager,
321 > workflowCache,
322 > clientBean,
323 > replicationTaskExecutorProvider,
324 > )
325 > historyEngImpl.replicationProcessorMgr = replication.NewTaskProcessorManager(
326 > config,
327 > shard,
328 > historyEngImpl,
329 > workflowCache,
330 > workflowDeleteManager,
331 > clientBean,
332 > serializer,
333 > replicationTaskFetcherFactory,
334 > replicationTaskExecutorProvider,
335 > testHooks,
336 > dlqWriter,
337 > )
338 >
339 > return historyEngImpl
340 }
341
343 // Make sure all the components are loaded lazily so start can return immediately. This is important because
344 // ShardController calls start sequentially for all the shards for a given host during startup.
345 > func (e *historyEngineImpl) Start() { history_engine.go
346 > if !atomic.CompareAndSwapInt32(
347 > &e.status,
348 > common.DaemonStatusInitialized,
349 > common.DaemonStatusStarted,
350 > ) {
351 return
352 }
353
354 > e.logger.Info("", tag.LifeCycleStarting) history_engine.go
355 > defer e.logger.Info("", tag.LifeCycleStarted)
356 >
357 > e.registerNamespaceStateChangeCallback()
358 >
359 > for _, queueProcessor := range e.queueProcessors {
360 > queueProcessor.Start()
361 > }
362 > e.replicationProcessorMgr.Start()
363 }
364
365 // Stop the service.
366 > func (e *historyEngineImpl) Stop() { history_engine.go
367 > if !atomic.CompareAndSwapInt32(
368 > &e.status,
369 > common.DaemonStatusStarted,
370 > common.DaemonStatusStopped,
371 > ) {
372 return
373 }
374
375 > e.logger.Info("", tag.LifeCycleStopping) history_engine.go
376 > defer e.logger.Info("", tag.LifeCycleStopped)
377 >
378 > for _, queueProcessor := range e.queueProcessors {
379 > queueProcessor.Stop()
380 > }
381 > e.replicationProcessorMgr.Stop()
382 > // unset the failover callback
383 > e.shardContext.GetNamespaceRegistry().UnregisterStateChangeCallback(e)
384 }
385
386 > func (e *historyEngineImpl) registerNamespaceStateChangeCallback() { history_engine.go
387 >
388 > e.shardContext.GetNamespaceRegistry().RegisterStateChangeCallback(e, func(ns *namespace.Namespace, deletedFromDb bool) {
389 > if e.shardContext.GetClusterMetadata().IsGlobalNamespaceEnabled() {
390 e.shardContext.UpdateHandoverNamespace(ns, deletedFromDb)
391 }
392
393 > if deletedFromDb { history_engine.go
394 return
395 }
396
397 > if ns.IsGlobalNamespace() && history_engine.go
398 > ns.ReplicationPolicy() == namespace.ReplicationPolicyMultiCluster &&
399 > //nolint:forbidigo // namespace state-change callback; FailoverNamespace operates per-namespace, no workflow context
400 > ns.ActiveInCluster(e.currentClusterName) {
401
402 for _, queueProcessor := range e.queueProcessors {
412 ctx context.Context,
413 startRequest *historyservice.StartWorkflowExecutionRequest,
414 > ) (*historyservice.StartWorkflowExecutionResponse, error) { history_engine.go
415 > starter, err := startworkflow.NewStarter(
416 > e.shardContext,
417 > e.workflowConsistencyChecker,
418 > e.tokenSerializer,
419 > startRequest,
420 > e.matchingClient,
421 > e.versionCache,
422 > e.workerDeploymentClient.SignalVersionReactivation,
423 > api.NewWorkflowLeaseAndContext,
424 > )
425 > if err != nil {
426 return nil, err
427 }
428
429 > resp, _, err := starter.Invoke(ctx) history_engine.go
430 > return resp, err
431 }
432
563 ctx context.Context,
564 request *historyservice.RecordWorkflowTaskStartedRequest,
565 > ) (*historyservice.RecordWorkflowTaskStartedResponseWithRawHistory, error) { history_engine.go
566 > return recordworkflowtaskstarted.Invoke(
567 > ctx,
568 > request,
569 > e.shardContext,
570 > e.config,
571 > e.eventNotifier,
572 > e.persistenceVisibilityMgr,
573 > e.workflowConsistencyChecker,
574 > )
575 > }
576
577 // RespondWorkflowTaskCompleted completes a workflow task
579 ctx context.Context,
580 req *historyservice.RespondWorkflowTaskCompletedRequest,
581 > ) (*historyservice.RespondWorkflowTaskCompletedResponse, error) { history_engine.go
582 > h := respondworkflowtaskcompleted.NewWorkflowTaskCompletedHandler(
583 > e.shardContext,
584 > e.tokenSerializer,
585 > e.eventNotifier,
586 > e.commandHandlerRegistry,
587 > e.chasmWorkflowRegistry,
588 > e.searchAttributesValidator,
589 > e.persistenceVisibilityMgr,
590 > e.workflowConsistencyChecker,
591 > e.matchingClient,
592 > e.versionCache,
593 > )
594 > return h.Invoke(ctx, req)
595 > }
596
597 // RespondWorkflowTaskFailed fails a workflow task
874 func (e *historyEngineImpl) NotifyNewHistoryEvent(
875 notification *events.Notification,
876 > ) { history_engine.go
877 >
878 > e.eventNotifier.NotifyNewHistoryEvent(notification)
879 > }
880
881 func (e *historyEngineImpl) NotifyChasmExecution(executionKey chasm.ExecutionKey, componentRef []byte) {
887 func (e *historyEngineImpl) NotifyNewTasks(
888 newTasks map[tasks.Category][]tasks.Task,
889 > ) { history_engine.go
890 > for category, tasksByCategory := range newTasks {
891 > // TODO: make replicatorProcessor part of queueProcessors list history_engine.go
892 > // and get rid of the special case here.
893 > if category == tasks.CategoryReplication {
894 > if e.replicationAckMgr != nil { history_engine.go
895 e.replicationAckMgr.NotifyNewTasks(tasksByCategory)
896 }
897 > continue history_engine.go
898 }
899
900 > if len(tasksByCategory) > 0 { history_engine.go
901 > proc, ok := e.queueProcessors[category]
902 > if !ok {
903 // On shard reload it sends fake tasks to wake up the queue processors. Only log if there are "real"
904 // tasks that can't be processed.
908 continue
909 }
910 > proc.NotifyNewTasks(tasksByCategory) history_engine.go
911 }
912 }
1039 ctx context.Context,
1040 request *historyservice.GetWorkflowExecutionHistoryRequest,
1041 > ) (_ *historyservice.GetWorkflowExecutionHistoryResponseWithRaw, retError error) { history_engine.go
1042 > return getworkflowexecutionhistory.Invoke(ctx, e.shardContext, e.workflowConsistencyChecker, e.versionChecker, e.eventNotifier, request, e.persistenceVisibilityMgr)
1043 > }
1044
1045 func (e *historyEngineImpl) GetWorkflowExecutionHistoryReverse(
go.temporal.io/server/service/history/workflow/task_generator.go 206 covered LOC · 38 ranges

Open complete file

115 archivalMetadata archiver.ArchivalMetadata,
116 logger log.Logger,
117 > ) *TaskGeneratorImpl { task_generator.go
118 > return &TaskGeneratorImpl{
119 > namespaceRegistry: namespaceRegistry,
120 > mutableState: mutableState,
121 > config: config,
122 > archivalMetadata: archivalMetadata,
123 > logger: logger,
124 > }
125 > }
126
127 func (r *TaskGeneratorImpl) GenerateWorkflowStartTasks(
128 startEvent *historypb.HistoryEvent,
129 > ) (int32, error) { task_generator.go
130 >
131 > executionInfo := r.mutableState.GetExecutionInfo()
132 > executionTimeoutTimerTaskStatus := executionInfo.WorkflowExecutionTimerTaskStatus
133 > if !r.mutableState.IsWorkflowExecutionRunning() {
134 return executionTimeoutTimerTaskStatus, nil
135 }
136
137 > workflowExecutionTimeoutTimerEnabled := r.config.EnableWorkflowExecutionTimeoutTimer() task_generator.go
138 > if !workflowExecutionTimeoutTimerEnabled {
139 // when the feature is disabled, reset this field so that it won't be carried over to the next run
140 // and new runs can always have the run timeout timer always generated.
155 // into the situation where execution timeout is set but no timeout timer task is generated.
156
157 > isFirstRun := executionInfo.FirstExecutionRunId == r.mutableState.GetExecutionState().RunId task_generator.go
158 > workflowExecutionExpirationTime := timestamp.TimeValue(
159 > executionInfo.WorkflowExecutionExpirationTime,
160 > )
161 > if workflowExecutionTimeoutTimerEnabled &&
162 > !isFirstRun &&
163 > !workflowExecutionExpirationTime.IsZero() &&
164 > executionInfo.WorkflowExecutionTimerTaskStatus == TimerTaskStatusNone {
165 r.mutableState.AddTasks(&tasks.WorkflowExecutionTimeoutTask{
166 // TaskID is set by shard
173 }
174
175 > workflowRunExpirationTime := timestamp.TimeValue( task_generator.go
176 > executionInfo.WorkflowRunExpirationTime,
177 > )
178 > if workflowRunExpirationTime.IsZero() {
179 > return executionTimeoutTimerTaskStatus, nil task_generator.go
180 > }
181 if executionTimeoutTimerTaskStatus == TimerTaskStatusNone ||
182 workflowRunExpirationTime.Before(workflowExecutionExpirationTime) {
196 deleteAfterClose bool,
197 skipCloseTransferTask bool,
198 > ) error { task_generator.go
199 > closeVersion, err := r.mutableState.GetCloseVersion()
200 > if err != nil {
201 return err
202 }
203
204 > var closeTasks []tasks.Task task_generator.go
205 >
206 > if !skipCloseTransferTask {
207 > closeExecutionTask := &tasks.CloseExecutionTask{
208 > // TaskID, Visiblitytimestamp is set by shard
209 > WorkflowKey: r.mutableState.GetWorkflowKey(),
210 > Version: closeVersion,
211 > DeleteAfterClose: deleteAfterClose,
212 > }
213 > closeTasks = append(closeTasks, closeExecutionTask)
214 > } else {
215 r.logger.Info("Skipping close transfer task generation - already acked on active cluster",
216 tag.WorkflowNamespaceID(r.mutableState.GetExecutionInfo().GetNamespaceId()),
223 // Also, there is no reason to schedule history retention task if workflow executions in about to be deleted.
224 // This will also save one call to visibility storage and one timer task creation.
225 > if !deleteAfterClose { task_generator.go
226 > // In most cases, the value of "now" is the closeEvent time. task_generator.go
227 > // however this is not true for task refresh, where now is
228 > // the refresh time, not the close time.
229 > // Also can't always use close time as "now" when calling the method
230 > // as it will be used as visibilityTimestamp for immediate task and
231 > // for emitting task_latency_queue/load metric. If close time is used
232 > // as now, upon refresh the latency metric may see a huge value.
233 > // TODO: remove all "now" parameters from task generator interface,
234 > // visibility timestamp for scheduled task should be calculated from event
235 > // or execution info in mutable state. For immediate task, visibility timestamp
236 > // should always be when the task is generated so that task_latency_queue/load
237 > // truly measures only task processing/loading latency.
238 > closeTasks = append(closeTasks,
239 > &tasks.CloseExecutionVisibilityTask{
240 > // TaskID, VisibilityTimestamp is set by shard
241 > WorkflowKey: r.mutableState.GetWorkflowKey(),
242 > Version: closeVersion,
243 > },
244 > )
245 > if r.archivalEnabled() {
246 retention, err := r.getRetention()
247 if err != nil {
262 }
263 closeTasks = append(closeTasks, task)
264 > } else if err := r.GenerateDeleteHistoryEventTask(closedTime); err != nil { task_generator.go
265 return err
266 }
267 }
268
269 > r.mutableState.AddTasks(closeTasks...) task_generator.go
270 >
271 > // Proactively cancel in-flight activities so they don't run uselessly after the workflow is closed.
272 > return r.mutableState.GenerateActivityCancelCommandsForClose()
273 }
274
278 // This method returns an error when the GetNamespaceByID call fails with anything other than
279 // serviceerror.NamespaceNotFound.
280 > func (r *TaskGeneratorImpl) getRetention() (time.Duration, error) { task_generator.go
281 > retention := defaultWorkflowRetention
282 > executionInfo := r.mutableState.GetExecutionInfo()
283 > namespaceEntry, err := r.namespaceRegistry.GetNamespaceByID(namespace.ID(executionInfo.NamespaceId))
284 > switch err.(type) {
285 > case nil: task_generator.go
286 > retention = namespaceEntry.Retention()
287 case *serviceerror.NamespaceNotFound:
288 // namespace is not accessible, use default value above
290 return 0, err
291 }
292 > return retention, nil task_generator.go
293 }
294
295 func (r *TaskGeneratorImpl) GenerateDirtySubStateMachineTasks(
296 stateMachineRegistry *hsm.Registry,
297 > ) error { task_generator.go
298 > tree := r.mutableState.HSM()
299 > opLog, err := tree.OpLog()
300 > if err != nil {
301 return err
302 }
303
304 > for _, op := range opLog { task_generator.go
305 switch transitionOp := op.(type) {
306 case hsm.DeleteOperation:
329 }
330
331 > AddNextStateMachineTimerTask(r.mutableState) task_generator.go
332 >
333 > return nil
334 }
335
337 // This method only adds the task to the mutable state object in memory; it does not write the task to the database.
338 // You must call shard.Context#AddTasks to notify the history engine of this task.
339 > func (r *TaskGeneratorImpl) GenerateDeleteHistoryEventTask(closeTime time.Time) error { task_generator.go
340 > retention, err := r.getRetention()
341 > if err != nil {
342 return err
343 }
344 > closeVersion, err := r.mutableState.GetCloseVersion() task_generator.go
345 > if err != nil {
346 return err
347 }
348
349 > branchToken, err := r.mutableState.GetCurrentBranchToken() task_generator.go
350 > if err != nil {
351 return err
352 }
353
354 > retentionJitterDuration := backoff.FullJitter(r.config.RetentionTimerJitterDuration()) task_generator.go
355 > deleteTime := closeTime.Add(retention).Add(retentionJitterDuration)
356 > r.mutableState.AddTasks(&tasks.DeleteHistoryEventTask{
357 > // TaskID is set by shard
358 > WorkflowKey: r.mutableState.GetWorkflowKey(),
359 > VisibilityTimestamp: deleteTime,
360 > Version: closeVersion,
361 > BranchToken: branchToken,
362 > ArchetypeID: r.mutableState.ChasmTree().ArchetypeID(),
363 > })
364 > return nil
365 }
366
375 func (r *TaskGeneratorImpl) GenerateDelayedWorkflowTasks(
376 startEvent *historypb.HistoryEvent,
377 > ) error { task_generator.go
378 >
379 > startVersion := startEvent.GetVersion()
380 > // start time may not be "now" if method called by refresher
381 > startTime := timestamp.TimeValue(startEvent.GetEventTime())
382 > startAttr := startEvent.GetWorkflowExecutionStartedEventAttributes()
383 >
384 > workflowTaskBackoffDuration := timestamp.DurationValue(startAttr.GetFirstWorkflowTaskBackoff())
385 > executionTimestamp := startTime.Add(workflowTaskBackoffDuration)
386 >
387 > var workflowBackoffType enumsspb.WorkflowBackoffType
388 > switch startAttr.GetInitiator() {
389 case enumspb.CONTINUE_AS_NEW_INITIATOR_RETRY:
390 workflowBackoffType = enumsspb.WORKFLOW_BACKOFF_TYPE_RETRY
391 > case enumspb.CONTINUE_AS_NEW_INITIATOR_CRON_SCHEDULE, enumspb.CONTINUE_AS_NEW_INITIATOR_WORKFLOW: task_generator.go
392 > workflowBackoffType = enumsspb.WORKFLOW_BACKOFF_TYPE_CRON
393 default:
394 workflowBackoffType = enumsspb.WORKFLOW_BACKOFF_TYPE_DELAY_START
395 }
396
397 > r.mutableState.AddTasks(&tasks.WorkflowBackoffTimerTask{ task_generator.go
398 > // TaskID is set by shard
399 > WorkflowKey: r.mutableState.GetWorkflowKey(),
400 > VisibilityTimestamp: executionTimestamp,
401 > WorkflowBackoffType: workflowBackoffType,
402 > Version: startVersion,
403 > })
404 >
405 > return nil
406 }
407
408 func (r *TaskGeneratorImpl) GenerateRecordWorkflowStartedTasks(
409 startEvent *historypb.HistoryEvent,
410 > ) error { task_generator.go
411 >
412 > startVersion := startEvent.GetVersion()
413 >
414 > r.mutableState.AddTasks(&tasks.StartExecutionVisibilityTask{
415 > // TaskID, VisibilityTimestamp is set by shard
416 > WorkflowKey: r.mutableState.GetWorkflowKey(),
417 > Version: startVersion,
418 > })
419 > return nil
420 > }
421
422 func (r *TaskGeneratorImpl) GenerateScheduleWorkflowTaskTasks(
423 workflowTaskScheduledEventID int64,
424 > ) error { task_generator.go
425 > workflowTask := r.mutableState.GetWorkflowTaskByID(workflowTaskScheduledEventID)
426 > if workflowTask == nil {
427 return serviceerror.NewInternalf("it could be a bug, cannot get pending workflow task: %v", workflowTaskScheduledEventID)
428 }
429 > if workflowTask.Type == enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE { task_generator.go
430 return serviceerror.NewInternalf("it could be a bug, GenerateScheduleSpeculativeWorkflowTaskTasks must be called for speculative workflow task: %v", workflowTaskScheduledEventID)
431 }
432
433 > if r.mutableState.IsStickyTaskQueueSet() { task_generator.go
434 scheduleToStartTimeout := timestamp.DurationValue(r.mutableState.GetExecutionInfo().StickyScheduleToStartTimeout)
435 wttt := &tasks.WorkflowTaskTimeoutTask{
447 }
448
449 > r.mutableState.AddTasks(&tasks.WorkflowTask{ task_generator.go
450 > // TaskID, VisibilityTimestamp is set by shard
451 > WorkflowKey: r.mutableState.GetWorkflowKey(),
452 > // Store current task queue to the transfer task.
453 > // If current task queue becomes sticky in between when this transfer task is created and processed,
454 > // it can't be used at process time, because timeout timer was not created for it,
455 > // because it used to be non-sticky when this transfer task was created here.
456 > // In short, task queue that was "current" when transfer task was created must be used when task is processed.
457 > TaskQueue: workflowTask.TaskQueue.GetName(),
458 > ScheduledEventID: workflowTask.ScheduledEventID,
459 > Version: workflowTask.Version,
460 > Stamp: workflowTask.Stamp,
461 > })
462 >
463 > return nil
464 }
465
517 func (r *TaskGeneratorImpl) GenerateStartWorkflowTaskTasks(
518 workflowTaskScheduledEventID int64,
519 > ) error { task_generator.go
520 > workflowTask := r.mutableState.GetWorkflowTaskByID(
521 > workflowTaskScheduledEventID,
522 > )
523 > if workflowTask == nil {
524 return serviceerror.NewInternalf("it could be a bug, cannot get pending workflow task: %v", workflowTaskScheduledEventID)
525 }
526
527 > isSpeculative := workflowTask.Type == enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE task_generator.go
528 > wttt := &tasks.WorkflowTaskTimeoutTask{
529 > // TaskID is set by shard
530 > WorkflowKey: r.mutableState.GetWorkflowKey(),
531 > VisibilityTimestamp: workflowTask.StartedTime.Add(workflowTask.WorkflowTaskTimeout),
532 > TimeoutType: enumspb.TIMEOUT_TYPE_START_TO_CLOSE,
533 > EventID: workflowTask.ScheduledEventID,
534 > ScheduleAttempt: workflowTask.Attempt,
535 > Version: workflowTask.Version,
536 > Stamp: workflowTask.Stamp,
537 > InMemory: isSpeculative,
538 > }
539 >
540 > if isSpeculative {
541 // If WT is speculative, create task in in-memory task queue.
542 return r.mutableState.SetSpeculativeWorkflowTaskTimeoutTask(wttt)
543 }
544 > r.mutableState.AddTasks(wttt) task_generator.go
545 > r.mutableState.SetWorkflowTaskStartToCloseTimeoutTask(wttt)
546 >
547 > return nil
548 }
549
703 }
704
705 > func (r *TaskGeneratorImpl) GenerateUpsertVisibilityTask() error { task_generator.go
706 > r.mutableState.AddTasks(&tasks.UpsertExecutionVisibilityTask{
707 > // TaskID, VisibilityTimestamp is set by shard
708 > WorkflowKey: r.mutableState.GetWorkflowKey(),
709 > })
710 > return nil
711 > }
712
713 func (r *TaskGeneratorImpl) GenerateWorkflowResetTasks() error {
724 }
725
726 > func (r *TaskGeneratorImpl) GenerateActivityTimerTasks() error { task_generator.go
727 > _, err := r.getTimerSequence().CreateNextActivityTimer()
728 > return err
729 > }
730
731 > func (r *TaskGeneratorImpl) GenerateUserTimerTasks() error { task_generator.go
732 > _, err := r.getTimerSequence().CreateNextUserTimer()
733 > return err
734 > }
735
736 func (r *TaskGeneratorImpl) GenerateHistoryReplicationTasks(
893 }
894
895 > func (r *TaskGeneratorImpl) getTimerSequence() TimerSequence { task_generator.go
896 > return NewTimerSequence(r.mutableState)
897 > }
898
899 func (r *TaskGeneratorImpl) getTargetNamespaceID(
920 // archivalEnabled returns true if archival is enabled for either history or visibility.
921 // For both history and visibility, we check that archival is enabled for both the cluster and the namespace.
922 > func (r *TaskGeneratorImpl) archivalEnabled() bool { task_generator.go
923 > namespaceEntry := r.mutableState.GetNamespaceEntry()
924 > return r.archivalMetadata.GetHistoryConfig().ClusterConfiguredForArchival() &&
925 > namespaceEntry.HistoryArchivalState().State == enumspb.ARCHIVAL_STATE_ENABLED ||
926 > r.archivalMetadata.GetVisibilityConfig().ClusterConfiguredForArchival() &&
927 > namespaceEntry.VisibilityArchivalState().State == enumspb.ARCHIVAL_STATE_ENABLED
928 > }
929
930 func generateSubStateMachineTask(
go.temporal.io/server/service/history/queues/reader.go 204 covered LOC · 62 ranges

Open complete file

88
89 var (
90 > NoopReaderCompletionFn = func(_ int64) {} reader.go
91 )
92
103 logger log.Logger,
104 metricsHandler metrics.Handler,
105 > ) *ReaderImpl { reader.go
106 >
107 > sliceList := list.New()
108 > for _, slice := range slices {
109 > sliceList.PushBack(slice) reader.go
110 > }
111 > monitor.SetSliceCount(readerID, len(slices)) reader.go
112 >
113 > rateLimitContext, rateLimitContextCancel := context.WithCancel(context.Background())
114 > return &ReaderImpl{
115 > readerID: readerID,
116 > options: options,
117 > scheduler: scheduler,
118 > rescheduler: rescheduler,
119 > timeSource: timeSource,
120 > ratelimiter: ratelimiter,
121 > monitor: monitor,
122 > completionFn: completionFn,
123 > logger: log.With(logger, tag.QueueReaderID(readerID)),
124 > metricsHandler: metricsHandler,
125 >
126 > status: common.DaemonStatusInitialized,
127 > shutdownCh: make(chan struct{}),
128 >
129 > slices: sliceList,
130 > nextReadSlice: sliceList.Front(),
131 > notifyCh: make(chan struct{}, 1),
132 >
133 > retrier: backoff.NewRetrier(
134 > common.CreateReadTaskRetryPolicy(),
135 > clock.NewRealTimeSource(),
136 > ),
137 >
138 > rateLimitContext: rateLimitContext,
139 > rateLimitContextCancel: rateLimitContextCancel,
140 > rateLimiterRequest: newReaderRequest(readerID),
141 > }
142 }
143
144 > func (r *ReaderImpl) Start() { reader.go
145 > if !atomic.CompareAndSwapInt32(
146 > &r.status,
147 > common.DaemonStatusInitialized,
148 > common.DaemonStatusStarted,
149 > ) {
150 return
151 }
152
153 > r.shutdownWG.Add(1) reader.go
154 > go r.eventLoop()
155 >
156 > r.notify()
157 >
158 > r.logger.Info("queue reader started", tag.LifeCycleStarted)
159 }
160
161 > func (r *ReaderImpl) Stop() { reader.go
162 > if !atomic.CompareAndSwapInt32(
163 > &r.status,
164 > common.DaemonStatusStarted,
165 > common.DaemonStatusStopped,
166 > ) {
167 return
168 }
169
170 > r.monitor.RemoveReader(r.readerID) reader.go
171 >
172 > close(r.shutdownCh)
173 > r.rateLimitContextCancel()
174 > if success := common.AwaitWaitGroup(&r.shutdownWG, time.Minute); !success {
175 r.logger.Warn("queue reader shutdown timed out waiting for event loop", tag.LifeCycleStopTimedout)
176 }
177 > r.logger.Info("queue reader stopped", tag.LifeCycleStopped) reader.go
178 }
179
228 }
229
230 > func (r *ReaderImpl) MergeSlices(incomingSlices ...Slice) { reader.go
231 > if len(incomingSlices) == 0 {
232 return
233 }
234
235 > validateSlicesOrderedDisjoint(incomingSlices) reader.go
236 >
237 > r.Lock()
238 > defer r.Unlock()
239 >
240 > mergedSlices := list.New()
241 >
242 > currentSliceElement := r.slices.Front()
243 > incomingSliceIdx := 0
244 >
245 > for currentSliceElement != nil && incomingSliceIdx < len(incomingSlices) {
246 > currentSlice := currentSliceElement.Value.(Slice) reader.go
247 > incomingSlice := incomingSlices[incomingSliceIdx]
248 >
249 > if currentSlice.Scope().Range.InclusiveMin.CompareTo(incomingSlice.Scope().Range.InclusiveMin) < 0 {
250 > mergeOrAppendSlice(mergedSlices, currentSlice) reader.go
251 > currentSliceElement = currentSliceElement.Next()
252 > } else { reader.go
253 mergeOrAppendSlice(mergedSlices, incomingSlice)
254 incomingSliceIdx++
256 }
257
258 > for ; currentSliceElement != nil; currentSliceElement = currentSliceElement.Next() { reader.go
259 mergeOrAppendSlice(mergedSlices, currentSliceElement.Value.(Slice))
260 }
261 > for _, slice := range incomingSlices[incomingSliceIdx:] { reader.go
262 > mergeOrAppendSlice(mergedSlices, slice)
263 > }
264
265 // clear existing list
266 > r.slices.Init() reader.go
267 > r.slices = mergedSlices
268 >
269 > r.resetNextReadSliceLocked()
270 > r.monitor.SetSliceCount(r.readerID, r.slices.Len())
271 }
272
273 > func (r *ReaderImpl) AppendSlices(incomingSlices ...Slice) { reader.go
274 > if len(incomingSlices) == 0 {
275 return
276 }
277
278 > validateSlicesOrderedDisjoint(incomingSlices) reader.go
279 > if back := r.slices.Back(); back != nil {
280 > lastSliceRange := back.Value.(Slice).Scope().Range
281 > firstIncomingRange := incomingSlices[0].Scope().Range
282 > if lastSliceRange.ExclusiveMax.CompareTo(firstIncomingRange.InclusiveMin) > 0 {
283 panic(fmt.Sprintf(
284 "Can not append slice to existing list of slices, incoming slice range: %v, existing slice range: %v ",
289 }
290
291 > r.Lock() reader.go
292 > defer r.Unlock()
293 >
294 > for _, incomingSlice := range incomingSlices {
295 > if scope := incomingSlice.Scope(); scope.IsEmpty() {
296 > continue reader.go
297 }
298 > r.slices.PushBack(incomingSlice) reader.go
299 }
300
301 > r.resetNextReadSliceLocked() reader.go
302 > r.monitor.SetSliceCount(r.readerID, r.slices.Len())
303 }
304
388 }
389
390 > func (r *ReaderImpl) pauseLocked(duration time.Duration) { reader.go
391 > if r.throttleTimer != nil {
392 r.throttleTimer.Stop()
393 }
394
395 > r.throttleTimer = time.AfterFunc(duration, func() { reader.go
396 > r.Lock() reader.go
397 > defer r.Unlock()
398 >
399 > r.throttleTimer = nil
400 > r.notify()
401 > })
402 }
403
404 > func (r *ReaderImpl) eventLoop() { reader.go
405 > defer func() {
406 > r.shutdownWG.Done() reader.go
407 > }()
408
409 > for { reader.go
410 > // prioritize shutdown
411 > select {
412 case <-r.shutdownCh:
413 return
414 > default: reader.go
415 }
416
417 > select { reader.go
418 > case <-r.shutdownCh: reader.go
419 > return
420 > case <-r.notifyCh: reader.go
421 > r.loadAndSubmitTasks()
422 }
423 }
424 }
425
426 > func (r *ReaderImpl) loadAndSubmitTasks() { reader.go
427 > if err := r.ratelimiter.Wait(r.rateLimitContext, r.rateLimiterRequest); err != nil {
428 if r.rateLimitContext.Err() != nil {
429 return
435 }
436
437 > r.Lock() reader.go
438 > defer r.Unlock()
439 >
440 > if !r.verifyPendingTaskSize() {
441 r.pauseLocked(r.options.PollBackoffInterval())
442 }
443
444 > if r.throttleTimer != nil { reader.go
445 > return reader.go
446 > }
447
448 > if r.nextReadSlice == nil { reader.go
449 r.completionFn(r.readerID)
450 return
451 }
452
453 > loadSlice := r.nextReadSlice.Value.(Slice) reader.go
454 > tasks, err := loadSlice.SelectTasks(r.readerID, r.options.BatchSize())
455 > if err != nil {
456 > r.logger.Error("Queue reader unable to retrieve tasks", tag.Error(err)) reader.go
457 > if common.IsResourceExhausted(err) {
458 r.pauseLocked(throttleRetryDelay)
459 > } else { reader.go
460 > r.pauseLocked(r.retrier.NextBackOff(err))
461 > }
462 > return
463 }
464 > r.retrier.Reset() reader.go
465 >
466 > if len(tasks) != 0 {
467 > for _, task := range tasks { reader.go
468 > r.submit(task)
469 > }
470 > r.monitor.SetReaderWatermark(r.readerID, tasks[len(tasks)-1].GetKey())
471 }
472
473 > if loadSlice.MoreTasks() { reader.go
474 r.notify()
475 return
476 }
477
478 > if r.nextReadSlice = r.nextReadSlice.Next(); r.nextReadSlice != nil { reader.go
479 > r.notify() reader.go
480 > return
481 > }
482
483 // No more tasks to load, trigger completion callback.
484 > r.completionFn(r.readerID) reader.go
485 }
486
487 > func (r *ReaderImpl) resetNextReadSliceLocked() { reader.go
488 > r.nextReadSlice = nil
489 > for element := r.slices.Front(); element != nil; element = element.Next() {
490 > if element.Value.(Slice).MoreTasks() {
491 > r.nextReadSlice = element reader.go
492 > break
493 }
494 }
495
496 > if r.nextReadSlice != nil { reader.go
497 > r.notify() reader.go
498 > return
499 > }
500
501 // No more tasks to load, trigger completion callback.
503 }
504
505 > func (r *ReaderImpl) notify() { reader.go
506 > select {
507 > case r.notifyCh <- struct{}{}:
508 > default: reader.go
509 }
510 }
512 func (r *ReaderImpl) submit(
513 executable Executable,
514 > ) { reader.go
515 > now := r.timeSource.Now()
516 > // Persistence layer may lose precision when persisting the task, which essentially moves
517 > // task fire time backward. Need to account for that when submitting the task.
518 > fireTime := executable.GetKey().FireTime.Add(common.ScheduledTaskMinPrecision)
519 > if now.Before(fireTime) {
520 r.rescheduler.Add(executable, fireTime)
521 return
522 }
523
524 > executable.SetScheduledTime(now) reader.go
525 > if !r.scheduler.TrySubmit(executable) {
526 executable.Reschedule()
527 }
528 }
529
530 > func (r *ReaderImpl) verifyPendingTaskSize() bool { reader.go
531 > return r.monitor.GetTotalPendingTaskCount() < r.options.MaxPendingTasksCount()
532 > }
533
534 func mergeOrAppendSlice(
535 slices *list.List,
536 incomingSlice Slice,
537 > ) { reader.go
538 > if scope := incomingSlice.Scope(); scope.IsEmpty() {
539 return
540 }
541
542 > if slices.Len() == 0 { reader.go
543 > slices.PushBack(incomingSlice)
544 > return
545 > }
546
547 > lastElement := slices.Back() reader.go
548 > lastSlice := lastElement.Value.(Slice)
549 > if !lastSlice.CanMergeWithSlice(incomingSlice) {
550 slices.PushBack(incomingSlice)
551 return
552 }
553
554 > mergedSlices := lastSlice.MergeWithSlice(incomingSlice) reader.go
555 > slices.Remove(lastElement)
556 > for _, mergedSlice := range mergedSlices {
557 > slices.PushBack(mergedSlice)
558 > }
559 }
560
561 func validateSlicesOrderedDisjoint(
562 slices []Slice,
563 > ) { reader.go
564 > if len(slices) <= 1 {
565 > return reader.go
566 > }
567
568 for idx, slice := range slices[:len(slices)-1] {
go.temporal.io/server/service/matching/pri_task_reader.go 204 covered LOC · 45 ranges

Open complete file

68 subqueue subqueueIndex,
69 initialAckLevel int64,
70 > ) *priTaskReader { pri_task_reader.go
71 > return &priTaskReader{
72 > backlogMgr: backlogMgr,
73 > subqueue: subqueue,
74 > notifyC: make(chan struct{}, 1),
75 > logger: backlogMgr.logger,
76 > retrier: backoff.NewRetrier(
77 > common.CreateReadTaskRetryPolicy(),
78 > clock.NewRealTimeSource(),
79 > ),
80 > backlogAge: newBacklogAgeTracker(),
81 > addRetries: semaphore.NewWeighted(concurrentAddRetries),
82 >
83 > // ack manager
84 > outstandingTasks: treemap.NewWith(godsutils.Int64Comparator),
85 > readLevel: initialAckLevel,
86 > ackLevel: initialAckLevel,
87 >
88 > // gc state
89 > lastGCTime: time.Now(),
90 > }
91 > }
92
93 // Start priTaskReader background goroutines.
94 > func (tr *priTaskReader) Start() { pri_task_reader.go
95 > go tr.getTasksPump()
96 > }
97
98 > func (tr *priTaskReader) SignalTaskLoading() { pri_task_reader.go
99 > select {
100 > case tr.notifyC <- struct{}{}:
101 default: // channel already has an event, don't block
102 }
103 }
104
105 > func (tr *priTaskReader) getOldestBacklogTime() time.Time { pri_task_reader.go
106 > tr.lock.Lock()
107 > defer tr.lock.Unlock()
108 > return tr.backlogAge.oldestTime()
109 > }
110
111 > func (tr *priTaskReader) completeTask(task *internalTask, res taskResponse) { pri_task_reader.go
112 > recordDroppedTask(tr.backlogMgr.metricsHandler, res.dropReason)
113 >
114 > err := res.err()
115 >
116 > // We can handle some transient errors by just putting the task back in the matcher to
117 > // match again. Note that for forwarded tasks, it's expected to get DeadlineExceeded when
118 > // the task doesn't match on the root after backlogTaskForwardTimeout, and also expected to
119 > // get errRemoteSyncMatchFailed, which is a serviceerror.Canceled error.
120 > if err != nil && (common.IsServiceClientTransientError(err) ||
121 > common.IsContextDeadlineExceededErr(err) ||
122 > common.IsContextCanceledErr(err)) {
123 > // TODO(pri): if this was a start error (not a forwarding error): consider adding a pri_task_reader.go
124 > // per-task backoff here, in case the error was workflow busy, we don't want to end up
125 > // trying the same task immediately. maybe also: after a few attempts on the same task,
126 > // let it get cycled to the end of the queue, in case there's some task/wf-specific
127 > // thing.
128 > tr.addTaskToMatcher(task)
129 > return
130 > }
131
132 // On other errors: ask backlog manager to re-spool to persistence
133 > if err != nil { pri_task_reader.go
134 if tr.backlogMgr.respoolTaskAfterError(task.event.Data) != nil {
135 return // task queue will unload now
137 }
138
139 > tr.lock.Lock() pri_task_reader.go
140 > defer tr.lock.Unlock()
141 >
142 > tr.backlogAge.record(task.event.Data.CreateTime, -1)
143 >
144 > numAcked := tr.ackTaskLocked(task.event.TaskId)
145 >
146 > tr.maybeGCLocked()
147 >
148 > // use == so we just signal once when we cross this threshold
149 > // TODO(pri): is this safe? maybe we need to improve this
150 > if tr.loadedTasks == tr.backlogMgr.config.GetTasksReloadAt() {
151 tr.SignalTaskLoading()
152 }
153
154 > tr.backlogMgr.db.updateAckLevelAndBacklogStats(tr.subqueue, tr.ackLevel, -numAcked, tr.backlogAge.oldestTime()) pri_task_reader.go
155 }
156
157 // nolint:revive // can simplify later
158 > func (tr *priTaskReader) getTasksPump() { pri_task_reader.go
159 > ctx := tr.backlogMgr.tqCtx
160 >
161 > tr.SignalTaskLoading() // prime pump
162 > for {
163 > select {
164 > case <-ctx.Done(): pri_task_reader.go
165 > return
166 > case <-tr.notifyC: pri_task_reader.go
167 }
168
169 > if tr.getLoadedTasks() > tr.backlogMgr.config.GetTasksReloadAt() { pri_task_reader.go
170 // Too many loaded already, ignore this signal. We'll get another signal when
171 // loadedTasks drops low enough.
173 }
174
175 > batch, err := tr.getTaskBatch(ctx) pri_task_reader.go
176 > tr.backlogMgr.signalIfFatal(err)
177 > if err != nil {
178 // TODO: Should we ever stop retrying on db errors?
179 if common.IsResourceExhausted(err) {
184 continue
185 }
186 > tr.retrier.Reset() pri_task_reader.go
187 >
188 > if len(batch.tasks) == 0 {
189 > tr.setReadLevelAfterGap(batch.readLevel) pri_task_reader.go
190 > if !batch.isReadBatchDone {
191 tr.SignalTaskLoading()
192 }
193 > continue pri_task_reader.go
194 }
195
210 // Also return a number that can be used to update readLevel
211 // Also return a bool to indicate whether read is finished
212 > func (tr *priTaskReader) getTaskBatch(ctx context.Context) (getTasksBatchResponse, error) { pri_task_reader.go
213 > tr.lock.Lock()
214 > readLevel := tr.readLevel
215 > tr.lock.Unlock()
216 >
217 > maxReadLevel := tr.backlogMgr.db.GetMaxReadLevel(tr.subqueue)
218 >
219 > // counter i is used to break and let caller check whether taskqueue is still alive and needs to resume read.
220 > for i := 0; i < 10 && readLevel < maxReadLevel; i++ {
221 upper := min(readLevel+tr.backlogMgr.config.RangeSize, maxReadLevel)
222 response, err := tr.backlogMgr.db.GetTasks(
236 readLevel = upper
237 }
238 > return getTasksBatchResponse{ pri_task_reader.go
239 > tasks: nil,
240 > readLevel: readLevel,
241 > isReadBatchDone: readLevel == maxReadLevel,
242 > }, nil // caller will update readLevel when no task grabbed
243 }
244
272 // lock and call addNewTasks. We call addTaskToMatcher outside tr.lock since it may take other
273 // locks to redirect the task.
274 > func (tr *priTaskReader) recordNewTasksLocked(tasks []*persistencespb.AllocatedTaskInfo) { pri_task_reader.go
275 > // After we get to this point, we must eventually call task.finish or
276 > // task.finishForwarded, which will call tr.completeTask.
277 > for _, t := range tasks {
278 > tr.outstandingTasks.Put(t.TaskId, false)
279 > tr.loadedTasks++
280 > tr.backlogAge.record(t.Data.CreateTime, 1)
281 > }
282 }
283
285 // lock and call addNewTasks. We call addTaskToMatcher outside tr.lock since it may take other
286 // locks to redirect the task.
287 > func (tr *priTaskReader) addNewTasks(tasks []*persistencespb.AllocatedTaskInfo) { pri_task_reader.go
288 > for _, t := range tasks {
289 > task := newInternalTaskFromBacklog(t, tr.completeTask)
290 > tr.backlogMgr.setPriority(task)
291 > tr.addTaskToMatcher(task)
292 > }
293 }
294
295 > func (tr *priTaskReader) addTaskToMatcher(task *internalTask) { pri_task_reader.go
296 > task.resetMatcherState()
297 > err := tr.backlogMgr.addSpooledTask(task)
298 > if err == nil {
299 > return
300 > }
301
302 if drop, retry := tr.addErrorBehavior(err); drop {
367 }
368
369 > func (tr *priTaskReader) signalNewTasks(resp subqueueCreateTasksResponse) { pri_task_reader.go
370 > tr.lock.Lock()
371 >
372 > // We have to be very careful not to increment the read level past an ID that will somehow
373 > // end up in the database, otherwise we might lose a task. We do this by verifying that our
374 > // read level was equal to the previous max read level (i.e. we were at the end of the
375 > // queue), and then we set it to the max read level as of CreateTasks.
376 > // We also check that there's room in memory.
377 > canAddDirect := tr.readLevel == resp.maxReadLevelBefore &&
378 > (tr.loadedTasks+len(resp.tasks)) <= tr.backlogMgr.config.GetTasksBatchSize() &&
379 > !slices.ContainsFunc(resp.tasks, func(t *persistencespb.AllocatedTaskInfo) bool {
380 > // Because we checked readLevel, we know that getTasksPump can't have beat us to pri_task_reader.go
381 > // adding these tasks to outstandingTasks. So they should definitely not be there.
382 > _, found := tr.outstandingTasks.Get(t.TaskId)
383 > softassert.That(tr.logger, !found, "newly-written task already present in outstanding tasks")
384 > return found
385 > })
386
387 > if !canAddDirect { pri_task_reader.go
388 tr.lock.Unlock()
389 tr.SignalTaskLoading()
391 }
392
393 > tr.readLevel = resp.maxReadLevelAfter pri_task_reader.go
394 >
395 > tr.recordNewTasksLocked(resp.tasks)
396 >
397 > tr.lock.Unlock()
398 >
399 > tr.addNewTasks(resp.tasks)
400 }
401
417 // ack manager
418
419 > func (tr *priTaskReader) getLoadedTasks() int { pri_task_reader.go
420 > tr.lock.Lock()
421 > defer tr.lock.Unlock()
422 > return tr.loadedTasks
423 > }
424
425 // isDrained returns true if this subqueue has been fully drained:
433 }
434
435 > func (tr *priTaskReader) isDrainedLocked() bool { pri_task_reader.go
436 > return tr.outstandingTasks.Empty() && tr.readLevel >= tr.backlogMgr.db.GetMaxReadLevel(tr.subqueue)
437 > }
438
439 > func (tr *priTaskReader) ackTaskLocked(taskId int64) int64 { pri_task_reader.go
440 > wasAlreadyAcked, found := tr.outstandingTasks.Get(taskId)
441 > if !softassert.That(tr.logger, found, "completed task not found in oustandingTasks") {
442 return 0
443 }
444 > if !softassert.That(tr.logger, !wasAlreadyAcked.(bool), "completed task was already acked") { pri_task_reader.go
445 return 0
446 }
447
448 > tr.outstandingTasks.Put(taskId, true) pri_task_reader.go
449 > tr.loadedTasks--
450 >
451 > // Adjust the ack level as far as we can
452 > var numAcked int64
453 > for {
454 > minId, acked := tr.outstandingTasks.Min()
455 > if minId == nil || !acked.(bool) {
456 > break
457 }
458 > tr.ackLevel = minId.(int64) // nolint:revive pri_task_reader.go
459 > tr.outstandingTasks.Remove(minId)
460 > numAcked += 1
461 }
462
463 // Also if we're completely drained, we can move the ack level up to the read level.
464 > if tr.isDrainedLocked() { pri_task_reader.go
465 > tr.ackLevel = tr.readLevel pri_task_reader.go
466 > }
467
468 > return numAcked pri_task_reader.go
469 }
470
471 > func (tr *priTaskReader) setReadLevelAfterGap(newReadLevel int64) { pri_task_reader.go
472 > tr.lock.Lock()
473 > defer tr.lock.Unlock()
474 > if tr.ackLevel == tr.readLevel {
475 > // This is called after we read a range and find no tasks. The range we read was tr.readLevel to newReadLevel. pri_task_reader.go
476 > // (We know this because nothing should change tr.readLevel except the getTasksPump loop itself, after initialization.
477 > // And getTasksPump doesn't start until it gets a signal from taskWriter that it's initialized the levels.)
478 > // If we've acked all tasks up to tr.readLevel, and there are no tasks between that and newReadLevel, then we've
479 > // acked all tasks up to newReadLevel too. This lets us advance the ack level on a task queue with no activity
480 > // but where the rangeid has moved higher, to prevent excessive reads on the next load.
481 > tr.ackLevel = newReadLevel
482 > // Push the updated ack level to the db. If we didn't do this here, the updated ack level
483 > // wouldn't reach the db until another task is written and acked, which could be far in the
484 > // future. This also lets the approximate backlog count reset if we've reached max read level.
485 > tr.backlogMgr.db.updateAckLevelAndBacklogStats(tr.subqueue, tr.ackLevel, 0, tr.backlogAge.oldestTime())
486 > }
487 > tr.readLevel = newReadLevel pri_task_reader.go
488 }
489
490 > func (tr *priTaskReader) getLevels() (readLevel, ackLevel int64) { pri_task_reader.go
491 > tr.lock.Lock()
492 > defer tr.lock.Unlock()
493 > return tr.readLevel, tr.ackLevel
494 > }
495
496 // gc
497
498 > func (tr *priTaskReader) maybeGCLocked() { pri_task_reader.go
499 > if !tr.shouldGCLocked() {
500 > return pri_task_reader.go
501 > }
502 tr.inGC = true
503 tr.lastGCTime = time.Now()
506 }
507
508 > func (tr *priTaskReader) shouldGCLocked() bool { pri_task_reader.go
509 > if tr.inGC {
510 return false
511 > } else if gcGap := int(tr.ackLevel - tr.gcAckLevel); gcGap == 0 { pri_task_reader.go
512 return false
513 > } else if gcGap >= tr.backlogMgr.config.MaxTaskDeleteBatchSize() { pri_task_reader.go
514 return true
515 }
516 > return time.Since(tr.lastGCTime) > tr.backlogMgr.config.TaskDeleteInterval() pri_task_reader.go
517 }
518
go.temporal.io/server/common/persistence/persistence_rate_limited_clients.go 202 covered LOC · 70 ranges

Open complete file

112 shardRateLimiter quotas.RequestRateLimiter,
113 logger log.Logger,
114 > ) ShardManager { persistence_rate_limited_clients.go
115 > return &shardRateLimitedPersistenceClient{
116 > persistence: persistence,
117 > systemRateLimiter: rateLimiter,
118 > namespaceRateLimiter: namespaceRateLimiter,
119 > shardRateLimiter: shardRateLimiter,
120 > logger: logger,
121 > }
122 > }
123
124 // NewExecutionPersistenceRateLimitedClient creates a client to manage executions
129 shardRateLimiter quotas.RequestRateLimiter,
130 logger log.Logger,
131 > ) ExecutionManager { persistence_rate_limited_clients.go
132 > return &executionRateLimitedPersistenceClient{
133 > persistence: persistence,
134 > systemRateLimiter: systemRateLimiter,
135 > namespaceRateLimiter: namespaceRateLimiter,
136 > shardRateLimiter: shardRateLimiter,
137 > logger: logger,
138 > }
139 > }
140
141 // NewTaskPersistenceRateLimitedClient creates a client to manage tasks
146 shardRateLimiter quotas.RequestRateLimiter,
147 logger log.Logger,
148 > ) TaskManager { persistence_rate_limited_clients.go
149 > return &taskRateLimitedPersistenceClient{
150 > persistence: persistence,
151 > systemRateLimiter: systemRateLimiter,
152 > namespaceRateLimiter: namespaceRateLimiter,
153 > shardRateLimiter: shardRateLimiter,
154 > logger: logger,
155 > }
156 > }
157
158 // NewMetadataPersistenceRateLimitedClient creates a MetadataManager client to manage metadata
163 shardRateLimiter quotas.RequestRateLimiter,
164 logger log.Logger,
165 > ) MetadataManager { persistence_rate_limited_clients.go
166 > return &metadataRateLimitedPersistenceClient{
167 > persistence: persistence,
168 > systemRateLimiter: systemRateLimiter,
169 > namespaceRateLimiter: namespaceRateLimiter,
170 > shardRateLimiter: shardRateLimiter,
171 > logger: logger,
172 > }
173 > }
174
175 // NewClusterMetadataPersistenceRateLimitedClient creates a ClusterMetadataManager client to manage cluster metadata
180 shardRateLimiter quotas.RequestRateLimiter,
181 logger log.Logger,
182 > ) ClusterMetadataManager { persistence_rate_limited_clients.go
183 > return &clusterMetadataRateLimitedPersistenceClient{
184 > persistence: persistence,
185 > systemRateLimiter: systemRateLimiter,
186 > namespaceRateLimiter: namespaceRateLimiter,
187 > shardRateLimiter: shardRateLimiter,
188 > logger: logger,
189 > }
190 > }
191
192 // NewQueuePersistenceRateLimitedClient creates a client to manage queue
197 shardRateLimiter quotas.RequestRateLimiter,
198 logger log.Logger,
200 > return &queueRateLimitedPersistenceClient{
201 > persistence: persistence,
202 > systemRateLimiter: systemRateLimiter,
203 > namespaceRateLimiter: namespaceRateLimiter,
204 > shardRateLimiter: shardRateLimiter,
205 > logger: logger,
206 > }
207 > }
208
209 // NewNexusEndpointPersistenceRateLimitedClient creates a NexusEndpointManager to manage nexus endpoints
214 shardRateLimiter quotas.RequestRateLimiter,
215 logger log.Logger,
216 > ) NexusEndpointManager { persistence_rate_limited_clients.go
217 > return &nexusEndpointRateLimitedPersistenceClient{
218 > persistence: persistence,
219 > systemRateLimiter: systemRateLimiter,
220 > namespaceRateLimiter: namespaceRateLimiter,
221 > shardRateLimiter: shardRateLimiter,
222 > logger: logger,
223 > }
224 > }
225
226 func (p *shardRateLimitedPersistenceClient) GetName() string {
231 ctx context.Context,
232 request *GetOrCreateShardRequest,
233 > ) (*GetOrCreateShardResponse, error) { persistence_rate_limited_clients.go
234 > if err := allow(ctx, "GetOrCreateShard", request.ShardID, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
235 return nil, err
236 }
237
238 > response, err := p.persistence.GetOrCreateShard(ctx, request) persistence_rate_limited_clients.go
239 > return response, err
240 }
241
243 ctx context.Context,
244 request *UpdateShardRequest,
246 > if err := allow(ctx, "UpdateShard", request.ShardInfo.ShardId, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
247 return err
248 }
249
250 > return p.persistence.UpdateShard(ctx, request) persistence_rate_limited_clients.go
251 }
252
254 ctx context.Context,
255 request *AssertShardOwnershipRequest,
257 > if err := allow(ctx, "AssertShardOwnership", request.ShardID, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
258 return err
259 }
260
261 > return p.persistence.AssertShardOwnership(ctx, request) persistence_rate_limited_clients.go
262 }
263
264 > func (p *shardRateLimitedPersistenceClient) Close() { persistence_rate_limited_clients.go
265 > p.persistence.Close()
266 > }
267
268 > func (p *executionRateLimitedPersistenceClient) GetName() string { persistence_rate_limited_clients.go
269 > return p.persistence.GetName()
270 > }
271
272 > func (p *executionRateLimitedPersistenceClient) GetHistoryBranchUtil() HistoryBranchUtil { persistence_rate_limited_clients.go
273 > return p.persistence.GetHistoryBranchUtil()
274 > }
275
276 func (p *executionRateLimitedPersistenceClient) CreateWorkflowExecution(
277 ctx context.Context,
278 request *CreateWorkflowExecutionRequest,
279 > ) (*CreateWorkflowExecutionResponse, error) { persistence_rate_limited_clients.go
280 > if err := allow(ctx, "CreateWorkflowExecution", request.ShardID, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
281 return nil, err
282 }
283
284 > response, err := p.persistence.CreateWorkflowExecution(ctx, request) persistence_rate_limited_clients.go
285 > return response, err
286 }
287
289 ctx context.Context,
290 request *GetWorkflowExecutionRequest,
291 > ) (*GetWorkflowExecutionResponse, error) { persistence_rate_limited_clients.go
292 > if err := allow(ctx, "GetWorkflowExecution", request.ShardID, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
293 return nil, err
294 }
295
296 > response, err := p.persistence.GetWorkflowExecution(ctx, request) persistence_rate_limited_clients.go
297 > return response, err
298 }
299
313 ctx context.Context,
314 request *UpdateWorkflowExecutionRequest,
315 > ) (*UpdateWorkflowExecutionResponse, error) { persistence_rate_limited_clients.go
316 > if err := allow(ctx, "UpdateWorkflowExecution", request.ShardID, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
317 return nil, err
318 }
319
320 > resp, err := p.persistence.UpdateWorkflowExecution(ctx, request) persistence_rate_limited_clients.go
321 > return resp, err
322 }
323
394 ctx context.Context,
395 request *GetHistoryTasksRequest,
396 > ) (*GetHistoryTasksResponse, error) { persistence_rate_limited_clients.go
397 > if err := allow(
398 > ctx,
399 > ConstructHistoryTaskAPI("GetHistoryTasks", request.TaskCategory),
400 > request.ShardID,
401 > p.systemRateLimiter,
402 > p.namespaceRateLimiter,
403 > p.shardRateLimiter,
404 > ); err != nil {
405 return nil, err
406 }
407
408 > response, err := p.persistence.GetHistoryTasks(ctx, request) persistence_rate_limited_clients.go
409 > return response, err
410 }
411
501 }
502
503 > func (p *executionRateLimitedPersistenceClient) Close() { persistence_rate_limited_clients.go
504 > p.persistence.Close()
505 > }
506
507 func (p *taskRateLimitedPersistenceClient) GetName() string {
512 ctx context.Context,
513 request *CreateTasksRequest,
514 > ) (*CreateTasksResponse, error) { persistence_rate_limited_clients.go
515 > if err := allow(ctx, "CreateTasks", CallerSegmentMissing, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
516 return nil, err
517 }
518
519 > response, err := p.persistence.CreateTasks(ctx, request) persistence_rate_limited_clients.go
520 > return response, err
521 }
522
524 ctx context.Context,
525 request *GetTasksRequest,
526 > ) (*GetTasksResponse, error) { persistence_rate_limited_clients.go
527 > if err := allow(ctx, "GetTasks", CallerSegmentMissing, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
528 return nil, err
529 }
530
531 > response, err := p.persistence.GetTasks(ctx, request) persistence_rate_limited_clients.go
532 > return response, err
533 }
534
546 ctx context.Context,
547 request *CreateTaskQueueRequest,
548 > ) (*CreateTaskQueueResponse, error) { persistence_rate_limited_clients.go
549 > if err := allow(ctx, "CreateTaskQueue", CallerSegmentMissing, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
550 return nil, err
551 }
552 > return p.persistence.CreateTaskQueue(ctx, request) persistence_rate_limited_clients.go
553 }
554
556 ctx context.Context,
557 request *UpdateTaskQueueRequest,
558 > ) (*UpdateTaskQueueResponse, error) { persistence_rate_limited_clients.go
559 > if err := allow(ctx, "UpdateTaskQueue", CallerSegmentMissing, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
560 return nil, err
561 }
562 > return p.persistence.UpdateTaskQueue(ctx, request) persistence_rate_limited_clients.go
563 }
564
566 ctx context.Context,
567 request *GetTaskQueueRequest,
568 > ) (*GetTaskQueueResponse, error) { persistence_rate_limited_clients.go
569 > if err := allow(ctx, "GetTaskQueue", CallerSegmentMissing, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
570 return nil, err
571 }
572 > return p.persistence.GetTaskQueue(ctx, request) persistence_rate_limited_clients.go
573 }
574
596 ctx context.Context,
597 request *GetTaskQueueUserDataRequest,
598 > ) (*GetTaskQueueUserDataResponse, error) { persistence_rate_limited_clients.go
599 > if err := allow(ctx, "GetTaskQueueUserData", CallerSegmentMissing, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
600 return nil, err
601 }
602 > return p.persistence.GetTaskQueueUserData(ctx, request) persistence_rate_limited_clients.go
603 }
604
637 }
638
639 > func (p *taskRateLimitedPersistenceClient) Close() { persistence_rate_limited_clients.go
640 > p.persistence.Close()
641 > }
642
643 func (p *metadataRateLimitedPersistenceClient) GetName() string {
648 ctx context.Context,
649 request *CreateNamespaceRequest,
650 > ) (*CreateNamespaceResponse, error) { persistence_rate_limited_clients.go
651 > if err := allow(ctx, "CreateNamespace", CallerSegmentMissing, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
652 return nil, err
653 }
654
655 > response, err := p.persistence.CreateNamespace(ctx, request) persistence_rate_limited_clients.go
656 > return response, err
657 }
658
660 ctx context.Context,
661 request *GetNamespaceRequest,
662 > ) (*GetNamespaceResponse, error) { persistence_rate_limited_clients.go
663 > if err := allow(ctx, "GetNamespace", CallerSegmentMissing, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
664 return nil, err
665 }
666
667 > response, err := p.persistence.GetNamespace(ctx, request) persistence_rate_limited_clients.go
668 > return response, err
669 }
670
716 ctx context.Context,
717 request *ListNamespacesRequest,
718 > ) (*ListNamespacesResponse, error) { persistence_rate_limited_clients.go
719 > if err := allow(ctx, "ListNamespaces", CallerSegmentMissing, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
720 return nil, err
721 }
722
723 > response, err := p.persistence.ListNamespaces(ctx, request) persistence_rate_limited_clients.go
724 > return response, err
725 }
726
748 func (p *metadataRateLimitedPersistenceClient) WatchNamespaces(
749 ctx context.Context,
750 > ) (<-chan *NamespaceWatchEvent, error) { persistence_rate_limited_clients.go
751 > if err := allow(ctx, "WatchNamespaces", CallerSegmentMissing, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
752 return nil, err
753 }
754 > return p.persistence.WatchNamespaces(ctx) persistence_rate_limited_clients.go
755 }
756
757 > func (p *metadataRateLimitedPersistenceClient) Close() { persistence_rate_limited_clients.go
758 > p.persistence.Close()
759 > }
760
761 // AppendHistoryNodes add a node to history node table
785 ctx context.Context,
786 request *ReadHistoryBranchRequest,
787 > ) (*ReadHistoryBranchResponse, error) { persistence_rate_limited_clients.go
788 > if err := allow(ctx, "ReadHistoryBranch", request.ShardID, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
789 return nil, err
790 }
791 > response, err := p.persistence.ReadHistoryBranch(ctx, request) persistence_rate_limited_clients.go
792 > return response, err
793 }
794
998 }
999
1000 > func (p *queueRateLimitedPersistenceClient) Close() { persistence_rate_limited_clients.go
1001 > p.persistence.Close()
1002 > }
1003
1004 func (p *queueRateLimitedPersistenceClient) Init(
1005 ctx context.Context,
1006 blob *commonpb.DataBlob,
1008 > return p.persistence.Init(ctx, blob)
1009 > }
1010
1011 > func (c *clusterMetadataRateLimitedPersistenceClient) Close() { persistence_rate_limited_clients.go
1012 > c.persistence.Close()
1013 > }
1014
1015 func (c *clusterMetadataRateLimitedPersistenceClient) GetName() string {
1020 ctx context.Context,
1021 request *GetClusterMembersRequest,
1022 > ) (*GetClusterMembersResponse, error) { persistence_rate_limited_clients.go
1023 > if err := allow(ctx, "GetClusterMembers", CallerSegmentMissing, c.systemRateLimiter, c.namespaceRateLimiter, c.shardRateLimiter); err != nil {
1024 return nil, err
1025 }
1026 > return c.persistence.GetClusterMembers(ctx, request) persistence_rate_limited_clients.go
1027 }
1028
1030 ctx context.Context,
1031 request *UpsertClusterMembershipRequest,
1033 > if err := allow(ctx, "UpsertClusterMembership", CallerSegmentMissing, c.systemRateLimiter, c.namespaceRateLimiter, c.shardRateLimiter); err != nil {
1034 return err
1035 }
1036 > return c.persistence.UpsertClusterMembership(ctx, request) persistence_rate_limited_clients.go
1037 }
1038
1040 ctx context.Context,
1041 request *PruneClusterMembershipRequest,
1043 > if err := allow(ctx, "PruneClusterMembership", CallerSegmentMissing, c.systemRateLimiter, c.namespaceRateLimiter, c.shardRateLimiter); err != nil {
1044 return err
1045 }
1046 > return c.persistence.PruneClusterMembership(ctx, request) persistence_rate_limited_clients.go
1047 }
1048
1050 ctx context.Context,
1051 request *ListClusterMetadataRequest,
1052 > ) (*ListClusterMetadataResponse, error) { persistence_rate_limited_clients.go
1053 > if err := allow(ctx, "ListClusterMetadata", CallerSegmentMissing, c.systemRateLimiter, c.namespaceRateLimiter, c.shardRateLimiter); err != nil {
1054 return nil, err
1055 }
1056 > return c.persistence.ListClusterMetadata(ctx, request) persistence_rate_limited_clients.go
1057 }
1058
1059 func (c *clusterMetadataRateLimitedPersistenceClient) GetCurrentClusterMetadata(
1060 ctx context.Context,
1061 > ) (*GetClusterMetadataResponse, error) { persistence_rate_limited_clients.go
1062 > if err := allow(ctx, "GetCurrentClusterMetadata", CallerSegmentMissing, c.systemRateLimiter, c.namespaceRateLimiter, c.shardRateLimiter); err != nil {
1063 return nil, err
1064 }
1065 > return c.persistence.GetCurrentClusterMetadata(ctx) persistence_rate_limited_clients.go
1066 }
1067
1100 }
1101
1102 > func (p *nexusEndpointRateLimitedPersistenceClient) Close() { persistence_rate_limited_clients.go
1103 > p.persistence.Close()
1104 > }
1105
1106 func (p *nexusEndpointRateLimitedPersistenceClient) GetNexusEndpoint(
1117 ctx context.Context,
1118 request *ListNexusEndpointsRequest,
1119 > ) (*ListNexusEndpointsResponse, error) { persistence_rate_limited_clients.go
1120 > if err := allow(ctx, "ListNexusEndpoints", CallerSegmentMissing, p.systemRateLimiter, p.namespaceRateLimiter, p.shardRateLimiter); err != nil {
1121 return nil, err
1122 }
1123 > return p.persistence.ListNexusEndpoints(ctx, request) persistence_rate_limited_clients.go
1124 }
1125
1151 namespaceRateLimiter quotas.RequestRateLimiter,
1152 shardRateLimiter quotas.RequestRateLimiter,
1154 > callerInfo := headers.GetCallerInfo(ctx)
1155 > // namespace-level rate limits has to be applied before system-level rate limits.
1156 > now := time.Now().UTC()
1157 > quotaRequest := quotas.NewRequest(
1158 > api,
1159 > RateLimitDefaultToken,
1160 > callerInfo.CallerName,
1161 > callerInfo.CallerType,
1162 > shardID,
1163 > callerInfo.CallOrigin,
1164 > )
1165 > if ok := shardRateLimiter.Allow(now, quotaRequest); !ok {
1166 return ErrPersistenceNamespaceShardLimitExceeded
1167 }
1168 > if ok := namespaceRateLimiter.Allow(now, quotaRequest); !ok { persistence_rate_limited_clients.go
1169 return ErrPersistenceNamespaceLimitExceeded
1170 }
1171 > if ok := systemRateLimiter.Allow(now, quotaRequest); !ok { persistence_rate_limited_clients.go
1172 return ErrPersistenceSystemLimitExceeded
1173 }
1175 }
1176
go.temporal.io/server/common/dynamicconfig/collection.go 198 covered LOC · 46 ranges

Open complete file

111 // NewCollection creates a new collection. For subscriptions to work, you must call Start/Stop.
112 // Get will work without Start/Stop.
113 > func NewCollection(client Client, logger log.Logger) *Collection { collection.go
114 > // Do this at the first convenient place we have a logger:
115 > logSharedStructureWarnings(logger)
116 >
117 > return &Collection{
118 > client: client,
119 > logger: logger,
120 > errCount: -1,
121 > subscriptions: make(map[Key]map[int]any),
122 > convertCache: new(sync.Map),
123 > indexCache: new(sync.Map),
124 > }
125 > }
126
127 > func (c *Collection) Start() { collection.go
128 > c.subscriptionLock.Lock()
129 > defer c.subscriptionLock.Unlock()
130 > if notifyingClient, ok := c.client.(NotifyingClient); ok {
131 c.cancelClientSubscription = notifyingClient.Subscribe(c.keysChanged)
132 > } else { collection.go
133 > c.poller.Go(c.pollForChanges) collection.go
134 > }
135 }
136
137 > func (c *Collection) Stop() { collection.go
138 > c.poller.Cancel()
139 > c.poller.Wait()
140 > if c.cancelClientSubscription != nil {
141 c.cancelClientSubscription()
142 }
144
145 // Implement pingable.Pingable
146 > func (c *Collection) GetPingChecks() []pingable.Check { collection.go
147 > return []pingable.Check{
148 > {
149 > Name: "dynamic config callbacks",
150 > Timeout: 5 * time.Second,
151 > Ping: func() []pingable.Pingable {
152 > c.subscriptionLock.Lock()
153 > //nolint:staticcheck // SA2001 just checking if we can acquire the lock
154 > c.subscriptionLock.Unlock()
155 > return nil
156 > },
157 },
158 }
159 }
160
161 > func (c *Collection) pollForChanges(ctx context.Context) error { collection.go
162 > interval := DynamicConfigSubscriptionPollInterval.Get(c)
163 > for ctx.Err() == nil {
164 > util.InterruptibleSleep(ctx, interval())
165 > c.pollOnce()
166 > }
167 > return ctx.Err() collection.go
168 }
169
170 > func (c *Collection) pollOnce() { collection.go
171 > c.subscriptionLock.Lock()
172 > defer c.subscriptionLock.Unlock()
173 >
174 > for key, subs := range c.subscriptions {
175 > setting := queryRegistry(key)
176 > if setting == nil {
177 continue
178 }
179 > for _, sub := range subs { collection.go
180 cvs := c.client.GetValue(key)
181 setting.dispatchUpdate(c, sub, cvs)
212 cvs []ConstrainedValue,
213 precedence []Constraints,
214 > ) (*ConstrainedValue, error) { collection.go
215 > if len(cvs) == 0 {
216 > return nil, errKeyNotPresent collection.go
217 > } else if len(cvs) > constraintsCacheThreshold && len(cvs) <= math.MaxInt32 { collection.go
218 return findMatchWithCache(cache, cvs, precedence)
219 }
279 convert func(value any) (T, error),
280 precedence []Constraints,
281 > ) T { collection.go
282 > cvs := c.client.GetValue(key)
283 > v, _ := matchAndConvertCvs(c, key, def, convert, precedence, cvs)
284 > return v
285 > }
286
287 func matchAndConvertCvs[T any](
292 precedence []Constraints,
293 cvs []ConstrainedValue,
294 > ) (T, any) { collection.go
295 > cvp, err := findMatch(c.indexCache, cvs, precedence)
296 > if err != nil {
297 > // couldn't find a constrained match, use default collection.go
298 > return def, usingDefaultValue
299 > }
300
301 typedVal, err := convertWithCache(c, key, convert, cvp)
317 valueOrder int,
318 defaultOrder int,
319 > ) { collection.go
320 > order := 0
321 > for _, m := range precedence {
322 > for idx, cv := range cvs {
323 > order++ collection.go
324 > if m == cv.Constraints {
325 > if valueOrder == 0 {
326 > valueOrder = order
327 > // Note: cvs here is the slice returned by Client.GetValue. We want to
328 > // return a pointer into that slice instead of copying the ConstrainedValue.
329 > // See findMatch.
330 > matchedValue = &cvs[idx]
331 > }
332 }
333 }
334 > for _, cv := range defaultCVs { collection.go
335 > order++
336 > if m == cv.Constraints {
337 > if defaultOrder == 0 {
338 > defaultOrder = order
339 > matchedDefault = cv.Value
340 > }
341 }
342 }
343 }
344 > return collection.go
345 }
346
352 defaultCVs []TypedConstrainedValue[T],
353 precedence []Constraints,
354 > ) (value T, raw any) { collection.go
355 > cvp, defVal, valOrder, defOrder := findMatchWithConstrainedDefaults(cvs, defaultCVs, precedence)
356 >
357 > if defOrder == 0 {
358 // This is a server bug: all precedence lists must end with no-constraints, and all
359 // constrained defaults must have a no-constraints value, so we should have gotten a match.
361 // leave value as the zero value, that's the best we can do
362 return value, usingDefaultValue
363 > } else if valOrder == 0 { collection.go
364 > return defVal, usingDefaultValue collection.go
365 > } else if defOrder < valOrder { collection.go
366 > // value was present but constrained default took precedence collection.go
367 > return defVal, usingDefaultValue // use sentinel since we're using default
368 > }
369 > typedVal, err := convertWithCache(c, key, convert, cvp) collection.go
370 > if err != nil {
371 // We failed to convert the value to the desired type. Use the default.
372 if c.throttleLog() {
375 return defVal, usingDefaultValue
376 }
377 > return typedVal, cvp.Value collection.go
378 }
379
384 convert func(value any) (T, error),
385 precedence []Constraints,
386 > ) T { collection.go
387 > cvs := c.client.GetValue(key)
388 > value, _ := findAndResolveWithConstrainedDefaults(c, key, convert, cvs, cdef, precedence)
389 > return value
390 > }
391
392 func subscribe[T any](
397 prec []Constraints,
398 callback func(T),
399 > ) (T, func()) { collection.go
400 > c.subscriptionLock.Lock()
401 > defer c.subscriptionLock.Unlock()
402 >
403 > // get one value immediately (note that subscriptionLock is held here so we can't race with
404 > // an update)
405 > cvs := c.client.GetValue(key)
406 > init, raw := matchAndConvertCvs(c, key, def, convert, prec, cvs)
407 >
408 > // As a convenience (and for efficiency), you can pass in a nil callback; we just return the
409 > // current value and skip the subscription. The cancellation func returned is also nil.
410 > if callback == nil {
411 return init, nil
412 }
413
414 > c.subscriptionIdx++ collection.go
415 > id := c.subscriptionIdx
416 >
417 > if c.subscriptions[key] == nil {
418 > c.subscriptions[key] = make(map[int]any)
419 > }
420
421 > c.subscriptions[key][id] = &subscription[T]{ collection.go
422 > prec: prec,
423 > f: callback,
424 > def: def,
425 > raw: raw,
426 > }
427 >
428 > return init, func() {
429 > c.subscriptionLock.Lock() collection.go
430 > defer c.subscriptionLock.Unlock()
431 > delete(c.subscriptions[key], id)
432 > }
433 }
434
440 prec []Constraints,
441 callback func(T),
442 > ) (T, func()) { collection.go
443 > c.subscriptionLock.Lock()
444 > defer c.subscriptionLock.Unlock()
445 >
446 > // get one value immediately (note that subscriptionLock is held here so we can't race with
447 > // an update)
448 > cvs := c.client.GetValue(key)
449 > init, raw := findAndResolveWithConstrainedDefaults(c, key, convert, cvs, cdef, prec)
450 >
451 > // As a convenience (and for efficiency), you can pass in a nil callback; we just return the
452 > // current value and skip the subscription. The cancellation func returned is also nil.
453 > if callback == nil {
454 return init, nil
455 }
456
457 > c.subscriptionIdx++ collection.go
458 > id := c.subscriptionIdx
459 >
460 > if c.subscriptions[key] == nil {
461 > c.subscriptions[key] = make(map[int]any)
462 > }
463
464 > c.subscriptions[key][id] = &subscription[T]{ collection.go
465 > prec: prec,
466 > f: callback,
467 > cdef: cdef,
468 > raw: raw,
469 > }
470 >
471 > return init, func() {
472 > c.subscriptionLock.Lock() collection.go
473 > defer c.subscriptionLock.Unlock()
474 > delete(c.subscriptions[key], id)
475 > }
476 }
477
547 }
548
549 > func convertWithCache[T any](c *Collection, key Key, convert func(any) (T, error), cvp *ConstrainedValue) (T, error) { collection.go
550 > weakcvp := weak.Make(cvp)
551 >
552 > if converted, ok := c.convertCache.Load(weakcvp); ok {
553 if t, ok := converted.(T); ok {
554 return t, nil
559 }
560
561 > t, err := convert(cvp.Value) collection.go
562 > if err != nil {
563 var zero T
564 return zero, err
565 }
566
567 > if _, loaded := c.convertCache.LoadOrStore(weakcvp, t); !loaded { collection.go
568 > cc := c.convertCache // capture only this pointer, not the whole Collection
569 > runtime.AddCleanup(cvp, func(w weak.Pointer[ConstrainedValue]) {
570 > cc.Delete(w) collection.go
571 > }, weakcvp)
572 }
573
574 > return t, nil collection.go
575 }
576
577 > func convertInt(val any) (int, error) { collection.go
578 > switch val := val.(type) {
579 > case int: collection.go
580 > return int(val), nil
581 case int8:
582 return int(val), nil
676 // treat the fields independently), or the zero value of its type (if you want to treat the fields
677 // as a group and default unset fields to zero).
678 > func ConvertStructure[T any](def T) func(v any) (T, error) { collection.go
679 > return func(v any) (T, error) {
680 > // if we already have the right type, no conversion is necessary
681 > if typedV, ok := v.(T); ok {
682 return typedV, nil
683 }
685 // Deep-copy the default and decode over it. This allows using e.g. a struct with some
686 // default fields filled in and a config that only set some fields.
687 > out := deepCopyForMapstructure(def) collection.go
688 >
689 > dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
690 > Result: &out,
691 > DecodeHook: mapstructure.ComposeDecodeHookFunc(
692 > mapstructureHookDuration,
693 > mapstructureHookTimestamp,
694 > mapstructureHookProtoEnum,
695 > mapstructureHookGeneric,
696 > ),
697 > })
698 > if err != nil {
699 return out, err
700 }
701 > err = dec.Decode(v) collection.go
702 > return out, err
703 }
704 }
go.temporal.io/server/common/cluster/metadata.go 194 covered LOC · 55 ranges

Open complete file

142 refreshDuration dynamicconfig.DurationPropertyFn,
143 logger log.Logger,
144 > ) Metadata { metadata.go
145 > if len(clusterInfo) == 0 {
146 panic("Empty cluster information")
147 > } else if len(masterClusterName) == 0 { metadata.go
148 panic("Master cluster name is empty")
149 > } else if len(currentClusterName) == 0 { metadata.go
150 panic("Current cluster name is empty")
151 > } else if failoverVersionIncrement == 0 || failoverVersionIncrement > math.MaxInt32 { metadata.go
152 panic("Version increment <= 0 or > 2147483647")
153 }
154
155 > versionToClusterName, err := updateVersionToClusterName(clusterInfo, failoverVersionIncrement) metadata.go
156 > if err != nil {
157 // nolint:forbidigo // matches the other startup-config panics in this constructor
158 panic(err.Error())
159 }
160 > if _, ok := clusterInfo[currentClusterName]; !ok { metadata.go
161 panic("Current cluster is not specified in cluster info")
162 }
163 > if _, ok := clusterInfo[masterClusterName]; !ok { metadata.go
164 panic("Master cluster is not specified in cluster info")
165 }
166
167 > copyClusterInfo := make(map[string]ClusterInformation) metadata.go
168 > maps.Copy(copyClusterInfo, clusterInfo)
169 > if refreshDuration == nil {
170 refreshDuration = dynamicconfig.GetDurationPropertyFn(refreshInterval)
171 }
172 > return &metadataImpl{ metadata.go
173 > status: common.DaemonStatusInitialized,
174 > enableGlobalNamespace: enableGlobalNamespace,
175 > failoverVersionIncrement: failoverVersionIncrement,
176 > masterClusterName: masterClusterName,
177 > currentClusterName: currentClusterName,
178 > clusterInfo: copyClusterInfo,
179 > versionToClusterName: versionToClusterName,
180 > clusterChangeCallback: make(map[any]CallbackFn),
181 > clusterMetadataStore: clusterMetadataStore,
182 > logger: logger,
183 > refreshDuration: refreshDuration,
184 > }
185 }
186
190 dynamicCollection *dynamicconfig.Collection,
191 logger log.Logger,
192 > ) Metadata { metadata.go
193 > return NewMetadata(
194 > config.EnableGlobalNamespace,
195 > config.FailoverVersionIncrement,
196 > config.MasterClusterName,
197 > config.CurrentClusterName,
198 > config.ClusterInformation,
199 > clusterMetadataStore,
200 > dynamicconfig.ClusterMetadataRefreshInterval.Get(dynamicCollection),
201 > logger,
202 > )
203 > }
204
205 > func (m *metadataImpl) Start() { metadata.go
206 > if !atomic.CompareAndSwapInt32(&m.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
207 return
208 }
209
210 // TODO: specify a timeout for the context
211 > ctx := headers.SetCallerInfo( metadata.go
212 > context.TODO(),
213 > headers.SystemBackgroundHighCallerInfo,
214 > )
215 > err := m.refreshClusterMetadata(ctx)
216 > if err != nil {
217 // Crash rather than start with partial cluster metadata (e.g. an invalid
218 // or missing row in cluster_metadata): replication and failover routing
221 m.logger.Fatal("Unable to initialize cluster metadata cache", tag.Error(err))
222 }
223 > m.refresher = goro.NewHandle(ctx).Go(m.refreshLoop) metadata.go
224 }
225
226 > func (m *metadataImpl) Stop() { metadata.go
227 > if !atomic.CompareAndSwapInt32(&m.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
228 return
229 }
230
231 > m.refresher.Cancel() metadata.go
232 > <-m.refresher.Done()
233 }
234
235 > func (m *metadataImpl) GetPingChecks() []pingable.Check { metadata.go
236 > return []pingable.Check{
237 > {
238 > Name: "cluster metadata lock",
239 > // we don't do any persistence ops under clusterLock, use a short timeout
240 > Timeout: 10 * time.Second,
241 > Ping: func() []pingable.Pingable {
242 > m.clusterLock.Lock()
243 > // nolint:staticcheck
244 > m.clusterLock.Unlock()
245 > return nil
246 > },
247 MetricsName: metrics.DDClusterMetadataLockLatency.Name(),
248 },
252 // not persistence ops.
253 Timeout: 10 * time.Second,
254 > Ping: func() []pingable.Pingable { metadata.go
255 > m.clusterCallbackLock.Lock()
256 > // nolint:staticcheck
257 > m.clusterCallbackLock.Unlock()
258 > return nil
259 > },
260 MetricsName: metrics.DDClusterMetadataCallbackLockLatency.Name(),
261 },
263 }
264
265 > func (m *metadataImpl) IsGlobalNamespaceEnabled() bool { metadata.go
266 > return m.enableGlobalNamespace
267 > }
268
269 func (m *metadataImpl) IsMasterCluster() bool {
271 }
272
273 > func (m *metadataImpl) GetClusterID() int64 { metadata.go
274 > m.clusterLock.RLock()
275 > defer m.clusterLock.RUnlock()
276 >
277 > info, ok := m.clusterInfo[m.currentClusterName]
278 > if !ok {
279 panic(fmt.Sprintf(
280 "Unknown cluster name: %v with given cluster initial failover version map: %v.",
283 ))
284 }
285 > return info.InitialFailoverVersion metadata.go
286 }
287
313 }
314
315 > func (m *metadataImpl) GetCurrentClusterName() string { metadata.go
316 > return m.currentClusterName
317 > }
318
319 > func (m *metadataImpl) GetAllClusterInfo() map[string]ClusterInformation { metadata.go
320 > m.clusterLock.RLock()
321 > defer m.clusterLock.RUnlock()
322 >
323 > result := make(map[string]ClusterInformation, len(m.clusterInfo))
324 > maps.Copy(result, m.clusterInfo)
325 > return result
326 > }
327
328 > func (m *metadataImpl) ClusterNameForFailoverVersion(isGlobalNamespace bool, failoverVersion int64) string { metadata.go
329 > if failoverVersion == common.EmptyVersion {
330 > // Local namespace uses EmptyVersion. But local namespace could be promoted to global namespace. Once promoted, metadata.go
331 > // workflows with EmptyVersion could be replicated to other clusters. The receiving cluster needs to know that
332 > // those workflows are not from their current cluster.
333 > if isGlobalNamespace {
334 return unknownClusterNamePrefix + strconv.Itoa(int(failoverVersion))
335 }
336 > return m.currentClusterName metadata.go
337 }
338
369 }
370
371 > func (m *metadataImpl) RegisterMetadataChangeCallback(callbackId any, cb CallbackFn) { metadata.go
372 > m.clusterCallbackLock.Lock()
373 > m.clusterChangeCallback[callbackId] = cb
374 > m.clusterCallbackLock.Unlock()
375 >
376 > oldEntries := make(map[string]*ClusterInformation)
377 > newEntries := make(map[string]*ClusterInformation)
378 > m.clusterLock.RLock()
379 > for clusterName, clusterInfo := range m.clusterInfo {
380 > oldEntries[clusterName] = nil
381 > newEntries[clusterName] = ShallowCopyClusterInformation(&clusterInfo)
382 > }
383 > m.clusterLock.RUnlock()
384 > cb(oldEntries, newEntries)
385 }
386
387 > func (m *metadataImpl) UnRegisterMetadataChangeCallback(callbackId any) { metadata.go
388 > m.clusterCallbackLock.Lock()
389 > delete(m.clusterChangeCallback, callbackId)
390 > m.clusterCallbackLock.Unlock()
391 > }
392
393 > func (m *metadataImpl) refreshLoop(ctx context.Context) error { metadata.go
394 > timer := time.NewTicker(m.refreshDuration())
395 > defer timer.Stop()
396 >
397 > for {
398 > select {
399 > case <-ctx.Done(): metadata.go
400 > return nil
401 case <-timer.C:
402 for err := m.refreshClusterMetadata(ctx); err != nil; err = m.refreshClusterMetadata(ctx) {
415 }
416
417 > func (m *metadataImpl) refreshClusterMetadata(ctx context.Context) error { metadata.go
418 > clusterMetadataMap, err := m.listAllClusterMetadataFromDB(ctx)
419 > if err != nil {
420 return err
421 }
422
423 > oldEntries := make(map[string]*ClusterInformation) metadata.go
424 > newEntries := make(map[string]*ClusterInformation)
425 >
426 > clusterInfoMap := m.GetAllClusterInfo()
427 > for clusterName, newClusterInfo := range clusterMetadataMap {
428 > oldClusterInfo, ok := clusterInfoMap[clusterName]
429 > if !ok {
430 // handle new cluster registry
431 oldEntries[clusterName] = nil
432 newEntries[clusterName] = ShallowCopyClusterInformation(newClusterInfo)
433 > } else if newClusterInfo.version > oldClusterInfo.version { metadata.go
434 if newClusterInfo.Enabled == oldClusterInfo.Enabled &&
435 newClusterInfo.ReplicationEnabled == oldClusterInfo.ReplicationEnabled &&
447 }
448 }
449 > for clusterName, oldClusterInfo := range clusterInfoMap { metadata.go
450 > if _, ok := clusterMetadataMap[clusterName]; !ok {
451 // removed cluster registry
452 oldEntries[clusterName] = &oldClusterInfo
455 }
456
457 > if len(oldEntries) > 0 { metadata.go
458 // Build a candidate map, validate it, and only commit on success.
459 // A bad row in cluster_metadata must not be able to crash the refresher
502 info ClusterInformation,
503 failoverVersionIncrement int64,
504 > ) error { metadata.go
505 > if clusterName == "" {
506 return errors.New("cluster name must not be empty")
507 }
508 > if info.InitialFailoverVersion <= 0 { metadata.go
509 return fmt.Errorf("cluster %q: InitialFailoverVersion must be > 0, got %d",
510 clusterName, info.InitialFailoverVersion)
511 }
512 > if info.InitialFailoverVersion >= failoverVersionIncrement { metadata.go
513 return fmt.Errorf("cluster %q: InitialFailoverVersion (%d) must be < FailoverVersionIncrement (%d)",
514 clusterName, info.InitialFailoverVersion, failoverVersionIncrement)
515 }
516 > if info.Enabled && info.RPCAddress == "" { metadata.go
517 return fmt.Errorf("cluster %q: RPCAddress must not be empty when Enabled=true", clusterName)
518 }
519 > return nil metadata.go
520 }
521
522 > func updateVersionToClusterName(clusterInfo map[string]ClusterInformation, failoverVersionIncrement int64) (map[int64]string, error) { metadata.go
523 > versionToClusterName := make(map[int64]string)
524 > for clusterName, info := range clusterInfo {
525 > if err := ValidateClusterInformation(clusterName, info, failoverVersionIncrement); err != nil {
526 return nil, err
527 }
528 > if existing, dup := versionToClusterName[info.InitialFailoverVersion]; dup { metadata.go
529 return nil, fmt.Errorf(
530 "duplicate InitialFailoverVersion %d for clusters %q and %q",
531 info.InitialFailoverVersion, existing, clusterName)
532 }
533 > versionToClusterName[info.InitialFailoverVersion] = clusterName metadata.go
534 }
535 > return versionToClusterName, nil metadata.go
536 }
537
538 func (m *metadataImpl) listAllClusterMetadataFromDB(
539 ctx context.Context,
540 > ) (map[string]*ClusterInformation, error) { metadata.go
541 > result := make(map[string]*ClusterInformation)
542 > metadataStore := m.clusterMetadataStore
543 > if metadataStore == nil {
544 return result, nil
545 }
546
547 > iterator := GetAllClustersIter(ctx, metadataStore) metadata.go
548 > for iterator.HasNext() {
549 > item, err := iterator.Next()
550 > if err != nil {
551 return nil, err
552 }
553 > result[item.GetClusterName()] = ClusterInformationFromDB(item) metadata.go
554 }
555 > return result, nil metadata.go
556 }
557
560 ctx context.Context,
561 metadataStore persistence.ClusterMetadataManager,
562 > ) collection.Iterator[*persistence.GetClusterMetadataResponse] { metadata.go
563 > paginationFn := func(paginationToken []byte) ([]*persistence.GetClusterMetadataResponse, []byte, error) {
564 > resp, err := metadataStore.ListClusterMetadata(
565 > ctx,
566 > &persistence.ListClusterMetadataRequest{
567 > PageSize: defaultClusterMetadataPageSize,
568 > NextPageToken: paginationToken,
569 > },
570 > )
571 > if err != nil {
572 return nil, nil, err
573 }
574 > return resp.ClusterMetadata, resp.NextPageToken, nil metadata.go
575 }
576
577 > iterator := collection.NewPagingIterator(paginationFn) metadata.go
578 > return iterator
579 }
580
581 > func ClusterInformationFromDB(getClusterResp *persistence.GetClusterMetadataResponse) *ClusterInformation { metadata.go
582 > return &ClusterInformation{
583 > Enabled: getClusterResp.GetIsConnectionEnabled(),
584 > InitialFailoverVersion: getClusterResp.GetInitialFailoverVersion(),
585 > RPCAddress: getClusterResp.GetClusterAddress(),
586 > HTTPAddress: getClusterResp.GetHttpAddress(),
587 > ClusterID: getClusterResp.GetClusterId(),
588 > ShardCount: getClusterResp.GetHistoryShardCount(),
589 > Tags: getClusterResp.GetTags(),
590 > ReplicationEnabled: getClusterResp.GetIsReplicationEnabled(),
591 > version: getClusterResp.Version,
592 > }
593 > }
594
595 // ShallowCopyClusterInformation returns a shallow copy of the given ClusterInformation. The [ClusterInformation.Tags]
596 // field is not deep-copied, so you must be careful when modifying it.
597 > func ShallowCopyClusterInformation(information *ClusterInformation) *ClusterInformation { metadata.go
598 > tmp := *information
599 > return &tmp
600 > }
601
602 // IsReplicationEnabledForCluster checks if replication is enabled for a cluster, considering the feature flag.
603 // When enableSeparateReplicationFlag is false, it falls back to only checking the Enabled flag.
604 // This is a shared helper function used across history service components.
605 > func IsReplicationEnabledForCluster(clusterInfo ClusterInformation, enableSeparateReplicationFlag bool) bool { metadata.go
606 > if enableSeparateReplicationFlag {
607 // New behavior: check both Enabled (for connectivity) and ReplicationEnabled (for replication streams)
608 return clusterInfo.Enabled && clusterInfo.ReplicationEnabled
609 }
610 // Old behavior: only check Enabled flag
611 > return clusterInfo.Enabled metadata.go
612 }
go.temporal.io/server/service/history/visibility_queue_task_executor.go 187 covered LOC · 43 ranges

Open complete file

56 relocateAttributesMinBlobSize dynamicconfig.IntPropertyFnWithNamespaceFilter,
57 externalPayloadsEnabled dynamicconfig.BoolPropertyFnWithNamespaceFilter,
58 > ) queues.Executor { visibility_queue_task_executor.go
59 > return &visibilityQueueTaskExecutor{
60 > shardContext: shardContext,
61 > cache: workflowCache,
62 > logger: logger,
63 > metricProvider: metricProvider,
64 > visibilityMgr: visibilityMgr,
65 >
66 > ensureCloseBeforeDelete: ensureCloseBeforeDelete,
67 > enableCloseWorkflowCleanup: enableCloseWorkflowCleanup,
68 > relocateAttributesMinBlobSize: relocateAttributesMinBlobSize,
69 > externalPayloadsEnabled: externalPayloadsEnabled,
70 > }
71 > }
72
73 func (t *visibilityQueueTaskExecutor) Execute(
74 ctx context.Context,
75 executable queues.Executable,
76 > ) queues.ExecuteResponse { visibility_queue_task_executor.go
77 > task := executable.GetTask()
78 > taskType := queues.GetVisibilityTaskTypeTagValue(task)
79 > namespaceTag, replicationState := getNamespaceTagAndReplicationStateByID(
80 > t.shardContext.GetNamespaceRegistry(),
81 > task.GetNamespaceID(),
82 > executable.GetWorkflowID(),
83 > )
84 > metricsTags := []metrics.Tag{
85 > namespaceTag,
86 > metrics.TaskTypeTag(taskType),
87 > metrics.OperationTag(taskType), // for backward compatibility
88 > }
89 >
90 > if replicationState == enumspb.REPLICATION_STATE_HANDOVER {
91 // TODO: exclude task types here if we believe it's safe & necessary to execute
92 // them during namespace handover.
103 }
104
105 > var err error visibility_queue_task_executor.go
106 > switch task := task.(type) {
107 > case *tasks.StartExecutionVisibilityTask: visibility_queue_task_executor.go
108 > err = t.processStartExecution(ctx, task)
109 case *tasks.UpsertExecutionVisibilityTask:
110 err = t.processUpsertExecution(ctx, task)
111 > case *tasks.CloseExecutionVisibilityTask: visibility_queue_task_executor.go
112 > err = t.processCloseExecution(ctx, task)
113 case *tasks.DeleteExecutionVisibilityTask:
114 err = t.processDeleteExecution(ctx, task)
120 }
121
122 > return queues.ExecuteResponse{ visibility_queue_task_executor.go
123 > ExecutionMetricTags: metricsTags,
124 > ExecutedAsActive: true,
125 > ExecutionErr: err,
126 > }
127 }
128
130 ctx context.Context,
131 task *tasks.StartExecutionVisibilityTask,
132 > ) (retError error) { visibility_queue_task_executor.go
133 > ctx, cancel := context.WithTimeout(ctx, taskTimeout)
134 > defer cancel()
135 >
136 > namespaceEntry, err := t.shardContext.GetNamespaceRegistry().
137 > GetNamespaceByID(namespace.ID(task.GetNamespaceID()))
138 > if err != nil {
139 return err
140 }
141
142 > weContext, release, err := getWorkflowExecutionContextForTask(ctx, t.shardContext, t.cache, task) visibility_queue_task_executor.go
143 > if err != nil {
144 return err
145 }
146 > defer func() { release(retError) }() visibility_queue_task_executor.go
147
148 > mutableState, err := weContext.LoadMutableState(ctx, t.shardContext) visibility_queue_task_executor.go
149 > if err != nil {
150 return err
151 }
152 > if mutableState == nil || !mutableState.IsWorkflowExecutionRunning() { visibility_queue_task_executor.go
153 return nil
154 }
156 // verify task version for RecordWorkflowStarted.
157 // upsert doesn't require verifyTask, because it is just a sync of mutableState.
158 > startVersion, err := mutableState.GetStartVersion() visibility_queue_task_executor.go
159 > if err != nil {
160 return err
161 }
162 > err = CheckTaskVersion(t.shardContext, t.logger, mutableState.GetNamespaceEntry(), startVersion, task.Version, task) visibility_queue_task_executor.go
163 > if err != nil {
164 return err
165 }
166
167 > requestBase := t.getVisibilityRequestBase( visibility_queue_task_executor.go
168 > task,
169 > namespaceEntry,
170 > mutableState,
171 > mutableState.GetExecutionInfo().Memo,
172 > mutableState.GetExecutionInfo().SearchAttributes,
173 > )
174 >
175 > // NOTE: do not access anything related mutable state after this lock release
176 > // release the context lock since we no longer need mutable state and
177 > // the rest of logic is making RPC call, which takes time.
178 > release(nil)
179 >
180 > return t.visibilityMgr.RecordWorkflowExecutionStarted(
181 > ctx,
182 > &manager.RecordWorkflowExecutionStartedRequest{
183 > VisibilityRequestBase: requestBase,
184 > },
185 > )
186 }
187
237 parentCtx context.Context,
238 task *tasks.CloseExecutionVisibilityTask,
239 > ) (retError error) { visibility_queue_task_executor.go
240 > ctx, cancel := context.WithTimeout(parentCtx, taskTimeout)
241 > defer cancel()
242 >
243 > namespaceEntry, err := t.shardContext.GetNamespaceRegistry().
244 > GetNamespaceByID(namespace.ID(task.GetNamespaceID()))
245 > if err != nil {
246 return err
247 }
248
249 > weContext, release, err := getWorkflowExecutionContextForTask(ctx, t.shardContext, t.cache, task) visibility_queue_task_executor.go
250 > if err != nil {
251 return err
252 }
253 > defer func() { release(retError) }() visibility_queue_task_executor.go
254
255 > mutableState, err := weContext.LoadMutableState(ctx, t.shardContext) visibility_queue_task_executor.go
256 > if err != nil {
257 return err
258 }
259 > if mutableState == nil || mutableState.IsWorkflowExecutionRunning() { visibility_queue_task_executor.go
260 return nil
261 }
262
263 > closeVersion, err := mutableState.GetCloseVersion() visibility_queue_task_executor.go
264 > if err != nil {
265 return err
266 }
267 > err = CheckTaskVersion(t.shardContext, t.logger, mutableState.GetNamespaceEntry(), closeVersion, task.Version, task) visibility_queue_task_executor.go
268 > if err != nil {
269 return err
270 }
271
272 > requestBase := t.getVisibilityRequestBase( visibility_queue_task_executor.go
273 > task,
274 > namespaceEntry,
275 > mutableState,
276 > mutableState.GetExecutionInfo().Memo,
277 > mutableState.GetExecutionInfo().SearchAttributes,
278 > )
279 > closedRequest, err := t.getClosedVisibilityRequest(ctx, requestBase, mutableState, namespaceEntry)
280 > if err != nil {
281 return err
282 }
285 // release the context lock since we no longer need mutable state and
286 // the rest of logic is making RPC call, which takes time.
288 >
289 > err = t.visibilityMgr.RecordWorkflowExecutionClosed(ctx, closedRequest)
290 > if err != nil {
291 return err
292 }
297 // and parentCtx (which doesn't have timeout) must be used everywhere bellow.
298
299 > if t.needRunCleanUp(requestBase) { visibility_queue_task_executor.go
300 return t.cleanupExecutionInfo(parentCtx, task)
301 }
303 }
304
305 func (t *visibilityQueueTaskExecutor) needRunCleanUp(
306 request *manager.VisibilityRequestBase,
308 > if !t.enableCloseWorkflowCleanup(request.Namespace.String()) {
310 > }
311 // If there are no memo nor search attributes, then no clean up is necessary.
312 if len(request.Memo.GetFields()) == 0 && len(request.SearchAttributes.GetIndexedFields()) == 0 {
516 memoMap map[string]*commonpb.Payload,
517 searchAttributesMap map[string]*commonpb.Payload,
518 > ) *manager.VisibilityRequestBase { visibility_queue_task_executor.go
519 > var (
520 > executionInfo = mutableState.GetExecutionInfo()
521 > startTime = timestamp.TimeValue(mutableState.GetExecutionState().GetStartTime())
522 > executionTime = timestamp.TimeValue(executionInfo.GetExecutionTime())
523 > visibilityMemo = getWorkflowMemo(copyMapPayload(memoMap))
524 > searchAttributes = getSearchAttributes(copyMapPayload(searchAttributesMap))
525 > )
526 >
527 > var parentExecution *commonpb.WorkflowExecution
528 > if executionInfo.ParentWorkflowId != "" && executionInfo.ParentRunId != "" {
529 parentExecution = &commonpb.WorkflowExecution{
530 WorkflowId: executionInfo.ParentWorkflowId,
536 // copied to ensure that the mutable state is not accessed after the workflow
537 // lock is released and that there is no data race.
538 > return &manager.VisibilityRequestBase{ visibility_queue_task_executor.go
539 > NamespaceID: namespaceEntry.ID(),
540 > Namespace: namespaceEntry.Name(),
541 > Execution: &commonpb.WorkflowExecution{
542 > WorkflowId: task.GetWorkflowID(),
543 > RunId: task.GetRunID(),
544 > },
545 > WorkflowTypeName: executionInfo.WorkflowTypeName,
546 > StartTime: startTime,
547 > Status: mutableState.GetExecutionState().GetStatus(),
548 > ExecutionTime: executionTime,
549 > TaskID: task.GetTaskID(),
550 > ShardID: t.shardContext.GetShardID(),
551 > Memo: visibilityMemo,
552 > TaskQueue: executionInfo.TaskQueue,
553 > SearchAttributes: searchAttributes,
554 > ParentExecution: parentExecution,
555 > RootExecution: &commonpb.WorkflowExecution{
556 > WorkflowId: executionInfo.RootWorkflowId,
557 > RunId: executionInfo.RootRunId,
558 > },
559 > }
560 }
561
620 mutableState historyi.MutableState,
621 namespaceEntry *namespace.Namespace,
622 > ) (*manager.RecordWorkflowExecutionClosedRequest, error) { visibility_queue_task_executor.go
623 > wfCloseTime, err := mutableState.GetWorkflowCloseTime(ctx)
624 > if err != nil {
625 return nil, err
626 }
627 > wfExecutionDuration, err := mutableState.GetWorkflowExecutionDuration(ctx) visibility_queue_task_executor.go
628 > if err != nil {
629 return nil, err
630 }
631 > historyLength := mutableState.GetNextEventID() - 1 visibility_queue_task_executor.go
632 > executionInfo := mutableState.GetExecutionInfo()
633 > stateTransitionCount := executionInfo.GetStateTransitionCount()
634 > historySizeBytes := executionInfo.GetExecutionStats().GetHistorySize()
635 >
636 > if base.SearchAttributes == nil {
637 base.SearchAttributes = &commonpb.SearchAttributes{
638 IndexedFields: make(map[string]*commonpb.Payload),
639 }
640 > } else if base.SearchAttributes.IndexedFields == nil { visibility_queue_task_executor.go
641 base.SearchAttributes.IndexedFields = make(map[string]*commonpb.Payload)
642 }
643
644 > if t.externalPayloadsEnabled(namespaceEntry.Name().String()) { visibility_queue_task_executor.go
645 > externalPayloadCount := executionInfo.GetExecutionStats().GetExternalPayloadCount()
646 > externalPayloadSizeBytes := executionInfo.GetExecutionStats().GetExternalPayloadSize()
647 > if externalPayloadCount > 0 {
648 externalPayloadCountPayload := sadefs.MustEncodeValue(externalPayloadCount, enumspb.INDEXED_VALUE_TYPE_INT)
649 externalPayloadSizeBytesPayload := sadefs.MustEncodeValue(externalPayloadSizeBytes, enumspb.INDEXED_VALUE_TYPE_INT)
653 }
654
655 > return &manager.RecordWorkflowExecutionClosedRequest{ visibility_queue_task_executor.go
656 > VisibilityRequestBase: base,
657 > CloseTime: wfCloseTime,
658 > ExecutionDuration: wfExecutionDuration,
659 > HistoryLength: historyLength,
660 > HistorySizeBytes: historySizeBytes,
661 > StateTransitionCount: stateTransitionCount,
662 > }, nil
663 }
664
737 func getSearchAttributes(
738 indexedFields map[string]*commonpb.Payload,
739 > ) *commonpb.SearchAttributes { visibility_queue_task_executor.go
740 > if indexedFields == nil {
742 > }
743 > return &commonpb.SearchAttributes{IndexedFields: indexedFields} visibility_queue_task_executor.go
744 }
745
746 > func copyMapPayload(input map[string]*commonpb.Payload) map[string]*commonpb.Payload { visibility_queue_task_executor.go
747 > if input == nil {
749 > }
750 > result := make(map[string]*commonpb.Payload, len(input)) visibility_queue_task_executor.go
751 > for k, v := range input {
752 > result[k] = common.CloneProto(v)
753 > }
754 > return result
755 }
go.temporal.io/server/service/worker/service.go 186 covered LOC · 14 ranges

Open complete file

134 grpcListener net.Listener,
135 healthServer *health.Server,
136 > ) (*Service, error) { service.go
137 > workerServiceResolver, err := membershipMonitor.GetResolver(primitives.WorkerService)
138 > if err != nil {
139 return nil, err
140 }
141
142 > s := &Service{ service.go
143 > config: serviceConfig,
144 > sdkClientFactory: sdkClientFactory,
145 > logger: logger,
146 > clusterMetadata: clusterMetadata,
147 > clientBean: clientBean,
148 > clusterMetadataManager: clusterMetadataManager,
149 > namespaceRegistry: namespaceRegistry,
150 > executionManager: executionManager,
151 > workerServiceResolver: workerServiceResolver,
152 > membershipMonitor: membershipMonitor,
153 > hostInfo: hostInfoProvider.HostInfo(),
154 > namespaceReplicationQueue: namespaceReplicationQueue,
155 > metricsHandler: metricsHandler,
156 > metadataManager: metadataManager,
157 > taskManager: taskManager,
158 > historyClient: historyClient,
159 > visibilityManager: visibilityManager,
160 >
161 > workerManager: workerManager,
162 > perNamespaceWorkerManager: perNamespaceWorkerManager,
163 > matchingClient: matchingClient,
164 > namespaceReplicationTaskExecutor: namespaceReplicationTaskExecutor,
165 >
166 > server: server,
167 > grpcListener: grpcListener,
168 > healthServer: healthServer,
169 > }
170 > if err := s.initScanner(serializer); err != nil {
171 return nil, err
172 }
173 > return s, nil service.go
174 }
175
183 dc *dynamicconfig.Collection,
184 persistenceConfig *config.Persistence,
185 > ) *Config { service.go
186 > config := &Config{
187 > ParentCloseCfg: &parentclosepolicy.Config{
188 > MaxConcurrentActivityExecutionSize: dynamicconfig.WorkerParentCloseMaxConcurrentActivityExecutionSize.Get(dc),
189 > MaxConcurrentWorkflowTaskExecutionSize: dynamicconfig.WorkerParentCloseMaxConcurrentWorkflowTaskExecutionSize.Get(dc),
190 > MaxConcurrentActivityTaskPollers: dynamicconfig.WorkerParentCloseMaxConcurrentActivityTaskPollers.Get(dc),
191 > MaxConcurrentWorkflowTaskPollers: dynamicconfig.WorkerParentCloseMaxConcurrentWorkflowTaskPollers.Get(dc),
192 > NumParentClosePolicySystemWorkflows: dynamicconfig.NumParentClosePolicySystemWorkflows.Get(dc),
193 > },
194 > ScannerCfg: &scanner.Config{
195 > MaxConcurrentActivityExecutionSize: dynamicconfig.WorkerScannerMaxConcurrentActivityExecutionSize.Get(dc),
196 > MaxConcurrentWorkflowTaskExecutionSize: dynamicconfig.WorkerScannerMaxConcurrentWorkflowTaskExecutionSize.Get(dc),
197 > MaxConcurrentActivityTaskPollers: dynamicconfig.WorkerScannerMaxConcurrentActivityTaskPollers.Get(dc),
198 > MaxConcurrentWorkflowTaskPollers: dynamicconfig.WorkerScannerMaxConcurrentWorkflowTaskPollers.Get(dc),
199 >
200 > PersistenceMaxQPS: dynamicconfig.ScannerPersistenceMaxQPS.Get(dc),
201 > Persistence: persistenceConfig,
202 > TaskQueueScannerEnabled: dynamicconfig.TaskQueueScannerEnabled.Get(dc),
203 > BuildIdScavengerEnabled: dynamicconfig.BuildIdScavengerEnabled.Get(dc),
204 > HistoryScannerEnabled: dynamicconfig.HistoryScannerEnabled.Get(dc),
205 > ExecutionsScannerEnabled: dynamicconfig.ExecutionsScannerEnabled.Get(dc),
206 > HistoryScannerDataMinAge: dynamicconfig.HistoryScannerDataMinAge.Get(dc),
207 > HistoryScannerVerifyRetention: dynamicconfig.HistoryScannerVerifyRetention.Get(dc),
208 > ExecutionScannerPerHostQPS: dynamicconfig.ExecutionScannerPerHostQPS.Get(dc),
209 > ExecutionScannerPerShardQPS: dynamicconfig.ExecutionScannerPerShardQPS.Get(dc),
210 > ExecutionDataDurationBuffer: dynamicconfig.ExecutionDataDurationBuffer.Get(dc),
211 > ExecutionScannerWorkerCount: dynamicconfig.ExecutionScannerWorkerCount.Get(dc),
212 > ExecutionScannerHistoryEventIdValidator: dynamicconfig.ExecutionScannerHistoryEventIdValidator.Get(dc),
213 > RemovableBuildIdDurationSinceDefault: dynamicconfig.RemovableBuildIdDurationSinceDefault.Get(dc),
214 > BuildIdScavengerVisibilityRPS: dynamicconfig.BuildIdScavengerVisibilityRPS.Get(dc),
215 >
216 > ScheduleInvariantsScannerOptions: dynamicconfig.ScheduleInvariantsScannerOptions.Get(dc),
217 > },
218 > BatcherRPS: dynamicconfig.BatcherRPS.Get(dc),
219 > BatcherConcurrency: dynamicconfig.BatcherConcurrency.Get(dc),
220 > EnableParentClosePolicyWorker: dynamicconfig.EnableParentClosePolicyWorker.Get(dc),
221 > PerNamespaceWorkerCount: dynamicconfig.WorkerPerNamespaceWorkerCount.Subscribe(dc),
222 > PerNamespaceWorkerOptions: dynamicconfig.WorkerPerNamespaceWorkerOptions.Subscribe(dc),
223 > PerNamespaceWorkerStartRate: dynamicconfig.WorkerPerNamespaceWorkerStartRate.Get(dc),
224 > ThrottledLogRPS: dynamicconfig.WorkerThrottledLogRPS.Get(dc),
225 > PersistenceMaxQPS: dynamicconfig.WorkerPersistenceMaxQPS.Get(dc),
226 > PersistenceGlobalMaxQPS: dynamicconfig.WorkerPersistenceGlobalMaxQPS.Get(dc),
227 > PersistenceNamespaceMaxQPS: dynamicconfig.WorkerPersistenceNamespaceMaxQPS.Get(dc),
228 > PersistenceGlobalNamespaceMaxQPS: dynamicconfig.WorkerPersistenceGlobalNamespaceMaxQPS.Get(dc),
229 > PersistencePerShardNamespaceMaxQPS: dynamicconfig.DefaultPerShardNamespaceRPSMax,
230 > PersistenceDynamicRateLimitingParams: dynamicconfig.WorkerPersistenceDynamicRateLimitingParams.Get(dc),
231 > PersistenceQPSBurstRatio: dynamicconfig.PersistenceQPSBurstRatio.Get(dc),
232 > OperatorRPSRatio: dynamicconfig.OperatorRPSRatio.Get(dc),
233 >
234 > VisibilityPersistenceMaxReadQPS: dynamicconfig.VisibilityPersistenceMaxReadQPS.Get(dc),
235 > VisibilityPersistenceMaxWriteQPS: dynamicconfig.VisibilityPersistenceMaxWriteQPS.Get(dc),
236 > VisibilityPersistenceSlowQueryThreshold: dynamicconfig.VisibilityPersistenceSlowQueryThreshold.Get(dc),
237 > EnableReadFromSecondaryVisibility: dynamicconfig.EnableReadFromSecondaryVisibility.Get(dc),
238 > VisibilityEnableShadowReadMode: dynamicconfig.VisibilityEnableShadowReadMode.Get(dc),
239 > VisibilityDisableOrderByClause: dynamicconfig.VisibilityDisableOrderByClause.Get(dc),
240 > VisibilityEnableManualPagination: dynamicconfig.VisibilityEnableManualPagination.Get(dc),
241 > VisibilityEnableUnifiedQueryConverter: dynamicconfig.VisibilityEnableUnifiedQueryConverter.Get(dc),
242 > }
243 > return config
244 > }
245
246 // Start is called to start the service
247 > func (s *Service) Start() { service.go
248 > s.logger.Info(
249 > "worker starting",
250 > tag.ComponentWorker,
251 > )
252 >
253 > metrics.RestartCount.With(s.metricsHandler).Record(1)
254 >
255 > s.membershipMonitor.Start()
256 >
257 > s.ensureSystemNamespaceExists(context.TODO())
258 > s.startScanner()
259 >
260 > if s.clusterMetadata.IsGlobalNamespaceEnabled() {
261 s.startReplicator()
262 }
263 > if s.config.EnableParentClosePolicyWorker() { service.go
264 > s.startParentClosePolicyProcessor()
265 > }
266
267 > s.workerManager.Start() service.go
268 > s.perNamespaceWorkerManager.Start(
269 > // TODO: get these from fx instead of passing through Start
270 > s.hostInfo,
271 > s.workerServiceResolver,
272 > )
273 >
274 > healthpb.RegisterHealthServer(s.server, s.healthServer)
275 > s.healthServer.SetServingStatus(ServiceName, healthpb.HealthCheckResponse_SERVING)
276 >
277 > reflection.Register(s.server)
278 >
279 > go func() {
280 > s.logger.Info("Starting to serve on worker listener")
281 > if err := s.server.Serve(s.grpcListener); err != nil {
282 s.logger.Fatal("Failed to serve on worker listener", tag.Error(err))
283 }
284 }()
285
286 > s.logger.Info( service.go
287 > "worker service started",
288 > tag.ComponentWorker,
289 > tag.Address(s.hostInfo.GetAddress()),
290 > )
291 }
292
293 // Stop is called to stop the service
294 > func (s *Service) Stop() { service.go
295 > s.healthServer.SetServingStatus(ServiceName, healthpb.HealthCheckResponse_NOT_SERVING)
296 >
297 > s.scanner.Stop()
298 > s.perNamespaceWorkerManager.Stop()
299 > s.workerManager.Stop()
300 > s.visibilityManager.Close()
301 >
302 > s.server.GracefulStop()
303 >
304 > s.logger.Info(
305 > "worker service stopped",
306 > tag.ComponentWorker,
307 > tag.Address(s.hostInfo.GetAddress()),
308 > )
309 > }
310
311 > func (s *Service) startParentClosePolicyProcessor() { service.go
312 > params := &parentclosepolicy.BootstrapParams{
313 > Config: *s.config.ParentCloseCfg,
314 > SdkClientFactory: s.sdkClientFactory,
315 > MetricsHandler: s.metricsHandler,
316 > Logger: s.logger,
317 > ClientBean: s.clientBean,
318 > CurrentCluster: s.clusterMetadata.GetCurrentClusterName(),
319 > HostInfo: s.hostInfo,
320 > }
321 > processor := parentclosepolicy.New(params)
322 > if err := processor.Start(); err != nil {
323 s.logger.Fatal(
324 "error starting parentclosepolicy processor",
328 }
329
330 > func (s *Service) initScanner(serializer serialization.Serializer) error { service.go
331 > currentCluster := s.clusterMetadata.GetCurrentClusterName()
332 > adminClient, err := s.clientBean.GetRemoteAdminClient(currentCluster)
333 > if err != nil {
334 return err
335 }
336 > s.scanner = scanner.New( service.go
337 > s.logger,
338 > s.config.ScannerCfg,
339 > s.sdkClientFactory,
340 > s.metricsHandler,
341 > s.executionManager,
342 > s.metadataManager,
343 > s.visibilityManager,
344 > s.taskManager,
345 > s.historyClient,
346 > adminClient,
347 > s.matchingClient,
348 > s.namespaceRegistry,
349 > currentCluster,
350 > s.hostInfo,
351 > serializer,
352 > )
353 > return nil
354 }
355
356 > func (s *Service) startScanner() { service.go
357 > if err := s.scanner.Start(); err != nil {
358 s.logger.Fatal(
359 "error starting scanner",
384 func (s *Service) ensureSystemNamespaceExists(
385 ctx context.Context,
386 > ) { service.go
387 > _, err := s.metadataManager.GetNamespace(ctx, &persistence.GetNamespaceRequest{Name: primitives.SystemLocalNamespace})
388 > switch err.(type) {
389 > case nil:
390 // noop
391 case *serviceerror.NamespaceNotFound:
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/execution.go 183 covered LOC · 42 ranges

Open complete file

186 ctx context.Context,
187 row *sqlplugin.ExecutionsRow,
188 > ) (sql.Result, error) { execution.go
189 > return mdb.conn.NamedExecContext(ctx,
190 > createExecutionQuery,
191 > row,
192 > )
193 > }
194
195 // UpdateExecutions updates a single row in executions table
197 ctx context.Context,
198 row *sqlplugin.ExecutionsRow,
199 > ) (sql.Result, error) { execution.go
200 > return mdb.conn.NamedExecContext(ctx,
201 > updateExecutionQuery,
202 > row,
203 > )
204 > }
205
206 // SelectFromExecutions reads a single row from executions table
208 ctx context.Context,
209 filter sqlplugin.ExecutionsFilter,
210 > ) (*sqlplugin.ExecutionsRow, error) { execution.go
211 > var row sqlplugin.ExecutionsRow
212 > err := mdb.conn.GetContext(ctx,
213 > &row, getExecutionQuery,
214 > filter.ShardID,
215 > filter.NamespaceID,
216 > filter.WorkflowID,
217 > filter.RunID,
218 > )
219 > if err != nil {
220 return nil, err
221 }
222 > return &row, err execution.go
223 }
224
258 ctx context.Context,
259 filter sqlplugin.ExecutionsFilter,
260 > ) (int64, int64, error) { execution.go
261 > var executionVersion sqlplugin.ExecutionVersion
262 > err := mdb.conn.GetContext(ctx,
263 > &executionVersion,
264 > writeLockExecutionQuery,
265 > filter.ShardID,
266 > filter.NamespaceID,
267 > filter.WorkflowID,
268 > filter.RunID,
269 > )
270 > return executionVersion.DBRecordVersion, executionVersion.NextEventID, err
271 > }
272
273 // InsertIntoCurrentExecutions inserts a single row into current_executions table
275 ctx context.Context,
276 row *sqlplugin.CurrentExecutionsRow,
277 > ) (sql.Result, error) { execution.go
278 > if err := mdb.assertArchetypeIDSpecified(row.ArchetypeID); err != nil {
279 return nil, err
280 }
281
282 > if row.ArchetypeID == chasm.WorkflowArchetypeID { execution.go
283 > return mdb.conn.NamedExecContext(ctx, execution.go
284 > createCurrentExecutionQuery,
285 > row,
286 > )
287 > }
288
289 return mdb.conn.NamedExecContext(ctx,
297 ctx context.Context,
298 row *sqlplugin.CurrentExecutionsRow,
299 > ) (sql.Result, error) { execution.go
300 > if err := mdb.assertArchetypeIDSpecified(row.ArchetypeID); err != nil {
301 return nil, err
302 }
303
304 > if row.ArchetypeID == chasm.WorkflowArchetypeID { execution.go
305 > return mdb.conn.NamedExecContext(ctx, execution.go
306 > updateCurrentExecutionsQuery,
307 > row,
308 > )
309 > }
310
311 return mdb.conn.NamedExecContext(ctx,
383 ctx context.Context,
384 filter sqlplugin.CurrentExecutionsFilter,
385 > ) (*sqlplugin.CurrentExecutionsRow, error) { execution.go
386 > var row sqlplugin.CurrentExecutionsRow
387 > var err error
388 >
389 > if err := mdb.assertArchetypeIDSpecified(filter.ArchetypeID); err != nil {
390 return nil, err
391 }
392
393 > if filter.ArchetypeID == chasm.WorkflowArchetypeID { execution.go
394 > err = mdb.conn.GetContext(ctx, execution.go
395 > &row,
396 > lockCurrentExecutionQuery,
397 > filter.ShardID,
398 > filter.NamespaceID,
399 > filter.WorkflowID,
400 > )
401 > } else { execution.go
402 err = mdb.conn.GetContext(ctx,
403 &row,
410 }
411
412 > row.ArchetypeID = filter.ArchetypeID execution.go
413 > return &row, err
414 }
415
419 ctx context.Context,
420 filter sqlplugin.CurrentExecutionsFilter,
421 > ) (rows []sqlplugin.CurrentExecutionsRow, err error) { execution.go
422 > if err := mdb.assertArchetypeIDSpecified(filter.ArchetypeID); err != nil {
423 return nil, err
424 }
425
426 > if filter.ArchetypeID == chasm.WorkflowArchetypeID { execution.go
427 > err = mdb.conn.SelectContext(ctx, execution.go
428 > &rows,
429 > lockCurrentExecutionJoinExecutionsQuery,
430 > filter.ShardID,
431 > filter.NamespaceID,
432 > filter.WorkflowID,
433 > )
434 > } else { execution.go
435 err = mdb.conn.SelectContext(ctx,
436 &rows,
443 }
444
445 > for i := range rows { execution.go
446 rows[i].ArchetypeID = filter.ArchetypeID
447 }
448 > return rows, err execution.go
449 }
450
464 ctx context.Context,
465 filter sqlplugin.HistoryImmediateTasksRangeFilter,
466 > ) ([]sqlplugin.HistoryImmediateTasksRow, error) { execution.go
467 > var rows []sqlplugin.HistoryImmediateTasksRow
468 > if err := mdb.conn.SelectContext(ctx,
469 > &rows,
470 > getHistoryImmediateTasksQuery,
471 > filter.ShardID,
472 > filter.CategoryID,
473 > filter.InclusiveMinTaskID,
474 > filter.ExclusiveMaxTaskID,
475 > filter.PageSize,
476 > ); err != nil {
477 return nil, err
478 }
479 > return rows, nil execution.go
480 }
481
526 ctx context.Context,
527 filter sqlplugin.HistoryScheduledTasksRangeFilter,
528 > ) ([]sqlplugin.HistoryScheduledTasksRow, error) { execution.go
529 > var rows []sqlplugin.HistoryScheduledTasksRow
530 > filter.InclusiveMinVisibilityTimestamp = mdb.converter.ToSQLiteDateTime(filter.InclusiveMinVisibilityTimestamp)
531 > filter.ExclusiveMaxVisibilityTimestamp = mdb.converter.ToSQLiteDateTime(filter.ExclusiveMaxVisibilityTimestamp)
532 > if err := mdb.conn.SelectContext(ctx,
533 > &rows,
534 > getHistoryScheduledTasksQuery,
535 > filter.ShardID,
536 > filter.CategoryID,
537 > filter.InclusiveMinVisibilityTimestamp,
538 > filter.InclusiveMinTaskID,
539 > filter.InclusiveMinVisibilityTimestamp,
540 > filter.ExclusiveMaxVisibilityTimestamp,
541 > filter.PageSize,
542 > ); err != nil {
543 return nil, err
544 }
545 > for i := range rows { execution.go
546 rows[i].VisibilityTimestamp = mdb.converter.ToSQLiteDateTime(rows[i].VisibilityTimestamp)
547 }
548 > return rows, nil execution.go
549 }
550
584 ctx context.Context,
585 rows []sqlplugin.TransferTasksRow,
586 > ) (sql.Result, error) { execution.go
587 > return mdb.conn.NamedExecContext(ctx,
588 > createTransferTasksQuery,
589 > rows,
590 > )
591 > }
592
593 // RangeSelectFromTransferTasks reads one or more rows from transfer_tasks table
595 ctx context.Context,
596 filter sqlplugin.TransferTasksRangeFilter,
597 > ) ([]sqlplugin.TransferTasksRow, error) { execution.go
598 > var rows []sqlplugin.TransferTasksRow
599 > if err := mdb.conn.SelectContext(ctx,
600 > &rows,
601 > getTransferTasksQuery,
602 > filter.ShardID,
603 > filter.InclusiveMinTaskID,
604 > filter.ExclusiveMaxTaskID,
605 > filter.PageSize,
606 > ); err != nil {
607 return nil, err
608 }
609 > return rows, nil execution.go
610 }
611
639 ctx context.Context,
640 rows []sqlplugin.TimerTasksRow,
641 > ) (sql.Result, error) { execution.go
642 > for i := range rows {
643 > rows[i].VisibilityTimestamp = mdb.converter.ToSQLiteDateTime(rows[i].VisibilityTimestamp)
644 > }
645 > return mdb.conn.NamedExecContext(
646 > ctx,
647 > createTimerTasksQuery,
648 > rows,
649 > )
650 }
651
654 ctx context.Context,
655 filter sqlplugin.TimerTasksRangeFilter,
656 > ) ([]sqlplugin.TimerTasksRow, error) { execution.go
657 > var rows []sqlplugin.TimerTasksRow
658 > filter.InclusiveMinVisibilityTimestamp = mdb.converter.ToSQLiteDateTime(filter.InclusiveMinVisibilityTimestamp)
659 > filter.ExclusiveMaxVisibilityTimestamp = mdb.converter.ToSQLiteDateTime(filter.ExclusiveMaxVisibilityTimestamp)
660 > if err := mdb.conn.SelectContext(ctx,
661 > &rows,
662 > getTimerTasksQuery,
663 > filter.ShardID,
664 > filter.InclusiveMinVisibilityTimestamp,
665 > filter.InclusiveMinTaskID,
666 > filter.InclusiveMinVisibilityTimestamp,
667 > filter.ExclusiveMaxVisibilityTimestamp,
668 > filter.PageSize,
669 > ); err != nil {
670 return nil, err
671 }
672 > for i := range rows { execution.go
673 rows[i].VisibilityTimestamp = mdb.converter.FromSQLiteDateTime(rows[i].VisibilityTimestamp)
674 }
675 > return rows, nil execution.go
676 }
677
720 ctx context.Context,
721 filter sqlplugin.BufferedEventsFilter,
722 > ) ([]sqlplugin.BufferedEventsRow, error) { execution.go
723 > var rows []sqlplugin.BufferedEventsRow
724 > if err := mdb.conn.SelectContext(ctx,
725 > &rows,
726 > getBufferedEventsQuery,
727 > filter.ShardID,
728 > filter.NamespaceID,
729 > filter.WorkflowID,
730 > filter.RunID,
731 > ); err != nil {
732 return nil, err
733 }
734 > for i := 0; i < len(rows); i++ { execution.go
735 rows[i].NamespaceID = filter.NamespaceID
736 rows[i].WorkflowID = filter.WorkflowID
738 rows[i].ShardID = filter.ShardID
739 }
740 > return rows, nil execution.go
741 }
742
869 ctx context.Context,
870 rows []sqlplugin.VisibilityTasksRow,
871 > ) (sql.Result, error) { execution.go
872 > return mdb.conn.NamedExecContext(ctx,
873 > createVisibilityTasksQuery,
874 > rows,
875 > )
876 > }
877
878 // RangeSelectFromVisibilityTasks reads one or more rows from visibility_tasks table
880 ctx context.Context,
881 filter sqlplugin.VisibilityTasksRangeFilter,
882 > ) ([]sqlplugin.VisibilityTasksRow, error) { execution.go
883 > var rows []sqlplugin.VisibilityTasksRow
884 > if err := mdb.conn.SelectContext(ctx,
885 > &rows,
886 > getVisibilityTasksQuery,
887 > filter.ShardID,
888 > filter.InclusiveMinTaskID,
889 > filter.ExclusiveMaxTaskID,
890 > filter.PageSize,
891 > ); err != nil {
892 return nil, err
893 }
894 > return rows, nil execution.go
895 }
896
920 }
921
922 > func (mdb *db) assertArchetypeIDSpecified(archetypeID chasm.ArchetypeID) error { execution.go
923 > if archetypeID == chasm.UnspecifiedArchetypeID {
924 return softassert.UnexpectedInternalErr(mdb.logger, "ArchetypeID not specified", nil)
925 }
926 > return nil execution.go
927 }
go.temporal.io/server/service/history/api/recordworkflowtaskstarted/api.go 181 covered LOC · 35 ranges

Open complete file

41 persistenceVisibilityMgr manager.VisibilityManager,
42 workflowConsistencyChecker api.WorkflowConsistencyChecker,
43 > ) (*historyservice.RecordWorkflowTaskStartedResponseWithRawHistory, error) { api.go
44 > namespaceEntry, err := api.GetActiveNamespace(shardContext, namespace.ID(req.GetNamespaceId()), req.WorkflowExecution.WorkflowId)
45 > if err != nil {
46 return nil, err
47 }
48
49 > scheduledEventID := req.GetScheduledEventId() api.go
50 > requestID := req.GetRequestId()
51 >
52 > var workflowKey definition.WorkflowKey
53 > var resp *historyservice.RecordWorkflowTaskStartedResponseWithRawHistory
54 >
55 > err = api.GetAndUpdateWorkflowWithNew(
56 > ctx,
57 > req.Clock,
58 > definition.NewWorkflowKey(
59 > req.NamespaceId,
60 > req.WorkflowExecution.WorkflowId,
61 > req.WorkflowExecution.RunId,
62 > ),
63 > func(workflowLease api.WorkflowLease) (res *api.UpdateWorkflowAction, retErr error) {
64 > mutableState := workflowLease.GetMutableState() api.go
65 > if !mutableState.IsWorkflowExecutionRunning() {
66 return nil, consts.ErrWorkflowCompleted
67 }
68
69 > workflowTask := mutableState.GetWorkflowTaskByID(scheduledEventID) api.go
70 > if workflowTask == nil {
71 // This can happen if (one of):
72 // - WFT is already completed as a result of another call (safe to drop this WFT),
74 return nil, serviceerror.NewNotFound("Workflow task not found.")
75 }
76 > if req.GetStamp() != mutableState.GetExecutionInfo().GetWorkflowTaskStamp() { api.go
77 // This happens when the workflow task was rescheduled.
78 return nil, serviceerrors.NewObsoleteMatchingTask("Workflow task stamp mismatch")
79 }
80
81 > metricsScope := shardContext.GetMetricsHandler().WithTags(metrics.OperationTag(metrics.HistoryRecordWorkflowTaskStartedScope)) api.go
82 >
83 > // Check to see if mutable cache is stale in some extreme cassandra failure cases.
84 > // For speculative and transient WFT scheduledEventID is always ahead of NextEventID.
85 > // Because there is a clock check above the stack, this should never happen.
86 > transientWFT := workflowTask.Attempt > 1
87 > if workflowTask.Type != enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE && !transientWFT &&
88 > scheduledEventID >= mutableState.GetNextEventID() {
89
90 metrics.StaleMutableStateCounter.With(metricsScope).Record(1)
92 }
93
94 > workflowKey = mutableState.GetWorkflowKey() api.go
95 > updateAction := &api.UpdateWorkflowAction{}
96 > updateRegistry := workflowLease.GetContext().UpdateRegistry(ctx)
97 >
98 > if workflowTask.StartedEventID != common.EmptyEventID {
99 // If workflow task is started as part of the current request scope then return a positive response
100 if workflowTask.RequestID == requestID {
119 // The stickiness info is used by frontend to decide if it should send down partial history or full history.
120 // Sending down partial history will cost the worker an extra fetch to server for the full history.
121 > currentTaskQueue := mutableState.CurrentTaskQueue() api.go
122 > pollerTaskQueue := req.PollRequest.TaskQueue
123 > if currentTaskQueue.Kind == enumspb.TASK_QUEUE_KIND_STICKY &&
124 > currentTaskQueue.GetName() != pollerTaskQueue.GetName() {
125 // For versioned workflows we additionally check for the poller queue to not be a sticky queue itself.
126 // Although it's ideal to check this for unversioned workflows as well, we can't rely on older clients
136 }
137
138 > if currentTaskQueue.Kind == enumspb.TASK_QUEUE_KIND_NORMAL && api.go
139 > pollerTaskQueue.Kind == enumspb.TASK_QUEUE_KIND_STICKY {
140 // A poll from a sticky queue while the workflow's task queue is not yet sticky
141 // should be rejected. This means the task was a stale task on the matching queue.
149 }
150
151 > wfBehavior := mutableState.GetEffectiveVersioningBehavior() api.go
152 > wfDeployment := mutableState.GetEffectiveDeployment()
153 > //nolint:staticcheck // SA1019 deprecated WorkerVersionCapabilities will clean up later
154 > pollerDeployment, err := worker_versioning.DeploymentFromCapabilities(req.PollRequest.WorkerVersionCapabilities, req.PollRequest.DeploymentOptions)
155 > if err != nil {
156 return nil, err
157 }
158 > err = worker_versioning.ValidateTaskVersionDirective(req.GetVersionDirective(), wfBehavior, wfDeployment, req.ScheduledDeployment) api.go
159 > if err != nil {
160 return nil, err
161 }
162
163 > _, workflowTask, err = mutableState.AddWorkflowTaskStartedEvent( api.go
164 > scheduledEventID,
165 > requestID,
166 > pollerTaskQueue,
167 > req.PollRequest.Identity,
168 > worker_versioning.StampFromCapabilities(req.PollRequest.WorkerVersionCapabilities, req.PollRequest.DeploymentOptions), //nolint:staticcheck // SA1019: WorkerVersionCapabilities is deprecated but still used for old versioning [cleanup-old-wv]
169 > req.GetBuildIdRedirectInfo(),
170 > workflowLease.GetContext().UpdateRegistry(ctx),
171 > false,
172 > req.TargetDeploymentVersion,
173 > req.TaskDispatchRevisionNumber,
174 > )
175 > if err != nil {
176 // Unable to add WorkflowTaskStarted event to history
177 return nil, err
178 }
179
180 > if workflowTask.Type == enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE { api.go
181 updateAction.Noop = true
182 > } else { api.go
183 > // If the wft is speculative MS changes are not persisted, so the possibly started api.go
184 > // transition by the StartDeploymentTransition call above won't be persisted. This is OK
185 > // because once the speculative task completes the transition will be applied
186 > // automatically based on wft completion info. If the speculative task fails or times
187 > // out, future wft will be redirected by matching again and the transition will
188 > // eventually happen. If an activity starts while the speculative is also started on the
189 > // new deployment, the activity will cause the transition to be created and persisted in
190 > // the MS.
191 > if !pollerDeployment.Equal(wfDeployment) {
192 // Dispatching to a different deployment. Try starting a transition. Starting the
193 // transition AFTER applying the start event because we don't want this pending
206 }
207
208 > workflowScheduleToStartLatency := workflowTask.StartedTime.Sub(workflowTask.ScheduledTime) api.go
209 > namespaceName := namespaceEntry.Name()
210 > tqPartition := tqid.UnsafePartitionFromProto(workflowTask.TaskQueue, req.GetNamespaceId(), enumspb.TASK_QUEUE_TYPE_WORKFLOW)
211 > metrics.TaskScheduleToStartLatency.With(
212 > metrics.GetPerTaskQueuePartitionTypeScope(
213 > metricsScope,
214 > namespaceName.String(),
215 > tqPartition,
216 > config.BreakdownMetricsByTaskQueue(namespaceName.String(), tqPartition.TaskQueue().Name(), enumspb.TASK_QUEUE_TYPE_WORKFLOW),
217 > ),
218 > ).Record(workflowScheduleToStartLatency)
219 >
220 > resp, err = CreateRecordWorkflowTaskStartedResponseWithRawHistory(
221 > ctx,
222 > mutableState,
223 > updateRegistry,
224 > workflowTask,
225 > req.PollRequest.GetIdentity(),
226 > false,
227 > )
228 > if err != nil {
229 return nil, err
230 }
231
232 > return updateAction, nil api.go
233 },
234 nil,
237 )
238
239 > if err != nil { api.go
240 return nil, err
241 }
242
243 > maxHistoryPageSize := int32(config.HistoryMaxPageSize(namespaceEntry.Name().String())) api.go
244 > err = setHistoryForRecordWfTaskStartedResp(
245 > ctx,
246 > shardContext,
247 > workflowKey,
248 > namespaceEntry.Name(),
249 > maxHistoryPageSize,
250 > workflowConsistencyChecker,
251 > eventNotifier,
252 > persistenceVisibilityMgr,
253 > resp,
254 > )
255 > if err != nil {
256 return nil, err
257 }
258 > return resp, nil api.go
259 }
260
269 persistenceVisibilityMgr manager.VisibilityManager,
270 response *historyservice.RecordWorkflowTaskStartedResponseWithRawHistory,
271 > ) (retError error) { api.go
272 >
273 > firstEventID := common.FirstEventID
274 > nextEventID := response.GetNextEventId()
275 > if response.GetStickyExecutionEnabled() {
276 // sticky tasks only need partial history
277 firstEventID = response.GetPreviousStartedEventId() + 1
281 // when data inconsistency occurs
282 // long term solution should check event batch pointing backwards within history store
283 > defer func() { api.go
284 > var dataLossErr *serviceerror.DataLoss
285 > if errors.As(retError, &dataLossErr) {
286 api.TrimHistoryNode(
287 ctx,
296 }()
297
298 > isInternalRawHistoryEnabled := shardContext.GetConfig().SendRawHistoryBetweenInternalServices() api.go
299 > var rawHistory []*commonpb.DataBlob
300 > var persistenceToken []byte
301 > var history *historypb.History
302 > var err error
303 > if isInternalRawHistoryEnabled {
304 rawHistory, persistenceToken, err = api.GetRawHistory(
305 ctx,
315 response.GetBranchToken(),
316 )
317 > } else { api.go
318 > history, persistenceToken, err = api.GetHistory( api.go
319 > ctx,
320 > shardContext,
321 > namespaceName,
322 > namespace.ID(workflowKey.GetNamespaceID()),
323 > &commonpb.WorkflowExecution{WorkflowId: workflowKey.GetWorkflowID(), RunId: workflowKey.GetRunID()},
324 > firstEventID,
325 > nextEventID,
326 > maximumPageSize,
327 > nil,
328 > response.GetTransientWorkflowTask(),
329 > response.GetBranchToken(),
330 > persistenceVisibilityMgr,
331 > )
332 > }
333 > if err != nil { api.go
334 return err
335 }
336
337 > var continuation []byte api.go
338 > if len(persistenceToken) != 0 {
339 continuation, err = api.SerializeHistoryToken(&tokenspb.HistoryContinuation{
340 RunId: workflowKey.GetRunID(),
348 }
349 }
350 > if isInternalRawHistoryEnabled { api.go
351 historyBlobs := make([][]byte, len(rawHistory))
352 for i, blob := range rawHistory {
358 response.RawHistory = historyBlobs //nolint:staticcheck // SA1019: Using deprecated field for backwards compatibility during rollout
359 }
360 > } else { api.go
361 > response.History = history
362 > }
363 > response.NextPageToken = continuation api.go
364 > return nil
365 }
366
405 identity string,
406 wtHeartbeat bool,
407 > ) (*historyservice.RecordWorkflowTaskStartedResponseWithRawHistory, error) { api.go
408 > response := &historyservice.RecordWorkflowTaskStartedResponseWithRawHistory{}
409 > response.WorkflowType = ms.GetWorkflowType()
410 > executionInfo := ms.GetExecutionInfo()
411 > if executionInfo.LastCompletedWorkflowTaskStartedEventId != common.EmptyEventID {
412 response.PreviousStartedEventId = executionInfo.LastCompletedWorkflowTaskStartedEventId
413 }
415 // Starting workflowTask could result in different scheduledEventID if workflowTask was transient and new events came in
416 // before it was started.
417 > response.ScheduledEventId = workflowTask.ScheduledEventID api.go
418 > response.StartedEventId = workflowTask.StartedEventID
419 > response.StickyExecutionEnabled = ms.IsStickyTaskQueueSet()
420 > response.NextEventId = ms.GetNextEventID()
421 > response.Attempt = workflowTask.Attempt
422 > response.WorkflowExecutionTaskQueue = &taskqueuepb.TaskQueue{
423 > Name: executionInfo.TaskQueue,
424 > Kind: enumspb.TASK_QUEUE_KIND_NORMAL,
425 > }
426 > response.ScheduledTime = timestamppb.New(workflowTask.ScheduledTime)
427 > response.StartedTime = timestamppb.New(workflowTask.StartedTime)
428 > response.Version = workflowTask.Version
429 >
430 > // TODO (alex-update): Transient needs to be renamed to "TransientOrSpeculative"
431 > response.TransientWorkflowTask = ms.GetTransientWorkflowTaskInfo(workflowTask, identity)
432 >
433 > currentBranchToken, err := ms.GetCurrentBranchToken()
434 > if err != nil {
435 return nil, err
436 }
437 > response.BranchToken = currentBranchToken api.go
438 >
439 > qr := ms.GetQueryRegistry()
440 > bufferedQueryIDs := qr.GetBufferedIDs()
441 > if len(bufferedQueryIDs) > 0 {
442 response.Queries = make(map[string]*querypb.WorkflowQuery, len(bufferedQueryIDs))
443 for _, bufferedQueryID := range bufferedQueryIDs {
455 // Resend these updates if this is not a heartbeat WT (includeAlreadySent = !wtHeartbeat).
456 // Heartbeat WT delivers only new updates that come while this WT was running (similar to queries and buffered events).
457 > response.Messages = updateRegistry.Send(ctx, !wtHeartbeat, workflowTask.StartedEventID) api.go
458 >
459 > if workflowTask.Type == enumsspb.WORKFLOW_TASK_TYPE_SPECULATIVE && len(response.GetMessages()) == 0 {
460 return nil, serviceerror.NewNotFound("No messages for speculative workflow task.")
461 }
462
463 > return response, nil api.go
464 }
go.temporal.io/server/common/tqid/task_queue_id.go 174 covered LOC · 61 ranges

Open complete file

128 // NewTaskQueueFamily takes a user-provided task queue name (aka family name) and returns a TaskQueueFamily. Returns an
129 // error if name looks like a mangled name.
130 > func NewTaskQueueFamily(namespaceId string, name string) (*TaskQueueFamily, error) { task_queue_id.go
131 > if strings.HasPrefix(name, nonRootPartitionPrefix) {
132 return nil, serviceerror.NewInvalidArgument("task queue family name cannot have prefix /_sys/ " + name)
133 }
134 > return &TaskQueueFamily{ task_queue_id.go
135 > namespaceId: namespaceId,
136 > name: name,
137 > }, nil
138 }
139
140 // UnsafeTaskQueueFamily returns a TaskQueueFamily object without validating the task queue name.
141 // This method should only be used in logs/metrics, not in the server logic (use NewTaskQueueFamily instead).
142 > func UnsafeTaskQueueFamily(namespaceId string, name string) *TaskQueueFamily { task_queue_id.go
143 > return &TaskQueueFamily{namespaceId, name}
144 > }
145
146 // UnsafePartitionFromProto tries parsing proto using PartitionFromProto but if it fails still returns a Partition
147 // object using the raw values in the proto.
148 // This method should only be used in logs/metrics, not in the server logic.
149 > func UnsafePartitionFromProto(proto *taskqueuepb.TaskQueue, namespaceId string, taskType enumspb.TaskQueueType) Partition { task_queue_id.go
150 > p, err := PartitionFromProto(proto, namespaceId, taskType)
151 > if err == nil {
152 > return p
153 > }
154 switch proto.GetKind() { //nolint:exhaustive
155 case enumspb.TASK_QUEUE_KIND_STICKY:
165 }
166
167 > func PartitionFromProto(proto *taskqueuepb.TaskQueue, namespaceId string, taskType enumspb.TaskQueueType) (Partition, error) { task_queue_id.go
168 > baseName, partition, err := parseRpcName(proto.GetName())
169 > if err != nil {
170 return nil, err
171 }
172
173 > kind := proto.GetKind() task_queue_id.go
174 > normalName := proto.GetNormalName()
175 > if normalName != "" && kind != enumspb.TASK_QUEUE_KIND_STICKY {
176 return nil, serviceerror.NewInvalidArgumentf("only sticky queues can have normal name. tq: %s, normal name: %s", baseName, normalName)
177 }
178
179 > switch kind { task_queue_id.go
180 > case enumspb.TASK_QUEUE_KIND_STICKY: task_queue_id.go
181 > if partition != 0 {
182 return nil, fmt.Errorf("%w. base name: %s, normal name: %s", ErrNonZeroSticky, baseName, normalName)
183 }
184 > tq := &TaskQueue{TaskQueueFamily{namespaceId, normalName}, taskType} task_queue_id.go
185 > return tq.StickyPartition(baseName), nil
186 case enumspb.TASK_QUEUE_KIND_WORKER_COMMANDS:
187 if partition != 0 {
193 tq := &TaskQueue{TaskQueueFamily{namespaceId, baseName}, taskType}
194 return tq.WorkerCommandsPartition(), nil
195 > default: task_queue_id.go
196 > tq := &TaskQueue{TaskQueueFamily{namespaceId, baseName}, taskType}
197 > return tq.NormalPartition(partition), nil
198 }
199 }
200
201 > func PartitionFromPartitionProto(proto *taskqueuespb.TaskQueuePartition, namespaceId string) Partition { task_queue_id.go
202 > tq := &TaskQueue{TaskQueueFamily{namespaceId, proto.GetTaskQueue()}, proto.GetTaskQueueType()}
203 > switch proto.GetPartitionId().(type) {
204 case *taskqueuespb.TaskQueuePartition_StickyName:
205 return tq.StickyPartition(proto.GetStickyName())
206 case *taskqueuespb.TaskQueuePartition_WorkerCommands:
207 return tq.WorkerCommandsPartition()
208 > default: task_queue_id.go
209 > return tq.NormalPartition(int(proto.GetNormalPartitionId()))
210 }
211 }
212
213 > func NormalPartitionFromRpcName(rpcName string, namespaceId string, taskType enumspb.TaskQueueType) (*NormalPartition, error) { task_queue_id.go
214 > baseName, partition, err := parseRpcName(rpcName)
215 > if err != nil {
216 return nil, err
217 }
218 > tq := &TaskQueue{TaskQueueFamily{namespaceId, baseName}, taskType} task_queue_id.go
219 > return tq.NormalPartition(partition), nil
220 }
221
222 > func MustNormalPartitionFromRpcName(rpcName string, namespaceId string, taskType enumspb.TaskQueueType) *NormalPartition { task_queue_id.go
223 > p, err := NormalPartitionFromRpcName(rpcName, namespaceId, taskType)
224 > if err != nil {
225 panic(err)
226 }
227 > return p task_queue_id.go
228 }
229
230 > func (n *TaskQueueFamily) Name() string { task_queue_id.go
231 > return n.name
232 > }
233
234 > func (n *TaskQueueFamily) NamespaceId() string { task_queue_id.go
235 > return n.namespaceId
236 > }
237
238 > func (n *TaskQueueFamily) TaskQueue(taskType enumspb.TaskQueueType) *TaskQueue { task_queue_id.go
239 > return &TaskQueue{
240 > family: *n,
241 > taskType: taskType,
242 > }
243 > }
244
245 > func (n *TaskQueue) Name() string { task_queue_id.go
246 > return n.family.Name()
247 > }
248
249 > func (n *TaskQueue) Family() *TaskQueueFamily { task_queue_id.go
250 > return &n.family
251 > }
252
253 > func (n *TaskQueue) NamespaceId() string { task_queue_id.go
254 > return n.family.NamespaceId()
255 > }
256
257 > func (n *TaskQueue) TaskType() enumspb.TaskQueueType { task_queue_id.go
258 > return n.taskType
259 > }
260
261 > func (n *TaskQueue) NormalPartition(partitionId int) *NormalPartition { task_queue_id.go
262 > return &NormalPartition{
263 > taskQueue: n,
264 > partitionId: partitionId,
265 > }
266 > }
267
268 > func (n *TaskQueue) StickyPartition(stickyName string) *StickyPartition { task_queue_id.go
269 > return &StickyPartition{stickyName, n}
270 > }
271
272 func (n *TaskQueue) WorkerCommandsPartition() *WorkerCommandsPartition {
274 }
275
276 > func (n *TaskQueue) RootPartition() *NormalPartition { task_queue_id.go
277 > return n.NormalPartition(0)
278 > }
279
280 > func (s *StickyPartition) StickyName() string { task_queue_id.go
281 > return s.stickyName
282 > }
283
284 > func (s *StickyPartition) TaskType() enumspb.TaskQueueType { task_queue_id.go
285 > return s.taskQueue.TaskType()
286 > }
287
288 > func (s *StickyPartition) Kind() enumspb.TaskQueueKind { task_queue_id.go
289 > return enumspb.TASK_QUEUE_KIND_STICKY
290 > }
291
292 > func (s *StickyPartition) NamespaceId() string { task_queue_id.go
293 > return s.taskQueue.family.NamespaceId()
294 > }
295
296 func (s *StickyPartition) RootPartition() Partition {
298 }
299
300 > func (s *StickyPartition) TaskQueue() *TaskQueue { task_queue_id.go
301 > return s.taskQueue
302 > }
303
304 > func (s *StickyPartition) IsRoot() bool { task_queue_id.go
305 > return false
306 > }
307
308 > func (s *StickyPartition) IsChild() bool { task_queue_id.go
309 > return false
310 > }
311
312 > func (s *StickyPartition) PersistenceTTL() time.Duration { return 24 * time.Hour } task_queue_id.go
313 > func (s *StickyPartition) SupportsFairness() bool { return false } task_queue_id.go
314 func (s *StickyPartition) SupportsVersioning() bool { return false }
315 func (s *StickyPartition) SupportsPartitions() bool { return false }
316 > func (s *StickyPartition) MetricTag(bool) string { return "__sticky__" } task_queue_id.go
317
318 > func (s *StickyPartition) RpcName() string { task_queue_id.go
319 > return s.stickyName
320 > }
321
322 > func (s *StickyPartition) Key() PartitionKey { task_queue_id.go
323 > return PartitionKey{
324 > namespaceId: s.NamespaceId(),
325 > name: s.StickyName(),
326 > taskType: s.TaskType(),
327 > }
328 > }
329
330 > func (s *StickyPartition) RoutingKey(int) (string, int) { task_queue_id.go
331 > return fmt.Sprintf("%s:%s:%d", s.NamespaceId(), s.RpcName(), s.TaskType()), 0
332 > }
333
334 > func (s *StickyPartition) GradualChangeKey() []byte { task_queue_id.go
335 > key := fmt.Sprintf("%s:%s:%d", s.NamespaceId(), s.RpcName(), s.TaskType())
336 > return []byte(key)
337 > }
338
339 func (w *WorkerCommandsPartition) TaskType() enumspb.TaskQueueType {
388 }
389
390 > func (p *NormalPartition) TaskQueue() *TaskQueue { task_queue_id.go
391 > return p.taskQueue
392 > }
393
394 > func (p *NormalPartition) IsRoot() bool { task_queue_id.go
395 > return p.partitionId == 0
396 > }
397
398 > func (p *NormalPartition) IsChild() bool { task_queue_id.go
399 > return !p.IsRoot()
400 > }
401
402 > func (p *NormalPartition) PersistenceTTL() time.Duration { return 0 } task_queue_id.go
403 > func (p *NormalPartition) SupportsFairness() bool { return true } task_queue_id.go
404 func (p *NormalPartition) SupportsVersioning() bool { return true }
405 func (p *NormalPartition) SupportsPartitions() bool { return true }
406 > func (p *NormalPartition) MetricTag(partitionIDBreakdown bool) string { task_queue_id.go
407 > if partitionIDBreakdown {
408 > return strconv.Itoa(p.partitionId) task_queue_id.go
409 > }
410 > return "__normal__" task_queue_id.go
411 }
412
413 > func (p *NormalPartition) Kind() enumspb.TaskQueueKind { task_queue_id.go
414 > return enumspb.TASK_QUEUE_KIND_NORMAL
415 > }
416
417 > func (p *NormalPartition) PartitionId() int { task_queue_id.go
418 > return p.partitionId
419 > }
420
421 > func (p *NormalPartition) NamespaceId() string { task_queue_id.go
422 > return p.taskQueue.family.namespaceId
423 > }
424
425 > func (p *NormalPartition) TaskType() enumspb.TaskQueueType { task_queue_id.go
426 > return p.taskQueue.taskType
427 > }
428
429 // ParentPartition returns a NormalPartition for the parent partition, using the given branching degree.
438 }
439
440 > func (p *NormalPartition) RpcName() string { task_queue_id.go
441 > if p.IsRoot() {
442 > return p.TaskQueue().family.Name() task_queue_id.go
443 > }
444 return nonRootPartitionPrefix + p.TaskQueue().Name() + partitionDelimiter + strconv.Itoa(p.partitionId)
445 }
446
447 > func (p *NormalPartition) Key() PartitionKey { task_queue_id.go
448 > return PartitionKey{
449 > namespaceId: p.NamespaceId(),
450 > name: p.TaskQueue().Name(),
451 > partitionId: p.partitionId,
452 > taskType: p.TaskType(),
453 > }
454 > }
455
456 > func (p *NormalPartition) RoutingKey(batchSize int) (string, int) { task_queue_id.go
457 > if batchSize == 0 {
458 > return fmt.Sprintf("%s:%s:%d", p.NamespaceId(), p.RpcName(), p.TaskType()), 0 task_queue_id.go
459 > }
460 // We want to use LookupN to spread partitions across available nodes, but LookupN takes O(n)
461 // time and space, so we should limit the n that we pass to it. Reduce the partition id by some
472 }
473
474 > func (p *NormalPartition) GradualChangeKey() []byte { task_queue_id.go
475 > key := fmt.Sprintf("%s:%s:%d", p.NamespaceId(), p.RpcName(), p.TaskType())
476 > return []byte(key)
477 > }
478
479 // parseRpcName takes the rpc name of a task queue partition and returns a ParseTaskQueuePartition.
480 // Returns an error if the given name is not a valid rpc name.
481 > func parseRpcName(rpcName string) (string, int, error) { task_queue_id.go
482 > baseName := rpcName
483 > partition := 0
484 >
485 > if strings.HasPrefix(rpcName, nonRootPartitionPrefix) {
486 suffixOff := strings.LastIndex(rpcName, partitionDelimiter)
487 if suffixOff <= len(nonRootPartitionPrefix) {
498 }
499
500 > if strings.HasPrefix(baseName, nonRootPartitionPrefix) { task_queue_id.go
501 return "", 0, serviceerror.NewInvalidArgument("task queue family name cannot have prefix /_sys/ " + baseName)
502 }
503 > return baseName, partition, nil task_queue_id.go
504 }
go.temporal.io/server/api/taskqueue/v1/message.pb.go 173 covered LOC · 67 ranges

Open complete file

81 func (*TaskVersionDirective) ProtoMessage() {}
82
83 > func (x *TaskVersionDirective) ProtoReflect() protoreflect.Message { message.pb.go
84 > mi := &file_temporal_server_api_taskqueue_v1_message_proto_msgTypes[0]
85 > if x != nil {
86 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) message.pb.go
87 > if ms.LoadMessageInfo() == nil {
88 > ms.StoreMessageInfo(mi)
89 > }
90 > return ms
91 }
92 > return mi.MessageOf(x) message.pb.go
93 }
94
98 }
99
100 > func (x *TaskVersionDirective) GetBuildId() isTaskVersionDirective_BuildId { message.pb.go
101 > if x != nil {
102 > return x.BuildId message.pb.go
103 > }
104 return nil
105 }
106
107 > func (x *TaskVersionDirective) GetUseAssignmentRules() *emptypb.Empty { message.pb.go
108 > if x != nil {
109 > if x, ok := x.BuildId.(*TaskVersionDirective_UseAssignmentRules); ok { message.pb.go
110 > return x.UseAssignmentRules message.pb.go
111 > }
112 }
113 return nil
114 }
115
116 > func (x *TaskVersionDirective) GetAssignedBuildId() string { message.pb.go
117 > if x != nil {
118 > if x, ok := x.BuildId.(*TaskVersionDirective_AssignedBuildId); ok { message.pb.go
119 return x.AssignedBuildId
120 }
121 }
122 > return "" message.pb.go
123 }
124
125 > func (x *TaskVersionDirective) GetBehavior() v1.VersioningBehavior { message.pb.go
126 > if x != nil {
127 > return x.Behavior message.pb.go
128 > }
129 return v1.VersioningBehavior(0)
130 }
131
132 > func (x *TaskVersionDirective) GetDeployment() *v11.Deployment { message.pb.go
133 > if x != nil {
134 > return x.Deployment message.pb.go
135 > }
136 return nil
137 }
138
139 > func (x *TaskVersionDirective) GetDeploymentVersion() *v12.WorkerDeploymentVersion { message.pb.go
140 > if x != nil {
141 > return x.DeploymentVersion message.pb.go
142 > }
143 return nil
144 }
145
146 > func (x *TaskVersionDirective) GetRevisionNumber() int64 { message.pb.go
147 > if x != nil {
148 > return x.RevisionNumber message.pb.go
149 > }
150 return 0
151 }
152
153 > func (x *TaskVersionDirective) GetUseRampingVersion() bool { message.pb.go
154 > if x != nil {
155 > return x.UseRampingVersion message.pb.go
156 > }
157 return false
158 }
201 func (*FairLevel) ProtoMessage() {}
202
203 > func (x *FairLevel) ProtoReflect() protoreflect.Message { message.pb.go
204 > mi := &file_temporal_server_api_taskqueue_v1_message_proto_msgTypes[1]
205 > if x != nil {
206 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
207 if ms.LoadMessageInfo() == nil {
210 return ms
211 }
212 > return mi.MessageOf(x) message.pb.go
213 }
214
382 func (*TaskQueueVersionInfoInternal) ProtoMessage() {}
383
384 > func (x *TaskQueueVersionInfoInternal) ProtoReflect() protoreflect.Message { message.pb.go
385 > mi := &file_temporal_server_api_taskqueue_v1_message_proto_msgTypes[3]
386 > if x != nil {
387 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
388 if ms.LoadMessageInfo() == nil {
391 return ms
392 }
393 > return mi.MessageOf(x) message.pb.go
394 }
395
399 }
400
401 > func (x *TaskQueueVersionInfoInternal) GetPhysicalTaskQueueInfo() *PhysicalTaskQueueInfo { message.pb.go
402 > if x != nil {
403 > return x.PhysicalTaskQueueInfo
404 > }
405 return nil
406 }
464 }
465
466 > func (x *PhysicalTaskQueueInfo) GetTaskQueueStats() *v13.TaskQueueStats { message.pb.go
467 > if x != nil {
468 > return x.TaskQueueStats
469 > }
470 return nil
471 }
510 func (*TaskQueuePartition) ProtoMessage() {}
511
512 > func (x *TaskQueuePartition) ProtoReflect() protoreflect.Message { message.pb.go
513 > mi := &file_temporal_server_api_taskqueue_v1_message_proto_msgTypes[5]
514 > if x != nil {
515 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
516 if ms.LoadMessageInfo() == nil {
519 return ms
520 }
521 > return mi.MessageOf(x) message.pb.go
522 }
523
527 }
528
529 > func (x *TaskQueuePartition) GetTaskQueue() string { message.pb.go
530 > if x != nil {
531 > return x.TaskQueue
532 > }
533 return ""
534 }
535
536 > func (x *TaskQueuePartition) GetTaskQueueType() v1.TaskQueueType { message.pb.go
537 > if x != nil {
538 > return x.TaskQueueType
539 > }
540 return v1.TaskQueueType(0)
541 }
542
543 > func (x *TaskQueuePartition) GetPartitionId() isTaskQueuePartition_PartitionId { message.pb.go
544 > if x != nil {
545 > return x.PartitionId
546 > }
547 return nil
548 }
549
550 > func (x *TaskQueuePartition) GetNormalPartitionId() int32 { message.pb.go
551 > if x != nil {
552 > if x, ok := x.PartitionId.(*TaskQueuePartition_NormalPartitionId); ok {
553 return x.NormalPartitionId
554 }
555 }
556 > return 0 message.pb.go
557 }
558
616 func (*WorkerCommandsPartitionId) ProtoMessage() {}
617
618 > func (x *WorkerCommandsPartitionId) ProtoReflect() protoreflect.Message { message.pb.go
619 > mi := &file_temporal_server_api_taskqueue_v1_message_proto_msgTypes[6]
620 > if x != nil {
621 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
622 if ms.LoadMessageInfo() == nil {
625 return ms
626 }
627 > return mi.MessageOf(x) message.pb.go
628 }
629
658 func (*BuildIdRedirectInfo) ProtoMessage() {}
659
660 > func (x *BuildIdRedirectInfo) ProtoReflect() protoreflect.Message { message.pb.go
661 > mi := &file_temporal_server_api_taskqueue_v1_message_proto_msgTypes[7]
662 > if x != nil {
663 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
664 if ms.LoadMessageInfo() == nil {
667 return ms
668 }
669 > return mi.MessageOf(x) message.pb.go
670 }
671
725 func (*TaskForwardInfo) ProtoMessage() {}
726
727 > func (x *TaskForwardInfo) ProtoReflect() protoreflect.Message { message.pb.go
728 > mi := &file_temporal_server_api_taskqueue_v1_message_proto_msgTypes[8]
729 > if x != nil {
730 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
731 if ms.LoadMessageInfo() == nil {
734 return ms
735 }
736 > return mi.MessageOf(x) message.pb.go
737 }
738
742 }
743
744 > func (x *TaskForwardInfo) GetSourcePartition() string { message.pb.go
745 > if x != nil {
746 return x.SourcePartition
747 }
748 > return "" message.pb.go
749 }
750
763 }
764
765 > func (x *TaskForwardInfo) GetCreateTime() *timestamppb.Timestamp { message.pb.go
766 > if x != nil {
767 return x.CreateTime
768 }
769 > return nil message.pb.go
770 }
771
841 }
842
843 > func (x *EphemeralData) GetScale() *PartitionScaleInfo { message.pb.go
844 > if x != nil {
845 return x.Scale
846 }
847 > return nil message.pb.go
848 }
849
869 func (*VersionedEphemeralData) ProtoMessage() {}
870
871 > func (x *VersionedEphemeralData) ProtoReflect() protoreflect.Message { message.pb.go
872 > mi := &file_temporal_server_api_taskqueue_v1_message_proto_msgTypes[10]
873 > if x != nil {
874 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
875 if ms.LoadMessageInfo() == nil {
878 return ms
879 }
880 > return mi.MessageOf(x) message.pb.go
881 }
882
886 }
887
888 > func (x *VersionedEphemeralData) GetData() *EphemeralData { message.pb.go
889 > if x != nil {
890 return x.Data
891 }
892 > return nil message.pb.go
893 }
894
895 > func (x *VersionedEphemeralData) GetVersion() int64 { message.pb.go
896 > if x != nil {
897 return x.Version
898 }
899 > return 0 message.pb.go
900 }
901
932 func (*PartitionScaleInfo) ProtoMessage() {}
933
934 > func (x *PartitionScaleInfo) ProtoReflect() protoreflect.Message { message.pb.go
935 > mi := &file_temporal_server_api_taskqueue_v1_message_proto_msgTypes[11]
936 > if x != nil {
937 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) message.pb.go
938 > if ms.LoadMessageInfo() == nil {
939 > ms.StoreMessageInfo(mi)
940 > }
941 > return ms
942 }
943 > return mi.MessageOf(x) message.pb.go
944 }
945
949 }
950
951 > func (x *PartitionScaleInfo) GetRead() int32 { message.pb.go
952 > if x != nil {
953 return x.Read
954 }
955 > return 0 message.pb.go
956 }
957
958 > func (x *PartitionScaleInfo) GetWrite() int32 { message.pb.go
959 > if x != nil {
960 return x.Write
961 }
962 > return 0 message.pb.go
963 }
964
965 > func (x *PartitionScaleInfo) GetBacklogCounts() []byte { message.pb.go
966 > if x != nil {
967 return x.BacklogCounts
968 }
969 > return nil message.pb.go
970 }
971
972 > func (x *PartitionScaleInfo) GetBacklogCap() int32 { message.pb.go
973 > if x != nil {
974 return x.BacklogCap
975 }
976 > return 0 message.pb.go
977 }
978
998 }
999
1000 > func (x *ClientPartitionCounts) Reset() { message.pb.go
1001 > *x = ClientPartitionCounts{}
1002 > mi := &file_temporal_server_api_taskqueue_v1_message_proto_msgTypes[12]
1003 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1004 > ms.StoreMessageInfo(mi)
1005 > }
1006
1007 func (x *ClientPartitionCounts) String() string {
1011 func (*ClientPartitionCounts) ProtoMessage() {}
1012
1013 > func (x *ClientPartitionCounts) ProtoReflect() protoreflect.Message { message.pb.go
1014 > mi := &file_temporal_server_api_taskqueue_v1_message_proto_msgTypes[12]
1015 > if x != nil {
1016 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1017 > if ms.LoadMessageInfo() == nil {
1018 > ms.StoreMessageInfo(mi)
1019 > }
1020 > return ms
1021 }
1022 return mi.MessageOf(x)
1330 }
1331
1332 > func init() { file_temporal_server_api_taskqueue_v1_message_proto_init() } message.pb.go
1333 > func file_temporal_server_api_taskqueue_v1_message_proto_init() {
1334 > if File_temporal_server_api_taskqueue_v1_message_proto != nil {
1335 return
1336 }
1337 > file_temporal_server_api_taskqueue_v1_message_proto_msgTypes[0].OneofWrappers = []any{ message.pb.go
1338 > (*TaskVersionDirective_UseAssignmentRules)(nil),
1339 > (*TaskVersionDirective_AssignedBuildId)(nil),
1340 > }
1341 > file_temporal_server_api_taskqueue_v1_message_proto_msgTypes[5].OneofWrappers = []any{
1342 > (*TaskQueuePartition_NormalPartitionId)(nil),
1343 > (*TaskQueuePartition_StickyName)(nil),
1344 > (*TaskQueuePartition_WorkerCommands)(nil),
1345 > }
1346 > type x struct{}
1347 > out := protoimpl.TypeBuilder{
1348 > File: protoimpl.DescBuilder{
1349 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1350 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_taskqueue_v1_message_proto_rawDesc), len(file_temporal_server_api_taskqueue_v1_message_proto_rawDesc)),
1351 > NumEnums: 0,
1352 > NumMessages: 16,
1353 > NumExtensions: 0,
1354 > NumServices: 0,
1355 > },
1356 > GoTypes: file_temporal_server_api_taskqueue_v1_message_proto_goTypes,
1357 > DependencyIndexes: file_temporal_server_api_taskqueue_v1_message_proto_depIdxs,
1358 > MessageInfos: file_temporal_server_api_taskqueue_v1_message_proto_msgTypes,
1359 > }.Build()
1360 > File_temporal_server_api_taskqueue_v1_message_proto = out.File
1361 > file_temporal_server_api_taskqueue_v1_message_proto_goTypes = nil
1362 > file_temporal_server_api_taskqueue_v1_message_proto_depIdxs = nil
1363 }
go.temporal.io/server/common/log/tag/tags.go 173 covered LOC · 58 ranges

Open complete file

30
31 // Operation returns tag for Operation
32 > func Operation(operation string) ZapTag { tags.go
33 > return NewStringTag("operation", operation)
34 > }
35
36 // Error returns tag for Error
37 > func Error(err error) ZapTag { tags.go
38 > return ZapTag{
39 > // NOTE: zap already chosen "error" as key
40 > field: zap.Error(err),
41 > }
42 > }
43
44 // ServiceErrorType returns tag for ServiceErrorType
45 > func ServiceErrorType(err error) ZapTag { tags.go
46 > return NewStringTag("service-error-type", util.ErrorType(err))
47 > }
48
49 // IsRetryable returns tag for IsRetryable
58
59 // Timestamp returns tag for Timestamp
60 > func Timestamp(timestamp time.Time) ZapTag { tags.go
61 > return NewTimeTag("timestamp", timestamp)
62 > }
63
64 // RequestID returns tag for RequestID
70
71 // WorkflowAction returns tag for WorkflowAction
72 > func workflowAction(action string) ZapTag { tags.go
73 > return NewStringTag("wf-action", action)
74 > }
75
76 // WorkflowListFilterType returns tag for WorkflowListFilterType
77 > func workflowListFilterType(listFilterType string) ZapTag { tags.go
78 > return NewStringTag("wf-list-filter-type", listFilterType)
79 > }
80
81 // general
108 // WorkflowID returns tag for WorkflowID
109 // TODO: Rename to BusinessID.
110 > func WorkflowID(workflowID string) ZapTag { tags.go
111 > return NewStringTag(WorkflowIDKey, workflowID)
112 > }
113
114 // WorkflowType returns tag for WorkflowType
115 > func WorkflowType(wfType string) ZapTag { tags.go
116 > return NewStringTag("wf-type", wfType)
117 > }
118
119 // WorkflowState returns tag for WorkflowState
124 // WorkflowRunID returns tag for WorkflowRunID
125 // TODO: Rename to RunID
126 > func WorkflowRunID(runID string) ZapTag { tags.go
127 > return NewStringTag(WorkflowRunIDKey, runID)
128 > }
129
130 // WorkflowNewRunID returns tag for WorkflowNewRunID
169
170 // WorkflowTaskTimeout returns tag for WorkflowTaskTimeoutSeconds
171 > func WorkflowTaskTimeout(s time.Duration) ZapTag { tags.go
172 > return NewDurationTag("workflow-task-timeout", s)
173 > }
174
175 // QueryID returns tag for QueryID
187 // WorkflowNamespaceID returns tag for WorkflowNamespaceID
188 // TODO: Rename to NamespaceID
189 > func WorkflowNamespaceID(namespaceID string) ZapTag { tags.go
190 > return NewStringTag("wf-namespace-id", namespaceID)
191 > }
192
193 // WorkflowNamespace returns tag for WorkflowNamespace
194 > func WorkflowNamespace(namespace string) ZapTag { tags.go
195 > return NewStringTag("wf-namespace", namespace)
196 > }
197
198 // WorkflowNamespaceIDs returns tag for WorkflowNamespaceIDs
204
205 // WorkflowEventID returns tag for WorkflowEventID
206 > func WorkflowEventID(eventID int64) ZapTag { tags.go
207 > return NewInt64("wf-history-event-id", eventID)
208 > }
209
210 // WorkflowScheduledEventID returns tag for WorkflowScheduledEventID
211 > func WorkflowScheduledEventID(scheduledEventID int64) ZapTag { tags.go
212 > return NewInt64("wf-scheduled-event-id", scheduledEventID)
213 > }
214
215 // WorkflowStartedEventID returns tag for WorkflowStartedEventID
216 > func WorkflowStartedEventID(startedEventID int64) ZapTag { tags.go
217 > return NewInt64("wf-started-event-id", startedEventID)
218 > }
219
220 // WorkflowStartedTimestamp returns tag for WorkflowStartedTimestamp
221 > func WorkflowStartedTimestamp(t time.Time) ZapTag { tags.go
222 > return NewTimeTag("wf-started-timestamp", t)
223 > }
224
225 // WorkflowInitiatedID returns tag for WorkflowInitiatedID
288
289 // WorkflowTaskQueueType returns tag for WorkflowTaskQueueType
290 > func WorkflowTaskQueueType(taskQueueType enumspb.TaskQueueType) ZapTag { tags.go
291 > return NewStringTag("wf-task-queue-type", taskQueueType.String())
292 > }
293
294 // WorkflowTaskQueueName returns tag for WorkflowTaskQueueName
295 > func WorkflowTaskQueueName(taskQueueName string) ZapTag { tags.go
296 > return NewStringTag("wf-task-queue-name", taskQueueName)
297 > }
298
299 // WorkerVersion returns tag for worker build ID
300 > func WorkerVersion(version string) ZapTag { tags.go
301 > if version == "" {
302 > version = "_unversioned_" tags.go
303 > }
304 > return NewStringTag("worker-version", version) tags.go
305 }
306
376
377 // Component returns tag for Component
378 > func component(component string) ZapTag { tags.go
379 > return NewStringTag("component", component)
380 > }
381
382 // Lifecycle returns tag for Lifecycle
383 > func lifecycle(lifecycle string) ZapTag { tags.go
384 > return NewStringTag("lifecycle", lifecycle)
385 > }
386
387 // StoreOperation returns tag for StoreOperation
388 > func storeOperation(storeOperation string) ZapTag { tags.go
389 > return NewStringTag("store-operation", storeOperation)
390 > }
391
392 // OperationResult returns tag for OperationResult
393 > func operationResult(operationResult string) ZapTag { tags.go
394 > return NewStringTag("operation-result", operationResult)
395 > }
396
397 // ErrorType returns tag for ErrorType
398 > func ErrorType(err error) ZapTag { tags.go
399 > return errorType(util.ErrorType(err))
400 > }
401
402 // errorType returns tag for ErrorType given a string
403 > func errorType(errorType string) ZapTag { tags.go
404 > return NewStringTag("error-type", errorType)
405 > }
406
407 // Shardupdate returns tag for Shardupdate
408 > func shardupdate(shardupdate string) ZapTag { tags.go
409 > return NewStringTag("shard-update", shardupdate)
410 > }
411
412 // scope returns a tag for scope
413 // Pre-defined scope tags are in values.go.
414 > func scope(scope string) ZapTag { tags.go
415 > return NewStringTag("scope", scope)
416 > }
417
418 // general
419
420 // Service returns tag for Service
421 > func Service(sv primitives.ServiceName) ZapTag { tags.go
422 > return NewStringTag("service", string(sv))
423 > }
424
425 // Addresses returns tag for Addresses
426 > func Addresses(ads []string) ZapTag { tags.go
427 > return NewStringsTag("addresses", ads)
428 > }
429
430 // ListenerName returns tag for ListenerName
434
435 // Address return tag for Address
436 > func Address(ad string) ZapTag { tags.go
437 > return NewStringTag("address", ad)
438 > }
439
440 // HostID return tag for HostID
441 > func HostID(hid string) ZapTag { tags.go
442 > return NewStringTag("hostId", hid)
443 > }
444
445 // Env return tag for runtime environment
449
450 // Key returns tag for Key
451 > func Key(k string) ZapTag { tags.go
452 > return NewStringTag("key", k)
453 > }
454
455 // Name returns tag for Name
456 > func Name(k string) ZapTag { tags.go
457 > return NewStringTag("name", k)
458 > }
459
460 // Value returns tag for Value
461 > func Value(v any) ZapTag { tags.go
462 > return NewAnyTag("value", v)
463 > }
464
465 // ValueType returns tag for ValueType
479
480 // Host returns tag for Host
481 > func Host(h string) ZapTag { tags.go
482 > return NewStringTag("host", h)
483 > }
484
485 // Port returns tag for Port
486 > func Port(p int) ZapTag { tags.go
487 > return NewInt("port", p)
488 > }
489
490 // CursorTimestamp returns tag for CursorTimestamp
491 > func CursorTimestamp(timestamp time.Time) ZapTag { tags.go
492 > return NewTimeTag("cursor-timestamp", timestamp)
493 > }
494
495 // MetricScope returns tag for MetricScope
524
525 // Number returns tag for Number
526 > func Number(n int64) ZapTag { tags.go
527 > return NewInt64("number", n)
528 > }
529
530 // NextNumber returns tag for NextNumber
531 > func NextNumber(n int64) ZapTag { tags.go
532 > return NewInt64("next-number", n)
533 > }
534
535 // ServerName returns tag for ServerName
553
554 // ShardID returns tag for ShardID
555 > func ShardID(shardID int32) ZapTag { tags.go
556 > return NewInt32("shard-id", shardID)
557 > }
558
559 // ShardTime returns tag for ShardTime
563
564 // PreviousShardRangeID returns tag for PreviousShardRangeID
565 > func PreviousShardRangeID(id int64) ZapTag { tags.go
566 > return NewInt64("previous-shard-range-id", id)
567 > }
568
569 // ShardRangeID returns tag for ShardRangeID
570 > func ShardRangeID(id int64) ZapTag { tags.go
571 > return NewInt64("shard-range-id", id)
572 > }
573
574 // ShardContextState returns tag for ShardContextState
605
606 // QueueReaderID returns tag for queue readerID
607 > func QueueReaderID(readerID int64) ZapTag { tags.go
608 > return NewInt64("queue-reader-id", readerID)
609 > }
610
611 // QueueAlert returns tag for queue alert
615
616 // Task returns tag for Task
617 > func Task(task any) ZapTag { tags.go
618 > return NewAnyTag("queue-task", task)
619 > }
620
621 // TaskID returns tag for TaskID
622 > func TaskID(taskID int64) ZapTag { tags.go
623 > return NewInt64("queue-task-id", taskID)
624 > }
625
626 // TaskKey returns tag for TaskKey
627 > func TaskKey(key any) ZapTag { tags.go
628 > return NewAnyTag("queue-task-key", key)
629 > }
630
631 // TaskVersion returns tag for TaskVersion
634 }
635
636 > func TaskType(taskType enumsspb.TaskType) ZapTag { tags.go
637 > return NewStringTag("queue-task-type", taskType.String())
638 > }
639
640 func TaskCategoryID(taskCategoryID int) ZapTag {
648
649 // NumberProcessed returns tag for NumberProcessed
650 > func NumberProcessed(n int) ZapTag { tags.go
651 > return NewInt("number-processed", n)
652 > }
653
654 // NumberDeleted returns tag for NumberDeleted
655 > func NumberDeleted(n int) ZapTag { tags.go
656 > return NewInt("number-deleted", n)
657 > }
658
659 // NumberChanged returns tag for NumberChanged
660 > func NumberChanged(n int) ZapTag { tags.go
661 > return NewInt("number-changed", n)
662 > }
663
664 // TimerTaskStatus returns tag for TimerTaskStatus
674
675 // Attempt returns tag for Attempt
676 > func Attempt(attempt int32) ZapTag { tags.go
677 > return NewInt32("attempt", attempt)
678 > }
679
680 // UnexpectedErrorAttempts returns tag for UnexpectedErrorAttempts
683 }
684
685 > func WorkflowTaskType(wtType string) ZapTag { tags.go
686 > return NewStringTag("wt-type", wtType)
687 > }
688
689 // AttemptCount returns tag for AttemptCount
934
935 // WorkflowTaskRequestId returns a tag for workflow task RequestId
936 > func WorkflowTaskRequestId(s string) ZapTag { tags.go
937 > return NewStringTag("workflow-task-request-id", s)
938 > }
939
940 // AckLevel returns tag for ack level
954
955 // BootstrapHostPorts returns tag for bootstrap host ports
956 > func BootstrapHostPorts(s string) ZapTag { tags.go
957 > return NewStringTag("bootstrap-hostports", s)
958 > }
959
960 // TLSCertFile returns tag for TLS cert file name
1002 }
1003
1004 > func UserDataVersion(v int64) ZapTag { tags.go
1005 > return NewInt64("user-data-version", v)
1006 > }
1007
1008 > func Cause(cause string) ZapTag { tags.go
1009 > return NewStringTag("cause", cause)
1010 > }
1011
1012 func NexusOperation(operation string) ZapTag {
go.temporal.io/server/service/history/workflow/cache/cache.go 173 covered LOC · 44 ranges

Open complete file

80 )
81
82 > var NoopReleaseFn historyi.ReleaseWorkflowContextFunc = func(err error) {} cache.go
83
84 const (
95 logger log.Logger,
96 handler metrics.Handler,
97 > ) Cache { cache.go
98 > maxSize := config.HistoryHostLevelCacheMaxSize()
99 > if config.HistoryCacheLimitSizeBased {
100 maxSize = config.HistoryHostLevelCacheMaxSizeBytes()
101 }
102 > opts := &cache.Options{ cache.go
103 > TTL: config.HistoryCacheTTL(),
104 > Pin: true,
105 > BackgroundEvict: config.HistoryCacheBackgroundEvict,
106 > OnPut: func(val any) {
107 > //revive:disable-next-line:unchecked-type-assertion cache.go
108 > item := val.(*cacheItem)
109 > if item.finalizer == nil {
110 return // should only happen in unit tests
111 }
112 > wfKey := item.wfContext.GetWorkflowKey() cache.go
113 > err := item.finalizer.Register(wfKey.String(), func(ctx context.Context) error {
114 > if err := item.wfContext.Lock(ctx, locks.PriorityHigh); err != nil { cache.go
115 return err
116 }
117 > defer item.wfContext.Unlock() cache.go
118 > item.wfContext.Clear()
119 > return nil
120 })
121 > if err != nil { cache.go
122 logger.Debug("cache failed to register callback in finalizer",
123 tag.Error(err), tag.ShardID(item.shardId))
141 }
142
143 > taggedHandler := handler.WithTags(metrics.CacheTypeTag(metrics.MutableStateCacheTypeTagValue)) cache.go
144 > c := cache.NewWithMetrics(maxSize, opts, taggedHandler)
145 > return &cacheImpl{
146 > Cache: c,
147 > nonUserContextLockTimeout: config.HistoryCacheNonUserContextLockTimeout(),
148 > }
149 }
150
151 > func (c *cacheImpl) stop() { cache.go
152 > c.Cache.(cache.StoppableCache).Stop()
153 > }
154
155 func (c *cacheImpl) GetOrCreateWorkflowExecution(
177 archetypeID chasm.ArchetypeID,
178 lockPriority locks.Priority,
179 > ) (historyi.ReleaseWorkflowContextFunc, error) { cache.go
180 > if err := c.validateWorkflowID(workflowID); err != nil {
181 return nil, err
182 }
183
184 > handler := shardContext.GetMetricsHandler().WithTags( cache.go
185 > metrics.OperationTag(metrics.HistoryCacheGetOrCreateCurrentScope),
186 > metrics.CacheTypeTag(metrics.MutableStateCacheTypeTagValue),
187 > metrics.NamespaceIDTag(namespaceID.String()),
188 > )
189 > metrics.CacheRequests.With(handler).Record(1)
190 > start := time.Now()
191 > defer func() { metrics.CacheLatency.With(handler).Record(time.Since(start)) }()
192
193 > execution := commonpb.WorkflowExecution{ cache.go
194 > WorkflowId: workflowID,
195 > // using empty run ID as current workflow run ID
196 > RunId: "",
197 > }
198 >
199 > _, weReleaseFn, err := c.getOrCreateWorkflowExecutionInternal(
200 > ctx,
201 > shardContext,
202 > namespaceID,
203 > &execution,
204 > archetypeID,
205 > handler,
206 > true,
207 > lockPriority,
208 > )
209 >
210 > metrics.ContextCounterAdd(ctx, metrics.HistoryWorkflowExecutionCacheLatency.Name(),
211 > time.Since(start).Nanoseconds())
212 >
213 > return weReleaseFn, err
214 }
215
221 archetypeID chasm.ArchetypeID,
222 lockPriority locks.Priority,
223 > ) (historyi.WorkflowContext, historyi.ReleaseWorkflowContextFunc, error) { cache.go
224 >
225 > if err := c.validateWorkflowExecutionInfo(ctx, shardContext, namespaceID, execution, archetypeID, lockPriority); err != nil {
226 return nil, nil, err
227 }
228
229 > handler := shardContext.GetMetricsHandler().WithTags( cache.go
230 > metrics.OperationTag(metrics.HistoryCacheGetOrCreateScope),
231 > metrics.CacheTypeTag(metrics.MutableStateCacheTypeTagValue),
232 > metrics.NamespaceIDTag(namespaceID.String()),
233 > )
234 > metrics.CacheRequests.With(handler).Record(1)
235 > start := time.Now()
236 > defer func() { metrics.CacheLatency.With(handler).Record(time.Since(start)) }()
237
238 > weCtx, weReleaseFunc, err := c.getOrCreateWorkflowExecutionInternal( cache.go
239 > ctx,
240 > shardContext,
241 > namespaceID,
242 > execution,
243 > archetypeID,
244 > handler,
245 > false,
246 > lockPriority,
247 > )
248 >
249 > metrics.ContextCounterAdd(ctx, metrics.HistoryWorkflowExecutionCacheLatency.Name(),
250 > time.Since(start).Nanoseconds())
251 >
252 > return weCtx, weReleaseFunc, err
253 }
254
262 forceClearContext bool,
263 lockPriority locks.Priority,
264 > ) (historyi.WorkflowContext, historyi.ReleaseWorkflowContextFunc, error) { cache.go
265 >
266 > if !softassert.That(
267 > shardContext.GetLogger(),
268 > archetypeID != chasm.UnspecifiedArchetypeID,
269 > "Creating execution cache key with unspecified archetype ID",
270 > ) {
271 archetypeID = chasm.WorkflowArchetypeID
272 }
273
274 > cacheKey := Key{ cache.go
275 > WorkflowKey: definition.NewWorkflowKey(namespaceID.String(), execution.GetWorkflowId(), execution.GetRunId()),
276 > ArchetypeID: archetypeID,
277 > ShardUUID: shardContext.GetOwner(),
278 > }
279 > item, cacheHit := c.Get(cacheKey).(*cacheItem)
280 > var workflowCtx historyi.WorkflowContext
281 > if cacheHit {
282 > workflowCtx = item.wfContext cache.go
283 > } else { cache.go
284 > metrics.CacheMissCounter.With(handler).Record(1) cache.go
285 > workflowCtx = workflow.NewContext(
286 > shardContext.GetConfig(),
287 > cacheKey.WorkflowKey,
288 > archetypeID,
289 > shardContext.GetLogger(),
290 > shardContext.GetThrottledLogger(),
291 > shardContext.GetMetricsHandler(),
292 > )
293 >
294 > var err error
295 > value := &cacheItem{shardId: shardContext.GetShardID(), wfContext: workflowCtx, finalizer: shardContext.GetFinalizer()}
296 > existing, err := c.PutIfNotExist(cacheKey, value)
297 > if err != nil {
298 metrics.CacheFailures.With(handler).Record(1)
299 return nil, nil, err
300 }
301 //nolint:revive
302 > workflowCtx = existing.(*cacheItem).wfContext cache.go
303 }
304
305 > if err := c.lockWorkflowExecution(ctx, workflowCtx, cacheKey, lockPriority); err != nil { cache.go
306 metrics.CacheFailures.With(handler).Record(1)
307 metrics.AcquireLockFailedCounter.With(handler).Record(1)
311 // TODO This will create a closure on every request.
312 // Consider revisiting this if it causes too much GC activity
313 > releaseFunc := c.makeReleaseFunc(cacheKey, shardContext, workflowCtx, forceClearContext, handler, time.Now()) cache.go
314 >
315 > return workflowCtx, releaseFunc, nil
316 }
317
321 cacheKey Key,
322 lockPriority locks.Priority,
323 > ) error { cache.go
324 > // skip if there is no deadline
325 > if deadline, ok := ctx.Deadline(); ok {
326 > var cancel context.CancelFunc cache.go
327 > if headers.GetCallerInfo(ctx).CallerType != headers.CallerTypeAPI {
328 > newDeadline := time.Now().Add(c.nonUserContextLockTimeout) cache.go
329 > if newDeadline.Before(deadline) {
330 > ctx, cancel = context.WithDeadline(ctx, newDeadline)
331 > defer cancel()
332 > }
333 > } else { cache.go
334 > newDeadline := deadline.Add(-workflowLockTimeoutTailTime)
335 > if newDeadline.After(time.Now()) {
336 > ctx, cancel = context.WithDeadline(ctx, newDeadline)
337 > defer cancel()
338 > }
339 }
340 }
341
342 > if err := workflowCtx.Lock(ctx, lockPriority); err != nil { cache.go
343 // ctx is done before lock can be acquired
344 c.Release(cacheKey)
345 return consts.ErrResourceExhaustedBusyWorkflow
346 }
347 > return nil cache.go
348 }
349
355 handler metrics.Handler,
356 acquireTime time.Time,
357 > ) func(error) { cache.go
358 >
359 > status := cacheNotReleased
360 > return func(err error) {
361 > if atomic.CompareAndSwapInt32(&status, cacheNotReleased, cacheReleased) {
362 > defer func() {
363 > metrics.HistoryWorkflowExecutionCacheLockHoldDuration.With(handler).Record(time.Since(acquireTime))
364 > }()
365 > if rec := recover(); rec != nil {
366 wfContext.Clear()
367 wfContext.Unlock()
368 c.Release(cacheKey)
369 panic(rec)
370 > } else { cache.go
371 > if err != nil || forceClearContext {
372 > // TODO see issue #668, there are certain type or errors which can bypass the clear cache.go
373 > wfContext.Clear()
374 > wfContext.Unlock()
375 > c.Release(cacheKey)
376 > } else { cache.go
377 > isDirty := wfContext.IsDirty() cache.go
378 > if isDirty {
379 wfContext.Clear()
380 softassert.Fail(shardContext.GetLogger(), "Cache encountered dirty mutable state transaction",
385 )
386 }
387 > wfContext.Unlock() cache.go
388 > c.Release(cacheKey)
389 > if isDirty {
390 panic("Cache encountered dirty mutable state transaction")
391 }
403 archetypeID chasm.ArchetypeID,
404 lockPriority locks.Priority,
405 > ) error { cache.go
406 >
407 > if err := c.validateWorkflowID(execution.GetWorkflowId()); err != nil {
408 return err
409 }
410
411 // RunID is not provided, lets try to retrieve the RunID for current active execution
412 > if execution.GetRunId() == "" { cache.go
413 runID, err := GetCurrentRunID(
414 ctx,
425
426 execution.RunId = runID
427 > } else if uuid.Validate(execution.GetRunId()) != nil { // immediately return if invalid runID cache.go
428 return serviceerror.NewInvalidArgument("RunId is not valid UUID.")
429 }
430 > return nil cache.go
431 }
432
433 func (c *cacheImpl) validateWorkflowID(
434 workflowID string,
435 > ) error { cache.go
436 > if workflowID == "" {
437 return serviceerror.NewInvalidArgument("Can't load workflow execution. WorkflowId not set.")
438 }
439 > return nil cache.go
440 }
441
477 }
478
479 > func (c *cacheItem) CacheSize() int { cache.go
480 > if sg, ok := c.wfContext.(cache.SizeGetter); ok {
481 > return sg.CacheSize() cache.go
482 > }
483 return 0
484 }
go.temporal.io/server/service/matching/fair_task_reader.go 171 covered LOC · 38 ranges

Open complete file

85 subqueue subqueueIndex,
86 initialAckLevel fairLevel,
87 > ) *fairTaskReader { fair_task_reader.go
88 > return &fairTaskReader{
89 > backlogMgr: backlogMgr,
90 > subqueue: subqueue,
91 > logger: backlogMgr.logger,
92 > retrier: backoff.NewRetrier(
93 > backoff.NewExponentialRetryPolicy(50*time.Millisecond).
94 > WithMaximumInterval(10*time.Second).
95 > WithExpirationInterval(backoff.NoInterval),
96 > clock.NewRealTimeSource(),
97 > ),
98 > throttleRetrier: backoff.NewRetrier(
99 > backoff.NewExponentialRetryPolicy(2*time.Second).
100 > WithMaximumInterval(30*time.Second).
101 > WithExpirationInterval(backoff.NoInterval),
102 > clock.NewRealTimeSource(),
103 > ),
104 > backlogAge: newBacklogAgeTracker(),
105 > addRetries: semaphore.NewWeighted(concurrentAddRetries),
106 >
107 > // ack manager
108 > outstandingTasks: *newFairLevelTreeMap(),
109 > readLevel: initialAckLevel,
110 > ackLevel: initialAckLevel,
111 > evictedAcks: *btree.NewBTreeGOptions(fairLevel.less, btree.Options{NoLocks: true}),
112 >
113 > // gc state
114 > lastGCTime: time.Now(),
115 > }
116 > }
117
118 > func (tr *fairTaskReader) Start() { fair_task_reader.go
119 > tr.lock.Lock()
120 > defer tr.lock.Unlock()
121 > tr.maybeReadTasksLocked()
122 > }
123
124 > func (tr *fairTaskReader) getOldestBacklogTime() time.Time { fair_task_reader.go
125 > tr.lock.Lock()
126 > defer tr.lock.Unlock()
127 > return tr.backlogAge.oldestTime()
128 > }
129
130 func (tr *fairTaskReader) completeTask(task *internalTask, res taskResponse) {
197 }
198
199 > func (tr *fairTaskReader) maybeReadTasksLocked() { fair_task_reader.go
200 > // If readPending is true, readTasksImpl is running and will check shouldReadMoreLocked
201 > // before it exits, so we'll definitely do another read if shouldReadMoreLocked is true.
202 > // We also abort here if we're in the middle of a backoff or shutting down.
203 > if tr.readPending || !tr.shouldReadMoreLocked() ||
204 > tr.backoffTimer != nil || tr.backlogMgr.tqCtx.Err() != nil {
205 > return
206 > }
207 > tr.readPending = true
208 > go tr.readTasksImpl()
209 }
210
211 > func (tr *fairTaskReader) shouldReadMoreLocked() bool { fair_task_reader.go
212 > if tr.atEnd {
213 > // If we have the whole backlog in memory, we don't need to read anything.
214 > return false
215 > } else if tr.loadedTasks > tr.backlogMgr.config.GetTasksReloadAt() {
216 // Too many loaded already. We'll get called again when loadedTasks drops.
217 return false
218 }
219 > return true fair_task_reader.go
220 }
221
222 > func (tr *fairTaskReader) readTasksImpl() { fair_task_reader.go
223 > var lastErr error
224 > for {
225 > tr.lock.Lock()
226 > if lastErr != nil || !tr.shouldReadMoreLocked() {
227 > break // with lock still held
228 }
229 > readLevel, loadedTasks := tr.readLevel, tr.loadedTasks fair_task_reader.go
230 > tr.lock.Unlock()
231 >
232 > lastErr = tr.readTaskBatch(readLevel, loadedTasks)
233 }
234
235 // note tr.lock is still held here!
236 > tr.readPending = false fair_task_reader.go
237 >
238 > // process any tasks that were written while readPending was true
239 > var newTasks []*internalTask
240 > if len(tr.newlyWrittenTasks) != 0 {
241 newTasks = tr.mergeTasksLocked(tr.newlyWrittenTasks, mergeWrite)
242 clear(tr.newlyWrittenTasks)
250 // If a backoff timer fired while readPending was still true, its maybeReadTasksLocked call
251 // was a no-op. Re-check now that readPending is false to avoid getting stuck.
252 > tr.maybeReadTasksLocked() fair_task_reader.go
253 >
254 > // unlock before calling addTaskToMatcher
255 > tr.lock.Unlock()
256 >
257 > for _, task := range newTasks {
258 tr.addTaskToMatcher(task)
259 }
260 }
261
262 > func (tr *fairTaskReader) readTaskBatch(readLevel fairLevel, loadedTasks int) error { fair_task_reader.go
263 > batchSize := tr.backlogMgr.config.GetTasksBatchSize() - loadedTasks
264 > readFrom := readLevel.max(fairLevel{pass: 1, id: 0}).inc()
265 > res, err := tr.backlogMgr.db.GetFairTasks(tr.backlogMgr.tqCtx, tr.subqueue, readFrom, batchSize)
266 > if err != nil {
267 // TODO: Should we ever stop retrying on db errors?
268 if tr.backlogMgr.signalIfFatal(err) || common.IsContextCanceledErr(err) {
275 return err
276 }
277 > tr.retrier.Reset() fair_task_reader.go
278 > tr.throttleRetrier.Reset()
279 >
280 > // If we got less than we asked for, we know we hit the end.
281 > // If there was a concurrent write such that we incorrectly think we hit the end here,
282 > // it will be held and processed after we're done reading, and maybe reset atEnd then.
283 > mode := mergeReadMiddle
284 > if len(res.Tasks) < batchSize {
285 > mode = mergeReadToEnd
286 > }
287
288 // Note: even if (especially if) len(tasks) == 0, we should go through the mergeTasks logic
290 // mergeTasksLocked where they'll be added as pre-acked (nil) entries so they advance the
291 // ack level and get GC'd.
292 > tr.mergeTasks(res.Tasks, mode) fair_task_reader.go
293 >
294 > return nil
295 }
296
374 }
375
376 > func (tr *fairTaskReader) mergeTasks(tasks []*persistencespb.AllocatedTaskInfo, mode mergeMode) { fair_task_reader.go
377 > tr.lock.Lock()
378 >
379 > if mode == mergeWrite && tr.readPending {
380 // concurrent write + read: hold the just-written tasks and merge them after we process
381 // the read.
385 }
386
387 > newTasks := tr.mergeTasksLocked(tasks, mode) fair_task_reader.go
388 >
389 > // Detect stuck reader: no tasks in memory, not at end, no read goroutine running, no
390 > // retry pending. In this state, written tasks go only to DB (filtered above readLevel)
391 > // and nothing will trigger a read. The root cause is still under investigation.
392 > // TODO: remove this once the root cause is found and fixed.
393 > if mode == mergeWrite && !tr.atEnd && tr.loadedTasks == 0 && !tr.readPending && tr.backoffTimer == nil {
394 metrics.FairReaderStuckDetected.With(tr.backlogMgr.metricsHandler).Record(1)
395 tr.backlogMgr.throttledLogger.Warn("fair task reader stuck: atEnd=false, loadedTasks=0, no read pending")
400
401 // unlock before calling addTaskToMatcher
402 > tr.lock.Unlock() fair_task_reader.go
403 >
404 > for _, task := range newTasks {
405 tr.addTaskToMatcher(task)
406 }
408
409 // nolint:revive,cognitive-complexity // will be simplified in the future
410 > func (tr *fairTaskReader) mergeTasksLocked(tasks []*persistencespb.AllocatedTaskInfo, mode mergeMode) []*internalTask { fair_task_reader.go
411 > // Collect (1) currently loaded tasks in the matcher plus (2) the tasks we just read/wrote; sorted by level.
412 >
413 > // (1) Note these values are *internalTask.
414 > merged := tr.outstandingTasks.Select(func(k, v any) bool {
415 _, ok := v.(*internalTask)
416 return ok
417 })
418 // (2) Note these values are *AllocatedTaskInfo.
419 > for _, t := range tasks { fair_task_reader.go
420 level := fairLevelFromAllocatedTask(t)
421 if !tr.ackLevel.less(level) {
440 // Take as many of those as we want to keep in memory. The ones that are not already in the
441 // matcher, we have to add to the matcher.
442 > batchSize := tr.backlogMgr.config.GetTasksBatchSize() fair_task_reader.go
443 > it := merged.Iterator()
444 > var highestLevel fairLevel
445 > tasks = tasks[:0] // reuse incoming slice to avoid an allocation
446 > for b := 0; b < batchSize && it.Next(); b++ {
447 if t, ok := it.Value().(*persistencespb.AllocatedTaskInfo); ok {
448 // new task we need to add to the matcher
452 }
453
454 > if highestLevel.id != 0 { fair_task_reader.go
455 // If we have any tasks at all in memory, set readLevel to the maximum of that set.
456 tr.readLevel = highestLevel
457 > } else { fair_task_reader.go
458 > // Otherwise start reading at ack level next. fair_task_reader.go
459 > tr.readLevel = tr.ackLevel
460 > }
461
462 // If there are remaining tasks in the merged set, they can't fit in memory. If they came
463 // from the tasks we just wrote, ignore them. If they came from matcher, remove them.
464 > evictedAnyTasks := false fair_task_reader.go
465 > for it.Next() {
466 evictedAnyTasks = true
467 if task, ok := it.Value().(*internalTask); ok {
483 // we may use these acks to increment our ack level across dropped ranges of tasks.
484 // Cache these evicted acks so we can skip them if we re-read them later.
485 > tr.outstandingTasks.Select(func(k, v any) bool { fair_task_reader.go
486 return v == nil && tr.readLevel.less(k.(fairLevel))
487 }).Each(func(k, v any) {
492 })
493 // Trim the cache to max size by removing highest levels.
494 > for tr.evictedAcks.Len() > evictedAcksCacheSize { fair_task_reader.go
495 tr.evictedAcks.PopMax()
496 }
497
498 > internalTasks := make([]*internalTask, 0, len(tasks)) fair_task_reader.go
499 > for _, t := range tasks {
500 level := fairLevelFromAllocatedTask(t)
501 if _, have := tr.evictedAcks.Delete(level); have {
529 // Advance the ack level past any pre-acked (nil) entries we just added: expired tasks and
530 // acks we re-inserted from the evicted-ack cache. Harmless if we added none.
531 > tr.advanceAckLevelLocked() fair_task_reader.go
532 >
533 > // Update atEnd:
534 > // If we did a read and didn't get to the end, we can't possibly be at the end.
535 > // Also if we evicted anything from memory, we can't either.
536 > // If we read to the end and didn't evict anything, then we know we're at the end.
537 > // Otherwise (i.e. on write) leave atEnd unchanged.
538 > if mode == mergeReadMiddle || evictedAnyTasks {
539 tr.atEnd = false
540 > } else if mode == mergeReadToEnd { fair_task_reader.go
541 > tr.atEnd = true
542 > }
543
544 // If we're at the end, then outstandingTasks is the whole queue so we can set count.
545 > if count := tr.knownCountLocked(); count >= 0 { fair_task_reader.go
546 > tr.backlogMgr.db.setKnownFairBacklogCount(tr.subqueue, count)
547 > }
548
549 > return internalTasks fair_task_reader.go
550
551 // TODO: fine-grained metrics for mergeTasks behavior:
574 // ack manager
575
576 > func (tr *fairTaskReader) getLoadedTasks() int { fair_task_reader.go
577 > tr.lock.Lock()
578 > defer tr.lock.Unlock()
579 > return tr.loadedTasks
580 > }
581
582 // isDrained returns true if this subqueue has been fully drained:
589 }
590
591 > func (tr *fairTaskReader) ackLevelPinnedLocked() bool { fair_task_reader.go
592 > return tr.ackLevelPinnedByWriter || len(tr.newlyWrittenTasks) > 0
593 > }
594
595 // call this whenever new tasks are acked or when ackLevelPinnedLocked() may turn from true to
596 // false (i.e. when ackLevelPinnedByWriter is set to false or newlyWrittenTasks is cleared).
597 > func (tr *fairTaskReader) advanceAckLevelLocked() { fair_task_reader.go
598 > if tr.ackLevelPinnedLocked() {
599 return
600 }
601
602 // Adjust the ack level as far as we can
603 > var numAcked int64 fair_task_reader.go
604 > for {
605 > minLevel, v := tr.outstandingTasks.Min()
606 > if minLevel == nil {
607 > break fair_task_reader.go
608 } else if _, ok := v.(*internalTask); ok {
609 break
614 }
615
616 > if numAcked > 0 { fair_task_reader.go
617 tr.numToGC += int(numAcked)
618 tr.maybeGCLocked()
649 }
650
651 > func (tr *fairTaskReader) getLevels() (readLevel, ackLevel fairLevel) { fair_task_reader.go
652 > tr.lock.Lock()
653 > defer tr.lock.Unlock()
654 > return tr.readLevel, tr.ackLevel
655 > }
656
657 > func (tr *fairTaskReader) knownCountLocked() int64 { fair_task_reader.go
658 > if tr.atEnd {
659 > return int64(tr.loadedTasks)
660 > }
661 return -1
662 }
go.temporal.io/server/client/matching/client.go 167 covered LOC · 34 ranges

Open complete file

61 resolver membership.ServiceResolver,
62 connectionCloseDelay dynamicconfig.DurationPropertyFn,
63 > ) matchingservice.MatchingServiceClient { client.go
64 > c := &clientImpl{
65 > timeout: timeout,
66 > longPollTimeout: longPollTimeout,
67 > clients: clients,
68 > resolver: resolver,
69 > connectionCloseDelay: connectionCloseDelay,
70 > metricsHandler: metricsHandler,
71 > logger: logger,
72 > loadBalancer: lb,
73 > spreadRouting: spreadRouting,
74 > partitionCache: newPartitionCache(metricsHandler),
75 > }
76 >
77 > // Start goroutine to prune partition count cache. Stopped by Stop().
78 > c.partitionCache.Start()
79 >
80 > // Evict cached clients whose host leaves the membership ring. Stopped by Stop().
81 > c.evictionWatcher = goro.NewHandle(context.Background()).Go(c.watchMembership)
82 >
83 > return c
84 > }
85
86 // Stop deterministically releases the resources started by NewClient: it stops
87 // the eviction watcher and partition-cache rotation goroutines and closes every
88 // cached gRPC connection. It is safe to call more than once.
89 > func (c *clientImpl) Stop() { client.go
90 > c.evictionWatcher.Cancel()
91 > <-c.evictionWatcher.Done()
92 > c.partitionCache.Stop()
93 > c.clients.EvictAll()
94 > }
95
96 // watchMembership evicts cached clients whose host leaves the membership ring.
97 // It runs until ctx is cancelled (by Stop).
98 > func (c *clientImpl) watchMembership(ctx context.Context) error { client.go
99 > listenerName := fmt.Sprintf("matchingClientCache-%s", uuid.New().String())
100 > ch := make(chan *membership.ChangedEvent, 1)
101 > if err := c.resolver.AddListener(listenerName, ch); err != nil {
102 c.logger.Error("Failed to subscribe matching cache to membership", tag.Error(err))
103 return err
104 }
105 > defer func() { _ = c.resolver.RemoveListener(listenerName) }() client.go
106
107 // Reap departed hosts via a per-address deadline checked by a single ticker;
108 // a re-add resets it to the latest removal.
109 > evictAt := make(map[string]time.Time) client.go
110 > ticker := time.NewTicker(evictionCheckInterval)
111 > defer ticker.Stop()
112 > for {
113 > select {
114 > case <-ctx.Done(): client.go
115 > return nil
116 > case event := <-ch: client.go
117 > for _, h := range event.HostsRemoved {
118 > evictAt[h.GetAddress()] = time.Now().Add(c.connectionCloseDelay()) client.go
119 > }
120 > for _, h := range event.HostsAdded { client.go
121 > delete(evictAt, h.GetAddress())
122 > }
123 case <-ticker.C:
124 reapEvictableClients(c.resolver, c.clients, evictAt)
195 ctx context.Context,
196 request *matchingservice.AddWorkflowTaskRequest,
197 > opts ...grpc.CallOption) (*matchingservice.AddWorkflowTaskResponse, error) { client.go
198 > if !isPartitionAwareKind(request.GetTaskQueue().GetKind()) {
199 return c.addWorkflowTask(ctx, PartitionCounts{}, request, opts)
200 }
201 > pkey := c.partitionCache.makeKey( client.go
202 > request.GetNamespaceId(),
203 > request.GetTaskQueue().GetName(),
204 > enumspb.TASK_QUEUE_TYPE_WORKFLOW,
205 > )
206 > return invokeWithPartitionCounts(ctx, c.logger, c.partitionCache, pkey, request, opts, c.addWorkflowTask)
207 }
208
212 request *matchingservice.AddWorkflowTaskRequest,
213 opts []grpc.CallOption,
214 > ) (*matchingservice.AddWorkflowTaskResponse, error) { client.go
215 > request = common.CloneProto(request)
216 > client, err := c.pickClientForWrite(
217 > request.GetTaskQueue(),
218 > request.GetNamespaceId(),
219 > enumspb.TASK_QUEUE_TYPE_WORKFLOW,
220 > request.GetForwardInfo().GetSourcePartition(),
221 > pc,
222 > )
223 > if err != nil {
224 return nil, err
225 }
226 > ctx, cancel := c.createContext(ctx) client.go
227 > defer cancel()
228 > return client.AddWorkflowTask(ctx, request, opts...)
229 }
230
233 request *matchingservice.PollActivityTaskQueueRequest,
234 opts ...grpc.CallOption,
235 > ) (*matchingservice.PollActivityTaskQueueResponse, error) { client.go
236 > if !isPartitionAwareKind(request.GetPollRequest().GetTaskQueue().GetKind()) {
237 return c.pollActivityTaskQueue(ctx, PartitionCounts{}, request, opts)
238 }
239 > pkey := c.partitionCache.makeKey( client.go
240 > request.GetNamespaceId(),
241 > request.GetPollRequest().GetTaskQueue().GetName(),
242 > enumspb.TASK_QUEUE_TYPE_ACTIVITY,
243 > )
244 > return invokeWithPartitionCounts(ctx, c.logger, c.partitionCache, pkey, request, opts, c.pollActivityTaskQueue)
245 }
246
250 request *matchingservice.PollActivityTaskQueueRequest,
251 opts []grpc.CallOption,
252 > ) (*matchingservice.PollActivityTaskQueueResponse, error) { client.go
253 > request = common.CloneProto(request)
254 > client, release, err := c.pickClientForRead(
255 > request.GetPollRequest().GetTaskQueue(),
256 > request.GetNamespaceId(),
257 > enumspb.TASK_QUEUE_TYPE_ACTIVITY,
258 > request.GetForwardedSource(),
259 > pc,
260 > )
261 > if err != nil {
262 return nil, err
263 }
264 > if release != nil { client.go
265 > defer release()
266 > }
267 > ctx, cancel := c.createLongPollContext(ctx)
268 > defer cancel()
269 > return client.PollActivityTaskQueue(ctx, request, opts...)
270 }
271
274 request *matchingservice.PollWorkflowTaskQueueRequest,
275 opts ...grpc.CallOption,
276 > ) (*matchingservice.PollWorkflowTaskQueueResponse, error) { client.go
277 > if !isPartitionAwareKind(request.GetPollRequest().GetTaskQueue().GetKind()) {
278 > return c.pollWorkflowTaskQueue(ctx, PartitionCounts{}, request, opts)
279 > }
280 > pkey := c.partitionCache.makeKey(
281 > request.GetNamespaceId(),
282 > request.GetPollRequest().GetTaskQueue().GetName(),
283 > enumspb.TASK_QUEUE_TYPE_WORKFLOW,
284 > )
285 > return invokeWithPartitionCounts(ctx, c.logger, c.partitionCache, pkey, request, opts, c.pollWorkflowTaskQueue)
286 }
287
291 request *matchingservice.PollWorkflowTaskQueueRequest,
292 opts []grpc.CallOption,
293 > ) (*matchingservice.PollWorkflowTaskQueueResponse, error) { client.go
294 > request = common.CloneProto(request)
295 > client, release, err := c.pickClientForRead(
296 > request.GetPollRequest().GetTaskQueue(),
297 > request.GetNamespaceId(),
298 > enumspb.TASK_QUEUE_TYPE_WORKFLOW,
299 > request.GetForwardedSource(),
300 > pc,
301 > )
302 > if err != nil {
303 return nil, err
304 }
305 > if release != nil { client.go
306 > defer release()
307 > }
308 > ctx, cancel := c.createLongPollContext(ctx)
309 > defer cancel()
310 > return client.PollWorkflowTaskQueue(ctx, request, opts...)
311 }
312
444 // processInputPartition returns a partition in certain cases that load balancer involvement is not necessary,
445 // otherwise, returns a task queue to pass down to the load balancer.
446 > func (c *clientImpl) processInputPartition(proto *taskqueuepb.TaskQueue, nsid string, taskType enumspb.TaskQueueType, forwardedFrom string) (tqid.Partition, *tqid.TaskQueue) { client.go
447 > partition, err := tqid.PartitionFromProto(proto, nsid, taskType)
448 > if err != nil {
449 // We preserve the old logic (not returning error in case of invalid proto info) until it's verified that
450 // clients are not sending invalid names.
454 }
455
456 > if forwardedFrom != "" || !partition.IsRoot() { client.go
457 > return partition, nil
458 > }
459
460 > switch p := partition.(type) { client.go
461 > case *tqid.NormalPartition:
462 > return nil, p.TaskQueue()
463 default:
464 return partition, nil
473 forwardedFrom string,
474 pc PartitionCounts,
475 > ) (matchingservice.MatchingServiceClient, error) { client.go
476 > p, tq := c.processInputPartition(proto, nsid, taskType, forwardedFrom)
477 > if tq != nil {
478 > p = c.loadBalancer.PickWritePartition(tq, pc)
479 > }
480 > proto.Name = p.RpcName()
481 > return c.getClientForTaskQueuePartition(p)
482 }
483
489 forwardedFrom string,
490 pc PartitionCounts,
491 > ) (client matchingservice.MatchingServiceClient, release func(), err error) { client.go
492 > p, tq := c.processInputPartition(proto, nsid, taskType, forwardedFrom)
493 > if tq != nil {
494 > token := c.loadBalancer.PickReadPartition(tq, pc)
495 > p = token.TQPartition
496 > release = token.Release
497 > }
498
499 > proto.Name = p.RpcName() client.go
500 > client, err = c.getClientForTaskQueuePartition(p)
501 > return client, release, err
502 }
503
504 > func (c *clientImpl) createContext(parent context.Context) (context.Context, context.CancelFunc) { client.go
505 > return context.WithTimeout(parent, c.timeout)
506 > }
507
508 > func (c *clientImpl) createLongPollContext(parent context.Context) (context.Context, context.CancelFunc) { client.go
509 > return context.WithTimeout(parent, c.longPollTimeout)
510 > }
511
512 > func (c *clientImpl) Route(p tqid.Partition) (string, error) { client.go
513 > spreadChange := c.spreadRouting()
514 > spread := spreadChange.Value(p.GradualChangeKey(), time.Now())
515 > return c.clients.Lookup(p.RoutingKey(spread))
516 > }
517
518 func (c *clientImpl) getClientForTaskQueuePartition(
519 partition tqid.Partition,
520 > ) (matchingservice.MatchingServiceClient, error) { client.go
521 > addr, err := c.Route(partition)
522 > if err != nil {
523 > return nil, err client.go
524 > }
525 > client, err := c.clients.GetClientForClientKey(addr) client.go
526 > if err != nil {
527 return nil, err
528 }
529 > return client.(matchingservice.MatchingServiceClient), nil client.go
530 }
531
532 > func isPartitionAwareKind(kind enumspb.TaskQueueKind) bool { client.go
533 > // only normal partitions participate in scaling
534 > return kind == enumspb.TASK_QUEUE_KIND_NORMAL
535 > }
go.temporal.io/server/service/history/api/create_workflow_util.go 167 covered LOC · 35 ranges

Open complete file

49 startRequest *historyservice.StartWorkflowExecutionRequest,
50 signalWithStartRequest *workflowservice.SignalWithStartWorkflowExecutionRequest,
51 > ) (historyi.MutableState, error) { create_workflow_util.go
52 > newMutableState, err := CreateMutableState(
53 > shard,
54 > namespaceEntry,
55 > startRequest.StartRequest.WorkflowExecutionTimeout,
56 > startRequest.StartRequest.WorkflowRunTimeout,
57 > workflowID,
58 > runID,
59 > )
60 > if err != nil {
61 return nil, err
62 }
63
64 > startEvent, err := newMutableState.AddWorkflowExecutionStartedEvent( create_workflow_util.go
65 > &commonpb.WorkflowExecution{
66 > WorkflowId: workflowID,
67 > RunId: runID,
68 > },
69 > startRequest,
70 > )
71 > if err != nil {
72 return nil, err
73 }
74
75 > if signalWithStartRequest != nil { create_workflow_util.go
76 if signalWithStartRequest.GetRequestId() != "" {
77 newMutableState.AddSignalRequested(signalWithStartRequest.GetRequestId())
88 }
89 }
90 > requestEagerExecution := startRequest.StartRequest.GetRequestEagerExecution() create_workflow_util.go
91 >
92 > var scheduledEventID int64
93 > // Generate first workflow task event if not child WF and no first workflow task backoff
94 > scheduledEventID, err = GenerateFirstWorkflowTask(
95 > newMutableState,
96 > startRequest.ParentExecutionInfo,
97 > startEvent,
98 > requestEagerExecution,
99 > )
100 > if err != nil {
101 return nil, err
102 }
103
104 // If first workflow task should back off (e.g. cron or workflow retry) a workflow task will not be scheduled.
105 > if requestEagerExecution && newMutableState.HasPendingWorkflowTask() { create_workflow_util.go
106 // TODO: get build ID from Starter so eager workflows can be versioned
107 _, _, err = newMutableState.AddWorkflowTaskStartedEvent(
131 shardCtx historyi.ShardContext,
132 ms historyi.MutableState,
133 > ) (WorkflowLease, error) { create_workflow_util.go
134 > // TODO(stephanos): remove this hack
135 > if existingLease != nil {
136 return existingLease, nil
137 }
138 > return NewWorkflowLease( create_workflow_util.go
139 > workflow.NewContext(
140 > shardCtx.GetConfig(),
141 > definition.NewWorkflowKey(
142 > ms.GetNamespaceEntry().ID().String(),
143 > ms.GetExecutionInfo().WorkflowId,
144 > ms.GetExecutionState().RunId,
145 > ),
146 > chasm.WorkflowArchetypeID,
147 > shardCtx.GetLogger(),
148 > shardCtx.GetThrottledLogger(),
149 > shardCtx.GetMetricsHandler(),
150 > ),
151 > wcache.NoopReleaseFn,
152 > ms,
153 > ), nil
154 }
155
161 workflowID string,
162 runID string,
163 > ) (historyi.MutableState, error) { create_workflow_util.go
164 > newMutableState := workflow.NewMutableState(
165 > shard,
166 > shard.GetEventsCache(),
167 > shard.GetLogger(),
168 > namespaceEntry,
169 > workflowID,
170 > runID,
171 > shard.GetTimeSource().Now(),
172 > )
173 > if err := newMutableState.SetHistoryTree(executionTimeout, runTimeout, runID); err != nil {
174 return nil, err
175 }
176 > return newMutableState, nil create_workflow_util.go
177 }
178
182 startEvent *historypb.HistoryEvent,
183 bypassTaskGeneration bool,
184 > ) (int64, error) { create_workflow_util.go
185 > if parentInfo == nil {
186 > // WorkflowTask is only created when it is not a Child Workflow and no backoff is needed
187 > return mutableState.AddFirstWorkflowTaskScheduled(nil, startEvent, bypassTaskGeneration)
188 > }
189 return 0, nil
190 }
221 workflowHeaderSize int,
222 operation string,
223 > ) error { create_workflow_util.go
224 > config := shard.GetConfig()
225 > logger := shard.GetLogger()
226 > throttledLogger := shard.GetThrottledLogger()
227 > namespaceName := namespaceEntry.Name().String()
228 >
229 > metricsHandler := interceptor.GetMetricsHandlerFromContext(ctx, logger)
230 > metrics.HeaderSize.With(metricsHandler.WithTags(metrics.HeaderCallsiteTag(operation))).Record(int64(workflowHeaderSize))
231 > handlerWithCommandTag := metricsHandler.WithTags(metrics.CommandTypeTag(operation))
232 > if err := common.CheckEventBlobSizeLimit(
233 > workflowInputSize,
234 > config.BlobSizeLimitWarn(namespaceName),
235 > config.BlobSizeLimitError(namespaceName),
236 > namespaceName,
237 > workflowID,
238 > "",
239 > handlerWithCommandTag,
240 > throttledLogger,
241 > operation,
242 > ); err != nil {
243 return err
244 }
245
246 > metrics.MemoSize.With(handlerWithCommandTag).Record(int64(workflowMemoSize)) create_workflow_util.go
247 > if err := common.CheckEventBlobSizeLimit(
248 > workflowMemoSize,
249 > config.MemoSizeLimitWarn(namespaceName),
250 > config.MemoSizeLimitError(namespaceName),
251 > namespaceName,
252 > workflowID,
253 > "",
254 > handlerWithCommandTag,
255 > throttledLogger,
256 > operation,
257 > ); err != nil {
258 return common.ErrMemoSizeExceedsLimit
259 }
260
261 > return nil create_workflow_util.go
262 }
263
268 namespaceEntry *namespace.Namespace,
269 operation string,
270 > ) error { create_workflow_util.go
271 >
272 > workflowID := request.GetWorkflowId()
273 > maxIDLengthLimit := shard.GetConfig().MaxIDLengthLimit()
274 >
275 > if len(request.GetRequestId()) == 0 {
276 return serviceerror.NewInvalidArgument("Missing request ID.")
277 }
278 > if err := timestamp.ValidateAndCapProtoDuration(request.GetWorkflowExecutionTimeout()); err != nil { create_workflow_util.go
279 return serviceerror.NewInvalidArgumentf("invalid WorkflowExecutionTimeoutSeconds: %s", err.Error())
280 }
281 > if err := timestamp.ValidateAndCapProtoDuration(request.GetWorkflowRunTimeout()); err != nil { create_workflow_util.go
282 return serviceerror.NewInvalidArgumentf("invalid WorkflowRunTimeoutSeconds: %s", err.Error())
283 }
284 > if err := timestamp.ValidateAndCapProtoDuration(request.GetWorkflowTaskTimeout()); err != nil { create_workflow_util.go
285 return serviceerror.NewInvalidArgumentf("invalid WorkflowTaskTimeoutSeconds: %s", err.Error())
286 }
287 > if request.TaskQueue == nil || request.TaskQueue.GetName() == "" { create_workflow_util.go
288 return serviceerror.NewInvalidArgument("Missing Taskqueue.")
289 }
290 > if request.WorkflowType == nil || request.WorkflowType.GetName() == "" { create_workflow_util.go
291 return serviceerror.NewInvalidArgument("Missing WorkflowType.")
292 }
293 > if len(request.GetNamespace()) > maxIDLengthLimit { create_workflow_util.go
294 return serviceerror.NewInvalidArgument("Namespace exceeds length limit.")
295 }
296 > if len(request.GetWorkflowId()) > maxIDLengthLimit { create_workflow_util.go
297 return serviceerror.NewInvalidArgument("WorkflowId exceeds length limit.")
298 }
299 > if len(request.TaskQueue.GetName()) > maxIDLengthLimit { create_workflow_util.go
300 return serviceerror.NewInvalidArgument("TaskQueue exceeds length limit.")
301 }
302 > if len(request.WorkflowType.GetName()) > maxIDLengthLimit { create_workflow_util.go
303 return serviceerror.NewInvalidArgument("WorkflowType exceeds length limit.")
304 }
305
306 > if err := retrypolicy.Validate(request.RetryPolicy); err != nil { create_workflow_util.go
307 return err
308 }
309 > return ValidateStart( create_workflow_util.go
310 > ctx,
311 > shard,
312 > namespaceEntry,
313 > workflowID,
314 > request.GetInput().Size(),
315 > request.GetMemo().Size(),
316 > request.GetHeader().Size(),
317 > operation,
318 > )
319 }
320
324 shard historyi.ShardContext,
325 metricsHandler metrics.Handler,
327 > // workflow execution timeout is left as is
328 > // if workflow execution timeout == 0 -> infinity
329 >
330 > ns := namespace.Name(request.GetNamespace())
331 >
332 > workflowRunTimeout := overrideWorkflowRunTimeout(
333 > timestamp.DurationValue(request.GetWorkflowRunTimeout()),
334 > timestamp.DurationValue(request.GetWorkflowExecutionTimeout()),
335 > )
336 > if workflowRunTimeout != timestamp.DurationValue(request.GetWorkflowRunTimeout()) {
337 request.WorkflowRunTimeout = durationpb.New(workflowRunTimeout)
338 metrics.WorkflowRunTimeoutOverrideCount.With(metricsHandler).Record(
343 }
344
345 > workflowTaskStartToCloseTimeout := overrideWorkflowTaskTimeout( create_workflow_util.go
346 > ns,
347 > timestamp.DurationValue(request.GetWorkflowTaskTimeout()),
348 > timestamp.DurationValue(request.GetWorkflowRunTimeout()),
349 > shard.GetConfig().DefaultWorkflowTaskTimeout,
350 > )
351 > if workflowTaskStartToCloseTimeout != timestamp.DurationValue(request.GetWorkflowTaskTimeout()) {
352 > request.WorkflowTaskTimeout = durationpb.New(workflowTaskStartToCloseTimeout)
353 > metrics.WorkflowTaskTimeoutOverrideCount.With(metricsHandler).Record(
354 > 1,
355 > metrics.OperationTag(operation),
356 > metrics.NamespaceTag(ns.String()),
357 > )
358 > }
359 }
360
379 workflowRunTimeout time.Duration,
380 getDefaultTimeoutFunc func(namespaceName string) time.Duration,
381 > ) time.Duration { create_workflow_util.go
382 >
383 > if taskStartToCloseTimeout == 0 {
384 > taskStartToCloseTimeout = getDefaultTimeoutFunc(ns.String()) create_workflow_util.go
385 > }
386
387 > taskStartToCloseTimeout = min(taskStartToCloseTimeout, maxWorkflowTaskStartToCloseTimeout) create_workflow_util.go
388 >
389 > if workflowRunTimeout == 0 {
390 > return taskStartToCloseTimeout create_workflow_util.go
391 > }
392
393 return min(taskStartToCloseTimeout, workflowRunTimeout)
go.temporal.io/server/service/history/api/get_workflow_util.go 165 covered LOC · 43 ranges

Open complete file

32 workflowConsistencyChecker WorkflowConsistencyChecker,
33 eventNotifier events.Notifier,
34 > ) (*historyservice.GetMutableStateResponse, error) { get_workflow_util.go
35 >
36 > logger := shardContext.GetLogger()
37 > namespaceID := namespace.ID(request.GetNamespaceId())
38 > err := ValidateNamespaceUUID(namespaceID)
39 > if err != nil {
40 return nil, err
41 }
42
43 > if len(request.Execution.RunId) == 0 { get_workflow_util.go
44 request.Execution.RunId, err = workflowConsistencyChecker.GetCurrentWorkflowRunID(
45 ctx,
52 }
53 }
54 > workflowKey := definition.NewWorkflowKey( get_workflow_util.go
55 > request.NamespaceId,
56 > request.Execution.WorkflowId,
57 > request.Execution.RunId,
58 > )
59 > response, err := GetMutableStateWithConsistencyCheck(
60 > ctx,
61 > shardContext,
62 > workflowKey,
63 > request.VersionHistoryItem.GetVersion(),
64 > request.VersionHistoryItem.GetEventId(),
65 > request.VersionedTransition,
66 > workflowConsistencyChecker,
67 > )
68 > if err != nil {
69 return nil, err
70 }
71 > currentVersionHistory, err := versionhistory.GetCurrentVersionHistory(response.GetVersionHistories()) get_workflow_util.go
72 > if err != nil {
73 return nil, err
74 }
75 > if request.GetVersionHistoryItem() == nil { get_workflow_util.go
76 > lastVersionHistoryItem, err := versionhistory.GetLastVersionHistoryItem(currentVersionHistory)
77 > if err != nil {
78 return nil, err
79 }
80 > request.VersionHistoryItem = lastVersionHistoryItem get_workflow_util.go
81 }
82
83 > transitionHistory := response.GetTransitionHistory() get_workflow_util.go
84 > currentVersionedTransition := transitionhistory.LastVersionedTransition(transitionHistory)
85 > if len(transitionHistory) != 0 && request.VersionedTransition != nil {
86 if transitionhistory.StalenessCheck(transitionHistory, request.VersionedTransition) != nil {
87 logger.Warn(fmt.Sprintf("Request versioned transition and transition history don't match. Request: %v, current: %v",
101 // We return the full version histories. Callers need to fetch the last version history item from current branch
102 // and use the last version history item in following calls.
103 > if !versionhistory.ContainsVersionHistoryItem(currentVersionHistory, request.VersionHistoryItem) { get_workflow_util.go
104 logItem, err := versionhistory.GetLastVersionHistoryItem(currentVersionHistory)
105 if err != nil {
120
121 // expectedNextEventID is 0 when caller want to get the current next event ID without blocking.
122 > expectedNextEventID := common.FirstEventID get_workflow_util.go
123 > if request.ExpectedNextEventId != common.EmptyEventID {
124 > expectedNextEventID = request.GetExpectedNextEventId() get_workflow_util.go
125 > }
126
127 // if caller decide to long poll on workflow execution
128 // and the event ID we are looking for is smaller than current next event ID
129 > if expectedNextEventID >= response.GetNextEventId() && response.GetWorkflowStatus() == enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING { get_workflow_util.go
130 > subscriberID, channel, err := eventNotifier.WatchHistoryEvent(workflowKey) get_workflow_util.go
131 > if err != nil {
132 return nil, err
133 }
134 > defer func() { _ = eventNotifier.UnwatchHistoryEvent(workflowKey, subscriberID) }() get_workflow_util.go
135 // check again in case the next event ID is updated
136 > response, err = GetMutableStateWithConsistencyCheck( get_workflow_util.go
137 > ctx,
138 > shardContext,
139 > workflowKey,
140 > request.VersionHistoryItem.GetVersion(),
141 > request.VersionHistoryItem.GetEventId(),
142 > request.VersionedTransition,
143 > workflowConsistencyChecker,
144 > )
145 > if err != nil {
146 return nil, err
147 }
148 > currentVersionHistory, err = versionhistory.GetCurrentVersionHistory(response.GetVersionHistories()) get_workflow_util.go
149 > if err != nil {
150 return nil, err
151 }
152
153 > transitionHistory := response.GetTransitionHistory() get_workflow_util.go
154 > currentVersionedTransition := transitionhistory.LastVersionedTransition(transitionHistory)
155 > if len(transitionHistory) != 0 && request.VersionedTransition != nil {
156 if transitionhistory.StalenessCheck(transitionHistory, request.VersionedTransition) != nil {
157 logger.Warn(fmt.Sprintf("Request versioned transition and transition history don't match prior to polling the mutable state. Request: %v, current: %v",
164 }
165 }
166 > if !versionhistory.ContainsVersionHistoryItem(currentVersionHistory, request.VersionHistoryItem) { get_workflow_util.go
167 logItem, err := versionhistory.GetLastVersionHistoryItem(currentVersionHistory)
168 if err != nil {
178 return nil, serviceerrors.NewCurrentBranchChanged(response.CurrentBranchToken, request.CurrentBranchToken, currentVersionedTransition, request.VersionedTransition)
179 }
180 > if expectedNextEventID < response.GetNextEventId() || response.GetWorkflowStatus() != enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING { get_workflow_util.go
181 return response, nil
182 }
183
184 > namespaceRegistry, err := shardContext.GetNamespaceRegistry().GetNamespaceByID(namespaceID) get_workflow_util.go
185 > if err != nil {
186 return nil, err
187 }
188
189 // Send back response just before caller context would time out.
190 > longPollInterval := shardContext.GetConfig().LongPollExpirationInterval(namespaceRegistry.Name().String()) get_workflow_util.go
191 > longPollCtx, cancel := contextutil.WithDeadlineBuffer(ctx, longPollInterval, common.DefaultLongPollBuffer)
192 > defer cancel()
193 >
194 > for {
195 > select {
196 > case event := <-channel: get_workflow_util.go
197 > response.LastFirstEventId = event.LastFirstEventID
198 > response.LastFirstEventTxnId = event.LastFirstEventTxnID
199 > response.NextEventId = event.NextEventID
200 > response.PreviousStartedEventId = event.PreviousStartedEventID
201 > response.WorkflowState = event.WorkflowState
202 > response.WorkflowStatus = event.WorkflowStatus
203 > // Note: Later events could modify response.WorkerVersionStamp and we won't
204 > // update it here. That's okay since this return value is only informative and isn't used for task dispatch.
205 > // For correctness we could pass it in the Notification event.
206 > eventVersionHistory, err := versionhistory.GetCurrentVersionHistory(event.VersionHistories)
207 > if err != nil {
208 return nil, err
209 }
210 > response.CurrentBranchToken = eventVersionHistory.GetBranchToken() get_workflow_util.go
211 > response.VersionHistories = event.VersionHistories
212 > response.TransitionHistory = event.TransitionHistory
213 >
214 > notifiedEventVersionItem, err := versionhistory.GetLastVersionHistoryItem(eventVersionHistory)
215 > if err != nil {
216 return nil, err
217 }
218 // It is possible the notifier sends an out of date event, we can ignore this event.
219 > if versionhistory.CompareVersionHistoryItem(notifiedEventVersionItem, request.VersionHistoryItem) < 0 { get_workflow_util.go
220 continue
221 }
222 > transitionHistory := response.GetTransitionHistory() get_workflow_util.go
223 > currentVersionedTransition := transitionhistory.LastVersionedTransition(transitionHistory)
224 > if len(transitionHistory) != 0 && request.VersionedTransition != nil {
225 if transitionhistory.StalenessCheck(transitionHistory, request.VersionedTransition) != nil {
226 logger.Warn(fmt.Sprintf("Request versioned transition and transition history don't match after polling the mutable state. Request: %v, current: %v",
233 }
234 }
235 > if !versionhistory.ContainsVersionHistoryItem(eventVersionHistory, request.VersionHistoryItem) { get_workflow_util.go
236 logger.Warn("Request history branch and current history branch don't match after polling the mutable state",
237 tag.Value(notifiedEventVersionItem),
243 return nil, serviceerrors.NewCurrentBranchChanged(response.CurrentBranchToken, request.CurrentBranchToken, currentVersionedTransition, request.VersionedTransition)
244 }
245 > if expectedNextEventID < response.GetNextEventId() || response.GetWorkflowStatus() != enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING { get_workflow_util.go
246 > return response, nil
247 > }
248 case <-longPollCtx.Done():
249 return response, nil
303 versionedTransition *persistencespb.VersionedTransition,
304 workflowConsistencyChecker WorkflowConsistencyChecker,
305 > ) (_ *historyservice.GetMutableStateResponse, retError error) { get_workflow_util.go
306 >
307 > if len(workflowKey.RunID) == 0 {
308 return nil, serviceerror.NewInternalf(
309 "getMutableState encountered empty run ID: %v", workflowKey,
311 }
312
313 > workflowLease, err := workflowConsistencyChecker.GetWorkflowLeaseWithConsistencyCheck( get_workflow_util.go
314 > ctx,
315 > nil,
316 > func(mutableState historyi.MutableState) bool {
317 > transitionHistory := mutableState.GetExecutionInfo().GetTransitionHistory() get_workflow_util.go
318 > if len(transitionHistory) != 0 && versionedTransition != nil {
319 return transitionhistory.StalenessCheck(transitionHistory, versionedTransition) == nil
320 }
321
322 > currentVersionHistory, err := versionhistory.GetCurrentVersionHistory(mutableState.GetExecutionInfo().GetVersionHistories()) get_workflow_util.go
323 > if err != nil {
324 return false
325 }
326 > lastVersionHistoryItem, err := versionhistory.GetLastVersionHistoryItem(currentVersionHistory) get_workflow_util.go
327 > if err != nil {
328 return false
329 }
330
331 > if currentVersion == lastVersionHistoryItem.GetVersion() { get_workflow_util.go
332 > return currentEventID <= lastVersionHistoryItem.GetEventId() get_workflow_util.go
333 > }
334 return currentVersion < lastVersionHistoryItem.GetVersion()
335 },
337 locks.PriorityHigh,
338 )
339 > if err != nil { get_workflow_util.go
340 return nil, err
341 }
342 > defer func() { workflowLease.GetReleaseFn()(retError) }() get_workflow_util.go
343
344 > mutableState, err := workflowLease.GetContext().LoadMutableState(ctx, shardContext) get_workflow_util.go
345 > if err != nil {
346 return nil, err
347 }
348 > return MutableStateToGetResponse(mutableState) get_workflow_util.go
349 }
350
351 func MutableStateToGetResponse(
352 mutableState historyi.MutableState,
353 > ) (*historyservice.GetMutableStateResponse, error) { get_workflow_util.go
354 > // NOTE: fields of GetMutableStateResponse (returned value of this func)
355 > // are accessed outside of workflow lock, and, therefore,
356 > // ***MUST*** be copied by value from mutableState fields.
357 > // strings are immutable, []byte is also considered to be immutable.
358 >
359 > currentBranchToken, err := mutableState.GetCurrentBranchToken()
360 > if err != nil {
361 return nil, err
362 }
363
364 > executionInfo := mutableState.GetExecutionInfo() get_workflow_util.go
365 > workflowState, workflowStatus := mutableState.GetWorkflowStateStatus()
366 > lastFirstEventID, lastFirstEventTxnID := mutableState.GetLastFirstEventIDTxnID()
367 >
368 > var mostRecentWorkerVersionStamp *commonpb.WorkerVersionStamp
369 > if mrwvs := mutableState.GetExecutionInfo().GetMostRecentWorkerVersionStamp(); mrwvs != nil {
370 mostRecentWorkerVersionStamp = &commonpb.WorkerVersionStamp{
371 BuildId: mrwvs.GetBuildId(),
375
376 // Get transient/speculative workflow task events if present
377 > var transientOrSpeculativeTasks *historyspb.TransientWorkflowTaskInfo get_workflow_util.go
378 > if workflowTask := mutableState.GetPendingWorkflowTask(); workflowTask != nil {
379 > transientOrSpeculativeTasks = mutableState.GetTransientWorkflowTaskInfo(workflowTask, "") get_workflow_util.go
380 > } else if workflowTask := mutableState.GetStartedWorkflowTask(); workflowTask != nil { get_workflow_util.go
381 transientOrSpeculativeTasks = mutableState.GetTransientWorkflowTaskInfo(workflowTask, "")
382 }
383
384 > return &historyservice.GetMutableStateResponse{ get_workflow_util.go
385 > Execution: &commonpb.WorkflowExecution{
386 > WorkflowId: mutableState.GetExecutionInfo().WorkflowId,
387 > RunId: mutableState.GetExecutionState().RunId,
388 > },
389 > WorkflowType: &commonpb.WorkflowType{Name: executionInfo.WorkflowTypeName},
390 > LastFirstEventId: lastFirstEventID,
391 > LastFirstEventTxnId: lastFirstEventTxnID,
392 > NextEventId: mutableState.GetNextEventID(),
393 > PreviousStartedEventId: mutableState.GetLastCompletedWorkflowTaskStartedEventId(),
394 > TaskQueue: &taskqueuepb.TaskQueue{
395 > Name: executionInfo.TaskQueue,
396 > Kind: enumspb.TASK_QUEUE_KIND_NORMAL,
397 > },
398 > StickyTaskQueue: &taskqueuepb.TaskQueue{
399 > Name: executionInfo.StickyTaskQueue,
400 > Kind: enumspb.TASK_QUEUE_KIND_STICKY,
401 > NormalName: executionInfo.TaskQueue,
402 > },
403 > StickyTaskQueueScheduleToStartTimeout: executionInfo.StickyScheduleToStartTimeout,
404 > CurrentBranchToken: currentBranchToken,
405 > WorkflowState: workflowState,
406 > WorkflowStatus: workflowStatus,
407 > IsStickyTaskQueueEnabled: mutableState.IsStickyTaskQueueSet(),
408 > VersionHistories: versionhistory.CopyVersionHistories(
409 > mutableState.GetExecutionInfo().GetVersionHistories(),
410 > ),
411 > FirstExecutionRunId: executionInfo.FirstExecutionRunId,
412 > AssignedBuildId: mutableState.GetAssignedBuildId(),
413 > InheritedBuildId: mutableState.GetInheritedBuildId(),
414 > MostRecentWorkerVersionStamp: mostRecentWorkerVersionStamp,
415 > TransitionHistory: transitionhistory.CopyVersionedTransitions(mutableState.GetExecutionInfo().TransitionHistory),
416 > VersioningInfo: common.CloneProto(mutableState.GetExecutionInfo().VersioningInfo),
417 > TransientOrSpeculativeTasks: transientOrSpeculativeTasks,
418 > }, nil
419 }
go.temporal.io/server/common/cache/lru.go 163 covered LOC · 47 ranges

Open complete file

126 }
127
128 > func (entry *entryImpl) Size() int { lru.go
129 > return entry.size
130 > }
131
132 func (entry *entryImpl) CreateTime() time.Time {
135
136 // New creates a new cache with the given options
137 > func New(maxSize int, opts *Options) StoppableCache { lru.go
138 > return NewWithMetrics(maxSize, opts, metrics.NoopMetricsHandler)
139 > }
140
141 // NewWithMetrics creates a new cache that will emit capacity and ttl metrics.
142 // handler should be tagged with metrics.CacheTypeTag.
143 > func NewWithMetrics(maxSize int, opts *Options, handler metrics.Handler) StoppableCache { lru.go
144 > if opts == nil {
145 > opts = &Options{} lru.go
146 > }
147
148 > backgroundEvict := opts.BackgroundEvict lru.go
149 > if backgroundEvict == nil {
150 > backgroundEvict = func() dynamicconfig.CacheBackgroundEvictSettings { lru.go
151 > return dynamicconfig.CacheBackgroundEvictSettings{
152 > Enabled: false,
153 > }
154 > }
155 }
156
157 > timeSource := opts.TimeSource lru.go
158 > if timeSource == nil {
159 > timeSource = clock.NewRealTimeSource() lru.go
160 > }
161
162 > metrics.CacheSize.With(handler).Record(float64(maxSize)) lru.go
163 > metrics.CacheTtl.With(handler).Record(opts.TTL)
164 > c := &lru{
165 > byAccess: list.New(),
166 > byKey: make(map[any]*list.Element),
167 > ttl: opts.TTL,
168 > maxSize: maxSize,
169 > currSize: 0,
170 > pin: opts.Pin,
171 > onPut: opts.OnPut,
172 > onEvict: opts.OnEvict,
173 > timeSource: timeSource,
174 > metricsHandler: handler,
175 > backgroundEvict: backgroundEvict,
176 > }
177 > if c.backgroundEvict().Enabled {
178 c.loops.Go(c.bgEvictLoop)
179 }
180 > return c lru.go
181 }
182
188
189 // Get retrieves the value stored under the given key
190 > func (c *lru) Get(key any) any { lru.go
191 > if c.maxSize == 0 { //
192 return nil
193 }
194 > c.mut.Lock() lru.go
195 > defer c.mut.Unlock()
196 >
197 > element := c.byKey[key]
198 > if element == nil {
199 > return nil lru.go
200 > }
201
202 > entry := element.Value.(*entryImpl) lru.go
203 >
204 > if c.isEntryExpired(entry, c.timeSource.Now().UTC()) {
205 // Entry has expired
206 c.deleteInternal(element)
208 }
209
210 > metrics.CacheEntryAgeOnGet.With(c.metricsHandler).Record(c.timeSource.Now().UTC().Sub(entry.createTime)) lru.go
211 >
212 > c.updateEntryRefCount(entry)
213 > c.byAccess.MoveToFront(element)
214 > return entry.value
215 }
216
217 // Put puts a new value associated with a given key, returning the existing value (if present)
218 > func (c *lru) Put(key any, value any) any { lru.go
219 > if c.pin {
220 panic("Cannot use Put API in Pin mode. Use Delete and PutIfNotExist if necessary")
221 }
222 > val, _ := c.putInternal(key, value, true) lru.go
223 > return val
224 }
225
226 // PutIfNotExist puts a value associated with a given key if it does not exist
227 > func (c *lru) PutIfNotExist(key any, value any) (any, error) { lru.go
228 > existing, err := c.putInternal(key, value, false)
229 > if err != nil {
230 return nil, err
231 }
232
233 > if existing == nil { lru.go
234 > // This is a new value lru.go
235 > return value, err
236 > }
237
238 return existing, err
254
255 // Release decrements the ref count of a pinned element.
256 > func (c *lru) Release(key any) { lru.go
257 > if c.maxSize == 0 || !c.pin {
258 return
259 }
260 > c.mut.Lock() lru.go
261 > defer c.mut.Unlock()
262 >
263 > elt, ok := c.byKey[key]
264 > if !ok {
265 return
266 }
267 > entry := elt.Value.(*entryImpl) lru.go
268 > entry.refCount--
269 > if entry.refCount == 0 {
270 > c.pinnedSize -= entry.Size() lru.go
271 > metrics.CachePinnedUsage.With(c.metricsHandler).Record(float64(c.pinnedSize))
272 > }
273 // Entry size might have changed. Recalculate size and evict entries if necessary.
274 > newEntrySize := getSize(entry.value) lru.go
275 > c.currSize = c.calculateNewCacheSize(newEntrySize, entry.Size())
276 > entry.size = newEntrySize
277 > if c.currSize > c.maxSize {
278 c.tryEvictUntilCacheSizeUnderLimit()
279 }
280 > metrics.CacheUsage.With(c.metricsHandler).Record(float64(c.currSize)) lru.go
281 }
282
285 // The size of the value is calculated implementing the Sizeable interface. If the value does not implement
286 // the Sizeable interface, the size is 1.
287 > func (c *lru) Size() int { lru.go
288 > c.mut.Lock()
289 > defer c.mut.Unlock()
290 >
291 > return c.currSize
292 > }
293
294 // Put puts a new value associated with a given key, returning the existing value (if present)
295 // allowUpdate flag is used to control overwrite behavior if the value exists.
296 > func (c *lru) putInternal(key any, value any, allowUpdate bool) (any, error) { lru.go
297 > if c.maxSize == 0 {
298 return nil, nil
299 }
300 > newEntrySize := getSize(value) lru.go
301 > if newEntrySize > c.maxSize {
302 return nil, ErrCacheItemTooLarge
303 }
304
305 > c.mut.Lock() lru.go
306 > defer c.mut.Unlock()
307 >
308 > elt := c.byKey[key]
309 > // If the entry exists, check if it has expired or update the value
310 > if elt != nil {
311 > existingEntry := elt.Value.(*entryImpl) lru.go
312 > if !c.isEntryExpired(existingEntry, c.timeSource.Now().UTC()) {
313 > existingVal := existingEntry.value
314 >
315 > if allowUpdate {
316 > newCacheSize := c.calculateNewCacheSize(newEntrySize, existingEntry.Size()) lru.go
317 > if newCacheSize > c.maxSize {
318 c.tryEvictUntilEnoughSpaceWithSkipEntry(newEntrySize, existingEntry)
319 // calculate again after eviction
327 }
328 }
329 > existingEntry.value = value lru.go
330 > existingEntry.size = newEntrySize
331 > c.currSize = newCacheSize
332 > metrics.CacheUsage.With(c.metricsHandler).Record(float64(c.currSize))
333 > c.updateEntryTTL(existingEntry)
334 >
335 > if c.onPut != nil {
336 c.onPut(value)
337 }
338 }
339
340 > c.updateEntryRefCount(existingEntry) lru.go
341 > c.byAccess.MoveToFront(elt)
342 > return existingVal, nil
343 }
344
347 }
348
349 > c.tryEvictUntilEnoughSpaceWithSkipEntry(newEntrySize, nil) lru.go
350 >
351 > // check if the new entry can fit in the cache
352 > newCacheSize := c.calculateNewCacheSize(newEntrySize, emptyEntrySize)
353 > if newCacheSize > c.maxSize {
354 return nil, ErrCacheFull
355 }
356
357 > entry := &entryImpl{ lru.go
358 > key: key,
359 > value: value,
360 > size: newEntrySize,
361 > }
362 > c.updateEntryTTL(entry)
363 > c.updateEntryRefCount(entry)
364 > element := c.byAccess.PushFront(entry)
365 > c.byKey[key] = element
366 > c.currSize = newCacheSize
367 > metrics.CacheUsage.With(c.metricsHandler).Record(float64(c.currSize))
368 >
369 > if c.onPut != nil {
370 > c.onPut(value) lru.go
371 > }
372
373 > return nil, nil lru.go
374 }
375
376 > func (c *lru) calculateNewCacheSize(newEntrySize int, existingEntrySize int) int { lru.go
377 > return c.currSize - existingEntrySize + newEntrySize
378 > }
379
380 func (c *lru) deleteInternal(element *list.Element) {
397 // tryEvictUntilEnoughSpaceWithSkipEntry try to evict entries until there is enough space for the new entry without
398 // evicting the existing entry. the existing entry is skipped because it is being updated.
399 > func (c *lru) tryEvictUntilEnoughSpaceWithSkipEntry(newEntrySize int, existingEntry *entryImpl) { lru.go
400 > element := c.byAccess.Back()
401 > existingEntrySize := 0
402 > if existingEntry != nil {
403 existingEntrySize = existingEntry.Size()
404 }
405
406 > for c.calculateNewCacheSize(newEntrySize, existingEntrySize) > c.maxSize && element != nil { lru.go
407 entry := element.Value.(*entryImpl)
408 if existingEntry != nil && entry.key == existingEntry.key {
426 }
427
428 > func (c *lru) isEntryExpired(entry *entryImpl, currentTime time.Time) bool { lru.go
429 > return entry.refCount == 0 && !entry.createTime.IsZero() && currentTime.After(entry.createTime.Add(c.ttl))
430 > }
431
432 > func (c *lru) updateEntryTTL(entry *entryImpl) { lru.go
433 > if c.ttl != 0 {
434 > entry.createTime = c.timeSource.Now().UTC() lru.go
435 > }
436 }
437
438 > func (c *lru) updateEntryRefCount(entry *entryImpl) { lru.go
439 > if c.pin {
440 > entry.refCount++ lru.go
441 > if entry.refCount == 1 {
442 > c.pinnedSize += entry.Size()
443 > metrics.CachePinnedUsage.With(c.metricsHandler).Record(float64(c.pinnedSize))
444 > }
445 }
446 }
447
448 > func (c *lru) Stop() { lru.go
449 > c.loops.Cancel()
450 > }
451
452 func (c *lru) bgEvictLoop(ctx context.Context) error {
go.temporal.io/server/service/history/timer_queue_factory.go 162 covered LOC · 3 ranges

Open complete file

39 func NewTimerQueueFactory(
40 params timerQueueFactoryParams,
41 > ) QueueFactory { timer_queue_factory.go
42 > return &timerQueueFactory{
43 > timerQueueFactoryParams: params,
44 > QueueFactoryBase: QueueFactoryBase{
45 > HostScheduler: queues.NewScheduler(
46 > params.ClusterMetadata.GetCurrentClusterName(),
47 > queues.SchedulerOptions{
48 > WorkerCount: params.Config.TimerProcessorSchedulerWorkerCount,
49 > ActiveNamespaceWeights: params.Config.TimerProcessorSchedulerActiveRoundRobinWeights,
50 > StandbyNamespaceWeights: params.Config.TimerProcessorSchedulerStandbyRoundRobinWeights,
51 > InactiveNamespaceDeletionDelay: params.Config.TaskSchedulerInactiveChannelDeletionDelay,
52 > ExecutionAwareSchedulerOptions: ctasks.ExecutionAwareSchedulerOptions{
53 > Enabled: params.Config.TaskSchedulerEnableExecutionQueueScheduler,
54 > MaxQueues: params.Config.TaskSchedulerExecutionQueueSchedulerMaxQueues,
55 > QueueTTL: params.Config.TaskSchedulerExecutionQueueSchedulerQueueTTL,
56 > QueueConcurrency: params.Config.TaskSchedulerExecutionQueueSchedulerQueueConcurrency,
57 > },
58 > },
59 > params.NamespaceRegistry,
60 > params.Logger,
61 > params.MetricsHandler,
62 > params.TimeSource,
63 > ),
64 > HostPriorityAssigner: queues.NewPriorityAssigner(
65 > params.NamespaceRegistry,
66 > params.ClusterMetadata.GetCurrentClusterName(),
67 > ),
68 > HostReaderRateLimiter: queues.NewReaderPriorityRateLimiter(
69 > NewHostRateLimiterRateFn(
70 > params.Config.TimerProcessorMaxPollHostRPS,
71 > params.Config.PersistenceMaxQPS,
72 > timerQueuePersistenceMaxRPSRatio,
73 > ),
74 > int64(params.Config.TimerQueueMaxReaderCount()),
75 > ),
76 > Tracer: params.TracerProvider.Tracer(telemetry.ComponentQueueTimer),
77 > },
78 > }
79 > }
80
81 func (f *timerQueueFactory) CreateQueue(
82 shardContext historyi.ShardContext,
83 > ) queues.Queue { timer_queue_factory.go
84 > logger := log.With(shardContext.GetLogger(), tag.ComponentTimerQueue)
85 > metricsHandler := f.MetricsHandler.WithTags(metrics.OperationTag(metrics.OperationTimerQueueProcessorScope))
86 >
87 > currentClusterName := f.ClusterMetadata.GetCurrentClusterName()
88 > workflowDeleteManager := deletemanager.NewDeleteManager(
89 > shardContext,
90 > f.WorkflowCache,
91 > f.Config,
92 > shardContext.GetTimeSource(),
93 > f.VisibilityManager,
94 > )
95 >
96 > shardScheduler := queues.NewRateLimitedScheduler(
97 > f.HostScheduler,
98 > queues.RateLimitedSchedulerOptions{
99 > Enabled: f.Config.TaskSchedulerEnableRateLimiter,
100 > EnableShadowMode: f.Config.TaskSchedulerEnableRateLimiterShadowMode,
101 > StartupDelay: f.Config.TaskSchedulerRateLimiterStartupDelay,
102 > },
103 > currentClusterName,
104 > f.NamespaceRegistry,
105 > f.SchedulerRateLimiter,
106 > f.TimeSource,
107 > f.ChasmRegistry,
108 > logger,
109 > metricsHandler,
110 > )
111 >
112 > rescheduler := queues.NewRescheduler(
113 > shardScheduler,
114 > shardContext.GetTimeSource(),
115 > logger,
116 > metricsHandler,
117 > )
118 >
119 > activeExecutor := newTimerQueueActiveTaskExecutor(
120 > shardContext,
121 > f.WorkflowCache,
122 > workflowDeleteManager,
123 > logger,
124 > f.MetricsHandler,
125 > f.Config,
126 > f.MatchingRawClient,
127 > f.ChasmEngine,
128 > )
129 >
130 > standbyExecutor := newTimerQueueStandbyTaskExecutor(
131 > shardContext,
132 > f.WorkflowCache,
133 > workflowDeleteManager,
134 > f.MatchingRawClient,
135 > f.ChasmEngine,
136 > logger,
137 > f.MetricsHandler,
138 > // note: the cluster name is for calculating time for standby tasks,
139 > // here we are basically using current cluster time
140 > // this field will be deprecated soon, currently exists so that
141 > // we have the option of revert to old behavior
142 > currentClusterName,
143 > f.Config,
144 > f.ClientBean,
145 > )
146 >
147 > executor := queues.NewActiveStandbyExecutor(
148 > currentClusterName,
149 > f.NamespaceRegistry,
150 > activeExecutor,
151 > standbyExecutor,
152 > logger,
153 > )
154 > if f.ExecutorWrapper != nil {
155 executor = f.ExecutorWrapper.Wrap(executor)
156 }
157
158 > factory := queues.NewExecutableFactory( timer_queue_factory.go
159 > executor,
160 > shardScheduler,
161 > rescheduler,
162 > f.HostPriorityAssigner,
163 > shardContext.GetTimeSource(),
164 > shardContext.GetNamespaceRegistry(),
165 > shardContext.GetClusterMetadata(),
166 > f.ChasmRegistry,
167 > queues.GetTaskTypeTagValue,
168 > logger,
169 > metricsHandler,
170 > f.Tracer,
171 > f.DLQWriter,
172 > f.Config.TaskDLQEnabled,
173 > f.Config.TaskDLQUnexpectedErrorAttempts,
174 > f.Config.TaskDLQInternalErrors,
175 > f.Config.TaskDLQErrorPattern,
176 > )
177 > return queues.NewScheduledQueue(
178 > shardContext,
179 > tasks.CategoryTimer,
180 > shardScheduler,
181 > rescheduler,
182 > factory,
183 > &queues.Options{
184 > ReaderOptions: queues.ReaderOptions{
185 > BatchSize: f.Config.TimerTaskBatchSize,
186 > MaxPendingTasksCount: f.Config.QueuePendingTaskMaxCount,
187 > PollBackoffInterval: f.Config.TimerProcessorPollBackoffInterval,
188 > MaxPredicateSize: f.Config.QueueMaxPredicateSize,
189 > },
190 > MonitorOptions: queues.MonitorOptions{
191 > PendingTasksCriticalCount: f.Config.QueuePendingTaskCriticalCount,
192 > ReaderStuckCriticalAttempts: f.Config.QueueReaderStuckCriticalAttempts,
193 > SliceCountCriticalThreshold: f.Config.QueueCriticalSlicesCount,
194 > },
195 > MaxPollRPS: f.Config.TimerProcessorMaxPollRPS,
196 > MaxPollInterval: f.Config.TimerProcessorMaxPollInterval,
197 > MaxPollIntervalJitterCoefficient: f.Config.TimerProcessorMaxPollIntervalJitterCoefficient,
198 > CheckpointInterval: f.Config.TimerProcessorUpdateAckInterval,
199 > CheckpointIntervalJitterCoefficient: f.Config.TimerProcessorUpdateAckIntervalJitterCoefficient,
200 > MaxReaderCount: f.Config.TimerQueueMaxReaderCount,
201 > MoveGroupTaskCountBase: f.Config.QueueMoveGroupTaskCountBase,
202 > MoveGroupTaskCountMultiplier: f.Config.QueueMoveGroupTaskCountMultiplier,
203 > ShrinkPredicateMaxPendingKeys: f.Config.QueueShrinkPredicateMaxPendingKeys,
204 > },
205 > f.HostReaderRateLimiter,
206 > logger,
207 > metricsHandler,
208 > )
209 }
go.temporal.io/server/service/history/transfer_queue_active_task_executor.go 162 covered LOC · 37 ranges

Open complete file

74 versionCache worker_versioning.VersionMembershipAndReactivationStatusCache,
75 testHooks testhooks.TestHooks,
76 > ) queues.Executor { transfer_queue_active_task_executor.go
77 > return &transferQueueActiveTaskExecutor{
78 > transferQueueTaskExecutorBase: newTransferQueueTaskExecutorBase(
79 > shard,
80 > workflowCache,
81 > logger,
82 > metricProvider,
83 > historyRawClient,
84 > matchingRawClient,
85 > visibilityManager,
86 > chasmEngine,
87 > ),
88 > workflowResetter: ndc.NewWorkflowResetter(
89 > shard,
90 > workflowCache,
91 > logger,
92 > ),
93 > parentClosePolicyClient: parentclosepolicy.NewClient(
94 > shard.GetMetricsHandler(),
95 > shard.GetLogger(),
96 > sdkClientFactory,
97 > config.NumParentClosePolicySystemWorkflows(),
98 > ),
99 > versionCache: versionCache,
100 > testHooks: testHooks,
101 > }
102 > }
103
104 func (t *transferQueueActiveTaskExecutor) Execute(
105 ctx context.Context,
106 executable queues.Executable,
107 > ) queues.ExecuteResponse { transfer_queue_active_task_executor.go
108 > task := executable.GetTask()
109 >
110 > // Tests use this hook to intercept tasks.
111 > if hook, ok := testhooks.Get(
112 > t.testHooks,
113 > testhooks.HistoryTransferTaskInterceptor,
114 > namespace.ID(task.GetNamespaceID()),
115 > ); ok {
116 var response queues.ExecuteResponse
117 hook(task, func() {
128 executable queues.Executable,
129 task tasks.Task,
130 > ) queues.ExecuteResponse { transfer_queue_active_task_executor.go
131 > taskType := queues.GetActiveTransferTaskTypeTagValue(task, t.shardContext.ChasmRegistry())
132 > namespaceTag, replicationState := getNamespaceTagAndReplicationStateByID(
133 > t.shardContext.GetNamespaceRegistry(),
134 > task.GetNamespaceID(),
135 > executable.GetWorkflowID(),
136 > )
137 > metricsTags := []metrics.Tag{
138 > namespaceTag,
139 > metrics.TaskTypeTag(taskType),
140 > metrics.OperationTag(taskType), // for backward compatibility
141 > }
142 >
143 > if replicationState == enumspb.REPLICATION_STATE_HANDOVER {
144 // TODO: exclude task types here if we believe it's safe & necessary to execute
145 // them during namespace handover.
153 }
154
156 > switch task := task.(type) {
157 case *tasks.ActivityTask:
158 err = t.processActivityTask(ctx, task)
159 > case *tasks.WorkflowTask: transfer_queue_active_task_executor.go
160 > err = t.processWorkflowTask(ctx, task)
161 > case *tasks.CloseExecutionTask: transfer_queue_active_task_executor.go
162 > err = t.processCloseExecution(ctx, task)
163 case *tasks.CancelExecutionTask:
164 err = t.processCancelExecution(ctx, task)
178 }
179
180 > return queues.ExecuteResponse{ transfer_queue_active_task_executor.go
181 > ExecutionMetricTags: metricsTags,
182 > ExecutedAsActive: true,
183 > ExecutionErr: err,
184 > }
185 }
186
288 ctx context.Context,
289 transferTask *tasks.WorkflowTask,
290 > ) (retError error) { transfer_queue_active_task_executor.go
291 > ctx, cancel := context.WithTimeout(ctx, taskTimeout)
292 > defer cancel()
293 >
294 > weContext, release, err := getWorkflowExecutionContextForTask(ctx, t.shardContext, t.cache, transferTask)
295 > if err != nil {
296 return err
297 }
298 > defer func() { release(retError) }() transfer_queue_active_task_executor.go
299
300 > mutableState, err := loadMutableStateForTransferTask(ctx, t.shardContext, weContext, transferTask, t.metricHandler, t.logger) transfer_queue_active_task_executor.go
301 > if err != nil {
302 return err
303 }
304 > if mutableState == nil || !mutableState.IsWorkflowExecutionRunning() { transfer_queue_active_task_executor.go
305 return nil
306 }
307
308 > workflowTask := mutableState.GetWorkflowTaskByID(transferTask.ScheduledEventID) transfer_queue_active_task_executor.go
309 > if workflowTask == nil {
310 return nil
311 }
312 > if transferTask.Stamp != workflowTask.Stamp { transfer_queue_active_task_executor.go
313 release(nil) // release(nil) so that the mutable state is not unloaded from cache
314 return consts.ErrStaleReference
315 }
316 > err = CheckTaskVersion(t.shardContext, t.logger, mutableState.GetNamespaceEntry(), workflowTask.Version, transferTask.Version, transferTask) transfer_queue_active_task_executor.go
317 > if err != nil {
318 return err
319 }
323 // it can't be used here, because timeout timer was not created for it,
324 // because it used to be non-sticky when this transfer task was created .
325 > taskQueue, scheduleToStartTimeout := mutableState.TaskQueueScheduleToStartTimeout(transferTask.TaskQueue) transfer_queue_active_task_executor.go
326 >
327 > normalTaskQueueName := mutableState.GetExecutionInfo().TaskQueue
328 >
329 > directive := MakeDirectiveForWorkflowTask(mutableState)
330 > priority := mutableState.GetExecutionInfo().Priority
331 >
332 > // NOTE: Do not access mutableState after this lock is released.
333 > // It is important to release the workflow lock here, because pushWorkflowTask will call matching,
334 > // which will call history back (with RecordWorkflowTaskStarted), and it will try to get workflow lock again.
335 > release(nil)
336 >
337 > err = t.pushWorkflowTask(
338 > ctx,
339 > transferTask,
340 > taskQueue,
341 > scheduleToStartTimeout.AsDuration(),
342 > directive,
343 > priority,
344 > historyi.TransactionPolicyActive,
345 > )
346 >
347 > if _, ok := err.(*serviceerrors.StickyWorkerUnavailable); ok {
348 // sticky worker is unavailable, switch to original normal task queue
349 taskQueue = &taskqueuepb.TaskQueue{
375 ctx context.Context,
376 task *tasks.CloseExecutionTask,
377 > ) (retError error) { transfer_queue_active_task_executor.go
378 > ctx, cancel := context.WithTimeout(ctx, taskTimeout)
379 > defer cancel()
380 >
381 > weContext, release, err := getWorkflowExecutionContextForTask(ctx, t.shardContext, t.cache, task)
382 > if err != nil {
383 return err
384 }
385 > defer func() { release(retError) }() transfer_queue_active_task_executor.go
386
387 > mutableState, err := loadMutableStateForTransferTask(ctx, t.shardContext, weContext, task, t.metricHandler, t.logger) transfer_queue_active_task_executor.go
388 > if err != nil {
389 return err
390 }
391 > if mutableState == nil || mutableState.IsWorkflowExecutionRunning() { transfer_queue_active_task_executor.go
392 return nil
393 }
395 // DeleteAfterClose is set to true when this close execution task was generated as part of delete open workflow execution procedure.
396 // Delete workflow execution is started by user API call and should be done regardless of current workflow version.
397 > if !task.DeleteAfterClose { transfer_queue_active_task_executor.go
398 > closeVersion, err := mutableState.GetCloseVersion()
399 > if err != nil {
400 return err
401 }
402 > err = CheckTaskVersion(t.shardContext, t.logger, mutableState.GetNamespaceEntry(), closeVersion, task.Version, task) transfer_queue_active_task_executor.go
403 > if err != nil {
404 return err
405 }
406 }
407
408 > workflowExecution := commonpb.WorkflowExecution{ transfer_queue_active_task_executor.go
409 > WorkflowId: task.GetWorkflowID(),
410 > RunId: task.GetRunID(),
411 > }
412 > executionInfo := mutableState.GetExecutionInfo()
413 > children := copyChildWorkflowInfos(mutableState.GetPendingChildExecutionInfos())
414 > var completionEvent *historypb.HistoryEvent // needed to report close event to parent workflow
415 > replyToParentWorkflow := mutableState.HasParentExecution() && executionInfo.NewExecutionRunId == ""
416 > if replyToParentWorkflow || len(children) > 0 {
417 // only load close event if needed.
418 completionEvent, err = mutableState.GetCompletionEvent(ctx)
422 replyToParentWorkflow = replyToParentWorkflow && !ndc.IsTerminatedByResetter(completionEvent)
423 }
424 > parentNamespaceID := executionInfo.ParentNamespaceId transfer_queue_active_task_executor.go
425 > parentWorkflowID := executionInfo.ParentWorkflowId
426 > parentRunID := executionInfo.ParentRunId
427 > parentInitiatedID := executionInfo.ParentInitiatedId
428 > parentInitiatedVersion := executionInfo.ParentInitiatedVersion
429 > var parentClock *clockspb.VectorClock
430 > if executionInfo.ParentClock != nil {
431 parentClock = vclock.NewVectorClock(
432 executionInfo.ParentClock.ClusterId,
436 }
437
438 > namespaceName := mutableState.GetNamespaceEntry().Name() transfer_queue_active_task_executor.go
439 >
440 > firstRunID, err := mutableState.GetFirstRunID(ctx)
441 > if err != nil {
442 return err
443 }
446 // Release lock immediately since mutable state is not needed
447 // and the rest of logic is RPC calls, which can take time.
449 >
450 > // Communicate the result to parent execution if this is Child Workflow execution
451 > if replyToParentWorkflow {
452 _, err := t.historyRawClient.RecordChildExecutionCompleted(ctx, &historyservice.RecordChildExecutionCompletedRequest{
453 NamespaceId: parentNamespaceID,
478 // So we need to additionally check the termination reason for this parent to determine if this task was indeed created due to reset or due to normal completion of the WF.
479 // Also, checking the dynamic config is not strictly safe since by definition it can change at any time. However this reduces the chance of us skipping the parent close policy when we shouldn't.
480 > allowResetWithPendingChildren := t.config.AllowResetWithPendingChildren(namespaceName.String()) transfer_queue_active_task_executor.go
481 > shouldSkipParentClosePolicy := false
482 > isParentTerminatedDueToReset := (completionEvent != nil) && ndc.IsTerminatedByResetter(completionEvent)
483 > if isParentTerminatedDueToReset && executionInfo.GetResetRunId() != "" && allowResetWithPendingChildren {
484 // TODO (Chetan): update this condition as new reset policies/cases are added.
485 shouldSkipParentClosePolicy = true // only skip if the parent is reset and we are using the new flow.
486 }
487 > if !shouldSkipParentClosePolicy { transfer_queue_active_task_executor.go
488 > if err := t.processParentClosePolicy( transfer_queue_active_task_executor.go
489 > ctx,
490 > namespaceName.String(),
491 > &workflowExecution,
492 > children,
493 > ); err != nil {
494 // This is some retryable error, not NotFound or NamespaceNotFound.
495 return err
1857 parentExecution *commonpb.WorkflowExecution,
1858 childInfos map[int64]*persistencespb.ChildExecutionInfo,
1860 > if len(childInfos) == 0 {
1862 > }
1863
1864 scope := t.metricHandler.WithTags(metrics.OperationTag(metrics.TransferActiveTaskCloseExecutionScope))
go.temporal.io/server/common/metrics/tally_metrics_handler.go 160 covered LOC · 48 ranges

Open complete file

37 }
38
39 > func newSharedScopeCache(maxSize int) *sharedScopeCache { tally_metrics_handler.go
40 > return &sharedScopeCache{
41 > maxSize: maxSize,
42 > scopes: make(map[string]tally.Scope),
43 > handlers: make(map[string]*tallyMetricsHandler),
44 > }
45 > }
46
47 > func (c *sharedScopeCache) loadOrStoreScope(key string, create func() tally.Scope) tally.Scope { tally_metrics_handler.go
48 > c.mu.RLock()
49 > if s, ok := c.scopes[key]; ok {
50 > c.mu.RUnlock() tally_metrics_handler.go
51 > return s
52 > }
53 > c.mu.RUnlock() tally_metrics_handler.go
54 >
55 > s := create()
56 >
57 > c.mu.Lock()
58 > defer c.mu.Unlock()
59 > // Double-check: another goroutine may have inserted while we were creating.
60 > if existing, ok := c.scopes[key]; ok {
61 > return existing tally_metrics_handler.go
62 > }
63 > if len(c.scopes) >= c.maxSize { tally_metrics_handler.go
64 clear(c.scopes)
65 }
66 > c.scopes[key] = s tally_metrics_handler.go
67 > return s
68 }
69
70 > func (c *sharedScopeCache) loadOrStoreHandler(key string, create func() *tallyMetricsHandler) *tallyMetricsHandler { tally_metrics_handler.go
71 > c.mu.RLock()
72 > if h, ok := c.handlers[key]; ok {
73 > c.mu.RUnlock() tally_metrics_handler.go
74 > return h
75 > }
76 > c.mu.RUnlock() tally_metrics_handler.go
77 >
78 > h := create()
79 >
80 > c.mu.Lock()
81 > defer c.mu.Unlock()
82 > // Double-check: another goroutine may have inserted while we were creating.
83 > if existing, ok := c.handlers[key]; ok {
84 > return existing tally_metrics_handler.go
85 > }
86 > if len(c.handlers) >= c.maxSize { tally_metrics_handler.go
87 clear(c.handlers)
88 }
89 > c.handlers[key] = h tally_metrics_handler.go
90 > return h
91 }
92
109 var _ Handler = (*tallyMetricsHandler)(nil)
110
111 > func NewTallyMetricsHandler(cfg ClientConfig, scope tally.Scope) *tallyMetricsHandler { tally_metrics_handler.go
112 > perUnitBuckets := make(map[MetricUnit]tally.Buckets)
113 >
114 > for unit, boundariesList := range cfg.PerUnitHistogramBoundaries {
115 > perUnitBuckets[MetricUnit(unit)] = tally.ValueBuckets(boundariesList) tally_metrics_handler.go
116 > }
117
118 > maxSize := cfg.TagsCacheMaxSize tally_metrics_handler.go
119 > if maxSize <= 0 {
120 > maxSize = defaultTagsCacheMaxSize tally_metrics_handler.go
121 > }
122
123 > return &tallyMetricsHandler{ tally_metrics_handler.go
124 > scope: scope,
125 > perUnitBuckets: perUnitBuckets,
126 > excludeTags: configExcludeTags(cfg),
127 > cache: newSharedScopeCache(maxSize),
128 > scopeKey: "",
129 > }
130 }
131
132 // tagsCacheKey builds a compact string key from a tag slice for use as a
133 // map lookup key.
134 > func tagsCacheKey(tags []Tag) string { tally_metrics_handler.go
135 > size := 0
136 > for i := range tags {
137 > size += len(tags[i].Key) + len(tags[i].Value) + 2*binary.MaxVarintLen64
138 > }
139 > var sb strings.Builder
140 > sb.Grow(size)
141 > for _, t := range tags {
142 > appendCacheKeyPart(&sb, t.Key)
143 > appendCacheKeyPart(&sb, t.Value)
144 > }
145 > return sb.String()
146 }
147
148 > func appendCacheKeyPart(sb *strings.Builder, value string) { tally_metrics_handler.go
149 > var lenBuf [binary.MaxVarintLen64]byte
150 > n := binary.PutUvarint(lenBuf[:], uint64(len(value)))
151 > _, _ = sb.Write(lenBuf[:n])
152 > sb.WriteString(value)
153 > }
154
155 // WithTags creates a new MetricProvider with provided []Tag
156 // Tags are merged with registered Tags from the source MetricsHandler.
157 // Handlers are cached by tag combination so repeated calls avoid allocations.
158 > func (tmh *tallyMetricsHandler) WithTags(tags ...Tag) Handler { tally_metrics_handler.go
159 > if len(tags) == 0 {
160 return tmh
161 }
162 > normalizedKey := tagsCacheKey(normalizeTagsForCaching(tags, tmh.excludeTags)) tally_metrics_handler.go
163 > key := tmh.scopeKey + normalizedKey
164 > return tmh.cache.loadOrStoreHandler(key, func() *tallyMetricsHandler {
165 > return &tallyMetricsHandler{
166 > scope: tmh.scope.Tagged(tagsToMap(tags, tmh.excludeTags)),
167 > perUnitBuckets: tmh.perUnitBuckets,
168 > excludeTags: tmh.excludeTags,
169 > cache: tmh.cache,
170 > scopeKey: key,
171 > }
172 > })
173 }
174
178 // excludeTags before cache key computation so that different raw values which
179 // map to the same excluded placeholder share a single cache entry.
180 > func (tmh *tallyMetricsHandler) cachedTaggedScope(tags []Tag) tally.Scope { tally_metrics_handler.go
181 > if len(tags) == 0 {
182 > return tmh.scope tally_metrics_handler.go
183 > }
184 > key := tmh.scopeKey + tagsCacheKey(normalizeTagsForCaching(tags, tmh.excludeTags)) tally_metrics_handler.go
185 > return tmh.cache.loadOrStoreScope(key, func() tally.Scope {
186 > return tmh.scope.Tagged(tagsToMap(tags, tmh.excludeTags))
187 > })
188 }
189
190 // normalizeTag applies excludeTags substitution to a single tag.
191 // Returns the (possibly modified) tag and whether it was normalized.
192 > func normalizeTag(t Tag, excl excludeTags) (Tag, bool) { tally_metrics_handler.go
193 > if vals, ok := excl[t.Key]; ok {
194 if _, ok := vals[t.Value]; !ok {
195 return Tag{Key: t.Key, Value: tagExcludedValue}, true
196 }
197 }
198 > return t, false tally_metrics_handler.go
199 }
200
202 // canonical tag values for cache key computation. Returns the original slice
203 // unchanged if no tags need normalization (zero-alloc fast path).
204 > func normalizeTagsForCaching(tags []Tag, excl excludeTags) []Tag { tally_metrics_handler.go
205 > if len(excl) == 0 {
206 > return tags tally_metrics_handler.go
207 > }
208 var normalized []Tag
209 for i, t := range tags {
223
224 // Counter obtains a counter for the given name.
225 > func (tmh *tallyMetricsHandler) Counter(counter string) CounterIface { tally_metrics_handler.go
226 > if v, ok := tmh.counters.Load(counter); ok {
227 > return v.(CounterIface) //nolint:revive // type-safe: only CounterIface is stored tally_metrics_handler.go
228 > }
229 > c := CounterFunc(func(i int64, t ...Tag) { tally_metrics_handler.go
230 > tmh.cachedTaggedScope(t).Counter(counter).Inc(i)
231 > })
232 > actual, _ := tmh.counters.LoadOrStore(counter, c)
233 > return actual.(CounterIface) //nolint:revive // type-safe: only CounterIface is stored
234 }
235
236 // Gauge obtains a gauge for the given name.
237 > func (tmh *tallyMetricsHandler) Gauge(gauge string) GaugeIface { tally_metrics_handler.go
238 > if v, ok := tmh.gauges.Load(gauge); ok {
239 > return v.(GaugeIface) //nolint:revive // type-safe: only GaugeIface is stored tally_metrics_handler.go
240 > }
241 > g := GaugeFunc(func(f float64, t ...Tag) { tally_metrics_handler.go
242 > tmh.cachedTaggedScope(t).Gauge(gauge).Update(f)
243 > })
244 > actual, _ := tmh.gauges.LoadOrStore(gauge, g)
245 > return actual.(GaugeIface) //nolint:revive // type-safe: only GaugeIface is stored
246 }
247
248 // Timer obtains a timer for the given name.
249 > func (tmh *tallyMetricsHandler) Timer(timer string) TimerIface { tally_metrics_handler.go
250 > if v, ok := tmh.timers.Load(timer); ok {
251 > return v.(TimerIface) //nolint:revive // type-safe: only TimerIface is stored tally_metrics_handler.go
252 > }
253 > ti := TimerFunc(func(d time.Duration, t ...Tag) { tally_metrics_handler.go
254 > tmh.cachedTaggedScope(t).Timer(timer).Record(d)
255 > })
256 > actual, _ := tmh.timers.LoadOrStore(timer, ti)
257 > return actual.(TimerIface) //nolint:revive // type-safe: only TimerIface is stored
258 }
259
260 // Histogram obtains a histogram for the given name.
261 > func (tmh *tallyMetricsHandler) Histogram(histogram string, unit MetricUnit) HistogramIface { tally_metrics_handler.go
262 > key := histogramCacheKey{name: histogram, unit: unit}
263 > if v, ok := tmh.histograms.Load(key); ok {
264 > return v.(HistogramIface) //nolint:revive // type-safe: only HistogramIface is stored tally_metrics_handler.go
265 > }
266 > h := HistogramFunc(func(i int64, t ...Tag) { tally_metrics_handler.go
267 > tmh.cachedTaggedScope(t).Histogram(histogram, tmh.perUnitBuckets[unit]).RecordValue(float64(i)) tally_metrics_handler.go
268 > })
269 > actual, _ := tmh.histograms.LoadOrStore(key, h) tally_metrics_handler.go
270 > return actual.(HistogramIface) //nolint:revive // type-safe: only HistogramIface is stored
271 }
272
273 > func (*tallyMetricsHandler) Stop(log.Logger) {} tally_metrics_handler.go
274
275 > func (*tallyMetricsHandler) Close() error { tally_metrics_handler.go
276 > return nil
277 > }
278
279 > func (tmh *tallyMetricsHandler) StartBatch(_ string) BatchHandler { tally_metrics_handler.go
280 > return tmh
281 > }
282
283 > func tagsToMap(t1 []Tag, e excludeTags) map[string]string { tally_metrics_handler.go
284 > if len(t1) == 0 {
285 return nil
286 }
287
288 > m := make(map[string]string, len(t1)) tally_metrics_handler.go
289 > for i := range t1 {
290 > nt, _ := normalizeTag(t1[i], e)
291 > m[nt.Key] = nt.Value
292 > }
293 > return m
294 }
go.temporal.io/server/api/persistence/v1/tasks.pb.go 159 covered LOC · 46 ranges

Open complete file

39 }
40
41 > func (x *AllocatedTaskInfo) Reset() { tasks.pb.go
42 > *x = AllocatedTaskInfo{}
43 > mi := &file_temporal_server_api_persistence_v1_tasks_proto_msgTypes[0]
44 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
45 > ms.StoreMessageInfo(mi)
46 > }
47
48 func (x *AllocatedTaskInfo) String() string {
52 func (*AllocatedTaskInfo) ProtoMessage() {}
53
54 > func (x *AllocatedTaskInfo) ProtoReflect() protoreflect.Message { tasks.pb.go
55 > mi := &file_temporal_server_api_persistence_v1_tasks_proto_msgTypes[0]
56 > if x != nil {
57 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) tasks.pb.go
58 > if ms.LoadMessageInfo() == nil {
59 > ms.StoreMessageInfo(mi)
60 > }
61 > return ms
62 }
63 > return mi.MessageOf(x) tasks.pb.go
64 }
65
69 }
70
71 > func (x *AllocatedTaskInfo) GetData() *TaskInfo { tasks.pb.go
72 > if x != nil {
73 > return x.Data
74 > }
75 return nil
76 }
124 func (*TaskInfo) ProtoMessage() {}
125
126 > func (x *TaskInfo) ProtoReflect() protoreflect.Message { tasks.pb.go
127 > mi := &file_temporal_server_api_persistence_v1_tasks_proto_msgTypes[1]
128 > if x != nil {
129 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) tasks.pb.go
130 > if ms.LoadMessageInfo() == nil {
131 > ms.StoreMessageInfo(mi)
132 > }
133 > return ms
134 }
135 > return mi.MessageOf(x) tasks.pb.go
136 }
137
141 }
142
143 > func (x *TaskInfo) GetNamespaceId() string { tasks.pb.go
144 > if x != nil {
145 > return x.NamespaceId
146 > }
147 return ""
148 }
149
150 > func (x *TaskInfo) GetWorkflowId() string { tasks.pb.go
151 > if x != nil {
152 > return x.WorkflowId
153 > }
154 return ""
155 }
156
157 > func (x *TaskInfo) GetRunId() string { tasks.pb.go
158 > if x != nil {
159 > return x.RunId
160 > }
161 return ""
162 }
163
164 > func (x *TaskInfo) GetScheduledEventId() int64 { tasks.pb.go
165 > if x != nil {
166 > return x.ScheduledEventId
167 > }
168 return 0
169 }
170
171 > func (x *TaskInfo) GetCreateTime() *timestamppb.Timestamp { tasks.pb.go
172 > if x != nil {
173 > return x.CreateTime
174 > }
175 return nil
176 }
177
178 > func (x *TaskInfo) GetExpiryTime() *timestamppb.Timestamp { tasks.pb.go
179 > if x != nil {
180 > return x.ExpiryTime
181 > }
182 return nil
183 }
184
185 > func (x *TaskInfo) GetClock() *v1.VectorClock { tasks.pb.go
186 > if x != nil {
187 > return x.Clock
188 > }
189 return nil
190 }
191
192 > func (x *TaskInfo) GetVersionDirective() *v11.TaskVersionDirective { tasks.pb.go
193 > if x != nil {
194 > return x.VersionDirective
195 > }
196 return nil
197 }
198
199 > func (x *TaskInfo) GetStamp() int32 { tasks.pb.go
200 > if x != nil {
201 > return x.Stamp
202 > }
203 return 0
204 }
205
206 > func (x *TaskInfo) GetPriority() *v12.Priority { tasks.pb.go
207 > if x != nil {
208 > return x.Priority
209 > }
210 return nil
211 }
260 }
261
262 > func (x *TaskQueueInfo) Reset() { tasks.pb.go
263 > *x = TaskQueueInfo{}
264 > mi := &file_temporal_server_api_persistence_v1_tasks_proto_msgTypes[2]
265 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
266 > ms.StoreMessageInfo(mi)
267 > }
268
269 func (x *TaskQueueInfo) String() string {
273 func (*TaskQueueInfo) ProtoMessage() {}
274
275 > func (x *TaskQueueInfo) ProtoReflect() protoreflect.Message { tasks.pb.go
276 > mi := &file_temporal_server_api_persistence_v1_tasks_proto_msgTypes[2]
277 > if x != nil {
278 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
279 > if ms.LoadMessageInfo() == nil {
280 > ms.StoreMessageInfo(mi)
281 > }
282 > return ms
283 }
284 return mi.MessageOf(x)
290 }
291
292 > func (x *TaskQueueInfo) GetNamespaceId() string { tasks.pb.go
293 > if x != nil {
294 > return x.NamespaceId
295 > }
296 return ""
297 }
298
299 > func (x *TaskQueueInfo) GetName() string { tasks.pb.go
300 > if x != nil {
301 > return x.Name
302 > }
303 return ""
304 }
305
306 > func (x *TaskQueueInfo) GetTaskType() v13.TaskQueueType { tasks.pb.go
307 > if x != nil {
308 > return x.TaskType
309 > }
310 return v13.TaskQueueType(0)
311 }
312
313 > func (x *TaskQueueInfo) GetKind() v13.TaskQueueKind { tasks.pb.go
314 > if x != nil {
315 > return x.Kind
316 > }
317 return v13.TaskQueueKind(0)
318 }
399 func (*SubqueueInfo) ProtoMessage() {}
400
401 > func (x *SubqueueInfo) ProtoReflect() protoreflect.Message { tasks.pb.go
402 > mi := &file_temporal_server_api_persistence_v1_tasks_proto_msgTypes[3]
403 > if x != nil {
404 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) tasks.pb.go
405 > if ms.LoadMessageInfo() == nil {
406 > ms.StoreMessageInfo(mi)
407 > }
408 > return ms
409 }
410 > return mi.MessageOf(x) tasks.pb.go
411 }
412
479 func (*FairnessKeyCount) ProtoMessage() {}
480
481 > func (x *FairnessKeyCount) ProtoReflect() protoreflect.Message { tasks.pb.go
482 > mi := &file_temporal_server_api_persistence_v1_tasks_proto_msgTypes[4]
483 > if x != nil {
484 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
485 if ms.LoadMessageInfo() == nil {
488 return ms
489 }
490 > return mi.MessageOf(x) tasks.pb.go
491 }
492
531 func (*SubqueueKey) ProtoMessage() {}
532
533 > func (x *SubqueueKey) ProtoReflect() protoreflect.Message { tasks.pb.go
534 > mi := &file_temporal_server_api_persistence_v1_tasks_proto_msgTypes[5]
535 > if x != nil {
536 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) tasks.pb.go
537 > if ms.LoadMessageInfo() == nil {
538 > ms.StoreMessageInfo(mi)
539 > }
540 > return ms
541 }
542 > return mi.MessageOf(x) tasks.pb.go
543 }
544
600 func (*PartitionScaleState) ProtoMessage() {}
601
602 > func (x *PartitionScaleState) ProtoReflect() protoreflect.Message { tasks.pb.go
603 > mi := &file_temporal_server_api_persistence_v1_tasks_proto_msgTypes[6]
604 > if x != nil {
605 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
606 if ms.LoadMessageInfo() == nil {
609 return ms
610 }
611 > return mi.MessageOf(x) tasks.pb.go
612 }
613
617 }
618
619 > func (x *PartitionScaleState) GetTarget() int32 { tasks.pb.go
620 > if x != nil {
621 return x.Target
622 }
623 > return 0 tasks.pb.go
624 }
625
631 }
632
633 > func (x *PartitionScaleState) GetTargetVersion() int64 { tasks.pb.go
634 > if x != nil {
635 return x.TargetVersion
636 }
637 > return 0 tasks.pb.go
638 }
639
640 > func (x *PartitionScaleState) GetBacklogState() []uint64 { tasks.pb.go
641 > if x != nil {
642 return x.BacklogState
643 }
644 > return nil tasks.pb.go
645 }
646
647 > func (x *PartitionScaleState) GetBacklogCounts() []byte { tasks.pb.go
648 > if x != nil {
649 return x.BacklogCounts
650 }
651 > return nil tasks.pb.go
652 }
653
654 > func (x *PartitionScaleState) GetBacklogCap() int32 { tasks.pb.go
655 > if x != nil {
656 return x.BacklogCap
657 }
658 > return 0 tasks.pb.go
659 }
660
846 }
847
848 > func init() { file_temporal_server_api_persistence_v1_tasks_proto_init() } tasks.pb.go
849 > func file_temporal_server_api_persistence_v1_tasks_proto_init() {
850 > if File_temporal_server_api_persistence_v1_tasks_proto != nil {
851 return
852 }
853 > type x struct{} tasks.pb.go
854 > out := protoimpl.TypeBuilder{
855 > File: protoimpl.DescBuilder{
856 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
857 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_tasks_proto_rawDesc), len(file_temporal_server_api_persistence_v1_tasks_proto_rawDesc)),
858 > NumEnums: 0,
859 > NumMessages: 8,
860 > NumExtensions: 0,
861 > NumServices: 0,
862 > },
863 > GoTypes: file_temporal_server_api_persistence_v1_tasks_proto_goTypes,
864 > DependencyIndexes: file_temporal_server_api_persistence_v1_tasks_proto_depIdxs,
865 > MessageInfos: file_temporal_server_api_persistence_v1_tasks_proto_msgTypes,
866 > }.Build()
867 > File_temporal_server_api_persistence_v1_tasks_proto = out.File
868 > file_temporal_server_api_persistence_v1_tasks_proto_goTypes = nil
869 > file_temporal_server_api_persistence_v1_tasks_proto_depIdxs = nil
870 }
go.temporal.io/server/service/history/transfer_queue_factory.go 157 covered LOC · 3 ranges

Open complete file

46 func NewTransferQueueFactory(
47 params transferQueueFactoryParams,
48 > ) QueueFactory { transfer_queue_factory.go
49 > return &transferQueueFactory{
50 > transferQueueFactoryParams: params,
51 > QueueFactoryBase: QueueFactoryBase{
52 > HostScheduler: queues.NewScheduler(
53 > params.ClusterMetadata.GetCurrentClusterName(),
54 > queues.SchedulerOptions{
55 > WorkerCount: params.Config.TransferProcessorSchedulerWorkerCount,
56 > ActiveNamespaceWeights: params.Config.TransferProcessorSchedulerActiveRoundRobinWeights,
57 > StandbyNamespaceWeights: params.Config.TransferProcessorSchedulerStandbyRoundRobinWeights,
58 > InactiveNamespaceDeletionDelay: params.Config.TaskSchedulerInactiveChannelDeletionDelay,
59 > ExecutionAwareSchedulerOptions: ctasks.ExecutionAwareSchedulerOptions{
60 > Enabled: params.Config.TaskSchedulerEnableExecutionQueueScheduler,
61 > MaxQueues: params.Config.TaskSchedulerExecutionQueueSchedulerMaxQueues,
62 > QueueTTL: params.Config.TaskSchedulerExecutionQueueSchedulerQueueTTL,
63 > QueueConcurrency: params.Config.TaskSchedulerExecutionQueueSchedulerQueueConcurrency,
64 > },
65 > },
66 > params.NamespaceRegistry,
67 > params.Logger,
68 > params.MetricsHandler,
69 > params.TimeSource,
70 > ),
71 > HostPriorityAssigner: queues.NewPriorityAssigner(
72 > params.NamespaceRegistry,
73 > params.ClusterMetadata.GetCurrentClusterName(),
74 > ),
75 > HostReaderRateLimiter: queues.NewReaderPriorityRateLimiter(
76 > NewHostRateLimiterRateFn(
77 > params.Config.TransferProcessorMaxPollHostRPS,
78 > params.Config.PersistenceMaxQPS,
79 > transferQueuePersistenceMaxRPSRatio,
80 > ),
81 > int64(params.Config.TransferQueueMaxReaderCount()),
82 > ),
83 > Tracer: params.TracerProvider.Tracer(telemetry.ComponentQueueTransfer),
84 > },
85 > }
86 > }
87
88 func (f *transferQueueFactory) CreateQueue(
89 shardContext historyi.ShardContext,
90 > ) queues.Queue { transfer_queue_factory.go
91 > logger := log.With(shardContext.GetLogger(), tag.ComponentTransferQueue)
92 > metricsHandler := f.MetricsHandler.WithTags(metrics.OperationTag(metrics.OperationTransferQueueProcessorScope))
93 >
94 > currentClusterName := f.ClusterMetadata.GetCurrentClusterName()
95 >
96 > shardScheduler := queues.NewRateLimitedScheduler(
97 > f.HostScheduler,
98 > queues.RateLimitedSchedulerOptions{
99 > Enabled: f.Config.TaskSchedulerEnableRateLimiter,
100 > EnableShadowMode: f.Config.TaskSchedulerEnableRateLimiterShadowMode,
101 > StartupDelay: f.Config.TaskSchedulerRateLimiterStartupDelay,
102 > },
103 > currentClusterName,
104 > f.NamespaceRegistry,
105 > f.SchedulerRateLimiter,
106 > f.TimeSource,
107 > f.ChasmRegistry,
108 > logger,
109 > metricsHandler,
110 > )
111 >
112 > rescheduler := queues.NewRescheduler(
113 > shardScheduler,
114 > shardContext.GetTimeSource(),
115 > logger,
116 > metricsHandler,
117 > )
118 >
119 > activeExecutor := newTransferQueueActiveTaskExecutor(
120 > shardContext,
121 > f.WorkflowCache,
122 > f.SdkClientFactory,
123 > logger,
124 > f.MetricsHandler,
125 > f.Config,
126 > f.HistoryRawClient,
127 > f.MatchingRawClient,
128 > f.VisibilityManager,
129 > f.ChasmEngine,
130 > f.VersionMembershipCache,
131 > f.TestHooks,
132 > )
133 >
134 > standbyExecutor := newTransferQueueStandbyTaskExecutor(
135 > shardContext,
136 > f.WorkflowCache,
137 > logger,
138 > f.MetricsHandler,
139 > currentClusterName,
140 > f.HistoryRawClient,
141 > f.MatchingRawClient,
142 > f.VisibilityManager,
143 > f.ChasmEngine,
144 > f.ClientBean,
145 > )
146 >
147 > executor := queues.NewActiveStandbyExecutor(
148 > currentClusterName,
149 > f.NamespaceRegistry,
150 > activeExecutor,
151 > standbyExecutor,
152 > logger,
153 > )
154 > if f.ExecutorWrapper != nil {
155 executor = f.ExecutorWrapper.Wrap(executor)
156 }
157
158 > factory := queues.NewExecutableFactory( transfer_queue_factory.go
159 > executor,
160 > shardScheduler,
161 > rescheduler,
162 > f.HostPriorityAssigner,
163 > shardContext.GetTimeSource(),
164 > shardContext.GetNamespaceRegistry(),
165 > shardContext.GetClusterMetadata(),
166 > f.ChasmRegistry,
167 > queues.GetTaskTypeTagValue,
168 > logger,
169 > metricsHandler,
170 > f.Tracer,
171 > f.DLQWriter,
172 > f.Config.TaskDLQEnabled,
173 > f.Config.TaskDLQUnexpectedErrorAttempts,
174 > f.Config.TaskDLQInternalErrors,
175 > f.Config.TaskDLQErrorPattern,
176 > )
177 > return queues.NewImmediateQueue(
178 > shardContext,
179 > tasks.CategoryTransfer,
180 > shardScheduler,
181 > rescheduler,
182 > &queues.Options{
183 > ReaderOptions: queues.ReaderOptions{
184 > BatchSize: f.Config.TransferTaskBatchSize,
185 > MaxPendingTasksCount: f.Config.QueuePendingTaskMaxCount,
186 > PollBackoffInterval: f.Config.TransferProcessorPollBackoffInterval,
187 > MaxPredicateSize: f.Config.QueueMaxPredicateSize,
188 > },
189 > MonitorOptions: queues.MonitorOptions{
190 > PendingTasksCriticalCount: f.Config.QueuePendingTaskCriticalCount,
191 > ReaderStuckCriticalAttempts: f.Config.QueueReaderStuckCriticalAttempts,
192 > SliceCountCriticalThreshold: f.Config.QueueCriticalSlicesCount,
193 > },
194 > MaxPollRPS: f.Config.TransferProcessorMaxPollRPS,
195 > MaxPollInterval: f.Config.TransferProcessorMaxPollInterval,
196 > MaxPollIntervalJitterCoefficient: f.Config.TransferProcessorMaxPollIntervalJitterCoefficient,
197 > CheckpointInterval: f.Config.TransferProcessorUpdateAckInterval,
198 > CheckpointIntervalJitterCoefficient: f.Config.TransferProcessorUpdateAckIntervalJitterCoefficient,
199 > MaxReaderCount: f.Config.TransferQueueMaxReaderCount,
200 > MoveGroupTaskCountBase: f.Config.QueueMoveGroupTaskCountBase,
201 > MoveGroupTaskCountMultiplier: f.Config.QueueMoveGroupTaskCountMultiplier,
202 > ShrinkPredicateMaxPendingKeys: f.Config.QueueShrinkPredicateMaxPendingKeys,
203 > },
204 > f.HostReaderRateLimiter,
205 > queues.GrouperNamespaceID{},
206 > logger,
207 > metricsHandler,
208 > factory,
209 > nil, // taskPostProcessor
210 > )
211 }
go.temporal.io/server/common/nexus/endpoint_registry.go 152 covered LOC · 22 ranges

Open complete file

74 var ErrNexusDisabled = serviceerror.NewFailedPrecondition("nexus is disabled")
75
76 > func NewEndpointRegistryConfig(dc *dynamicconfig.Collection) *EndpointRegistryConfig { endpoint_registry.go
77 > config := &EndpointRegistryConfig{
78 > refreshLongPollTimeout: dynamicconfig.RefreshNexusEndpointsLongPollTimeout.Get(dc),
79 > refreshPageSize: dynamicconfig.NexusEndpointListDefaultPageSize.Get(dc),
80 > refreshMinWait: dynamicconfig.RefreshNexusEndpointsMinWait.Get(dc),
81 > readThroughCacheSize: dynamicconfig.NexusReadThroughCacheSize.Get(dc),
82 > readThroughCacheTTL: dynamicconfig.NexusReadThroughCacheTTL.Get(dc),
83 > refreshOnRead: dynamicconfig.ForceNexusEndpointRefreshOnRead.Get(dc),
84 > }
85 > config.refreshRetryPolicy = backoff.NewExponentialRetryPolicy(config.refreshMinWait()).WithMaximumInterval(config.refreshLongPollTimeout())
86 > return config
87 > }
88
89 func NewEndpointRegistry(
93 logger log.Logger,
94 metricsHandler metrics.Handler,
95 > ) *EndpointRegistryImpl { endpoint_registry.go
96 > return &EndpointRegistryImpl{
97 > config: config,
98 > endpointsByID: make(map[string]*persistencespb.NexusEndpointEntry),
99 > endpointsByName: make(map[string]*persistencespb.NexusEndpointEntry),
100 > matchingClient: matchingClient,
101 > persistence: persistence,
102 > logger: logger,
103 > readThroughCacheByID: cache.NewWithMetrics(config.readThroughCacheSize(), &cache.Options{
104 > TTL: config.readThroughCacheTTL(),
105 > }, metricsHandler.WithTags(metrics.CacheTypeTag(metrics.NexusEndpointRegistryReadThroughCacheTypeTagValue))),
106 > }
107 > }
108
109 // StartLifecycle starts this component. It should only be invoked by an fx lifecycle hook.
110 // Should not be called multiple times or concurrently with StopLifecycle()
111 > func (r *EndpointRegistryImpl) StartLifecycle() { endpoint_registry.go
112 > r.setEnabled(true)
113 > }
114
115 // StopLifecycle stops this component. It should only be invoked by an fx lifecycle hook.
116 // Should not be called multiple times or concurrently with StartLifecycle()
117 > func (r *EndpointRegistryImpl) StopLifecycle() { endpoint_registry.go
118 > r.setEnabled(false)
119 > }
120
121 > func (r *EndpointRegistryImpl) setEnabled(enabled bool) { endpoint_registry.go
122 > oldReady := r.dataReady.Load()
123 > if oldReady == nil && enabled {
124 > backgroundCtx := headers.SetCallerInfo(
125 > context.Background(),
126 > headers.SystemBackgroundHighCallerInfo,
127 > )
128 > newReady := &dataReady{
129 > refresh: goro.NewHandle(backgroundCtx),
130 > ready: make(chan struct{}),
131 > }
132 > if r.dataReady.CompareAndSwap(oldReady, newReady) {
133 > newReady.refresh.Go(func(ctx context.Context) error {
134 > return r.refreshEndpointsLoop(ctx, newReady)
135 > })
136 }
137 > } else if oldReady != nil && !enabled { endpoint_registry.go
138 > if r.dataReady.CompareAndSwap(oldReady, nil) {
139 > oldReady.refresh.Cancel()
140 > <-oldReady.refresh.Done()
141 > // If oldReady.ready was not already closed here, callers blocked in waitUntilInitialized
142 > // will block indefinitely (until context timeout). If we wanted to wake them up, we
143 > // could close ready here, but we would need to use a sync.Once to avoid closing it
144 > // twice. Then waitUntilInitialized would need to reload r.dataReady to check that the
145 > // wakeup was due to data being ready rather than this close.
146 > }
147 }
148 }
222 }
223
224 > func (r *EndpointRegistryImpl) refreshEndpointsLoop(ctx context.Context, dataReady *dataReady) error { endpoint_registry.go
225 > hasLoadedEndpointData := false
226 >
227 > for ctx.Err() == nil {
228 > start := time.Now()
229 > enforceMinWait := true
230 > if !hasLoadedEndpointData {
231 > // Loading endpoints for the first time after being (re)enabled, so load with fallback to persistence
232 > // and unblock any threads waiting on r.dataReady if successful.
233 > err := backoff.ThrottleRetryContext(ctx, r.loadEndpoints, r.config.refreshRetryPolicy, nil)
234 > if err == nil {
235 > hasLoadedEndpointData = true endpoint_registry.go
236 > enforceMinWait = false
237 > // Note: do not reload r.dataReady here, use value from argument to ensure that
238 > // each channel is closed no more than once.
239 > close(dataReady.ready)
240 > }
241 > } else {
242 > r.dataLock.Lock()
243 > prevTableVersion := r.tableVersion
244 > r.dataLock.Unlock()
245 >
246 > // Endpoints have previously been loaded, so just keep them up to date with long poll requests to
247 > // matching, without fallback to persistence. Ignoring long poll errors since we will just retry
248 > // on next loop iteration.
249 > _ = backoff.ThrottleRetryContext(ctx, r.refreshEndpoints, r.config.refreshRetryPolicy, nil)
250 >
251 > r.dataLock.Lock()
252 > enforceMinWait = prevTableVersion == r.tableVersion
253 > r.dataLock.Unlock()
254 > }
255 > elapsed := time.Since(start) endpoint_registry.go
256 >
257 > minWaitTime := r.config.refreshMinWait()
258 > // In general, we want to start a new call immediately on completion of the previous one. But if the remote is
259 > // broken and returns success immediately, we might end up spinning. So enforce a minimum wait time that
260 > // increases as long as we keep getting very fast replies. Only enforce the min wait if the remote does not
261 > // return new data.
262 > if enforceMinWait && elapsed < minWaitTime {
263 util.InterruptibleSleep(ctx, minWaitTime-elapsed)
264 }
265 }
266
267 > return ctx.Err() endpoint_registry.go
268 }
269
270 // loadEndpoints initializes the in-memory view of endpoints data.
271 // It first tries to load from matching service and falls back to querying persistence directly if matching is unavailable.
272 > func (r *EndpointRegistryImpl) loadEndpoints(ctx context.Context) error { endpoint_registry.go
273 > tableVersion, endpoints, err := r.getAllEndpointsMatchingWithPersistenceFallback(ctx)
274 > if err != nil {
275 return err
276 }
277 > endpointsByID := make(map[string]*persistencespb.NexusEndpointEntry, len(endpoints)) endpoint_registry.go
278 > endpointsByName := make(map[string]*persistencespb.NexusEndpointEntry, len(endpoints))
279 > for _, endpoint := range endpoints {
280 endpointsByID[endpoint.Id] = endpoint
281 endpointsByName[endpoint.Endpoint.Spec.Name] = endpoint
282 }
283
284 > r.dataLock.Lock() endpoint_registry.go
285 > defer r.dataLock.Unlock()
286 >
287 > r.tableVersion = tableVersion
288 > r.endpointsByID = endpointsByID
289 > r.endpointsByName = endpointsByName
290 > return nil
291 }
292
293 // refreshEndpoints sends long-poll requests to matching to check for any updates to endpoint data.
294 > func (r *EndpointRegistryImpl) refreshEndpoints(ctx context.Context) error { endpoint_registry.go
295 > r.dataLock.RLock()
296 > currentTableVersion := r.tableVersion
297 > r.dataLock.RUnlock()
298 >
299 > resp, err := r.matchingClient.ListNexusEndpoints(ctx, &matchingservice.ListNexusEndpointsRequest{
300 > NextPageToken: nil,
301 > PageSize: int32(r.config.refreshPageSize()),
302 > LastKnownTableVersion: currentTableVersion,
303 > Wait: true,
304 > })
305 > if err != nil {
306 > if ctx.Err() == nil { endpoint_registry.go
307 r.logger.Error("long poll to refresh Nexus endpoints returned error", tag.Error(err))
308 }
309 > return err endpoint_registry.go
310 }
311
366 }
367
368 > func (r *EndpointRegistryImpl) getAllEndpointsMatchingWithPersistenceFallback(ctx context.Context) (int64, []*persistencespb.NexusEndpointEntry, error) { endpoint_registry.go
369 > tableVersion, endpoints, err := r.getAllEndpointsMatching(ctx)
370 > if err != nil {
371 // Fallback to persistence on matching error during initial load.
372 r.logger.Error("error from matching when initializing Nexus endpoint cache", tag.Error(err))
373 tableVersion, endpoints, err = r.getAllEndpointsPersistence(ctx)
374 }
375 > return tableVersion, endpoints, err endpoint_registry.go
376 }
377
378 // getAllEndpointsMatching paginates over all endpoints returned by matching. It always does a simple get.
379 > func (r *EndpointRegistryImpl) getAllEndpointsMatching(ctx context.Context) (int64, []*persistencespb.NexusEndpointEntry, error) { endpoint_registry.go
380 > return r.getAllEndpoints(ctx, func(currentTableVersion int64, currentPageToken []byte) (int64, []byte, []*persistencespb.NexusEndpointEntry, error) {
381 > resp, err := r.matchingClient.ListNexusEndpoints(ctx, &matchingservice.ListNexusEndpointsRequest{
382 > NextPageToken: currentPageToken,
383 > PageSize: int32(r.config.refreshPageSize()),
384 > LastKnownTableVersion: currentTableVersion,
385 > Wait: false,
386 > })
387 > if err != nil {
388 return 0, nil, nil, err
389 }
390 > return resp.TableVersion, resp.NextPageToken, resp.Entries, nil endpoint_registry.go
391 })
392 }
410 // getAllEndpointsPersistence paginates over all endpoints returned by persistence.
411 // Should only be used as a fall-back if matching service is unavailable during initial load.
412 > func (r *EndpointRegistryImpl) getAllEndpoints(ctx context.Context, getter func(int64, []byte) (int64, []byte, []*persistencespb.NexusEndpointEntry, error)) (int64, []*persistencespb.NexusEndpointEntry, error) { endpoint_registry.go
413 > var currentPageToken []byte
414 >
415 > currentTableVersion := int64(0)
416 > entries := make([]*persistencespb.NexusEndpointEntry, 0)
417 >
418 > for ctx.Err() == nil {
419 > respTableVersion, respNextPageToken, respEntries, err := getter(currentTableVersion, currentPageToken)
420 > if err != nil {
421 var fpe *serviceerror.FailedPrecondition
422 if errors.As(err, &fpe) && fpe.Message == p.ErrNexusTableVersionConflict.Error() {
430 }
431
432 > currentTableVersion = respTableVersion endpoint_registry.go
433 > entries = append(entries, respEntries...)
434 >
435 > if len(respNextPageToken) == 0 {
436 > return currentTableVersion, entries, nil
437 > }
438
439 currentPageToken = respNextPageToken
go.temporal.io/server/service/history/queues/executable.go 151 covered LOC · 34 ranges

Open complete file

194 tracer trace.Tracer,
195 opts ...ExecutableOption,
196 > ) Executable { executable.go
197 > params := ExecutableParams{
198 > DLQEnabled: func() bool {
199 return false
200 },
210 },
211 }
212 > for _, opt := range opts { executable.go
213 > opt(&params) executable.go
214 > }
215 > e := &executableImpl{ executable.go
216 > Task: task,
217 > state: ctasks.TaskStatePending,
218 >
219 > executor: executor,
220 > scheduler: scheduler,
221 > rescheduler: rescheduler,
222 > priorityAssigner: priorityAssigner,
223 > timeSource: timeSource,
224 > namespaceRegistry: namespaceRegistry,
225 > clusterMetadata: clusterMetadata,
226 > chasmRegistry: chasmRegistry,
227 > taskTypeTagProvider: taskTypeTagProvider,
228 > readerID: readerID,
229 > logger: log.NewLazyLogger(
230 > logger,
231 > func() []tag.Tag {
232 return tasks.Tags(task)
233 },
241 dlqErrorPattern: params.DLQErrorPattern,
242 }
243 > e.refreshMetricsHandlers(nil) executable.go
244 > e.attempt.Store(1)
245 > e.priority = priorityAssigner.Assign(e)
246 >
247 > loadTime := util.MaxTime(timeSource.Now(), task.GetKey().FireTime)
248 > metrics.TaskLoadLatency.With(e.chasmMetricsHandler).Record(
249 > loadTime.Sub(task.GetVisibilityTime()),
250 > metrics.QueueReaderIDTag(readerID),
251 > )
252 > return e
253 }
254
255 > func (e *executableImpl) Execute() (retErr error) { executable.go
256 > startTime := e.timeSource.Now()
257 > e.scheduleLatency = startTime.Sub(e.scheduledTime)
258 >
259 > e.Lock()
260 > if e.state != ctasks.TaskStatePending {
261 e.Unlock()
262 return nil
263 }
264
265 > ns, _ := e.namespaceRegistry.GetNamespaceName(namespace.ID(e.GetNamespaceID())) executable.go
266 > var callerInfo headers.CallerInfo
267 > switch e.priority {
268 > case ctasks.PriorityHigh:
269 > callerInfo = headers.NewBackgroundHighCallerInfo(ns.String())
270 case ctasks.PriorityLow:
271 callerInfo = headers.NewBackgroundLowCallerInfo(ns.String())
274 callerInfo = headers.NewPreemptableCallerInfo(ns.String())
275 }
276 > ctx := headers.SetCallerInfo( executable.go
277 > metrics.AddMetricsContext(context.Background()),
278 > callerInfo,
279 > )
280 > e.Unlock()
281 >
282 > // Wrapped in if block to avoid unnecessary allocations when OTEL is disabled.
283 > if telemetry.IsEnabled(e.tracer) {
284 var span trace.Span
285
323 }
324
325 > defer func() { executable.go
326 > if pObj := recover(); pObj != nil {
327 err, ok := pObj.(error)
328 if !ok {
338 }
339
340 > attemptUserLatency := time.Duration(0) executable.go
341 > if duration, ok := metrics.ContextCounterGet(ctx, metrics.HistoryWorkflowExecutionCacheLatency.Name()); ok {
342 > attemptUserLatency = time.Duration(duration) executable.go
343 > }
344
345 > attemptLatency := e.timeSource.Now().Sub(startTime) executable.go
346 > e.attemptNoUserLatency = attemptLatency - attemptUserLatency
347 > // emit total attempt latency so that we know how much time a task will occpy a worker goroutine
348 > metrics.TaskProcessingLatency.With(e.chasmMetricsHandler).Record(attemptLatency)
349 >
350 > if persistenceDuration, ok := metrics.ContextCounterGet(ctx, metrics.TaskPersistenceLatency.Name()); ok {
351 > attemptNoPersistence := attemptLatency - time.Duration(persistenceDuration) executable.go
352 > metrics.TaskProcessingNoPersistenceLatency.With(e.chasmMetricsHandler).Record(attemptNoPersistence)
353 > }
354
355 > priorityTaggedProvider := e.chasmMetricsHandler.WithTags(metrics.TaskPriorityTag(e.priority.String())) executable.go
356 > metrics.TaskRequests.With(priorityTaggedProvider).Record(1)
357 > metrics.TaskScheduleLatency.With(priorityTaggedProvider).Record(e.scheduleLatency)
358 > metrics.OperationCounter.With(e.defaultMetricsHandler).Record(1)
359 >
360 > if retErr == nil {
361 > e.inMemoryNoUserLatency += e.scheduleLatency + e.attemptNoUserLatency executable.go
362 > }
363 // if retErr is not nil, HandleErr will take care of the inMemoryNoUserLatency calculation
364 // Not doing it here as for certain errors latency for the attempt should not be counted
367 // A previous attempt has marked this executable as no longer retryable.
368 // Instead of executing it, we try to write to the DLQ if enabled, otherwise - drop it.
369 > if e.terminalFailureCause != nil { executable.go
370 if e.dlqEnabled() {
371 return e.writeToDLQ(ctx)
382 }
383
384 > resp := e.executor.Execute(ctx, e) executable.go
385 > e.refreshMetricsHandlers(resp.ExecutionMetricTags)
386 >
387 > if resp.ExecutedAsActive != e.lastActiveness {
388 > // namespace did a failover, executable.go
389 > // reset task attempt since the execution logic used will change
390 > // reset task priority since it changes between active/standby
391 > e.resetAttempt()
392 > e.priority = e.priorityAssigner.Assign(e)
393 > }
394 > e.lastActiveness = resp.ExecutedAsActive executable.go
395 >
396 > return resp.ExecutionErr
397 }
398
651 }
652
653 > func (e *executableImpl) RetryPolicy() backoff.RetryPolicy { executable.go
654 > // this is the retry policy for one submission
655 > // not for calculating the backoff after the task is nacked
656 > //
657 > // never retry task while holding the goroutine, and rely on shouldResubmitOnNack
658 > return backoff.DisabledRetryPolicy
659 > }
660
661 func (e *executableImpl) Abort() {
677 }
678
679 > func (e *executableImpl) Ack() { executable.go
680 > e.Lock()
681 > defer e.Unlock()
682 >
683 > if e.state != ctasks.TaskStatePending {
684 return
685 }
686
687 > e.state = ctasks.TaskStateAcked executable.go
688 >
689 > if e.invalidTask {
690 // do not emit metrics for invalid tasks
691 // as they are expected to have to high latency due to reprocessing upon shard movement.
693 }
694
695 > metrics.TaskAttempt.With(e.chasmMetricsHandler).Record(e.attempt.Load()) executable.go
696 >
697 > priorityTaggedProvider := e.chasmMetricsHandler.WithTags(metrics.TaskPriorityTag(e.priority.String()))
698 > metrics.TaskLatency.With(priorityTaggedProvider).Record(e.inMemoryNoUserLatency)
699 > metrics.TaskQueueLatency.With(priorityTaggedProvider.WithTags(metrics.QueueReaderIDTag(e.readerID))).
700 > Record(time.Since(e.GetVisibilityTime()))
701 }
702
762 }
763
764 > func (e *executableImpl) GetTask() tasks.Task { executable.go
765 > return e.Task
766 > }
767
768 func (e *executableImpl) GetScheduledTime() time.Time {
770 }
771
772 > func (e *executableImpl) SetScheduledTime(t time.Time) { executable.go
773 > e.scheduledTime = t
774 > }
775
776 // GetDestination returns the embedded task's destination if it exists. Defaults to an empty string.
856 }
857
858 > func (e *executableImpl) resetAttempt() { executable.go
859 > e.attempt.Store(1)
860 > }
861
862 > func (e *executableImpl) refreshMetricsHandlers(executionMetricTags []metrics.Tag) { executable.go
863 > sharedTags := taskBaseMetricTagsWithoutArchetype(
864 > e.GetTask(),
865 > e.namespaceRegistry,
866 > e.clusterMetadata.GetCurrentClusterName(),
867 > e.chasmRegistry,
868 > e.taskTypeTagProvider,
869 > )
870 > if len(executionMetricTags) > 0 {
871 > sharedTags = append(sharedTags, executionMetricTags...) executable.go
872 > }
873 > e.defaultMetricsHandler = e.baseMetricsHandler.WithTags(sharedTags...) executable.go
874 > e.chasmMetricsHandler = e.defaultMetricsHandler.WithTags(getArchetypeTag(e.GetTask(), e.chasmRegistry))
875 }
876
892 chasmRegistry *chasm.Registry,
893 taskTypeTagProvider TaskTypeTagProvider,
894 > ) []metrics.Tag { executable.go
895 > namespaceTag := metrics.NamespaceUnknownTag()
896 > isActive := true
897 >
898 > ns, err := namespaceRegistry.GetNamespaceByID(namespace.ID(task.GetNamespaceID()))
899 > if err == nil {
900 > namespaceTag = metrics.NamespaceTag(ns.Name().String()) executable.go
901 > isActive = ns.ActiveClusterName(namespace.RoutingKey{ID: task.GetWorkflowID()}) == currentClusterName
902 > }
903
904 > taskType := taskTypeTagProvider(task, isActive, chasmRegistry) executable.go
905 > return []metrics.Tag{
906 > namespaceTag,
907 > metrics.TaskTypeTag(taskType),
908 > metrics.OperationTag(taskType), // for backward compatibility
909 > // TODO: add task priority tag here as well
910 > }
911 }
912
913 > func getArchetypeTag(task tasks.Task, chasmRegistry *chasm.Registry) metrics.Tag { executable.go
914 > if t, ok := task.(tasks.HasArchetypeID); ok {
915 if name, ok := chasmRegistry.ArchetypeDisplayName(t.GetArchetypeID()); ok {
916 return metrics.ArchetypeTag(name)
917 }
918 }
919 > return metrics.ArchetypeTag(chasm.WorkflowComponentName) executable.go
920 }
921
go.temporal.io/server/api/matchingservice/v1/service_grpc.pb.go 149 covered LOC · 45 ranges

Open complete file

259 }
260
261 > func NewMatchingServiceClient(cc grpc.ClientConnInterface) MatchingServiceClient { service_grpc.pb.go
262 > return &matchingServiceClient{cc}
263 > }
264
265 > func (c *matchingServiceClient) PollWorkflowTaskQueue(ctx context.Context, in *PollWorkflowTaskQueueRequest, opts ...grpc.CallOption) (*PollWorkflowTaskQueueResponse, error) { service_grpc.pb.go
266 > out := new(PollWorkflowTaskQueueResponse)
267 > err := c.cc.Invoke(ctx, MatchingService_PollWorkflowTaskQueue_FullMethodName, in, out, opts...)
268 > if err != nil {
269 > return nil, err service_grpc.pb.go
270 > }
271 > return out, nil service_grpc.pb.go
272 }
273
274 > func (c *matchingServiceClient) PollActivityTaskQueue(ctx context.Context, in *PollActivityTaskQueueRequest, opts ...grpc.CallOption) (*PollActivityTaskQueueResponse, error) { service_grpc.pb.go
275 > out := new(PollActivityTaskQueueResponse)
276 > err := c.cc.Invoke(ctx, MatchingService_PollActivityTaskQueue_FullMethodName, in, out, opts...)
277 > if err != nil {
278 > return nil, err service_grpc.pb.go
279 > }
280 return out, nil
281 }
282
283 > func (c *matchingServiceClient) AddWorkflowTask(ctx context.Context, in *AddWorkflowTaskRequest, opts ...grpc.CallOption) (*AddWorkflowTaskResponse, error) { service_grpc.pb.go
284 > out := new(AddWorkflowTaskResponse)
285 > err := c.cc.Invoke(ctx, MatchingService_AddWorkflowTask_FullMethodName, in, out, opts...)
286 > if err != nil {
287 return nil, err
288 }
289 > return out, nil service_grpc.pb.go
290 }
291
353 }
354
355 > func (c *matchingServiceClient) CancelOutstandingPoll(ctx context.Context, in *CancelOutstandingPollRequest, opts ...grpc.CallOption) (*CancelOutstandingPollResponse, error) { service_grpc.pb.go
356 > out := new(CancelOutstandingPollResponse)
357 > err := c.cc.Invoke(ctx, MatchingService_CancelOutstandingPoll_FullMethodName, in, out, opts...)
358 > if err != nil {
359 return nil, err
360 }
361 > return out, nil service_grpc.pb.go
362 }
363
434 }
435
436 > func (c *matchingServiceClient) GetTaskQueueUserData(ctx context.Context, in *GetTaskQueueUserDataRequest, opts ...grpc.CallOption) (*GetTaskQueueUserDataResponse, error) { service_grpc.pb.go
437 > out := new(GetTaskQueueUserDataResponse)
438 > err := c.cc.Invoke(ctx, MatchingService_GetTaskQueueUserData_FullMethodName, in, out, opts...)
439 > if err != nil {
440 > return nil, err service_grpc.pb.go
441 > }
442 > return out, nil service_grpc.pb.go
443 }
444
506 }
507
508 > func (c *matchingServiceClient) ForceUnloadTaskQueuePartition(ctx context.Context, in *ForceUnloadTaskQueuePartitionRequest, opts ...grpc.CallOption) (*ForceUnloadTaskQueuePartitionResponse, error) { service_grpc.pb.go
509 > out := new(ForceUnloadTaskQueuePartitionResponse)
510 > err := c.cc.Invoke(ctx, MatchingService_ForceUnloadTaskQueuePartition_FullMethodName, in, out, opts...)
511 > if err != nil {
512 return nil, err
513 }
514 > return out, nil service_grpc.pb.go
515 }
516
569 }
570
571 > func (c *matchingServiceClient) ListNexusEndpoints(ctx context.Context, in *ListNexusEndpointsRequest, opts ...grpc.CallOption) (*ListNexusEndpointsResponse, error) { service_grpc.pb.go
572 > out := new(ListNexusEndpointsResponse)
573 > err := c.cc.Invoke(ctx, MatchingService_ListNexusEndpoints_FullMethodName, in, out, opts...)
574 > if err != nil {
575 > return nil, err service_grpc.pb.go
576 > }
577 > return out, nil service_grpc.pb.go
578 }
579
580 > func (c *matchingServiceClient) RecordWorkerHeartbeat(ctx context.Context, in *RecordWorkerHeartbeatRequest, opts ...grpc.CallOption) (*RecordWorkerHeartbeatResponse, error) { service_grpc.pb.go
581 > out := new(RecordWorkerHeartbeatResponse)
582 > err := c.cc.Invoke(ctx, MatchingService_RecordWorkerHeartbeat_FullMethodName, in, out, opts...)
583 > if err != nil {
584 return nil, err
585 }
586 > return out, nil service_grpc.pb.go
587 }
588
971 }
972
973 > func RegisterMatchingServiceServer(s grpc.ServiceRegistrar, srv MatchingServiceServer) { service_grpc.pb.go
974 > s.RegisterService(&MatchingService_ServiceDesc, srv)
975 > }
976
977 > func _MatchingService_PollWorkflowTaskQueue_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { service_grpc.pb.go
978 > in := new(PollWorkflowTaskQueueRequest)
979 > if err := dec(in); err != nil {
980 return nil, err
981 }
982 > if interceptor == nil { service_grpc.pb.go
983 return srv.(MatchingServiceServer).PollWorkflowTaskQueue(ctx, in)
984 }
985 > info := &grpc.UnaryServerInfo{ service_grpc.pb.go
986 > Server: srv,
987 > FullMethod: MatchingService_PollWorkflowTaskQueue_FullMethodName,
988 > }
989 > handler := func(ctx context.Context, req interface{}) (interface{}, error) {
990 > return srv.(MatchingServiceServer).PollWorkflowTaskQueue(ctx, req.(*PollWorkflowTaskQueueRequest))
991 > }
992 > return interceptor(ctx, in, info, handler)
993 }
994
995 > func _MatchingService_PollActivityTaskQueue_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { service_grpc.pb.go
996 > in := new(PollActivityTaskQueueRequest)
997 > if err := dec(in); err != nil {
998 return nil, err
999 }
1000 > if interceptor == nil { service_grpc.pb.go
1001 return srv.(MatchingServiceServer).PollActivityTaskQueue(ctx, in)
1002 }
1003 > info := &grpc.UnaryServerInfo{ service_grpc.pb.go
1004 > Server: srv,
1005 > FullMethod: MatchingService_PollActivityTaskQueue_FullMethodName,
1006 > }
1007 > handler := func(ctx context.Context, req interface{}) (interface{}, error) {
1008 > return srv.(MatchingServiceServer).PollActivityTaskQueue(ctx, req.(*PollActivityTaskQueueRequest))
1009 > }
1010 > return interceptor(ctx, in, info, handler)
1011 }
1012
1013 > func _MatchingService_AddWorkflowTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { service_grpc.pb.go
1014 > in := new(AddWorkflowTaskRequest)
1015 > if err := dec(in); err != nil {
1016 return nil, err
1017 }
1018 > if interceptor == nil { service_grpc.pb.go
1019 return srv.(MatchingServiceServer).AddWorkflowTask(ctx, in)
1020 }
1021 > info := &grpc.UnaryServerInfo{ service_grpc.pb.go
1022 > Server: srv,
1023 > FullMethod: MatchingService_AddWorkflowTask_FullMethodName,
1024 > }
1025 > handler := func(ctx context.Context, req interface{}) (interface{}, error) {
1026 > return srv.(MatchingServiceServer).AddWorkflowTask(ctx, req.(*AddWorkflowTaskRequest))
1027 > }
1028 > return interceptor(ctx, in, info, handler)
1029 }
1030
1155 }
1156
1157 > func _MatchingService_CancelOutstandingPoll_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { service_grpc.pb.go
1158 > in := new(CancelOutstandingPollRequest)
1159 > if err := dec(in); err != nil {
1160 return nil, err
1161 }
1162 > if interceptor == nil { service_grpc.pb.go
1163 return srv.(MatchingServiceServer).CancelOutstandingPoll(ctx, in)
1164 }
1165 > info := &grpc.UnaryServerInfo{ service_grpc.pb.go
1166 > Server: srv,
1167 > FullMethod: MatchingService_CancelOutstandingPoll_FullMethodName,
1168 > }
1169 > handler := func(ctx context.Context, req interface{}) (interface{}, error) {
1170 > return srv.(MatchingServiceServer).CancelOutstandingPoll(ctx, req.(*CancelOutstandingPollRequest))
1171 > }
1172 > return interceptor(ctx, in, info, handler)
1173 }
1174
1317 }
1318
1319 > func _MatchingService_GetTaskQueueUserData_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { service_grpc.pb.go
1320 > in := new(GetTaskQueueUserDataRequest)
1321 > if err := dec(in); err != nil {
1322 return nil, err
1323 }
1324 > if interceptor == nil { service_grpc.pb.go
1325 return srv.(MatchingServiceServer).GetTaskQueueUserData(ctx, in)
1326 }
1327 > info := &grpc.UnaryServerInfo{ service_grpc.pb.go
1328 > Server: srv,
1329 > FullMethod: MatchingService_GetTaskQueueUserData_FullMethodName,
1330 > }
1331 > handler := func(ctx context.Context, req interface{}) (interface{}, error) {
1332 > return srv.(MatchingServiceServer).GetTaskQueueUserData(ctx, req.(*GetTaskQueueUserDataRequest))
1333 > }
1334 > return interceptor(ctx, in, info, handler)
1335 }
1336
1461 }
1462
1463 > func _MatchingService_ForceUnloadTaskQueuePartition_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { service_grpc.pb.go
1464 > in := new(ForceUnloadTaskQueuePartitionRequest)
1465 > if err := dec(in); err != nil {
1466 return nil, err
1467 }
1468 > if interceptor == nil { service_grpc.pb.go
1469 return srv.(MatchingServiceServer).ForceUnloadTaskQueuePartition(ctx, in)
1470 }
1471 > info := &grpc.UnaryServerInfo{ service_grpc.pb.go
1472 > Server: srv,
1473 > FullMethod: MatchingService_ForceUnloadTaskQueuePartition_FullMethodName,
1474 > }
1475 > handler := func(ctx context.Context, req interface{}) (interface{}, error) {
1476 > return srv.(MatchingServiceServer).ForceUnloadTaskQueuePartition(ctx, req.(*ForceUnloadTaskQueuePartitionRequest))
1477 > }
1478 > return interceptor(ctx, in, info, handler)
1479 }
1480
1587 }
1588
1589 > func _MatchingService_ListNexusEndpoints_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { service_grpc.pb.go
1590 > in := new(ListNexusEndpointsRequest)
1591 > if err := dec(in); err != nil {
1592 return nil, err
1593 }
1594 > if interceptor == nil { service_grpc.pb.go
1595 return srv.(MatchingServiceServer).ListNexusEndpoints(ctx, in)
1596 }
1597 > info := &grpc.UnaryServerInfo{ service_grpc.pb.go
1598 > Server: srv,
1599 > FullMethod: MatchingService_ListNexusEndpoints_FullMethodName,
1600 > }
1601 > handler := func(ctx context.Context, req interface{}) (interface{}, error) {
1602 > return srv.(MatchingServiceServer).ListNexusEndpoints(ctx, req.(*ListNexusEndpointsRequest))
1603 > }
1604 > return interceptor(ctx, in, info, handler)
1605 }
1606
1607 > func _MatchingService_RecordWorkerHeartbeat_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { service_grpc.pb.go
1608 > in := new(RecordWorkerHeartbeatRequest)
1609 > if err := dec(in); err != nil {
1610 return nil, err
1611 }
1612 > if interceptor == nil { service_grpc.pb.go
1613 return srv.(MatchingServiceServer).RecordWorkerHeartbeat(ctx, in)
1614 }
1615 > info := &grpc.UnaryServerInfo{ service_grpc.pb.go
1616 > Server: srv,
1617 > FullMethod: MatchingService_RecordWorkerHeartbeat_FullMethodName,
1618 > }
1619 > handler := func(ctx context.Context, req interface{}) (interface{}, error) {
1620 > return srv.(MatchingServiceServer).RecordWorkerHeartbeat(ctx, req.(*RecordWorkerHeartbeatRequest))
1621 > }
1622 > return interceptor(ctx, in, info, handler)
1623 }
1624
go.temporal.io/server/service/history/outbound_queue_factory.go 149 covered LOC · 10 ranges

Open complete file

84 }
85
86 > func NewOutboundQueueFactory(params outboundQueueFactoryParams) QueueFactory { outbound_queue_factory.go
87 > metricsHandler := getOutbountQueueProcessorMetricsHandler(params.MetricsHandler)
88 >
89 > rateLimiterPool := collection.NewOnceMap(
90 > func(key tasks.TaskGroupNamespaceIDAndDestination) quotas.RateLimiter {
91 return quotas.NewDefaultOutgoingRateLimiter(func() float64 {
92 // This is intentionally not failing the function in case of error. The task
106 )
107
108 > grouper := queues.GrouperStateMachineNamespaceIDAndDestination{} outbound_queue_factory.go
109 > f := &outboundQueueFactory{
110 > outboundQueueFactoryParams: params,
111 > hostReaderRateLimiter: queues.NewReaderPriorityRateLimiter(
112 > NewHostRateLimiterRateFn(
113 > params.Config.OutboundProcessorMaxPollHostRPS,
114 > params.Config.PersistenceMaxQPS,
115 > outboundQueuePersistenceMaxRPSRatio,
116 > ),
117 > int64(params.Config.OutboundQueueMaxReaderCount()),
118 > ),
119 > hostScheduler: &queues.CommonSchedulerWrapper{
120 > Scheduler: ctasks.NewGroupByScheduler(
121 > ctasks.GroupBySchedulerOptions[
122 > tasks.TaskGroupNamespaceIDAndDestination,
123 > queues.Executable,
124 > ]{
125 > Logger: params.Logger,
126 > KeyFn: func(e queues.Executable) tasks.TaskGroupNamespaceIDAndDestination {
127 return grouper.KeyTyped(e.GetTask())
128 },
183 },
184 }
185 > return f outbound_queue_factory.go
186 }
187
188 // Start implements QueueFactory.
189 > func (f *outboundQueueFactory) Start() { outbound_queue_factory.go
190 > f.hostScheduler.Start()
191 > }
192
193 // Stop implements QueueFactory.
194 > func (f *outboundQueueFactory) Stop() { outbound_queue_factory.go
195 > f.hostScheduler.Stop()
196 > }
197
198 func (f *outboundQueueFactory) CreateQueue(
199 shardContext historyi.ShardContext,
200 > ) queues.Queue { outbound_queue_factory.go
201 > logger := log.With(shardContext.GetLogger(), tag.ComponentOutboundQueue)
202 > metricsHandler := getOutbountQueueProcessorMetricsHandler(f.MetricsHandler)
203 >
204 > currentClusterName := f.ClusterMetadata.GetCurrentClusterName()
205 >
206 > scheduler := queues.NewRateLimitedScheduler(
207 > f.hostScheduler,
208 > queues.RateLimitedSchedulerOptions{
209 > Enabled: f.Config.TaskSchedulerEnableRateLimiter,
210 > EnableShadowMode: f.Config.TaskSchedulerEnableRateLimiterShadowMode,
211 > StartupDelay: f.Config.TaskSchedulerRateLimiterStartupDelay,
212 > },
213 > currentClusterName,
214 > f.NamespaceRegistry,
215 > f.SchedulerRateLimiter,
216 > f.TimeSource,
217 > f.ChasmRegistry,
218 > logger,
219 > metricsHandler,
220 > )
221 >
222 > rescheduler := queues.NewRescheduler(
223 > scheduler,
224 > shardContext.GetTimeSource(),
225 > logger,
226 > metricsHandler,
227 > )
228 >
229 > activeExecutor := newOutboundQueueActiveTaskExecutor(
230 > shardContext,
231 > f.WorkflowCache,
232 > logger,
233 > metricsHandler,
234 > f.ChasmEngine,
235 > f.MatchingClient,
236 > )
237 >
238 > standbyExecutor := newOutboundQueueStandbyTaskExecutor(
239 > shardContext,
240 > f.WorkflowCache,
241 > currentClusterName,
242 > logger,
243 > metricsHandler,
244 > f.ChasmEngine,
245 > f.ClientBean,
246 > )
247 >
248 > executor := queues.NewActiveStandbyExecutor(
249 > currentClusterName,
250 > f.NamespaceRegistry,
251 > activeExecutor,
252 > standbyExecutor,
253 > logger,
254 > )
255 >
256 > if f.ExecutorWrapper != nil {
257 executor = f.ExecutorWrapper.Wrap(executor)
258 }
259
260 > factory := queues.NewExecutableFactory( outbound_queue_factory.go
261 > executor,
262 > scheduler,
263 > rescheduler,
264 > queues.NewNoopPriorityAssigner(),
265 > shardContext.GetTimeSource(),
266 > shardContext.GetNamespaceRegistry(),
267 > shardContext.GetClusterMetadata(),
268 > f.ChasmRegistry,
269 > queues.GetTaskTypeTagValue,
270 > logger,
271 > metricsHandler,
272 > f.TracerProvider.Tracer(telemetry.ComponentQueueOutbound),
273 > f.DLQWriter,
274 > f.Config.TaskDLQEnabled,
275 > f.Config.TaskDLQUnexpectedErrorAttempts,
276 > f.Config.TaskDLQInternalErrors,
277 > f.Config.TaskDLQErrorPattern,
278 > )
279 > return queues.NewImmediateQueue(
280 > shardContext,
281 > tasks.CategoryOutbound,
282 > scheduler,
283 > rescheduler,
284 > &queues.Options{
285 > ReaderOptions: queues.ReaderOptions{
286 > BatchSize: f.Config.OutboundTaskBatchSize,
287 > MaxPendingTasksCount: f.Config.OutboundQueuePendingTaskMaxCount,
288 > PollBackoffInterval: f.Config.OutboundProcessorPollBackoffInterval,
289 > MaxPredicateSize: f.Config.OutboundQueueMaxPredicateSize,
290 > },
291 > MonitorOptions: queues.MonitorOptions{
292 > PendingTasksCriticalCount: f.Config.OutboundQueuePendingTaskCriticalCount,
293 > // Shared configuration with other queues.
294 > ReaderStuckCriticalAttempts: f.Config.QueueReaderStuckCriticalAttempts,
295 > SliceCountCriticalThreshold: f.Config.QueueCriticalSlicesCount,
296 > },
297 > MaxPollRPS: f.Config.OutboundProcessorMaxPollRPS,
298 > MaxPollInterval: f.Config.OutboundProcessorMaxPollInterval,
299 > MaxPollIntervalJitterCoefficient: f.Config.OutboundProcessorMaxPollIntervalJitterCoefficient,
300 > CheckpointInterval: f.Config.OutboundProcessorUpdateAckInterval,
301 > CheckpointIntervalJitterCoefficient: f.Config.OutboundProcessorUpdateAckIntervalJitterCoefficient,
302 > MaxReaderCount: f.Config.OutboundQueueMaxReaderCount,
303 > MoveGroupTaskCountBase: f.Config.QueueMoveGroupTaskCountBase,
304 > MoveGroupTaskCountMultiplier: f.Config.QueueMoveGroupTaskCountMultiplier,
305 > ShrinkPredicateMaxPendingKeys: f.Config.QueueShrinkPredicateMaxPendingKeys,
306 > },
307 > f.hostReaderRateLimiter,
308 > queues.GrouperStateMachineNamespaceIDAndDestination{},
309 > logger,
310 > metricsHandler,
311 > factory,
312 > outboundTaskGroupPostProcessor(f.ChasmRegistry),
313 > )
314 }
315
316 > func getOutbountQueueProcessorMetricsHandler(handler metrics.Handler) metrics.Handler { outbound_queue_factory.go
317 > return handler.WithTags(metrics.OperationTag(metrics.OperationOutboundQueueProcessorScope))
318 > }
319
320 func StateMachineTask(smRegistry *hsm.Registry, task tasks.Task) (hsm.Ref, hsm.Task, error) {
364 }
365
366 > func outboundTaskGroupPostProcessor(registry *chasm.Registry) func([]tasks.Task) { outbound_queue_factory.go
367 > if registry == nil {
368 return nil
369 }
370 > return func(taskSlice []tasks.Task) { outbound_queue_factory.go
371 > for _, t := range taskSlice {
372 if ct, ok := t.(*tasks.ChasmTask); ok {
373 if rt, ok := registry.TaskByID(ct.Info.GetTypeId()); ok {
go.temporal.io/server/service/matching/pri_matcher.go 148 covered LOC · 38 ranges

Open complete file

100 onRateLimited func(),
101 markAlive func(),
102 > ) *priTaskMatcher { pri_matcher.go
103 > tm := &priTaskMatcher{
104 > config: config,
105 > data: newMatcherData(config, logger, clock.NewRealTimeSource(), fwdr != nil, rateLimitManager, onRateLimited),
106 > tqCtx: tqCtx,
107 > logger: logger,
108 > metricsHandler: metricsHandler,
109 > partition: partition,
110 > fwdr: fwdr,
111 > client: client,
112 > validator: validator,
113 > rateLimitManager: rateLimitManager,
114 > markAlive: markAlive,
115 > priorityBacklogForwarders: goro.NewKeyedSet[remotePriorityBacklog](tqCtx),
116 > }
117 >
118 > return tm
119 > }
120
121 > func (tm *priTaskMatcher) Start() { pri_matcher.go
122 > policy := backoff.NewExponentialRetryPolicy(time.Second).
123 > WithMaximumInterval(tm.config.BacklogTaskForwardTimeout()).
124 > WithExpirationInterval(backoff.NoInterval)
125 > retrier := backoff.NewRetrier(policy, clock.NewRealTimeSource())
126 > lim := quotas.NewDefaultOutgoingRateLimiter(tm.config.ForwarderMaxRatePerSecond)
127 >
128 > if tm.fwdr == nil {
129 > // Root/sticky doesn't forward. But it does need something to validate tasks. pri_matcher.go
130 > go tm.validateTasksOnRoot(retrier)
131 > return
132 > }
133
134 // Non-root normal partitions:
150 }
151
152 > func (tm *priTaskMatcher) Stop() { pri_matcher.go
153 > tm.data.Stop()
154 >
155 > tm.priorityBacklogForwarders.Sync(nil, nil)
156 >
157 > // When we're stopping, sync tasks and pollers will be cancelled by tqCtx being canceled.
158 > // Backlog tasks held in this matcher will be dropped. That's okay if we're stopping the
159 > // whole partition, or for tasks that came from this partition's readers. The exception is
160 > // backlog tasks that were redirected from another versioned queue (or the default). To
161 > // handle those, the caller of Stop should also call ReprocessRedirectedTasksAfterStop
162 > // when applicable.
163 > }
164
165 // TODO(pri): access to retrier is not synchronized
245 }
246
247 > func (tm *priTaskMatcher) validateTasksOnRoot(retrier backoff.Retrier) { pri_matcher.go
248 > ctxs := []context.Context{tm.tqCtx}
249 > poller := &waitingPoller{taskForwarderType: validatorTaskForwarder}
250 > for {
251 > res := tm.data.EnqueuePollerAndWait(ctxs, poller)
252 > if res.ctxErr != nil {
253 > return // task queue closing pri_matcher.go
254 > }
255 > if !softassert.That(tm.logger, res.task != nil, "expected a task from match") { pri_matcher.go
256 continue
257 }
258
259 > task := res.task pri_matcher.go
260 > if !softassert.That(tm.logger, task.forwardCtx == nil, "expected non-forwarded task") ||
261 > !softassert.That(tm.logger, !task.isSyncMatchTask(), "expected non-sync match task") ||
262 > !softassert.That(tm.logger, task.source == enumsspb.TASK_SOURCE_DB_BACKLOG, "expected backlog task") {
263 continue
264 }
265
266 > maybeValid := tm.validator == nil || tm.validator.maybeValidate(task.event.AllocatedTaskInfo, tm.partition.TaskType()) pri_matcher.go
267 > if !maybeValid {
268 // We found an invalid one, complete it and go back for another immediately.
269 task.finish(taskFinishResult{dropReason: getDroppedTaskExpiryReason(task)})
273
274 retrier.Reset()
275 > } else { pri_matcher.go
276 > // Task was valid, put it back and slow down checking. pri_matcher.go
277 > task.finish(taskFinishResult{err: errReprocessTask, consumedToken: true})
278 > // retrier's max interval is backlogTaskForwardTimeout, so for just valid tasks,
279 > // this loop will essentially be limited to that interval.
280 > util.InterruptibleSleep(tm.tqCtx, retrier.NextBackOff(nil))
281 > }
282 }
283 }
386 // - task is matched and consumer returns error in response channel
387
388 > func (tm *priTaskMatcher) Offer(ctx context.Context, task *internalTask) (syncMatchOutcome, error) { pri_matcher.go
389 > finish := func() (syncMatchOutcome, error) {
390 res, ok := task.getResponse()
391 if !softassert.That(tm.logger, ok, "expected a sync match task") {
413 // Fast path if we have a waiting poller (or forwarder).
414 // Forwarding happens here if we match with the task forwarding poller.
415 > task.forwardCtx = ctx pri_matcher.go
416 > outcome := tm.data.MatchTaskImmediately(task)
417 > switch outcome {
418 case syncMatchSuccess:
419 return finish()
420 case syncMatchBacklogPresent:
421 return outcome, nil
422 > default: pri_matcher.go
423 > // We only block if we are the root and the task is forwarded from a backlog.
424 > // Otherwise, stop here.
425 > if tm.isForwardingAllowed() ||
426 > task.source != enumsspb.TASK_SOURCE_DB_BACKLOG ||
427 > !task.isForwarded() {
428 > return outcome, nil
429 > }
430 }
431
511 }
512
513 > func (tm *priTaskMatcher) AddTask(task *internalTask) error { pri_matcher.go
514 > if !task.setRemoveFunc(func() { tm.data.RemoveTask(task) }) {
515 return nil // handle race where task is evicted from reader before being added
516 }
517 > return tm.data.EnqueueTaskNoWait(task) pri_matcher.go
518 }
519
537 // On success, the returned task could be a query task or a regular task
538 // Returns errNoTasks when context deadline is exceeded
539 > func (tm *priTaskMatcher) Poll(ctx context.Context, pollMetadata *pollMetadata) (*internalTask, error) { pri_matcher.go
540 > return tm.poll(ctx, pollMetadata, false)
541 > }
542
543 // PollForQuery blocks until a *query* task is found or context deadline is exceeded
547 }
548
549 > func (tm *priTaskMatcher) ReprocessAllTasks() { pri_matcher.go
550 > tasks := tm.data.ReprocessTasks(func(task *internalTask) (shouldRemove bool) {
551 // TODO(pri): do we have to reprocess _all_ backlog tasks or can we determine
552 // somehow which are potentially redirected?
554 })
555 // ReprocessTasks will have woken sync tasks, but for backlog we also need to call finish.
556 > for _, task := range tasks { pri_matcher.go
557 if !task.isSyncMatchTask() {
558 task.finish(taskFinishResult{err: errReprocessTask, consumedToken: true})
599 func (tm *priTaskMatcher) poll(
600 ctx context.Context, pollMetadata *pollMetadata, queryOnly bool,
601 > ) (*internalTask, error) { pri_matcher.go
602 > start := time.Now()
603 > pollWasForwarded := false
604 > var priority int32
605 > pollResult := "failed"
606 >
607 > defer func() {
608 > // TODO(pri): can we consolidate all the metrics code below?
609 > if pollMetadata.forwardedFrom == "" {
610 > // Only recording for original polls (i.e. on child if forwarded)
611 > metrics.PollLatencyPerTaskQueue.With(tm.metricsHandler).Record(
612 > time.Since(start),
613 > metrics.ForwardedTag(pollWasForwarded),
614 > metrics.MatchingTaskPriorityTag(priority),
615 > metrics.PollResultTag(pollResult),
616 > )
617 > }
618 }()
619
620 > poller := &waitingPoller{ pri_matcher.go
621 > startTime: start,
622 > queryOnly: queryOnly,
623 > forwardCtx: ctx,
624 > pollMetadata: pollMetadata,
625 > }
626 >
627 > var res *matchResult
628 > if pollMetadata.conditions.GetNoWait() {
629 res = tm.data.MatchPollerImmediately(poller)
630 > } else { pri_matcher.go
631 > ctxs := []context.Context{ctx, tm.tqCtx}
632 > res = tm.data.EnqueuePollerAndWait(ctxs, poller)
633 > }
634
635 > if res == nil { pri_matcher.go
636 pollResult = "timeout"
637 return nil, errNoTasks // only possible for MatchPollerImmediately
638 > } else if res.ctxErr != nil { pri_matcher.go
639 > if res.ctxErrIdx == 0 { pri_matcher.go
640 > metrics.PollTimeoutPerTaskQueueCounter.With(tm.metricsHandler).Record(1) pri_matcher.go
641 > }
642 > pollResult = "timeout" pri_matcher.go
643 > return nil, errNoTasks
644 }
645
646 > if !softassert.That(tm.logger, res.task != nil, "expected task from match") { pri_matcher.go
647 return nil, errInternalMatchError
648 }
649
650 > task := res.task pri_matcher.go
651 > pollWasForwarded = task.isStarted() // true if this poll was forwarded _from_ this matcher
652 > priority = task.getPriority().GetPriorityKey()
653 > pollResult = "dispatch"
654 >
655 > if !pollWasForwarded {
656 > // Only record these metrics on the parent for forwarded polls pri_matcher.go
657 > if !task.isQuery() {
658 > if task.isSyncMatchTask() {
659 metrics.PollSuccessWithSyncPerTaskQueueCounter.With(tm.metricsHandler).Record(1)
660 }
661 > metrics.PollSuccessPerTaskQueueCounter.With(tm.metricsHandler).Record(1) pri_matcher.go
662 } else {
663 metrics.PollSuccessWithSyncPerTaskQueueCounter.With(tm.metricsHandler).Record(1)
664 metrics.PollSuccessPerTaskQueueCounter.With(tm.metricsHandler).Record(1)
665 }
666 > tm.emitForwardedSourceStats(task.isForwarded(), pollMetadata.forwardedFrom) pri_matcher.go
667 }
668
669 > return task, nil pri_matcher.go
670 }
671
674 }
675
676 > func (tm *priTaskMatcher) isForwardingAllowed() bool { pri_matcher.go
677 > return tm.fwdr != nil
678 > }
679
680 func (tm *priTaskMatcher) emitForwardedSourceStats(
681 isTaskForwarded bool,
682 pollForwardedSource string,
683 > ) { pri_matcher.go
684 > isPollForwarded := len(pollForwardedSource) > 0
685 > switch {
686 case isTaskForwarded && isPollForwarded:
687 metrics.RemoteToRemoteMatchPerTaskQueueCounter.With(tm.metricsHandler).Record(1)
690 case isPollForwarded:
691 metrics.LocalToRemoteMatchPerTaskQueueCounter.With(tm.metricsHandler).Record(1)
692 > default: pri_matcher.go
693 > metrics.LocalToLocalMatchPerTaskQueueCounter.With(tm.metricsHandler).Record(1)
694 }
695 }
696
697 > func (p *waitingPoller) minPriority() priorityKey { pri_matcher.go
698 > if p.pollMetadata == nil || p.pollMetadata.conditions == nil {
699 > return 0 pri_matcher.go
700 > }
701 return priorityKey(p.pollMetadata.conditions.MinPriority)
702 }
go.temporal.io/server/service/frontend/http_api_server.go 146 covered LOC · 25 ranges

Open complete file

79 namespaceRegistry namespace.Registry,
80 logger log.Logger,
81 > ) (*HTTPAPIServer, error) { http_api_server.go
82 > // Create a TCP listener the same as the frontend one but with different port
83 > tcpAddrRef, _ := grpcListener.Addr().(*net.TCPAddr)
84 > if tcpAddrRef == nil {
85 return nil, errHTTPGRPCListenerNotTCP
86 }
87 > tcpAddr := *tcpAddrRef http_api_server.go
88 > tcpAddr.Port = rpcConfig.HTTPPort
89 > var listener net.Listener
90 > var err error
91 > if listener, err = net.ListenTCP("tcp", &tcpAddr); err != nil {
92 return nil, fmt.Errorf("failed listening for HTTP API on %v: %w", &tcpAddr, err)
93 }
94 // Close the listener if anything else in this function fails
95 > success := false http_api_server.go
96 > defer func() {
97 > if !success {
98 _ = listener.Close()
99 }
101
102 // Wrap the listener in a TLS listener if there is any TLS config
103 > if tlsConfigProvider != nil { http_api_server.go
104 > if tlsConfig, err := tlsConfigProvider.GetFrontendServerConfig(); err != nil { http_api_server.go
105 return nil, fmt.Errorf("failed getting TLS config for HTTP API: %w", err)
106 > } else if tlsConfig != nil { http_api_server.go
107 listener = tls.NewListener(listener, tlsConfig)
108 }
109 }
110
111 > h := &HTTPAPIServer{ http_api_server.go
112 > listener: listener,
113 > logger: logger,
114 > stopped: make(chan struct{}),
115 > allowedHosts: serviceConfig.HTTPAllowedHosts,
116 > }
117 >
118 > // Build 4 possible marshalers in order based on content type
119 > opts := []runtime.ServeMuxOption{
120 > runtime.WithMarshalerOption(newTemporalProtoMarshaler(" ", false)),
121 > runtime.WithMarshalerOption(newTemporalProtoMarshaler("", false)),
122 > runtime.WithMarshalerOption(newTemporalProtoMarshaler(" ", true)),
123 > runtime.WithMarshalerOption(newTemporalProtoMarshaler("", true)),
124 > }
125 >
126 > // Set Temporal service error handler
127 > opts = append(opts, runtime.WithErrorHandler(h.errorHandler))
128 >
129 > // Match headers w/ default
130 > h.matchAdditionalHeaders = map[string]bool{}
131 > for _, v := range defaultForwardedHeaders {
132 > h.matchAdditionalHeaders[v] = true
133 > }
134 > for _, v := range rpcConfig.HTTPAdditionalForwardedHeaders {
135 if before, ok := strings.CutSuffix(v, "*"); ok {
136 h.matchAdditionalHeaderPrefixes = append(h.matchAdditionalHeaderPrefixes, http.CanonicalHeaderKey(before))
140 }
141
142 > opts = append(opts, runtime.WithMiddlewares(h.allowedHostsMiddleware)) http_api_server.go
143 > opts = append(opts, runtime.WithIncomingHeaderMatcher(h.incomingHeaderMatcher))
144 >
145 > // Create inline client connection
146 > clientConn := newInlineClientConn(
147 > map[string]any{
148 > "temporal.api.workflowservice.v1.WorkflowService": handler,
149 > "temporal.api.operatorservice.v1.OperatorService": operatorHandler,
150 > },
151 > interceptors,
152 > metricsHandler,
153 > namespaceRegistry,
154 > )
155 >
156 > // Create serve mux
157 > h.serveMux = runtime.NewServeMux(opts...)
158 >
159 > err = workflowservice.RegisterWorkflowServiceHandlerClient(
160 > context.Background(),
161 > h.serveMux,
162 > workflowservice.NewWorkflowServiceClient(clientConn),
163 > )
164 > if err != nil {
165 return nil, fmt.Errorf("failed registering workflowservice HTTP API handler: %w", err)
166 }
167
168 > err = operatorservice.RegisterOperatorServiceHandlerClient( http_api_server.go
169 > context.Background(),
170 > h.serveMux,
171 > operatorservice.NewOperatorServiceClient(clientConn),
172 > )
173 > if err != nil {
174 return nil, fmt.Errorf("failed registering operatorservice HTTP API handler: %w", err)
175 }
176
177 // Set the / handler as our function that wraps serve mux.
178 > router.PathPrefix("/").HandlerFunc(h.serveHTTP) http_api_server.go
179 > // Register the router as the HTTP server handler.
180 > h.server.Handler = router
181 >
182 > // Put the remote address on the context
183 > h.server.ConnContext = func(ctx context.Context, c net.Conn) context.Context {
184 return context.WithValue(ctx, httpRemoteAddrContextKey{}, c)
185 }
188 // defaults to ReadTimeout) to ensure that a connection cannot hang over that
189 // amount of time.
190 > h.server.ReadTimeout = serviceConfig.KeepAliveMaxConnectionIdle() http_api_server.go
191 > h.server.WriteTimeout = serviceConfig.KeepAliveMaxConnectionIdle()
192 >
193 > success = true
194 > return h, nil
195 }
196
198 // GracefulStop completes. Upon graceful stop, this will return nil. If an error
199 // is returned, the message is clear that it came from the HTTP API server.
200 > func (h *HTTPAPIServer) Serve() error { http_api_server.go
201 > err := h.server.Serve(h.listener)
202 > // If the error is for close, we have to wait for the shutdown to complete and
203 > // we don't consider it an error
204 > if errors.Is(err, http.ErrServerClosed) {
205 > <-h.stopped
206 > err = nil
207 > }
208 // Wrap the error to be clearer it's from the HTTP API
209 > if err != nil { http_api_server.go
210 return fmt.Errorf("HTTP API serve failed: %w", err)
211 }
212 > return nil http_api_server.go
213 }
214
215 // GracefulStop stops the HTTP server. This will first attempt a graceful stop
216 // with a drain time, then will hard-stop. This will not return until stopped.
217 > func (h *HTTPAPIServer) GracefulStop(gracefulDrainTime time.Duration) { http_api_server.go
218 > // We try a graceful stop for the amount of time we can drain, then we do a
219 > // hard stop
220 > shutdownCtx, cancel := context.WithTimeout(context.Background(), gracefulDrainTime)
221 > defer cancel()
222 > // We intentionally ignore this error, we're gonna stop at this point no
223 > // matter what. This closes the listener too.
224 > _ = h.server.Shutdown(shutdownCtx)
225 > _ = h.server.Close()
226 > close(h.stopped)
227 > }
228
229 func (h *HTTPAPIServer) serveHTTP(w http.ResponseWriter, r *http.Request) {
272 }
273
274 > func (h *HTTPAPIServer) allowedHostsMiddleware(hf runtime.HandlerFunc) runtime.HandlerFunc { http_api_server.go
275 > return func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) {
276 allowedHosts := h.allowedHosts()
277 if allowedHosts.MatchString(r.Host) {
318 }
319
320 > func (h *HTTPAPIServer) incomingHeaderMatcher(headerName string) (string, bool) { http_api_server.go
321 > // Try ours before falling back to default
322 > if h.matchAdditionalHeaders[headerName] {
323 return headerName, true
324 }
325 > for _, prefix := range h.matchAdditionalHeaderPrefixes { http_api_server.go
326 if strings.HasPrefix(headerName, prefix) {
327 return headerName, true
328 }
329 }
330 > return runtime.DefaultHeaderMatcher(headerName) http_api_server.go
331 }
332
359 metricsHandler metrics.Handler,
360 namespaceRegistry namespace.Registry,
361 > ) *inlineClientConn { http_api_server.go
362 > // Create the set of methods via reflection. We currently accept the overhead
363 > // of reflection compared to having to custom generate gateway code.
364 > methods := map[string]*serviceMethod{}
365 > for qualifiedServerName, server := range servers {
366 > serverVal := reflect.ValueOf(server)
367 > for reflectMethod := range serverVal.Type().Methods() {
368 > // We intentionally look this up by name to not assume method indexes line
369 > // up from type to value
370 > methodVal := serverVal.MethodByName(reflectMethod.Name)
371 > // We assume the methods we want only accept a context + request and only
372 > // return a response + error. We also assume the method name matches the
373 > // RPC name.
374 > methodType := methodVal.Type()
375 > validRPCMethod := methodType.Kind() == reflect.Func &&
376 > methodType.NumIn() == 2 &&
377 > methodType.NumOut() == 2 &&
378 > methodType.In(0) == contextType &&
379 > methodType.In(1).Implements(protoMessageType) &&
380 > methodType.Out(0).Implements(protoMessageType) &&
381 > methodType.Out(1) == errorType
382 > if !validRPCMethod {
383 > continue
384 }
385 > fullMethod := "/" + qualifiedServerName + "/" + reflectMethod.Name http_api_server.go
386 > methods[fullMethod] = &serviceMethod{
387 > info: grpc.UnaryServerInfo{Server: server, FullMethod: fullMethod},
388 > handler: func(ctx context.Context, req any) (any, error) {
389 ret := methodVal.Call([]reflect.Value{reflect.ValueOf(ctx), reflect.ValueOf(req)})
390 err, _ := ret[1].Interface().(error)
395 }
396
397 > return &inlineClientConn{ http_api_server.go
398 > methods: methods,
399 > interceptor: chainUnaryServerInterceptors(interceptors),
400 > requestsCounter: metrics.HTTPServiceRequests.With(metricsHandler),
401 > namespaceRegistry: namespaceRegistry,
402 > }
403 }
404
475 // Mostly taken from https://github.com/grpc/grpc-go/blob/v1.56.1/server.go#L1124-L1158
476 // with slight modifications.
477 > func chainUnaryServerInterceptors(interceptors []grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor { http_api_server.go
478 > switch len(interceptors) {
479 case 0:
480 return nil
481 case 1:
482 return interceptors[0]
483 > default: http_api_server.go
484 > return chainUnaryInterceptors(interceptors)
485 }
486 }
487
488 > func chainUnaryInterceptors(interceptors []grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor { http_api_server.go
489 > return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
490 return interceptors[0](ctx, req, info, getChainUnaryHandler(interceptors, 0, info, handler))
491 }
go.temporal.io/server/service/matching/pri_backlog_manager.go 146 covered LOC · 27 ranges

Open complete file

83 metricsHandler metrics.Handler,
84 isDraining bool,
85 > ) *priBacklogManagerImpl { pri_backlog_manager.go
86 > bmg := &priBacklogManagerImpl{
87 > pqMgr: pqMgr,
88 > config: config,
89 > tqCtx: tqCtx,
90 > isDraining: isDraining,
91 > db: newTaskQueueDB(config, taskManager, pqMgr.QueueKey(), logger, metricsHandler, isDraining),
92 > subqueuesByPriority: make(map[priorityKey]subqueueIndex),
93 > priorityBySubqueue: make(map[subqueueIndex]priorityKey),
94 > matchingClient: matchingClient,
95 > metricsHandler: metricsHandler,
96 > logger: logger,
97 > throttledLogger: throttledLogger,
98 > initializedError: future.NewFuture[struct{}](),
99 > }
100 > bmg.taskWriter = newPriTaskWriter(bmg)
101 > return bmg
102 > }
103
104 // signalIfFatal calls UnloadFromPartitionManager of the physicalTaskQueueManager
106 // of a newer lease by another backlogManager. Returns true if the unload signal
107 // is emitted, false otherwise.
108 > func (c *priBacklogManagerImpl) signalIfFatal(err error) bool { pri_backlog_manager.go
109 > if err == nil {
110 > return false
111 > }
112 var condfail *persistence.ConditionFailedError
113 if errors.As(err, &condfail) {
120 }
121
122 > func (c *priBacklogManagerImpl) Start() { pri_backlog_manager.go
123 > c.taskWriter.Start()
124 > }
125
126 > func (c *priBacklogManagerImpl) Stop() { pri_backlog_manager.go
127 > // Maybe try to write one final update of ack level. Skip the update if we never
128 > // initialized. Also skip if we're stopping due to lost ownership (the update will
129 > // fail in that case). Ignore any errors. Don't bother with GC, the next reload will
130 > // handle that.
131 > if !c.initializedError.Ready() || c.skipFinalUpdate.Load() {
132 return
133 }
134
135 > c.subqueueLock.Lock() pri_backlog_manager.go
136 > for i, r := range c.subqueues {
137 > _, ackLevel := r.getLevels()
138 > // oldestTime can be time.Time{} here since countDelta is 0
139 > c.db.updateAckLevelAndBacklogStats(subqueueIndex(i), ackLevel, 0, time.Time{})
140 > }
141 > c.subqueueLock.Unlock()
142 >
143 > ctx, cancel := context.WithTimeout(c.tqCtx, ioTimeout)
144 > _ = c.db.SyncState(ctx)
145 > cancel()
146 }
147
148 > func (c *priBacklogManagerImpl) initState(state taskQueueState, err error) { pri_backlog_manager.go
149 > defer c.initializedError.Set(struct{}{}, err)
150 >
151 > if err != nil {
152 // We can't recover from here without starting over, so unload the whole task queue.
153 // Skip final update since we never initialized.
159 // Pass scale info back to physical tq from unversioned (default) queue.
160 // This must be done before c.initializedError.Set().
161 > if c.queueKey().Partition().IsRoot() && !c.queueKey().IsVersioned() && !c.isDraining { pri_backlog_manager.go
162 > c.pqMgr.StartScaleManager(state.scaleState) pri_backlog_manager.go
163 > }
164
165 > if state.otherHasTasks { pri_backlog_manager.go
166 > c.pqMgr.SetupDraining() pri_backlog_manager.go
167 > }
168
169 > c.subqueueLock.Lock() pri_backlog_manager.go
170 > defer c.subqueueLock.Unlock()
171 >
172 > c.loadSubqueuesLocked(state.subqueues)
173 > go c.periodicSync()
174 }
175
176 > func (c *priBacklogManagerImpl) WaitUntilInitialized(ctx context.Context) error { pri_backlog_manager.go
177 > _, err := c.initializedError.Get(ctx)
178 > return err
179 > }
180
181 > func (c *priBacklogManagerImpl) loadSubqueuesLocked(subqueues []persistencespb.SubqueueInfo) { pri_backlog_manager.go
182 > // TODO(pri): This assumes that subqueues never shrinks, and priority/fairness index of
183 > // existing subqueues never changes. If we change that, this logic will need to change.
184 > for i := range subqueues {
185 > if i >= len(c.subqueues) {
186 > r := newPriTaskReader(c, subqueueIndex(i), subqueues[i].AckLevel)
187 > r.Start()
188 > c.subqueues = append(c.subqueues, r)
189 > }
190 > c.subqueuesByPriority[priorityKey(subqueues[i].Key.Priority)] = subqueueIndex(i)
191 > c.priorityBySubqueue[subqueueIndex(i)] = priorityKey(subqueues[i].Key.Priority)
192 }
193 }
194
195 > func (c *priBacklogManagerImpl) getSubqueueForPriority(priority priorityKey) subqueueIndex { pri_backlog_manager.go
196 > priority = c.config.clipPriority(priority)
197 >
198 > c.subqueueLock.Lock()
199 > defer c.subqueueLock.Unlock()
200 >
201 > if i, ok := c.subqueuesByPriority[priority]; ok {
202 > return i
203 > }
204
205 // We need to allocate a new subqueue. Note this is doing io under subqueueLock,
228 }
229
230 > func (c *priBacklogManagerImpl) periodicSync() { pri_backlog_manager.go
231 > for {
232 > select {
233 > case <-c.tqCtx.Done(): pri_backlog_manager.go
234 > return
235 case <-time.After(c.config.UpdateAckInterval()):
236 ctx, cancel := context.WithTimeout(c.tqCtx, ioTimeout)
247 }
248
249 > func (c *priBacklogManagerImpl) SpoolTask(taskInfo *persistencespb.TaskInfo) error { pri_backlog_manager.go
250 > subqueue := c.getSubqueueForPriority(priorityKey(taskInfo.Priority.GetPriorityKey()))
251 > err := c.taskWriter.appendTask(subqueue, taskInfo)
252 > c.signalIfFatal(err)
253 > return err
254 > }
255
256 > func (c *priBacklogManagerImpl) signalReaders(resp createTasksResponse) { pri_backlog_manager.go
257 > c.subqueueLock.Lock()
258 > subqueues := slices.Clone(c.subqueues)
259 > c.subqueueLock.Unlock()
260 >
261 > for subqueue, subqueueResp := range resp.bySubqueue {
262 > subqueues[subqueue].signalNewTasks(subqueueResp)
263 > }
264 }
265
266 > func (c *priBacklogManagerImpl) addSpooledTask(task *internalTask) error { pri_backlog_manager.go
267 > return c.pqMgr.AddSpooledTask(task)
268 > }
269
270 > func (c *priBacklogManagerImpl) BacklogCountHint() (total int64) { pri_backlog_manager.go
271 > c.subqueueLock.Lock()
272 > defer c.subqueueLock.Unlock()
273 > for _, r := range c.subqueues {
274 > total += int64(r.getLoadedTasks())
275 > }
276 > return
277 }
278
279 > func (c *priBacklogManagerImpl) BacklogStatsByPriority() map[int32]*taskqueuepb.TaskQueueStats { pri_backlog_manager.go
280 > c.subqueueLock.Lock()
281 > defer c.subqueueLock.Unlock()
282 >
283 > result := make(map[int32]*taskqueuepb.TaskQueueStats)
284 > backlogCounts := c.db.getApproximateBacklogCountsBySubqueue()
285 > for subqueueIdx, priorityKey := range c.priorityBySubqueue {
286 > pk := int32(priorityKey)
287 >
288 > // Note that there could be more than one subqueue for the same priority.
289 > if _, ok := result[pk]; !ok {
290 > result[pk] = &taskqueuepb.TaskQueueStats{
291 > // TODO(pri): returning 0 to match existing behavior, but maybe emptyBacklogAge would
292 > // be more appropriate in the future.
293 > ApproximateBacklogAge: durationpb.New(0),
294 > }
295 > }
296
297 // Add backlog counts together across all subqueues for the same priority.
298 > result[pk].ApproximateBacklogCount += backlogCounts[subqueueIdx] pri_backlog_manager.go
299 >
300 > // Find greatest backlog age for across all subqueues for the same priority.
301 > oldestBacklogTime := c.subqueues[subqueueIdx].getOldestBacklogTime()
302 > if !oldestBacklogTime.IsZero() {
303 > oldestBacklogAge := time.Since(oldestBacklogTime) pri_backlog_manager.go
304 > if oldestBacklogAge > result[pk].ApproximateBacklogAge.AsDuration() {
305 > result[pk].ApproximateBacklogAge = durationpb.New(oldestBacklogAge)
306 > }
307 }
308 }
309 > return result pri_backlog_manager.go
310 }
311
397 // }
398
399 > func (c *priBacklogManagerImpl) queueKey() *PhysicalTaskQueueKey { pri_backlog_manager.go
400 > return c.pqMgr.QueueKey()
401 > }
402
403 > func (c *priBacklogManagerImpl) getDB() *taskQueueDB { pri_backlog_manager.go
404 > return c.db
405 > }
406
407 // hasFinishedDraining returns true if this is a draining backlog manager and all tasks have
437 }
438
439 > func (c *priBacklogManagerImpl) setPriority(task *internalTask) { pri_backlog_manager.go
440 > c.config.setDefaultPriority(task)
441 > if c.isDraining {
442 // draining goes before active backlog so we're guaranteed to finish migration
443 task.effectivePriority -= effectivePriorityFactor * maxPriorityLevels
go.temporal.io/server/common/persistence/client/quotas.go 143 covered LOC · 28 ranges

Open complete file

70 metricsHandler metrics.Handler,
71 logger log.Logger,
72 > ) quotas.RequestRateLimiter { quotas.go
73 > hostRateFn := func() float64 { return float64(hostMaxQPS()) }
74
75 > return quotas.NewMultiRequestRateLimiter( quotas.go
76 > // host-level dynamic rate limiter
77 > newPriorityDynamicRateLimiter(
78 > hostRateFn,
79 > requestPriorityFn,
80 > operatorRPSRatio,
81 > burstRatio,
82 > healthSignals,
83 > dynamicParams,
84 > metricsHandler,
85 > logger,
86 > ),
87 > // basic host-level rate limiter
88 > newPriorityRateLimiter(
89 > hostRateFn,
90 > requestPriorityFn,
91 > operatorRPSRatio,
92 > burstRatio,
93 > ),
94 > )
95 }
96
101 operatorRPSRatio OperatorRPSRatio,
102 burstRatio PersistenceBurstRatio,
103 > ) quotas.RequestRateLimiter { quotas.go
104 >
105 > return newPriorityNamespaceRateLimiter(
106 > namespaceMaxQPS,
107 > hostMaxQPS,
108 > requestPriorityFn,
109 > operatorRPSRatio,
110 > burstRatio,
111 > )
112 > }
113
114 func NewPriorityNamespaceShardRateLimiter(
118 operatorRPSRatio OperatorRPSRatio,
119 burstRatio PersistenceBurstRatio,
120 > ) quotas.RequestRateLimiter { quotas.go
121 >
122 > return newPerShardPerNamespacePriorityRateLimiter(
123 > perShardNamespaceMaxQPS,
124 > hostMaxQPS,
125 > requestPriorityFn,
126 > operatorRPSRatio,
127 > burstRatio,
128 > )
129 > }
130
131 func newPerShardPerNamespacePriorityRateLimiter(
135 operatorRPSRatio OperatorRPSRatio,
136 burstRatio PersistenceBurstRatio,
137 > ) quotas.RequestRateLimiter { quotas.go
138 > return quotas.NewMapRequestRateLimiter(func(req quotas.Request) quotas.RequestRateLimiter {
139 > if hasCaller(req) && hasCallerSegment(req) {
140 > return newPriorityRateLimiter(func() float64 { quotas.go
141 > if perShardNamespaceMaxQPS == nil || perShardNamespaceMaxQPS(req.Caller) <= 0 {
142 > return float64(hostMaxQPS()) quotas.go
143 > }
144 return float64(perShardNamespaceMaxQPS(req.Caller))
145 },
149 )
150 }
151 > return quotas.NoopRequestRateLimiter quotas.go
152 },
153 perShardPerNamespaceKeyFn,
155 }
156
157 > func perShardPerNamespaceKeyFn(req quotas.Request) perShardPerNamespaceKey { quotas.go
158 > return perShardPerNamespaceKey{
159 > namespaceID: req.Caller,
160 > shardID: req.CallerSegment,
161 > }
162 > }
163
164 func newPriorityNamespaceRateLimiter(
168 operatorRPSRatio OperatorRPSRatio,
169 burstRatio PersistenceBurstRatio,
170 > ) quotas.RequestRateLimiter { quotas.go
171 > return quotas.NewNamespaceRequestRateLimiter(func(req quotas.Request) quotas.RequestRateLimiter {
172 > if hasCaller(req) {
173 > return newPriorityRateLimiter( quotas.go
174 > func() float64 {
175 > if namespaceMaxQPS == nil {
176 return float64(hostMaxQPS())
177 }
178
179 > namespaceQPS := float64(namespaceMaxQPS(req.Caller)) quotas.go
180 > if namespaceQPS <= 0 {
181 > return float64(hostMaxQPS()) quotas.go
182 > }
183
184 return namespaceQPS
189 )
190 }
191 > return quotas.NoopRequestRateLimiter quotas.go
192 })
193 }
198 operatorRPSRatio OperatorRPSRatio,
199 burstRatio PersistenceBurstRatio,
200 > ) quotas.RequestRateLimiter { quotas.go
201 > rateLimiters := make(map[int]quotas.RequestRateLimiter)
202 > for priority := range RequestPrioritiesOrdered {
203 > if priority == CallerTypeDefaultPriority[headers.CallerTypeOperator] {
204 > rateLimiters[priority] = quotas.NewRequestRateLimiterAdapter(
205 > quotas.NewDefaultRateLimiter(
206 > operatorRateFn(rateFn, operatorRPSRatio),
207 > quotas.BurstRatioFn(burstRatio),
208 > ),
209 > )
210 > } else {
211 > rateLimiters[priority] = quotas.NewRequestRateLimiterAdapter(
212 > quotas.NewDefaultRateLimiter(
213 > rateFn,
214 > quotas.BurstRatioFn(burstRatio),
215 > ),
216 > )
217 > }
218 }
219
220 > return quotas.NewPriorityRateLimiter( quotas.go
221 > requestPriorityFn,
222 > rateLimiters,
223 > )
224 }
225
233 metricsHandler metrics.Handler,
234 logger log.Logger,
235 > ) quotas.RequestRateLimiter { quotas.go
236 > rateLimiters := make(map[int]quotas.RequestRateLimiter)
237 > for priority := range RequestPrioritiesOrdered {
238 > // TODO: refactor this so dynamic rate adjustment is global for all priorities
239 > if priority == CallerTypeDefaultPriority[headers.CallerTypeOperator] {
240 > rateLimiters[priority] = NewHealthRequestRateLimiterImpl(
241 > healthSignals,
242 > operatorRateFn(rateFn, operatorRPSRatio),
243 > dynamicParams,
244 > burstRatio,
245 > metricsHandler,
246 > logger,
247 > )
248 > } else {
249 > rateLimiters[priority] = NewHealthRequestRateLimiterImpl(
250 > healthSignals,
251 > rateFn,
252 > dynamicParams,
253 > burstRatio,
254 > metricsHandler,
255 > logger,
256 > )
257 > }
258 }
259
260 > return quotas.NewPriorityRateLimiter( quotas.go
261 > requestPriorityFn,
262 > rateLimiters,
263 > )
264 }
265
266 > func RequestPriorityFn(req quotas.Request) int { quotas.go
267 > switch req.CallerType {
268 > case headers.CallerTypeOperator: quotas.go
269 > return CallerTypeDefaultPriority[req.CallerType]
270 > case headers.CallerTypeAPI: quotas.go
271 > if priority, ok := APITypeCallOriginPriorityOverride[req.Initiation]; ok {
272 > return priority quotas.go
273 > }
274 > return CallerTypeDefaultPriority[req.CallerType] quotas.go
275 > case headers.CallerTypeBackgroundHigh, headers.CallerTypeBackgroundLow: quotas.go
276 > if priority, ok := BackgroundTypeAPIPriorityOverride[req.API]; ok {
277 > return priority
278 > }
279 > return CallerTypeDefaultPriority[req.CallerType]
280 case headers.CallerTypePreemptable:
281 return CallerTypeDefaultPriority[req.CallerType]
282 > default: quotas.go
283 > // default requests to API priority to be consistent with existing behavior
284 > return CallerTypeDefaultPriority[headers.CallerTypeAPI]
285 }
286 }
287
288 > func operatorRateFn(rateFn quotas.RateFn, operatorRPSRatio OperatorRPSRatio) quotas.RateFn { quotas.go
289 > return func() float64 {
290 > return operatorRPSRatio() * rateFn()
291 > }
292 }
293
294 > func hasCaller(req quotas.Request) bool { quotas.go
295 > return req.Caller != "" && req.Caller != headers.CallerNameSystem
296 > }
297
298 > func hasCallerSegment(req quotas.Request) bool { quotas.go
299 > return req.CallerSegment > 0 && req.CallerSegment != p.CallerSegmentMissing
300 > }
go.temporal.io/server/service/history/api/startworkflow/api.go 142 covered LOC · 27 ranges

Open complete file

95 reactivationSignaler api.VersionReactivationSignalerFn,
96 createLeaseFn api.CreateOrUpdateLeaseFunc,
97 > ) (*Starter, error) { api.go
98 > namespaceEntry, err := api.GetActiveNamespace(shardContext, namespace.ID(request.GetNamespaceId()), request.StartRequest.WorkflowId)
99 > if err != nil {
100 return nil, err
101 }
102
103 > return &Starter{ api.go
104 > // metricsHandler is lazily created when needed in Starter.getMetricsHandler
105 > metricsHandler: nil,
106 > shardContext: shardContext,
107 > workflowConsistencyChecker: workflowConsistencyChecker,
108 > matchingClient: matchingClient,
109 > tokenSerializer: tokenSerializer,
110 > request: request,
111 > namespace: namespaceEntry,
112 > createOrUpdateLeaseFn: createLeaseFn,
113 > versionCache: versionCache,
114 > reactivationSignaler: reactivationSignaler,
115 > }, nil
116 }
117
118 // prepare applies request overrides, validates the request, and records eager execution metrics.
119 > func (s *Starter) prepare(ctx context.Context) error { api.go
120 > request := s.request.StartRequest
121 >
122 > api.MigrateWorkflowIDReusePolicyForRunningWorkflow(
123 > &request.WorkflowIdReusePolicy,
124 > &request.WorkflowIdConflictPolicy)
125 >
126 > api.OverrideStartWorkflowExecutionRequest(
127 > request,
128 > metrics.HistoryStartWorkflowExecutionScope,
129 > s.shardContext,
130 > s.shardContext.GetMetricsHandler(),
131 > )
132 >
133 > err := api.ValidateStartWorkflowExecutionRequest(ctx, request, s.shardContext, s.namespace, "StartWorkflowExecution")
134 > if err != nil {
135 return err
136 }
137
138 // Validation for versioning override, if any.
139 > s.shouldSkipReactivation, s.revisionNumber, err = worker_versioning.ValidateVersioningOverrideAndGetReactivationEligibility(ctx, request.GetVersioningOverride(), s.matchingClient, s.versionCache, request.GetTaskQueue().GetName(), enumspb.TASK_QUEUE_TYPE_WORKFLOW, s.namespace.ID().String()) api.go
140 > if err != nil {
141 return err
142 }
143
144 > if request.RequestEagerExecution { api.go
145 metricsHandler := s.getMetricsHandler()
146 metrics.WorkflowEagerExecutionCounter.With(metricsHandler).Record(1)
157 }
158 }
159 > return nil api.go
160 }
161
173 }
174
175 > func (s *Starter) requestEagerStart() bool { api.go
176 > return s.request.StartRequest.GetRequestEagerExecution()
177 > }
178
179 // Invoke starts a new workflow execution.
182 func (s *Starter) Invoke(
183 ctx context.Context,
184 > ) (resp *historyservice.StartWorkflowExecutionResponse, startOutcome StartOutcome, retError error) { api.go
185 > request := s.request.StartRequest
186 > if err := s.prepare(ctx); err != nil {
187 return nil, StartErr, err
188 }
189
190 > creationParams, err := s.prepareNewWorkflow(ctx, request.GetWorkflowId()) api.go
191 > if err != nil {
192 return nil, StartErr, err
193 }
194 > defer func() { api.go
195 > creationParams.workflowLease.GetReleaseFn()(retError)
196 > }()
197
198 > currentExecutionLock, err := s.lockCurrentWorkflowExecution(ctx) api.go
199 > if err != nil {
200 return nil, StartErr, err
201 }
202 > defer func() { api.go
203 > currentExecutionLock(retError)
204 > }()
205
206 > err = s.createBrandNew(ctx, creationParams) api.go
207 > if err != nil {
208 var currentWorkflowConditionFailedError *persistence.CurrentWorkflowConditionFailedError
209 if errors.As(err, &currentWorkflowConditionFailedError) && len(currentWorkflowConditionFailedError.RunID) > 0 {
222
223 // Notify version workflow if we're pinning to a potentially drained version
224 > api.ReactivateVersionWorkflowIfPinned(ctx, s.namespace, s.request.StartRequest.GetVersioningOverride(), s.reactivationSignaler, s.shardContext.GetConfig().EnableVersionReactivationSignals(), s.shouldSkipReactivation, s.revisionNumber) api.go
225 >
226 > resp, err = s.generateResponse(
227 > creationParams.runID,
228 > creationParams.runID, // brand-new chain: first == current run
229 > creationParams.workflowTaskInfo,
230 > extractHistoryEvents(creationParams.workflowEventBatches),
231 > )
232 > return resp, StartNew, err
233 }
234
235 func (s *Starter) lockCurrentWorkflowExecution(
236 ctx context.Context,
237 > ) (historyi.ReleaseWorkflowContextFunc, error) { api.go
238 > currentRelease, err := s.workflowConsistencyChecker.GetWorkflowCache().GetOrCreateCurrentExecution(
239 > ctx,
240 > s.shardContext,
241 > s.namespace.ID(),
242 > s.request.StartRequest.WorkflowId,
243 > chasm.WorkflowArchetypeID,
244 > locks.PriorityHigh,
245 > )
246 > if err != nil {
247 return nil, err
248 }
249 > return currentRelease, nil api.go
250 }
251
252 // prepareNewWorkflow creates a new workflow context, and closes its mutable state transaction as snapshot.
253 // It returns the creationContext which can later be used to insert into the executions table.
254 > func (s *Starter) prepareNewWorkflow(ctx context.Context, workflowID string) (*creationParams, error) { api.go
255 > runID := primitives.NewUUID().String()
256 > mutableState, err := api.NewWorkflowWithSignal(
257 > s.shardContext,
258 > s.namespace,
259 > workflowID,
260 > runID,
261 > s.request,
262 > nil,
263 > )
264 > if err != nil {
265 return nil, err
266 }
267
268 > workflowLease, err := s.createOrUpdateLeaseFn(nil, s.shardContext, mutableState) api.go
269 > if err != nil {
270 return nil, err
271 }
272
273 > workflowTaskInfo := mutableState.GetStartedWorkflowTask() api.go
274 > if s.requestEagerStart() && workflowTaskInfo == nil {
275 return nil, softassert.UnexpectedInternalErr(
276 s.shardContext.GetLogger(),
279 )
280 }
281 > workflowSnapshot, eventBatches, err := mutableState.CloseTransactionAsSnapshot( api.go
282 > ctx,
283 > historyi.TransactionPolicyActive,
284 > )
285 > if err != nil {
286 return nil, err
287 }
288 > if len(eventBatches) != 1 { api.go
289 return nil, softassert.UnexpectedInternalErr(
290 s.shardContext.GetLogger(),
294 }
295
296 > return &creationParams{ api.go
297 > workflowID: workflowID,
298 > runID: runID,
299 > workflowLease: workflowLease,
300 > workflowTaskInfo: workflowTaskInfo,
301 > workflowSnapshot: workflowSnapshot,
302 > workflowEventBatches: eventBatches,
303 > }, nil
304 }
305
306 // createBrandNew creates a "brand new" execution in the executions table.
307 > func (s *Starter) createBrandNew(ctx context.Context, creationParams *creationParams) error { api.go
308 > return creationParams.workflowLease.GetContext().CreateWorkflowExecution(
309 > ctx,
310 > s.shardContext,
311 > persistence.CreateWorkflowModeBrandNew,
312 > "", // prevRunID
313 > 0, // prevLastWriteVersion
314 > creationParams.workflowLease.GetMutableState(),
315 > creationParams.workflowSnapshot,
316 > creationParams.workflowEventBatches,
317 > historyi.TransactionPolicyActive,
318 > )
319 > }
320
321 // handleConflict handles CurrentWorkflowConditionFailedError where there's a workflow with the same workflowID.
769 // extractHistoryEvents extracts all history events from a batch of events sent to persistence.
770 // It's unlikely that persistence events would span multiple batches but better safe than sorry.
771 > func extractHistoryEvents(persistenceEvents []*persistence.WorkflowEvents) []*historypb.HistoryEvent { api.go
772 > if len(persistenceEvents) == 1 {
773 > return persistenceEvents[0].Events
774 > }
775 var events []*historypb.HistoryEvent
776 for _, page := range persistenceEvents {
789 workflowTaskInfo *historyi.WorkflowTaskInfo,
790 historyEvents []*historypb.HistoryEvent,
791 > ) (*historyservice.StartWorkflowExecutionResponse, error) { api.go
792 > shardCtx := s.shardContext
793 > tokenSerializer := s.tokenSerializer
794 > request := s.request.StartRequest
795 > workflowID := request.WorkflowId
796 >
797 > if !s.requestEagerStart() {
798 > return &historyservice.StartWorkflowExecutionResponse{ api.go
799 > RunId: runID,
800 > FirstExecutionRunId: firstExecutionRunID,
801 > Started: true,
802 > Status: enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING,
803 > Link: s.generateStartedEventRefLink(runID),
804 > }, nil
805 > }
806
807 clock, err := shardCtx.NewVectorClock()
850 }
851
852 > func (s *Starter) generateStartedEventRefLink(runID string) *commonpb.Link { api.go
853 > return api.GenerateStartedEventRefLink(
854 > s.namespace.Name().String(),
855 > s.request.StartRequest.WorkflowId,
856 > runID,
857 > )
858 > }
859
860 func (s *Starter) generateRequestIdRefLink(runID string) *commonpb.Link {
go.temporal.io/server/service/history/replication/fx.go 141 covered LOC · 22 ranges

Open complete file

42 var Module = fx.Provide(
43 NewTaskFetcherFactory,
44 > func(m persistence.ExecutionManager) ExecutionManager { fx.go
45 > return m
46 > },
47 nsreplication.NewNoopDataMerger,
48 nsreplication.NewDefaultAdmitter,
51 ServerSchedulerRateLimiterProvider,
52 PersistenceRateLimiterProvider,
53 > func(serializer serialization.Serializer) TaskSerializer { fx.go
54 > return serializer
55 > },
56 replicationTaskConverterFactoryProvider,
57 replicationTaskExecutorProvider,
86 metricsHandler metrics.Handler,
87 testHooks testhooks.TestHooks,
88 > ) EagerNamespaceRefresher { fx.go
89 > return NewEagerNamespaceRefresher(
90 > metadataManager,
91 > namespaceRegistry,
92 > logger,
93 > clientBean,
94 > nsreplication.NewTaskExecutor(
95 > clusterMetadata.GetCurrentClusterName(),
96 > metadataManager,
97 > dataMerger,
98 > admitter,
99 > logger,
100 > testHooks,
101 > ),
102 > clusterMetadata.GetCurrentClusterName(),
103 > metricsHandler,
104 > )
105 > }
106
107 func replicationTaskConverterFactoryProvider(
108 config *configs.Config,
109 replicationTaskSerializer TaskSerializer,
110 > ) SourceTaskConverterProvider { fx.go
111 > return func(
112 > historyEngine historyi.Engine,
113 > shardContext historyi.ShardContext,
114 > clientClusterName string,
115 > serializer serialization.Serializer,
116 > ) SourceTaskConverter {
117 return NewSourceTaskConverter(
118 historyEngine,
124 }
125
126 > func replicationTaskExecutorProvider() TaskExecutorProvider { fx.go
127 > return func(params TaskExecutorParams) TaskExecutor {
128 return NewTaskExecutor(
129 params.RemoteCluster,
141 queueFactory ctasks.SequentialTaskQueueFactory[TrackableExecutableTask],
142 lc fx.Lifecycle,
143 > ) ctasks.Scheduler[TrackableExecutableTask] { fx.go
144 > // SequentialScheduler has panic wrapper when executing task,
145 > // if changing the executor, please make sure other executor has panic wrapper
146 > scheduler := ctasks.NewSequentialScheduler[TrackableExecutableTask](
147 > &ctasks.SequentialSchedulerOptions{
148 > QueueSize: config.ReplicationProcessorSchedulerQueueSize(),
149 > WorkerCount: config.ReplicationProcessorSchedulerWorkerCount,
150 > },
151 > WorkflowKeyHashFn,
152 > queueFactory,
153 > logger,
154 > )
155 > taskChannelKeyFn := func(e TrackableExecutableTask) ClusterChannelKey {
156 return ClusterChannelKey{
157 ClusterName: e.SourceClusterName(),
158 }
159 }
160 > channelWeightFn := func(key ClusterChannelKey) int { fx.go
161 return 1
162 }
163 // This creates a per cluster channel.
164 // They share the same weight so it just does a round-robin on all clusters' tasks.
165 > rrScheduler := ctasks.NewInterleavedWeightedRoundRobinScheduler( fx.go
166 > ctasks.InterleavedWeightedRoundRobinSchedulerOptions[TrackableExecutableTask, ClusterChannelKey]{
167 > TaskChannelKeyFn: taskChannelKeyFn,
168 > ChannelWeightFn: channelWeightFn,
169 > },
170 > scheduler,
171 > logger,
172 > )
173 > lc.Append(fx.StartStopHook(rrScheduler.Start, rrScheduler.Stop))
174 > return rrScheduler
175 }
176
183 metricsHandler metrics.Handler,
184 lc fx.Lifecycle,
185 > ) ctasks.Scheduler[TrackableExecutableTask] { fx.go
186 > // P-way parallelism for executions of the same workflow (per ReplicationLowPriorityTaskParallelism)
187 > // is modeled as P distinct per-namespace-workflow queue IDs. We bucket by execution (RunID) so all
188 > // low-priority tasks for one execution share a queue; the third field stores the slot index, not
189 > // the run UUID.
190 > queueFactory := func(task TrackableExecutableTask) ctasks.SequentialTaskQueue[TrackableExecutableTask] {
191 item := task.QueueID()
192 workflowKey, ok := item.(definition.WorkflowKey)
204 // SequentialScheduler has panic wrapper when executing task,
205 // if changing the executor, please make sure other executor has panic wrapper
206 > scheduler := ctasks.NewSequentialScheduler[TrackableExecutableTask]( fx.go
207 > &ctasks.SequentialSchedulerOptions{
208 > QueueSize: config.ReplicationProcessorSchedulerQueueSize(),
209 > WorkerCount: config.ReplicationLowPriorityProcessorSchedulerWorkerCount,
210 > },
211 > WorkflowKeyHashFn,
212 > queueFactory,
213 > logger,
214 > )
215 > taskChannelKeyFn := func(e TrackableExecutableTask) ClusterChannelKey {
216 return ClusterChannelKey{
217 ClusterName: e.SourceClusterName(),
218 }
219 }
220 > channelWeightFn := func(key ClusterChannelKey) int { fx.go
221 return 1
222 }
223 > taskQuotaRequestFn := func(t TrackableExecutableTask) quotas.Request { fx.go
224 var taskType string
225 var nsName namespace.Name
245 "")
246 }
247 > taskMetricsTagsFn := func(t TrackableExecutableTask) []metrics.Tag { fx.go
248 replicationTask := t.ReplicationTask()
249 var taskType string
268 // This creates a per cluster channel.
269 // They share the same weight so it just does a round-robin on all clusters' tasks.
270 > rrScheduler := ctasks.NewInterleavedWeightedRoundRobinScheduler( fx.go
271 > ctasks.InterleavedWeightedRoundRobinSchedulerOptions[TrackableExecutableTask, ClusterChannelKey]{
272 > TaskChannelKeyFn: taskChannelKeyFn,
273 > ChannelWeightFn: channelWeightFn,
274 > },
275 > scheduler,
276 > logger,
277 > )
278 > ts := ctasks.NewRateLimitedScheduler[TrackableExecutableTask](
279 > rrScheduler,
280 > rateLimiter,
281 > timeSource,
282 > taskQuotaRequestFn,
283 > taskMetricsTagsFn,
284 > ctasks.RateLimitedSchedulerOptions{
285 > Enabled: config.ReplicationEnableRateLimit,
286 > EnableShadowMode: config.ReplicationEnableRateLimitShadowMode,
287 > },
288 > logger,
289 > metricsHandler,
290 > )
291 > lc.Append(fx.StartStopHook(ts.Start, ts.Stop))
292 > return ts
293 }
294
297 metricsHandler metrics.Handler,
298 config *configs.Config,
299 > ) ctasks.SequentialTaskQueueFactory[TrackableExecutableTask] { fx.go
300 > return func(task TrackableExecutableTask) ctasks.SequentialTaskQueue[TrackableExecutableTask] {
301 if config.EnableReplicationTaskBatching() {
302 return NewSequentialBatchableTaskQueue(task, nil, logger, metricsHandler)
315 func executableTaskConverterProvider(
316 processToolBox ProcessToolBox,
317 > ) ExecutableTaskConverter { fx.go
318 > return NewExecutableTaskConverter(processToolBox)
319 > }
320
321 func streamReceiverMonitorProvider(
322 processToolBox ProcessToolBox,
323 taskConverter ExecutableTaskConverter,
324 > ) StreamReceiverMonitor { fx.go
325 > return NewStreamReceiverMonitor(
326 > processToolBox,
327 > taskConverter,
328 > processToolBox.Config.EnableReplicationStream(),
329 > )
330 > }
331
332 func resendHandlerProvider(
340 logger log.Logger,
341 importer eventhandler.EventImporter,
342 > ) eventhandler.ResendHandler { fx.go
343 > return eventhandler.NewResendHandler(
344 > namespaceRegistry,
345 > clientBean,
346 > serializer,
347 > clusterMetadata,
348 > func(ctx context.Context, namespaceId namespace.ID, workflowId string) (historyi.Engine, error) {
349 shardContext, err := shardController.GetShardByNamespaceWorkflow(
350 namespaceId,
368 serializer serialization.Serializer,
369 logger log.Logger,
370 > ) eventhandler.EventImporter { fx.go
371 > return eventhandler.NewEventImporter(
372 > historyFetcher,
373 > func(ctx context.Context, namespaceId namespace.ID, workflowId string) (historyi.Engine, error) {
374 shardContext, err := shardController.GetShardByNamespaceWorkflow(
375 namespaceId,
390 replicationTaskSerializer TaskSerializer,
391 clusterMetadata cluster.Metadata,
392 > ) *DLQWriterAdapter { fx.go
393 > return NewDLQWriterAdapter(dlqWriter, replicationTaskSerializer, clusterMetadata.GetCurrentClusterName())
394 > }
395
396 func historyEventsHandlerProvider(
399 shardController shard.Controller,
400 logger log.Logger,
401 > ) eventhandler.HistoryEventsHandler { fx.go
402 > return eventhandler.NewHistoryEventsHandler(
403 > clusterMetadata,
404 > importer,
405 > shardController,
406 > logger,
407 > )
408 > }
409
410 func historyPaginatedFetcherProvider(
413 serializer serialization.Serializer,
414 logger log.Logger,
415 > ) eventhandler.HistoryPaginatedFetcher { fx.go
416 > return eventhandler.NewHistoryPaginatedFetcher(
417 > namespaceRegistry,
418 > clientBean,
419 > serializer,
420 > logger,
421 > )
422 > }
go.temporal.io/server/common/persistence/client/factory.go 140 covered LOC · 43 ranges

Open complete file

86 enableDataLossMetrics EnableDataLossMetrics,
87 enableBestEffortDeleteTasksOnWorkflowUpdate EnableBestEffortDeleteTasksOnWorkflowUpdate,
88 > ) Factory { factory.go
89 > factory := &factoryImpl{
90 > dataStoreFactory: dataStoreFactory,
91 > config: cfg,
92 > serializer: serializer,
93 > eventBlobCache: eventBlobCache,
94 > metricsHandler: metricsHandler,
95 > logger: logger,
96 > clusterName: clusterName,
97 > systemRateLimiter: systemRateLimiter,
98 > namespaceRateLimiter: namespaceRateLimiter,
99 > shardRateLimiter: shardRateLimiter,
100 > healthSignals: healthSignals,
101 > enableDataLossMetrics: dynamicconfig.BoolPropertyFn(enableDataLossMetrics),
102 > enableBestEffortDeleteTasksOnWorkflowUpdate: dynamicconfig.BoolPropertyFn(enableBestEffortDeleteTasksOnWorkflowUpdate),
103 > }
104 > factory.initDependencies()
105 > return factory
106 > }
107
108 // NewTaskManager returns a new task manager
109 > func (f *factoryImpl) NewTaskManager() (persistence.TaskManager, error) { factory.go
110 > taskStore, err := f.dataStoreFactory.NewTaskStore()
111 > if err != nil {
112 return nil, err
113 }
114 > result := persistence.NewTaskManager(taskStore, f.serializer) factory.go
115 > if f.systemRateLimiter != nil && f.namespaceRateLimiter != nil {
116 > result = persistence.NewTaskPersistenceRateLimitedClient(result, f.systemRateLimiter, f.namespaceRateLimiter, f.shardRateLimiter, f.logger) factory.go
117 > }
118 > if f.metricsHandler != nil && f.healthSignals != nil { factory.go
119 > result = persistence.NewTaskPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger, f.enableDataLossMetrics)
120 > }
121 > result = persistence.NewTaskPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
122 > return result, nil
123 }
124
125 // NewFairTaskManager returns a new task fairness manager
126 > func (f *factoryImpl) NewFairTaskManager() (persistence.FairTaskManager, error) { factory.go
127 > taskStore, err := f.dataStoreFactory.NewFairTaskStore()
128 > if err != nil {
129 return nil, err
130 }
131 > result := persistence.NewTaskManager(taskStore, f.serializer) factory.go
132 > if f.systemRateLimiter != nil && f.namespaceRateLimiter != nil {
133 > result = persistence.NewTaskPersistenceRateLimitedClient(result, f.systemRateLimiter, f.namespaceRateLimiter, f.shardRateLimiter, f.logger) factory.go
134 > }
135 > if f.metricsHandler != nil && f.healthSignals != nil { factory.go
136 > result = persistence.NewTaskPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger, f.enableDataLossMetrics)
137 > }
138 > result = persistence.NewTaskPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
139 > return result, nil
140 }
141
142 // NewShardManager returns a new shard manager
143 > func (f *factoryImpl) NewShardManager() (persistence.ShardManager, error) { factory.go
144 > shardStore, err := f.dataStoreFactory.NewShardStore()
145 > if err != nil {
146 return nil, err
147 }
148
149 > result := persistence.NewShardManager(shardStore, f.serializer) factory.go
150 > if f.systemRateLimiter != nil && f.namespaceRateLimiter != nil {
151 > result = persistence.NewShardPersistenceRateLimitedClient(result, f.systemRateLimiter, f.namespaceRateLimiter, f.shardRateLimiter, f.logger) factory.go
152 > }
153 > if f.metricsHandler != nil && f.healthSignals != nil { factory.go
154 > result = persistence.NewShardPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger, f.enableDataLossMetrics)
155 > }
156 > result = persistence.NewShardPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
157 > return result, nil
158 }
159
160 // NewMetadataManager returns a new metadata manager
161 > func (f *factoryImpl) NewMetadataManager() (persistence.MetadataManager, error) { factory.go
162 > store, err := f.dataStoreFactory.NewMetadataStore()
163 > if err != nil {
164 return nil, err
165 }
166
167 > result := persistence.NewMetadataManagerImpl(store, f.serializer, f.logger, f.clusterName) factory.go
168 > if f.systemRateLimiter != nil && f.namespaceRateLimiter != nil {
169 > result = persistence.NewMetadataPersistenceRateLimitedClient(result, f.systemRateLimiter, f.namespaceRateLimiter, f.shardRateLimiter, f.logger) factory.go
170 > }
171 > if f.metricsHandler != nil && f.healthSignals != nil { factory.go
172 > result = persistence.NewMetadataPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger, f.enableDataLossMetrics)
173 > }
174 > result = persistence.NewMetadataPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
175 > return result, nil
176 }
177
178 // NewClusterMetadataManager returns a new cluster metadata manager
179 > func (f *factoryImpl) NewClusterMetadataManager() (persistence.ClusterMetadataManager, error) { factory.go
180 > store, err := f.dataStoreFactory.NewClusterMetadataStore()
181 > if err != nil {
182 return nil, err
183 }
184
185 > result := persistence.NewClusterMetadataManagerImpl(store, f.serializer, f.clusterName, f.logger) factory.go
186 > if f.systemRateLimiter != nil && f.namespaceRateLimiter != nil {
187 > result = persistence.NewClusterMetadataPersistenceRateLimitedClient(result, f.systemRateLimiter, f.namespaceRateLimiter, f.shardRateLimiter, f.logger) factory.go
188 > }
189 > if f.metricsHandler != nil && f.healthSignals != nil { factory.go
190 > result = persistence.NewClusterMetadataPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger, f.enableDataLossMetrics)
191 > }
192 > result = persistence.NewClusterMetadataPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
193 > return result, nil
194 }
195
196 // NewExecutionManager returns a new execution manager
197 > func (f *factoryImpl) NewExecutionManager() (persistence.ExecutionManager, error) { factory.go
198 > store, err := f.dataStoreFactory.NewExecutionStore()
199 > if err != nil {
200 return nil, err
201 }
202
203 > result := persistence.NewExecutionManager( factory.go
204 > store,
205 > f.serializer,
206 > f.eventBlobCache,
207 > f.logger,
208 > f.config.TransactionSizeLimit,
209 > f.enableBestEffortDeleteTasksOnWorkflowUpdate,
210 > )
211 > if f.systemRateLimiter != nil && f.namespaceRateLimiter != nil {
212 > result = persistence.NewExecutionPersistenceRateLimitedClient(result, f.systemRateLimiter, f.namespaceRateLimiter, f.shardRateLimiter, f.logger) factory.go
213 > }
214 > if f.metricsHandler != nil && f.healthSignals != nil { factory.go
215 > result = persistence.NewExecutionPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger, f.enableDataLossMetrics)
216 > }
217 > result = persistence.NewExecutionPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
218 > return result, nil
219 }
220
221 > func (f *factoryImpl) NewNamespaceReplicationQueue() (persistence.NamespaceReplicationQueue, error) { factory.go
222 > result, err := f.dataStoreFactory.NewQueue(persistence.NamespaceReplicationQueueType)
223 > if err != nil {
224 return nil, err
225 }
226
227 > if f.systemRateLimiter != nil && f.namespaceRateLimiter != nil { factory.go
228 > result = persistence.NewQueuePersistenceRateLimitedClient(result, f.systemRateLimiter, f.namespaceRateLimiter, f.shardRateLimiter, f.logger) factory.go
229 > }
230 > if f.metricsHandler != nil && f.healthSignals != nil { factory.go
231 > result = persistence.NewQueuePersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger, f.enableDataLossMetrics)
232 > }
233 > result = persistence.NewQueuePersistenceRetryableClient(result, namespaceQueueRetryPolicy, IsNamespaceQueueTransientError)
234 > return persistence.NewNamespaceReplicationQueue(result, f.serializer, f.clusterName, f.metricsHandler, f.logger)
235 }
236
237 > func (f *factoryImpl) NewHistoryTaskQueueManager() (persistence.HistoryTaskQueueManager, error) { factory.go
238 > q, err := f.dataStoreFactory.NewQueueV2()
239 > if err != nil {
240 return nil, err
241 }
242 > return persistence.NewHistoryTaskQueueManager(q, f.serializer), nil factory.go
243 }
244
245 > func (f *factoryImpl) NewNexusEndpointManager() (persistence.NexusEndpointManager, error) { factory.go
246 > store, err := f.dataStoreFactory.NewNexusEndpointStore()
247 > if err != nil {
248 return nil, err
249 }
250
251 > result := persistence.NewNexusEndpointManager(store, f.serializer, f.logger) factory.go
252 > if f.systemRateLimiter != nil && f.namespaceRateLimiter != nil {
253 > result = persistence.NewNexusEndpointPersistenceRateLimitedClient(result, f.systemRateLimiter, f.namespaceRateLimiter, f.shardRateLimiter, f.logger) factory.go
254 > }
255 > if f.metricsHandler != nil && f.healthSignals != nil { factory.go
256 > result = persistence.NewNexusEndpointPersistenceMetricsClient(result, f.metricsHandler, f.healthSignals, f.logger, f.enableDataLossMetrics)
257 > }
258 > result = persistence.NewNexusEndpointPersistenceRetryableClient(result, retryPolicy, IsPersistenceTransientError)
259 > return result, nil
260 }
261
262 // Close closes this factory
263 > func (f *factoryImpl) Close() { factory.go
264 > f.dataStoreFactory.Close()
265 > if f.healthSignals != nil {
266 > f.healthSignals.Stop()
267 > }
268 }
269
270 > func IsPersistenceTransientError(err error) bool { factory.go
271 > switch err.(type) {
272 // we retry on DataLoss errors because persistence layer is sometimes unreliable when we immediately read-after-write
273 case *serviceerror.Unavailable, *serviceerror.DataLoss:
275 }
276
277 > return false factory.go
278 }
279
287 }
288
289 > func (f *factoryImpl) initDependencies() { factory.go
290 > if f.metricsHandler == nil && f.healthSignals == nil {
291 return
292 }
293
294 > if f.metricsHandler == nil { factory.go
295 f.metricsHandler = metrics.NoopMetricsHandler
296 }
297 > if f.healthSignals == nil { factory.go
298 > f.healthSignals = persistence.NoopHealthSignalAggregator factory.go
299 > }
300 > f.healthSignals.Start() factory.go
301 }
go.temporal.io/server/service/history/api/getworkflowexecutionhistory/api.go 140 covered LOC · 23 ranges

Open complete file

125 request *historyservice.GetWorkflowExecutionHistoryRequest,
126 persistenceVisibilityMgr manager.VisibilityManager,
127 > ) (_ *historyservice.GetWorkflowExecutionHistoryResponseWithRaw, retError error) { api.go
128 > namespaceID := namespace.ID(request.GetNamespaceId())
129 > namespaceName := namespace.Name(request.GetRequest().GetNamespace())
130 > err := api.ValidateNamespaceUUID(namespaceID)
131 > if err != nil {
132 return nil, err
133 }
134
135 > isCloseEventOnly := request.Request.GetHistoryEventFilterType() == enumspb.HISTORY_EVENT_FILTER_TYPE_CLOSE_EVENT api.go
136 >
137 > queryMutableState := func(
138 > namespaceUUID namespace.ID,
139 > execution *commonpb.WorkflowExecution,
140 > expectedNextEventID int64,
141 > currentBranchToken []byte,
142 > versionHistoryItem *historyspb.VersionHistoryItem,
143 > versionedTransition *persistencespb.VersionedTransition,
144 > ) (
145 > []byte, // current branch token (to use to retrieve history events)
146 > string, // workflow run ID
147 > int64, // last first event ID (the event ID of the last batch of events in the history)
148 > int64, // last first event transaction id
149 > bool, // whether the workflow is running
150 > *historyspb.VersionHistoryItem, // version history item for the current branch
151 > *persistencespb.VersionedTransition, // last versioned transition
152 > *historyspb.TransientWorkflowTaskInfo, // transient workflow task info
153 > error, // error if any
154 > ) {
155 > response, err := api.GetOrPollWorkflowMutableState(
156 > ctx,
157 > shardContext,
158 > &historyservice.GetMutableStateRequest{
159 > NamespaceId: namespaceUUID.String(),
160 > Execution: execution,
161 > ExpectedNextEventId: expectedNextEventID,
162 > CurrentBranchToken: currentBranchToken,
163 > VersionHistoryItem: versionHistoryItem,
164 > VersionedTransition: versionedTransition,
165 > },
166 > workflowConsistencyChecker,
167 > eventNotifier,
168 > )
169 >
170 > var branchErr *serviceerrors.CurrentBranchChanged
171 > if errors.As(err, &branchErr) && isCloseEventOnly {
172 shardContext.GetLogger().Info("Got CurrentBranchChanged, retry with empty branch token",
173 tag.WorkflowNamespaceID(namespaceUUID.String()),
192 )
193 }
194 > if err != nil { api.go
195 return nil, "", 0, 0, false, nil, nil, nil, err
196 }
197
198 > isWorkflowRunning := response.GetWorkflowStatus() == enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING api.go
199 > currentVersionHistory, err := versionhistory.GetCurrentVersionHistory(response.GetVersionHistories())
200 > if err != nil {
201 return nil, "", 0, 0, false, nil, nil, nil, err
202 }
203 > lastVersionHistoryItem, err := versionhistory.GetLastVersionHistoryItem(currentVersionHistory) api.go
204 > if err != nil {
205 return nil, "", 0, 0, false, nil, nil, nil, err
206 }
207
208 > lastVersionedTransition := transitionhistory.LastVersionedTransition(response.GetTransitionHistory()) api.go
209 > return response.CurrentBranchToken,
210 > response.Execution.GetRunId(),
211 > response.GetLastFirstEventId(),
212 > response.GetNextEventId(),
213 > isWorkflowRunning,
214 > lastVersionHistoryItem,
215 > lastVersionedTransition,
216 > response.GetTransientOrSpeculativeTasks(),
217 > nil
218 }
219
220 > isLongPoll := request.Request.GetWaitNewEvent() api.go
221 > execution := request.Request.Execution
222 > var continuationToken *tokenspb.HistoryContinuation
223 >
224 > var runID string
225 > lastFirstEventID := common.FirstEventID
226 > var nextEventID int64
227 > var isWorkflowRunning bool
228 > var cachedTransientTasks *historyspb.TransientWorkflowTaskInfo
229 >
230 > // process the token for paging
231 > queryNextEventID := common.EndEventID
232 > if request.Request.NextPageToken != nil {
233 continuationToken, err = api.DeserializeHistoryToken(request.Request.NextPageToken)
234 if err != nil {
258 continuationToken.IsWorkflowRunning = isWorkflowRunning
259 }
260 > } else { api.go
261 > continuationToken = &tokenspb.HistoryContinuation{}
262 > if !isCloseEventOnly {
263 queryNextEventID = common.FirstEventID
264 }
265 > continuationToken.BranchToken, runID, lastFirstEventID, nextEventID, isWorkflowRunning, continuationToken.VersionHistoryItem, continuationToken.VersionedTransition, cachedTransientTasks, err = api.go
266 > queryMutableState(namespaceID, execution, queryNextEventID, nil, nil, nil)
267 > if err != nil {
268 return nil, err
269 }
270
271 > execution.RunId = runID api.go
272 >
273 > continuationToken.RunId = runID
274 > continuationToken.FirstEventId = common.FirstEventID
275 > continuationToken.NextEventId = nextEventID
276 > continuationToken.IsWorkflowRunning = isWorkflowRunning
277 > continuationToken.PersistenceToken = nil
278 }
279
281 // when data inconsistency occurs. Long term solution should check event
282 // batch pointing backwards within history store.
283 > defer func() { api.go
284 > var dataLossErr *serviceerror.DataLoss
285 > if errors.As(retError, &dataLossErr) {
286 api.TrimHistoryNode(
287 ctx,
296 }()
297
298 > history := &historypb.History{} api.go
299 > history.Events = []*historypb.HistoryEvent{}
300 > var historyBlob []*commonpb.DataBlob
301 > config := shardContext.GetConfig()
302 > sendRawHistoryBetweenInternalServices := config.SendRawHistoryBetweenInternalServices()
303 > sendRawWorkflowHistoryForNamespace := config.SendRawWorkflowHistory(request.Request.GetNamespace())
304 > // fetchGapEvents fetches events in [fromEventID, toEventID) from persistence and appends
305 > // them to the current response (history or historyBlob). Used to close gaps that form
306 > // when events are committed to DB between paginated GetWorkflowExecutionHistory calls.
307 > fetchGapEvents := func(fromEventID, toEventID int64, branchToken []byte) error {
308 if sendRawWorkflowHistoryForNamespace || sendRawHistoryBetweenInternalServices {
309 gapBlob, _, err := api.GetRawHistory(ctx, shardContext, namespaceName, namespaceID, execution,
325 return nil
326 }
327 > if isCloseEventOnly { api.go
328 > if !isWorkflowRunning { api.go
329 > if sendRawWorkflowHistoryForNamespace || sendRawHistoryBetweenInternalServices {
330 historyBlob, _, err = api.GetRawHistory(
331 ctx,
346 // since getHistory func will not return empty history, so the below is safe
347 historyBlob = historyBlob[len(historyBlob)-1:]
348 > } else { api.go
349 > history, _, err = api.GetHistory(
350 > ctx,
351 > shardContext,
352 > namespaceName,
353 > namespaceID,
354 > execution,
355 > lastFirstEventID,
356 > nextEventID,
357 > request.Request.GetMaximumPageSize(),
358 > nil,
359 > nil,
360 > continuationToken.BranchToken,
361 > persistenceVisibilityMgr,
362 > )
363 > if err != nil {
364 return nil, err
365 }
366 // GetHistory func will not return empty history. Log workflow details if that is not the case
367 > if len(history.Events) == 0 { api.go
368 dataLossErr := softassert.UnexpectedDataLoss(
369 shardContext.GetLogger(),
388 return nil, dataLossErr
389 }
390 > history.Events = history.Events[len(history.Events)-1 : len(history.Events)] api.go
391 }
392 > continuationToken = nil api.go
393 } else if isLongPoll {
394 // set the persistence token to be nil so next time we will query history for updates
493 }
494
495 > nextToken, err := api.SerializeHistoryToken(continuationToken) api.go
496 > if err != nil {
497 return nil, err
498 }
499
500 // if SendRawHistoryBetweenInternalServices is enabled, we do this check in frontend service
501 > if len(history.Events) > 0 { api.go
502 > err = api.FixFollowEvents(ctx, versionChecker, isCloseEventOnly, history) api.go
503 > if err != nil {
504 return nil, err
505 }
506 }
507
508 > var rawHistory [][]byte api.go
509 > // if sendRawHistoryBetweenInternalServices is true and SendRawWorkflowHistory is not enabled for this namespace,
510 > // send history in raw format in History field of historyservice.GetWorkflowExecutionHistoryResponseWithRaw.
511 > // If SendRawWorkflowHistory is enabled for this namespace, raw history will be appended to RawHistory field in
512 > // workflowservice.GetWorkflowExecutionHistoryResponse.
513 > if sendRawHistoryBetweenInternalServices && !sendRawWorkflowHistoryForNamespace {
514 rawHistory = make([][]byte, 0, len(historyBlob))
515 for _, blob := range historyBlob {
518 historyBlob = nil
519 }
520 > return &historyservice.GetWorkflowExecutionHistoryResponseWithRaw{ api.go
521 > Response: &workflowservice.GetWorkflowExecutionHistoryResponse{
522 > History: history,
523 > RawHistory: historyBlob,
524 > NextPageToken: nextToken,
525 > Archived: false,
526 > },
527 >
528 > History: rawHistory,
529 > }, nil
530 }
go.temporal.io/server/common/rpc/rpc.go 138 covered LOC · 35 ranges

Open complete file

79 monitor membership.Monitor,
80 tokenProvider auth.TokenProvider,
81 > ) *RPCFactory { rpc.go
82 > authHeaderName := "authorization"
83 > requireRemoteClusterAuth := false
84 > if cfg != nil {
85 > authHeaderName = cmp.Or(cfg.Global.Authorization.AuthHeaderName, authHeaderName) rpc.go
86 > requireRemoteClusterAuth = cfg.Global.Authorization.RemoteClusterAuth.Require
87 > }
88 > f := &RPCFactory{ rpc.go
89 > config: cfg,
90 > serviceName: sName,
91 > logger: logger,
92 > metricsHandler: metricsHandler,
93 > frontendURL: frontendURL,
94 > frontendHTTPURL: frontendHTTPURL,
95 > frontendHTTPPort: frontendHTTPPort,
96 > frontendTLSConfig: frontendTLSConfig,
97 > tlsFactory: tlsProvider,
98 > commonDialOptions: commonDialOptions,
99 > perServiceDialOptions: perServiceDialOptions,
100 > tokenProvider: tokenProvider,
101 > authHeaderName: authHeaderName,
102 > requireRemoteClusterAuth: requireRemoteClusterAuth,
103 > monitor: monitor,
104 > }
105 > f.grpcListener = sync.OnceValue(f.createGRPCListener)
106 > f.localFrontendClient = sync.OnceValues(f.createLocalFrontendHTTPClient)
107 > return f
108 }
109
110 > func (d *RPCFactory) GetFrontendGRPCServerOptions() ([]grpc.ServerOption, error) { rpc.go
111 > var opts []grpc.ServerOption
112 >
113 > if d.tlsFactory != nil {
114 > serverConfig, err := d.tlsFactory.GetFrontendServerConfig() rpc.go
115 > if err != nil {
116 return nil, err
117 }
118 > if serverConfig == nil { rpc.go
119 > return opts, nil
120 > }
121 opts = append(opts, grpc.Creds(credentials.NewTLS(serverConfig)))
122 }
141 }
142
143 > func (d *RPCFactory) GetInternodeGRPCServerOptions() ([]grpc.ServerOption, error) { rpc.go
144 > var opts []grpc.ServerOption
145 >
146 > if d.EnableInternodeServerKeepalive {
147 rpcConfig := d.config.Services[string(d.serviceName)].RPC
148 kep := rpcConfig.KeepAliveServerConfig.GetKeepAliveEnforcementPolicy()
150 opts = append(opts, grpc.KeepaliveEnforcementPolicy(kep), grpc.KeepaliveParams(kp))
151 }
152 > if d.tlsFactory != nil { rpc.go
153 > serverConfig, err := d.tlsFactory.GetInternodeServerConfig() rpc.go
154 > if err != nil {
155 return nil, err
156 }
157 > if serverConfig == nil { rpc.go
158 > return opts, nil
159 > }
160 opts = append(opts, grpc.Creds(credentials.NewTLS(serverConfig)))
161 }
173
174 // GetGRPCListener returns cached dispatcher for gRPC inbound or creates one
175 > func (d *RPCFactory) GetGRPCListener() net.Listener { rpc.go
176 > return d.grpcListener()
177 > }
178
179 > func (d *RPCFactory) createGRPCListener() net.Listener { rpc.go
180 > rpcConfig := d.config.Services[string(d.serviceName)].RPC
181 > hostAddress := net.JoinHostPort(getListenIP(&rpcConfig, d.logger).String(), convert.IntToString(rpcConfig.GRPCPort))
182 >
183 > grpcListener, err := net.Listen("tcp", hostAddress)
184 > if err != nil || grpcListener == nil || grpcListener.Addr() == nil {
185 d.logger.Fatal("Failed to start gRPC listener", tag.Error(err), tag.Service(d.serviceName), tag.Address(hostAddress))
186 }
187
188 > d.logger.Info("Created gRPC listener", tag.Service(d.serviceName), tag.Address(hostAddress)) rpc.go
189 > return grpcListener
190 }
191
192 > func getListenIP(cfg *config.RPC, logger log.Logger) net.IP { rpc.go
193 > if cfg.BindOnLocalHost && len(cfg.BindOnIP) > 0 {
194 logger.Fatal("ListenIP failed, bindOnLocalHost and bindOnIP are mutually exclusive")
195 return nil
196 }
197
198 > if cfg.BindOnLocalHost { rpc.go
199 > return net.ParseIP(environment.GetLocalhostIP()) rpc.go
200 > }
201
202 if len(cfg.BindOnIP) > 0 {
261
262 // CreateLocalFrontendGRPCConnection creates connection for internal frontend calls
263 > func (d *RPCFactory) CreateLocalFrontendGRPCConnection() *grpc.ClientConn { rpc.go
264 > additionalDialOptions := append([]grpc.DialOption{}, d.perServiceDialOptions[primitives.InternalFrontendService]...)
265 >
266 > return d.dial(d.frontendURL, d.frontendTLSConfig, additionalDialOptions...)
267 > }
268
269 // createInternodeGRPCConnection creates connection for gRPC calls
270 > func (d *RPCFactory) createInternodeGRPCConnection(hostName string, serviceName primitives.ServiceName) *grpc.ClientConn { rpc.go
271 > var tlsClientConfig *tls.Config
272 > var err error
273 > if d.tlsFactory != nil {
274 > tlsClientConfig, err = d.tlsFactory.GetInternodeClientConfig() rpc.go
275 > if err != nil {
276 d.logger.Fatal("Failed to create tls config for gRPC connection", tag.Error(err))
277 return nil
278 }
279 }
280 > additionalDialOptions := append([]grpc.DialOption{}, d.perServiceDialOptions[serviceName]...) rpc.go
281 > return d.dial(hostName, tlsClientConfig, append(additionalDialOptions, d.getClientKeepAliveConfig(serviceName))...)
282 }
283
284 > func (d *RPCFactory) CreateHistoryGRPCConnection(rpcAddress string) *grpc.ClientConn { rpc.go
285 > return d.createInternodeGRPCConnection(rpcAddress, primitives.HistoryService)
286 > }
287
288 > func (d *RPCFactory) CreateMatchingGRPCConnection(rpcAddress string) *grpc.ClientConn { rpc.go
289 > return d.createInternodeGRPCConnection(rpcAddress, primitives.MatchingService)
290 > }
291
292 > func (d *RPCFactory) dial(hostName string, tlsClientConfig *tls.Config, dialOptions ...grpc.DialOption) *grpc.ClientConn { rpc.go
293 > dialOptions = append(d.commonDialOptions, dialOptions...)
294 > connection, err := Dial(hostName, tlsClientConfig, d.logger, d.metricsHandler, dialOptions...)
295 > if err != nil {
296 d.logger.Fatal("Failed to create gRPC connection", tag.Error(err))
297 return nil
298 }
299
300 > return connection rpc.go
301 }
302
303 > func (d *RPCFactory) getClientKeepAliveConfig(serviceName primitives.ServiceName) grpc.DialOption { rpc.go
304 > // default keepalive settings for clients
305 > params := keepalive.ClientParameters{
306 > Time: time.Duration(math.MaxInt64),
307 > Timeout: 20 * time.Second,
308 > PermitWithoutStream: false,
309 > }
310 > if d.EnableInternodeClientKeepalive {
311 serviceConfig := d.config.Services[string(serviceName)]
312 params = serviceConfig.RPC.ClientConnectionConfig.GetKeepAliveClientParameters()
313 }
314 > return grpc.WithKeepaliveParams(params) rpc.go
315 }
316
320
321 // CreateLocalFrontendHTTPClient gets or creates a cached frontend client.
322 > func (d *RPCFactory) CreateLocalFrontendHTTPClient() (*common.FrontendHTTPClient, error) { rpc.go
323 > return d.localFrontendClient()
324 > }
325
326 // createLocalFrontendHTTPClient creates an HTTP client for communicating with the frontend.
327 // It uses either the provided frontendURL or membership to resolve the frontend address.
328 > func (d *RPCFactory) createLocalFrontendHTTPClient() (*common.FrontendHTTPClient, error) { rpc.go
329 > // dialer and transport field values copied from http.DefaultTransport.
330 > dialer := &net.Dialer{
331 > Timeout: 30 * time.Second,
332 > KeepAlive: 30 * time.Second,
333 > }
334 > transport := &http.Transport{
335 > Proxy: http.ProxyFromEnvironment,
336 > DialContext: dialer.DialContext,
337 > ForceAttemptHTTP2: true,
338 > MaxIdleConns: 100,
339 > IdleConnTimeout: 90 * time.Second,
340 > TLSHandshakeTimeout: 10 * time.Second,
341 > ExpectContinueTimeout: 1 * time.Second,
342 > }
343 > client := http.Client{}
344 >
345 > // Default to http unless TLS is configured.
346 > scheme := "http"
347 > if d.frontendTLSConfig != nil {
348 transport.TLSClientConfig = d.frontendTLSConfig
349 scheme = "https"
350 }
351
352 > var address string rpc.go
353 > if r := serviceResolverFromGRPCURL(d.frontendHTTPURL); r != nil {
354 > client.Transport = &roundTripper{ rpc.go
355 > resolver: r,
356 > underlying: transport,
357 > httpPort: d.frontendHTTPPort,
358 > }
359 > address = "internal" // This will be replaced by the roundTripper
360 > } else { rpc.go
361 // Use the URL as-is and leave the transport unmodified.
362 client.Transport = transport
364 }
365
366 > return &common.FrontendHTTPClient{ rpc.go
367 > Client: client,
368 > Address: address,
369 > Scheme: scheme,
370 > }, nil
371 }
372
401 // serviceResolverFromGRPCURL returns a ServiceResolver if ustr corresponds to a
402 // membership url, otherwise nil.
403 > func serviceResolverFromGRPCURL(ustr string) membership.ServiceResolver { rpc.go
404 > u, err := url.Parse(ustr)
405 > if err != nil {
406 return nil
407 }
408 > res, err := membership.GetServiceResolverFromURL(u) rpc.go
409 > if err != nil {
410 return nil
411 }
412 > return res rpc.go
413 }
go.temporal.io/server/service/history/archival_queue_factory.go 138 covered LOC · 7 ranges

Open complete file

58 func NewArchivalQueueFactory(
59 params ArchivalQueueFactoryParams,
60 > ) QueueFactory { archival_queue_factory.go
61 > return &archivalQueueFactory{
62 > ArchivalQueueFactoryParams: params,
63 > QueueFactoryBase: newQueueFactoryBase(params),
64 > }
65 > }
66
67 // newHostScheduler creates a new task scheduler for tasks on the archival queue.
68 > func newHostScheduler(params ArchivalQueueFactoryParams) queues.Scheduler { archival_queue_factory.go
69 > return queues.NewScheduler(
70 > params.ClusterMetadata.GetCurrentClusterName(),
71 > queues.SchedulerOptions{
72 > WorkerCount: params.Config.ArchivalProcessorSchedulerWorkerCount,
73 > ActiveNamespaceWeights: dynamicconfig.GetMapPropertyFnFilteredByNamespace(ArchivalTaskPriorities),
74 > StandbyNamespaceWeights: dynamicconfig.GetMapPropertyFnFilteredByNamespace(ArchivalTaskPriorities),
75 > InactiveNamespaceDeletionDelay: params.Config.TaskSchedulerInactiveChannelDeletionDelay,
76 > ExecutionAwareSchedulerOptions: ctasks.ExecutionAwareSchedulerOptions{
77 > Enabled: params.Config.TaskSchedulerEnableExecutionQueueScheduler,
78 > MaxQueues: params.Config.TaskSchedulerExecutionQueueSchedulerMaxQueues,
79 > QueueTTL: params.Config.TaskSchedulerExecutionQueueSchedulerQueueTTL,
80 > QueueConcurrency: params.Config.TaskSchedulerExecutionQueueSchedulerQueueConcurrency,
81 > },
82 > },
83 > params.NamespaceRegistry,
84 > params.Logger,
85 > params.MetricsHandler,
86 > params.TimeSource,
87 > )
88 > }
89
90 // newQueueFactoryBase creates a new QueueFactoryBase for the archival queue, which contains common configurations
91 // like the task scheduler, task priority assigner, and rate limiters.
92 > func newQueueFactoryBase(params ArchivalQueueFactoryParams) QueueFactoryBase { archival_queue_factory.go
93 > return QueueFactoryBase{
94 > HostScheduler: newHostScheduler(params),
95 > HostPriorityAssigner: queues.NewPriorityAssigner(
96 > params.NamespaceRegistry,
97 > params.ClusterMetadata.GetCurrentClusterName(),
98 > ),
99 > HostReaderRateLimiter: queues.NewReaderPriorityRateLimiter(
100 > NewHostRateLimiterRateFn(
101 > params.Config.ArchivalProcessorMaxPollHostRPS,
102 > params.Config.PersistenceMaxQPS,
103 > archivalQueuePersistenceMaxRPSRatio,
104 > ),
105 > int64(params.Config.ArchivalQueueMaxReaderCount()),
106 > ),
107 > Tracer: params.TracerProvider.Tracer(telemetry.ComponentQueueArchival),
108 > }
109 > }
110
111 // CreateQueue creates a new archival queue for the given shard.
112 func (f *archivalQueueFactory) CreateQueue(
113 shard historyi.ShardContext,
114 > ) queues.Queue { archival_queue_factory.go
115 > executor := f.newArchivalTaskExecutor(shard, f.WorkflowCache)
116 > if f.ExecutorWrapper != nil {
117 executor = f.ExecutorWrapper.Wrap(executor)
118 }
119 > return f.newScheduledQueue(shard, executor) archival_queue_factory.go
120 }
121
122 // newArchivalTaskExecutor creates a new archival task executor for the given shard.
123 > func (f *archivalQueueFactory) newArchivalTaskExecutor(shard historyi.ShardContext, workflowCache wcache.Cache) queues.Executor { archival_queue_factory.go
124 > return NewArchivalQueueTaskExecutor(
125 > f.Archiver,
126 > shard,
127 > workflowCache,
128 > f.RelocatableAttributesFetcher,
129 > f.MetricsHandler,
130 > log.With(shard.GetLogger(), tag.ComponentArchivalQueue),
131 > )
132 > }
133
134 // newScheduledQueue creates a new scheduled queue for the given shard with archival-specific configurations.
135 > func (f *archivalQueueFactory) newScheduledQueue(shard historyi.ShardContext, executor queues.Executor) queues.Queue { archival_queue_factory.go
136 > logger := log.With(shard.GetLogger(), tag.ComponentArchivalQueue)
137 > metricsHandler := f.MetricsHandler.WithTags(metrics.OperationTag(metrics.OperationArchivalQueueProcessorScope))
138 >
139 > shardScheduler := queues.NewRateLimitedScheduler(
140 > f.HostScheduler,
141 > queues.RateLimitedSchedulerOptions{
142 > Enabled: f.Config.TaskSchedulerEnableRateLimiter,
143 > EnableShadowMode: f.Config.TaskSchedulerEnableRateLimiterShadowMode,
144 > StartupDelay: f.Config.TaskSchedulerRateLimiterStartupDelay,
145 > },
146 > f.ClusterMetadata.GetCurrentClusterName(),
147 > f.NamespaceRegistry,
148 > f.SchedulerRateLimiter,
149 > f.TimeSource,
150 > f.ChasmRegistry,
151 > logger,
152 > metricsHandler,
153 > )
154 >
155 > rescheduler := queues.NewRescheduler(
156 > shardScheduler,
157 > shard.GetTimeSource(),
158 > logger,
159 > metricsHandler,
160 > )
161 >
162 > factory := queues.NewExecutableFactory(
163 > executor,
164 > shardScheduler,
165 > rescheduler,
166 > f.HostPriorityAssigner,
167 > shard.GetTimeSource(),
168 > shard.GetNamespaceRegistry(),
169 > shard.GetClusterMetadata(),
170 > f.ChasmRegistry,
171 > queues.GetTaskTypeTagValue,
172 > logger,
173 > metricsHandler,
174 > f.Tracer,
175 > f.DLQWriter,
176 > f.Config.TaskDLQEnabled,
177 > f.Config.TaskDLQUnexpectedErrorAttempts,
178 > f.Config.TaskDLQInternalErrors,
179 > f.Config.TaskDLQErrorPattern,
180 > )
181 > return queues.NewScheduledQueue(
182 > shard,
183 > tasks.CategoryArchival,
184 > shardScheduler,
185 > rescheduler,
186 > factory,
187 > &queues.Options{
188 > ReaderOptions: queues.ReaderOptions{
189 > BatchSize: f.Config.ArchivalTaskBatchSize,
190 > MaxPendingTasksCount: f.Config.QueuePendingTaskMaxCount,
191 > PollBackoffInterval: f.Config.ArchivalProcessorPollBackoffInterval,
192 > MaxPredicateSize: f.Config.QueueMaxPredicateSize,
193 > },
194 > MonitorOptions: queues.MonitorOptions{
195 > PendingTasksCriticalCount: f.Config.QueuePendingTaskCriticalCount,
196 > ReaderStuckCriticalAttempts: f.Config.QueueReaderStuckCriticalAttempts,
197 > SliceCountCriticalThreshold: f.Config.QueueCriticalSlicesCount,
198 > },
199 > MaxPollRPS: f.Config.ArchivalProcessorMaxPollRPS,
200 > MaxPollInterval: f.Config.ArchivalProcessorMaxPollInterval,
201 > MaxPollIntervalJitterCoefficient: f.Config.ArchivalProcessorMaxPollIntervalJitterCoefficient,
202 > CheckpointInterval: f.Config.ArchivalProcessorUpdateAckInterval,
203 > CheckpointIntervalJitterCoefficient: f.Config.ArchivalProcessorUpdateAckIntervalJitterCoefficient,
204 > MaxReaderCount: f.Config.ArchivalQueueMaxReaderCount,
205 > MoveGroupTaskCountBase: f.Config.QueueMoveGroupTaskCountBase,
206 > MoveGroupTaskCountMultiplier: f.Config.QueueMoveGroupTaskCountMultiplier,
207 > ShrinkPredicateMaxPendingKeys: f.Config.QueueShrinkPredicateMaxPendingKeys,
208 > },
209 > f.HostReaderRateLimiter,
210 > logger,
211 > metricsHandler,
212 > )
213 > }
go.temporal.io/server/service/history/queues/queue_scheduled.go 138 covered LOC · 30 ranges

Open complete file

51 logger log.Logger,
52 metricsHandler metrics.Handler,
53 > ) *scheduledQueue { queue_scheduled.go
54 > paginationFnProvider := func(r Range) collection.PaginationFn[tasks.Task] {
55 > return func(paginationToken []byte) ([]tasks.Task, []byte, error) { queue_scheduled.go
56 > ctx, cancel := newQueueIOContext()
57 > defer cancel()
58 >
59 > request := &persistence.GetHistoryTasksRequest{
60 > ShardID: shard.GetShardID(),
61 > TaskCategory: category,
62 > InclusiveMinTaskKey: tasks.NewKey(r.InclusiveMin.FireTime, 0),
63 > ExclusiveMaxTaskKey: tasks.NewKey(
64 > r.ExclusiveMax.FireTime.Add(common.ScheduledTaskMinPrecision),
65 > 0,
66 > ),
67 > BatchSize: options.BatchSize(),
68 > NextPageToken: paginationToken,
69 > }
70 >
71 > resp, err := shard.GetHistoryTasks(ctx, request)
72 > if err != nil {
73 > return nil, nil, err queue_scheduled.go
74 > }
75
76 > for len(resp.Tasks) > 0 && !r.ContainsKey(resp.Tasks[0].GetKey()) { queue_scheduled.go
77 resp.Tasks = resp.Tasks[1:]
78 }
79
80 > for len(resp.Tasks) > 0 && !r.ContainsKey(resp.Tasks[len(resp.Tasks)-1].GetKey()) { queue_scheduled.go
81 resp.Tasks = resp.Tasks[:len(resp.Tasks)-1]
82 resp.NextPageToken = nil
83 }
84
85 > return resp.Tasks, resp.NextPageToken, nil queue_scheduled.go
86 }
87 }
88
89 > lookAheadCh := make(chan struct{}, 1) queue_scheduled.go
90 > readerCompletionFn := func(readerID int64) {
91 > if readerID != DefaultReaderId { queue_scheduled.go
92 return
93 }
94
95 > select { queue_scheduled.go
96 > case lookAheadCh <- struct{}{}:
97 default:
98 }
99 }
100
101 > return &scheduledQueue{ queue_scheduled.go
102 > queueBase: newQueueBase(
103 > shard,
104 > category,
105 > paginationFnProvider,
106 > scheduler,
107 > rescheduler,
108 > executableFactory,
109 > options,
110 > hostRateLimiter,
111 > readerCompletionFn,
112 > GrouperNamespaceID{},
113 > logger,
114 > metricsHandler,
115 > ),
116 >
117 > timerGate: timer.NewLocalGate(shard.GetTimeSource()),
118 > newTimerCh: make(chan struct{}, 1),
119 >
120 > lookAheadCh: lookAheadCh,
121 > lookAheadRateLimitRequest: newReaderRequest(DefaultReaderId),
122 > }
123 }
124
125 > func (p *scheduledQueue) Start() { queue_scheduled.go
126 > if !atomic.CompareAndSwapInt32(&p.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
127 return
128 }
129
130 > p.logger.Info("", tag.LifeCycleStarting) queue_scheduled.go
131 > defer p.logger.Info("", tag.LifeCycleStarted)
132 >
133 > p.queueBase.Start()
134 >
135 > p.shutdownWG.Add(1)
136 > go p.processEventLoop()
137 >
138 > p.notify(time.Time{})
139 }
140
141 > func (p *scheduledQueue) Stop() { queue_scheduled.go
142 > if !atomic.CompareAndSwapInt32(&p.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
143 return
144 }
145
146 > p.logger.Info("", tag.LifeCycleStopping) queue_scheduled.go
147 > defer p.logger.Info("", tag.LifeCycleStopped)
148 >
149 > close(p.shutdownCh)
150 > p.timerGate.Close()
151 >
152 > if success := common.AwaitWaitGroup(&p.shutdownWG, time.Minute); !success {
153 p.logger.Warn("", tag.LifeCycleStopTimedout)
154 }
155
156 > p.queueBase.Stop() queue_scheduled.go
157 }
158
159 > func (p *scheduledQueue) NotifyNewTasks(tasks []tasks.Task) { queue_scheduled.go
160 > if len(tasks) == 0 {
161 return
162 }
163
164 > newTime := tasks[0].GetVisibilityTime() queue_scheduled.go
165 > for _, task := range tasks {
166 > ts := task.GetVisibilityTime()
167 > if ts.Before(newTime) {
168 newTime = ts
169 }
170 }
171
172 > p.notify(newTime) queue_scheduled.go
173 }
174
175 > func (p *scheduledQueue) processEventLoop() { queue_scheduled.go
176 > defer p.shutdownWG.Done()
177 >
178 > for {
179 > select {
180 case <-p.shutdownCh:
181 return
182 > default: queue_scheduled.go
183 }
184
185 > select { queue_scheduled.go
186 > case <-p.shutdownCh: queue_scheduled.go
187 > return
188 > case <-p.newTimerCh: queue_scheduled.go
189 > metrics.NewTimerNotifyCounter.With(p.metricsHandler).Record(1)
190 > p.processNewTime()
191 > case <-p.lookAheadCh:
192 > p.lookAheadTask()
193 > case <-p.timerGate.FireCh():
194 > p.processNewRange()
195 case <-p.checkpointTimer.C:
196 p.checkpoint()
201 }
202
203 > func (p *scheduledQueue) notify(newTime time.Time) { queue_scheduled.go
204 > p.newTimeLock.Lock()
205 > defer p.newTimeLock.Unlock()
206 >
207 > if !p.newTime.IsZero() && !newTime.Before(p.newTime) {
208 return
209 }
210
211 > p.newTime = newTime queue_scheduled.go
212 > select {
213 > case p.newTimerCh <- struct{}{}:
214 default:
215 }
216 }
217
218 > func (p *scheduledQueue) processNewTime() { queue_scheduled.go
219 > p.newTimeLock.Lock()
220 > newTime := p.newTime
221 > p.newTime = time.Time{}
222 > p.newTimeLock.Unlock()
223 >
224 > p.timerGate.Update(newTime)
225 > }
226
227 > func (p *scheduledQueue) lookAheadTask() { queue_scheduled.go
228 > rateLimitCtx, rateLimitCancel := context.WithTimeout(context.Background(), lookAheadRateLimitDelay)
229 > rateLimitErr := p.readerRateLimiter.Wait(rateLimitCtx, p.lookAheadRateLimitRequest)
230 > rateLimitCancel()
231 > if rateLimitErr != nil {
232 deadline, _ := rateLimitCtx.Deadline()
233 p.timerGate.Update(deadline)
235 }
236
237 > lookAheadMinTime := p.nonReadableScope.Range.InclusiveMin.FireTime queue_scheduled.go
238 > lookAheadMaxTime := lookAheadMinTime.Add(backoff.Jitter(
239 > p.options.MaxPollInterval(),
240 > p.options.MaxPollIntervalJitterCoefficient(),
241 > ))
242 >
243 > ctx, cancel := newQueueIOContext()
244 > defer cancel()
245 >
246 > request := &persistence.GetHistoryTasksRequest{
247 > ShardID: p.shard.GetShardID(),
248 > TaskCategory: p.category,
249 > InclusiveMinTaskKey: tasks.NewKey(lookAheadMinTime, 0),
250 > ExclusiveMaxTaskKey: tasks.NewKey(lookAheadMaxTime, 0),
251 > BatchSize: 1,
252 > NextPageToken: nil,
253 > }
254 > response, err := p.shard.GetHistoryTasks(ctx, request)
255 > if err != nil {
256 p.logger.Error("Failed to load look ahead task", tag.Error(err))
257 if common.IsResourceExhausted(err) {
266 }
267
268 > if len(response.Tasks) == 1 { queue_scheduled.go
269 p.timerGate.Update(response.Tasks[0].GetKey().FireTime)
270 return
275 // NOTE: with this we don't need a separate max poll timer, loading will be triggerred
276 // every maxPollInterval + jitter.
277 > p.timerGate.Update(lookAheadMaxTime) queue_scheduled.go
278 }
279
go.temporal.io/server/common/persistence/serialization/serializer.go 137 covered LOC · 56 ranges

Open complete file

139 )
140
141 > func NewSerializer() Serializer { serializer.go
142 > return &serializerImpl{encodingType: encodingTypeFromEnv()}
143 > }
144
145 func (t *serializerImpl) EncodingType() enumspb.EncodingType {
149 func (t *serializerImpl) SerializeTask(
150 task tasks.Task,
151 > ) (*commonpb.DataBlob, error) { serializer.go
152 > category := task.GetCategory()
153 > switch category.ID() {
154 > case tasks.CategoryIDTransfer: serializer.go
155 > return serializeTransferTask(t, task)
156 > case tasks.CategoryIDTimer: serializer.go
157 > return serializeTimerTask(t, task)
158 > case tasks.CategoryIDVisibility: serializer.go
159 > return serializeVisibilityTask(t, task)
160 case tasks.CategoryIDReplication:
161 return serializeReplicationTask(t, task)
172 category tasks.Category,
173 blob *commonpb.DataBlob,
174 > ) (tasks.Task, error) { serializer.go
175 > switch category.ID() {
176 > case tasks.CategoryIDTransfer: serializer.go
177 > return deserializeTransferTask(t, blob)
178 case tasks.CategoryIDTimer:
179 return deserializeTimerTask(t, blob)
180 > case tasks.CategoryIDVisibility: serializer.go
181 > return deserializeVisibilityTask(t, blob)
182 case tasks.CategoryIDReplication:
183 return deserializeReplicationTask(t, blob)
191 }
192
193 > func (t *serializerImpl) SerializeEvents(events []*historypb.HistoryEvent) (*commonpb.DataBlob, error) { serializer.go
194 > return t.serialize(&historypb.History{Events: events})
195 > }
196
197 > func (t *serializerImpl) DeserializeEvents(data *commonpb.DataBlob) ([]*historypb.HistoryEvent, error) { serializer.go
198 > if data == nil {
199 return nil, nil
200 }
201 > if len(data.Data) == 0 { serializer.go
202 return nil, nil
203 }
204
205 > events := &historypb.History{} serializer.go
206 > err := Decode(data, events)
207 > if err != nil {
208 return nil, err
209 }
210 > return events.Events, nil serializer.go
211 }
212
265 }
266
267 > func (t *serializerImpl) SerializeClusterMetadata(cm *persistencespb.ClusterMetadata) (*commonpb.DataBlob, error) { serializer.go
268 > if cm == nil {
269 cm = &persistencespb.ClusterMetadata{}
270 }
271 > return t.serialize(cm) serializer.go
272 }
273
274 > func (t *serializerImpl) DeserializeClusterMetadata(data *commonpb.DataBlob) (*persistencespb.ClusterMetadata, error) { serializer.go
275 > if data == nil {
276 return nil, nil
277 }
278 > if len(data.Data) == 0 { serializer.go
279 return nil, nil
280 }
281
282 > cm := &persistencespb.ClusterMetadata{} serializer.go
283 > err := Decode(data, cm)
284 > if err != nil {
285 return nil, err
286 }
287 > return cm, nil serializer.go
288 }
289
290 > func (t *serializerImpl) serialize(p proto.Message) (*commonpb.DataBlob, error) { serializer.go
291 > if p == nil {
292 return nil, nil
293 }
294 > blob, err := encodeBlob(p, t.encodingType) serializer.go
295 > if err != nil {
296 return nil, NewSerializationError(t.encodingType, err)
297 }
298 > return blob, nil serializer.go
299 }
300
372 func (e *DeserializationError) IsTerminalTaskError() bool { return true }
373
374 > func (t *serializerImpl) ShardInfoToBlob(info *persistencespb.ShardInfo) (*commonpb.DataBlob, error) { serializer.go
375 > return encodeBlob(info, t.encodingType)
376 > }
377
378 > func (t *serializerImpl) ShardInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.ShardInfo, error) { serializer.go
379 > shardInfo := &persistencespb.ShardInfo{}
380 > err := Decode(data, shardInfo)
381 >
382 > if err != nil {
383 return nil, err
384 }
385
386 > if shardInfo.GetReplicationDlqAckLevel() == nil { serializer.go
387 > shardInfo.ReplicationDlqAckLevel = make(map[string]int64) serializer.go
388 > }
389
390 > if shardInfo.GetQueueStates() == nil { serializer.go
391 > shardInfo.QueueStates = make(map[int32]*persistencespb.QueueState) serializer.go
392 > }
393 > for _, queueState := range shardInfo.QueueStates { serializer.go
394 if queueState.ReaderStates == nil {
395 queueState.ReaderStates = make(map[int64]*persistencespb.QueueReaderState)
402 }
403
404 > return shardInfo, nil serializer.go
405 }
406
407 > func (t *serializerImpl) NamespaceDetailToBlob(info *persistencespb.NamespaceDetail) (*commonpb.DataBlob, error) { serializer.go
408 > return encodeBlob(info, t.encodingType)
409 > }
410
411 > func (t *serializerImpl) NamespaceDetailFromBlob(data *commonpb.DataBlob) (*persistencespb.NamespaceDetail, error) { serializer.go
412 > result := &persistencespb.NamespaceDetail{}
413 > return result, Decode(data, result)
414 > }
415
416 > func (t *serializerImpl) HistoryTreeInfoToBlob(info *persistencespb.HistoryTreeInfo) (*commonpb.DataBlob, error) { serializer.go
417 > return encodeBlob(info, t.encodingType)
418 > }
419
420 func (t *serializerImpl) HistoryTreeInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.HistoryTreeInfo, error) {
423 }
424
425 > func (t *serializerImpl) HistoryBranchToBlob(info *persistencespb.HistoryBranch) (*commonpb.DataBlob, error) { serializer.go
426 > return encodeBlob(info, t.encodingType)
427 > }
428
429 // NOTE: HistoryBranch does not have an encoding type; so we use the serializer's encoding type.
430 > func (t *serializerImpl) HistoryBranchFromBlob(data []byte) (*persistencespb.HistoryBranch, error) { serializer.go
431 > result := &persistencespb.HistoryBranch{}
432 > return result, Decode(&commonpb.DataBlob{Data: data, EncodingType: t.encodingType}, result)
433 > }
434
435 > func (t *serializerImpl) WorkflowExecutionInfoToBlob(info *persistencespb.WorkflowExecutionInfo) (*commonpb.DataBlob, error) { serializer.go
436 > return encodeBlob(info, t.encodingType)
437 > }
438
439 > func (t *serializerImpl) WorkflowExecutionInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.WorkflowExecutionInfo, error) { serializer.go
440 > result := &persistencespb.WorkflowExecutionInfo{}
441 > err := Decode(data, result)
442 > if err != nil {
443 return nil, err
444 }
445 // Proto serialization replaces empty maps with nils, ensure this map is never nil.
446 > if result.SubStateMachinesByType == nil { serializer.go
447 > result.SubStateMachinesByType = make(map[string]*persistencespb.StateMachineMap) serializer.go
448 > }
449 > return result, nil serializer.go
450 }
451
452 > func (t *serializerImpl) WorkflowExecutionStateToBlob(info *persistencespb.WorkflowExecutionState) (*commonpb.DataBlob, error) { serializer.go
453 > return encodeBlob(info, t.encodingType)
454 > }
455
456 > func (t *serializerImpl) WorkflowExecutionStateFromBlob(data *commonpb.DataBlob) (*persistencespb.WorkflowExecutionState, error) { serializer.go
457 > result := &persistencespb.WorkflowExecutionState{}
458 > if err := Decode(data, result); err != nil {
459 return nil, err
460 }
461 // Initialize the WorkflowExecutionStateDetails for old records.
462 > if result.RequestIds == nil { serializer.go
463 result.RequestIds = make(map[string]*persistencespb.RequestIDInfo, 1)
464 }
465 > if result.CreateRequestId != "" && result.RequestIds[result.CreateRequestId] == nil { serializer.go
466 result.RequestIds[result.CreateRequestId] = &persistencespb.RequestIDInfo{
467 EventType: enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_STARTED,
517 }
518
519 > func (t *serializerImpl) TaskInfoToBlob(info *persistencespb.AllocatedTaskInfo) (*commonpb.DataBlob, error) { serializer.go
520 > return encodeBlob(info, t.encodingType)
521 > }
522
523 > func (t *serializerImpl) TaskInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.AllocatedTaskInfo, error) { serializer.go
524 > result := &persistencespb.AllocatedTaskInfo{}
525 > return result, Decode(data, result)
526 > }
527
528 > func (t *serializerImpl) TaskQueueInfoToBlob(info *persistencespb.TaskQueueInfo) (*commonpb.DataBlob, error) { serializer.go
529 > return encodeBlob(info, t.encodingType)
530 > }
531
532 > func (t *serializerImpl) TaskQueueInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.TaskQueueInfo, error) { serializer.go
533 > result := &persistencespb.TaskQueueInfo{}
534 > return result, Decode(data, result)
535 > }
536
537 func (t *serializerImpl) TaskQueueUserDataToBlob(data *persistencespb.TaskQueueUserData) (*commonpb.DataBlob, error) {
544 }
545
546 > func (t *serializerImpl) ChecksumToBlob(checksum *persistencespb.Checksum) (*commonpb.DataBlob, error) { serializer.go
547 > // nil is replaced with empty object because it is not supported for "checksum" field in DB.
548 > if checksum == nil {
549 > checksum = &persistencespb.Checksum{}
550 > }
551 > return encodeBlob(checksum, t.encodingType)
552 }
553
562 }
563
564 > func (t *serializerImpl) QueueMetadataToBlob(metadata *persistencespb.QueueMetadata) (*commonpb.DataBlob, error) { serializer.go
565 > // TODO change ENCODING_TYPE_JSON to ENCODING_TYPE_PROTO3
566 > return encodeBlob(metadata, enumspb.ENCODING_TYPE_JSON)
567 > }
568
569 func (t *serializerImpl) QueueMetadataFromBlob(data *commonpb.DataBlob) (*persistencespb.QueueMetadata, error) {
615 }
616
617 > func (t *serializerImpl) TransferTaskInfoToBlob(info *persistencespb.TransferTaskInfo) (*commonpb.DataBlob, error) { serializer.go
618 > return encodeBlob(info, t.encodingType)
619 > }
620
621 > func (t *serializerImpl) TransferTaskInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.TransferTaskInfo, error) { serializer.go
622 > result := &persistencespb.TransferTaskInfo{}
623 > return result, Decode(data, result)
624 > }
625
626 > func (t *serializerImpl) TimerTaskInfoToBlob(info *persistencespb.TimerTaskInfo) (*commonpb.DataBlob, error) { serializer.go
627 > return encodeBlob(info, t.encodingType)
628 > }
629
630 func (t *serializerImpl) TimerTaskInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.TimerTaskInfo, error) {
642 }
643
644 > func (t *serializerImpl) VisibilityTaskInfoToBlob(info *persistencespb.VisibilityTaskInfo) (*commonpb.DataBlob, error) { serializer.go
645 > return encodeBlob(info, t.encodingType)
646 > }
647
648 > func (t *serializerImpl) VisibilityTaskInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.VisibilityTaskInfo, error) { serializer.go
649 > result := &persistencespb.VisibilityTaskInfo{}
650 > return result, Decode(data, result)
651 > }
652
653 func (t *serializerImpl) ArchivalTaskInfoToBlob(info *persistencespb.ArchivalTaskInfo) (*commonpb.DataBlob, error) {
go.temporal.io/server/api/adminservice/v1/request_response.pb.go 136 covered LOC · 33 ranges

Open complete file

791 func (*ListHistoryTasksRequest) ProtoMessage() {}
792
793 > func (x *ListHistoryTasksRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
794 > mi := &file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[12]
795 > if x != nil {
796 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
797 if ms.LoadMessageInfo() == nil {
864 func (*ListHistoryTasksResponse) ProtoMessage() {}
865
866 > func (x *ListHistoryTasksResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
867 > mi := &file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[13]
868 > if x != nil {
869 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
870 if ms.LoadMessageInfo() == nil {
1122 func (*GetWorkflowExecutionRawHistoryV2Request) ProtoMessage() {}
1123
1124 > func (x *GetWorkflowExecutionRawHistoryV2Request) ProtoReflect() protoreflect.Message { request_response.pb.go
1125 > mi := &file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[17]
1126 > if x != nil {
1127 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1128 if ms.LoadMessageInfo() == nil {
1218 func (*GetWorkflowExecutionRawHistoryV2Response) ProtoMessage() {}
1219
1220 > func (x *GetWorkflowExecutionRawHistoryV2Response) ProtoReflect() protoreflect.Message { request_response.pb.go
1221 > mi := &file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[18]
1222 > if x != nil {
1223 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1224 if ms.LoadMessageInfo() == nil {
1290 func (*GetWorkflowExecutionRawHistoryRequest) ProtoMessage() {}
1291
1292 > func (x *GetWorkflowExecutionRawHistoryRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
1293 > mi := &file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[19]
1294 > if x != nil {
1295 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1296 if ms.LoadMessageInfo() == nil {
1386 func (*GetWorkflowExecutionRawHistoryResponse) ProtoMessage() {}
1387
1388 > func (x *GetWorkflowExecutionRawHistoryResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
1389 > mi := &file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[20]
1390 > if x != nil {
1391 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1392 if ms.LoadMessageInfo() == nil {
1746 func (*ReapplyEventsRequest) ProtoMessage() {}
1747
1748 > func (x *ReapplyEventsRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
1749 > mi := &file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[27]
1750 > if x != nil {
1751 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1752 if ms.LoadMessageInfo() == nil {
3182 func (*RefreshWorkflowTasksRequest) ProtoMessage() {}
3183
3184 > func (x *RefreshWorkflowTasksRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
3185 > mi := &file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[51]
3186 > if x != nil {
3187 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3188 if ms.LoadMessageInfo() == nil {
3414 }
3415
3416 > func (x *GetTaskQueueTasksRequest) Reset() { request_response.pb.go
3417 > *x = GetTaskQueueTasksRequest{}
3418 > mi := &file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[55]
3419 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3420 > ms.StoreMessageInfo(mi)
3421 > }
3422
3423 func (x *GetTaskQueueTasksRequest) String() string {
3427 func (*GetTaskQueueTasksRequest) ProtoMessage() {}
3428
3429 > func (x *GetTaskQueueTasksRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
3430 > mi := &file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[55]
3431 > if x != nil {
3432 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3433 > if ms.LoadMessageInfo() == nil {
3434 > ms.StoreMessageInfo(mi)
3435 > }
3436 > return ms
3437 }
3438 return mi.MessageOf(x)
3444 }
3445
3446 > func (x *GetTaskQueueTasksRequest) GetNamespace() string { request_response.pb.go
3447 > if x != nil {
3448 > return x.Namespace
3449 > }
3450 return ""
3451 }
3452
3453 > func (x *GetTaskQueueTasksRequest) GetTaskQueue() string { request_response.pb.go
3454 > if x != nil {
3455 > return x.TaskQueue
3456 > }
3457 return ""
3458 }
3459
3460 > func (x *GetTaskQueueTasksRequest) GetTaskQueueType() v16.TaskQueueType { request_response.pb.go
3461 > if x != nil {
3462 > return x.TaskQueueType
3463 > }
3464 return v16.TaskQueueType(0)
3465 }
3466
3467 > func (x *GetTaskQueueTasksRequest) GetMinPass() int64 { request_response.pb.go
3468 > if x != nil {
3469 > return x.MinPass
3470 > }
3471 return 0
3472 }
3473
3474 > func (x *GetTaskQueueTasksRequest) GetMinTaskId() int64 { request_response.pb.go
3475 > if x != nil {
3476 > return x.MinTaskId
3477 > }
3478 return 0
3479 }
3480
3481 > func (x *GetTaskQueueTasksRequest) GetMaxTaskId() int64 { request_response.pb.go
3482 > if x != nil {
3483 > return x.MaxTaskId
3484 > }
3485 return 0
3486 }
3487
3488 > func (x *GetTaskQueueTasksRequest) GetBatchSize() int32 { request_response.pb.go
3489 > if x != nil {
3490 > return x.BatchSize
3491 > }
3492 return 0
3493 }
3500 }
3501
3502 > func (x *GetTaskQueueTasksRequest) GetSubqueue() int32 { request_response.pb.go
3503 > if x != nil {
3504 > return x.Subqueue
3505 > }
3506 return 0
3507 }
3515 }
3516
3517 > func (x *GetTaskQueueTasksResponse) Reset() { request_response.pb.go
3518 > *x = GetTaskQueueTasksResponse{}
3519 > mi := &file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[56]
3520 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3521 > ms.StoreMessageInfo(mi)
3522 > }
3523
3524 func (x *GetTaskQueueTasksResponse) String() string {
3528 func (*GetTaskQueueTasksResponse) ProtoMessage() {}
3529
3530 > func (x *GetTaskQueueTasksResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
3531 > mi := &file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[56]
3532 > if x != nil {
3533 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3534 > if ms.LoadMessageInfo() == nil {
3535 > ms.StoreMessageInfo(mi)
3536 > }
3537 > return ms
3538 }
3539 return mi.MessageOf(x)
3583 func (*DeleteWorkflowExecutionRequest) ProtoMessage() {}
3584
3585 > func (x *DeleteWorkflowExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
3586 > mi := &file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[57]
3587 > if x != nil {
3588 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3589 if ms.LoadMessageInfo() == nil {
3648 func (*DeleteWorkflowExecutionResponse) ProtoMessage() {}
3649
3650 > func (x *DeleteWorkflowExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
3651 > mi := &file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[58]
3652 > if x != nil {
3653 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
3654 if ms.LoadMessageInfo() == nil {
6623 }
6624
6625 > func init() { file_temporal_server_api_adminservice_v1_request_response_proto_init() } request_response.pb.go
6626 > func file_temporal_server_api_adminservice_v1_request_response_proto_init() {
6627 > if File_temporal_server_api_adminservice_v1_request_response_proto != nil {
6628 > return
6629 > }
6630 > file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[59].OneofWrappers = []any{
6631 > (*StreamWorkflowReplicationMessagesRequest_SyncReplicationState)(nil),
6632 > }
6633 > file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[60].OneofWrappers = []any{
6634 > (*StreamWorkflowReplicationMessagesResponse_Messages)(nil),
6635 > }
6636 > file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[61].OneofWrappers = []any{
6637 > (*GetNamespaceRequest_Namespace)(nil),
6638 > (*GetNamespaceRequest_Id)(nil),
6639 > }
6640 > file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes[90].OneofWrappers = []any{
6641 > (*StartAdminBatchOperationRequest_RefreshTasksOperation)(nil),
6642 > }
6643 > type x struct{}
6644 > out := protoimpl.TypeBuilder{
6645 > File: protoimpl.DescBuilder{
6646 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
6647 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_adminservice_v1_request_response_proto_rawDesc), len(file_temporal_server_api_adminservice_v1_request_response_proto_rawDesc)),
6648 > NumEnums: 1,
6649 > NumMessages: 105,
6650 > NumExtensions: 0,
6651 > NumServices: 0,
6652 > },
6653 > GoTypes: file_temporal_server_api_adminservice_v1_request_response_proto_goTypes,
6654 > DependencyIndexes: file_temporal_server_api_adminservice_v1_request_response_proto_depIdxs,
6655 > EnumInfos: file_temporal_server_api_adminservice_v1_request_response_proto_enumTypes,
6656 > MessageInfos: file_temporal_server_api_adminservice_v1_request_response_proto_msgTypes,
6657 > }.Build()
6658 > File_temporal_server_api_adminservice_v1_request_response_proto = out.File
6659 > file_temporal_server_api_adminservice_v1_request_response_proto_goTypes = nil
6660 > file_temporal_server_api_adminservice_v1_request_response_proto_depIdxs = nil
6661 }
go.temporal.io/server/service/history/queues/queue_base.go 134 covered LOC · 19 ranges

Open complete file

116 logger log.Logger,
117 metricsHandler metrics.Handler,
118 > ) *queueBase { queue_base.go
119 > var readerScopes map[int64][]Scope
120 > var exclusiveReaderHighWatermark tasks.Key
121 > if persistenceState, ok := shard.GetQueueState(category); ok {
122 queueState := FromPersistenceQueueState(persistenceState)
123
124 readerScopes = queueState.readerScopes
125 exclusiveReaderHighWatermark = queueState.exclusiveReaderHighWatermark
126 > } else { queue_base.go
127 > ackLevel := tasks.NewKey(tasks.DefaultFireTime, 0) queue_base.go
128 > if category.Type() == tasks.CategoryTypeImmediate {
129 > // convert to exclusive ack level queue_base.go
130 > ackLevel = ackLevel.Next()
131 > }
132
133 > exclusiveReaderHighWatermark = ackLevel queue_base.go
134 }
135
136 > monitor := newMonitor(category.Type(), shard.GetTimeSource(), &options.MonitorOptions) queue_base.go
137 > readerRateLimiter := newShardReaderRateLimiter(
138 > options.MaxPollRPS,
139 > hostReaderRateLimiter,
140 > int64(options.MaxReaderCount()),
141 > )
142 > readerInitializer := func(readerID int64, slices []Slice) Reader {
143 > readerOptions := options.ReaderOptions // make a copy queue_base.go
144 > if readerID != DefaultReaderId {
145 // non-default reader should not trigger task unloading
146 // otherwise those readers will keep loading, hit pending task count limit, unload, throttle, load, etc...
161 }
162
163 > return NewReader( queue_base.go
164 > readerID,
165 > slices,
166 > &readerOptions,
167 > scheduler,
168 > rescheduler,
169 > shard.GetTimeSource(),
170 > readerRateLimiter,
171 > monitor,
172 > completionFn,
173 > logger,
174 > metricsHandler,
175 > )
176 }
177
178 > exclusiveDeletionHighWatermark := exclusiveReaderHighWatermark queue_base.go
179 > readerGroup := NewReaderGroup(readerInitializer)
180 > for readerID, scopes := range readerScopes {
181 if len(scopes) == 0 {
182 continue
192 }
193
194 > mitigator := newMitigator(readerGroup, monitor, logger, metricsHandler, options.MaxReaderCount, grouper) queue_base.go
195 >
196 > return &queueBase{
197 > shard: shard,
198 >
199 > status: common.DaemonStatusInitialized,
200 > shutdownCh: make(chan struct{}),
201 >
202 > category: category,
203 > options: options,
204 > scheduler: scheduler,
205 > rescheduler: rescheduler,
206 > timeSource: shard.GetTimeSource(),
207 > monitor: monitor,
208 > mitigator: mitigator,
209 > grouper: grouper,
210 > logger: logger,
211 > metricsHandler: metricsHandler,
212 >
213 > paginationFnProvider: paginationFnProvider,
214 > executableFactory: executableFactory,
215 >
216 > lastRangeID: -1, // start from an invalid rangeID
217 > exclusiveDeletionHighWatermark: exclusiveDeletionHighWatermark,
218 > nonReadableScope: NewScope(
219 > NewRange(exclusiveReaderHighWatermark, tasks.MaximumKey),
220 > predicates.Universal[tasks.Task](),
221 > ),
222 > readerRateLimiter: readerRateLimiter,
223 > readerGroup: readerGroup,
224 >
225 > // pollTimer and checkpointTimer are initialized on Start()
226 > checkpointRetrier: backoff.NewRetrier(
227 > createCheckpointRetryPolicy(),
228 > clock.NewRealTimeSource(),
229 > ),
230 >
231 > alertCh: monitor.AlertCh(),
232 > }
233 }
234
235 > func (p *queueBase) Start() { queue_base.go
236 > p.rescheduler.Start()
237 > p.readerGroup.Start()
238 >
239 > p.checkpointTimer = time.NewTimer(backoff.Jitter(
240 > p.options.CheckpointInterval(),
241 > p.options.CheckpointIntervalJitterCoefficient(),
242 > ))
243 > }
244
245 > func (p *queueBase) Stop() { queue_base.go
246 > p.monitor.Close()
247 > p.readerGroup.Stop()
248 > p.rescheduler.Stop()
249 > p.checkpointTimer.Stop()
250 > }
251
252 > func (p *queueBase) Category() tasks.Category { queue_base.go
253 > return p.category
254 > }
255
256 func (p *queueBase) FailoverNamespace(
260 }
261
262 > func (p *queueBase) processNewRange() { queue_base.go
263 > newMaxKey := p.shard.GetQueueExclusiveHighReadWatermark(p.category)
264 >
265 > slices := make([]Slice, 0, 1)
266 > if p.nonReadableScope.CanSplitByRange(newMaxKey) {
267 > var newReadScope Scope
268 > newReadScope, p.nonReadableScope = p.nonReadableScope.SplitByRange(newMaxKey)
269 > slices = append(slices, NewSlice(
270 > p.paginationFnProvider,
271 > p.executableFactory,
272 > p.monitor,
273 > newReadScope,
274 > p.grouper,
275 > p.options.MaxPredicateSize,
276 > p.options.ShrinkPredicateMaxPendingKeys,
277 > p.metricsHandler,
278 > ))
279 > }
280
281 > reader, ok := p.readerGroup.ReaderByID(DefaultReaderId) queue_base.go
282 > if !ok {
283 > p.readerGroup.NewReader(DefaultReaderId, slices...)
284 > return
285 > }
286
287 > if now := p.timeSource.Now(); now.After(p.nextForceNewSliceTime) { queue_base.go
288 > reader.AppendSlices(slices...)
289 > p.nextForceNewSliceTime = now.Add(forceNewSliceDuration)
290 > } else {
291 > reader.MergeSlices(slices...) queue_base.go
292 > }
293 }
294
446 }
447
448 > func createCheckpointRetryPolicy() backoff.RetryPolicy { queue_base.go
449 > policy := backoff.NewExponentialRetryPolicy(100 * time.Millisecond).
450 > WithMaximumInterval(5 * time.Second).
451 > WithExpirationInterval(backoff.NoInterval)
452 >
453 > return policy
454 > }
455
456 > func newQueueIOContext() (context.Context, context.CancelFunc) { queue_base.go
457 > ctx, cancel := context.WithTimeout(context.Background(), queueIOTimeout)
458 > ctx = headers.SetCallerInfo(ctx, headers.SystemBackgroundHighCallerInfo)
459 > return ctx, cancel
460 > }
go.temporal.io/server/service/matching/handler.go 134 covered LOC · 20 ranges

Open complete file

90 func NewHandler(
91 params HandlerParams,
92 > ) *Handler { handler.go
93 > handler := &Handler{
94 > config: params.Config,
95 > metricsHandler: params.MetricsHandler,
96 > logger: params.Logger,
97 > throttledLogger: params.ThrottledLogger,
98 > engine: NewEngine(
99 > params.TaskManager,
100 > params.FairTaskManager,
101 > params.HistoryClient,
102 > params.MatchingRawClient, // Use non retry client inside matching
103 > params.WorkerDeploymentClient,
104 > params.Config,
105 > params.Logger,
106 > params.ThrottledLogger,
107 > params.MetricsHandler,
108 > params.NamespaceRegistry,
109 > params.HostInfoProvider,
110 > params.MatchingServiceResolver,
111 > params.ClusterMetadata,
112 > params.NamespaceReplicationQueue,
113 > params.VisibilityManager,
114 > params.NexusEndpointManager,
115 > params.TestHooks,
116 > params.SearchAttributeProvider,
117 > params.SearchAttributeMapperProvider,
118 > params.RateLimiter,
119 > params.Serializer,
120 > params.TaskHookFactories,
121 > params.PartitionScalerFactory,
122 > ),
123 > namespaceRegistry: params.NamespaceRegistry,
124 > workersRegistry: params.WorkersRegistry,
125 > }
126 >
127 > // prevent from serving requests before matching engine is started and ready
128 > handler.startWG.Add(1)
129 >
130 > return handler
131 > }
132
133 // Start starts the handler
134 > func (h *Handler) Start() { handler.go
135 > h.engine.Start()
136 > h.startWG.Done()
137 > }
138
139 // Stop stops the handler
140 > func (h *Handler) Stop() { handler.go
141 > h.engine.Stop()
142 > }
143
144 func (h *Handler) opMetricsHandler(
147 taskQueueType enumspb.TaskQueueType,
148 operation string,
149 > ) metrics.Handler { handler.go
150 > nsName := h.namespaceName(namespace.ID(namespaceID))
151 > partition := tqid.UnsafePartitionFromProto(taskQueue, namespaceID, taskQueueType)
152 > return metrics.GetPerTaskQueuePartitionIDScope(
153 > h.metricsHandler.WithTags(metrics.OperationTag(operation)),
154 > nsName.String(),
155 > partition,
156 > h.config.BreakdownMetricsByTaskQueue(nsName.String(), partition.TaskQueue().Name(), partition.TaskType()),
157 > h.config.BreakdownMetricsByPartition(nsName.String(), partition.TaskQueue().Name(), partition.TaskType()),
158 > )
159 > }
160
161 // recordNexusTaskRequest emits the nexus_task_requests metric with namespace,
202 ctx context.Context,
203 request *matchingservice.AddWorkflowTaskRequest,
204 > ) (_ *matchingservice.AddWorkflowTaskResponse, retError error) { handler.go
205 > defer log.CapturePanic(h.logger, &retError)
206 > startT := time.Now().UTC()
207 > opMetrics := h.opMetricsHandler(
208 > request.GetNamespaceId(),
209 > request.GetTaskQueue(),
210 > enumspb.TASK_QUEUE_TYPE_WORKFLOW,
211 > metrics.MatchingAddWorkflowTaskScope,
212 > )
213 >
214 > if request.GetForwardInfo() != nil {
215 h.reportForwardedPerTaskQueueCounter(opMetrics, namespace.ID(request.GetNamespaceId()))
216 }
217
218 > assignedBuildId, syncMatch, err := h.engine.AddWorkflowTask(ctx, request) handler.go
219 > if syncMatch {
220 metrics.SyncMatchLatencyPerTaskQueue.With(opMetrics).Record(time.Since(startT))
221 }
222 > return &matchingservice.AddWorkflowTaskResponse{AssignedBuildId: assignedBuildId}, err handler.go
223 }
224
227 ctx context.Context,
228 request *matchingservice.PollActivityTaskQueueRequest,
229 > ) (_ *matchingservice.PollActivityTaskQueueResponse, retError error) { handler.go
230 > defer log.CapturePanic(h.logger, &retError)
231 > opMetrics := h.opMetricsHandler(
232 > request.GetNamespaceId(),
233 > request.GetPollRequest().GetTaskQueue(),
234 > enumspb.TASK_QUEUE_TYPE_ACTIVITY,
235 > metrics.MatchingPollActivityTaskQueueScope,
236 > )
237 >
238 > if request.GetForwardedSource() != "" {
239 h.reportForwardedPerTaskQueueCounter(opMetrics, namespace.ID(request.GetNamespaceId()))
240 }
241
242 > if _, err := common.ValidateLongPollContextTimeoutIsSet( handler.go
243 > ctx,
244 > "PollActivityTaskQueue",
245 > h.throttledLogger,
246 > ); err != nil {
247 return nil, err
248 }
249
250 > return h.engine.PollActivityTaskQueue(ctx, request, opMetrics) handler.go
251 }
252
255 ctx context.Context,
256 request *matchingservice.PollWorkflowTaskQueueRequest,
257 > ) (_ *matchingservice.PollWorkflowTaskQueueResponseWithRawHistory, retError error) { handler.go
258 > defer log.CapturePanic(h.logger, &retError)
259 > opMetrics := h.opMetricsHandler(
260 > request.GetNamespaceId(),
261 > request.GetPollRequest().GetTaskQueue(),
262 > enumspb.TASK_QUEUE_TYPE_WORKFLOW,
263 > metrics.MatchingPollWorkflowTaskQueueScope,
264 > )
265 >
266 > if request.GetForwardedSource() != "" {
267 h.reportForwardedPerTaskQueueCounter(opMetrics, namespace.ID(request.GetNamespaceId()))
268 }
269
270 > if _, err := common.ValidateLongPollContextTimeoutIsSet( handler.go
271 > ctx,
272 > "PollWorkflowTaskQueue",
273 > h.throttledLogger,
274 > ); err != nil {
275 return nil, err
276 }
277
278 > return h.engine.PollWorkflowTaskQueue(ctx, request, opMetrics) handler.go
279 }
280
318 // CancelOutstandingPoll is used to cancel outstanding pollers
319 func (h *Handler) CancelOutstandingPoll(ctx context.Context,
320 > request *matchingservice.CancelOutstandingPollRequest) (_ *matchingservice.CancelOutstandingPollResponse, retError error) { handler.go
321 > defer log.CapturePanic(h.logger, &retError)
322 > err := h.engine.CancelOutstandingPoll(ctx, request)
323 > return &matchingservice.CancelOutstandingPollResponse{}, err
324 > }
325
326 // CancelOutstandingWorkerPolls cancels all outstanding polls for a given worker instance key.
434 ctx context.Context,
435 request *matchingservice.GetTaskQueueUserDataRequest,
436 > ) (_ *matchingservice.GetTaskQueueUserDataResponse, retError error) { handler.go
437 > defer log.CapturePanic(h.logger, &retError)
438 > return h.engine.GetTaskQueueUserData(ctx, request)
439 > }
440
441 func (h *Handler) SyncDeploymentUserData(
474 ctx context.Context,
475 request *matchingservice.ForceUnloadTaskQueuePartitionRequest,
476 > ) (_ *matchingservice.ForceUnloadTaskQueuePartitionResponse, retError error) { handler.go
477 > defer log.CapturePanic(h.logger, &retError)
478 > return h.engine.ForceUnloadTaskQueuePartition(ctx, request)
479 > }
480
481 func (h *Handler) ForceLoadTaskQueuePartition(
593 }
594
595 > func (h *Handler) ListNexusEndpoints(ctx context.Context, request *matchingservice.ListNexusEndpointsRequest) (_ *matchingservice.ListNexusEndpointsResponse, retError error) { handler.go
596 > defer log.CapturePanic(h.logger, &retError)
597 > return h.engine.ListNexusEndpoints(ctx, request)
598 > }
599
600 // RecordWorkerHeartbeat receive heartbeat request from the worker.
601 func (h *Handler) RecordWorkerHeartbeat(
602 ctx context.Context, request *matchingservice.RecordWorkerHeartbeatRequest,
603 > ) (_ *matchingservice.RecordWorkerHeartbeatResponse, retError error) { handler.go
604 > defer log.CapturePanic(h.logger, &retError)
605 > nsID := namespace.ID(request.GetNamespaceId())
606 > nsName := h.namespaceName(nsID)
607 > principal := headers.GetPrincipal(ctx)
608 >
609 > h.workersRegistry.RecordWorkerHeartbeats(nsID, nsName, principal, request.GetHeartbeartRequest().GetWorkerHeartbeat())
610 > return &matchingservice.RecordWorkerHeartbeatResponse{}, nil
611 > }
612
613 // ListWorkers retrieves a list of workers in the specified namespace that match the provided filters.
684 }
685
686 > func (h *Handler) namespaceName(id namespace.ID) namespace.Name { handler.go
687 > entry, err := h.namespaceRegistry.GetNamespaceByID(id)
688 > if err != nil {
689 return ""
690 }
691 > return entry.Name() handler.go
692 }
693
go.temporal.io/server/service/history/historybuilder/event_store.go 132 covered LOC · 46 ranges

Open complete file

49 }
50
51 > func (b *EventStore) IsDirty() bool { event_store.go
52 > return len(b.memEventsBatches) > 0 ||
53 > len(b.memLatestBatch) > 0 ||
54 > len(b.memBufferBatch) > 0 ||
55 > len(b.scheduledIDToStartedID) > 0
56 > }
57
58 > func (b *EventStore) AllocateEventID() int64 { event_store.go
59 > result := b.nextEventID
60 > b.nextEventID++
61 > return result
62 > }
63
64 > func (b *EventStore) NextEventID() int64 { event_store.go
65 > return b.nextEventID
66 > }
67
68 > func (b *EventStore) LastEventVersion() (int64, bool) { event_store.go
69 > if len(b.memLatestBatch) != 0 {
70 > lastEvent := b.memLatestBatch[len(b.memLatestBatch)-1] event_store.go
71 > return lastEvent.GetVersion(), true
72 > }
73
74 > if len(b.memEventsBatches) != 0 { event_store.go
75 lastBatch := b.memEventsBatches[len(b.memEventsBatches)-1]
76 lastEvent := lastBatch[len(lastBatch)-1]
80 // buffered events are not real events yet, so not taken into account here
81
82 > return common.EmptyVersion, false event_store.go
83 }
84
85 func (b *EventStore) add(
86 event *historypb.HistoryEvent,
87 > ) (*historypb.HistoryEvent, int64) { event_store.go
88 > b.assertMutable()
89 > if b.workflowFinished {
90 panic("history builder unable to add new event after workflow finish")
91 }
92 > if b.finishEvent(event.GetEventType()) { event_store.go
93 > b.workflowFinished = true event_store.go
94 > }
95
96 > batchID := common.EmptyEventID event_store.go
97 > if b.bufferEvent(event.GetEventType()) {
98 event.EventId = common.BufferedEventID
99 b.memBufferBatch = append(b.memBufferBatch, event)
100 > } else { event_store.go
101 > event.EventId = b.AllocateEventID() event_store.go
102 > b.appendToLatestBatch(event)
103 > batchID = b.memLatestBatch[0].EventId
104 > }
105 > return event, batchID event_store.go
106 }
107
118 // first if the additional event would push the current batch over
119 // maxEventBatchSizeInBytes. A value of <= 0 disables the check.
120 > func (b *EventStore) appendToLatestBatch(event *historypb.HistoryEvent) { event_store.go
121 > eventSize := proto.Size(event)
122 > if limit := b.maxEventBatchSizeInBytes(); limit > 0 {
123 if len(b.memLatestBatch) > 0 && b.memLatestBatchSize+eventSize > limit {
124 b.FlushAndCreateNewBatch()
128 // limit is disabled. Otherwise, enabling maxEventBatchSizeInBytes mid-flight
129 // would start counting from that point and undercount the current batch.
130 > b.memLatestBatchSize += eventSize event_store.go
131 > b.memLatestBatch = append(b.memLatestBatch, event)
132 }
133
134 > func (b *EventStore) HasBufferEvents() bool { event_store.go
135 > return len(b.dbBufferBatch) > 0 || len(b.memBufferBatch) > 0
136 > }
137
138 // HasAnyBufferedEvent returns true if there is at least one buffered event that matches the provided filter.
144 }
145
146 > func (b *EventStore) NumBufferedEvents() int { event_store.go
147 > return len(b.dbBufferBatch) + len(b.memBufferBatch)
148 > }
149
150 > func (b *EventStore) SizeInBytesOfBufferedEvents() int { event_store.go
151 > size := 0
152 > for _, ev := range b.dbBufferBatch {
153 size += proto.Size(ev)
154 }
155 > for _, ev := range b.memBufferBatch { event_store.go
156 size += proto.Size(ev)
157 }
158 > return size event_store.go
159 }
160
161 > func (b *EventStore) FlushBufferToCurrentBatch() (map[int64]int64, map[string]int64) { event_store.go
162 > if len(b.dbBufferBatch) == 0 && len(b.memBufferBatch) == 0 {
163 > return b.scheduledIDToStartedID, b.requestIDToEventID event_store.go
164 > }
165
166 b.assertMutable()
200 }
201
202 > func (b *EventStore) FlushAndCreateNewBatch() { event_store.go
203 > b.assertNotSealed()
204 > if len(b.memLatestBatch) == 0 {
205 > return event_store.go
206 > }
207
208 > b.memEventsBatches = append(b.memEventsBatches, b.memLatestBatch) event_store.go
209 > b.memLatestBatch = nil
210 > b.memLatestBatchSize = 0
211 }
212
213 func (b *EventStore) Finish(
214 flushBufferEvent bool,
215 > ) (*HistoryMutation, error) { event_store.go
216 > defer func() {
217 > b.state = HistoryBuilderStateSealed
218 > }()
219
220 > if flushBufferEvent { event_store.go
221 > _, _ = b.FlushBufferToCurrentBatch() event_store.go
222 > }
223 > b.FlushAndCreateNewBatch() event_store.go
224 >
225 > dbEventsBatches := b.memEventsBatches
226 > dbClearBuffer := b.dbClearBuffer
227 > dbBufferBatch := b.memBufferBatch
228 > memBufferBatch := b.dbBufferBatch
229 > memBufferBatch = append(memBufferBatch, dbBufferBatch...)
230 > scheduledIDToStartedID := b.scheduledIDToStartedID
231 > requestIDToEventID := b.requestIDToEventID
232 >
233 > b.memEventsBatches = nil
234 > b.memBufferBatch = nil
235 > b.memLatestBatch = nil
236 > b.memLatestBatchSize = 0
237 > b.dbClearBuffer = false
238 > b.dbBufferBatch = nil
239 > b.scheduledIDToStartedID = nil
240 >
241 > if err := b.assignTaskIDs(dbEventsBatches); err != nil {
242 return nil, err
243 }
244
245 > return &HistoryMutation{ event_store.go
246 > DBEventsBatches: dbEventsBatches,
247 > DBClearBuffer: dbClearBuffer,
248 > DBBufferBatch: dbBufferBatch,
249 > MemBufferBatch: memBufferBatch,
250 > ScheduledIDToStartedID: scheduledIDToStartedID,
251 > RequestIDToEventID: requestIDToEventID,
252 > }, nil
253 }
254
255 func (b *EventStore) assignTaskIDs(
256 dbEventsBatches [][]*historypb.HistoryEvent,
257 > ) error { event_store.go
258 > b.assertNotSealed()
259 >
260 > if b.state == HistoryBuilderStateImmutable {
261 return nil
262 }
263
264 > taskIDCount := 0 event_store.go
265 > for i := range dbEventsBatches {
266 > taskIDCount += len(dbEventsBatches[i]) event_store.go
267 > }
268 > taskIDs, err := b.taskIDGenerator(taskIDCount) event_store.go
269 > if err != nil {
270 return err
271 }
272
273 > taskIDPointer := 0 event_store.go
274 > height := len(dbEventsBatches)
275 > for i := range height {
276 > width := len(dbEventsBatches[i]) event_store.go
277 > for j := range width {
278 > dbEventsBatches[i][j].TaskId = taskIDs[taskIDPointer]
279 > taskIDPointer++
280 > }
281 }
282 > return nil event_store.go
283 }
284
285 > func (b *EventStore) assertMutable() { event_store.go
286 > if b.state != HistoryBuilderStateMutable {
287 panic("history builder is mutated while not in mutable state")
288 }
289 }
290
291 > func (b *EventStore) assertNotSealed() { event_store.go
292 > if b.state == HistoryBuilderStateSealed {
293 panic("history builder is in sealed state")
294 }
297 func (b *EventStore) bufferEvent(
298 eventType enumspb.EventType,
299 > ) bool { event_store.go
300 > switch eventType {
301 case // do not buffer for workflow state change
302 enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_STARTED,
306 enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_TERMINATED,
307 enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_CONTINUED_AS_NEW,
308 > enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_CANCELED: event_store.go
309 > return false
310
311 case // workflow task event should not be buffered
314 enumspb.EVENT_TYPE_WORKFLOW_TASK_COMPLETED,
315 enumspb.EVENT_TYPE_WORKFLOW_TASK_FAILED,
316 > enumspb.EVENT_TYPE_WORKFLOW_TASK_TIMED_OUT: event_store.go
317 > return false
318
319 case // events generated directly from commands should not be buffered
362 func (b *EventStore) finishEvent(
363 eventType enumspb.EventType,
364 > ) bool { event_store.go
365 > switch eventType {
366 case
367 enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED,
370 enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_TERMINATED,
371 enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_CONTINUED_AS_NEW,
372 > enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_CANCELED: event_store.go
373 > return true
374
375 > default: event_store.go
376 > return false
377 }
378 }
go.temporal.io/server/common/persistence/visibility/factory.go 131 covered LOC · 12 ranges

Open complete file

56 logger log.Logger,
57 serializer serialization.Serializer,
58 > ) (manager.VisibilityManager, error) { factory.go
59 > visibilityManager, err := newVisibilityManagerFromDataStoreConfig(
60 > persistenceCfg.GetVisibilityStoreConfig(),
61 > persistenceResolver,
62 > customVisibilityStoreFactory,
63 > esProcessorConfig,
64 > searchAttributesProvider,
65 > searchAttributesMapperProvider,
66 > namespaceRegistry,
67 > chasmRegistry,
68 > maxReadQPS,
69 > maxWriteQPS,
70 > operatorRPSRatio,
71 > slowQueryThreshold,
72 > visibilityDisableOrderByClause,
73 > visibilityEnableManualPagination,
74 > visibilityEnableUnifiedQueryConverter,
75 > metricsHandler,
76 > logger,
77 > serializer,
78 > )
79 > if err != nil {
80 return nil, err
81 }
82 > if visibilityManager == nil { factory.go
83 logger.Fatal("invalid config: visibility store must be configured")
84 return nil, nil
85 }
86
87 > secondaryVisibilityManager, err := newVisibilityManagerFromDataStoreConfig( factory.go
88 > persistenceCfg.GetSecondaryVisibilityStoreConfig(),
89 > persistenceResolver,
90 > customVisibilityStoreFactory,
91 > esProcessorConfig,
92 > searchAttributesProvider,
93 > searchAttributesMapperProvider,
94 > namespaceRegistry,
95 > chasmRegistry,
96 > maxReadQPS,
97 > maxWriteQPS,
98 > operatorRPSRatio,
99 > slowQueryThreshold,
100 > visibilityDisableOrderByClause,
101 > visibilityEnableManualPagination,
102 > visibilityEnableUnifiedQueryConverter,
103 > metricsHandler,
104 > logger,
105 > serializer,
106 > )
107 > if err != nil {
108 return nil, err
109 }
110
111 > if secondaryVisibilityManager != nil { factory.go
112 managerSelector := newDefaultManagerSelector(
113 visibilityManager,
124 }
125
126 > return visibilityManager, nil factory.go
127 }
128
139 searchAttributesMapperProvider searchattribute.MapperProvider,
140 chasmRegistry *chasm.Registry,
141 > ) manager.VisibilityManager { factory.go
142 > if visStore == nil {
143 return nil
144 }
145 > logger.Info( factory.go
146 > "creating new visibility manager",
147 > tag.String(visibilityPluginNameTag.Key, visibilityPluginNameTag.Value),
148 > tag.String(visibilityIndexNameTag.Key, visibilityIndexNameTag.Value),
149 > )
150 > var visManager manager.VisibilityManager = newVisibilityManagerImpl(
151 > visStore,
152 > logger,
153 > searchAttributesMapperProvider,
154 > chasmRegistry,
155 > )
156 >
157 > // wrap with rate limiter
158 > visManager = NewVisibilityManagerRateLimited(
159 > visManager,
160 > maxReadQPS,
161 > maxWriteQPS,
162 > operatorRPSRatio,
163 > )
164 > // wrap with metrics client
165 > visManager = NewVisibilityManagerMetrics(
166 > visManager,
167 > metricsHandler,
168 > logger,
169 > slowQueryThreshold,
170 > visibilityPluginNameTag,
171 > visibilityIndexNameTag,
172 > )
173 > return visManager
174 }
175
197 logger log.Logger,
198 serializer serialization.Serializer,
199 > ) (manager.VisibilityManager, error) { factory.go
200 > visStore, err := newVisibilityStoreFromDataStoreConfig(
201 > dsConfig,
202 > persistenceResolver,
203 > customVisibilityStoreFactory,
204 > esProcessorConfig,
205 > searchAttributesProvider,
206 > searchAttributesMapperProvider,
207 > namespaceRegistry,
208 > chasmRegistry,
209 > visibilityDisableOrderByClause,
210 > visibilityEnableManualPagination,
211 > visibilityEnableUnifiedQueryConverter,
212 > metricsHandler,
213 > logger,
214 > serializer,
215 > )
216 > if err != nil {
217 return nil, err
218 }
219 > if visStore == nil { factory.go
220 > return nil, nil
221 > }
222 > return newVisibilityManager(
223 > visStore,
224 > maxReadQPS,
225 > maxWriteQPS,
226 > operatorRPSRatio,
227 > slowQueryThreshold,
228 > metricsHandler,
229 > metrics.VisibilityPluginNameTag(visStore.GetName()),
230 > metrics.VisibilityIndexNameTag(visStore.GetIndexName()),
231 > logger,
232 > searchAttributesMapperProvider,
233 > chasmRegistry,
234 > ), nil
235 }
236
252 logger log.Logger,
253 serializer serialization.Serializer,
254 > ) (store.VisibilityStore, error) { factory.go
255 > var (
256 > visStore store.VisibilityStore
257 > err error
258 > )
259 > if dsConfig.SQL != nil {
260 > visStore, err = sql.NewSQLVisibilityStore(
261 > *dsConfig.SQL,
262 > persistenceResolver,
263 > searchAttributesProvider,
264 > searchAttributesMapperProvider,
265 > chasmRegistry,
266 > visibilityEnableUnifiedQueryConverter,
267 > logger,
268 > metricsHandler,
269 > serializer,
270 > )
271 > } else if dsConfig.Elasticsearch != nil {
272 visStore, err = elasticsearch.NewVisibilityStore(
273 dsConfig.Elasticsearch,
282 logger,
283 )
284 > } else if dsConfig.CustomDataStoreConfig != nil { factory.go
285 if customVisibilityStoreFactory == nil {
286 logger.Fatal("custom visibility store factory must be defined")
298 )
299 }
300 > return visStore, err factory.go
301 }
go.temporal.io/server/service/history/visibility_queue_factory.go 131 covered LOC · 3 ranges

Open complete file

35 func NewVisibilityQueueFactory(
36 params visibilityQueueFactoryParams,
37 > ) QueueFactory { visibility_queue_factory.go
38 > return &visibilityQueueFactory{
39 > visibilityQueueFactoryParams: params,
40 > QueueFactoryBase: QueueFactoryBase{
41 > HostScheduler: queues.NewScheduler(
42 > params.ClusterMetadata.GetCurrentClusterName(),
43 > queues.SchedulerOptions{
44 > WorkerCount: params.Config.VisibilityProcessorSchedulerWorkerCount,
45 > ActiveNamespaceWeights: params.Config.VisibilityProcessorSchedulerActiveRoundRobinWeights,
46 > StandbyNamespaceWeights: params.Config.VisibilityProcessorSchedulerStandbyRoundRobinWeights,
47 > InactiveNamespaceDeletionDelay: params.Config.TaskSchedulerInactiveChannelDeletionDelay,
48 > ExecutionAwareSchedulerOptions: ctasks.ExecutionAwareSchedulerOptions{
49 > Enabled: params.Config.TaskSchedulerEnableExecutionQueueScheduler,
50 > MaxQueues: params.Config.TaskSchedulerExecutionQueueSchedulerMaxQueues,
51 > QueueTTL: params.Config.TaskSchedulerExecutionQueueSchedulerQueueTTL,
52 > QueueConcurrency: params.Config.TaskSchedulerExecutionQueueSchedulerQueueConcurrency,
53 > },
54 > },
55 > params.NamespaceRegistry,
56 > params.Logger,
57 > params.MetricsHandler,
58 > params.TimeSource,
59 > ),
60 > HostPriorityAssigner: queues.NewPriorityAssigner(
61 > params.NamespaceRegistry,
62 > params.ClusterMetadata.GetCurrentClusterName(),
63 > ),
64 > HostReaderRateLimiter: queues.NewReaderPriorityRateLimiter(
65 > NewHostRateLimiterRateFn(
66 > params.Config.VisibilityProcessorMaxPollHostRPS,
67 > params.Config.PersistenceMaxQPS,
68 > visibilityQueuePersistenceMaxRPSRatio,
69 > ),
70 > int64(params.Config.VisibilityQueueMaxReaderCount()),
71 > ),
72 > Tracer: params.TracerProvider.Tracer(telemetry.ComponentQueueVisibility),
73 > },
74 > }
75 > }
76
77 func (f *visibilityQueueFactory) CreateQueue(
78 shard historyi.ShardContext,
79 > ) queues.Queue { visibility_queue_factory.go
80 > logger := log.With(shard.GetLogger(), tag.ComponentVisibilityQueue)
81 > metricsHandler := f.MetricsHandler.WithTags(metrics.OperationTag(metrics.OperationVisibilityQueueProcessorScope))
82 >
83 > shardScheduler := queues.NewRateLimitedScheduler(
84 > f.HostScheduler,
85 > queues.RateLimitedSchedulerOptions{
86 > Enabled: f.Config.TaskSchedulerEnableRateLimiter,
87 > EnableShadowMode: f.Config.TaskSchedulerEnableRateLimiterShadowMode,
88 > StartupDelay: f.Config.TaskSchedulerRateLimiterStartupDelay,
89 > },
90 > f.ClusterMetadata.GetCurrentClusterName(),
91 > f.NamespaceRegistry,
92 > f.SchedulerRateLimiter,
93 > f.TimeSource,
94 > f.ChasmRegistry,
95 > logger,
96 > metricsHandler,
97 > )
98 >
99 > rescheduler := queues.NewRescheduler(
100 > shardScheduler,
101 > shard.GetTimeSource(),
102 > logger,
103 > metricsHandler,
104 > )
105 >
106 > executor := newVisibilityQueueTaskExecutor(
107 > shard,
108 > f.WorkflowCache,
109 > f.VisibilityMgr,
110 > logger,
111 > f.MetricsHandler,
112 > f.Config.VisibilityProcessorEnsureCloseBeforeDelete,
113 > f.Config.VisibilityProcessorEnableCloseWorkflowCleanup,
114 > f.Config.VisibilityProcessorRelocateAttributesMinBlobSize,
115 > f.Config.ExternalPayloadsEnabled,
116 > )
117 > if f.ExecutorWrapper != nil {
118 executor = f.ExecutorWrapper.Wrap(executor)
119 }
120
121 > factory := queues.NewExecutableFactory( visibility_queue_factory.go
122 > executor,
123 > shardScheduler,
124 > rescheduler,
125 > f.HostPriorityAssigner,
126 > shard.GetTimeSource(),
127 > shard.GetNamespaceRegistry(),
128 > shard.GetClusterMetadata(),
129 > f.ChasmRegistry,
130 > queues.GetTaskTypeTagValue,
131 > logger,
132 > metricsHandler,
133 > f.Tracer,
134 > f.DLQWriter,
135 > f.Config.TaskDLQEnabled,
136 > f.Config.TaskDLQUnexpectedErrorAttempts,
137 > f.Config.TaskDLQInternalErrors,
138 > f.Config.TaskDLQErrorPattern,
139 > )
140 > return queues.NewImmediateQueue(
141 > shard,
142 > tasks.CategoryVisibility,
143 > shardScheduler,
144 > rescheduler,
145 > &queues.Options{
146 > ReaderOptions: queues.ReaderOptions{
147 > BatchSize: f.Config.VisibilityTaskBatchSize,
148 > MaxPendingTasksCount: f.Config.QueuePendingTaskMaxCount,
149 > PollBackoffInterval: f.Config.VisibilityProcessorPollBackoffInterval,
150 > MaxPredicateSize: f.Config.QueueMaxPredicateSize,
151 > },
152 > MonitorOptions: queues.MonitorOptions{
153 > PendingTasksCriticalCount: f.Config.QueuePendingTaskCriticalCount,
154 > ReaderStuckCriticalAttempts: f.Config.QueueReaderStuckCriticalAttempts,
155 > SliceCountCriticalThreshold: f.Config.QueueCriticalSlicesCount,
156 > },
157 > MaxPollRPS: f.Config.VisibilityProcessorMaxPollRPS,
158 > MaxPollInterval: f.Config.VisibilityProcessorMaxPollInterval,
159 > MaxPollIntervalJitterCoefficient: f.Config.VisibilityProcessorMaxPollIntervalJitterCoefficient,
160 > CheckpointInterval: f.Config.VisibilityProcessorUpdateAckInterval,
161 > CheckpointIntervalJitterCoefficient: f.Config.VisibilityProcessorUpdateAckIntervalJitterCoefficient,
162 > MaxReaderCount: f.Config.VisibilityQueueMaxReaderCount,
163 > MoveGroupTaskCountBase: f.Config.QueueMoveGroupTaskCountBase,
164 > MoveGroupTaskCountMultiplier: f.Config.QueueMoveGroupTaskCountMultiplier,
165 > ShrinkPredicateMaxPendingKeys: f.Config.QueueShrinkPredicateMaxPendingKeys,
166 > },
167 > f.HostReaderRateLimiter,
168 > queues.GrouperNamespaceID{},
169 > logger,
170 > metricsHandler,
171 > factory,
172 > nil, // taskPostProcessor
173 > )
174 }
go.temporal.io/server/service/history/historybuilder/event_factory.go 127 covered LOC · 8 ranges

Open complete file

36 firstRunID string,
37 originalRunID string,
38 > ) *historypb.HistoryEvent { event_factory.go
39 > event := b.createHistoryEvent(enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_STARTED, startTime)
40 > req := request.StartRequest
41 >
42 > // Versioning override might be set on the workflow service request if a user passes it to
43 > // StartWorkflow options, or it might be set on the history service request if a workflow is
44 > // continuing-as-new and inheriting a Pinned override. Use whichever of the two is non-nil.
45 > nonNilVersioningOverride := req.GetVersioningOverride() // From user.
46 > if nonNilVersioningOverride == nil {
47 > nonNilVersioningOverride = request.GetVersioningOverride() // From server during continue-as-new.
48 > }
49
50 > attributes := &historypb.WorkflowExecutionStartedEventAttributes{ event_factory.go
51 > WorkflowType: req.WorkflowType,
52 > TaskQueue: req.TaskQueue,
53 > Header: req.Header,
54 > Input: req.Input,
55 > WorkflowRunTimeout: req.WorkflowRunTimeout,
56 > WorkflowExecutionTimeout: req.WorkflowExecutionTimeout,
57 > WorkflowTaskTimeout: req.WorkflowTaskTimeout,
58 > ContinuedExecutionRunId: prevRunID,
59 > PrevAutoResetPoints: resetPoints,
60 > Identity: req.Identity,
61 > RetryPolicy: req.RetryPolicy,
62 > Attempt: request.GetAttempt(),
63 > WorkflowExecutionExpirationTime: request.WorkflowExecutionExpirationTime,
64 > CronSchedule: req.CronSchedule,
65 > LastCompletionResult: request.LastCompletionResult,
66 > ContinuedFailure: request.GetContinuedFailure(),
67 > Initiator: request.ContinueAsNewInitiator,
68 > FirstWorkflowTaskBackoff: request.FirstWorkflowTaskBackoff,
69 > FirstExecutionRunId: firstRunID,
70 > OriginalExecutionRunId: originalRunID,
71 > // Filter nil values here rather than in the API layer because not all
72 > // creation paths go through the frontend (e.g. continue-as-new, child workflows, replication).
73 > Memo: payload.FilterNilMemo(req.Memo),
74 > SearchAttributes: payload.FilterNilSearchAttributes(req.SearchAttributes),
75 > WorkflowId: req.WorkflowId,
76 > SourceVersionStamp: request.SourceVersionStamp,
77 > CompletionCallbacks: req.CompletionCallbacks,
78 > RootWorkflowExecution: request.RootExecutionInfo.GetExecution(),
79 > InheritedBuildId: request.InheritedBuildId,
80 > VersioningOverride: worker_versioning.ConvertOverrideToV32(nonNilVersioningOverride),
81 > Priority: req.GetPriority(),
82 > InheritedPinnedVersion: request.InheritedPinnedVersion,
83 > // We expect the API handler to unset RequestEagerExecution if eager execution cannot be accepted.
84 > EagerExecutionAccepted: req.GetRequestEagerExecution(),
85 > InheritedAutoUpgradeInfo: request.InheritedAutoUpgradeInfo,
86 > DeclinedTargetVersionUpgrade: request.DeclinedTargetVersionUpgrade,
87 > TimeSkippingConfig: req.GetTimeSkippingConfig(),
88 > TimeSkippingStatePropagation: request.GetTimeSkippingStatePropagation(),
89 > }
90 >
91 > parentInfo := request.ParentExecutionInfo
92 > if parentInfo != nil {
93 attributes.ParentWorkflowNamespaceId = parentInfo.NamespaceId
94 attributes.ParentWorkflowNamespace = parentInfo.Namespace
98 }
99
100 > event.Attributes = &historypb.HistoryEvent_WorkflowExecutionStartedEventAttributes{ event_factory.go
101 > WorkflowExecutionStartedEventAttributes: attributes,
102 > }
103 > return event
104 }
105
109 attempt int32,
110 scheduleTime time.Time,
111 > ) *historypb.HistoryEvent { event_factory.go
112 > event := b.createHistoryEvent(enumspb.EVENT_TYPE_WORKFLOW_TASK_SCHEDULED, scheduleTime)
113 > event.Attributes = &historypb.HistoryEvent_WorkflowTaskScheduledEventAttributes{
114 > WorkflowTaskScheduledEventAttributes: &historypb.WorkflowTaskScheduledEventAttributes{
115 > TaskQueue: taskQueue,
116 > StartToCloseTimeout: startToCloseTimeout,
117 > Attempt: attempt,
118 > },
119 > }
120 >
121 > return event
122 > }
123
124 func (b *EventFactory) CreateWorkflowTaskStartedEvent(
133 suggestContinueAsNewReasons []enumspb.SuggestContinueAsNewReason,
134 targetWorkerDeploymentVersionChanged bool,
135 > ) *historypb.HistoryEvent { event_factory.go
136 > event := b.createHistoryEvent(enumspb.EVENT_TYPE_WORKFLOW_TASK_STARTED, startTime)
137 > event.Attributes = &historypb.HistoryEvent_WorkflowTaskStartedEventAttributes{
138 > WorkflowTaskStartedEventAttributes: &historypb.WorkflowTaskStartedEventAttributes{
139 > ScheduledEventId: scheduledEventID,
140 > Identity: identity,
141 > RequestId: requestID,
142 > SuggestContinueAsNew: suggestContinueAsNew,
143 > SuggestContinueAsNewReasons: suggestContinueAsNewReasons,
144 > HistorySizeBytes: historySizeBytes,
145 > WorkerVersion: versioningStamp,
146 > BuildIdRedirectCounter: buildIdRedirectCounter,
147 >
148 > TargetWorkerDeploymentVersionChanged: targetWorkerDeploymentVersionChanged,
149 > },
150 > }
151 > return event
152 > }
153
154 func (b *EventFactory) CreateWorkflowTaskCompletedEvent(
163 deployment *deploymentpb.Deployment,
164 behavior enumspb.VersioningBehavior,
165 > ) *historypb.HistoryEvent { event_factory.go
166 > event := b.createHistoryEvent(enumspb.EVENT_TYPE_WORKFLOW_TASK_COMPLETED, b.timeSource.Now())
167 > event.Attributes = &historypb.HistoryEvent_WorkflowTaskCompletedEventAttributes{
168 > WorkflowTaskCompletedEventAttributes: &historypb.WorkflowTaskCompletedEventAttributes{
169 > ScheduledEventId: scheduledEventID,
170 > StartedEventId: startedEventID,
171 > Identity: identity,
172 > BinaryChecksum: checksum,
173 > WorkerVersion: workerVersionStamp,
174 > SdkMetadata: sdkMetadata,
175 > MeteringMetadata: meteringMetadata,
176 > WorkerDeploymentName: deploymentName,
177 > DeploymentVersion: worker_versioning.ExternalWorkerDeploymentVersionFromDeployment(deployment),
178 > VersioningBehavior: behavior,
179 > },
180 > }
181 >
182 > return event
183 > }
184
185 func (b *EventFactory) CreateWorkflowTaskTimedOutEvent(
337 command *commandpb.CompleteWorkflowExecutionCommandAttributes,
338 newExecutionRunID string,
339 > ) *historypb.HistoryEvent { event_factory.go
340 > event := b.createHistoryEvent(enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED, b.timeSource.Now())
341 > event.Attributes = &historypb.HistoryEvent_WorkflowExecutionCompletedEventAttributes{
342 > WorkflowExecutionCompletedEventAttributes: &historypb.WorkflowExecutionCompletedEventAttributes{
343 > WorkflowTaskCompletedEventId: workflowTaskCompletedEventID,
344 > Result: command.Result,
345 > NewExecutionRunId: newExecutionRunID,
346 > },
347 > }
348 > return event
349 > }
350
351 func (b *EventFactory) CreateFailWorkflowEvent(
1086 eventType enumspb.EventType,
1087 time time.Time,
1088 > ) *historypb.HistoryEvent { event_factory.go
1089 > historyEvent := &historypb.HistoryEvent{}
1090 > historyEvent.EventTime = timestamppb.New(time.UTC())
1091 > historyEvent.EventType = eventType
1092 > historyEvent.Version = b.version
1093 > historyEvent.TaskId = common.EmptyEventTaskID
1094 >
1095 > return historyEvent
1096 > }
1097
1098 // CreateWorkflowExecutionTimeSkippingTransitionedEvent creates a workflow execution time skipping transitioned event.
go.temporal.io/server/service/history/queues/slice.go 126 covered LOC · 33 ranges

Open complete file

69 maxPendingKeysFn func() int,
70 metricsHandler metrics.Handler,
71 > ) *SliceImpl { slice.go
72 > s := &SliceImpl{
73 > paginationFnProvider: paginationFnProvider,
74 > executableFactory: executableFactory,
75 > scope: scope,
76 > iterators: []Iterator{
77 > NewIterator(paginationFnProvider, scope.Range),
78 > },
79 > executableTracker: newExecutableTracker(grouper),
80 > monitor: monitor,
81 > maxPredicateSizeFn: maxPredicateSizeFn,
82 > maxPendingKeysFn: maxPendingKeysFn,
83 > metricsHandler: metricsHandler,
84 > }
85 > s.ensurePredicateSizeLimit()
86 > return s
87 > }
88
89 > func (s *SliceImpl) Scope() Scope { slice.go
90 > s.stateSanityCheck()
91 > return s.scope
92 > }
93
94 func (s *SliceImpl) CanSplitByRange(key tasks.Key) bool {
155 }
156
157 > func (s *SliceImpl) CanMergeWithSlice(slice Slice) bool { slice.go
158 > s.stateSanityCheck()
159 >
160 > return s != slice && s.scope.Range.CanMerge(slice.Scope().Range)
161 > }
162
163 > func (s *SliceImpl) MergeWithSlice(slice Slice) []Slice { slice.go
164 > if s.scope.Range.InclusiveMin.CompareTo(slice.Scope().Range.InclusiveMin) > 0 {
165 return slice.MergeWithSlice(s)
166 }
167
168 > if !s.CanMergeWithSlice(slice) { slice.go
169 panic(fmt.Sprintf("Unable to merge queue slice having scope %v with slice having scope %v", s.scope, slice.Scope()))
170 }
171
172 > incomingSlice, ok := slice.(*SliceImpl) slice.go
173 > if !ok {
174 panic(fmt.Sprintf("Unable to merge queue slice of type %T with type %T", s, slice))
175 }
176
177 > if s.scope.CanMergeByRange(incomingSlice.scope) { slice.go
178 > return []Slice{s.mergeByRange(incomingSlice)} slice.go
179 > }
180
181 mergedSlices := make([]Slice, 0, 3)
199 }
200
201 > func (s *SliceImpl) mergeByRange(incomingSlice *SliceImpl) *SliceImpl { slice.go
202 > mergedTaskTracker := s.merge(incomingSlice.executableTracker)
203 > mergedIterators := s.mergeIterators(incomingSlice)
204 >
205 > s.destroy()
206 > incomingSlice.destroy()
207 >
208 > return s.newSlice(
209 > s.scope.MergeByRange(incomingSlice.scope),
210 > mergedIterators,
211 > mergedTaskTracker,
212 > )
213 > }
214
215 func (s *SliceImpl) mergeByPredicate(incomingSlice *SliceImpl) *SliceImpl {
227 }
228
229 > func (s *SliceImpl) mergeIterators(incomingSlice *SliceImpl) []Iterator { slice.go
230 > mergedIterators := make([]Iterator, 0, len(s.iterators)+len(incomingSlice.iterators))
231 > currentIterIdx := 0
232 > incomingIterIdx := 0
233 > for currentIterIdx < len(s.iterators) && incomingIterIdx < len(incomingSlice.iterators) {
234 currentIter := s.iterators[currentIterIdx]
235 incomingIter := incomingSlice.iterators[incomingIterIdx]
244 }
245
246 > for _, iterator := range s.iterators[currentIterIdx:] { slice.go
247 mergedIterators = s.appendIterator(mergedIterators, iterator)
248 }
249 > for _, iterator := range incomingSlice.iterators[incomingIterIdx:] { slice.go
250 > mergedIterators = s.appendIterator(mergedIterators, iterator) slice.go
251 > }
252
253 > validateIteratorsOrderedDisjoint(mergedIterators) slice.go
254 >
255 > return mergedIterators
256 }
257
259 iterators []Iterator,
260 iterator Iterator,
261 > ) []Iterator { slice.go
262 > if len(iterators) == 0 {
263 > return []Iterator{iterator}
264 > }
265
266 size := len(iterators)
360 }
361
362 > func (s *SliceImpl) SelectTasks(readerID int64, batchSize int) ([]Executable, error) { slice.go
363 > s.stateSanityCheck()
364 >
365 > if len(s.iterators) == 0 {
366 return []Executable{}, nil
367 }
368
369 > defer func() { slice.go
370 > s.monitor.SetSlicePendingTaskCount(s, len(s.pendingExecutables))
371 > }()
372
373 > executables := make([]Executable, 0, batchSize) slice.go
374 > for len(executables) < batchSize && len(s.iterators) != 0 {
375 > if s.iterators[0].HasNext() {
376 > task, err := s.iterators[0].Next() slice.go
377 > if err != nil {
378 > s.iterators[0] = s.iterators[0].Remaining() slice.go
379 > if len(executables) != 0 {
380 // NOTE: we must return the executables here
381 // MoreTasks() will return true so queue reader will try to load again
382 return executables, nil
383 }
384 > return nil, err slice.go
385 }
386
387 > taskKey := task.GetKey() slice.go
388 > if !s.scope.Range.ContainsKey(taskKey) {
389 panic(fmt.Sprintf("Queue slice get task from iterator doesn't belong to its range, range: %v, task key %v",
390 s.scope.Range, taskKey))
391 }
392
393 > if !s.scope.Predicate.Test(task) { slice.go
394 continue
395 }
396
397 > executable := s.executableFactory.NewExecutable(task, readerID) slice.go
398 > s.add(executable)
399 > executables = append(executables, executable)
400 > } else { slice.go
401 > s.iterators = s.iterators[1:]
402 > }
403 }
404
405 > return executables, nil slice.go
406 }
407
408 > func (s *SliceImpl) MoreTasks() bool { slice.go
409 > s.stateSanityCheck()
410 >
411 > return len(s.iterators) != 0
412 > }
413
414 func (s *SliceImpl) TaskStats() TaskStats {
433 }
434
435 > func (s *SliceImpl) destroy() { slice.go
436 > s.destroyed = true
437 > s.iterators = nil
438 > s.executableTracker = nil
439 > s.monitor.RemoveSlice(s)
440 > }
441
442 > func (s *SliceImpl) stateSanityCheck() { slice.go
443 > if s.destroyed {
444 panic("Can not invoke method on destroyed queue slice")
445 }
450 iterators []Iterator,
451 tracker *executableTracker,
452 > ) *SliceImpl { slice.go
453 > slice := &SliceImpl{
454 > paginationFnProvider: s.paginationFnProvider,
455 > executableFactory: s.executableFactory,
456 > scope: scope,
457 > iterators: iterators,
458 > executableTracker: tracker,
459 > monitor: s.monitor,
460 > maxPredicateSizeFn: s.maxPredicateSizeFn,
461 > maxPendingKeysFn: s.maxPendingKeysFn,
462 > metricsHandler: s.metricsHandler,
463 > }
464 > slice.ensurePredicateSizeLimit()
465 > slice.monitor.SetSlicePendingTaskCount(slice, len(slice.pendingExecutables))
466 >
467 > return slice
468 > }
469
470 > func (s *SliceImpl) ensurePredicateSizeLimit() { slice.go
471 > maxPredicateSize := s.maxPredicateSizeFn()
472 > // 0 == unlimited
473 > if maxPredicateSize > 0 && s.scope.Predicate.Size() > maxPredicateSize {
474 // Due to the limitations in predicate merging logic, the predicate size can easily grow unbounded.
475 // The simplest mitigation is to stop merging and replace with the univeral predicate.
496 func validateIteratorsOrderedDisjoint(
497 iterators []Iterator,
498 > ) { slice.go
499 > if len(iterators) <= 1 {
500 > return slice.go
501 > }
502
503 for idx, iterator := range iterators[:len(iterators)-1] {
go.temporal.io/server/common/rpc/interceptor/telemetry.go 125 covered LOC · 47 ranges

Open complete file

101 logAllReqErrors dynamicconfig.BoolPropertyFnWithNamespaceFilter,
102 requestErrorHandler ErrorHandler,
103 > ) *TelemetryInterceptor { telemetry.go
104 > return &TelemetryInterceptor{
105 > namespaceRegistry: namespaceRegistry,
106 > metricsHandler: metricsHandler,
107 > logger: logger,
108 > workflowTags: logtags.NewWorkflowTags(tasktoken.NewSerializer(), logger),
109 > logAllReqErrors: logAllReqErrors,
110 > requestErrorHandler: requestErrorHandler,
111 > }
112 > }
113
114 // telemetryUnaryOverrideOperationTag is used to override scope used for reporting a metric.
115 // Ideally this method should never be used.
116 > func telemetryUnaryOverrideOperationTag(fullName, operation string, req any) string { telemetry.go
117 > if strings.HasPrefix(fullName, api.WorkflowServicePrefix) {
118 > // GetWorkflowExecutionHistory method handles both long poll and regular calls. telemetry.go
119 > // Current plan is to eventually split GetWorkflowExecutionHistory into two APIs,
120 > // remove this "if" case when that is done.
121 > if operation == metrics.FrontendGetWorkflowExecutionHistoryScope {
122 > if request, ok := req.(*workflowservice.GetWorkflowExecutionHistoryRequest); ok { telemetry.go
123 > if request.GetWaitNewEvent() {
124 > return metrics.FrontendPollWorkflowExecutionHistoryScope telemetry.go
125 > }
126 }
127 }
128 > return operation telemetry.go
129 > } else if strings.HasPrefix(fullName, api.HistoryServicePrefix) { telemetry.go
130 > // Special handling for Nexus operations to include service and operation in metric tag since the API is generic for all Nexus operations. telemetry.go
131 > if request, ok := req.(*historyservice.StartNexusOperationRequest); ok {
132 return "StartNexusOperation_" + request.GetRequest().GetService() + "_" + request.GetRequest().GetOperation()
133 }
134 > if request, ok := req.(*historyservice.CancelNexusOperationRequest); ok { telemetry.go
135 return "CancelNexusOperation_" + request.GetRequest().GetService() + "_" + request.GetRequest().GetOperation()
136 }
138 // Current plan is to eventually split GetWorkflowExecutionHistory into two APIs,
139 // remove this "if" case when that is done.
140 > if operation == metrics.HistoryGetWorkflowExecutionHistoryScope { telemetry.go
141 > if request, ok := req.(*historyservice.GetWorkflowExecutionHistoryRequest); ok {
142 > if r := request.GetRequest(); r != nil && r.GetWaitNewEvent() {
143 > return metrics.HistoryPollWorkflowExecutionHistoryScope telemetry.go
144 > }
145 }
146 }
147 }
148 > return telemetryOverrideOperationTag(fullName, operation) telemetry.go
149 }
150
151 // telemetryOverrideOperationTag is used to override scope used for reporting a metric.
152 // Ideally this method should never be used.
153 > func telemetryOverrideOperationTag(fullName, operation string) string { telemetry.go
154 > // prepend Operator prefix to Operator APIs
155 > if strings.HasPrefix(fullName, api.OperatorServicePrefix) {
156 return "Operator" + operation
157 }
158 // prepend Admin prefix to Admin APIs
159 > if strings.HasPrefix(fullName, api.AdminServicePrefix) { telemetry.go
160 > return "Admin" + operation telemetry.go
161 > }
162 > return operation telemetry.go
163 }
164
168 info *grpc.UnaryServerInfo,
169 handler grpc.UnaryHandler,
170 > ) (any, error) { telemetry.go
171 > methodName := api.MethodName(info.FullMethod)
172 > nsName := MustGetNamespaceName(ti.namespaceRegistry, req)
173 >
174 > metricsHandler, logTags := ti.unaryMetricsHandlerLogTags(req, info.FullMethod, methodName, nsName)
175 >
176 > ctx = AddTelemetryContext(ctx, metricsHandler)
177 > metrics.ServiceRequests.With(metricsHandler).Record(1)
178 >
179 > startTime := time.Now().UTC()
180 > defer func() {
181 > ti.RecordLatencyMetrics(ctx, startTime, metricsHandler)
182 > }()
183
184 > resp, err := handler(ctx, req) telemetry.go
185 >
186 > if configs.IsAPIOperation(info.FullMethod) {
187 > metrics.OperationCounter.With(metricsHandler).Record( telemetry.go
188 > 1,
189 > metrics.TaskTypeTag(""), // Added to make tags consistent with history task executor.
190 > )
191 > }
192
193 > if err != nil { telemetry.go
194 > ti.requestErrorHandler.HandleError(req, info.FullMethod, metricsHandler, logTags, err, nsName) telemetry.go
195 > } else { telemetry.go
196 > // emit action metrics only after successful calls
197 > ti.emitActionMetric(methodName, info.FullMethod, req, metricsHandler, resp)
198 > }
199
200 > return resp, err telemetry.go
201 }
202
203 > func AddTelemetryContext(ctx context.Context, metricsHandler metrics.Handler) context.Context { telemetry.go
204 > return context.WithValue(ctx, metricsCtxKey, metricsHandler)
205 > }
206
207 > func (ti *TelemetryInterceptor) RecordLatencyMetrics(ctx context.Context, startTime time.Time, metricsHandler metrics.Handler) { telemetry.go
208 > userLatencyDuration := time.Duration(0)
209 > if val, ok := metrics.ContextCounterGet(ctx, metrics.HistoryWorkflowExecutionCacheLatency.Name()); ok {
210 > userLatencyDuration = time.Duration(val) telemetry.go
211 > metrics.ServiceLatencyUserLatency.With(metricsHandler).Record(userLatencyDuration)
212 > }
213
214 > latency := time.Since(startTime) telemetry.go
215 > metrics.ServiceLatency.With(metricsHandler).Record(latency)
216 > noUserLatency := max(0, latency-userLatencyDuration)
217 > metrics.ServiceLatencyNoUserLatency.With(metricsHandler).Record(noUserLatency)
218 }
219
242 metricsHandler metrics.Handler,
243 result any,
244 > ) { telemetry.go
245 > if _, ok := grpcActions[methodName]; !ok || !strings.HasPrefix(fullName, api.WorkflowServicePrefix) {
246 > // grpcActions checks that methodName is the one that we care about, and we only care about WorkflowService. telemetry.go
247 > return
248 > }
249
250 > switch methodName { telemetry.go
251 > case startWorkflowExecution: telemetry.go
252 > resp, ok := result.(*workflowservice.StartWorkflowExecutionResponse)
253 > if !ok {
254 return
255 }
256 > if resp.Started { telemetry.go
257 > metrics.ActionCounter.With(metricsHandler).Record(1, metrics.ActionType("grpc_"+methodName)) telemetry.go
258 > } else { telemetry.go
259 typedReq, ok := req.(*workflowservice.StartWorkflowExecutionRequest)
260 if ok && typedReq.GetWorkflowIdConflictPolicy() == enumspb.WORKFLOW_ID_CONFLICT_POLICY_USE_EXISTING && typedReq.GetOnConflictOptions() != nil {
284 }
285 }
286 > case respondWorkflowTaskCompleted: telemetry.go
287 > // handle commands
288 > completedRequest, ok := req.(*workflowservice.RespondWorkflowTaskCompletedRequest)
289 > if !ok {
290 return
291 }
292
293 > hasMarker := false telemetry.go
294 > for _, command := range completedRequest.Commands {
295 > if _, ok := commandActions[command.CommandType]; !ok { telemetry.go
296 > continue telemetry.go
297 }
298
311 }
312
313 > if hasMarker { telemetry.go
314 // Emit separate action metric for batch of markers.
315 // One workflow task response may contain multiple marker commands. Each marker will emit one
319 }
320
321 > for _, msg := range completedRequest.Messages { telemetry.go
322 if msg == nil || msg.Body == nil {
323 continue
333 }
334
335 > case pollActivityTaskQueue: telemetry.go
336 > // handle activity retries
337 > activityPollResponse, ok := result.(*workflowservice.PollActivityTaskQueueResponse)
338 > if !ok {
339 return
340 }
341 > if activityPollResponse == nil || len(activityPollResponse.TaskToken) == 0 { telemetry.go
342 > // empty response
343 > return
344 > }
345 if activityPollResponse.Attempt > 1 {
346 metrics.ActionCounter.With(metricsHandler).Record(1, metrics.ActionType("activity_retry"))
371 methodName string,
372 nsName namespace.Name,
373 > ) (metrics.Handler, []tag.Tag) { telemetry.go
374 > overridedMethodName := telemetryUnaryOverrideOperationTag(fullMethod, methodName, req)
375 >
376 > if nsName == "" {
377 > return baseMetricsHandler.WithTags(metrics.OperationTag(overridedMethodName), metrics.NamespaceUnknownTag()),
378 > []tag.Tag{tag.Operation(overridedMethodName)}
379 > }
380 > return baseMetricsHandler.WithTags(metrics.OperationTag(overridedMethodName), metrics.NamespaceTag(nsName.String())), telemetry.go
381 > []tag.Tag{tag.Operation(overridedMethodName), tag.WorkflowNamespace(nsName.String())}
382 }
383
385 fullMethod string,
386 methodName string,
387 > nsName namespace.Name) (metrics.Handler, []tag.Tag) { telemetry.go
388 > return CreateUnaryMetricsHandlerLogTags(ti.metricsHandler, req, fullMethod, methodName, nsName)
389 > }
390
391 func (ti *TelemetryInterceptor) streamMetricsHandlerLogTags(
403 ctx context.Context,
404 logger log.Logger,
405 > ) metrics.Handler { telemetry.go
406 > handler, ok := ctx.Value(metricsCtxKey).(metrics.Handler)
407 > if !ok {
408 logger.Error("unable to get metrics scope")
409 return metrics.NoopMetricsHandler
410 }
411 > return handler telemetry.go
412 }
go.temporal.io/server/common/persistence/sql/execution_tasks.go 124 covered LOC · 35 ranges

Open complete file

35 ctx context.Context,
36 request *p.GetHistoryTasksRequest,
37 > ) (*p.InternalGetHistoryTasksResponse, error) { execution_tasks.go
38 > switch request.TaskCategory.Type() {
39 > case tasks.CategoryTypeImmediate: execution_tasks.go
40 > return m.getHistoryImmediateTasks(ctx, request)
41 > case tasks.CategoryTypeScheduled: execution_tasks.go
42 > return m.getHistoryScheduledTasks(ctx, request)
43 default:
44 return nil, serviceerror.NewInternalf("Unknown task category type: %v", request.TaskCategory)
81 ctx context.Context,
82 request *p.GetHistoryTasksRequest,
83 > ) (*p.InternalGetHistoryTasksResponse, error) { execution_tasks.go
84 > // This is for backward compatiblity.
85 > // These task categories exist before the general history_immediate_tasks table is created,
86 > // so they have their own tables.
87 > categoryID := request.TaskCategory.ID()
88 > switch categoryID {
89 > case tasks.CategoryIDTransfer: execution_tasks.go
90 > return m.getTransferTasks(ctx, request)
91 > case tasks.CategoryIDVisibility: execution_tasks.go
92 > return m.getVisibilityTasks(ctx, request)
93 case tasks.CategoryIDReplication:
94 return m.getReplicationTasks(ctx, request)
95 }
96
97 > inclusiveMinTaskID, exclusiveMaxTaskID, err := getImmediateTaskReadRange(request) execution_tasks.go
98 > if err != nil {
99 return nil, err
100 }
101
102 > rows, err := m.DB.RangeSelectFromHistoryImmediateTasks(ctx, sqlplugin.HistoryImmediateTasksRangeFilter{ execution_tasks.go
103 > ShardID: request.ShardID,
104 > CategoryID: int32(categoryID),
105 > InclusiveMinTaskID: inclusiveMinTaskID,
106 > ExclusiveMaxTaskID: exclusiveMaxTaskID,
107 > PageSize: request.BatchSize,
108 > })
109 > if err != nil {
110 if err != sql.ErrNoRows {
111 return nil, serviceerror.NewUnavailablef(
114 }
115 }
116 > resp := &p.InternalGetHistoryTasksResponse{ execution_tasks.go
117 > Tasks: make([]p.InternalHistoryTask, len(rows)),
118 > }
119 > if len(rows) == 0 {
120 > return resp, nil
121 > }
122
123 for i, row := range rows {
199 ctx context.Context,
200 request *p.GetHistoryTasksRequest,
201 > ) (*p.InternalGetHistoryTasksResponse, error) { execution_tasks.go
202 > // This is for backward compatiblity.
203 > // These task categories exist before the general history_scheduled_tasks table is created,
204 > // so they have their own tables.
205 > categoryID := request.TaskCategory.ID()
206 > if categoryID == tasks.CategoryIDTimer {
207 > return m.getTimerTasks(ctx, request) execution_tasks.go
208 > }
209
210 > pageToken := &scheduledTaskPageToken{TaskID: math.MinInt64, Timestamp: request.InclusiveMinTaskKey.FireTime} execution_tasks.go
211 > if len(request.NextPageToken) > 0 {
212 if err := pageToken.deserialize(request.NextPageToken); err != nil {
213 return nil, serviceerror.NewInternalf(
217 }
218
219 > rows, err := m.DB.RangeSelectFromHistoryScheduledTasks(ctx, sqlplugin.HistoryScheduledTasksRangeFilter{ execution_tasks.go
220 > ShardID: request.ShardID,
221 > CategoryID: int32(categoryID),
222 > InclusiveMinVisibilityTimestamp: pageToken.Timestamp,
223 > InclusiveMinTaskID: pageToken.TaskID,
224 > ExclusiveMaxVisibilityTimestamp: request.ExclusiveMaxTaskKey.FireTime,
225 > PageSize: request.BatchSize,
226 > })
227 >
228 > if err != nil && err != sql.ErrNoRows {
229 return nil, serviceerror.NewUnavailablef(
230 "GetHistoryTasks operation failed. Select failed. CategoryID: %v. Error: %v", categoryID, err,
232 }
233
234 > resp := &p.InternalGetHistoryTasksResponse{Tasks: make([]p.InternalHistoryTask, 0, len(rows))} execution_tasks.go
235 > for _, row := range rows {
236 resp.Tasks = append(resp.Tasks, p.InternalHistoryTask{
237 Key: tasks.NewKey(row.VisibilityTimestamp, row.TaskID),
240 }
241
242 > if len(resp.Tasks) == request.BatchSize { execution_tasks.go
243 pageToken = &scheduledTaskPageToken{
244 TaskID: rows[request.BatchSize-1].TaskID + 1,
306 ctx context.Context,
307 request *p.GetHistoryTasksRequest,
308 > ) (*p.InternalGetHistoryTasksResponse, error) { execution_tasks.go
309 > inclusiveMinTaskID, exclusiveMaxTaskID, err := getImmediateTaskReadRange(request)
310 > if err != nil {
311 return nil, err
312 }
313
314 > rows, err := m.DB.RangeSelectFromTransferTasks(ctx, sqlplugin.TransferTasksRangeFilter{ execution_tasks.go
315 > ShardID: request.ShardID,
316 > InclusiveMinTaskID: inclusiveMinTaskID,
317 > ExclusiveMaxTaskID: exclusiveMaxTaskID,
318 > PageSize: request.BatchSize,
319 > })
320 > if err != nil {
321 if err != sql.ErrNoRows {
322 return nil, serviceerror.NewUnavailablef("GetTransferTasks operation failed. Select failed. Error: %v", err)
323 }
324 }
325 > resp := &p.InternalGetHistoryTasksResponse{ execution_tasks.go
326 > Tasks: make([]p.InternalHistoryTask, len(rows)),
327 > }
328 > if len(rows) == 0 {
329 > return resp, nil execution_tasks.go
330 > }
331
332 > for i, row := range rows { execution_tasks.go
333 > resp.Tasks[i] = p.InternalHistoryTask{
334 > Key: tasks.NewImmediateKey(row.TaskID),
335 > Blob: p.NewDataBlob(row.Data, row.DataEncoding),
336 > }
337 > }
338 > if len(rows) == request.BatchSize {
339 resp.NextPageToken = getImmediateTaskNextPageToken(
340 rows[len(rows)-1].TaskID,
376 ctx context.Context,
377 request *p.GetHistoryTasksRequest,
378 > ) (*p.InternalGetHistoryTasksResponse, error) { execution_tasks.go
379 > pageToken := &scheduledTaskPageToken{TaskID: math.MinInt64, Timestamp: request.InclusiveMinTaskKey.FireTime}
380 > if len(request.NextPageToken) > 0 {
381 if err := pageToken.deserialize(request.NextPageToken); err != nil {
382 return nil, serviceerror.NewInternalf("error deserializing timerTaskPageToken: %v", err)
384 }
385
386 > rows, err := m.DB.RangeSelectFromTimerTasks(ctx, sqlplugin.TimerTasksRangeFilter{ execution_tasks.go
387 > ShardID: request.ShardID,
388 > InclusiveMinVisibilityTimestamp: pageToken.Timestamp,
389 > InclusiveMinTaskID: pageToken.TaskID,
390 > ExclusiveMaxVisibilityTimestamp: request.ExclusiveMaxTaskKey.FireTime,
391 > PageSize: request.BatchSize,
392 > })
393 >
394 > if err != nil && err != sql.ErrNoRows {
395 return nil, serviceerror.NewUnavailablef("GetTimerTasks operation failed. Select failed. Error: %v", err)
396 }
397
398 > resp := &p.InternalGetHistoryTasksResponse{Tasks: make([]p.InternalHistoryTask, 0, len(rows))} execution_tasks.go
399 > for _, row := range rows {
400 resp.Tasks = append(resp.Tasks, p.InternalHistoryTask{
401 Key: tasks.NewKey(row.VisibilityTimestamp, row.TaskID),
404 }
405
406 > if len(resp.Tasks) == request.BatchSize { execution_tasks.go
407 pageToken = &scheduledTaskPageToken{
408 TaskID: rows[request.BatchSize-1].TaskID + 1,
477 func getImmediateTaskReadRange(
478 request *p.GetHistoryTasksRequest,
479 > ) (inclusiveMinTaskID int64, exclusiveMaxTaskID int64, err error) { execution_tasks.go
480 > inclusiveMinTaskID = request.InclusiveMinTaskKey.TaskID
481 > if len(request.NextPageToken) > 0 {
482 inclusiveMinTaskID, err = deserializePageToken(request.NextPageToken)
483 if err != nil {
486 }
487
488 > return inclusiveMinTaskID, request.ExclusiveMaxTaskKey.TaskID, nil execution_tasks.go
489 }
490
693 ctx context.Context,
694 request *p.GetHistoryTasksRequest,
695 > ) (*p.InternalGetHistoryTasksResponse, error) { execution_tasks.go
696 > inclusiveMinTaskID, exclusiveMaxTaskID, err := getImmediateTaskReadRange(request)
697 > if err != nil {
698 return nil, err
699 }
700
701 > rows, err := m.DB.RangeSelectFromVisibilityTasks(ctx, sqlplugin.VisibilityTasksRangeFilter{ execution_tasks.go
702 > ShardID: request.ShardID,
703 > InclusiveMinTaskID: inclusiveMinTaskID,
704 > ExclusiveMaxTaskID: exclusiveMaxTaskID,
705 > PageSize: request.BatchSize,
706 > })
707 > if err != nil {
708 if err != sql.ErrNoRows {
709 return nil, serviceerror.NewUnavailablef("GetVisibilityTasks operation failed. Select failed. Error: %v", err)
710 }
711 }
712 > resp := &p.InternalGetHistoryTasksResponse{ execution_tasks.go
713 > Tasks: make([]p.InternalHistoryTask, len(rows)),
714 > }
715 > if len(rows) == 0 {
716 > return resp, nil execution_tasks.go
717 > }
718
719 > for i, row := range rows { execution_tasks.go
720 > resp.Tasks[i] = p.InternalHistoryTask{
721 > Key: tasks.NewImmediateKey(row.TaskID),
722 > Blob: p.NewDataBlob(row.Data, row.DataEncoding),
723 > }
724 > }
725 > if len(rows) == request.BatchSize {
726 resp.NextPageToken = getImmediateTaskNextPageToken(
727 rows[len(rows)-1].TaskID,
go.temporal.io/server/service/matching/fx.go 124 covered LOC · 19 ranges

Open complete file

56 )
57
58 > func ServerProvider(grpcServerOptions []grpc.ServerOption) *grpc.Server { fx.go
59 > return grpc.NewServer(grpcServerOptions...)
60 > }
61
62 func ConfigProvider(
64 persistenceConfig config.Persistence,
65 rateLimitFractionProvider TaskQueueRateLimitFractionProvider,
66 > ) *Config { fx.go
67 > cfg := NewConfig(dc)
68 > cfg.RateLimitFractionProvider = rateLimitFractionProvider
69 > return cfg
70 > }
71
72 func ServiceErrorInterceptorProvider(
73 dc *dynamicconfig.Collection,
74 > ) *interceptor.ServiceErrorInterceptor { fx.go
75 > return interceptor.NewServiceErrorInterceptor(
76 > dynamicconfig.MaxServiceErrorMessageLength.Get(dc),
77 > )
78 > }
79
80 > func RetryableInterceptorProvider() *interceptor.RetryableInterceptor { fx.go
81 > return interceptor.NewRetryableInterceptor(
82 > common.CreateMatchingHandlerRetryPolicy(),
83 > common.IsServiceHandlerRetryableError,
84 > )
85 > }
86
87 func ErrorHandlerProvider(
88 logger log.Logger,
89 serviceConfig *Config,
90 > ) *interceptor.RequestErrorHandler { fx.go
91 > return interceptor.NewRequestErrorHandler(
92 > logger,
93 > serviceConfig.LogAllReqErrors,
94 > )
95 > }
96
97 func TelemetryInterceptorProvider(
101 serviceConfig *Config,
102 requestErrorHandler *interceptor.RequestErrorHandler,
103 > ) *interceptor.TelemetryInterceptor { fx.go
104 > return interceptor.NewTelemetryInterceptor(
105 > namespaceRegistry,
106 > metricsHandler,
107 > logger,
108 > serviceConfig.LogAllReqErrors,
109 > requestErrorHandler,
110 > )
111 > }
112
113 > func ThrottledLoggerRpsFnProvider(serviceConfig *Config) resource.ThrottledLoggerRpsFn { fx.go
114 > return func() float64 { return float64(serviceConfig.ThrottledLogRPS()) }
115 }
116
119 namespaceRegistry namespace.Registry,
120 metricsHandler metrics.Handler,
121 > ) interceptor.NamespaceRateLimitInterceptor { fx.go
122 >
123 > namespaceRateFn := func(namespaceName string) float64 {
124 > if namespaceRPS := serviceConfig.NamespaceRPS(namespaceName); namespaceRPS > 0 { fx.go
125 return float64(namespaceRPS)
126 }
127 // This fallback to host level rps limit when NamespaceRPS is not configured (i.e. 0)
128 > return float64(serviceConfig.RPS()) fx.go
129 }
130
131 > return interceptor.NewNamespaceRateLimitInterceptor( fx.go
132 > namespaceRegistry,
133 > configs.NewNamespaceRateLimiter(
134 > namespaceRateFn,
135 > serviceConfig.OperatorRPSRatio,
136 > ),
137 > map[string]int{}, // no token overrides
138 > configs.PollTaskAPISet, // set of APIs that will wait for token instead of immediate rejection
139 > serviceConfig.PollWaitForNamespaceRateLimitToken,
140 > metricsHandler,
141 > )
142 }
143
144 func RateLimitInterceptorProvider(
145 serviceConfig *Config,
146 > ) *interceptor.RateLimitInterceptor { fx.go
147 > return interceptor.NewRateLimitInterceptor(
148 > configs.NewPriorityRateLimiter(func() float64 { return float64(serviceConfig.RPS()) }, serviceConfig.OperatorRPSRatio),
149 map[string]int{
150 healthpb.Health_Check_FullMethodName: 0, // exclude health check requests from rate limiting.
159 persistenceLazyLoadedServiceResolver service.PersistenceLazyLoadedServiceResolver,
160 logger log.SnTaggedLogger,
161 > ) service.PersistenceRateLimitingParams { fx.go
162 > return service.NewPersistenceRateLimitingParams(
163 > serviceConfig.PersistenceMaxQPS,
164 > serviceConfig.PersistenceGlobalMaxQPS,
165 > serviceConfig.PersistenceNamespaceMaxQPS,
166 > serviceConfig.PersistenceGlobalNamespaceMaxQPS,
167 > serviceConfig.PersistencePerShardNamespaceMaxQPS,
168 > serviceConfig.OperatorRPSRatio,
169 > serviceConfig.PersistenceQPSBurstRatio,
170 > serviceConfig.PersistenceDynamicRateLimitingParams,
171 > persistenceLazyLoadedServiceResolver,
172 > logger,
173 > )
174 > }
175
176 func ServiceResolverProvider(
177 membershipMonitor membership.Monitor,
178 > ) (membership.ServiceResolver, error) { fx.go
179 > return membershipMonitor.GetResolver(primitives.MatchingService)
180 > }
181
182 // TaskQueueReplicatorNamespaceReplicationQueue is used to ensure the replicator only gets set if global namespaces are
207 chasmRegistry *chasm.Registry,
208 serializer serialization.Serializer,
209 > ) (manager.VisibilityManager, error) { fx.go
210 > return visibility.NewManager(
211 > *persistenceConfig,
212 > persistenceServiceResolver,
213 > customVisibilityStoreFactory,
214 > nil, // matching visibility never writes
215 > saProvider,
216 > searchAttributesMapperProvider,
217 > namespaceRegistry,
218 > chasmRegistry,
219 > serviceConfig.VisibilityPersistenceMaxReadQPS,
220 > serviceConfig.VisibilityPersistenceMaxWriteQPS,
221 > serviceConfig.OperatorRPSRatio,
222 > serviceConfig.VisibilityPersistenceSlowQueryThreshold,
223 > serviceConfig.EnableReadFromSecondaryVisibility,
224 > serviceConfig.VisibilityEnableShadowReadMode,
225 > dynamicconfig.GetStringPropertyFn(visibility.SecondaryVisibilityWritingModeOff), // matching visibility never writes
226 > serviceConfig.VisibilityDisableOrderByClause,
227 > serviceConfig.VisibilityEnableManualPagination,
228 > serviceConfig.VisibilityEnableUnifiedQueryConverter,
229 > metricsHandler,
230 > logger,
231 > serializer,
232 > )
233 > }
234
235 > func ContextMetadataInterceptorProvider(logger log.Logger) *interceptor.ContextMetadataInterceptor { fx.go
236 > return interceptor.NewContextMetadataInterceptor(true, logger)
237 > }
238
239 > func ServiceLifetimeHooks(lc fx.Lifecycle, svc *Service) { fx.go
240 > lc.Append(fx.StartStopHook(svc.Start, svc.Stop))
241 > }
242
243 func WorkersRegistryProvider(
245 metricsHandler metrics.Handler,
246 serviceConfig *Config,
247 > ) workers.Registry { fx.go
248 > return workers.NewRegistry(lc, workers.RegistryParams{
249 > NumBuckets: serviceConfig.WorkerRegistryNumBuckets,
250 > TTL: serviceConfig.WorkerRegistryEntryTTL,
251 > MinEvictAge: serviceConfig.WorkerRegistryMinEvictAge,
252 > MaxItems: serviceConfig.WorkerRegistryMaxEntries,
253 > EvictionInterval: serviceConfig.WorkerRegistryEvictionInterval,
254 > MetricsHandler: metricsHandler,
255 > MetricsConfig: workers.WorkerMetricsConfig{
256 > EnablePluginMetrics: serviceConfig.EnableWorkerPluginMetrics,
257 > EnablePollerAutoscalingMetrics: serviceConfig.EnablePollerAutoscalingMetrics,
258 > BreakdownMetricsByTaskQueue: serviceConfig.BreakdownMetricsByTaskQueue,
259 > ExternalPayloadsEnabled: serviceConfig.ExternalPayloadsEnabled,
260 > },
261 > })
262 > }
263
264 > func simplePartitionScalerFactoryProvider(dc *dynamicconfig.Collection) PartitionScalerFactory { fx.go
265 > return newSimplePartitionScalerFactory(
266 > dynamicconfig.MatchingPartitionScaler.Get(dc),
267 > )
268 > }
go.temporal.io/server/common/worker_versioning/worker_versioning.go 123 covered LOC · 62 ranges

Open complete file

114
115 // IsUnversionedOrAssignedBuildIdSearchAttribute returns the value is "unversioned" or "assigned:<bld>"
116 > func IsUnversionedOrAssignedBuildIdSearchAttribute(buildId string) bool { worker_versioning.go
117 > return buildId == UnversionedSearchAttribute ||
118 > strings.HasPrefix(buildId, buildIdSearchAttributePrefixAssigned+BuildIdSearchAttributeDelimiter)
119 > }
120
121 // VersionedBuildIdSearchAttribute returns the search attribute value for a versioned build ID
125
126 // UnversionedBuildIdSearchAttribute returns the search attribute value for an unversioned build ID
127 > func UnversionedBuildIdSearchAttribute(buildId string) string { worker_versioning.go
128 > return buildIdSearchAttributePrefixUnversioned + BuildIdSearchAttributeDelimiter + buildId
129 > }
130
131 // VersionStampToBuildIdSearchAttribute returns the search attribute value for a version stamp
132 > func VersionStampToBuildIdSearchAttribute(stamp *commonpb.WorkerVersionStamp) string { worker_versioning.go
133 > if stamp.GetBuildId() == "" {
134 return UnversionedSearchAttribute
135 }
136 > if stamp.UseVersioning { worker_versioning.go
137 return VersionedBuildIdSearchAttribute(stamp.BuildId)
138 }
139 > return UnversionedBuildIdSearchAttribute(stamp.BuildId) worker_versioning.go
140 }
141
181 // BuildIdIfUsingVersioning returns the given WorkerVersionStamp if it is using versioning,
182 // otherwise returns nil.
183 > func BuildIdIfUsingVersioning(stamp *commonpb.WorkerVersionStamp) string { worker_versioning.go
184 > if stamp.GetUseVersioning() {
185 return stamp.GetBuildId()
186 }
187 > return "" worker_versioning.go
188 }
189
190 // DeploymentFromCapabilities returns the deployment if it is using versioning V3, otherwise nil.
191 // It returns the deployment from the `options` if present, otherwise, from `capabilities`,
192 > func DeploymentFromCapabilities(capabilities *commonpb.WorkerVersionCapabilities, options *deploymentpb.WorkerDeploymentOptions) (*deploymentpb.Deployment, error) { worker_versioning.go
193 > if options.GetWorkerVersioningMode() == enumspb.WORKER_VERSIONING_MODE_VERSIONED {
194 d := options.GetDeploymentName()
195 b := options.GetBuildId()
209 }, nil
210 }
211 > if capabilities.GetUseVersioning() && capabilities.GetDeploymentSeriesName() != "" && capabilities.GetBuildId() != "" { worker_versioning.go
212 return &deploymentpb.Deployment{
213 SeriesName: capabilities.GetDeploymentSeriesName(),
232 }
233
234 > func DeploymentVersionFromOptions(options *deploymentpb.WorkerDeploymentOptions) *deploymentspb.WorkerDeploymentVersion { worker_versioning.go
235 > if options.GetWorkerVersioningMode() == enumspb.WORKER_VERSIONING_MODE_VERSIONED {
236 return &deploymentspb.WorkerDeploymentVersion{
237 DeploymentName: options.GetDeploymentName(),
239 }
240 }
241 > return nil worker_versioning.go
242 }
243
244 // DeploymentOrVersion Temporary helper function to return a Deployment based on passed Deployment
245 // or WorkerDeploymentVersion objects, if `v` is not nil, it'll take precedence.
246 > func DeploymentOrVersion(d *deploymentpb.Deployment, v *deploymentspb.WorkerDeploymentVersion) *deploymentpb.Deployment { worker_versioning.go
247 > if v != nil {
248 return DeploymentIfValid(DeploymentFromDeploymentVersion(v))
249 }
250 > return DeploymentIfValid(d) worker_versioning.go
251 }
252
253 // DeploymentIfValid returns the deployment back if is both of its fields have value.
254 > func DeploymentIfValid(d *deploymentpb.Deployment) *deploymentpb.Deployment { worker_versioning.go
255 > if d.GetSeriesName() != "" && d.GetBuildId() != "" {
256 return d
257 }
258 > return nil worker_versioning.go
259 }
260
275 revisionNumber int64,
276 useRampingVersion bool,
277 > ) *taskqueuespb.TaskVersionDirective { worker_versioning.go
278 > if behavior != enumspb.VERSIONING_BEHAVIOR_UNSPECIFIED {
279 return &taskqueuespb.TaskVersionDirective{
280 Behavior: behavior,
284 }
285 }
286 > if id := BuildIdIfUsingVersioning(stamp); id != "" && assignedBuildId == "" { worker_versioning.go
287 // TODO: old versioning only [cleanup-old-wv]
288 return MakeBuildIdDirective(id)
289 > } else if !hasCompletedWorkflowTask && inheritedBuildId == "" { worker_versioning.go
290 > // first workflow task (or a retry of) and build ID not inherited. if this is retry we reassign build ID worker_versioning.go
291 > // if WF has an inherited build ID, we do not allow usage of assignment rules
292 > return MakeUseAssignmentRulesDirective()
293 > } else if assignedBuildId != "" { worker_versioning.go
294 return MakeBuildIdDirective(assignedBuildId)
295 }
478 // DeploymentVersionFromDeployment Temporary helper function to convert Deployment to
479 // WorkerDeploymentVersion proto until we update code to use the new proto in all places.
480 > func DeploymentVersionFromDeployment(deployment *deploymentpb.Deployment) *deploymentspb.WorkerDeploymentVersion { worker_versioning.go
481 > if deployment == nil {
482 > return nil worker_versioning.go
483 > }
484 return &deploymentspb.WorkerDeploymentVersion{
485 BuildId: deployment.GetBuildId(),
490 // ExternalWorkerDeploymentVersionFromDeployment Temporary helper function to convert Deployment to
491 // WorkerDeploymentVersion proto until we update code to use the new proto in all places.
492 > func ExternalWorkerDeploymentVersionFromDeployment(deployment *deploymentpb.Deployment) *deploymentpb.WorkerDeploymentVersion { worker_versioning.go
493 > if deployment == nil {
494 > return nil worker_versioning.go
495 > }
496 return &deploymentpb.WorkerDeploymentVersion{
497 BuildId: deployment.GetBuildId(),
502 // ExternalWorkerDeploymentVersionFromVersion Temporary helper function to convert internal Worker Deployment to
503 // WorkerDeploymentVersion proto until we update code to use the new proto in all places.
504 > func ExternalWorkerDeploymentVersionFromVersion(version *deploymentspb.WorkerDeploymentVersion) *deploymentpb.WorkerDeploymentVersion { worker_versioning.go
505 > if version == nil {
506 > return nil worker_versioning.go
507 > }
508 return &deploymentpb.WorkerDeploymentVersion{
509 BuildId: version.GetBuildId(),
526 // DeploymentFromDeploymentVersion Temporary helper function to convert WorkerDeploymentVersion to
527 // Deployment proto until we update code to use the new proto in all places.
528 > func DeploymentFromDeploymentVersion(dv *deploymentspb.WorkerDeploymentVersion) *deploymentpb.Deployment { worker_versioning.go
529 > if dv == nil {
530 > return nil worker_versioning.go
531 > }
532 return &deploymentpb.Deployment{
533 BuildId: dv.GetBuildId(),
536 }
537
538 > func MakeUseAssignmentRulesDirective() *taskqueuespb.TaskVersionDirective { worker_versioning.go
539 > return &taskqueuespb.TaskVersionDirective{BuildId: &taskqueuespb.TaskVersionDirective_UseAssignmentRules{UseAssignmentRules: &emptypb.Empty{}}}
540 > }
541
542 func MakeBuildIdDirective(buildId string) *taskqueuespb.TaskVersionDirective {
544 }
545
546 > func StampFromCapabilities(capabilities *commonpb.WorkerVersionCapabilities, options *deploymentpb.WorkerDeploymentOptions) *commonpb.WorkerVersionStamp { worker_versioning.go
547 > if options.GetWorkerVersioningMode() == enumspb.WORKER_VERSIONING_MODE_VERSIONED && options.GetDeploymentName() != "" {
548 // Versioning 3, do not return stamp.
549 return nil
550 }
551 > if capabilities.GetUseVersioning() && capabilities.GetDeploymentSeriesName() != "" { worker_versioning.go
552 // Versioning 3, do not return stamp.
553 return nil
556 // between old and new versioning in Record*TaskStart calls. [cleanup-old-wv]
557 // we don't want to add stamp for task started events in old versioning
558 > if capabilities.GetBuildId() != "" { worker_versioning.go
559 > return &commonpb.WorkerVersionStamp{UseVersioning: capabilities.UseVersioning, BuildId: capabilities.BuildId} worker_versioning.go
560 > }
561 return nil
562 }
749 }
750
751 > func ValidateVersioningOverrideStructure(override *workflowpb.VersioningOverride) error { worker_versioning.go
752 > if override == nil {
753 > return nil worker_versioning.go
754 > }
755
756 switch o := override.GetOverride().(type) { // v0.32
811 tq string,
812 tqType enumspb.TaskQueueType,
813 > namespaceID string) (shouldSkipReactivation bool, revisionNumber int64, err error) { worker_versioning.go
814 > if err := ValidateVersioningOverrideStructure(override); err != nil {
815 return false, 0, err
816 }
817 > if override == nil { worker_versioning.go
818 > return false, 0, nil worker_versioning.go
819 > }
820
821 // The following checks are for v0.32 protos of worker-versioning which may/may not require reactivation checks
850 workflowId string,
851 useRampingVersion bool,
852 > ) (*deploymentspb.WorkerDeploymentVersion, int64) { worker_versioning.go
853 > if useRampingVersion && ramping != nil {
854 return ramping, rampingRevisionNumber
855 }
856
857 // Apply ramp logic using final values
858 > if rampingPercentage <= 0 { worker_versioning.go
859 > // No ramp worker_versioning.go
860 > return current, currentRevisionNumber
861 > } else if rampingPercentage == 100 { worker_versioning.go
862 return ramping, rampingRevisionNumber
863 }
969 int64, // ramping revision number
970 time.Time, // ramping update time
972 > if deployments == nil {
973 > return nil, 0, time.Time{}, nil, false, 0, 0, time.Time{} worker_versioning.go
974 > }
975
976 var current *deploymentspb.DeploymentVersionData
1072 wfDeployment *deploymentpb.Deployment,
1073 scheduledDeployment *deploymentpb.Deployment,
1074 > ) error { worker_versioning.go
1075 > // TODO: consider using activity and wft Stamp for simplifying validation here.
1076 >
1077 > // Effective behavior and deployment of the workflow when History scheduled the WFT.
1078 > directiveBehavior := directive.GetBehavior()
1079 > if directiveBehavior != wfBehavior &&
1080 > // Verisoning 3 pre-release (v1.26, Dec 2024) is not populating request.VersionDirective so
1081 > // we skip this check until v1.28 if directiveBehavior is unspecified.
1082 > // TODO (shahab): remove this line after v1.27 is released.
1083 > directiveBehavior != enumspb.VERSIONING_BEHAVIOR_UNSPECIFIED {
1084 // This must be a task scheduled before the workflow changes behavior. Matching can drop it.
1085 return serviceerrors.NewObsoleteMatchingTaskf(
1088 }
1089
1090 > directiveDeployment := DirectiveDeployment(directive) worker_versioning.go
1091 > if directiveDeployment == nil {
1092 > // TODO: remove this once the ScheduledDeployment field is removed from proto
1093 > directiveDeployment = scheduledDeployment
1094 > }
1095 > if !directiveDeployment.Equal(wfDeployment) {
1096 // This must be a task scheduled before the workflow transitions to the current
1097 // deployment. Matching can drop it.
1100 directiveDeployment.GetBuildId(), wfDeployment.GetBuildId())
1101 }
1102 > return nil worker_versioning.go
1103 }
1104
1105 // DirectiveDeployment Temporary function until Directive proto is removed.
1106 > func DirectiveDeployment(directive *taskqueuespb.TaskVersionDirective) *deploymentpb.Deployment { worker_versioning.go
1107 > if dv := directive.GetDeploymentVersion(); dv != nil {
1108 return DeploymentFromDeploymentVersion(dv)
1109 }
1110 > return directive.GetDeployment() worker_versioning.go
1111 }
1112
1148 // ConvertOverrideToV32 reads from deprecated fields and returns a new object with ONLY the equivalent non-deprecated v0.32
1149 // fields. Should be used to replace any passed in override that is stored in persistence.
1150 > func ConvertOverrideToV32(override *workflowpb.VersioningOverride) *workflowpb.VersioningOverride { worker_versioning.go
1151 > if override == nil {
1152 > return nil worker_versioning.go
1153 > }
1154 ret := &workflowpb.VersioningOverride{
1155 Override: override.GetOverride(),
1190 }
1191
1192 > func WorkerDeploymentVersionToStringV32(v *deploymentspb.WorkerDeploymentVersion) string { worker_versioning.go
1193 > if v == nil {
1194 > return "" worker_versioning.go
1195 > }
1196 return v.GetDeploymentName() + WorkerDeploymentVersionDelimiter + v.GetBuildId()
1197 }
1201 }
1202
1203 > func ExternalWorkerDeploymentVersionToString(v *deploymentpb.WorkerDeploymentVersion) string { worker_versioning.go
1204 > if v == nil {
1205 > return "" worker_versioning.go
1206 > }
1207 return v.GetDeploymentName() + WorkerDeploymentVersionDelimiter + v.GetBuildId()
1208 }
1215 }
1216
1217 > func ExternalWorkerDeploymentVersionFromStringV31(s string) *deploymentpb.WorkerDeploymentVersion { worker_versioning.go
1218 > if s == "" { // unset ramp is no longer supported in v32, so all empty version strings will be treated as unversioned.
1219 > s = UnversionedVersionId worker_versioning.go
1220 > }
1221 > v, _ := WorkerDeploymentVersionFromStringV31(s) worker_versioning.go
1222 > if v == nil {
1223 > return nil worker_versioning.go
1224 > }
1225 return &deploymentpb.WorkerDeploymentVersion{
1226 BuildId: v.BuildId,
1229 }
1230
1231 > func WorkerDeploymentVersionFromStringV31(s string) (*deploymentspb.WorkerDeploymentVersion, error) { worker_versioning.go
1232 > if s == UnversionedVersionId {
1233 > return nil, nil worker_versioning.go
1234 > }
1235 before, after, found := strings.Cut(s, WorkerDeploymentVersionIDDelimiterV31)
1236 // Also try parsing via the v32 delimiter in case user is using an old CLI/SDK but passing new version strings.
go.temporal.io/server/service/matching/ratelimit_manager.go 123 covered LOC · 27 ranges

Open complete file

70 config *taskQueueConfig,
71 taskQueueType enumspb.TaskQueueType,
72 > ) *rateLimitManager { ratelimit_manager.go
73 > r := &rateLimitManager{
74 > userDataManager: userDataManager,
75 > config: config,
76 > taskQueueType: taskQueueType,
77 > perKeyReady: cache.New(config.FairnessKeyRateLimitCacheSize(), nil),
78 > timeSource: clock.NewRealTimeSource(),
79 > }
80 > r.dynamicRateBurst = quotas.NewMutableRateBurst(
81 > defaultTaskDispatchRPS,
82 > int(defaultTaskDispatchRPS),
83 > )
84 > r.dynamicRateLimiter = quotas.NewDynamicRateLimiter(
85 > r.dynamicRateBurst,
86 > config.RateLimiterRefreshInterval,
87 > )
88 > return r
89 > }
90
91 // Start registers dynamic config subscriptions and computes the initial rate limits.
92 > func (r *rateLimitManager) Start() { ratelimit_manager.go
93 > r.mu.Lock()
94 > defer r.mu.Unlock()
95 >
96 > // Overall system rate limit will be the min of the two configs that are partition wise times the number of partitons.
97 > var cancel func()
98 > r.adminNsRate, cancel = r.config.AdminNamespaceToPartitionRateSub(r.setAdminNsRate)
99 > r.cancels = append(r.cancels, cancel)
100 > r.adminTqRate, cancel = r.config.AdminNamespaceTaskQueueToPartitionRateSub(r.setAdminTqRate)
101 > r.cancels = append(r.cancels, cancel)
102 > r.numReadPartitions, cancel = r.config.NumReadPartitionsSub(r.setNumReadPartitions)
103 > r.cancels = append(r.cancels, cancel)
104 > r.computeEffectiveRPSAndSourceLocked()
105 > }
106
107 func (r *rateLimitManager) setAdminNsRate(rps float64) {
137 // - Else if a worker-level RPS is configured, effectiveRPS = min(system default RPS, worker-configured RPS)
138 // - Otherwise, fall back to the system default RPS from dynamic config.
139 > func (r *rateLimitManager) computeEffectiveRPSAndSourceLocked() { ratelimit_manager.go
140 >
141 > var (
142 > effectiveRPS = math.Inf(1)
143 > rateLimitSource enumspb.RateLimitSource
144 > )
145 > // Overall system rate limit will be the min of the two configs that are partition wise times the number of partions.
146 > systemRPS := min(
147 > r.adminNsRate,
148 > r.adminTqRate,
149 > )
150 > r.systemRPS = systemRPS
151 > fraction := r.config.RateLimitFraction()
152 > switch {
153 case r.apiConfigRPS != nil:
154 effectiveRPS = *r.apiConfigRPS * fraction / float64(r.numReadPartitions)
155 rateLimitSource = enumspb.RATE_LIMIT_SOURCE_API
156 > case r.workerRPS != nil: ratelimit_manager.go
157 > effectiveRPS = *r.workerRPS * fraction / float64(r.numReadPartitions)
158 > rateLimitSource = enumspb.RATE_LIMIT_SOURCE_WORKER
159 }
160
161 > if effectiveRPS < r.systemRPS { ratelimit_manager.go
162 r.effectiveRPS = effectiveRPS
163 r.rateLimitSource = rateLimitSource
164 > } else { ratelimit_manager.go
165 > r.effectiveRPS = r.systemRPS
166 > r.rateLimitSource = enumspb.RATE_LIMIT_SOURCE_SYSTEM
167 > }
168 }
169
170 > func (r *rateLimitManager) computeAndApplyRateLimitLocked() { ratelimit_manager.go
171 > oldRPS := r.effectiveRPS
172 > r.computeEffectiveRPSAndSourceLocked()
173 > newRPS := r.effectiveRPS
174 > // If the effective RPS has changed, we need to update the rate limiters.
175 > if oldRPS != newRPS {
176 r.updateRatelimitLocked()
177 r.updateSimpleRateLimitWithBurstLocked(defaultBurstDuration)
178 }
179 // Internally, checks if the per-key rate limit has changed and updates it accordingly.
180 > r.updatePerKeySimpleRateLimitWithBurstLocked(defaultBurstDuration) ratelimit_manager.go
181 }
182
184 // Called whenever a new poll request comes in.
185 // This allows the rate limit manager to adjust its rate limits based on any updates right before polling happens.
186 > func (r *rateLimitManager) InjectWorkerRPS(meta *pollMetadata) { ratelimit_manager.go
187 > r.mu.Lock()
188 > defer r.mu.Unlock()
189 > var rps *float64
190 > if meta != nil && meta.taskQueueMetadata != nil {
191 > if workerRPS := meta.taskQueueMetadata.GetMaxTasksPerSecond(); workerRPS != nil { ratelimit_manager.go
192 > value := workerRPS.GetValue()
193 > rps = &value
194 > }
195 }
196 > r.workerRPS = rps ratelimit_manager.go
197 > r.computeAndApplyRateLimitLocked()
198 }
199
213 // Updates the API-configured RPS based on the latest user data
214 // and applies the new rate limit if the effective RPS has changed.
215 > func (r *rateLimitManager) UserDataChanged() { ratelimit_manager.go
216 > r.mu.Lock()
217 > defer r.mu.Unlock()
218 > // Fetch the latest user data and update the API-configured RPS.
219 > r.trySetRPSFromUserDataLocked()
220 > r.computeAndApplyRateLimitLocked()
221 > }
222
223 // trySetRPSFromUserDataLocked sets the apiConfigRPS from user data.
224 // Called exclusively in response to updates in user data.
225 > func (r *rateLimitManager) trySetRPSFromUserDataLocked() { ratelimit_manager.go
226 > userData, _, err := r.userDataManager.GetUserData()
227 > if err != nil {
228 return
229 }
230 > config := userData.GetData().GetPerType()[int32(r.taskQueueType)].GetConfig() ratelimit_manager.go
231 > // If rate limit is an empty message, it means rate limit could have been unset via API.
232 > // In this case, the apiConfigRPS will need to be unset.
233 > queueRateLimit := config.GetQueueRateLimit()
234 > if queueRateLimit.GetRateLimit() == nil {
235 > r.apiConfigRPS = nil
236 > } else {
237 val := float64(queueRateLimit.GetRateLimit().GetRequestsPerSecond())
238 r.apiConfigRPS = &val
239 }
240 > fairnessKeyRateLimitDefault := config.GetFairnessKeysRateLimitDefault() ratelimit_manager.go
241 > if fairnessKeyRateLimitDefault.GetRateLimit() == nil {
242 > r.fairnessKeyRateLimitDefault = nil ratelimit_manager.go
243 > } else { ratelimit_manager.go
244 // Maintain the fairnessKeyRateLimitDefault as per-partition rate, scaled by the same
245 // fraction applied to the whole-queue effectiveRPS.
248 r.fairnessKeyRateLimitDefault = &val
249 }
250 > fairnessWeightOverrides := config.GetFairnessWeightOverrides() ratelimit_manager.go
251 > r.perKeyOverrides = fairnessWeightOverrides
252 }
253
284 // UpdatePerKeySimpleRateLimit updates the per-key rate limit for the simpleRateLimit implementation
285 // UpdateTaskQueueConfig api is the single source for the per-key rate limit.
286 > func (r *rateLimitManager) updatePerKeySimpleRateLimitWithBurstLocked(burstDuration time.Duration) { ratelimit_manager.go
287 > if r.fairnessKeyRateLimitDefault == nil {
288 > r.clearPerKeyRateLimitsLocked() ratelimit_manager.go
289 > return
290 > }
291 rate := *r.fairnessKeyRateLimitDefault
292 slp := makeSimpleLimiterParams(rate, burstDuration)
322
323 // clearPerKeyRateLimitsLocked removes all fairness per-key rate limits.
324 > func (r *rateLimitManager) clearPerKeyRateLimitsLocked() { ratelimit_manager.go
325 > r.perKeyReady = cache.New(r.config.FairnessKeyRateLimitCacheSize(), nil)
326 > r.perKeyLimit = simpleLimiterParams{}
327 > }
328
329 // rateLimitState returns the whole-queue ready time and whether a per-key limit is in effect.
330 > func (r *rateLimitManager) rateLimitState() (wholeQueueReady simpleLimiter, perKeyLimited bool) { ratelimit_manager.go
331 > r.mu.Lock()
332 > defer r.mu.Unlock()
333 > return r.wholeQueueReady, r.perKeyLimit.limited()
334 > }
335
336 func (r *rateLimitManager) readyTimeForTask(task *internalTask) simpleLimiter {
354 }
355
356 > func (r *rateLimitManager) consumeTokens(now int64, task *internalTask, tokens int64) { ratelimit_manager.go
357 > r.mu.Lock()
358 > defer r.mu.Unlock()
359 > if task.isForwarded() {
360 // don't count any rate limit for forwarded tasks, it was counted on the child
361 return
362 }
363
364 > r.wholeQueueReady = r.wholeQueueReady.consume(r.wholeQueueLimit, now, tokens) ratelimit_manager.go
365 >
366 > if r.perKeyLimit.limited() {
367 pri := task.getPriority()
368 key := pri.GetFairnessKey()
go.temporal.io/server/common/metrics/tags.go 120 covered LOC · 58 ranges

Open complete file

101 // dual emit the metric with the all tag. If a blank namespace is provided then
102 // this converts that to an unknown namespace.
103 > func NamespaceTag(value string) Tag { tags.go
104 > if len(value) == 0 {
105 > value = unknownValue tags.go
106 > }
107 > return Tag{Key: namespace, Value: value} tags.go
108 }
109
110 // NamespaceIDTag returns a new namespace ID tag.
111 > func NamespaceIDTag(value string) Tag { tags.go
112 > if len(value) == 0 {
113 value = unknownValue
114 }
115 > return Tag{Key: namespaceID, Value: value} tags.go
116 }
117
119
120 // NamespaceUnknownTag returns a new namespace:unknown tag-value
121 > func NamespaceUnknownTag() Tag { tags.go
122 > return namespaceUnknownTag
123 > }
124
125 // NamespaceStateTag returns a new namespace state tag.
126 > func NamespaceStateTag(value string) Tag { tags.go
127 > if len(value) == 0 {
128 value = unknownValue
129 }
130 > return Tag{Key: namespaceState, Value: value} tags.go
131 }
132
177 // - `tqid.PerTaskQueueScope`
178 // - `tqid.PerTaskQueuePartitionScope`
179 > func UnsafeTaskQueueTag(value string) Tag { tags.go
180 > if len(value) == 0 {
181 value = unknownValue
182 }
183 > return Tag{Key: taskQueue, Value: value} tags.go
184 }
185
186 > func TaskQueueTypeTag(tqType enumspb.TaskQueueType) Tag { tags.go
187 > return Tag{Key: TaskTypeTagName, Value: tqType.String()}
188 > }
189
190 // Consider passing the value of "metrics.breakdownByBuildID" dynamic config to this function.
191 > func WorkerVersionTag(version string, versionBreakdown bool) Tag { tags.go
192 > if version == "" {
193 > version = "__unversioned__" tags.go
194 > } else if !versionBreakdown { tags.go
195 version = "__versioned__"
196 }
197 > return Tag{Key: workerVersion, Value: version} tags.go
198 }
199
200 > func WorkerDeploymentNameTag(deploymentName string, versionBreakdown bool) Tag { tags.go
201 > if !versionBreakdown {
202 deploymentName = ""
203 }
204 > return Tag{Key: workerDeploymentName, Value: deploymentName} tags.go
205 }
206
207 > func WorkerDeploymentBuildIDTag(buildID string, versionBreakdown bool) Tag { tags.go
208 > if !versionBreakdown {
209 buildID = ""
210 }
211 > return Tag{Key: workerDeploymentBuildID, Value: buildID} tags.go
212 }
213
214 // WorkflowTypeTag returns a new workflow type tag.
215 > func WorkflowTypeTag(value string) Tag { tags.go
216 > if len(value) == 0 {
217 value = unknownValue
218 }
219 > return Tag{Key: workflowType, Value: value} tags.go
220 }
221
234
235 // CommandTypeTag returns a new command type tag.
236 > func CommandTypeTag(value string) Tag { tags.go
237 > if len(value) == 0 {
238 value = unknownValue
239 }
240 > return Tag{Key: commandType, Value: value} tags.go
241 }
242
243 // Returns a new service role tag.
244 > func ServiceRoleTag(value string) Tag { tags.go
245 > if len(value) == 0 {
246 value = unknownValue
247 }
248 > return Tag{Key: ServiceRoleTagName, Value: value} tags.go
249 }
250
257 }
258
259 > func FirstAttemptTag(attempt int32) Tag { tags.go
260 > value := falseValue
261 > if attempt == 1 {
262 > value = trueValue
263 > }
264 > return Tag{Key: isFirstAttempt, Value: value}
265 }
266
272 }
273
274 > func TaskCategoryTag(value string) Tag { tags.go
275 > if len(value) == 0 {
276 value = unknownValue
277 }
278 > return Tag{Key: TaskCategoryTagName, Value: value} tags.go
279 }
280
281 > func TaskTypeTag(value string) Tag { tags.go
282 > if len(value) == 0 {
283 > value = unknownValue tags.go
284 > }
285 > return Tag{Key: TaskTypeTagName, Value: value} tags.go
286 }
287
288 > func ArchetypeTag(value string) Tag { tags.go
289 > if len(value) == 0 {
290 value = unknownValue
291 }
292 > return Tag{Key: ArchetypeTagName, Value: value} tags.go
293 }
294
300 }
301
302 > func PartitionTag(partition string) Tag { tags.go
303 > return Tag{Key: PartitionTagName, Value: partition}
304 > }
305
306 > func TaskPriorityTag(value string) Tag { tags.go
307 > if len(value) == 0 {
308 value = unknownValue
309 }
310 > return Tag{Key: TaskPriorityTagName, Value: value} tags.go
311 }
312
313 > func TaskSourceTag(source enumsspb.TaskSource) Tag { tags.go
314 > return Tag{Key: taskSourceTag, Value: source.String()}
315 > }
316
317 > func ForwardedTag(forwarded bool) Tag { tags.go
318 > return Tag{Key: forwardedTag, Value: strconv.FormatBool(forwarded)}
319 > }
320
321 > func PollResultTag(result string) Tag { tags.go
322 > return Tag{Key: pollResultTagName, Value: result}
323 > }
324
325 const (
331 )
332
333 > func TaskAddResultTag(result string) Tag { tags.go
334 > return Tag{Key: taskAddResult, Value: result}
335 > }
336
337 const (
354 }
355
356 > func MatchingTaskPriorityTag(value int32) Tag { tags.go
357 > priStr := ""
358 > if value != 0 {
359 > priStr = strconv.FormatInt(int64(value), 10) tags.go
360 > }
361 > return Tag{Key: TaskPriorityTagName, Value: priStr} tags.go
362 }
363
364 > func QueueReaderIDTag(readerID int64) Tag { tags.go
365 > return Tag{Key: QueueReaderIDTagName, Value: strconv.Itoa(int(readerID))}
366 > }
367
368 func QueueActionTag(value string) Tag {
380 }
381
382 > func VisibilityPluginNameTag(value string) Tag { tags.go
383 > if value == "" {
384 value = unknownValue
385 }
386 > return Tag{Key: visibilityPluginNameTagName, Value: value} tags.go
387 }
388
389 > func VisibilityIndexNameTag(value string) Tag { tags.go
390 > if value == "" {
391 value = unknownValue
392 }
393 > return Tag{Key: visibilityIndexNameTagName, Value: value} tags.go
394 }
395
403
404 // VersionedTag represents whether a loaded task queue manager represents a specific version set or build ID or not.
405 > func VersionedTag(versioned string) Tag { tags.go
406 > return Tag{Key: versionedTagName, Value: versioned}
407 > }
408
409 > func ServiceErrorTypeTag(err error) Tag { tags.go
410 > return Tag{Key: ErrorTypeTagName, Value: strings.TrimPrefix(util.ErrorType(err), errorPrefix)}
411 > }
412
413 func OutcomeTag(outcome string) Tag {
447 }
448
449 > func ServiceNameTag(value primitives.ServiceName) Tag { tags.go
450 > return Tag{Key: serviceName, Value: string(value)}
451 > }
452
453 > func ActionType(value string) Tag { tags.go
454 > return Tag{Key: actionType, Value: value}
455 > }
456
457 > func OperationTag(value string) Tag { tags.go
458 > return Tag{Key: OperationTagName, Value: value}
459 > }
460
461 > func StringTag(key string, value string) Tag { tags.go
462 > return Tag{Key: key, Value: value}
463 > }
464
465 > func CacheTypeTag(value string) Tag { tags.go
466 > return Tag{Key: CacheTypeTagName, Value: value}
467 > }
468
469 > func PriorityTag(value locks.Priority) Tag { tags.go
470 > return Tag{Key: PriorityTagName, Value: strconv.Itoa(int(value))}
471 > }
472
473 // ReasonString is just a string but the special type is defined here to remind callers of ReasonTag to limit the
496 }
497
498 > func VersioningBehaviorTag(behavior enumspb.VersioningBehavior) Tag { tags.go
499 > return Tag{Key: versioningBehavior, Value: behavior.String()}
500 > }
501
502 func ContinueAsNewVersioningBehaviorTag(canBehavior enumspb.ContinueAsNewVersioningBehavior) Tag {
603 }
604
605 > func HeaderCallsiteTag(kind string) Tag { tags.go
606 > return Tag{Key: headerCallsiteTagName, Value: kind}
607 > }
608
609 func TimeoutTypeTag(timeoutType string) Tag {
go.temporal.io/server/service/history/replication/stream_receiver_monitor.go 120 covered LOC · 32 ranges

Open complete file

56 executableTaskConverter ExecutableTaskConverter,
57 enableStreaming bool,
58 > ) *StreamReceiverMonitorImpl { stream_receiver_monitor.go
59 > return &StreamReceiverMonitorImpl{
60 > ProcessToolBox: processToolBox,
61 > executableTaskConverter: executableTaskConverter,
62 > enableStreaming: enableStreaming,
63 >
64 > status: streamStatusInitialized,
65 > shutdownOnce: channel.NewShutdownOnce(),
66 >
67 > inboundStreams: make(map[ClusterShardKeyPair]StreamSender),
68 > outboundStreams: make(map[ClusterShardKeyPair]StreamReceiver),
69 > }
70 > }
71
72 > func (m *StreamReceiverMonitorImpl) Start() { stream_receiver_monitor.go
73 > if !atomic.CompareAndSwapInt32(
74 > &m.status,
75 > common.DaemonStatusInitialized,
76 > common.DaemonStatusStarted,
77 > ) {
78 return
79 }
80 > if !m.enableStreaming { stream_receiver_monitor.go
81 return
82 }
83
84 > go m.eventLoop() stream_receiver_monitor.go
85 > go m.statusMonitorLoop()
86 >
87 > m.Logger.Info("StreamReceiverMonitor started.")
88 }
89
90 > func (m *StreamReceiverMonitorImpl) Stop() { stream_receiver_monitor.go
91 > if !atomic.CompareAndSwapInt32(
92 > &m.status,
93 > common.DaemonStatusStarted,
94 > common.DaemonStatusStopped,
95 > ) {
97 > }
98 > if !m.enableStreaming { stream_receiver_monitor.go
99 return
100 }
101
102 > m.shutdownOnce.Shutdown() stream_receiver_monitor.go
103 > m.Lock()
104 > defer m.Unlock()
105 > for serverKey, stream := range m.outboundStreams {
106 stream.Stop()
107 delete(m.outboundStreams, serverKey)
108 }
109 > if m.Config.EnableCloseInboundReplicationStreamOnShutdown() { stream_receiver_monitor.go
110 > for clientKey, stream := range m.inboundStreams { stream_receiver_monitor.go
111 stream.Stop()
112 delete(m.inboundStreams, clientKey)
113 }
114 }
115 > m.Logger.Info("StreamReceiverMonitor stopped.") stream_receiver_monitor.go
116 }
117
131 }
132
133 > func (m *StreamReceiverMonitorImpl) eventLoop() { stream_receiver_monitor.go
134 > defer m.Stop()
135 > ticker := time.NewTicker(streamReceiverMonitorInterval)
136 > defer ticker.Stop()
137 >
138 > clusterMetadataChangeChan := make(chan struct{}, 1)
139 > m.ClusterMetadata.RegisterMetadataChangeCallback(m, func(_ map[string]*cluster.ClusterInformation, _ map[string]*cluster.ClusterInformation) {
140 > select {
141 > case clusterMetadataChangeChan <- struct{}{}:
142 default:
143 }
144 })
145 > defer m.ClusterMetadata.UnRegisterMetadataChangeCallback(m) stream_receiver_monitor.go
146 > m.reconcileOutboundStreams()
147 >
148 > Loop:
149 > for !m.shutdownOnce.IsShutdown() {
150 > select {
151 > case <-clusterMetadataChangeChan:
152 > m.reconcileInboundStreams()
153 > m.reconcileOutboundStreams()
154 > case <-ticker.C: stream_receiver_monitor.go
155 > m.reconcileInboundStreams()
156 > m.reconcileOutboundStreams()
157 > case <-m.shutdownOnce.Channel(): stream_receiver_monitor.go
158 > break Loop
159 }
160 }
161 }
162
163 > func (m *StreamReceiverMonitorImpl) reconcileInboundStreams() { stream_receiver_monitor.go
164 > streamKeys := m.generateInboundStreamKeys()
165 > m.doReconcileInboundStreams(streamKeys)
166 > }
167
168 > func (m *StreamReceiverMonitorImpl) reconcileOutboundStreams() { stream_receiver_monitor.go
169 > streamKeys := m.generateOutboundStreamKeys()
170 > m.doReconcileOutboundStreams(streamKeys)
171 > }
172
173 > func (m *StreamReceiverMonitorImpl) generateInboundStreamKeys() map[ClusterShardKeyPair]struct{} { stream_receiver_monitor.go
174 > allClusterInfo := m.ClusterMetadata.GetAllClusterInfo()
175 >
176 > clientClusterIDs := make(map[int32]struct{})
177 > serverClusterID := int32(m.ClusterMetadata.GetClusterID())
178 > clusterIDToShardCount := make(map[int32]int32)
179 > for _, clusterInfo := range allClusterInfo {
180 > clusterIDToShardCount[int32(clusterInfo.InitialFailoverVersion)] = clusterInfo.ShardCount
181 >
182 > if !cluster.IsReplicationEnabledForCluster(clusterInfo, m.Config.EnableSeparateReplicationEnableFlag()) || int32(clusterInfo.InitialFailoverVersion) == serverClusterID {
183 > continue
184 }
185 clientClusterIDs[int32(clusterInfo.InitialFailoverVersion)] = struct{}{}
186 }
187 > streamKeys := make(map[ClusterShardKeyPair]struct{}) stream_receiver_monitor.go
188 > for _, shardID := range m.ShardController.ShardIDs() {
189 > for clientClusterID := range clientClusterIDs { stream_receiver_monitor.go
190 serverShardID := shardID
191 for _, clientShardID := range common.MapShardID(
205 }
206 }
207 > return streamKeys stream_receiver_monitor.go
208 }
209
210 > func (m *StreamReceiverMonitorImpl) generateOutboundStreamKeys() map[ClusterShardKeyPair]struct{} { stream_receiver_monitor.go
211 > allClusterInfo := m.ClusterMetadata.GetAllClusterInfo()
212 >
213 > clientClusterID := int32(m.ClusterMetadata.GetClusterID())
214 > serverClusterIDs := make(map[int32]struct{})
215 > clusterIDToShardCount := make(map[int32]int32)
216 > for _, clusterInfo := range allClusterInfo {
217 > clusterIDToShardCount[int32(clusterInfo.InitialFailoverVersion)] = clusterInfo.ShardCount
218 >
219 > if !clusterInfo.Enabled || !cluster.IsReplicationEnabledForCluster(clusterInfo, m.Config.EnableSeparateReplicationEnableFlag()) || int32(clusterInfo.InitialFailoverVersion) == clientClusterID {
220 > continue
221 }
222 serverClusterIDs[int32(clusterInfo.InitialFailoverVersion)] = struct{}{}
223 }
224 > streamKeys := make(map[ClusterShardKeyPair]struct{}) stream_receiver_monitor.go
225 > for _, shardID := range m.ShardController.ShardIDs() {
226 > for serverClusterID := range serverClusterIDs { stream_receiver_monitor.go
227 clientShardID := shardID
228 for _, serverShardID := range common.MapShardID(
242 }
243 }
244 > return streamKeys stream_receiver_monitor.go
245 }
246
247 func (m *StreamReceiverMonitorImpl) doReconcileInboundStreams(
248 streamKeys map[ClusterShardKeyPair]struct{},
250 > m.Lock()
251 > defer m.Unlock()
252 > if m.shutdownOnce.IsShutdown() {
253 return
254 }
255
256 > for streamKey, stream := range m.inboundStreams { stream_receiver_monitor.go
257 if !stream.IsValid() {
258 stream.Stop()
267 func (m *StreamReceiverMonitorImpl) doReconcileOutboundStreams(
268 streamKeys map[ClusterShardKeyPair]struct{},
270 > m.Lock()
271 > defer m.Unlock()
272 > if m.shutdownOnce.IsShutdown() {
273 return
274 }
275
276 > for streamKey, stream := range m.outboundStreams { stream_receiver_monitor.go
277 if !stream.IsValid() {
278 stream.Stop()
283 }
284 }
285 > for streamKey := range streamKeys { stream_receiver_monitor.go
286 if _, ok := m.outboundStreams[streamKey]; !ok {
287 stream := NewStreamReceiver(
297 }
298
299 > func (m *StreamReceiverMonitorImpl) statusMonitorLoop() { stream_receiver_monitor.go
300 > ticker := time.NewTicker(5 * time.Minute)
301 > defer ticker.Stop()
302 >
303 > for {
304 > select {
305 case <-ticker.C:
306 m.monitorStreamStatus()
307 > case <-m.shutdownOnce.Channel(): stream_receiver_monitor.go
308 > return
309 }
310 }
go.temporal.io/server/common/backoff/retrypolicy.go 119 covered LOC · 31 ranges

Open complete file

80
81 // NewExponentialRetryPolicy returns an instance of ExponentialRetryPolicy using the provided initialInterval
82 > func NewExponentialRetryPolicy(initialInterval time.Duration) *ExponentialRetryPolicy { retrypolicy.go
83 > p := &ExponentialRetryPolicy{
84 > initialInterval: initialInterval,
85 > backoffCoefficient: defaultBackoffCoefficient,
86 > maximumInterval: defaultMaximumInterval,
87 > expirationInterval: defaultExpirationInterval,
88 > maximumAttempts: defaultMaximumAttempts,
89 > }
90 >
91 > return p
92 > }
93
94 // NewRetrier is used for creating a new instance of Retrier
95 > func NewRetrier(policy RetryPolicy, timeSource clock.TimeSource) Retrier { retrypolicy.go
96 > return &retrierImpl{
97 > policy: policy,
98 > timeSource: timeSource,
99 > startTime: timeSource.Now(),
100 > currentAttempt: 1,
101 > }
102 > }
103
104 // WithInitialInterval sets the initial interval used by ExponentialRetryPolicy for the very first retry
113 // All retries are computed using the following formula:
114 // initialInterval * math.Pow(backoffCoefficient, currentAttempt)
115 > func (p *ExponentialRetryPolicy) WithBackoffCoefficient(backoffCoefficient float64) *ExponentialRetryPolicy { retrypolicy.go
116 > p.backoffCoefficient = backoffCoefficient
117 > return p
118 > }
119
120 // WithMaximumInterval sets the maximum interval for each retry.
121 // This does *not* cause the policy to stop retrying when the interval between retries reaches the supplied duration.
122 // That is what WithExpirationInterval does. Instead, this prevents the interval from exceeding maximumInterval.
123 > func (p *ExponentialRetryPolicy) WithMaximumInterval(maximumInterval time.Duration) *ExponentialRetryPolicy { retrypolicy.go
124 > p.maximumInterval = maximumInterval
125 > return p
126 > }
127
128 // WithExpirationInterval sets the absolute expiration interval for all retries
129 > func (p *ExponentialRetryPolicy) WithExpirationInterval(expirationInterval time.Duration) *ExponentialRetryPolicy { retrypolicy.go
130 > p.expirationInterval = expirationInterval
131 > return p
132 > }
133
134 // WithMaximumAttempts sets the maximum number of retry attempts
135 > func (p *ExponentialRetryPolicy) WithMaximumAttempts(maximumAttempts int) *ExponentialRetryPolicy { retrypolicy.go
136 > p.maximumAttempts = maximumAttempts
137 > return p
138 > }
139
140 // ComputeNextDelay returns the next delay interval. This is used by Retrier to delay calling the operation again
141 > func (p *ExponentialRetryPolicy) ComputeNextDelay(elapsedTime time.Duration, numAttempts int, _ error) time.Duration { retrypolicy.go
142 > // Check to see if we ran out of maximum number of attempts
143 > // NOTE: if maxAttempts is X, return done when numAttempts == X, otherwise there will be attempt X+1
144 > if p.maximumAttempts != noMaximumAttempts && numAttempts >= p.maximumAttempts {
145 > return done retrypolicy.go
146 > }
147
148 // Stop retrying after expiration interval is elapsed
149 > if p.expirationInterval != NoInterval && elapsedTime > p.expirationInterval { retrypolicy.go
150 return done
151 }
152
153 > nextInterval := float64(p.initialInterval) * math.Pow(p.backoffCoefficient, float64(numAttempts-1)) retrypolicy.go
154 > // Disallow retries if initialInterval is negative or nextInterval overflows
155 > if nextInterval <= 0 {
156 return done
157 }
158 > if p.maximumInterval != NoInterval { retrypolicy.go
159 > nextInterval = math.Min(nextInterval, float64(p.maximumInterval)) retrypolicy.go
160 > }
161
162 > if p.expirationInterval != NoInterval { retrypolicy.go
163 > remainingTime := float64(math.Max(0, float64(p.expirationInterval-elapsedTime))) retrypolicy.go
164 > nextInterval = math.Min(remainingTime, nextInterval)
165 > }
166
167 // Bail out if the next interval is smaller than initial retry interval
168 > nextDuration := time.Duration(nextInterval) retrypolicy.go
169 > if nextDuration < p.initialInterval {
170 return done
171 }
172
173 > nextInterval = p.addJitter(nextInterval) retrypolicy.go
174 >
175 > return time.Duration(nextInterval)
176 }
177
178 > func (p *ExponentialRetryPolicy) addJitter(nextInterval float64) float64 { retrypolicy.go
179 > // add jitter to avoid global synchronization
180 > jitterPortion := max(
181 > // Prevent overflow
182 > int(0.2*nextInterval), 1)
183 > nextInterval = nextInterval*0.8 + float64(getJitterRand().Intn(jitterPortion))
184 > return nextInterval
185 > }
186
187 func (r *disabledRetryPolicyImpl) ComputeNextDelay(_ time.Duration, _ int, _ error) time.Duration {
203 // NewConditionalRetryPolicy returns a policy that delegates to whenTrue when
204 // predicate(err) is true, and whenFalse otherwise.
205 > func NewConditionalRetryPolicy(predicate func(err error) bool, whenTrue, whenFalse RetryPolicy) *ConditionalRetryPolicy { retrypolicy.go
206 > return &ConditionalRetryPolicy{
207 > predicate: predicate,
208 > whenTrue: whenTrue,
209 > whenFalse: whenFalse,
210 > }
211 > }
212
213 > func (p *ConditionalRetryPolicy) ComputeNextDelay(elapsedTime time.Duration, numAttempts int, err error) time.Duration { retrypolicy.go
214 > if p.predicate(err) {
215 return p.whenTrue.ComputeNextDelay(elapsedTime, numAttempts, err)
216 }
217 > return p.whenFalse.ComputeNextDelay(elapsedTime, numAttempts, err) retrypolicy.go
218 }
219
220 // Reset will set the Retrier into initial state
221 > func (r *retrierImpl) Reset() { retrypolicy.go
222 > r.startTime = r.timeSource.Now()
223 > r.currentAttempt = 1
224 > }
225
226 // NextBackOff returns the next delay interval. This is used by Retry to delay calling the operation again
227 > func (r *retrierImpl) NextBackOff(err error) time.Duration { retrypolicy.go
228 > nextInterval := r.policy.ComputeNextDelay(r.getElapsedTime(), r.currentAttempt, err)
229 >
230 > // Now increment the current attempt
231 > r.currentAttempt++
232 > return nextInterval
233 > }
234
235 > func (r *retrierImpl) getElapsedTime() time.Duration { retrypolicy.go
236 > return r.timeSource.Now().Sub(r.startTime)
237 > }
238
239 var _ RetryPolicy = (*ErrorDependentRetryPolicy)(nil)
267 var _ RetryPolicy = (*ConstantDelayRetryPolicy)(nil)
268
269 > func NewConstantDelayRetryPolicy(delay time.Duration) *ConstantDelayRetryPolicy { retrypolicy.go
270 > return &ConstantDelayRetryPolicy{
271 > maximumAttempts: defaultMaximumAttempts,
272 > jitterPct: defaultJitterPct,
273 > delay: delay,
274 > }
275 > }
276
277 > func (p *ConstantDelayRetryPolicy) WithMaximumAttempts(maximumAttempts int) *ConstantDelayRetryPolicy { retrypolicy.go
278 > p.maximumAttempts = maximumAttempts
279 > return p
280 > }
281
282 func (p *ConstantDelayRetryPolicy) WithJitter(jitterPct float64) *ConstantDelayRetryPolicy {
297 }
298
299 > func getJitterRand() *rand.Rand { retrypolicy.go
300 > if r := jitterRand.Load(); r != nil {
301 > return r retrypolicy.go
302 > }
303 > r := rand.New(NewRetryLockedSource()) retrypolicy.go
304 >
305 > if !jitterRand.CompareAndSwap(nil, r) {
306 // Two different goroutines called some top-level
307 // function at the same time. While the results in
330 }
331
332 > func (r *RetryLockedSource) Int63() int64 { retrypolicy.go
333 > r.lk.Lock()
334 > defer r.lk.Unlock()
335 > return r.s.Int63()
336 > }
337
338 func (r *RetryLockedSource) Seed(seed int64) {
340 }
341
342 > func NewRetryLockedSource() *RetryLockedSource { retrypolicy.go
343 > return &RetryLockedSource{
344 > lk: sync.Mutex{},
345 > s: rand.NewSource(time.Now().UnixNano()),
346 > }
347 > }
go.temporal.io/server/common/rpc/interceptor/namespace_validator.go 115 covered LOC · 52 ranges

Open complete file

95 maxNamespaceLength dynamicconfig.IntPropertyFn,
96 additionalAllowedMethodsDuringHandover []string,
97 > ) *NamespaceValidatorInterceptor { namespace_validator.go
98 > additional := make(map[string]struct{}, len(additionalAllowedMethodsDuringHandover))
99 > for _, m := range additionalAllowedMethodsDuringHandover {
100 additional[m] = struct{}{}
101 }
102 > return &NamespaceValidatorInterceptor{ namespace_validator.go
103 > namespaceRegistry: namespaceRegistry,
104 > tokenSerializer: tasktoken.NewSerializer(),
105 > enableTokenNamespaceEnforcement: enableTokenNamespaceEnforcement,
106 > additionalAllowedMethodsDuringHandover: additional,
107 > maxNamespaceLength: maxNamespaceLength,
108 > }
109 }
110
114 info *grpc.UnaryServerInfo,
115 handler grpc.UnaryHandler,
116 > ) (any, error) { namespace_validator.go
117 > err := ni.setNamespaceIfNotPresent(req)
118 > if err != nil {
119 return nil, err
120 }
121 > reqWithNamespace, hasNamespace := req.(NamespaceNameGetter) namespace_validator.go
122 > if hasNamespace {
123 > if err := ni.ValidateName(reqWithNamespace.GetNamespace()); err != nil {
124 return nil, err
125 }
126 }
127
128 > return handler(ctx, req) namespace_validator.go
129 }
130
131 // ValidateName validates a namespace name (currently only a max length check).
132 > func (ni *NamespaceValidatorInterceptor) ValidateName(ns string) error { namespace_validator.go
133 > if len(ns) > ni.maxNamespaceLength() {
134 return errNamespaceTooLong
135 }
136 > return nil namespace_validator.go
137 }
138
139 func (ni *NamespaceValidatorInterceptor) setNamespaceIfNotPresent(
140 req any,
141 > ) error { namespace_validator.go
142 > switch request := req.(type) {
143 > case NamespaceNameGetter:
144 > if request.GetNamespace() == "" {
145 namespaceEntry, err := ni.extractNamespaceFromTaskToken(req)
146 if err != nil {
205 info *grpc.UnaryServerInfo,
206 handler grpc.UnaryHandler,
207 > ) (any, error) { namespace_validator.go
208 > namespaceEntry, err := ni.extractNamespace(req)
209 > if err != nil {
210 return nil, err
211 }
212
213 > if err := ni.ValidateState(namespaceEntry, info.FullMethod, GetRoutingKeyFromContext(ctx).ID); err != nil { namespace_validator.go
214 return nil, err
215 }
216
217 > return handler(ctx, req) namespace_validator.go
218 }
219
224 // 4. Namespace from request match namespace from task token, if check is enabled with dynamic config.
225 // 5. Namespace is in correct state.
226 > func (ni *NamespaceValidatorInterceptor) ValidateState(namespaceEntry *namespace.Namespace, fullMethod string, businessID string) error { namespace_validator.go
227 > if err := ni.checkNamespaceState(namespaceEntry, fullMethod); err != nil {
228 return err
229 }
230 > return ni.checkReplicationState(namespaceEntry, fullMethod, businessID) namespace_validator.go
231 }
232
233 > func (ni *NamespaceValidatorInterceptor) extractNamespace(req any) (*namespace.Namespace, error) { namespace_validator.go
234 > // Token namespace has priority over request namespace. Check it first.
235 > tokenNamespaceEntry, tokenErr := ni.extractNamespaceFromTaskToken(req)
236 > if tokenErr != nil {
237 return nil, tokenErr
238 }
239
240 > requestNamespaceEntry, requestErr := ni.extractNamespaceFromRequest(req) namespace_validator.go
241 > // If namespace was extracted from token then it will be used.
242 > if requestErr != nil && tokenNamespaceEntry == nil {
243 return nil, requestErr
244 }
245
246 > err := ni.checkNamespaceMatch(requestNamespaceEntry, tokenNamespaceEntry) namespace_validator.go
247 > if err != nil {
248 return nil, err
249 }
250
251 // Use namespace from task token (if specified) and ignore namespace from request.
252 > if tokenNamespaceEntry != nil { namespace_validator.go
253 > return tokenNamespaceEntry, nil namespace_validator.go
254 > }
255
256 > return requestNamespaceEntry, nil namespace_validator.go
257 }
258
259 > func (ni *NamespaceValidatorInterceptor) extractNamespaceFromRequest(req any) (*namespace.Namespace, error) { namespace_validator.go
260 > reqWithNamespace, hasNamespace := req.(NamespaceNameGetter)
261 > if !hasNamespace {
262 > return nil, nil namespace_validator.go
263 > }
264 > namespaceName := namespace.Name(reqWithNamespace.GetNamespace()) namespace_validator.go
265 >
266 > switch request := req.(type) {
267 > case *workflowservice.DescribeNamespaceRequest: namespace_validator.go
268 > // Special case for DescribeNamespace API which should read namespace directly from database.
269 > // Therefore, it must bypass namespace registry and validator.
270 > if request.GetId() == "" && namespaceName.IsEmpty() {
271 return nil, errNamespaceNotSet
272 }
273 > return nil, nil namespace_validator.go
274 case *adminservice.GetNamespaceRequest:
275 // special case for Admin.GetNamespace API which accept either Namespace ID or Namespace name as input
278 }
279 return nil, nil
280 > case *workflowservice.RegisterNamespaceRequest: namespace_validator.go
281 > // Special case for RegisterNamespace API. `namespaceName` is name of namespace that about to be registered.
282 > // There is no namespace entry for it, therefore, it must bypass namespace registry and validator.
283 > if namespaceName.IsEmpty() {
284 return nil, errNamespaceNotSet
285 }
286 > return nil, nil namespace_validator.go
287 case *operatorservice.DeleteNamespaceRequest:
288 // special case for Operator.DeleteNamespace API which accept either Namespace ID or Namespace name as input
313 }
314 return nil, nil
315 > default: namespace_validator.go
316 > // All other APIs.
317 > if namespaceName.IsEmpty() {
318 return nil, errNamespaceNotSet
319 }
320 > return ni.namespaceRegistry.GetNamespace(namespaceName) namespace_validator.go
321 }
322 }
323
324 > func (ni *NamespaceValidatorInterceptor) extractNamespaceFromTaskToken(req any) (*namespace.Namespace, error) { namespace_validator.go
325 > reqWithTaskToken, hasTaskToken := req.(TaskTokenGetter)
326 > if !hasTaskToken {
327 > return nil, nil namespace_validator.go
328 > }
329 > taskTokenBytes := reqWithTaskToken.GetTaskToken() namespace_validator.go
330 > if len(taskTokenBytes) == 0 {
331 return nil, errTaskTokenNotSet
332 }
333 > var namespaceID namespace.ID namespace_validator.go
334 > // Special case for deprecated RespondQueryTaskCompleted API.
335 > if _, ok := req.(*workflowservice.RespondQueryTaskCompletedRequest); ok {
336 taskToken, err := ni.tokenSerializer.DeserializeQueryTaskToken(taskTokenBytes)
337 if err != nil {
339 }
340 namespaceID = namespace.ID(taskToken.GetNamespaceId())
341 > } else { namespace_validator.go
342 > taskToken, err := ni.tokenSerializer.Deserialize(taskTokenBytes)
343 > if err != nil {
344 return nil, errDeserializingToken
345 }
346 > namespaceID = namespace.ID(taskToken.GetNamespaceId()) namespace_validator.go
347 }
348
349 > if namespaceID.IsEmpty() { namespace_validator.go
350 return nil, errNamespaceNotSet
351 }
352 > return ni.namespaceRegistry.GetNamespaceByID(namespaceID) namespace_validator.go
353 }
354
355 > func (ni *NamespaceValidatorInterceptor) checkNamespaceMatch(requestNamespace *namespace.Namespace, tokenNamespace *namespace.Namespace) error { namespace_validator.go
356 > if tokenNamespace == nil || requestNamespace == nil || !ni.enableTokenNamespaceEnforcement() {
357 > return nil
358 > }
359
360 > if requestNamespace.ID() != tokenNamespace.ID() { namespace_validator.go
361 return errTaskTokenNamespaceMismatch
362 }
363 > return nil namespace_validator.go
364 }
365
366 > func (ni *NamespaceValidatorInterceptor) checkNamespaceState(namespaceEntry *namespace.Namespace, fullMethod string) error { namespace_validator.go
367 > if namespaceEntry == nil {
368 > return nil namespace_validator.go
369 > }
370
371 > allowedStates, allowedStatesPerAPIDefined := allowedNamespaceStatesPerAPI[fullMethod] namespace_validator.go
372 > if !allowedStatesPerAPIDefined {
373 > serviceName := api.ServiceName(fullMethod) namespace_validator.go
374 > var allowedStatesPerServiceDefined bool
375 > allowedStates, allowedStatesPerServiceDefined = allowedNamespaceStatesPerService[serviceName]
376 > if !allowedStatesPerServiceDefined {
377 > allowedStates = allowedNamespaceStatesDefault namespace_validator.go
378 > }
379 }
380 > for _, allowedState := range allowedStates { namespace_validator.go
381 > if allowedState == namespaceEntry.State() {
382 > return nil namespace_validator.go
383 > }
384 }
385 return serviceerror.NewNamespaceInvalidState(namespaceEntry.Name().String(), namespaceEntry.State(), allowedStates)
386 }
387
388 > func (ni *NamespaceValidatorInterceptor) checkReplicationState(namespaceEntry *namespace.Namespace, fullMethod string, businessID string) error { namespace_validator.go
389 > if namespaceEntry == nil {
390 > return nil namespace_validator.go
391 > }
392 > if namespaceEntry.ReplicationState(businessID) != enumspb.REPLICATION_STATE_HANDOVER { namespace_validator.go
393 > return nil namespace_validator.go
394 > }
395
396 methodName := api.MethodName(fullMethod)
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/execution_maps.go 114 covered LOC · 26 ranges

Open complete file

52 )
53
54 > func stringMap(a []string, f func(string) string) []string { execution_maps.go
55 > b := make([]string, len(a))
56 > for i, v := range a {
57 > b[i] = f(v)
58 > }
59 > return b
60 }
61
62 > func makeDeleteMapQry(tableName string) string { execution_maps.go
63 > return fmt.Sprintf(deleteMapQryTemplate, tableName)
64 > }
65
66 > func makeSetKeyInMapQry(tableName string, nonPrimaryKeyColumns []string, mapKeyName string) string { execution_maps.go
67 > return fmt.Sprintf(setKeyInMapQryTemplate,
68 > tableName,
69 > strings.Join(nonPrimaryKeyColumns, ","),
70 > strings.Join(stringMap(nonPrimaryKeyColumns, func(x string) string {
71 > return ":" + x
72 > }), ","),
73 > strings.Join(stringMap(nonPrimaryKeyColumns, func(x string) string {
74 > return x + "=" + x
75 > }), ","),
76 mapKeyName)
77 }
78
79 > func makeDeleteKeyInMapQry(tableName string, mapKeyName string) string { execution_maps.go
80 > return fmt.Sprintf(deleteKeyInMapQryTemplate,
81 > tableName,
82 > mapKeyName)
83 > }
84
85 > func makeGetMapQryTemplate(tableName string, nonPrimaryKeyColumns []string, mapKeyName string) string { execution_maps.go
86 > return fmt.Sprintf(getMapQryTemplate,
87 > tableName,
88 > mapKeyName,
89 > strings.Join(nonPrimaryKeyColumns, ","))
90 > }
91
92 var (
120 ctx context.Context,
121 filter sqlplugin.ActivityInfoMapsAllFilter,
122 > ) ([]sqlplugin.ActivityInfoMapsRow, error) { execution_maps.go
123 > var rows []sqlplugin.ActivityInfoMapsRow
124 > if err := mdb.conn.SelectContext(ctx,
125 > &rows,
126 > getActivityInfoMapQry,
127 > filter.ShardID,
128 > filter.NamespaceID,
129 > filter.WorkflowID,
130 > filter.RunID,
131 > ); err != nil {
132 return nil, err
133 }
134 > for i := 0; i < len(rows); i++ { execution_maps.go
135 rows[i].ShardID = filter.ShardID
136 rows[i].NamespaceID = filter.NamespaceID
138 rows[i].RunID = filter.RunID
139 }
140 > return rows, nil execution_maps.go
141 }
142
206 ctx context.Context,
207 filter sqlplugin.TimerInfoMapsAllFilter,
208 > ) ([]sqlplugin.TimerInfoMapsRow, error) { execution_maps.go
209 > var rows []sqlplugin.TimerInfoMapsRow
210 > if err := mdb.conn.SelectContext(ctx,
211 > &rows,
212 > getTimerInfoMapSQLQuery,
213 > filter.ShardID,
214 > filter.NamespaceID,
215 > filter.WorkflowID,
216 > filter.RunID,
217 > ); err != nil {
218 return nil, err
219 }
220 > for i := 0; i < len(rows); i++ { execution_maps.go
221 rows[i].ShardID = filter.ShardID
222 rows[i].NamespaceID = filter.NamespaceID
224 rows[i].RunID = filter.RunID
225 }
226 > return rows, nil execution_maps.go
227 }
228
292 ctx context.Context,
293 filter sqlplugin.ChildExecutionInfoMapsAllFilter,
294 > ) ([]sqlplugin.ChildExecutionInfoMapsRow, error) { execution_maps.go
295 > var rows []sqlplugin.ChildExecutionInfoMapsRow
296 > if err := mdb.conn.SelectContext(ctx,
297 > &rows,
298 > getChildExecutionInfoMapQry,
299 > filter.ShardID,
300 > filter.NamespaceID,
301 > filter.WorkflowID,
302 > filter.RunID,
303 > ); err != nil {
304 return nil, err
305 }
306 > for i := 0; i < len(rows); i++ { execution_maps.go
307 rows[i].ShardID = filter.ShardID
308 rows[i].NamespaceID = filter.NamespaceID
310 rows[i].RunID = filter.RunID
311 }
312 > return rows, nil execution_maps.go
313 }
314
378 ctx context.Context,
379 filter sqlplugin.RequestCancelInfoMapsAllFilter,
380 > ) ([]sqlplugin.RequestCancelInfoMapsRow, error) { execution_maps.go
381 > var rows []sqlplugin.RequestCancelInfoMapsRow
382 > if err := mdb.conn.SelectContext(ctx,
383 > &rows, getRequestCancelInfoMapQry,
384 > filter.ShardID,
385 > filter.NamespaceID,
386 > filter.WorkflowID,
387 > filter.RunID,
388 > ); err != nil {
389 return nil, err
390 }
391 > for i := 0; i < len(rows); i++ { execution_maps.go
392 rows[i].ShardID = filter.ShardID
393 rows[i].NamespaceID = filter.NamespaceID
395 rows[i].RunID = filter.RunID
396 }
397 > return rows, nil execution_maps.go
398 }
399
463 ctx context.Context,
464 filter sqlplugin.SignalInfoMapsAllFilter,
465 > ) ([]sqlplugin.SignalInfoMapsRow, error) { execution_maps.go
466 > var rows []sqlplugin.SignalInfoMapsRow
467 > if err := mdb.conn.SelectContext(ctx,
468 > &rows,
469 > getSignalInfoMapQry,
470 > filter.ShardID,
471 > filter.NamespaceID,
472 > filter.WorkflowID,
473 > filter.RunID,
474 > ); err != nil {
475 return nil, err
476 }
477 > for i := 0; i < len(rows); i++ { execution_maps.go
478 rows[i].ShardID = filter.ShardID
479 rows[i].NamespaceID = filter.NamespaceID
481 rows[i].RunID = filter.RunID
482 }
483 > return rows, nil execution_maps.go
484 }
485
565 ctx context.Context,
566 filter sqlplugin.SignalsRequestedSetsAllFilter,
567 > ) ([]sqlplugin.SignalsRequestedSetsRow, error) { execution_maps.go
568 > var rows []sqlplugin.SignalsRequestedSetsRow
569 > if err := mdb.conn.SelectContext(ctx,
570 > &rows,
571 > getSignalsRequestedSetQry,
572 > filter.ShardID,
573 > filter.NamespaceID,
574 > filter.WorkflowID,
575 > filter.RunID,
576 > ); err != nil {
577 return nil, err
578 }
579 > for i := 0; i < len(rows); i++ { execution_maps.go
580 rows[i].ShardID = filter.ShardID
581 rows[i].NamespaceID = filter.NamespaceID
583 rows[i].RunID = filter.RunID
584 }
585 > return rows, nil execution_maps.go
586 }
587
641 ctx context.Context,
642 filter sqlplugin.ChasmNodeMapsAllFilter,
643 > ) ([]sqlplugin.ChasmNodeMapsRow, error) { execution_maps.go
644 > var rows []sqlplugin.ChasmNodeMapsRow
645 >
646 > if err := mdb.conn.SelectContext(ctx,
647 > &rows,
648 > getChasmNodeMapSQLQuery,
649 > filter.ShardID,
650 > filter.NamespaceID,
651 > filter.WorkflowID,
652 > filter.RunID,
653 > ); err != nil {
654 return nil, err
655 }
656
657 > for i := range rows { execution_maps.go
658 rows[i].ShardID = filter.ShardID
659 rows[i].NamespaceID = filter.NamespaceID
go.temporal.io/server/chasm/registry.go 110 covered LOC · 49 ranges

Open complete file

51 }
52
53 > func NewRegistry(logger log.Logger) *Registry { registry.go
54 > return &Registry{
55 > libraries: make(map[string]Library),
56 > rcByFqn: make(map[string]*RegistrableComponent),
57 > rcByID: make(map[uint32]*RegistrableComponent),
58 > rcByGoType: make(map[reflect.Type]*RegistrableComponent),
59 > rtByFqn: make(map[string]*RegistrableTask),
60 > rtByID: make(map[uint32]*RegistrableTask),
61 > rtByGoType: make(map[reflect.Type]*RegistrableTask),
62 > rcContextValues: make(map[any]valueWithFqn),
63 > nexusServices: make(map[string]*nexus.Service),
64 > NexusEndpointProcessor: NewNexusEndpointProcessor(),
65 > logger: logger,
66 > }
67 > }
68
69 > func (r *Registry) Register(lib Library) error { registry.go
70 > if err := r.validateName(lib.Name()); err != nil {
71 return err
72 }
73 > if _, ok := r.libraries[lib.Name()]; ok { registry.go
74 return fmt.Errorf("library %s is already registered", lib.Name())
75 }
76 > r.libraries[lib.Name()] = lib registry.go
77 >
78 > for _, c := range lib.Components() {
79 > if err := r.registerComponent(lib, c); err != nil { registry.go
80 return err
81 }
82 }
83 > for _, t := range lib.Tasks() { registry.go
84 > if err := r.registerTask(lib, t); err != nil { registry.go
85 return err
86 }
87 }
88
89 > for _, svc := range lib.NexusServices() { registry.go
90 > if err := r.registerNexusService(svc); err != nil { registry.go
91 return err
92 }
93 }
94
95 > for _, svc := range lib.NexusServiceProcessors() { registry.go
96 > if err := r.NexusEndpointProcessor.RegisterServiceProcessor(svc); err != nil { registry.go
97 return err
98 }
99 }
100
101 > return nil registry.go
102 }
103
104 // RegisterServices registers all gRPC services from all registered libraries.
105 > func (r *Registry) RegisterServices(server *grpc.Server) { registry.go
106 > for _, lib := range r.libraries {
107 > lib.RegisterServices(server)
108 > }
109 }
110
134 // This method should only be used by CHASM framework internal code,
135 // NOT CHASM library developers.
136 > func (r *Registry) ComponentByID(id uint32) (*RegistrableComponent, bool) { registry.go
137 > rc, ok := r.rcByID[id]
138 > return rc, ok
139 > }
140
141 // ComponentIDFor converts registered component instance to component type ID.
235 lib namer,
236 rc *RegistrableComponent,
237 > ) error { registry.go
238 > if err := r.validate(rc); err != nil {
239 return err
240 }
241
242 > fqn, id, err := rc.registerToLibrary(lib) registry.go
243 > if err != nil {
244 return err
245 }
246
247 > if _, ok := r.rcByFqn[fqn]; ok { registry.go
248 return fmt.Errorf("component %s is already registered", fqn)
249 }
250
251 > if id == UnspecifiedArchetypeID { registry.go
252 return fmt.Errorf("component %s maps to a reserved archetype id %d, please use a different name", fqn, UnspecifiedArchetypeID)
253 }
254
255 > if existingComponent, ok := r.rcByID[id]; ok { registry.go
256 return fmt.Errorf("component ID %d collision between %s and %s", id, fqn, existingComponent.fqType())
257 }
258
259 > for key, value := range rc.contextValues { registry.go
260 > if existingValue, ok := r.rcContextValues[key]; ok { registry.go
261 return fmt.Errorf("context value key %v registered by component %s conflicts with component %s", key, fqn, existingValue.fqn)
262 }
263 > r.rcContextValues[key] = valueWithFqn{ registry.go
264 > v: value,
265 > fqn: fqn,
266 > }
267 }
268
269 // rc.goType implements Component interface; therefore, it must be a struct.
270 // This check to protect against the interface itself being registered.
271 > if !(rc.goType.Kind() == reflect.Struct || registry.go
272 > (rc.goType.Kind() == reflect.Pointer && rc.goType.Elem().Kind() == reflect.Struct)) {
273 return fmt.Errorf("component type %s must be struct or pointer to struct", rc.goType.String())
274 }
275 > if _, ok := r.rcByGoType[rc.goType]; ok { registry.go
276 return fmt.Errorf("component type %s is already registered", rc.goType.String())
277 }
278 > r.warnUnmanagedFields(fqn, rc) registry.go
279 >
280 > r.rcByFqn[fqn] = rc
281 > r.rcByID[id] = rc
282 > r.rcByGoType[rc.goType] = rc
283 > return nil
284 }
285
286 > func (r *Registry) validate(rc *RegistrableComponent) error { registry.go
287 > if err := r.validateName(rc.componentType); err != nil {
288 return err
289 }
290 > return r.validateVisibilityBusinessIDAlias(rc) registry.go
291 }
292
294 lib namer,
295 rt *RegistrableTask,
296 > ) error { registry.go
297 > if err := r.validateName(rt.taskType); err != nil {
298 return err
299 }
300
301 > fqn, id, err := rt.registerToLibrary(lib) registry.go
302 > if err != nil {
303 return err
304 }
305
306 > if _, ok := r.rtByFqn[fqn]; ok { registry.go
307 return fmt.Errorf("task %s is already registered", fqn)
308 }
309
310 > if existingTask, ok := r.rtByID[id]; ok { registry.go
311 return fmt.Errorf("task type ID %d collision between %s and %s", id, fqn, existingTask.fqType())
312 }
313
314 > if !(rt.goType.Kind() == reflect.Struct || registry.go
315 > (rt.goType.Kind() == reflect.Pointer && rt.goType.Elem().Kind() == reflect.Struct)) {
316 return fmt.Errorf("task type %s must be struct or pointer to struct", rt.goType.String())
317 }
318 > if _, ok := r.rtByGoType[rt.goType]; ok { registry.go
319 return fmt.Errorf("task type %s is already registered", rt.goType.String())
320 }
321 > if !(rt.componentGoType.Kind() == reflect.Interface || registry.go
322 > (rt.componentGoType.Kind() == reflect.Struct ||
323 > (rt.componentGoType.Kind() == reflect.Pointer && rt.componentGoType.Elem().Kind() == reflect.Struct)) &&
324 > rt.componentGoType.AssignableTo(reflect.TypeFor[Component]())) {
325 return fmt.Errorf("component type %s must be and interface or struct that implements Component interface", rt.componentGoType.String())
326 }
327
328 > r.rtByFqn[fqn] = rt registry.go
329 > r.rtByID[id] = rt
330 > r.rtByGoType[rt.goType] = rt
331 > return nil
332 }
333
334 > func (r *Registry) validateName(n string) error { registry.go
335 > if n == "" {
336 return errors.New("name must not be empty")
337 }
338 > if !nameValidator.MatchString(n) { registry.go
339 return fmt.Errorf("name %s is invalid. name must follow golang identifier rules: %s", n, nameValidator.String())
340 }
341 > return nil registry.go
342 }
343
344 > func (r *Registry) validateVisibilityBusinessIDAlias(rc *RegistrableComponent) error { registry.go
345 > if !hasVisibilityField(rc.goType) {
346 > return nil registry.go
347 > }
348 // Archetypes that contain a Field[*Visibility] must specify WithBusinessIDAlias.
349 > if !rc.hasBusinessIDAlias() { registry.go
350 return fmt.Errorf("component %s has Field[*Visibility] but no businessID alias; use WithBusinessIDAlias option", rc.componentType)
351 }
352 > return nil registry.go
353 }
354
355 > func (r *Registry) warnUnmanagedFields(fqn string, rc *RegistrableComponent) { registry.go
356 > var unmanagedFields []string
357 > for f := range unmanagedFieldsOf(rc.goType) {
358 > unmanagedFields = append(unmanagedFields, fmt.Sprintf("%s %s", f.name, f.typ)) registry.go
359 > }
360 > if len(unmanagedFields) > 0 { registry.go
361 > r.logger.Info(fmt.Sprintf( registry.go
362 > "Warning: CHASM component %s declares state fields that won't be managed by CHASM:\n\t%s",
363 > fqn,
364 > strings.Join(unmanagedFields, "\n\t")))
365 > }
366 }
367
368 > func (r *Registry) registerNexusService(svc *nexus.Service) error { registry.go
369 > if _, ok := r.nexusServices[svc.Name]; ok {
370 return fmt.Errorf("nexus service %s is already registered", svc.Name)
371 }
372 > r.nexusServices[svc.Name] = svc registry.go
373 > return nil
374 }
375
376 // NexusServices returns all registered Nexus services.
377 > func (r *Registry) NexusServices() map[string]*nexus.Service { registry.go
378 > // Return a copy to prevent external modification
379 > services := make(map[string]*nexus.Service, len(r.nexusServices))
380 > maps.Copy(services, r.nexusServices)
381 > return services
382 > }
383
384 func (r *Registry) componentContextValue(key any) any {
go.temporal.io/server/common/persistence/sql/cluster_metadata.go 110 covered LOC · 28 ranges

Open complete file

23 ctx context.Context,
24 request *p.InternalListClusterMetadataRequest,
25 > ) (*p.InternalListClusterMetadataResponse, error) { cluster_metadata.go
26 > var clusterName string
27 > if request.NextPageToken != nil {
28 err := gobDeserialize(request.NextPageToken, &clusterName)
29 if err != nil {
32 }
33
34 > rows, err := s.DB.ListClusterMetadata(ctx, &sqlplugin.ClusterMetadataFilter{ClusterName: clusterName, PageSize: &request.PageSize}) cluster_metadata.go
35 > if err != nil {
36 if err == sql.ErrNoRows {
37 return &p.InternalListClusterMetadataResponse{}, nil
40 }
41
42 > var clusterMetadata []*p.InternalGetClusterMetadataResponse cluster_metadata.go
43 > for _, row := range rows {
44 > resp := &p.InternalGetClusterMetadataResponse{
45 > ClusterMetadata: p.NewDataBlob(row.Data, row.DataEncoding),
46 > Version: row.Version,
47 > }
48 > clusterMetadata = append(clusterMetadata, resp)
49 > }
50
51 > resp := &p.InternalListClusterMetadataResponse{ClusterMetadata: clusterMetadata} cluster_metadata.go
52 > if len(rows) >= request.PageSize {
53 nextPageToken, err := gobSerialize(rows[len(rows)-1].ClusterName)
54 if err != nil {
63 ctx context.Context,
64 request *p.InternalGetClusterMetadataRequest,
65 > ) (*p.InternalGetClusterMetadataResponse, error) { cluster_metadata.go
66 > row, err := s.DB.GetClusterMetadata(ctx, &sqlplugin.ClusterMetadataFilter{ClusterName: request.ClusterName})
67 >
68 > if err != nil {
69 > return nil, convertCommonErrors("GetClusterMetadata", err)
70 > }
71
72 > return &p.InternalGetClusterMetadataResponse{ cluster_metadata.go
73 > ClusterMetadata: p.NewDataBlob(row.Data, row.DataEncoding),
74 > Version: row.Version,
75 > }, nil
76 }
77
79 ctx context.Context,
80 request *p.InternalSaveClusterMetadataRequest,
81 > ) (bool, error) { cluster_metadata.go
82 > err := s.txExecute(ctx, "SaveClusterMetadata", func(tx sqlplugin.Tx) error {
83 > oldClusterMetadata, err := tx.WriteLockGetClusterMetadata(
84 > ctx,
85 > &sqlplugin.ClusterMetadataFilter{ClusterName: request.ClusterName})
86 > var lastVersion int64
87 > if err != nil {
88 > if err != sql.ErrNoRows {
89 return serviceerror.NewUnavailablef("SaveClusterMetadata operation failed. Error %v", err)
90 }
92 lastVersion = oldClusterMetadata.Version
93 }
94 > if request.Version != lastVersion { cluster_metadata.go
95 return serviceerror.NewUnavailablef("SaveClusterMetadata encountered version mismatch, expected %v but got %v.",
96 request.Version, oldClusterMetadata.Version)
97 }
98 > _, err = tx.SaveClusterMetadata(ctx, &sqlplugin.ClusterMetadataRow{ cluster_metadata.go
99 > ClusterName: request.ClusterName,
100 > Data: request.ClusterMetadata.Data,
101 > DataEncoding: request.ClusterMetadata.EncodingType.String(),
102 > Version: request.Version,
103 > })
104 > if err != nil {
105 return convertCommonErrors("SaveClusterMetadata", err)
106 }
107 > return nil cluster_metadata.go
108 })
109
110 > if err != nil { cluster_metadata.go
111 return false, serviceerror.NewUnavailable(err.Error())
112 }
113 > return true, nil cluster_metadata.go
114 }
115
129 ctx context.Context,
130 request *p.GetClusterMembersRequest,
131 > ) (*p.GetClusterMembersResponse, error) { cluster_metadata.go
132 > var lastSeenHostId []byte
133 > if len(request.NextPageToken) == 16 {
134 lastSeenHostId = request.NextPageToken
135 > } else if len(request.NextPageToken) > 0 { cluster_metadata.go
136 return nil, serviceerror.NewInternal("page token is corrupted.")
137 }
138
139 > now := time.Now().UTC() cluster_metadata.go
140 > filter := &sqlplugin.ClusterMembershipFilter{
141 > HostIDEquals: request.HostIDEquals,
142 > RoleEquals: request.RoleEquals,
143 > RecordExpiryAfter: now,
144 > SessionStartedAfter: request.SessionStartedAfter,
145 > MaxRecordCount: request.PageSize,
146 > }
147 >
148 > if lastSeenHostId != nil && filter.HostIDEquals == nil {
149 filter.HostIDGreaterThan = lastSeenHostId
150 }
151
152 > if request.LastHeartbeatWithin > 0 { cluster_metadata.go
153 > filter.LastHeartbeatAfter = now.Add(-request.LastHeartbeatWithin)
154 > }
155
156 > if request.RPCAddressEquals != nil { cluster_metadata.go
157 filter.RPCAddressEquals = request.RPCAddressEquals.String()
158 }
159
160 > rows, err := s.DB.GetClusterMembers(ctx, filter) cluster_metadata.go
161 >
162 > if err != nil {
163 return nil, convertCommonErrors("GetClusterMembers", err)
164 }
165
166 > convertedRows := make([]*p.ClusterMember, 0, len(rows)) cluster_metadata.go
167 > for _, row := range rows {
168 > convertedRows = append(convertedRows, &p.ClusterMember{ cluster_metadata.go
169 > HostID: row.HostID,
170 > Role: row.Role,
171 > RPCAddress: net.ParseIP(row.RPCAddress),
172 > RPCPort: row.RPCPort,
173 > SessionStart: row.SessionStart,
174 > LastHeartbeat: row.LastHeartbeat,
175 > RecordExpiry: row.RecordExpiry,
176 > })
177 > }
178
179 > var nextPageToken []byte cluster_metadata.go
180 > if request.PageSize > 0 && len(rows) == request.PageSize {
181 lastRow := rows[len(rows)-1]
182 nextPageToken = lastRow.HostID
183 }
184
185 > return &p.GetClusterMembersResponse{ActiveMembers: convertedRows, NextPageToken: nextPageToken}, nil cluster_metadata.go
186 }
187
189 ctx context.Context,
190 request *p.UpsertClusterMembershipRequest,
191 > ) error { cluster_metadata.go
192 > now := time.Now().UTC()
193 > recordExpiry := now.Add(request.RecordExpiry)
194 > _, err := s.DB.UpsertClusterMembership(ctx, &sqlplugin.ClusterMembershipRow{
195 > Role: request.Role,
196 > HostID: request.HostID,
197 > RPCAddress: request.RPCAddress.String(),
198 > RPCPort: request.RPCPort,
199 > SessionStart: request.SessionStart,
200 > LastHeartbeat: now,
201 > RecordExpiry: recordExpiry})
202 >
203 > if err != nil {
204 return convertCommonErrors("UpsertClusterMembership", err)
205 }
206
207 > return nil cluster_metadata.go
208 }
209
211 ctx context.Context,
212 request *p.PruneClusterMembershipRequest,
213 > ) error { cluster_metadata.go
214 > _, err := s.DB.PruneClusterMembership(
215 > ctx,
216 > &sqlplugin.PruneClusterMembershipFilter{
217 > PruneRecordsBefore: time.Now().UTC(),
218 > },
219 > )
220 >
221 > if err != nil {
222 return convertCommonErrors("PruneClusterMembership", err)
223 }
224
225 > return nil cluster_metadata.go
226 }
227
230 logger log.Logger,
231 serializer serialization.Serializer,
232 > ) (p.ClusterMetadataStore, error) { cluster_metadata.go
233 > return &sqlClusterMetadataManager{
234 > SqlStore: NewSQLStore(db, logger, serializer),
235 > }, nil
236 > }
go.temporal.io/server/service/history/api/get_history_util.go 108 covered LOC · 25 ranges

Open complete file

157 branchToken []byte,
158 persistenceVisibilityMgr manager.VisibilityManager,
159 > ) (history *historypb.History, token []byte, retError error) { get_history_util.go
160 > defer func() {
161 > var dataLossErr *serviceerror.DataLoss
162 > var serializationErr *serialization.DeserializationError
163 > var deserializationErr *serialization.SerializationError
164 > if errors.As(retError, &dataLossErr) || errors.As(retError, &serializationErr) || errors.As(retError, &deserializationErr) {
165 // log event
166 shardContext.GetLogger().Error("encountered data loss event in GetHistory",
184 }()
185
186 > var size int get_history_util.go
187 > isFirstPage := len(nextPageToken) == 0
188 > shardID := common.WorkflowIDToHistoryShard(namespaceID.String(), execution.GetWorkflowId(), shardContext.GetConfig().NumberOfShards)
189 > var err error
190 > var historyEvents []*historypb.HistoryEvent
191 > historyEvents, size, nextPageToken, err = persistence.ReadFullPageEvents(ctx, shardContext.GetExecutionManager(), &persistence.ReadHistoryBranchRequest{
192 > BranchToken: branchToken,
193 > MinEventID: firstEventID,
194 > MaxEventID: nextEventID,
195 > PageSize: int(pageSize),
196 > NextPageToken: nextPageToken,
197 > ShardID: shardID,
198 > })
199 > if err != nil {
200 return nil, nil, err
201 }
202
203 > logger := shardContext.GetLogger() get_history_util.go
204 > metricsHandler := interceptor.GetMetricsHandlerFromContext(ctx, logger).WithTags(metrics.OperationTag(metrics.HistoryGetHistoryScope))
205 > metrics.HistorySize.With(metricsHandler).Record(int64(size))
206 >
207 > isLastPage := len(nextPageToken) == 0
208 > var firstEvent, lastEvent *historyspb.StrippedHistoryEvent
209 > if len(historyEvents) > 0 {
210 > firstEvent = &historyspb.StrippedHistoryEvent{ get_history_util.go
211 > EventId: historyEvents[0].GetEventId(),
212 > }
213 > lastEvent = &historyspb.StrippedHistoryEvent{
214 > EventId: historyEvents[len(historyEvents)-1].GetEventId(),
215 > }
216 > }
217 > if err := VerifyHistoryIsComplete( get_history_util.go
218 > shardContext.GetLogger(),
219 > firstEvent,
220 > lastEvent,
221 > len(historyEvents),
222 > firstEventID,
223 > nextEventID-1,
224 > isFirstPage,
225 > isLastPage,
226 > int(pageSize)); err != nil {
227 metrics.ServiceErrIncompleteHistoryCounter.With(metricsHandler).Record(1)
228 logger.Error("getHistory: incomplete history",
232 tag.Error(err))
233 }
234 > if len(nextPageToken) == 0 && transientWorkflowTaskInfo != nil { get_history_util.go
235 // Check if we should include transient/speculative events
236 if shouldIncludeTransientOrSpeculativeTasks(ctx, transientWorkflowTaskInfo) {
248 }
249
250 > if err := ProcessOutgoingSearchAttributes( get_history_util.go
251 > shardContext.GetSearchAttributesProvider(),
252 > shardContext.GetSearchAttributesMapperProvider(),
253 > historyEvents,
254 > namespaceName,
255 > persistenceVisibilityMgr); err != nil {
256 return nil, nil, err
257 }
258
259 > executionHistory := &historypb.History{ get_history_util.go
260 > Events: historyEvents,
261 > }
262 > return executionHistory, nextPageToken, nil
263 }
264
355 ns namespace.Name,
356 persistenceVisibilityMgr manager.VisibilityManager,
357 > ) error { get_history_util.go
358 > saTypeMap, err := saProvider.GetSearchAttributes(persistenceVisibilityMgr.GetIndexName(), false)
359 > if err != nil {
360 return serviceerror.NewUnavailablef(consts.ErrUnableToGetSearchAttributesMessage, err)
361 }
362 > for _, event := range events { get_history_util.go
363 > var searchAttributes *commonpb.SearchAttributes get_history_util.go
364 > switch event.EventType {
365 > case enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_STARTED: get_history_util.go
366 > searchAttributes = event.GetWorkflowExecutionStartedEventAttributes().GetSearchAttributes()
367 case enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_CONTINUED_AS_NEW:
368 searchAttributes = event.GetWorkflowExecutionContinuedAsNewEventAttributes().GetSearchAttributes()
372 searchAttributes = event.GetUpsertWorkflowSearchAttributesEventAttributes().GetSearchAttributes()
373 }
374 > if searchAttributes != nil { get_history_util.go
375 searchattribute.ApplyTypeMap(searchAttributes, saTypeMap)
376 aliasedSas, err := searchattribute.AliasFields(saMapperProvider, searchAttributes, ns.String())
466 isLastPage bool,
467 pageSize int,
468 > ) error { get_history_util.go
469 >
470 > if eventCount == 0 {
471 if isLastPage {
472 // we seem to be returning a non-nil pageToken on the lastPage which
478 }
479
480 > if !isFirstPage { // at least one page of history has been read previously get_history_util.go
481 if firstEvent.GetEventId() <= expectedFirstEventID {
482 // not first page and no events have been read in the previous pages - not possible
488 }
489
490 > if !isLastPage { get_history_util.go
491 // estimate lastEventID based on pageSize. This is a lower bound
492 // since the persistence layer counts "batch of events" as a single page
494 }
495
496 > nExpectedEvents := expectedLastEventID - expectedFirstEventID + 1 get_history_util.go
497 >
498 > if firstEvent.GetEventId() == expectedFirstEventID &&
499 > ((isLastPage && lastEvent.GetEventId() == expectedLastEventID && int64(eventCount) == nExpectedEvents) ||
500 > (!isLastPage && lastEvent.GetEventId() >= expectedLastEventID && int64(eventCount) >= nExpectedEvents)) {
501 > return nil
502 > }
503
504 return softassert.UnexpectedDataLoss(logger,
528 ns namespace.Name,
529 isCloseEventOnly bool,
530 > ) error { get_history_util.go
531 > if response == nil || response.History == nil {
532 > return nil get_history_util.go
533 > }
534 response.Response.History = response.History
535 if isCloseEventOnly && len(response.Response.History.Events) > 0 {
558 isCloseEventOnly bool,
559 history *historypb.History,
560 > ) error { get_history_util.go
561 > // Backwards-compatibility fix for retry events after #1866: older SDKs don't know how to "follow"
562 > // subsequent runs linked in WorkflowExecutionFailed or TimedOut events, so they'll get the wrong result
563 > // when trying to "get" the result of a workflow run. (This applies to cron runs also but "get" on a cron
564 > // workflow isn't really sensible.)
565 > //
566 > // To handle this in a backwards-compatible way, we'll pretend the completion event is actually
567 > // ContinuedAsNew, if it's Failed or TimedOut. We want to do this only when the client is looking for a
568 > // completion event, and not when it's getting the history to display for other purposes. The best signal
569 > // for that purpose is `isCloseEventOnly`. (We can't use `isLongPoll` also because in some cases, older
570 > // versions of the Java SDK don't set that flag.)
571 > //
572 > // TODO: We can remove this once we no longer support SDK versions prior to around September 2021.
573 > // Revisit this once we have an SDK deprecation policy.
574 > followsNextRunId := versionChecker.ClientSupportsFeature(ctx, headers.FeatureFollowsNextRunID)
575 > if isCloseEventOnly && !followsNextRunId && len(history.Events) > 0 {
576 > lastEvent := history.Events[len(history.Events)-1]
577 > fakeEvent, err := makeFakeContinuedAsNewEvent(ctx, lastEvent)
578 > if err != nil {
579 return err
580 }
581 > if fakeEvent != nil { get_history_util.go
582 history.Events[len(history.Events)-1] = fakeEvent
583 }
584 }
585 > return nil get_history_util.go
586 }
587
589 _ context.Context,
590 lastEvent *historypb.HistoryEvent,
591 > ) (*historypb.HistoryEvent, error) { get_history_util.go
592 > switch lastEvent.EventType { // nolint:exhaustive
593 > case enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED: get_history_util.go
594 > if lastEvent.GetWorkflowExecutionCompletedEventAttributes().GetNewExecutionRunId() == "" {
595 > return nil, nil
596 > }
597 case enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_FAILED:
598 if lastEvent.GetWorkflowExecutionFailedEventAttributes().GetNewExecutionRunId() == "" {
go.temporal.io/server/service/history/api/respondworkflowtaskcompleted/workflow_task_completed_handler.go 108 covered LOC · 32 ranges

Open complete file

128 matchingClient matchingservice.MatchingServiceClient,
129 versionCache worker_versioning.VersionMembershipAndReactivationStatusCache,
130 > ) *workflowTaskCompletedHandler { workflow_task_completed_handler.go
131 > return &workflowTaskCompletedHandler{
132 > identity: identity,
133 > workerControlTaskQueue: workerControlTaskQueue,
134 > workflowTaskCompletedID: workflowTaskCompletedID,
135 >
136 > // internal state
137 > hasBufferedEventsOrMessages: hasBufferedEventsOrMessages,
138 > workflowTaskFailedCause: nil,
139 > activityNotStartedCancelled: false,
140 > newMutableState: nil,
141 > stopProcessing: false,
142 > mutableState: mutableState,
143 > effects: effects,
144 > initiatedChildExecutionsInBatch: make(map[string]struct{}),
145 > updateRegistry: updateRegistry,
146 >
147 > // validation
148 > attrValidator: attrValidator,
149 > sizeLimitChecker: sizeLimitChecker,
150 > searchAttributesMapperProvider: searchAttributesMapperProvider,
151 >
152 > logger: logger,
153 > namespaceRegistry: namespaceRegistry,
154 > metricsHandler: metricsHandler.WithTags(
155 > metrics.OperationTag(metrics.HistoryRespondWorkflowTaskCompletedScope),
156 > metrics.NamespaceTag(mutableState.GetNamespaceEntry().Name().String()),
157 > ),
158 > config: config,
159 > shard: shard,
160 > tokenSerializer: tasktoken.NewSerializer(),
161 > commandHandlerRegistry: commandHandlerRegistry,
162 > chasmWorkflowRegistry: chasmWorkflowRegistry,
163 > matchingClient: matchingClient,
164 > versionCache: versionCache,
165 > }
166 > }
167
168 func (handler *workflowTaskCompletedHandler) handleCommands(
170 commands []*commandpb.Command,
171 msgs *collection.IndexedTakeList[string, *protocolpb.Message],
172 > ) ([]workflowTaskResponseMutation, error) { workflow_task_completed_handler.go
173 > if err := handler.attrValidator.ValidateCommandSequence(
174 > commands,
175 > ); err != nil {
176 return nil, err
177 }
178
179 > var mutations []workflowTaskResponseMutation workflow_task_completed_handler.go
180 > var postActions []commandPostAction
181 > for _, command := range commands {
182 > response, err := handler.handleCommand(ctx, command, msgs) workflow_task_completed_handler.go
183 > if err != nil || handler.stopProcessing {
184 return nil, err
185 }
186 > if response != nil { workflow_task_completed_handler.go
187 if response.workflowTaskResponseMutation != nil {
188 mutations = append(mutations, response.workflowTaskResponseMutation)
200 // However, PROTOCOL_MESSAGE command is not required by server. If it is not present,
201 // update.Acceptance and update.Respond messages will be processed after all commands in order they are in request.
202 > for _, msg := range msgs.TakeRemaining() { workflow_task_completed_handler.go
203 err := handler.handleMessage(ctx, msg)
204 if err != nil || handler.stopProcessing {
207 }
208
209 > for _, postAction := range postActions { workflow_task_completed_handler.go
210 mutation, err := postAction(ctx)
211 if err != nil || handler.stopProcessing {
230 wfKey definition.WorkflowKey,
231 workerIdentity string,
233 >
234 > // If server decided to fail WT (instead of completing), don't reject updates.
235 > // New WT will be created, and it will deliver these updates again to the worker.
236 > // Worker will do full history replay, and updates should be delivered again.
237 > if handler.workflowTaskFailedCause != nil {
238 return
239 }
240
241 // If WT is a heartbeat WT, then it doesn't have to have messages.
242 > if wtHeartbeat { workflow_task_completed_handler.go
243 return
244 }
247 // then it might skip processing some updates. In this case, it doesn't indicate old SDK or bug.
248 // All unprocessed updates will be aborted later though.
249 > if !handler.mutableState.IsWorkflowExecutionRunning() { workflow_task_completed_handler.go
251 > }
252
253 rejectedUpdateIDs := handler.updateRegistry.RejectUnprocessed(
277 command *commandpb.Command,
278 msgs *collection.IndexedTakeList[string, *protocolpb.Message],
279 > ) (*handleCommandResponse, error) { workflow_task_completed_handler.go
280 >
281 > metrics.CommandCounter.With(handler.metricsHandler).
282 > Record(1, metrics.CommandTypeTag(command.GetCommandType().String()))
283 > var response *handleCommandResponse
284 > var historyEvent *historypb.HistoryEvent
285 > var err error
286 >
287 > // TODO: ideally history events should not be exposed here. We should be passing the command
288 > // all the way down but it requires a bigger refactor of the mutable state interface.
289 > switch command.GetCommandType() {
290 case enumspb.COMMAND_TYPE_SCHEDULE_ACTIVITY_TASK:
291 historyEvent, response, err = handler.handleCommandScheduleActivity(ctx, command.GetScheduleActivityTaskCommandAttributes())
292
293 > case enumspb.COMMAND_TYPE_COMPLETE_WORKFLOW_EXECUTION: workflow_task_completed_handler.go
294 > historyEvent, err = handler.handleCommandCompleteWorkflow(ctx, command.GetCompleteWorkflowExecutionCommandAttributes())
295
296 case enumspb.COMMAND_TYPE_FAIL_WORKFLOW_EXECUTION:
757 // flushWorkerCommandsTasks creates WorkerCommandsTasks for all collected worker commands,
758 // batched by control queue.
759 > func (handler *workflowTaskCompletedHandler) flushWorkerCommandsTasks() error { workflow_task_completed_handler.go
760 > for controlQueue, commands := range handler.pendingWorkerCommandsByControlQueue {
761 if err := handler.mutableState.AddWorkerCommandsTasks(
762 commands,
791 ctx context.Context,
792 attr *commandpb.CompleteWorkflowExecutionCommandAttributes,
793 > ) (*historypb.HistoryEvent, error) { workflow_task_completed_handler.go
794 > if handler.hasBufferedEventsOrMessages {
795 return nil, handler.failWorkflowTask(enumspb.WORKFLOW_TASK_FAILED_CAUSE_UNHANDLED_COMMAND, nil)
796 }
797
798 > if err := handler.validateCommandAttr( workflow_task_completed_handler.go
799 > func() (enumspb.WorkflowTaskFailedCause, error) {
800 > return handler.attrValidator.ValidateCompleteWorkflowExecutionAttributes(attr)
801 > },
802 ); err != nil || handler.stopProcessing {
803 return nil, err
804 }
805
806 > if err := handler.sizeLimitChecker.checkIfPayloadSizeExceedsLimit( workflow_task_completed_handler.go
807 > metrics.CommandTypeTag(enumspb.COMMAND_TYPE_COMPLETE_WORKFLOW_EXECUTION.String()),
808 > attr.GetResult().Size(),
809 > "CompleteWorkflowExecutionCommandAttributes.Result exceeds size limit.",
810 > ); err != nil {
811 return nil, handler.terminateWorkflow(enumspb.WORKFLOW_TASK_FAILED_CAUSE_BAD_SCHEDULE_ACTIVITY_ATTRIBUTES, err)
812 }
813
814 // If the workflow task has more than one completion event then just pick the first one
815 > if !handler.mutableState.IsWorkflowExecutionRunning() { workflow_task_completed_handler.go
816 metrics.MultipleCompletionCommandsCounter.With(handler.metricsHandler).Record(1)
817 handler.logger.Warn(
823 }
824
825 > cronBackoff := handler.mutableState.GetCronBackoffDuration() workflow_task_completed_handler.go
826 > var newExecutionRunID string
827 > if cronBackoff != backoff.NoBackoff {
828 newExecutionRunID = uuid.NewString()
829 }
830
831 // Always add workflow completed event to this one
832 > event, err := handler.mutableState.AddCompletedWorkflowEvent(handler.workflowTaskCompletedID, attr, newExecutionRunID) workflow_task_completed_handler.go
833 > if err != nil {
834 return nil, err
835 }
836
837 // Check if this workflow has a cron schedule
838 > if cronBackoff != backoff.NoBackoff { workflow_task_completed_handler.go
839 return event, handler.handleCron(ctx, cronBackoff, attr.GetResult(), nil, newExecutionRunID)
840 }
841
842 > return event, nil workflow_task_completed_handler.go
843 }
844
1548 func (handler *workflowTaskCompletedHandler) validateCommandAttr(
1549 validationFn commandAttrValidationFn,
1551 >
1552 > return handler.failWorkflowTaskOnInvalidArgument(validationFn())
1553 > }
1554
1555 func (handler *workflowTaskCompletedHandler) failWorkflowTaskOnInvalidArgument(
1556 wtFailedCause enumspb.WorkflowTaskFailedCause,
1557 err error,
1559 > var invalidArgument *serviceerror.InvalidArgument
1560 > if errors.As(err, &invalidArgument) {
1561 return handler.failWorkflowTask(wtFailedCause, err)
1562 }
1564 }
1565
go.temporal.io/server/service/matching/fair_backlog_manager.go 108 covered LOC · 17 ranges

Open complete file

65 counterFactory func() counter.Counter,
66 isDraining bool,
67 > ) *fairBacklogManagerImpl { fair_backlog_manager.go
68 > // For the purposes of taskQueueDB, call this just a TaskManager. It'll return errors if we
69 > // use it incorectly. TODO(fairness): consider a cleaner way of doing this.
70 > taskManager := persistence.TaskManager(fairTaskManager)
71 >
72 > bmg := &fairBacklogManagerImpl{
73 > pqMgr: pqMgr,
74 > config: config,
75 > tqCtx: tqCtx,
76 > isDraining: isDraining,
77 > db: newTaskQueueDB(config, taskManager, pqMgr.QueueKey(), logger, metricsHandler, isDraining),
78 > subqueuesByPriority: make(map[priorityKey]subqueueIndex),
79 > priorityBySubqueue: make(map[subqueueIndex]priorityKey),
80 > matchingClient: matchingClient,
81 > metricsHandler: metricsHandler,
82 > counterFactory: counterFactory,
83 > logger: logger,
84 > throttledLogger: throttledLogger,
85 > initializedError: future.NewFuture[struct{}](),
86 > }
87 > bmg.taskWriter = newFairTaskWriter(bmg, bmg.newCounterForSubqueue)
88 > return bmg
89 > }
90
91 // signalIfFatal calls UnloadFromPartitionManager of the physicalTaskQueueManager
107 }
108
109 > func (c *fairBacklogManagerImpl) Start() { fair_backlog_manager.go
110 > c.taskWriter.Start()
111 > }
112
113 > func (c *fairBacklogManagerImpl) Stop() { fair_backlog_manager.go
114 > // Maybe try to write one final update of ack level. Skip the update if we never
115 > // initialized. Also skip if we're stopping due to lost ownership (the update will
116 > // fail in that case). Ignore any errors. Don't bother with GC, the next reload will
117 > // handle that.
118 > if !c.initializedError.Ready() || c.skipFinalUpdate.Load() {
119 return
120 }
121
122 > c.subqueueLock.Lock() fair_backlog_manager.go
123 > for i, r := range c.subqueues {
124 > _, ackLevel := r.getLevels()
125 > // oldestTime can be time.Time{} here since countDelta is 0
126 > c.db.updateFairAckLevel(subqueueIndex(i), ackLevel, 0, -1, time.Time{})
127 > }
128 > c.subqueueLock.Unlock()
129 >
130 > ctx, cancel := context.WithTimeout(c.tqCtx, ioTimeout)
131 > _ = c.db.SyncState(ctx)
132 > cancel()
133 }
134
135 > func (c *fairBacklogManagerImpl) initState(state taskQueueState, err error) { fair_backlog_manager.go
136 > defer c.initializedError.Set(struct{}{}, err)
137 >
138 > if err != nil {
139 // We can't recover from here without starting over, so unload the whole task queue.
140 // Skip final update since we never initialized.
146 // Pass scale info back to physical tq from unversioned (default) queue.
147 // This must be done before c.initializedError.Set().
148 > if c.queueKey().Partition().IsRoot() && !c.queueKey().IsVersioned() && !c.isDraining { fair_backlog_manager.go
149 c.pqMgr.StartScaleManager(state.scaleState)
150 }
151
152 > if state.otherHasTasks { fair_backlog_manager.go
153 c.pqMgr.SetupDraining()
154 }
155
156 > c.subqueueLock.Lock() fair_backlog_manager.go
157 > defer c.subqueueLock.Unlock()
158 >
159 > c.loadSubqueuesLocked(state.subqueues)
160 > go c.periodicSync()
161 }
162
163 > func (c *fairBacklogManagerImpl) WaitUntilInitialized(ctx context.Context) error { fair_backlog_manager.go
164 > _, err := c.initializedError.Get(ctx)
165 > return err
166 > }
167
168 > func (c *fairBacklogManagerImpl) loadSubqueuesLocked(subqueues []persistencespb.SubqueueInfo) { fair_backlog_manager.go
169 > // TODO(pri): This assumes that subqueues never shrinks, and priority/fairness index of
170 > // existing subqueues never changes. If we change that, this logic will need to change.
171 > for i := range subqueues {
172 > subqueueIdx := subqueueIndex(i)
173 > if i >= len(c.subqueues) {
174 > r := newFairTaskReader(c, subqueueIdx, fairLevelFromProto(subqueues[i].FairAckLevel))
175 > r.Start()
176 > c.subqueues = append(c.subqueues, r)
177 > }
178 > c.subqueuesByPriority[priorityKey(subqueues[i].Key.Priority)] = subqueueIdx
179 > c.priorityBySubqueue[subqueueIdx] = priorityKey(subqueues[i].Key.Priority)
180 }
181 }
216 }
217
218 > func (c *fairBacklogManagerImpl) periodicSync() { fair_backlog_manager.go
219 > for {
220 > select {
221 > case <-c.tqCtx.Done(): fair_backlog_manager.go
222 > return
223 case <-time.After(c.config.UpdateAckInterval()):
224 ctx, cancel := context.WithTimeout(c.tqCtx, ioTimeout)
273 }
274
275 > func (c *fairBacklogManagerImpl) BacklogCountHint() (total int64) { fair_backlog_manager.go
276 > c.subqueueLock.Lock()
277 > defer c.subqueueLock.Unlock()
278 > for _, r := range c.subqueues {
279 > total += int64(r.getLoadedTasks())
280 > }
281 > return
282 }
283
284 > func (c *fairBacklogManagerImpl) BacklogStatsByPriority() map[int32]*taskqueuepb.TaskQueueStats { fair_backlog_manager.go
285 > c.subqueueLock.Lock()
286 > defer c.subqueueLock.Unlock()
287 >
288 > result := make(map[int32]*taskqueuepb.TaskQueueStats)
289 > backlogCounts := c.db.getApproximateBacklogCountsBySubqueue()
290 > for subqueueIdx, priorityKey := range c.priorityBySubqueue {
291 > pk := int32(priorityKey)
292 >
293 > // Note that there could be more than one subqueue for the same priority.
294 > if _, ok := result[pk]; !ok {
295 > result[pk] = &taskqueuepb.TaskQueueStats{
296 > // TODO(pri): returning 0 to match existing behavior, but maybe emptyBacklogAge would
297 > // be more appropriate in the future.
298 > ApproximateBacklogAge: durationpb.New(0),
299 > }
300 > }
301
302 // Add backlog counts together across all subqueues for the same priority.
303 > result[pk].ApproximateBacklogCount += backlogCounts[subqueueIdx] fair_backlog_manager.go
304 >
305 > // Find greatest backlog age for across all subqueues for the same priority.
306 > oldestBacklogTime := c.subqueues[subqueueIdx].getOldestBacklogTime()
307 > if !oldestBacklogTime.IsZero() {
308 oldestBacklogAge := time.Since(oldestBacklogTime)
309 if oldestBacklogAge > result[pk].ApproximateBacklogAge.AsDuration() {
395 }
396
397 > func (c *fairBacklogManagerImpl) queueKey() *PhysicalTaskQueueKey { fair_backlog_manager.go
398 > return c.pqMgr.QueueKey()
399 > }
400
401 func (c *fairBacklogManagerImpl) getDB() *taskQueueDB {
go.temporal.io/server/service/matching/workers/registry_impl.go 106 covered LOC · 20 ranges

Open complete file

80 )
81
82 > func newBucket() *bucket { registry_impl.go
83 > return &bucket{
84 > namespaces: make(map[namespace.ID]*nsEntries),
85 > order: list.New(),
86 > }
87 > }
88
89 // upsertHeartbeats inserts or refreshes a WorkerHeartbeat under the given namespace.
90 // Returns the count of added and removed entries separately.
91 // Workers with WORKER_STATUS_SHUTDOWN are immediately removed from the registry.
92 > func (b *bucket) upsertHeartbeats(nsID namespace.ID, nsName namespace.Name, principal *commonpb.Principal, heartbeats []*workerpb.WorkerHeartbeat) (added int64, removed int64) { registry_impl.go
93 > now := time.Now()
94 >
95 > b.mu.Lock()
96 > defer b.mu.Unlock()
97 >
98 > ns, ok := b.namespaces[nsID]
99 > if !ok {
100 > ns = &nsEntries{name: nsName, workers: make(map[string]*entry)}
101 > b.namespaces[nsID] = ns
102 > }
103 > ns.name = nsName
104 >
105 > for _, hb := range heartbeats {
106 > key := hb.WorkerInstanceKey
107 >
108 > // If worker is shutting down, remove it immediately
109 > if hb.Status == enumspb.WORKER_STATUS_SHUTDOWN {
110 if e, exists := ns.workers[key]; exists {
111 b.order.Remove(e.elem)
116 }
117
118 > isSystemWorker := isSystemWorker(principal, hb.GetTaskQueue()) registry_impl.go
119 >
120 > // Normal upsert
121 > if e, exists := ns.workers[key]; exists {
122 e.hb = hb
123 e.lastSeen = now
124 e.isSystemWorker = isSystemWorker
125 b.order.MoveToBack(e.elem)
126 > } else { registry_impl.go
127 > e = &entry{
128 > nsID: nsID,
129 > hb: hb,
130 > lastSeen: now,
131 > isSystemWorker: isSystemWorker,
132 > }
133 > e.elem = b.order.PushBack(e)
134 > ns.workers[key] = e
135 > added++
136 > }
137 }
138
139 > return added, removed registry_impl.go
140 }
141
229
230 // NewRegistry creates a workers heartbeat registry with the given parameters.
231 > func NewRegistry(lc fx.Lifecycle, params RegistryParams) Registry { registry_impl.go
232 > m := newRegistryImpl(params)
233 > lc.Append(fx.StartStopHook(m.Start, m.Stop))
234 > return m
235 > }
236
237 > func newRegistryImpl(params RegistryParams) *registryImpl { registry_impl.go
238 > m := &registryImpl{
239 > buckets: make([]*bucket, params.NumBuckets()),
240 > maxItemsFn: params.MaxItems,
241 > ttlFn: params.TTL,
242 > minEvictAgeFn: params.MinEvictAge,
243 > evictionIntervalFn: params.EvictionInterval,
244 > seed: maphash.MakeSeed(),
245 > quit: make(chan struct{}),
246 > metricsHandler: params.MetricsHandler,
247 > metricsEmitter: &workerMetricsEmitter{
248 > handler: params.MetricsHandler,
249 > config: params.MetricsConfig,
250 > },
251 > }
252 >
253 > for i := range m.buckets {
254 > m.buckets[i] = newBucket()
255 > }
256 > return m
257 }
258
259 // bucketFor hashes the namespace to select a bucket.
260 > func (m *registryImpl) getBucket(nsID namespace.ID) *bucket { registry_impl.go
261 > var h maphash.Hash
262 > h.SetSeed(m.seed)
263 > h.WriteString(nsID.String()) //nolint:revive
264 > hs := h.Sum64()
265 > idx := int(hs % uint64(len(m.buckets)))
266 >
267 > return m.buckets[idx]
268 > }
269
270 // upsertHeartbeat records or refreshes a WorkerHeartbeat under the given namespace.
271 // New entries increment the global counter.
272 > func (m *registryImpl) upsertHeartbeats(nsID namespace.ID, nsName namespace.Name, principal *commonpb.Principal, heartbeats []*workerpb.WorkerHeartbeat) { registry_impl.go
273 > b := m.getBucket(nsID)
274 > added, removed := b.upsertHeartbeats(nsID, nsName, principal, heartbeats)
275 > m.total.Add(added - removed)
276 > if added > 0 {
277 > metrics.WorkerRegistryWorkersAdded.With(m.metricsHandler).Record(added) registry_impl.go
278 > }
279 > if removed > 0 { registry_impl.go
280 metrics.WorkerRegistryWorkersRemoved.With(m.metricsHandler).Record(removed)
281 }
282 > m.recordUtilizationMetric() registry_impl.go
283 }
284
285 // recordUtilizationMetric records the overall capacity utilization ratio.
286 > func (m *registryImpl) recordUtilizationMetric() { registry_impl.go
287 > maxItems := int64(m.maxItemsFn())
288 > utilization := float64(m.total.Load()) / float64(maxItems)
289 > metrics.WorkerRegistryCapacityUtilizationMetric.With(m.metricsHandler).Record(utilization)
290 > }
291
292 // recordEvictionMetric sets the eviction metric based on current capacity state.
337
338 // evictLoop periodically triggers TTL and capacity-based eviction.
339 > func (m *registryImpl) evictLoop() { registry_impl.go
340 > for {
341 > select {
342 case <-time.After(m.evictionIntervalFn()):
343 m.evictByTTL()
345 m.recordUtilizationMetric()
346 m.recordWorkerCountMetric()
347 > case <-m.quit: registry_impl.go
348 > return
349 }
350 }
397
398 // Start begins the background eviction process.
399 > func (m *registryImpl) Start() { registry_impl.go
400 > go m.evictLoop()
401 > }
402
403 // Stop halts background eviction.
404 > func (m *registryImpl) Stop() { registry_impl.go
405 > close(m.quit)
406 > }
407
408 > func (m *registryImpl) RecordWorkerHeartbeats(nsID namespace.ID, nsName namespace.Name, principal *commonpb.Principal, workerHeartbeat []*workerpb.WorkerHeartbeat) { registry_impl.go
409 > m.upsertHeartbeats(nsID, nsName, principal, workerHeartbeat)
410 > m.metricsEmitter.emit(nsID, nsName, workerHeartbeat)
411 > }
412
413 func buildQueryPredicate(nsID namespace.ID, query string) (func(*workerpb.WorkerHeartbeat) bool, error) {
525 // the Temporal server itself (type="temporal"). Otherwise, it falls back to
526 // checking the task queue name prefix.
527 > func isSystemWorker(principal *commonpb.Principal, taskQueue string) bool { registry_impl.go
528 > if principal != nil {
529 return principal.GetType() == authorization.InternalPrincipalType
530 }
531 > return primitives.IsInternalTaskQueue(taskQueue) registry_impl.go
532 }
go.temporal.io/server/chasm/search_attribute.go 105 covered LOC · 16 ranges

Open complete file

136 }
137
138 > func newSearchAttributeFieldBool(index int) SearchAttributeFieldBool { search_attribute.go
139 > return SearchAttributeFieldBool{
140 > field: resolveFieldName(enumspb.INDEXED_VALUE_TYPE_BOOL, index),
141 > }
142 > }
143
144 // SearchAttributeFieldDateTime is a search attribute field for a datetime value.
147 }
148
149 > func newSearchAttributeFieldDateTime(index int) SearchAttributeFieldDateTime { search_attribute.go
150 > return SearchAttributeFieldDateTime{
151 > field: resolveFieldName(enumspb.INDEXED_VALUE_TYPE_DATETIME, index),
152 > }
153 > }
154
155 // SearchAttributeFieldInt is a search attribute field for an integer value.
158 }
159
160 > func newSearchAttributeFieldInt(index int) SearchAttributeFieldInt { search_attribute.go
161 > return SearchAttributeFieldInt{
162 > field: resolveFieldName(enumspb.INDEXED_VALUE_TYPE_INT, index),
163 > }
164 > }
165
166 // SearchAttributeFieldDouble is a search attribute field for a double value.
169 }
170
171 > func newSearchAttributeFieldDouble(index int) SearchAttributeFieldDouble { search_attribute.go
172 > return SearchAttributeFieldDouble{
173 > field: resolveFieldName(enumspb.INDEXED_VALUE_TYPE_DOUBLE, index),
174 > }
175 > }
176
177 // SearchAttributeFieldKeyword is a search attribute field for a keyword value.
180 }
181
182 > func newSearchAttributeFieldKeyword(index int) SearchAttributeFieldKeyword { search_attribute.go
183 > return SearchAttributeFieldKeyword{
184 > field: resolveFieldName(enumspb.INDEXED_VALUE_TYPE_KEYWORD, index),
185 > }
186 > }
187
188 > func newSearchAttributeFieldLowCardinalityKeyword(index int) SearchAttributeFieldKeyword { search_attribute.go
189 > return SearchAttributeFieldKeyword{
190 > field: fmt.Sprintf("%s%s%02d", sadefs.ReservedPrefix, "LowCardinalityKeyword", index),
191 > }
192 > }
193
194 // SearchAttributeFieldKeywordList is a search attribute field for a keyword list value.
197 }
198
199 > func newSearchAttributeFieldKeywordList(index int) SearchAttributeFieldKeywordList { search_attribute.go
200 > return SearchAttributeFieldKeywordList{
201 > field: resolveFieldName(enumspb.INDEXED_VALUE_TYPE_KEYWORD_LIST, index),
202 > }
203 > }
204
205 // SearchAttributeFieldText is a search attribute field for a text value.
214 }
215
216 > func resolveFieldName(valueType enumspb.IndexedValueType, index int) string { search_attribute.go
217 > // Columns are named like TemporalBool01, TemporalDatetime01, TemporalDouble01, TemporalInt01.
218 > return fmt.Sprintf("%s%s%02d", sadefs.ReservedPrefix, valueType.String(), index)
219 > }
220
221 > func (s searchAttributeDefinition) definition() searchAttributeDefinition { search_attribute.go
222 > return s
223 > }
224
225 // SearchAttributeBool is a search attribute for a boolean value.
239 }
240
241 > func newSearchAttributeBoolByField(field string) SearchAttributeBool { search_attribute.go
242 > return SearchAttributeBool{
243 > searchAttributeDefinition: searchAttributeDefinition{
244 > alias: field,
245 > field: field,
246 > valueType: enumspb.INDEXED_VALUE_TYPE_BOOL,
247 > },
248 > }
249 > }
250
251 // Value sets the boolean value of the search attribute.
266
267 // NewSearchAttributeDateTime creates a new date time search attribute given a predefined chasm field
268 > func NewSearchAttributeDateTime(alias string, datetimeField SearchAttributeFieldDateTime) SearchAttributeDateTime { search_attribute.go
269 > return SearchAttributeDateTime{
270 > searchAttributeDefinition: searchAttributeDefinition{
271 > alias: alias,
272 > field: datetimeField.field,
273 > valueType: enumspb.INDEXED_VALUE_TYPE_DATETIME,
274 > },
275 > }
276 > }
277
278 > func newSearchAttributeDateTimeByField(field string) SearchAttributeDateTime { search_attribute.go
279 > return SearchAttributeDateTime{
280 > searchAttributeDefinition: searchAttributeDefinition{
281 > alias: field,
282 > field: field,
283 > valueType: enumspb.INDEXED_VALUE_TYPE_DATETIME,
284 > },
285 > }
286 > }
287
288 // Value sets the date time value of the search attribute.
303
304 // NewSearchAttributeInt creates a new integer search attribute given a predefined chasm field
305 > func NewSearchAttributeInt(alias string, intField SearchAttributeFieldInt) SearchAttributeInt { search_attribute.go
306 > return SearchAttributeInt{
307 > searchAttributeDefinition: searchAttributeDefinition{
308 > alias: alias,
309 > field: intField.field,
310 > valueType: enumspb.INDEXED_VALUE_TYPE_INT,
311 > },
312 > }
313 > }
314
315 // Value sets the integer value of the search attribute.
367
368 // NewSearchAttributeKeyword creates a new keyword search attribute given a predefined chasm field
369 > func NewSearchAttributeKeyword(alias string, keywordField SearchAttributeFieldKeyword) SearchAttributeKeyword { search_attribute.go
370 > return SearchAttributeKeyword{
371 > searchAttributeDefinition: searchAttributeDefinition{
372 > alias: alias,
373 > field: keywordField.field,
374 > valueType: enumspb.INDEXED_VALUE_TYPE_KEYWORD,
375 > },
376 > }
377 > }
378
379 > func newSearchAttributeKeywordByField(field string) SearchAttributeKeyword { search_attribute.go
380 > return SearchAttributeKeyword{
381 > searchAttributeDefinition: searchAttributeDefinition{
382 > alias: field,
383 > field: field,
384 > valueType: enumspb.INDEXED_VALUE_TYPE_KEYWORD,
385 > },
386 > }
387 > }
388
389 // Value sets the string value of the search attribute.
414 }
415
416 > func newSearchAttributeKeywordListByField(field string) SearchAttributeKeywordList { search_attribute.go
417 > return SearchAttributeKeywordList{
418 > searchAttributeDefinition: searchAttributeDefinition{
419 > alias: field,
420 > field: field,
421 > valueType: enumspb.INDEXED_VALUE_TYPE_KEYWORD_LIST,
422 > },
423 > }
424 > }
425
426 // Value sets the string list value of the search attribute.
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/cluster_metadata.go 104 covered LOC · 21 ranges

Open complete file

55 ctx context.Context,
56 row *sqlplugin.ClusterMetadataRow,
57 > ) (sql.Result, error) { cluster_metadata.go
58 > if row.Version == 0 {
59 > return mdb.conn.ExecContext(ctx,
60 > insertClusterMetadataQry,
61 > constMetadataPartition,
62 > row.ClusterName,
63 > row.Data,
64 > row.DataEncoding,
65 > 1,
66 > )
67 > }
68 return mdb.conn.ExecContext(ctx,
69 updateClusterMetadataQry,
79 ctx context.Context,
80 filter *sqlplugin.ClusterMetadataFilter,
81 > ) ([]sqlplugin.ClusterMetadataRow, error) { cluster_metadata.go
82 > var err error
83 > var rows []sqlplugin.ClusterMetadataRow
84 > switch {
85 case len(filter.ClusterName) != 0:
86 err = mdb.conn.SelectContext(ctx,
91 filter.PageSize,
92 )
93 > default: cluster_metadata.go
94 > err = mdb.conn.SelectContext(ctx,
95 > &rows,
96 > listClusterMetadataQry,
97 > constMetadataPartition,
98 > filter.PageSize,
99 > )
100 }
101 > return rows, err cluster_metadata.go
102 }
103
105 ctx context.Context,
106 filter *sqlplugin.ClusterMetadataFilter,
107 > ) (*sqlplugin.ClusterMetadataRow, error) { cluster_metadata.go
108 > var row sqlplugin.ClusterMetadataRow
109 > err := mdb.conn.GetContext(ctx,
110 > &row,
111 > getClusterMetadataQry,
112 > constMetadataPartition,
113 > filter.ClusterName,
114 > )
115 > if err != nil {
116 > return nil, err
117 > }
118 > return &row, err
119 }
120
122 ctx context.Context,
123 filter *sqlplugin.ClusterMetadataFilter,
124 > ) (*sqlplugin.ClusterMetadataRow, error) { cluster_metadata.go
125 > var row sqlplugin.ClusterMetadataRow
126 > err := mdb.conn.GetContext(ctx,
127 > &row,
128 > writeLockGetClusterMetadataQry,
129 > constMetadataPartition,
130 > filter.ClusterName,
131 > )
132 > if err != nil {
133 > return nil, err
134 > }
135 return &row, err
136 }
151 ctx context.Context,
152 row *sqlplugin.ClusterMembershipRow,
153 > ) (sql.Result, error) { cluster_metadata.go
154 > return mdb.conn.ExecContext(ctx,
155 > templateUpsertActiveClusterMembership,
156 > constMembershipPartition,
157 > row.HostID,
158 > row.RPCAddress,
159 > row.RPCPort,
160 > row.Role,
161 > mdb.converter.ToSQLiteDateTime(row.SessionStart),
162 > mdb.converter.ToSQLiteDateTime(row.LastHeartbeat),
163 > mdb.converter.ToSQLiteDateTime(row.RecordExpiry))
164 > }
165
166 func (mdb *db) GetClusterMembers(
167 ctx context.Context,
168 filter *sqlplugin.ClusterMembershipFilter,
169 > ) ([]sqlplugin.ClusterMembershipRow, error) { cluster_metadata.go
170 > var queryString strings.Builder
171 > var operands []any
172 > queryString.WriteString(templateGetClusterMembership)
173 > operands = append(operands, constMembershipPartition)
174 >
175 > if filter.HostIDEquals != nil {
176 queryString.WriteString(templateWithHostIDSuffix)
177 operands = append(operands, filter.HostIDEquals)
178 }
179
180 > if filter.RPCAddressEquals != "" { cluster_metadata.go
181 queryString.WriteString(templateWithRPCAddressSuffix)
182 operands = append(operands, filter.RPCAddressEquals)
183 }
184
185 > if filter.RoleEquals != p.All { cluster_metadata.go
186 queryString.WriteString(templateWithRoleSuffix)
187 operands = append(operands, filter.RoleEquals)
188 }
189
190 > if !filter.LastHeartbeatAfter.IsZero() { cluster_metadata.go
191 > queryString.WriteString(templateWithHeartbeatSinceSuffix)
192 > operands = append(operands, filter.LastHeartbeatAfter)
193 > }
194
195 > if !filter.RecordExpiryAfter.IsZero() { cluster_metadata.go
196 > queryString.WriteString(templateWithRecordExpirySuffix)
197 > operands = append(operands, filter.RecordExpiryAfter)
198 > }
199
200 > if !filter.SessionStartedAfter.IsZero() { cluster_metadata.go
201 queryString.WriteString(templateWithSessionStartSuffix)
202 operands = append(operands, filter.SessionStartedAfter)
203 }
204
205 > if filter.HostIDGreaterThan != nil { cluster_metadata.go
206 queryString.WriteString(templateWithHostIDGreaterSuffix)
207 operands = append(operands, filter.HostIDGreaterThan)
208 }
209
210 > queryString.WriteString(templateWithOrderBySessionStartSuffix) cluster_metadata.go
211 >
212 > if filter.MaxRecordCount > 0 {
213 > queryString.WriteString(templateWithLimitSuffix) cluster_metadata.go
214 > operands = append(operands, filter.MaxRecordCount)
215 > }
216
217 > compiledQryString := queryString.String() cluster_metadata.go
218 >
219 > var rows []sqlplugin.ClusterMembershipRow
220 > if err := mdb.conn.SelectContext(ctx,
221 > &rows,
222 > compiledQryString,
223 > operands...,
224 > ); err != nil {
225 return nil, err
226 }
227 > for i := range rows { cluster_metadata.go
228 > rows[i].SessionStart = mdb.converter.FromSQLiteDateTime(rows[i].SessionStart) cluster_metadata.go
229 > rows[i].LastHeartbeat = mdb.converter.FromSQLiteDateTime(rows[i].LastHeartbeat)
230 > rows[i].RecordExpiry = mdb.converter.FromSQLiteDateTime(rows[i].RecordExpiry)
231 > }
232 > return rows, nil cluster_metadata.go
233 }
234
236 ctx context.Context,
237 filter *sqlplugin.PruneClusterMembershipFilter,
238 > ) (sql.Result, error) { cluster_metadata.go
239 > return mdb.conn.ExecContext(ctx,
240 > templatePruneStaleClusterMembership,
241 > constMembershipPartition,
242 > mdb.converter.ToSQLiteDateTime(filter.PruneRecordsBefore),
243 > )
244 > }
go.temporal.io/server/common/persistence/task_manager.go 103 covered LOC · 28 ranges

Open complete file

27 store TaskStore,
28 serializer serialization.Serializer,
29 > ) TaskManager { task_manager.go
30 > return &taskManagerImpl{
31 > taskStore: store,
32 > serializer: serializer,
33 > }
34 > }
35
36 > func (m *taskManagerImpl) Close() { task_manager.go
37 > m.taskStore.Close()
38 > }
39
40 func (m *taskManagerImpl) GetName() string {
45 ctx context.Context,
46 request *CreateTaskQueueRequest,
47 > ) (*CreateTaskQueueResponse, error) { task_manager.go
48 > taskQueueInfo := request.TaskQueueInfo
49 > if taskQueueInfo.LastUpdateTime == nil {
50 panic("CreateTaskQueue encountered LastUpdateTime not set")
51 }
52 > if taskQueueInfo.ExpiryTime == nil && taskQueueInfo.GetKind() == enumspb.TASK_QUEUE_KIND_STICKY { task_manager.go
53 panic("CreateTaskQueue encountered ExpiryTime not set for sticky task queue")
54 }
55 > taskQueueInfoBlob, err := m.serializer.TaskQueueInfoToBlob(taskQueueInfo) task_manager.go
56 > if err != nil {
57 return nil, err
58 }
59
60 > internalRequest := &InternalCreateTaskQueueRequest{ task_manager.go
61 > NamespaceID: request.TaskQueueInfo.GetNamespaceId(),
62 > TaskQueue: request.TaskQueueInfo.GetName(),
63 > TaskType: request.TaskQueueInfo.GetTaskType(),
64 > TaskQueueKind: request.TaskQueueInfo.GetKind(),
65 > RangeID: request.RangeID,
66 > ExpiryTime: taskQueueInfo.ExpiryTime,
67 > TaskQueueInfo: taskQueueInfoBlob,
68 > }
69 > if err := m.taskStore.CreateTaskQueue(ctx, internalRequest); err != nil {
70 return nil, err
71 }
72 > return &CreateTaskQueueResponse{}, nil task_manager.go
73 }
74
76 ctx context.Context,
77 request *UpdateTaskQueueRequest,
78 > ) (*UpdateTaskQueueResponse, error) { task_manager.go
79 > taskQueueInfo := request.TaskQueueInfo
80 > if taskQueueInfo.LastUpdateTime == nil {
81 panic("UpdateTaskQueue encountered LastUpdateTime not set")
82 }
83 > if taskQueueInfo.ExpiryTime == nil && taskQueueInfo.GetKind() == enumspb.TASK_QUEUE_KIND_STICKY { task_manager.go
84 panic("UpdateTaskQueue encountered ExpiryTime not set for sticky task queue")
85 }
86 > taskQueueInfoBlob, err := m.serializer.TaskQueueInfoToBlob(taskQueueInfo) task_manager.go
87 > if err != nil {
88 return nil, err
89 }
90
91 > internalRequest := &InternalUpdateTaskQueueRequest{ task_manager.go
92 > NamespaceID: request.TaskQueueInfo.GetNamespaceId(),
93 > TaskQueue: request.TaskQueueInfo.GetName(),
94 > TaskType: request.TaskQueueInfo.GetTaskType(),
95 > RangeID: request.RangeID,
96 > TaskQueueInfo: taskQueueInfoBlob,
97 >
98 > TaskQueueKind: request.TaskQueueInfo.GetKind(),
99 > ExpiryTime: taskQueueInfo.ExpiryTime,
100 >
101 > PrevRangeID: request.PrevRangeID,
102 > }
103 > return m.taskStore.UpdateTaskQueue(ctx, internalRequest)
104 }
105
107 ctx context.Context,
108 request *GetTaskQueueRequest,
109 > ) (*GetTaskQueueResponse, error) { task_manager.go
110 > response, err := m.taskStore.GetTaskQueue(ctx, &InternalGetTaskQueueRequest{
111 > NamespaceID: request.NamespaceID,
112 > TaskQueue: request.TaskQueue,
113 > TaskType: request.TaskType,
114 > })
115 > if err != nil {
116 > return nil, err task_manager.go
117 > }
118
119 > taskQueueInfo, err := m.serializer.TaskQueueInfoFromBlob(response.TaskQueueInfo) task_manager.go
120 > if err != nil {
121 return nil, err
122 }
123 > return &GetTaskQueueResponse{ task_manager.go
124 > TaskQueueInfo: taskQueueInfo,
125 > RangeID: response.RangeID,
126 > }, nil
127 }
128
163 ctx context.Context,
164 request *CreateTasksRequest,
165 > ) (*CreateTasksResponse, error) { task_manager.go
166 > taskQueueInfo := request.TaskQueueInfo.Data
167 >
168 > var taskQueueInfoBlob *commonpb.DataBlob
169 > if request.UpdateMetadata {
170 taskQueueInfo.LastUpdateTime = timestamp.TimeNowPtrUtc()
171 var err error
176 }
177
178 > tasks := make([]*InternalCreateTask, len(request.Tasks)) task_manager.go
179 > for i, task := range request.Tasks {
180 > taskBlob, err := m.serializer.TaskInfoToBlob(task)
181 > if err != nil {
182 return nil, serviceerror.NewUnavailablef("CreateTasks operation failed during serialization. Error : %v", err)
183 }
184 > tasks[i] = &InternalCreateTask{ task_manager.go
185 > TaskPass: task.TaskPass,
186 > TaskId: task.TaskId,
187 > ExpiryTime: task.Data.ExpiryTime,
188 > Task: taskBlob,
189 > }
190 > if i < len(request.Subqueues) {
191 > tasks[i].Subqueue = request.Subqueues[i] task_manager.go
192 > }
193 }
194 > internalRequest := &InternalCreateTasksRequest{ task_manager.go
195 > NamespaceID: taskQueueInfo.GetNamespaceId(),
196 > TaskQueue: taskQueueInfo.GetName(),
197 > TaskType: taskQueueInfo.GetTaskType(),
198 > RangeID: request.TaskQueueInfo.RangeID,
199 > TaskQueueInfo: taskQueueInfoBlob,
200 > Tasks: tasks,
201 > UpdateMetadata: request.UpdateMetadata,
202 > }
203 > return m.taskStore.CreateTasks(ctx, internalRequest)
204 }
205
207 ctx context.Context,
208 request *GetTasksRequest,
209 > ) (*GetTasksResponse, error) { task_manager.go
210 > if request.InclusiveMinTaskID >= request.ExclusiveMaxTaskID {
211 return &GetTasksResponse{}, nil
212 }
213
214 > internalResp, err := m.taskStore.GetTasks(ctx, request) task_manager.go
215 > if err != nil {
216 return nil, err
217 }
218 > tasks := make([]*persistencespb.AllocatedTaskInfo, len(internalResp.Tasks)) task_manager.go
219 > for i, taskBlob := range internalResp.Tasks {
220 > task, err := m.serializer.TaskInfoFromBlob(taskBlob) task_manager.go
221 > if err != nil {
222 return nil, serviceerror.NewUnavailablef("GetTasks failed to deserialize task: %s", err.Error())
223 }
224 > tasks[i] = task task_manager.go
225 }
226 > return &GetTasksResponse{Tasks: tasks, NextPageToken: internalResp.NextPageToken}, nil task_manager.go
227 }
228
235
236 // GetTaskQueueUserData implements TaskManager
237 > func (m *taskManagerImpl) GetTaskQueueUserData(ctx context.Context, request *GetTaskQueueUserDataRequest) (*GetTaskQueueUserDataResponse, error) { task_manager.go
238 > response, err := m.taskStore.GetTaskQueueUserData(ctx, request)
239 > if err != nil {
240 > return nil, err task_manager.go
241 > }
242 data, err := m.serializer.TaskQueueUserDataFromBlob(response.UserData)
243 if err != nil {
go.temporal.io/server/service/history/queues/scheduler.go 103 covered LOC · 14 ranges

Open complete file

100 metricsHandler metrics.Handler,
101 timeSource clock.TimeSource,
102 > ) Scheduler { scheduler.go
103 > var scheduler tasks.Scheduler[Executable]
104 >
105 > taskChannelKeyFn := func(e Executable) TaskChannelKey {
106 return TaskChannelKey{
107 NamespaceID: e.GetNamespaceID(),
109 }
110 }
111 > channelWeightFn := func(key TaskChannelKey) int { scheduler.go
112 namespaceWeights := options.ActiveNamespaceWeights
113 namespaceName := namespace.EmptyName
143 return weight
144 }
145 > channelWeightUpdateCh := make(chan struct{}, 1) scheduler.go
146 > fifoSchedulerOptions := &tasks.FIFOSchedulerOptions{
147 > QueueSize: prioritySchedulerProcessorQueueSize,
148 > WorkerCount: options.WorkerCount,
149 > }
150 >
151 > fifoScheduler := tasks.NewFIFOScheduler[Executable](
152 > fifoSchedulerOptions,
153 > logger,
154 > )
155 >
156 > // Wrap the FIFO scheduler with ExecutionAwareScheduler for sequential per-execution processing
157 > executionAwareScheduler := tasks.NewExecutionAwareScheduler[Executable](
158 > fifoScheduler,
159 > options.ExecutionAwareSchedulerOptions,
160 > executableQueueKeyFn,
161 > logger,
162 > metricsHandler,
163 > timeSource,
164 > )
165 >
166 > scheduler = tasks.NewInterleavedWeightedRoundRobinScheduler(
167 > tasks.InterleavedWeightedRoundRobinSchedulerOptions[Executable, TaskChannelKey]{
168 > TaskChannelKeyFn: taskChannelKeyFn,
169 > ChannelWeightFn: channelWeightFn,
170 > ChannelWeightUpdateCh: channelWeightUpdateCh,
171 > InactiveChannelDeletionDelay: options.InactiveNamespaceDeletionDelay,
172 > },
173 > executionAwareScheduler,
174 > logger,
175 > )
176 >
177 > return &schedulerImpl{
178 > Scheduler: scheduler,
179 > namespaceRegistry: namespaceRegistry,
180 > taskChannelKeyFn: taskChannelKeyFn,
181 > channelWeightFn: channelWeightFn,
182 > channelWeightUpdateCh: channelWeightUpdateCh,
183 > executionAwareScheduler: executionAwareScheduler,
184 > }
185 }
186
187 > func (s *schedulerImpl) Start() { scheduler.go
188 > if s.channelWeightUpdateCh != nil {
189 > s.namespaceRegistry.RegisterStateChangeCallback(s, func(ns *namespace.Namespace, deletedFromDb bool) {
190 > select {
191 > case s.channelWeightUpdateCh <- struct{}{}:
192 > default:
193 }
194 })
195 }
196 > s.Scheduler.Start() scheduler.go
197 }
198
199 > func (s *schedulerImpl) Stop() { scheduler.go
200 > if s.channelWeightUpdateCh != nil {
201 > s.namespaceRegistry.UnregisterStateChangeCallback(s)
202 >
203 > // note we can't close the channelWeightUpdateCh here
204 > // as callback may still be triggered even after unregister returns
205 > // due to race condition
206 > //
207 > // channelWeightFn is only not nil when using host level scheduler
208 > // so Stop is only called when host is shutting down, and we don't need
209 > // to worry about open channels
210 > }
211 > s.Scheduler.Stop()
212 }
213
214 > func (s *schedulerImpl) TaskChannelKeyFn() TaskChannelKeyFn { scheduler.go
215 > return s.taskChannelKeyFn
216 > }
217
218 // HandleBusyWorkflow implements BusyWorkflowHandler by delegating to the
230 }
231
232 > func (s *CommonSchedulerWrapper) TaskChannelKeyFn() TaskChannelKeyFn { scheduler.go
233 > return s.TaskKeyFn
234 > }
235
236 func NewRateLimitedScheduler(
244 logger log.Logger,
245 metricsHandler metrics.Handler,
246 > ) Scheduler { scheduler.go
247 > if delay := options.StartupDelay(); delay > 0 {
248 > delayedRateLimiter, err := quotas.NewDelayedRequestRateLimiter(
249 > rateLimiter,
250 > delay,
251 > timeSource,
252 > )
253 > if err != nil {
254 logger.Error("Failed to create delayed rate limited scheduler", tag.Error(err))
255 return baseScheduler
256 }
257
258 > rateLimiter = delayedRateLimiter scheduler.go
259 }
260
261 > taskQuotaRequestFn := func(e Executable) quotas.Request { scheduler.go
262 namespaceName, err := namespaceRegistry.GetNamespaceName(namespace.ID(e.GetNamespaceID()))
263 if err != nil {
266 return quotas.NewRequest(e.GetType().String(), taskSchedulerToken, namespaceName.String(), e.GetPriority().CallerType(), 0, "")
267 }
268 > taskMetricsTagsFn := func(e Executable) []metrics.Tag { scheduler.go
269 return append(
270 taskBaseMetricTags(e.GetTask(), namespaceRegistry, currentClusterName, chasmRegistry, GetTaskTypeTagValue),
273 }
274
275 > rateLimitedScheduler := tasks.NewRateLimitedScheduler[Executable]( scheduler.go
276 > baseScheduler,
277 > rateLimiter,
278 > timeSource,
279 > taskQuotaRequestFn,
280 > taskMetricsTagsFn,
281 > tasks.RateLimitedSchedulerOptions{
282 > Enabled: options.Enabled,
283 > EnableShadowMode: options.EnableShadowMode,
284 > },
285 > logger,
286 > metricsHandler,
287 > )
288 >
289 > return &rateLimitedSchedulerImpl{
290 > Scheduler: rateLimitedScheduler,
291 > baseScheduler: baseScheduler,
292 > }
293 }
294
301 }
302
303 > func (s *rateLimitedSchedulerImpl) TaskChannelKeyFn() TaskChannelKeyFn { scheduler.go
304 > return s.baseScheduler.TaskChannelKeyFn()
305 > }
306
307 // HandleBusyWorkflow implements BusyWorkflowHandler by delegating to the
go.temporal.io/server/chasm/lib/activity/gen/activitypb/v1/request_response.pb.go 102 covered LOC · 41 ranges

Open complete file

45 func (*StartActivityExecutionRequest) ProtoMessage() {}
46
47 > func (x *StartActivityExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
48 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[0]
49 > if x != nil {
50 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
51 if ms.LoadMessageInfo() == nil {
96 func (*StartActivityExecutionResponse) ProtoMessage() {}
97
98 > func (x *StartActivityExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
99 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[1]
100 > if x != nil {
101 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
102 if ms.LoadMessageInfo() == nil {
141 func (*DescribeActivityExecutionRequest) ProtoMessage() {}
142
143 > func (x *DescribeActivityExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
144 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[2]
145 > if x != nil {
146 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
147 if ms.LoadMessageInfo() == nil {
192 func (*DescribeActivityExecutionResponse) ProtoMessage() {}
193
194 > func (x *DescribeActivityExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
195 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[3]
196 > if x != nil {
197 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
198 if ms.LoadMessageInfo() == nil {
237 func (*PollActivityExecutionRequest) ProtoMessage() {}
238
239 > func (x *PollActivityExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
240 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[4]
241 > if x != nil {
242 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
243 if ms.LoadMessageInfo() == nil {
288 func (*PollActivityExecutionResponse) ProtoMessage() {}
289
290 > func (x *PollActivityExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
291 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[5]
292 > if x != nil {
293 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
294 if ms.LoadMessageInfo() == nil {
333 func (*TerminateActivityExecutionRequest) ProtoMessage() {}
334
335 > func (x *TerminateActivityExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
336 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[6]
337 > if x != nil {
338 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
339 if ms.LoadMessageInfo() == nil {
383 func (*TerminateActivityExecutionResponse) ProtoMessage() {}
384
385 > func (x *TerminateActivityExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
386 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[7]
387 > if x != nil {
388 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
389 if ms.LoadMessageInfo() == nil {
421 func (*RequestCancelActivityExecutionRequest) ProtoMessage() {}
422
423 > func (x *RequestCancelActivityExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
424 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[8]
425 > if x != nil {
426 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
427 if ms.LoadMessageInfo() == nil {
471 func (*RequestCancelActivityExecutionResponse) ProtoMessage() {}
472
473 > func (x *RequestCancelActivityExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
474 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[9]
475 > if x != nil {
476 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
477 if ms.LoadMessageInfo() == nil {
509 func (*DeleteActivityExecutionRequest) ProtoMessage() {}
510
511 > func (x *DeleteActivityExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
512 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[10]
513 > if x != nil {
514 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
515 if ms.LoadMessageInfo() == nil {
559 func (*DeleteActivityExecutionResponse) ProtoMessage() {}
560
561 > func (x *DeleteActivityExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
562 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[11]
563 > if x != nil {
564 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
565 if ms.LoadMessageInfo() == nil {
597 func (*PauseActivityExecutionRequest) ProtoMessage() {}
598
599 > func (x *PauseActivityExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
600 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[12]
601 > if x != nil {
602 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
603 if ms.LoadMessageInfo() == nil {
647 func (*PauseActivityExecutionResponse) ProtoMessage() {}
648
649 > func (x *PauseActivityExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
650 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[13]
651 > if x != nil {
652 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
653 if ms.LoadMessageInfo() == nil {
685 func (*UnpauseActivityExecutionRequest) ProtoMessage() {}
686
687 > func (x *UnpauseActivityExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
688 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[14]
689 > if x != nil {
690 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
691 if ms.LoadMessageInfo() == nil {
735 func (*UnpauseActivityExecutionResponse) ProtoMessage() {}
736
737 > func (x *UnpauseActivityExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
738 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[15]
739 > if x != nil {
740 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
741 if ms.LoadMessageInfo() == nil {
773 func (*ResetActivityExecutionRequest) ProtoMessage() {}
774
775 > func (x *ResetActivityExecutionRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
776 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[16]
777 > if x != nil {
778 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
779 if ms.LoadMessageInfo() == nil {
823 func (*ResetActivityExecutionResponse) ProtoMessage() {}
824
825 > func (x *ResetActivityExecutionResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
826 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[17]
827 > if x != nil {
828 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
829 if ms.LoadMessageInfo() == nil {
861 func (*UpdateActivityExecutionOptionsRequest) ProtoMessage() {}
862
863 > func (x *UpdateActivityExecutionOptionsRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
864 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[18]
865 > if x != nil {
866 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
867 if ms.LoadMessageInfo() == nil {
912 func (*UpdateActivityExecutionOptionsResponse) ProtoMessage() {}
913
914 > func (x *UpdateActivityExecutionOptionsResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
915 > mi := &file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes[19]
916 > if x != nil {
917 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
918 if ms.LoadMessageInfo() == nil {
1057 }
1058
1059 > func init() { file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_init() } request_response.pb.go
1060 > func file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_init() {
1061 > if File_temporal_server_chasm_lib_activity_proto_v1_request_response_proto != nil {
1062 > return
1063 > }
1064 > type x struct{}
1065 > out := protoimpl.TypeBuilder{
1066 > File: protoimpl.DescBuilder{
1067 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1068 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_rawDesc), len(file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_rawDesc)),
1069 > NumEnums: 0,
1070 > NumMessages: 20,
1071 > NumExtensions: 0,
1072 > NumServices: 0,
1073 > },
1074 > GoTypes: file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_goTypes,
1075 > DependencyIndexes: file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_depIdxs,
1076 > MessageInfos: file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_msgTypes,
1077 > }.Build()
1078 > File_temporal_server_chasm_lib_activity_proto_v1_request_response_proto = out.File
1079 > file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_goTypes = nil
1080 > file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_depIdxs = nil
1081 }
go.temporal.io/server/service/history/events/notifier.go 102 covered LOC · 24 ranges

Open complete file

81 versionHistories *historyspb.VersionHistories,
82 transitionHistory []*persistencespb.VersionedTransition,
83 > ) *Notification { notifier.go
84 >
85 > return &Notification{
86 > ID: definition.NewWorkflowKey(
87 > namespaceID,
88 > workflowExecution.GetWorkflowId(),
89 > workflowExecution.GetRunId(),
90 > ),
91 > LastFirstEventID: lastFirstEventID,
92 > LastFirstEventTxnID: lastFirstEventTxnID,
93 > NextEventID: nextEventID,
94 > PreviousStartedEventID: previousStartedEventID,
95 > WorkflowState: workflowState,
96 > WorkflowStatus: workflowStatus,
97 > VersionHistories: versionhistory.CopyVersionHistories(versionHistories),
98 > TransitionHistory: transitionhistory.CopyVersionedTransitions(transitionHistory),
99 > }
100 > }
101
102 func NewNotifier(
104 metricsHandler metrics.Handler,
105 workflowIDToShardID func(namespace.ID, string) int32,
106 > ) *NotifierImpl { notifier.go
107 >
108 > hashFn := func(key any) uint32 {
109 > notification, ok := key.(Notification) notifier.go
110 > if !ok {
111 > return 0
112 > }
113 return uint32(workflowIDToShardID(namespace.ID(notification.ID.NamespaceID), notification.ID.WorkflowID))
114 }
115 > return &NotifierImpl{ notifier.go
116 > timeSource: timeSource,
117 > metricsHandler: metricsHandler.WithTags(metrics.OperationTag(metrics.HistoryEventNotificationScope)),
118 > status: common.DaemonStatusInitialized,
119 > closeChan: make(chan bool),
120 > eventsChan: make(chan *Notification, eventsChanSize),
121 >
122 > workflowIDToShardID: workflowIDToShardID,
123 >
124 > eventsPubsubs: collection.NewShardedConcurrentTxMap(1024, hashFn),
125 > }
126 }
127
128 func (notifier *NotifierImpl) WatchHistoryEvent(
129 > identifier definition.WorkflowKey) (string, chan *Notification, error) { notifier.go
130 >
131 > channel := make(chan *Notification, 1)
132 > subscriberID := uuid.NewString()
133 > subscribers := map[string]chan *Notification{
134 > subscriberID: channel,
135 > }
136 >
137 > _, _, err := notifier.eventsPubsubs.PutOrDo(identifier, subscribers, func(key any, value any) error {
138 subscribers := value.(map[string]chan *Notification)
139
146 })
147
148 > if err != nil { notifier.go
149 return "", nil, err
150 }
151
152 > return subscriberID, channel, nil notifier.go
153 }
154
155 func (notifier *NotifierImpl) UnwatchHistoryEvent(
156 > identifier definition.WorkflowKey, subscriberID string) error { notifier.go
157 >
158 > success := true
159 > notifier.eventsPubsubs.RemoveIf(identifier, func(key any, value any) bool {
160 > subscribers := value.(map[string]chan *Notification)
161 >
162 > if _, ok := subscribers[subscriberID]; !ok {
163 // cannot find the subscribe ID, which means there is a bug
164 success = false
165 > } else { notifier.go
166 > delete(subscribers, subscriberID)
167 > }
168
169 > return len(subscribers) == 0 notifier.go
170 })
171
172 > if !success { notifier.go
173 // cannot find the subscribe ID, which means there is a bug
174 return serviceerror.NewInternal("Unable to unwatch on workflow execution.")
175 }
176
177 > return nil notifier.go
178 }
179
180 > func (notifier *NotifierImpl) dispatchHistoryEventNotification(event *Notification) { notifier.go
181 > identifier := event.ID
182 >
183 > startTime := time.Now().UTC()
184 > defer func() {
185 > metrics.HistoryEventNotificationFanoutLatency.With(notifier.metricsHandler).Record(time.Since(startTime))
186 > }()
187 > _, _, _ = notifier.eventsPubsubs.GetAndDo(identifier, func(key any, value any) error {
188 > subscribers := value.(map[string]chan *Notification) notifier.go
189 >
190 > for _, channel := range subscribers {
191 > select {
192 > case channel <- event:
193 default:
194 // in case the channel is already filled with message
196 }
197 }
198 > return nil notifier.go
199 })
200 }
201
202 > func (notifier *NotifierImpl) enqueueHistoryEventNotification(event *Notification) { notifier.go
203 > // set the Timestamp just before enqueuing the event
204 > event.Timestamp = notifier.timeSource.Now()
205 > select {
206 > case notifier.eventsChan <- event:
207 default:
208 // in case the channel is already filled with message
212 }
213
214 > func (notifier *NotifierImpl) dequeueHistoryEventNotifications() { notifier.go
215 > for {
216 > // send out metrics about the current number of messages in flight
217 > metrics.HistoryEventNotificationInFlightMessageGauge.With(notifier.metricsHandler).Record(float64(len(notifier.eventsChan)))
218 > select {
219 > case event := <-notifier.eventsChan: notifier.go
220 > // send out metrics about message processing delay
221 > timeelapsed := time.Since(event.Timestamp)
222 > metrics.HistoryEventNotificationQueueingLatency.With(notifier.metricsHandler).Record(timeelapsed)
223 >
224 > notifier.dispatchHistoryEventNotification(event)
225 > case <-notifier.closeChan: notifier.go
226 > // shutdown
227 > return
228 }
229 }
230 }
231
232 > func (notifier *NotifierImpl) Start() { notifier.go
233 > if !atomic.CompareAndSwapInt32(&notifier.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
234 return
235 }
236 > go notifier.dequeueHistoryEventNotifications() notifier.go
237 }
238
239 > func (notifier *NotifierImpl) Stop() { notifier.go
240 > if !atomic.CompareAndSwapInt32(&notifier.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
241 return
242 }
243 > close(notifier.closeChan) notifier.go
244 }
245
246 > func (notifier *NotifierImpl) NotifyNewHistoryEvent(event *Notification) { notifier.go
247 > notifier.enqueueHistoryEventNotification(event)
248 > }
go.temporal.io/server/common/tasks/fifo_scheduler.go 101 covered LOC · 31 ranges

Open complete file

42 options *FIFOSchedulerOptions,
43 logger log.Logger,
44 > ) *FIFOScheduler[T] { fifo_scheduler.go
45 > return &FIFOScheduler[T]{
46 > status: common.DaemonStatusInitialized,
47 > options: options,
48 >
49 > logger: logger,
50 >
51 > tasksChan: make(chan T, options.QueueSize),
52 > }
53 > }
54
55 > func (f *FIFOScheduler[T]) Start() { fifo_scheduler.go
56 > if !atomic.CompareAndSwapInt32(
57 > &f.status,
58 > common.DaemonStatusInitialized,
59 > common.DaemonStatusStarted,
60 > ) {
61 return
62 }
63
64 > initialWorkerCount, workerCountSubscriptionCancelFn := f.options.WorkerCount(f.updateWorkerCount) fifo_scheduler.go
65 > f.workerCountSubscriptionCancelFn = workerCountSubscriptionCancelFn
66 > f.updateWorkerCount(initialWorkerCount)
67 >
68 > f.logger.Info("fifo scheduler started")
69 }
70
71 > func (f *FIFOScheduler[T]) Stop() { fifo_scheduler.go
72 > if !atomic.CompareAndSwapInt32(
73 > &f.status,
74 > common.DaemonStatusStarted,
75 > common.DaemonStatusStopped,
76 > ) {
77 return
78 }
79
80 > f.workerCountSubscriptionCancelFn() fifo_scheduler.go
81 > f.updateWorkerCount(0)
82 > f.drainTasks()
83 >
84 > go func() {
85 > if success := common.AwaitWaitGroup(&f.shutdownWG, time.Minute); !success {
86 f.logger.Warn("fifo scheduler timed out waiting for workers")
87 }
88 }()
89 > f.logger.Info("fifo scheduler stopped") fifo_scheduler.go
90 }
91
97 }
98
99 > func (f *FIFOScheduler[T]) TrySubmit(task T) bool { fifo_scheduler.go
100 > select {
101 > case f.tasksChan <- task:
102 > if f.isStopped() {
103 f.drainTasks()
104 }
105 > return true fifo_scheduler.go
106 default:
107 return false
109 }
110
111 > func (f *FIFOScheduler[T]) updateWorkerCount(targetWorkerNum int) { fifo_scheduler.go
112 > f.workerLock.Lock()
113 > defer f.workerLock.Unlock()
114 >
115 > if f.isStopped() {
116 > // Always set the value to 0 when scheduler is stopped, fifo_scheduler.go
117 > // in case there's a race condition between subscription callback invocation
118 > // and the invocation made from Stop()
119 > targetWorkerNum = 0
120 > }
121
122 > if targetWorkerNum < 0 { fifo_scheduler.go
123 f.logger.Error("Target worker pool size is negative. Please fix the dynamic config.", tag.Key("worker-pool-size"), tag.Value(targetWorkerNum))
124 return
125 }
126
127 > currentWorkerNum := len(f.workerShutdownCh) fifo_scheduler.go
128 > if targetWorkerNum == currentWorkerNum {
129 return
130 }
131
132 > if targetWorkerNum > currentWorkerNum { fifo_scheduler.go
133 > f.startWorkers(targetWorkerNum - currentWorkerNum)
134 > } else {
135 > f.stopWorkers(currentWorkerNum - targetWorkerNum) fifo_scheduler.go
136 > }
137
138 > f.logger.Info("Update worker pool size", tag.Key("worker-pool-size"), tag.Value(targetWorkerNum)) fifo_scheduler.go
139 }
140
141 func (f *FIFOScheduler[T]) startWorkers(
142 count int,
143 > ) { fifo_scheduler.go
144 > for range count {
145 > shutdownCh := make(chan struct{})
146 > f.workerShutdownCh = append(f.workerShutdownCh, shutdownCh)
147 >
148 > f.shutdownWG.Add(1)
149 > go f.processTask(shutdownCh)
150 > }
151 }
152
153 func (f *FIFOScheduler[T]) stopWorkers(
154 count int,
155 > ) { fifo_scheduler.go
156 > shutdownChToClose := f.workerShutdownCh[:count]
157 > f.workerShutdownCh = f.workerShutdownCh[count:]
158 >
159 > for _, shutdownCh := range shutdownChToClose {
160 > close(shutdownCh)
161 > }
162 }
163
164 func (f *FIFOScheduler[T]) processTask(
165 shutdownCh chan struct{},
166 > ) { fifo_scheduler.go
167 > defer f.shutdownWG.Done()
168 >
169 > for {
170 > if f.isStopped() {
171 return
172 }
173
174 > select { fifo_scheduler.go
175 case <-shutdownCh:
176 return
177 > default: fifo_scheduler.go
178 }
179
180 > select { fifo_scheduler.go
181 > case task := <-f.tasksChan: fifo_scheduler.go
182 > f.executeTask(task)
183
184 > case <-shutdownCh: fifo_scheduler.go
185 > return
186 }
187 }
190 func (f *FIFOScheduler[T]) executeTask(
191 task T,
192 > ) { fifo_scheduler.go
193 > operation := func() error {
194 > if err := task.Execute(); err != nil {
195 return task.HandleErr(err)
196 }
197 > return nil fifo_scheduler.go
198 }
199
200 > isRetryable := func(err error) bool { fifo_scheduler.go
201 return !f.isStopped() && task.IsRetryableError(err)
202 }
203
204 > if err := backoff.ThrottleRetry(operation, task.RetryPolicy(), isRetryable); err != nil { fifo_scheduler.go
205 if f.isStopped() {
206 task.Abort()
212 }
213
214 > task.Ack() fifo_scheduler.go
215 }
216
217 > func (f *FIFOScheduler[T]) drainTasks() { fifo_scheduler.go
218 > LoopDrain:
219 > for {
220 > select {
221 case task := <-f.tasksChan:
222 task.Abort()
223 > default: fifo_scheduler.go
224 > break LoopDrain
225 }
226 }
227 }
228
229 > func (f *FIFOScheduler[T]) isStopped() bool { fifo_scheduler.go
230 > return atomic.LoadInt32(&f.status) == common.DaemonStatusStopped
231 > }
go.temporal.io/server/common/persistence/sql/execution_state_map.go 100 covered LOC · 36 ranges

Open complete file

23 workflowID string,
24 runID primitives.UUID,
25 > ) error { execution_state_map.go
26 >
27 > if len(activityInfos) > 0 {
28 rows := make([]sqlplugin.ActivityInfoMapsRow, 0, len(activityInfos))
29 for scheduledEventId, blob := range activityInfos {
44 }
45
46 > if len(deleteIDs) > 0 { execution_state_map.go
47 if _, err := tx.DeleteFromActivityInfoMaps(ctx, sqlplugin.ActivityInfoMapsFilter{
48 ShardID: shardID,
65 workflowID string,
66 runID primitives.UUID,
67 > ) (map[int64]*commonpb.DataBlob, error) { execution_state_map.go
68 >
69 > rows, err := db.SelectAllFromActivityInfoMaps(ctx, sqlplugin.ActivityInfoMapsAllFilter{
70 > ShardID: shardID,
71 > NamespaceID: namespaceID,
72 > WorkflowID: workflowID,
73 > RunID: runID,
74 > })
75 > if err != nil && err != sql.ErrNoRows {
76 return nil, serviceerror.NewUnavailablef("Failed to get activity info. Error: %v", err)
77 }
78
79 > ret := make(map[int64]*commonpb.DataBlob) execution_state_map.go
80 > for _, row := range rows {
81 ret[row.ScheduleID] = persistence.NewDataBlob(row.Data, row.DataEncoding)
82 }
83
84 > return ret, nil execution_state_map.go
85 }
86
114 workflowID string,
115 runID primitives.UUID,
116 > ) error { execution_state_map.go
117 >
118 > if len(timerInfos) > 0 {
119 rows := make([]sqlplugin.TimerInfoMapsRow, 0, len(timerInfos))
120 for timerID, blob := range timerInfos {
134 }
135
136 > if len(deleteIDs) > 0 { execution_state_map.go
137 if _, err := tx.DeleteFromTimerInfoMaps(ctx, sqlplugin.TimerInfoMapsFilter{
138 ShardID: shardID,
155 workflowID string,
156 runID primitives.UUID,
157 > ) (map[string]*commonpb.DataBlob, error) { execution_state_map.go
158 >
159 > rows, err := db.SelectAllFromTimerInfoMaps(ctx, sqlplugin.TimerInfoMapsAllFilter{
160 > ShardID: shardID,
161 > NamespaceID: namespaceID,
162 > WorkflowID: workflowID,
163 > RunID: runID,
164 > })
165 > if err != nil && err != sql.ErrNoRows {
166 return nil, serviceerror.NewUnavailablef("Failed to get timer info. Error: %v", err)
167 }
168 > ret := make(map[string]*commonpb.DataBlob) execution_state_map.go
169 > for _, row := range rows {
170 ret[row.TimerID] = persistence.NewDataBlob(row.Data, row.DataEncoding)
171 }
172
173 > return ret, nil execution_state_map.go
174 }
175
203 workflowID string,
204 runID primitives.UUID,
205 > ) error { execution_state_map.go
206 >
207 > if len(childExecutionInfos) > 0 {
208 rows := make([]sqlplugin.ChildExecutionInfoMapsRow, 0, len(childExecutionInfos))
209 for initiatedID, blob := range childExecutionInfos {
223 }
224
225 > if len(deleteIDs) > 0 { execution_state_map.go
226 if _, err := tx.DeleteFromChildExecutionInfoMaps(ctx, sqlplugin.ChildExecutionInfoMapsFilter{
227 ShardID: shardID,
244 workflowID string,
245 runID primitives.UUID,
246 > ) (map[int64]*commonpb.DataBlob, error) { execution_state_map.go
247 >
248 > rows, err := db.SelectAllFromChildExecutionInfoMaps(ctx, sqlplugin.ChildExecutionInfoMapsAllFilter{
249 > ShardID: shardID,
250 > NamespaceID: namespaceID,
251 > WorkflowID: workflowID,
252 > RunID: runID,
253 > })
254 > if err != nil && err != sql.ErrNoRows {
255 return nil, serviceerror.NewUnavailablef("Failed to get timer info. Error: %v", err)
256 }
257
258 > ret := make(map[int64]*commonpb.DataBlob) execution_state_map.go
259 > for _, row := range rows {
260 ret[row.InitiatedID] = persistence.NewDataBlob(row.Data, row.DataEncoding)
261 }
262
263 > return ret, nil execution_state_map.go
264 }
265
293 workflowID string,
294 runID primitives.UUID,
295 > ) error { execution_state_map.go
296 >
297 > if len(requestCancelInfos) > 0 {
298 rows := make([]sqlplugin.RequestCancelInfoMapsRow, 0, len(requestCancelInfos))
299 for initiatedID, blob := range requestCancelInfos {
314 }
315
316 > if len(deleteIDs) > 0 { execution_state_map.go
317 if _, err := tx.DeleteFromRequestCancelInfoMaps(ctx, sqlplugin.RequestCancelInfoMapsFilter{
318 ShardID: shardID,
335 workflowID string,
336 runID primitives.UUID,
337 > ) (map[int64]*commonpb.DataBlob, error) { execution_state_map.go
338 >
339 > rows, err := db.SelectAllFromRequestCancelInfoMaps(ctx, sqlplugin.RequestCancelInfoMapsAllFilter{
340 > ShardID: shardID,
341 > NamespaceID: namespaceID,
342 > WorkflowID: workflowID,
343 > RunID: runID,
344 > })
345 > if err != nil && err != sql.ErrNoRows {
346 return nil, serviceerror.NewUnavailablef("Failed to get request cancel info. Error: %v", err)
347 }
348
349 > ret := make(map[int64]*commonpb.DataBlob) execution_state_map.go
350 > for _, row := range rows {
351 ret[row.InitiatedID] = persistence.NewDataBlob(row.Data, row.DataEncoding)
352 }
353
354 > return ret, nil execution_state_map.go
355 }
356
384 workflowID string,
385 runID primitives.UUID,
386 > ) error { execution_state_map.go
387 >
388 > if len(signalInfos) > 0 {
389 rows := make([]sqlplugin.SignalInfoMapsRow, 0, len(signalInfos))
390 for initiatedId, blob := range signalInfos {
405 }
406
407 > if len(deleteIDs) > 0 { execution_state_map.go
408 if _, err := tx.DeleteFromSignalInfoMaps(ctx, sqlplugin.SignalInfoMapsFilter{
409 ShardID: shardID,
426 workflowID string,
427 runID primitives.UUID,
428 > ) (map[int64]*commonpb.DataBlob, error) { execution_state_map.go
429 >
430 > rows, err := db.SelectAllFromSignalInfoMaps(ctx, sqlplugin.SignalInfoMapsAllFilter{
431 > ShardID: shardID,
432 > NamespaceID: namespaceID,
433 > WorkflowID: workflowID,
434 > RunID: runID,
435 > })
436 > if err != nil && err != sql.ErrNoRows {
437 return nil, serviceerror.NewUnavailablef("Failed to get signal info. Error: %v", err)
438 }
439
440 > ret := make(map[int64]*commonpb.DataBlob) execution_state_map.go
441 > for _, row := range rows {
442 ret[row.InitiatedID] = persistence.NewDataBlob(row.Data, row.DataEncoding)
443 }
444
445 > return ret, nil execution_state_map.go
446 }
447
475 workflowID string,
476 runID primitives.UUID,
477 > ) error { execution_state_map.go
478 > if len(chasmNodes) > 0 {
479 rows := make([]sqlplugin.ChasmNodeMapsRow, 0, len(chasmNodes))
480 for path, node := range chasmNodes {
499 }
500
501 > if len(deleteIDs) > 0 { execution_state_map.go
502 if _, err := tx.DeleteFromChasmNodeMaps(ctx, sqlplugin.ChasmNodeMapsFilter{
503 ShardID: shardID,
521 workflowID string,
522 runID primitives.UUID,
523 > ) (map[string]persistence.InternalChasmNode, error) { execution_state_map.go
524 > rows, err := db.SelectAllFromChasmNodeMaps(ctx, sqlplugin.ChasmNodeMapsAllFilter{
525 > ShardID: shardID,
526 > NamespaceID: namespaceID,
527 > WorkflowID: workflowID,
528 > RunID: runID,
529 > })
530 > if err != nil && err != sql.ErrNoRows {
531 return nil, serviceerror.NewUnavailablef("Failed to get CHASM nodes. Error: %v", err)
532 }
533
534 > ret := make(map[string]persistence.InternalChasmNode) execution_state_map.go
535 > for _, row := range rows {
536 ret[row.ChasmPath] = persistence.InternalChasmNode{
537 Metadata: persistence.NewDataBlob(row.Metadata, row.MetadataEncoding),
go.temporal.io/server/service/matching/nexus_endpoint_client.go 99 covered LOC · 23 ranges

Open complete file

74 endpointsRefreshInterval dynamicconfig.DurationPropertyFn,
75 persistence p.NexusEndpointManager,
76 > ) *nexusEndpointClient { nexus_endpoint_client.go
77 > return &nexusEndpointClient{
78 > endpointsRefreshInterval: endpointsRefreshInterval,
79 > persistence: persistence,
80 > tableVersionChanged: make(chan struct{}),
81 > }
82 > }
83
84 func (m *nexusEndpointClient) CreateNexusEndpoint(
243 ctx context.Context,
244 request *matchingservice.ListNexusEndpointsRequest,
245 > ) (*matchingservice.ListNexusEndpointsResponse, chan struct{}, error) { nexus_endpoint_client.go
246 > m.RLock()
247 > if request.LastKnownTableVersion > m.tableVersion {
248 // indicates we may have lost table ownership, so need to reload from persistence
249 m.hasLoadedEndpoints.Store(false)
250 }
251 > m.RUnlock() nexus_endpoint_client.go
252 >
253 > if !m.hasLoadedEndpoints.Load() {
254 > if err := m.loadEndpoints(ctx); err != nil {
255 return nil, nil, fmt.Errorf("error loading nexus endpoints cache: %w", err)
256 }
257 }
258
259 > m.RLock() nexus_endpoint_client.go
260 > defer m.RUnlock()
261 >
262 > if request.LastKnownTableVersion != 0 && request.LastKnownTableVersion != m.tableVersion {
263 return nil, nil, serviceerror.NewFailedPreconditionf("nexus endpoints table version mismatch. received: %v expected %v", request.LastKnownTableVersion, m.tableVersion)
264 }
265
266 > startIdx := 0 nexus_endpoint_client.go
267 > if request.NextPageToken != nil {
268 nextEndpointID := string(request.NextPageToken)
269
281 }
282
283 > endIdx := min(startIdx+int(request.PageSize), len(m.endpointEntries)) nexus_endpoint_client.go
284 >
285 > var nextPageToken []byte
286 > if endIdx < len(m.endpointEntries) {
287 nextPageToken = []byte(m.endpointEntries[endIdx].Id)
288 }
289
290 > resp := &matchingservice.ListNexusEndpointsResponse{ nexus_endpoint_client.go
291 > TableVersion: m.tableVersion,
292 > NextPageToken: nextPageToken,
293 > Entries: slices.Clone(m.endpointEntries[startIdx:endIdx]),
294 > }
295 >
296 > return resp, m.tableVersionChanged, nil
297 }
298
299 > func (m *nexusEndpointClient) loadEndpoints(ctx context.Context) error { nexus_endpoint_client.go
300 > m.Lock()
301 > defer m.Unlock()
302 >
303 > if m.hasLoadedEndpoints.Load() {
304 // check whether endpoints were loaded while waiting for write lock
305 return nil
307
308 // reset cached view since we will be paging from the start
309 > m.resetCacheStateLocked() nexus_endpoint_client.go
310 >
311 > var pageToken []byte
312 >
313 > for ctx.Err() == nil {
314 > resp, err := m.persistence.ListNexusEndpoints(ctx, &p.ListNexusEndpointsRequest{
315 > LastKnownTableVersion: m.tableVersion,
316 > NextPageToken: pageToken,
317 > PageSize: loadEndpointsPageSize,
318 > })
319 > if err != nil {
320 if errors.Is(err, p.ErrNexusTableVersionConflict) {
321 // indicates table was updated during paging, so reset and start from the beginning
327 }
328
329 > pageToken = resp.NextPageToken nexus_endpoint_client.go
330 > m.tableVersion = resp.TableVersion
331 > for _, entry := range resp.Entries {
332 m.endpointEntries = append(m.endpointEntries, entry)
333 m.endpointsByID[entry.Id] = entry
335 }
336
337 > if len(pageToken) == 0 { nexus_endpoint_client.go
338 > break
339 }
340 }
341
342 > m.hasLoadedEndpoints.Store(ctx.Err() == nil) nexus_endpoint_client.go
343 > return ctx.Err()
344 }
345
346 > func (m *nexusEndpointClient) resetCacheStateLocked() { nexus_endpoint_client.go
347 > m.tableVersion = 0
348 > m.endpointEntries = []*persistencespb.NexusEndpointEntry{}
349 > m.endpointsByID = make(map[string]*persistencespb.NexusEndpointEntry)
350 > m.endpointsByName = make(map[string]*persistencespb.NexusEndpointEntry)
351 > }
352
353 // notifyOwnershipChanged starts or stops a background routine which watches the Nexus endpoints table version for
354 // changes. This is only expected to be called from matchingEngineImpl.notifyNexusEndpointsOwnershipChange()
355 > func (m *nexusEndpointClient) notifyOwnershipChanged(isOwner bool) { nexus_endpoint_client.go
356 > var oldHandle *goro.Handle
357 >
358 > m.refreshLock.Lock()
359 > if isOwner && m.refreshHandle == nil {
360 > // Just acquired ownership. Start refresh loop on table version to catch any updates from previous owner. nexus_endpoint_client.go
361 > backgroundCtx := headers.SetCallerInfo(
362 > context.Background(),
363 > headers.SystemBackgroundHighCallerInfo,
364 > )
365 > m.refreshHandle = goro.NewHandle(backgroundCtx)
366 > m.refreshHandle.Go(m.refreshTableVersion)
367 > } else if !isOwner && m.refreshHandle != nil { nexus_endpoint_client.go
368 > // Just lost ownership. Stop table version refresh loop. nexus_endpoint_client.go
369 > oldHandle = m.refreshHandle
370 > m.refreshHandle = nil
371 > }
372 > m.refreshLock.Unlock() nexus_endpoint_client.go
373 >
374 > if oldHandle != nil {
375 > oldHandle.Cancel() nexus_endpoint_client.go
376 > <-oldHandle.Done()
377 > }
378 }
379
380 > func (m *nexusEndpointClient) refreshTableVersion(ctx context.Context) error { nexus_endpoint_client.go
381 > for ctx.Err() == nil {
382 > m.checkTableVersion(ctx) nexus_endpoint_client.go
383 > util.InterruptibleSleep(ctx, backoff.Jitter(m.endpointsRefreshInterval(), 0.2))
384 > }
385 > return ctx.Err() nexus_endpoint_client.go
386 }
387
388 > func (m *nexusEndpointClient) checkTableVersion(ctx context.Context) { nexus_endpoint_client.go
389 > // Acquire lock to make sure we are not in the middle of an update.
390 > m.Lock()
391 > defer m.Unlock()
392 >
393 > resp, err := m.persistence.ListNexusEndpoints(ctx, &p.ListNexusEndpointsRequest{
394 > LastKnownTableVersion: 0,
395 > PageSize: 0,
396 > })
397 > if err != nil || resp.TableVersion != m.tableVersion {
398 m.hasLoadedEndpoints.Store(false)
399 ch := m.tableVersionChanged
go.temporal.io/server/service/frontend/admin_handler.go 98 covered LOC · 10 ranges

Open complete file

174 args NewAdminHandlerArgs,
175 namespaceDLQHandler nsreplication.DLQMessageHandler,
176 > ) *AdminHandler { admin_handler.go
177 > historyHealthChecker := NewHealthChecker(
178 > primitives.HistoryService,
179 > args.MembershipMonitor,
180 > args.Config.HistoryHostErrorPercentage,
181 > args.Config.HistoryHostSelfErrorProportion,
182 > func(ctx context.Context, hostAddress string) (*historyservice.DeepHealthCheckResponse, error) {
183 return args.HistoryClient.DeepHealthCheck(ctx, &historyservice.DeepHealthCheckRequest{HostAddress: hostAddress})
184 },
186 )
187
188 > return &AdminHandler{ admin_handler.go
189 > logger: args.Logger,
190 > status: common.DaemonStatusInitialized,
191 > numberOfHistoryShards: args.PersistenceConfig.NumHistoryShards,
192 > config: args.Config,
193 > namespaceDLQHandler: namespaceDLQHandler,
194 > eventSerializer: args.EventSerializer,
195 > visibilityMgr: args.visibilityMgr,
196 > persistenceExecutionName: args.PersistenceExecutionManager.GetName(),
197 > namespaceReplicationQueue: args.NamespaceReplicationQueue,
198 > taskManager: args.TaskManager,
199 > fairTaskManager: args.FairTaskManager,
200 > clusterMetadataManager: args.ClusterMetadataManager,
201 > persistenceMetadataManager: args.PersistenceMetadataManager,
202 > clientFactory: args.ClientFactory,
203 > clientBean: args.ClientBean,
204 > historyClient: args.HistoryClient,
205 > sdkClientFactory: args.sdkClientFactory,
206 > membershipMonitor: args.MembershipMonitor,
207 > hostInfoProvider: args.HostInfoProvider,
208 > metricsHandler: args.MetricsHandler,
209 > namespaceRegistry: args.NamespaceRegistry,
210 > saProvider: args.SaProvider,
211 > saManager: args.SaManager,
212 > saMapperProvider: args.SaMapperProvider,
213 > saValidator: searchattribute.NewValidator(
214 > args.SaProvider,
215 > args.SaMapperProvider,
216 > args.Config.SearchAttributesNumberOfKeysLimit,
217 > args.Config.SearchAttributesSizeOfValueLimit,
218 > args.Config.SearchAttributesTotalSizeLimit,
219 > args.visibilityMgr,
220 > visibility.AllowListForValidation(
221 > args.visibilityMgr.GetStoreNames(),
222 > args.Config.VisibilityAllowList,
223 > ),
224 > args.Config.SuppressErrorSetSystemSearchAttribute,
225 > args.MetricsHandler,
226 > args.Logger,
227 > ),
228 > clusterMetadata: args.ClusterMetadata,
229 > healthServer: args.HealthServer,
230 > historyHealthChecker: historyHealthChecker,
231 > taskCategoryRegistry: args.CategoryRegistry,
232 > matchingClient: args.matchingClient,
233 > chasmRegistry: args.ChasmRegistry,
234 > schedulerClient: args.SchedulerClient,
235 > }
236 }
237
238 // Start starts the handler
239 > func (adh *AdminHandler) Start() { admin_handler.go
240 > if atomic.CompareAndSwapInt32(
241 > &adh.status,
242 > common.DaemonStatusInitialized,
243 > common.DaemonStatusStarted,
244 > ) {
245 > adh.healthServer.SetServingStatus(AdminServiceName, grpchealthspb.HealthCheckResponse_SERVING)
246 > }
247 }
248
249 // Stop stops the handler
250 > func (adh *AdminHandler) Stop() { admin_handler.go
251 > if atomic.CompareAndSwapInt32(
252 > &adh.status,
253 > common.DaemonStatusStarted,
254 > common.DaemonStatusStopped,
255 > ) {
256 > adh.healthServer.SetServingStatus(AdminServiceName, grpchealthspb.HealthCheckResponse_NOT_SERVING)
257 > }
258 }
259
1743 ctx context.Context,
1744 request *adminservice.GetTaskQueueTasksRequest,
1745 > ) (_ *adminservice.GetTaskQueueTasksResponse, err error) { admin_handler.go
1746 > defer log.CapturePanic(adh.logger, &err)
1747 >
1748 > if request == nil {
1749 return nil, errRequestNotSet
1750 }
1751
1752 > namespaceID, err := adh.namespaceRegistry.GetNamespaceID(namespace.Name(request.GetNamespace())) admin_handler.go
1753 > if err != nil {
1754 return nil, err
1755 }
1756
1757 > var taskManager persistence.TaskManager admin_handler.go
1758 > if request.GetMinPass() != 0 {
1759 if adh.fairTaskManager == nil {
1760 return nil, serviceerror.NewInvalidArgument("Fairness table is not available on this cluster")
1762 taskManager = adh.fairTaskManager
1763 request.MaxTaskId = math.MaxInt64 // required for fairness GetTasks call
1764 > } else { admin_handler.go
1765 > taskManager = adh.taskManager
1766 > }
1767
1768 > resp, err := taskManager.GetTasks(ctx, &persistence.GetTasksRequest{ admin_handler.go
1769 > NamespaceID: namespaceID.String(),
1770 > TaskQueue: request.GetTaskQueue(),
1771 > TaskType: request.GetTaskQueueType(),
1772 > InclusiveMinTaskID: request.GetMinTaskId(),
1773 > ExclusiveMaxTaskID: request.GetMaxTaskId(),
1774 > InclusiveMinPass: request.GetMinPass(),
1775 > Subqueue: int(request.GetSubqueue()),
1776 > PageSize: int(request.GetBatchSize()),
1777 > NextPageToken: request.NextPageToken,
1778 > })
1779 > if err != nil {
1780 return nil, err
1781 }
1782
1783 > return &adminservice.GetTaskQueueTasksResponse{ admin_handler.go
1784 > Tasks: resp.Tasks,
1785 > NextPageToken: resp.NextPageToken,
1786 > }, nil
1787 }
1788
go.temporal.io/server/client/matching/loadbalancer.go 97 covered LOC · 20 ranges

Open complete file

65 dc *dynamicconfig.Collection,
66 testHooks testhooks.TestHooks,
67 > ) LoadBalancer { loadbalancer.go
68 > lb := &defaultLoadBalancer{
69 > namespaceIDToName: namespaceIDToName,
70 > nReadPartitions: dynamicconfig.MatchingNumTaskqueueReadPartitions.Get(dc),
71 > nWritePartitions: dynamicconfig.MatchingNumTaskqueueWritePartitions.Get(dc),
72 > testHooks: testHooks,
73 > taskQueueLBs: make(map[tqid.TaskQueue]*tqLoadBalancer),
74 > }
75 > return lb
76 > }
77
78 func (lb *defaultLoadBalancer) PickWritePartition(
79 taskQueue *tqid.TaskQueue,
80 pc PartitionCounts,
81 > ) *tqid.NormalPartition { loadbalancer.go
82 > if n, ok := testhooks.Get(lb.testHooks, testhooks.MatchingLBForceWritePartition, namespace.ID(taskQueue.NamespaceId())); ok {
83 return taskQueue.NormalPartition(n)
84 }
85
86 > nsName, err := lb.namespaceIDToName(namespace.ID(taskQueue.NamespaceId())) loadbalancer.go
87 > if err != nil {
88 return taskQueue.RootPartition()
89 }
90
91 > var partitionCount int loadbalancer.go
92 > if pc.Write > 0 {
93 partitionCount = int(pc.Write)
94 > } else { loadbalancer.go
95 > partitionCount = max(1, lb.nWritePartitions(nsName.String(), taskQueue.Name(), taskQueue.TaskType()))
96 > }
97
98 > return taskQueue.NormalPartition(rand.Intn(partitionCount)) loadbalancer.go
99 }
100
104 taskQueue *tqid.TaskQueue,
105 pc PartitionCounts,
106 > ) *pollToken { loadbalancer.go
107 > tqlb := lb.getTaskQueueLoadBalancer(taskQueue)
108 >
109 > // For read path it's safer to return global default partition count instead of root partition, when we fail to
110 > // map namespace ID to name.
111 > var partitionCount = dynamicconfig.GlobalDefaultNumTaskQueuePartitions
112 >
113 > if pc.Read > 0 {
114 partitionCount = int(pc.Read)
115 > } else { loadbalancer.go
116 > namespaceName, err := lb.namespaceIDToName(namespace.ID(taskQueue.NamespaceId()))
117 > if err == nil {
118 > partitionCount = lb.nReadPartitions(string(namespaceName), taskQueue.Name(), taskQueue.TaskType())
119 > }
120 }
121
122 > if n, ok := testhooks.Get(lb.testHooks, testhooks.MatchingLBForceReadPartition, namespace.ID(taskQueue.NamespaceId())); ok { loadbalancer.go
123 return tqlb.forceReadPartition(partitionCount, n)
124 }
125
126 > return tqlb.pickReadPartition(partitionCount) loadbalancer.go
127 }
128
129 > func (lb *defaultLoadBalancer) getTaskQueueLoadBalancer(tq *tqid.TaskQueue) *tqLoadBalancer { loadbalancer.go
130 > lb.lock.RLock()
131 > tqlb, ok := lb.taskQueueLBs[*tq]
132 > lb.lock.RUnlock()
133 > if ok {
134 > return tqlb
135 > }
136
137 > lb.lock.Lock() loadbalancer.go
138 > tqlb, ok = lb.taskQueueLBs[*tq]
139 > if !ok {
140 > tqlb = newTaskQueueLoadBalancer(tq)
141 > lb.taskQueueLBs[*tq] = tqlb
142 > }
143 > lb.lock.Unlock()
144 > return tqlb
145 }
146
147 > func newTaskQueueLoadBalancer(tq *tqid.TaskQueue) *tqLoadBalancer { loadbalancer.go
148 > return &tqLoadBalancer{
149 > taskQueue: tq,
150 > }
151 > }
152
153 > func (b *tqLoadBalancer) pickReadPartition(partitionCount int) *pollToken { loadbalancer.go
154 > b.lock.Lock()
155 > defer b.lock.Unlock()
156 >
157 > b.ensurePartitionCountLocked(partitionCount)
158 > partitionID := b.pickReadPartitionWithFewestPolls(partitionCount)
159 >
160 > b.pollerCounts[partitionID]++
161 >
162 > return &pollToken{
163 > TQPartition: b.taskQueue.NormalPartition(partitionID),
164 > balancer: b,
165 > }
166 > }
167
168 func (b *tqLoadBalancer) forceReadPartition(partitionCount, partitionID int) *pollToken {
181
182 // caller to ensure that lock is obtained before call this function
183 > func (b *tqLoadBalancer) pickReadPartitionWithFewestPolls(partitionCount int) int { loadbalancer.go
184 > // pick a random partition to start with
185 > startPartitionID := rand.Intn(partitionCount)
186 > pickedPartitionID := startPartitionID
187 > minPollerCount := b.pollerCounts[pickedPartitionID]
188 > for i := 1; i < partitionCount && minPollerCount > 0; i++ {
189 currPartitionID := (startPartitionID + i) % int(partitionCount)
190 if b.pollerCounts[currPartitionID] < minPollerCount {
194 }
195
196 > return pickedPartitionID loadbalancer.go
197 }
198
199 // caller to ensure that lock is obtained before call this function
200 > func (b *tqLoadBalancer) ensurePartitionCountLocked(partitionCount int) { loadbalancer.go
201 > if len(b.pollerCounts) == partitionCount {
202 > return
203 > }
204
205 > if len(b.pollerCounts) < partitionCount { loadbalancer.go
206 > // add more partition entries
207 > for i := len(b.pollerCounts); i < partitionCount; i++ {
208 > b.pollerCounts = append(b.pollerCounts, 0)
209 > }
210 } else {
211 // truncate existing partition entries
214 }
215
216 > func (b *tqLoadBalancer) Release(partitionID int) { loadbalancer.go
217 > b.lock.Lock()
218 > defer b.lock.Unlock()
219 > // partitionID could be out of range if dynamic config reduce taskQueue partition count
220 > if len(b.pollerCounts) > partitionID && b.pollerCounts[partitionID] > 0 {
221 > b.pollerCounts[partitionID]--
222 > }
223 }
224
225 > func (t *pollToken) Release() { loadbalancer.go
226 > if t.balancer != nil {
227 > // t.balancer == nil is valid for example sticky task queue.
228 > t.balancer.Release(t.TQPartition.PartitionId())
229 > }
230 }
go.temporal.io/server/common/persistence/metadata_manager.go 97 covered LOC · 23 ranges

Open complete file

37 logger log.Logger,
38 clusterName string,
39 > ) MetadataManager { metadata_manager.go
40 > return &metadataManagerImpl{
41 > serializer: serializer,
42 > persistence: persistence,
43 > logger: logger,
44 > clusterName: clusterName,
45 > }
46 > }
47
48 func (m *metadataManagerImpl) GetName() string {
53 ctx context.Context,
54 request *CreateNamespaceRequest,
55 > ) (*CreateNamespaceResponse, error) { metadata_manager.go
56 > datablob, err := m.serializer.NamespaceDetailToBlob(request.Namespace)
57 > if err != nil {
58 return nil, err
59 }
60
61 > return m.persistence.CreateNamespace(ctx, &InternalCreateNamespaceRequest{ metadata_manager.go
62 > ID: request.Namespace.Info.Id,
63 > Name: request.Namespace.Info.Name,
64 > IsGlobal: request.IsGlobalNamespace,
65 > Namespace: datablob,
66 > })
67 }
68
70 ctx context.Context,
71 request *GetNamespaceRequest,
72 > ) (*GetNamespaceResponse, error) { metadata_manager.go
73 > resp, err := m.persistence.GetNamespace(ctx, request)
74 > if err != nil {
75 > return nil, err metadata_manager.go
76 > }
77 > return ConvertInternalGetNamespaceResponse(m.serializer, m.clusterName, resp) metadata_manager.go
78 }
79
148 }
149
150 > func ConvertInternalGetNamespaceResponse(serializer serialization.Serializer, currentClusterName string, d *InternalGetNamespaceResponse) (*GetNamespaceResponse, error) { metadata_manager.go
151 > ns, err := serializer.NamespaceDetailFromBlob(d.Namespace)
152 > if err != nil {
153 return nil, err
154 }
155
156 > if ns.Info.Data == nil { metadata_manager.go
157 > ns.Info.Data = map[string]string{} metadata_manager.go
158 > }
159
160 > if ns.Config.BadBinaries == nil || ns.Config.BadBinaries.Binaries == nil { metadata_manager.go
161 > ns.Config.BadBinaries = &namespacepb.BadBinaries{Binaries: map[string]*namespacepb.BadBinaryInfo{}} metadata_manager.go
162 > }
163
164 > ns.ReplicationConfig.ActiveClusterName = GetOrUseDefaultActiveCluster(currentClusterName, ns.ReplicationConfig.ActiveClusterName) metadata_manager.go
165 > ns.ReplicationConfig.Clusters = GetOrUseDefaultClusters(currentClusterName, ns.ReplicationConfig.Clusters)
166 > return &GetNamespaceResponse{
167 > Namespace: ns,
168 > IsGlobalNamespace: d.IsGlobal,
169 > NotificationVersion: d.NotificationVersion,
170 > }, nil
171 }
172
174 ctx context.Context,
175 request *ListNamespacesRequest,
176 > ) (*ListNamespacesResponse, error) { metadata_manager.go
177 > var namespaces []*GetNamespaceResponse
178 > nextPageToken := request.NextPageToken
179 > pageSize := request.PageSize
180 >
181 > for {
182 > resp, err := m.persistence.ListNamespaces(ctx, &InternalListNamespacesRequest{
183 > PageSize: pageSize,
184 > NextPageToken: nextPageToken,
185 > })
186 > if err != nil {
187 return nil, err
188 }
189 > deletedNamespacesCount := 0 metadata_manager.go
190 > for _, d := range resp.Namespaces {
191 > ret, err := ConvertInternalGetNamespaceResponse(m.serializer, m.clusterName, d) metadata_manager.go
192 > if err != nil {
193 return nil, err
194 }
195 > if ret.Namespace.Info.State == enumspb.NAMESPACE_STATE_DELETED && !request.IncludeDeleted { metadata_manager.go
196 deletedNamespacesCount++
197 continue
198 }
199 > namespaces = append(namespaces, ret) metadata_manager.go
200 }
201 > nextPageToken = resp.NextPageToken metadata_manager.go
202 > if len(nextPageToken) == 0 {
203 > // Page wasn't full, no more namespaces in DB.
204 > break
205 }
206 if deletedNamespacesCount == 0 {
211 }
212
213 > return &ListNamespacesResponse{ metadata_manager.go
214 > Namespaces: namespaces,
215 > NextPageToken: nextPageToken,
216 > }, nil
217 }
218
220 ctx context.Context,
221 currentClusterName string,
222 > ) error { metadata_manager.go
223 > _, err := m.CreateNamespace(ctx, &CreateNamespaceRequest{
224 > Namespace: &persistencespb.NamespaceDetail{
225 > Info: &persistencespb.NamespaceInfo{
226 > Id: primitives.SystemNamespaceID,
227 > Name: primitives.SystemLocalNamespace,
228 > State: enumspb.NAMESPACE_STATE_REGISTERED,
229 > Description: "Temporal internal system namespace",
230 > Owner: "[email protected]",
231 > },
232 > Config: &persistencespb.NamespaceConfig{
233 > Retention: durationpb.New(primitives.SystemNamespaceRetention),
234 > HistoryArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
235 > VisibilityArchivalState: enumspb.ARCHIVAL_STATE_DISABLED,
236 > },
237 > ReplicationConfig: &persistencespb.NamespaceReplicationConfig{
238 > ActiveClusterName: currentClusterName,
239 > Clusters: []string{currentClusterName},
240 > },
241 > FailoverVersion: common.EmptyVersion,
242 > FailoverNotificationVersion: -1,
243 > },
244 > IsGlobalNamespace: false,
245 > })
246 >
247 > if err != nil {
248 if _, ok := err.(*serviceerror.NamespaceAlreadyExists); !ok {
249 return err
250 }
251 }
252 > return nil metadata_manager.go
253 }
254
259 }
260
261 > func (m *metadataManagerImpl) Close() { metadata_manager.go
262 > m.persistence.Close()
263 > }
264
265 > func (m *metadataManagerImpl) WatchNamespaces(context.Context) (<-chan *NamespaceWatchEvent, error) { metadata_manager.go
266 > return nil, ErrWatchNotSupported
267 > }
go.temporal.io/server/common/persistence/sql/history_store.go 97 covered LOC · 21 ranges

Open complete file

25 ctx context.Context,
26 request *p.InternalAppendHistoryNodesRequest,
27 > ) error { history_store.go
28 > branchInfo := request.BranchInfo
29 > node := request.Node
30 >
31 > treeIDBytes, err := primitives.ParseUUID(branchInfo.GetTreeId())
32 > if err != nil {
33 return err
34 }
35 > branchIDBytes, err := primitives.ParseUUID(branchInfo.GetBranchId()) history_store.go
36 > if err != nil {
37 return err
38 }
39
40 > nodeRow := &sqlplugin.HistoryNodeRow{ history_store.go
41 > TreeID: treeIDBytes,
42 > BranchID: branchIDBytes,
43 > NodeID: node.NodeID,
44 > PrevTxnID: node.PrevTransactionID,
45 > TxnID: node.TransactionID,
46 > Data: node.Events.Data,
47 > DataEncoding: node.Events.EncodingType.String(),
48 > ShardID: request.ShardID,
49 > }
50 >
51 > if !request.IsNewBranch {
52 > _, err = m.DB.InsertIntoHistoryNode(ctx, nodeRow) history_store.go
53 > switch err {
54 > case nil:
55 > return nil
56 case context.DeadlineExceeded, context.Canceled:
57 return &p.AppendHistoryTimeoutError{
66 }
67
68 > treeInfoBlob := request.TreeInfo history_store.go
69 > treeRow := &sqlplugin.HistoryTreeRow{
70 > ShardID: request.ShardID,
71 > TreeID: treeIDBytes,
72 > BranchID: branchIDBytes,
73 > Data: treeInfoBlob.Data,
74 > DataEncoding: treeInfoBlob.EncodingType.String(),
75 > }
76 >
77 > return m.txExecute(ctx, "AppendHistoryNodes", func(tx sqlplugin.Tx) error {
78 > result, err := tx.InsertIntoHistoryNode(ctx, nodeRow)
79 > if err != nil {
80 return err
81 }
82 > rowsAffected, err := result.RowsAffected() history_store.go
83 > if err != nil {
84 return err
85 }
86 > if rowsAffected != 1 && rowsAffected != 2 { history_store.go
87 return fmt.Errorf("expected 1 or 2 row to be affected for node table, got %v", rowsAffected)
88 }
89
90 > result, err = tx.InsertIntoHistoryTree(ctx, treeRow) history_store.go
91 > switch err {
92 > case nil:
93 > rowsAffected, err = result.RowsAffected()
94 > if err != nil {
95 return err
96 }
97 > if rowsAffected != 1 && rowsAffected != 2 { history_store.go
98 return fmt.Errorf("expected 1 or 2 rows to be affected for tree table as we allow upserts, got %v", rowsAffected)
99 }
100 > return nil history_store.go
101 case context.DeadlineExceeded, context.Canceled:
102 return &p.AppendHistoryTimeoutError{
157 ctx context.Context,
158 request *p.InternalReadHistoryBranchRequest,
159 > ) (*p.InternalReadHistoryBranchResponse, error) { history_store.go
160 > branch, err := m.ParseHistoryBranchInfo(request.BranchToken)
161 > if err != nil {
162 return nil, err
163 }
164 > branchIDBytes, err := primitives.ParseUUID(request.BranchID) history_store.go
165 > if err != nil {
166 return nil, err
167 }
168 > treeIDBytes, err := primitives.ParseUUID(branch.TreeId) history_store.go
169 > if err != nil {
170 return nil, err
171 }
172
173 > var token *historyNodePaginationToken history_store.go
174 > if len(request.NextPageToken) == 0 {
175 > if request.ReverseOrder {
176 token = &historyNodePaginationToken{LastNodeID: request.MaxNodeID, LastTxnID: MaxTxnID}
177 > } else { history_store.go
178 > token = &historyNodePaginationToken{LastNodeID: request.MinNodeID, LastTxnID: MinTxnID}
179 > }
180 } else {
181 token, err = deserializePageTokenJson[historyNodePaginationToken](request.NextPageToken)
185 }
186
187 > minNodeId, maxNodeId := request.MinNodeID, request.MaxNodeID history_store.go
188 > minTxnId, maxTxnId := MinTxnID, MaxTxnID
189 > if request.ReverseOrder {
190 maxNodeId = token.LastNodeID
191 maxTxnId = token.LastTxnID
192 > } else { history_store.go
193 > minNodeId = token.LastNodeID
194 > minTxnId = token.LastTxnID
195 > }
196
197 > rows, err := m.DB.RangeSelectFromHistoryNode(ctx, sqlplugin.HistoryNodeSelectFilter{ history_store.go
198 > ShardID: request.ShardID,
199 > TreeID: treeIDBytes,
200 > BranchID: branchIDBytes,
201 > MinNodeID: minNodeId,
202 > MinTxnID: minTxnId,
203 > MaxNodeID: maxNodeId,
204 > MaxTxnID: maxTxnId,
205 > PageSize: request.PageSize,
206 > MetadataOnly: request.MetadataOnly,
207 > ReverseOrder: request.ReverseOrder,
208 > })
209 > switch err {
210 > case nil:
211 // noop
212 case sql.ErrNoRows:
216 }
217
218 > nodes := make([]p.InternalHistoryNode, 0, len(rows)) history_store.go
219 > for _, row := range rows {
220 > nodes = append(nodes, p.InternalHistoryNode{
221 > NodeID: row.NodeID,
222 > PrevTransactionID: row.PrevTxnID,
223 > TransactionID: row.TxnID,
224 > Events: p.NewDataBlob(row.Data, row.DataEncoding),
225 > })
226 > }
227
228 > var pagingToken []byte history_store.go
229 > if len(rows) < request.PageSize {
230 > pagingToken = nil
231 > } else {
232 lastRow := rows[len(rows)-1]
233 pagingToken, err = serializePageTokenJson(&historyNodePaginationToken{
240 }
241
242 > return &p.InternalReadHistoryBranchResponse{ history_store.go
243 > Nodes: nodes,
244 > NextPageToken: pagingToken,
245 > }, nil
246 }
247
go.temporal.io/server/service/worker/scanner/scanner.go 97 covered LOC · 20 ranges

Open complete file

131 hostInfo membership.HostInfo,
132 serializer serialization.Serializer,
133 > ) *Scanner { scanner.go
134 > return &Scanner{
135 > context: scannerContext{
136 > cfg: cfg,
137 > sdkClientFactory: sdkClientFactory,
138 > logger: logger,
139 > metricsHandler: metricsHandler,
140 > executionManager: executionManager,
141 > taskManager: taskManager,
142 > visibilityManager: visibilityManager,
143 > metadataManager: metadataManager,
144 > historyClient: historyClient,
145 > matchingClient: matchingClient,
146 > adminClient: adminClient,
147 > namespaceRegistry: registry,
148 > currentClusterName: currentClusterName,
149 > hostInfo: hostInfo,
150 > serializer: serializer,
151 > },
152 > }
153 > }
154
155 // Start starts the scanner
156 > func (s *Scanner) Start() error { scanner.go
157 > ctx := context.WithValue(context.Background(), scannerContextKey, s.context)
158 > ctx = headers.SetCallerInfo(ctx, headers.SystemBackgroundHighCallerInfo)
159 > ctx, s.lifecycleCancel = context.WithCancel(ctx)
160 >
161 > workerOpts := worker.Options{
162 > Identity: "temporal-system@" + s.context.hostInfo.Identity(),
163 > MaxConcurrentActivityExecutionSize: s.context.cfg.MaxConcurrentActivityExecutionSize(),
164 > MaxConcurrentWorkflowTaskExecutionSize: s.context.cfg.MaxConcurrentWorkflowTaskExecutionSize(),
165 > MaxConcurrentActivityTaskPollers: s.context.cfg.MaxConcurrentActivityTaskPollers(),
166 > MaxConcurrentWorkflowTaskPollers: s.context.cfg.MaxConcurrentWorkflowTaskPollers(),
167 >
168 > BackgroundActivityContext: ctx,
169 > }
170 >
171 > var workerTaskQueueNames []string
172 > if s.context.cfg.Persistence.DefaultStoreType() != config.StoreTypeSQL && s.context.cfg.ExecutionsScannerEnabled() {
173 s.wg.Add(1)
174 go s.startWorkflowWithRetry(ctx, executionsScannerWFStartOptions, executionsScannerWFTypeName)
175 workerTaskQueueNames = append(workerTaskQueueNames, executionsScannerTaskQueueName)
176 > } else if s.context.cfg.ExecutionsScannerEnabled() { scanner.go
177 s.context.logger.Info("ExecutionsScanner is not supported for SQL store")
178 }
179
180 > if s.context.cfg.Persistence.DefaultStoreType() == config.StoreTypeSQL && s.context.cfg.TaskQueueScannerEnabled() { scanner.go
181 > s.wg.Add(1) scanner.go
182 > go s.startWorkflowWithRetry(ctx, tlScannerWFStartOptions, tqScannerWFTypeName)
183 > workerTaskQueueNames = append(workerTaskQueueNames, tqScannerTaskQueueName)
184 > }
185
186 > if s.context.cfg.HistoryScannerEnabled() { scanner.go
187 > s.wg.Add(1) scanner.go
188 > go s.startWorkflowWithRetry(ctx, historyScannerWFStartOptions, historyScannerWFTypeName)
189 > workerTaskQueueNames = append(workerTaskQueueNames, historyScannerTaskQueueName)
190 > }
191
192 > if s.context.cfg.BuildIdScavengerEnabled() { scanner.go
193 s.wg.Add(1)
194 go s.startWorkflowWithRetry(ctx, build_ids.BuildIdScavengerWFStartOptions, build_ids.BuildIdScavangerWorkflowName)
216 }
217
218 > siOpts := s.context.cfg.ScheduleInvariantsScannerOptions() scanner.go
219 > if siOpts.OverdueNextActionTimeEnabled || siOpts.StuckOpenEnabled || siOpts.UnknownStateEnabled {
220 scheduleActivities := scheduleinvariants.NewActivities(
221 s.context.logger,
271
272 // TODO: There's no reason to register all activities and workflows on every task queue.
273 > for _, tl := range workerTaskQueueNames { scanner.go
274 > work := s.context.sdkClientFactory.NewWorker(s.context.sdkClientFactory.GetSystemClient(), tl, workerOpts) scanner.go
275 >
276 > work.RegisterWorkflowWithOptions(TaskQueueScannerWorkflow, workflow.RegisterOptions{Name: tqScannerWFTypeName})
277 > work.RegisterWorkflowWithOptions(HistoryScannerWorkflow, workflow.RegisterOptions{Name: historyScannerWFTypeName})
278 > work.RegisterWorkflowWithOptions(ExecutionsScannerWorkflow, workflow.RegisterOptions{Name: executionsScannerWFTypeName})
279 > work.RegisterActivityWithOptions(TaskQueueScavengerActivity, activity.RegisterOptions{Name: taskQueueScavengerActivityName})
280 > work.RegisterActivityWithOptions(HistoryScavengerActivity, activity.RegisterOptions{Name: historyScavengerActivityName})
281 > work.RegisterActivityWithOptions(ExecutionsScavengerActivity, activity.RegisterOptions{Name: executionsScavengerActivityName})
282 >
283 > // TODO: Nothing is gracefully stopping these workers or listening for fatal errors.
284 > if err := work.Start(); err != nil {
285 return err
286 }
287 }
288
289 > return nil scanner.go
290 }
291
292 > func (s *Scanner) Stop() { scanner.go
293 > s.lifecycleCancel()
294 > s.wg.Wait()
295 > }
296
297 // startWorkflowWithRetry starts a scanner workflow, retrying until it succeeds or the
298 // scanner shuts down. workflowType may be either a registered type-name string or the
299 // workflow function itself (registered under its Go function name).
300 > func (s *Scanner) startWorkflowWithRetry(ctx context.Context, options sdkclient.StartWorkflowOptions, workflowType string, workflowArgs ...any) { scanner.go
301 > defer s.wg.Done()
302 >
303 > policy := backoff.NewExponentialRetryPolicy(time.Second).
304 > WithMaximumInterval(time.Minute).
305 > WithExpirationInterval(backoff.NoInterval)
306 > err := backoff.ThrottleRetryContext(ctx, func(ctx context.Context) error {
307 > return s.startWorkflow(
308 > ctx,
309 > s.context.sdkClientFactory.GetSystemClient(),
310 > options,
311 > workflowType,
312 > workflowArgs...,
313 > )
314 > }, policy, func(err error) bool {
315 > return true scanner.go
316 > })
317 // if the scanner shuts down before the workflow is started, then the error will be context canceled
318 > if err != nil && !common.IsContextCanceledErr(err) { scanner.go
319 s.context.logger.Fatal("unable to start scanner", tag.WorkflowType(workflowType), tag.Error(err))
320 }
327 workflowType string,
328 workflowArgs ...any,
329 > ) error { scanner.go
330 > ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
331 > _, err := client.ExecuteWorkflow(ctx, options, workflowType, workflowArgs...)
332 > cancel()
333 > if err != nil {
334 > if _, ok := err.(*serviceerror.WorkflowExecutionAlreadyStarted); ok { scanner.go
335 return nil
336 }
337 > s.context.logger.Error("error starting workflow", tag.WorkflowType(workflowType), tag.Error(err)) scanner.go
338 > return err
339 }
340 > s.context.logger.Info("workflow successfully started", tag.WorkflowType(workflowType)) scanner.go
341 > return nil
342 }
go.temporal.io/server/temporal/server_impl.go 97 covered LOC · 13 ranges

Open complete file

65 metricsHandler metrics.Handler,
66 serializer serialization.Serializer,
67 > ) *ServerImpl { server_impl.go
68 > s := &ServerImpl{
69 > so: opts,
70 > stoppedCh: stoppedCh,
71 > logger: logger,
72 > namespaceLogger: namespaceLogger,
73 > persistenceConfig: persistenceConfig,
74 > clusterMetadata: clusterMetadata,
75 > persistenceFactoryProvider: persistenceFactoryProvider,
76 > metricsHandler: metricsHandler,
77 > }
78 > for _, svcMeta := range servicesGroup.Services {
79 > if svcMeta != nil {
80 > s.servicesMetadata = append(s.servicesMetadata, svcMeta)
81 > }
82 }
83 // Store serializer for use in Start()
84 > s.serializer = serializer server_impl.go
85 > return s
86 }
87
88 > func (s *ServerImpl) Start(ctx context.Context) error { server_impl.go
89 > s.logger.Info("Starting server for services", tag.Value(s.so.serviceNames))
90 > s.logger.Debug(s.so.config.String())
91 >
92 > if err := initSystemNamespaces(
93 > ctx,
94 > &s.persistenceConfig,
95 > s.clusterMetadata.CurrentClusterName,
96 > s.so.persistenceServiceResolver,
97 > s.persistenceFactoryProvider,
98 > s.logger,
99 > s.so.customDataStoreFactory,
100 > s.metricsHandler,
101 > s.serializer,
102 > ); err != nil {
103 return fmt.Errorf("unable to initialize system namespace: %w", err)
104 }
105
106 > return s.startServices() server_impl.go
107 }
108
109 > func (s *ServerImpl) Stop(ctx context.Context) error { server_impl.go
110 > close(s.stoppedCh)
111 >
112 > svcs := slices.Clone(s.servicesMetadata)
113 > slices.SortFunc(svcs, func(a, b *ServicesMetadata) int {
114 > return -cmp.Compare(initOrder[a.serviceName], initOrder[b.serviceName]) // note negative
115 > })
116 > for _, svc := range svcs {
117 > svc.Stop(ctx)
118 > }
119
120 > if s.so.metricHandler != nil { server_impl.go
121 s.so.metricHandler.Stop(s.logger)
122 }
123 > return nil server_impl.go
124 }
125
126 > func (s *ServerImpl) startServices() error { server_impl.go
127 > // The membership join time may exceed the configured max join duration.
128 > // Double the service start timeout to make sure there is enough time for start logic.
129 > timeout := max(serviceStartTimeout, 2*s.so.config.Global.Membership.MaxJoinDuration)
130 > ctx, cancel := context.WithTimeout(context.Background(), timeout)
131 > defer cancel()
132 >
133 > svcs := slices.Clone(s.servicesMetadata)
134 > slices.SortFunc(svcs, func(a, b *ServicesMetadata) int {
135 > return cmp.Compare(initOrder[a.serviceName], initOrder[b.serviceName])
136 > })
137
138 > var allErrs error server_impl.go
139 > for _, svc := range svcs {
140 > err := svc.app.Start(ctx)
141 > if err != nil {
142 allErrs = multierr.Append(allErrs, fmt.Errorf("failed to start service %v: %w", svc.serviceName, err))
143 }
144 }
145 > return allErrs server_impl.go
146 }
147
156 metricsHandler metrics.Handler,
157 serializer serialization.Serializer,
158 > ) error { server_impl.go
159 > clusterName := persistenceClient.ClusterName(currentClusterName)
160 > metricsHandler = metricsHandler.WithTags(metrics.ServiceNameTag(primitives.ServerService))
161 > dataStoreFactory := persistenceClient.DataStoreFactoryProvider(
162 > clusterName,
163 > persistenceServiceResolver,
164 > cfg,
165 > customDataStoreFactory,
166 > logger,
167 > metricsHandler,
168 > telemetry.NoopTracerProvider,
169 > serializer,
170 > )
171 > factory := persistenceFactoryProvider(persistenceClient.NewFactoryParams{
172 > DataStoreFactory: dataStoreFactory,
173 > Cfg: cfg,
174 > PersistenceMaxQPS: nil,
175 > PersistenceNamespaceMaxQPS: nil,
176 > ClusterName: persistenceClient.ClusterName(currentClusterName),
177 > MetricsHandler: metricsHandler,
178 > Logger: logger,
179 > Serializer: serializer,
180 > })
181 > defer factory.Close()
182 >
183 > metadataManager, err := factory.NewMetadataManager()
184 > if err != nil {
185 return fmt.Errorf("unable to initialize metadata manager: %w", err)
186 }
187 > defer metadataManager.Close() server_impl.go
188 > ctx, cancel := context.WithTimeout(
189 > headers.SetCallerInfo(ctx, headers.SystemBackgroundHighCallerInfo),
190 > 30*time.Second,
191 > )
192 > defer cancel()
193 >
194 > if err = metadataManager.InitializeSystemNamespaces(ctx, currentClusterName); err != nil {
195 return fmt.Errorf("unable to register system namespace: %w", err)
196 }
197 > return nil server_impl.go
198 }
go.temporal.io/server/common/membership/ringpop/factory.go 96 covered LOC · 27 ranges

Open complete file

65
66 // newFactory builds a ringpop factory
67 > func newFactory(params factoryParams) (*factory, error) { factory.go
68 > cfg := params.Config
69 > if cfg.BroadcastAddress != "" && net.ParseIP(cfg.BroadcastAddress) == nil {
70 return nil, fmt.Errorf("%w: %s", errMalformedBroadcastAddress, cfg.BroadcastAddress)
71 }
72
73 > if cfg.MaxJoinDuration == 0 { factory.go
74 cfg.MaxJoinDuration = defaultMaxJoinDuration
75 }
76
77 > return &factory{ factory.go
78 > Config: params.Config,
79 > ServiceName: params.ServiceName,
80 > ServicePortMap: params.ServicePortMap,
81 > Logger: params.Logger,
82 > MetadataManager: params.MetadataManager,
83 > RPCConfig: params.RPCConfig,
84 > TLSFactory: params.TLSFactory,
85 > DC: params.DC,
86 > }, nil
87 }
88
89 // getMonitor returns a membership monitor
90 > func (factory *factory) getMonitor() *monitor { factory.go
91 > factory.monOnce.Do(func() {
92 > ctx, cancel := context.WithTimeout(context.Background(), persistenceOperationTimeout)
93 > defer cancel()
94 >
95 > ctx = headers.SetCallerInfo(ctx, headers.SystemBackgroundHighCallerInfo)
96 > currentClusterMetadata, err := factory.MetadataManager.GetCurrentClusterMetadata(ctx)
97 > if err != nil {
98 factory.Logger.Fatal("Failed to get current cluster ID", tag.Error(err))
99 }
100
101 > appName := "temporal" factory.go
102 > if currentClusterMetadata.UseClusterIdMembership {
103 > appName = fmt.Sprintf("temporal-%s", currentClusterMetadata.GetClusterId())
104 > }
105 > rp, err := ringpop.New(appName, ringpop.Channel(factory.getTChannel()), ringpop.AddressResolverFunc(factory.broadcastAddressResolver))
106 > if err != nil {
107 factory.Logger.Fatal("Failed to get new ringpop", tag.Error(err))
108 }
110 // Empirically, ringpop updates usually propagate in under a second even in relatively large clusters.
111 // 3 seconds is an over-estimate to be safer.
112 > maxPropagationTime := dynamicconfig.RingpopApproximateMaxPropagationTime.Get(factory.DC)() factory.go
113 > replicaPoints := dynamicconfig.RingpopReplicaPoints.Get(factory.DC)()
114 >
115 > factory.monitor = newMonitor(
116 > factory.ServiceName,
117 > factory.ServicePortMap,
118 > rp,
119 > factory.Logger,
120 > factory.MetadataManager,
121 > factory.broadcastAddressResolver,
122 > factory.Config.MaxJoinDuration,
123 > maxPropagationTime,
124 > factory.getJoinTime(maxPropagationTime),
125 > replicaPoints,
126 > )
127 })
128
129 > return factory.monitor factory.go
130 }
131
132 > func (factory *factory) getJoinTime(maxPropagationTime time.Duration) time.Time { factory.go
133 > var alignTime time.Duration
134 > switch factory.ServiceName {
135 > case primitives.MatchingService:
136 > alignTime = dynamicconfig.MatchingAlignMembershipChange.Get(factory.DC)()
137 > case primitives.HistoryService:
138 > alignTime = dynamicconfig.HistoryAlignMembershipChange.Get(factory.DC)()
139 }
140 > if alignTime == 0 { factory.go
141 > return time.Time{}
142 > }
143 return util.NextAlignedTime(time.Now().Add(maxPropagationTime), alignTime)
144 }
145
146 > func (factory *factory) broadcastAddressResolver() (string, error) { factory.go
147 > return buildBroadcastHostPort(factory.getTChannel().PeerInfo(), factory.Config.BroadcastAddress)
148 > }
149
150 > func (factory *factory) getTChannel() *tchannel.Channel { factory.go
151 > factory.chOnce.Do(func() {
152 > ringpopServiceName := fmt.Sprintf("%v-ringpop", factory.ServiceName)
153 > ringpopHostAddress := net.JoinHostPort(factory.getListenIP().String(), convert.IntToString(factory.RPCConfig.MembershipPort))
154 > enableTLS := dynamicconfig.EnableRingpopTLS.Get(factory.DC)()
155 >
156 > var tChannel *tchannel.Channel
157 > if enableTLS {
158 tChannel = factory.getTLSChannel(ringpopHostAddress, ringpopServiceName)
159 > } else { factory.go
160 > tChannel = factory.getTCPChannel(ringpopHostAddress, ringpopServiceName) factory.go
161 > }
162 > factory.channel = tChannel factory.go
163 })
164
165 > return factory.channel factory.go
166 }
167
168 > func (factory *factory) getTCPChannel(ringpopHostAddress string, ringpopServiceName string) *tchannel.Channel { factory.go
169 > listener, err := net.Listen("tcp", ringpopHostAddress)
170 > if err != nil {
171 factory.Logger.Fatal("Failed to start ringpop listener", tag.Error(err), tag.Address(ringpopHostAddress))
172 }
173
174 > tChannel, err := tchannel.NewChannel(ringpopServiceName, &tchannel.ChannelOptions{}) factory.go
175 > if err != nil {
176 factory.Logger.Fatal("Failed to create ringpop TChannel", tag.Error(err))
177 }
178
179 > if err := tChannel.Serve(listener); err != nil { factory.go
180 factory.Logger.Fatal("Failed to serve ringpop listener", tag.Error(err), tag.Address(ringpopHostAddress))
181 }
182 > return tChannel factory.go
183 }
184
211 }
212
213 > func (factory *factory) getListenIP() net.IP { factory.go
214 > if factory.RPCConfig.BindOnLocalHost && len(factory.RPCConfig.BindOnIP) > 0 {
215 factory.Logger.Fatal("ListenIP failed, bindOnLocalHost and bindOnIP are mutually exclusive")
216 return nil
217 }
218
219 > if factory.RPCConfig.BindOnLocalHost { factory.go
220 > return net.ParseIP(environment.GetLocalhostIP()) factory.go
221 > }
222
223 if len(factory.RPCConfig.BindOnIP) > 0 {
240
241 // closeTChannel allows fx Stop hook to close channel
242 > func (factory *factory) closeTChannel() { factory.go
243 > if factory.channel != nil {
244 > factory.getTChannel().Close()
245 > factory.channel = nil
246 > }
247 }
248
249 > func (factory *factory) getHostInfoProvider() (membership.HostInfoProvider, error) { factory.go
250 > address, err := factory.broadcastAddressResolver()
251 > if err != nil {
252 return nil, err
253 }
254
255 > servicePort, ok := factory.ServicePortMap[factory.ServiceName] factory.go
256 > if !ok {
257 return nil, membership.ErrUnknownService
258 }
261 // ringpop messages. We use a different port for the service, so we
262 // replace that portion.
263 > serviceAddress, err := replaceServicePort(address, servicePort) factory.go
264 > if err != nil {
265 return nil, err
266 }
267
268 > hostInfo := membership.NewHostInfoFromAddress(serviceAddress) factory.go
269 > return membership.NewHostInfoProvider(hostInfo), nil
270 }
go.temporal.io/server/common/metrics/grpc.go 96 covered LOC · 26 ranges

Open complete file

32 // NewServerMetricsContextInjectorInterceptor returns grpc server interceptor that adds metrics context to golang
33 // context.
34 > func NewServerMetricsContextInjectorInterceptor() grpc.UnaryServerInterceptor { grpc.go
35 > return func(
36 > ctx context.Context,
37 > req any,
38 > info *grpc.UnaryServerInfo,
39 > handler grpc.UnaryHandler,
40 > ) (any, error) {
41 > ctxWithMetricsBaggage := AddMetricsContext(ctx)
42 > return handler(ctxWithMetricsBaggage, req)
43 > }
44 }
45
46 // NewClientMetricsTrailerPropagatorInterceptor returns grpc client interceptor that injects metrics received in trailer
47 // into metrics context.
48 > func NewClientMetricsTrailerPropagatorInterceptor(logger log.Logger) grpc.UnaryClientInterceptor { grpc.go
49 > return func(
50 > ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker,
51 > opts ...grpc.CallOption,
52 > ) error {
53 > var trailer metadata.MD grpc.go
54 > optsWithTrailer := append(opts, grpc.Trailer(&trailer))
55 > err := invoker(ctx, method, req, reply, cc, optsWithTrailer...)
56 >
57 > baggageStrings := trailer.Get(metricsTrailerKey)
58 > if len(baggageStrings) == 0 {
59 > return err grpc.go
60 > }
61
62 > for _, baggageString := range baggageStrings { grpc.go
63 > baggageBytes := []byte(baggageString)
64 > metricsBaggage := &metricsspb.Baggage{}
65 > unmarshalErr := metricsBaggage.Unmarshal(baggageBytes)
66 > if unmarshalErr != nil {
67 logger.Error("unable to unmarshal metrics baggage from trailer", tag.Error(unmarshalErr))
68 continue
69 }
70 > for counterName, counterValue := range metricsBaggage.CountersInt { grpc.go
71 > ContextCounterAdd(ctx, counterName, counterValue) grpc.go
72 > }
73 }
74
75 > return err grpc.go
76 }
77 }
79 // NewServerMetricsTrailerPropagatorInterceptor returns grpc server interceptor that injects metrics from context into
80 // gRPC trailer.
81 > func NewServerMetricsTrailerPropagatorInterceptor(logger log.Logger) grpc.UnaryServerInterceptor { grpc.go
82 > return func(
83 > ctx context.Context,
84 > req any,
85 > info *grpc.UnaryServerInfo,
86 > handler grpc.UnaryHandler,
87 > ) (any, error) {
88 > // we want to return original handler response, so don't override err grpc.go
89 > resp, err := handler(ctx, req)
90 >
91 > select {
92 > case <-ctx.Done(): grpc.go
93 > return resp, err
94 > default: grpc.go
95 }
96
97 > metricsCtx := getMetricsContext(ctx) grpc.go
98 > if metricsCtx == nil {
99 return resp, err
100 }
101
102 > metricsBaggage := &metricsspb.Baggage{CountersInt: make(map[string]int64)} grpc.go
103 >
104 > metricsCtx.Lock()
105 > maps.Copy(metricsBaggage.CountersInt, metricsCtx.CountersInt)
106 > metricsCtx.Unlock()
107 >
108 > bytes, marshalErr := metricsBaggage.Marshal()
109 > if marshalErr != nil {
110 logger.Error("unable to marshal metric baggage", tag.Error(marshalErr))
111 }
112
113 > md := metadata.Pairs(metricsTrailerKey, string(bytes)) grpc.go
114 >
115 > marshalErr = grpc.SetTrailer(ctx, md)
116 > if marshalErr != nil {
117 logger.Error("unable to add metrics baggage to gRPC trailer", tag.Error(marshalErr))
118 }
119
120 > return resp, err grpc.go
121 }
122 }
123
124 // getMetricsContext extracts metrics context from golang context.
125 > func getMetricsContext(ctx context.Context) *metricsContext { grpc.go
126 > metricsCtx := ctx.Value(metricsCtxKey)
127 > if metricsCtx == nil {
128 return nil
129 }
130
131 > return metricsCtx.(*metricsContext) grpc.go
132 }
133
134 > func AddMetricsContext(ctx context.Context) context.Context { grpc.go
135 > metricsCtx := &metricsContext{}
136 > return context.WithValue(ctx, metricsCtxKey, metricsCtx)
137 > }
138
139 // ContextCounterAdd adds value to counter within metrics context.
140 > func ContextCounterAdd(ctx context.Context, name string, value int64) bool { grpc.go
141 > metricsCtx := getMetricsContext(ctx)
142 >
143 > if metricsCtx == nil {
144 return false
145 }
146
147 > metricsCtx.Lock() grpc.go
148 > defer metricsCtx.Unlock()
149 >
150 > if metricsCtx.CountersInt == nil {
151 > metricsCtx.CountersInt = make(map[string]int64)
152 > }
153
154 > val := metricsCtx.CountersInt[name] grpc.go
155 > val += value
156 > metricsCtx.CountersInt[name] = val
157 >
158 > return true
159 }
160
161 // ContextCounterGet returns value and true if successfully retrieved value
162 > func ContextCounterGet(ctx context.Context, name string) (int64, bool) { grpc.go
163 > metricsCtx := getMetricsContext(ctx)
164 >
165 > if metricsCtx == nil {
166 return 0, false
167 }
168
169 > metricsCtx.Lock() grpc.go
170 > defer metricsCtx.Unlock()
171 >
172 > if metricsCtx.CountersInt == nil {
173 > return 0, false grpc.go
174 > }
175
176 > result, ok := metricsCtx.CountersInt[name] grpc.go
177 > return result, ok
178 }
go.temporal.io/server/chasm/lib/scheduler/gen/schedulerpb/v1/request_response.pb.go 95 covered LOC · 37 ranges

Open complete file

46 func (*CreateScheduleRequest) ProtoMessage() {}
47
48 > func (x *CreateScheduleRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
49 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[0]
50 > if x != nil {
51 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
52 if ms.LoadMessageInfo() == nil {
97 func (*CreateScheduleResponse) ProtoMessage() {}
98
99 > func (x *CreateScheduleResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
100 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[1]
101 > if x != nil {
102 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
103 if ms.LoadMessageInfo() == nil {
143 func (*UpdateScheduleRequest) ProtoMessage() {}
144
145 > func (x *UpdateScheduleRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
146 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[2]
147 > if x != nil {
148 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
149 if ms.LoadMessageInfo() == nil {
194 func (*UpdateScheduleResponse) ProtoMessage() {}
195
196 > func (x *UpdateScheduleResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
197 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[3]
198 > if x != nil {
199 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
200 if ms.LoadMessageInfo() == nil {
240 func (*PatchScheduleRequest) ProtoMessage() {}
241
242 > func (x *PatchScheduleRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
243 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[4]
244 > if x != nil {
245 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
246 if ms.LoadMessageInfo() == nil {
291 func (*PatchScheduleResponse) ProtoMessage() {}
292
293 > func (x *PatchScheduleResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
294 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[5]
295 > if x != nil {
296 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
297 if ms.LoadMessageInfo() == nil {
337 func (*DeleteScheduleRequest) ProtoMessage() {}
338
339 > func (x *DeleteScheduleRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
340 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[6]
341 > if x != nil {
342 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
343 if ms.LoadMessageInfo() == nil {
388 func (*DeleteScheduleResponse) ProtoMessage() {}
389
390 > func (x *DeleteScheduleResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
391 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[7]
392 > if x != nil {
393 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
394 if ms.LoadMessageInfo() == nil {
434 func (*DescribeScheduleRequest) ProtoMessage() {}
435
436 > func (x *DescribeScheduleRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
437 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[8]
438 > if x != nil {
439 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
440 if ms.LoadMessageInfo() == nil {
485 func (*DescribeScheduleResponse) ProtoMessage() {}
486
487 > func (x *DescribeScheduleResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
488 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[9]
489 > if x != nil {
490 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
491 if ms.LoadMessageInfo() == nil {
531 func (*ListScheduleMatchingTimesRequest) ProtoMessage() {}
532
533 > func (x *ListScheduleMatchingTimesRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
534 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[10]
535 > if x != nil {
536 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
537 if ms.LoadMessageInfo() == nil {
582 func (*ListScheduleMatchingTimesResponse) ProtoMessage() {}
583
584 > func (x *ListScheduleMatchingTimesResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
585 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[11]
586 > if x != nil {
587 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
588 if ms.LoadMessageInfo() == nil {
628 func (*CreateFromMigrationStateRequest) ProtoMessage() {}
629
630 > func (x *CreateFromMigrationStateRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
631 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[12]
632 > if x != nil {
633 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
634 if ms.LoadMessageInfo() == nil {
678 func (*CreateFromMigrationStateResponse) ProtoMessage() {}
679
680 > func (x *CreateFromMigrationStateResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
681 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[13]
682 > if x != nil {
683 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
684 if ms.LoadMessageInfo() == nil {
718 func (*CreateSentinelRequest) ProtoMessage() {}
719
720 > func (x *CreateSentinelRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
721 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[14]
722 > if x != nil {
723 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
724 if ms.LoadMessageInfo() == nil {
775 func (*CreateSentinelResponse) ProtoMessage() {}
776
777 > func (x *CreateSentinelResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
778 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[15]
779 > if x != nil {
780 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
781 if ms.LoadMessageInfo() == nil {
819 func (*MigrateToWorkflowRequest) ProtoMessage() {}
820
821 > func (x *MigrateToWorkflowRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
822 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[16]
823 > if x != nil {
824 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
825 if ms.LoadMessageInfo() == nil {
883 func (*MigrateToWorkflowResponse) ProtoMessage() {}
884
885 > func (x *MigrateToWorkflowResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
886 > mi := &file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes[17]
887 > if x != nil {
888 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
889 if ms.LoadMessageInfo() == nil {
1021 }
1022
1023 > func init() { file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_init() } request_response.pb.go
1024 > func file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_init() {
1025 > if File_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto != nil {
1026 > return
1027 > }
1028 > file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_init()
1029 > type x struct{}
1030 > out := protoimpl.TypeBuilder{
1031 > File: protoimpl.DescBuilder{
1032 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1033 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_rawDesc), len(file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_rawDesc)),
1034 > NumEnums: 0,
1035 > NumMessages: 18,
1036 > NumExtensions: 0,
1037 > NumServices: 0,
1038 > },
1039 > GoTypes: file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_goTypes,
1040 > DependencyIndexes: file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_depIdxs,
1041 > MessageInfos: file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_msgTypes,
1042 > }.Build()
1043 > File_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto = out.File
1044 > file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_goTypes = nil
1045 > file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_depIdxs = nil
1046 }
go.temporal.io/server/common/log/zap_logger.go 94 covered LOC · 24 ranges

Open complete file

58 // NewTestLogger returns a logger for tests
59 // Deprecated: Use testlogger.TestLogger instead.
60 > func NewTestLogger() *zapLogger { zap_logger.go
61 > format := os.Getenv(TestLogFormatEnvVar)
62 > if format == "" {
63 > format = "console"
64 > }
65
66 > logger := BuildZapLogger(Config{ zap_logger.go
67 > Level: os.Getenv(TestLogLevelEnvVar),
68 > Format: format,
69 > Development: true,
70 > })
71 >
72 > // Don't include stack traces for warnings during tests. Only include them for logs with level error and above.
73 > logger = logger.WithOptions(zap.AddStacktrace(zap.ErrorLevel))
74 >
75 > return NewZapLogger(logger)
76 }
77
82
83 // NewZapLogger returns a new zap based logger from zap.Logger
84 > func NewZapLogger(zl *zap.Logger) *zapLogger { zap_logger.go
85 > return &zapLogger{
86 > zl: zl,
87 > skip: skipForZapLogger,
88 > baseZl: zl,
89 > }
90 > }
91
92 // BuildZapLogger builds and returns a new zap.Logger for this logging configuration
93 > func BuildZapLogger(cfg Config) *zap.Logger { zap_logger.go
94 > return buildZapLogger(cfg, true)
95 > }
96
97 > func caller(skip int) string { zap_logger.go
98 > _, path, line, ok := runtime.Caller(skip)
99 > if !ok {
100 return ""
101 }
102 > return path + ":" + strconv.Itoa(line) zap_logger.go
103 }
104
105 > func (l *zapLogger) buildFieldsWithCallAt(tags []tag.Tag) []zap.Field { zap_logger.go
106 > fields := make([]zap.Field, len(tags)+1)
107 > l.fillFields(tags, fields)
108 > fields[len(fields)-1] = zap.String(tag.LoggingCallAtKey, caller(l.skip))
109 > return fields
110 > }
111
112 // fillFields fill fields parameter with fields read from tags. Optimized for performance.
113 > func (l *zapLogger) fillFields(tags []tag.Tag, fields []zap.Field) { zap_logger.go
114 > for i, t := range tags {
115 > if zt, ok := t.(tag.ZapTag); ok { zap_logger.go
116 > fields[i] = zt.Field()
117 > } else {
118 fields[i] = zap.Any(t.Key(), t.Value())
119 }
121 }
122
123 > func setDefaultMsg(msg string) string { zap_logger.go
124 > if msg == "" {
125 > return defaultMsgForEmpty zap_logger.go
126 > }
127 > return msg zap_logger.go
128 }
129
130 > func (l *zapLogger) Debug(msg string, tags ...tag.Tag) { zap_logger.go
131 > if l.zl.Core().Enabled(zap.DebugLevel) {
132 msg = setDefaultMsg(msg)
133 fields := l.buildFieldsWithCallAt(tags)
136 }
137
138 > func (l *zapLogger) Info(msg string, tags ...tag.Tag) { zap_logger.go
139 > if l.zl.Core().Enabled(zap.InfoLevel) {
140 > msg = setDefaultMsg(msg)
141 > fields := l.buildFieldsWithCallAt(tags)
142 > l.zl.Info(msg, fields...)
143 > }
144 }
145
146 > func (l *zapLogger) Warn(msg string, tags ...tag.Tag) { zap_logger.go
147 > if l.zl.Core().Enabled(zap.WarnLevel) {
148 > msg = setDefaultMsg(msg)
149 > fields := l.buildFieldsWithCallAt(tags)
150 > l.zl.Warn(msg, fields...)
151 > }
152 }
153
154 > func (l *zapLogger) Error(msg string, tags ...tag.Tag) { zap_logger.go
155 > if l.zl.Core().Enabled(zap.ErrorLevel) {
156 > msg = setDefaultMsg(msg)
157 > fields := l.buildFieldsWithCallAt(tags)
158 > l.zl.Error(msg, fields...)
159 > }
160 }
161
234 }
235
236 > func buildZapLogger(cfg Config, disableCaller bool) *zap.Logger { zap_logger.go
237 > encodeConfig := DefaultZapEncoderConfig
238 > if disableCaller {
239 > encodeConfig.CallerKey = zapcore.OmitKey
240 > encodeConfig.EncodeCaller = nil
241 > }
242
243 > outputPath := "stderr" zap_logger.go
244 > if len(cfg.OutputFile) > 0 {
245 outputPath = cfg.OutputFile
246 }
247 > if cfg.Stdout { zap_logger.go
248 outputPath = "stdout"
249 }
250 > encoding := "json" zap_logger.go
251 > if cfg.Format == "console" {
252 > encoding = "console" zap_logger.go
253 > }
254 > config := zap.Config{ zap_logger.go
255 > Level: zap.NewAtomicLevelAt(ParseZapLevel(cfg.Level)),
256 > Development: cfg.Development,
257 > Sampling: nil,
258 > Encoding: encoding,
259 > EncoderConfig: encodeConfig,
260 > OutputPaths: []string{outputPath},
261 > ErrorOutputPaths: []string{outputPath},
262 > DisableCaller: disableCaller,
263 > }
264 > logger, _ := config.Build()
265 > return logger
266 }
267
297 }
298
299 > func ParseZapLevel(level string) zapcore.Level { zap_logger.go
300 > switch strings.ToLower(level) {
301 case "debug":
302 return zap.DebugLevel
313 case "fatal":
314 return zap.FatalLevel
315 > default: zap_logger.go
316 > return zap.InfoLevel
317 }
318 }
go.temporal.io/server/common/persistence/client/fx.go 93 covered LOC · 16 ranges

Open complete file

85 )
86
87 > func ClusterNameProvider(config *cluster.Config) ClusterName { fx.go
88 > return ClusterName(config.CurrentClusterName)
89 > }
90
91 func EventBlobCacheProvider(
93 logger log.Logger,
94 serializer serialization.Serializer,
95 > ) persistence.XDCCache { fx.go
96 > return persistence.NewEventsBlobCache(
97 > dynamicconfig.XDCCacheMaxSizeBytes.Get(dc)(),
98 > 20*time.Second,
99 > logger,
100 > )
101 > }
102
103 func EnableDataLossMetricsProvider(
104 dc *dynamicconfig.Collection,
105 > ) EnableDataLossMetrics { fx.go
106 > return EnableDataLossMetrics(dynamicconfig.EnableDataLossMetrics.Get(dc))
107 > }
108
109 func EnableBestEffortDeleteTasksOnWorkflowUpdateProvider(
110 dc *dynamicconfig.Collection,
111 > ) EnableBestEffortDeleteTasksOnWorkflowUpdate { fx.go
112 > return EnableBestEffortDeleteTasksOnWorkflowUpdate(dynamicconfig.EnableBestEffortDeleteTasksOnWorkflowUpdate.Get(dc))
113 > }
114
115 func FactoryProvider(
116 params NewFactoryParams,
117 > ) Factory { fx.go
118 > var systemRequestRateLimiter, namespaceRequestRateLimiter, shardRequestRateLimiter quotas.RequestRateLimiter
119 > if params.PersistenceMaxQPS != nil && params.PersistenceMaxQPS() > 0 {
120 > systemRequestRateLimiter = NewPriorityRateLimiter(
121 > params.PersistenceMaxQPS,
122 > RequestPriorityFn,
123 > params.OperatorRPSRatio,
124 > params.PersistenceBurstRatio,
125 > params.HealthSignals,
126 > params.DynamicRateLimitingParams,
127 > params.MetricsHandler,
128 > params.Logger,
129 > )
130 > namespaceRequestRateLimiter = NewPriorityNamespaceRateLimiter(
131 > params.PersistenceMaxQPS,
132 > params.PersistenceNamespaceMaxQPS,
133 > RequestPriorityFn,
134 > params.OperatorRPSRatio,
135 > params.PersistenceBurstRatio,
136 > )
137 > shardRequestRateLimiter = NewPriorityNamespaceShardRateLimiter(
138 > params.PersistenceMaxQPS,
139 > params.PersistencePerShardNamespaceMaxQPS,
140 > RequestPriorityFn,
141 > params.OperatorRPSRatio,
142 > params.PersistenceBurstRatio,
143 > )
144 > }
145
146 > return NewFactory( fx.go
147 > params.DataStoreFactory,
148 > params.Cfg,
149 > systemRequestRateLimiter,
150 > namespaceRequestRateLimiter,
151 > shardRequestRateLimiter,
152 > params.Serializer,
153 > params.EventBlobCache,
154 > string(params.ClusterName),
155 > params.MetricsHandler,
156 > params.Logger,
157 > params.HealthSignals,
158 > params.EnableDataLossMetrics,
159 > params.EnableBestEffortDeleteTasksOnWorkflowUpdate,
160 > )
161 }
162
166 metricsHandler metrics.Handler,
167 logger log.ThrottledLogger,
168 > ) persistence.HealthSignalAggregator { fx.go
169 > if dynamicconfig.PersistenceHealthSignalMetricsEnabled.Get(dynamicCollection)() {
170 > aggregator := persistence.NewHealthSignalAggregator(
171 > dynamicconfig.PersistenceHealthSignalAggregationEnabled.Get(dynamicCollection)(),
172 > dynamicconfig.PersistenceHealthSignalPercentilesEnabled.Get(dynamicCollection),
173 > dynamicconfig.PersistenceHealthSignalWindowSize.Get(dynamicCollection)(),
174 > dynamicconfig.PersistenceHealthSignalBufferSize.Get(dynamicCollection)(),
175 > metricsHandler,
176 > logger,
177 > dynamicconfig.PersistenceHealthSignalLatencyWindowSize.Get(dynamicCollection)(),
178 > dynamicconfig.PersistenceHealthSignalLatencyWindowCount.Get(dynamicCollection)(),
179 > )
180 > lc.Append(fx.StopHook(aggregator.Stop))
181 > return aggregator
182 > }
183
184 return persistence.NoopHealthSignalAggregator
194 tracerProvider trace.TracerProvider,
195 serializer serialization.Serializer,
196 > ) persistence.DataStoreFactory { fx.go
197 > var dataStoreFactory persistence.DataStoreFactory
198 > defaultStoreCfg := cfg.DataStores[cfg.DefaultStore]
199 > switch {
200 case defaultStoreCfg.Cassandra != nil:
201 dataStoreFactory = cassandra.NewFactory(*defaultStoreCfg.Cassandra, r, string(clusterName), logger, metricsHandler, serializer)
202 > case defaultStoreCfg.SQL != nil: fx.go
203 > dataStoreFactory = sql.NewFactory(*defaultStoreCfg.SQL, r, string(clusterName), logger, metricsHandler, serializer)
204 case defaultStoreCfg.CustomDataStoreConfig != nil:
205 dataStoreFactory = abstractDataStoreFactory.NewFactory(*defaultStoreCfg.CustomDataStoreConfig, r, string(clusterName), logger, metricsHandler, serializer)
208 }
209
210 > if defaultStoreCfg.FaultInjection != nil { fx.go
211 dataStoreFactory = faultinjection.NewFaultInjectionDatastoreFactory(defaultStoreCfg.FaultInjection, dataStoreFactory)
212 }
213
214 > tracer := tracerProvider.Tracer(otel.ComponentPersistence) fx.go
215 > if otel.IsEnabled(tracer) {
216 dataStoreFactory = telemetry.NewTelemetryDataStoreFactory(dataStoreFactory, logger, tracer)
217 }
218
219 > return dataStoreFactory fx.go
220 }
221
222 > func DataStoreFactoryLifetimeHooks(lc fx.Lifecycle, f persistence.DataStoreFactory) { fx.go
223 > lc.Append(fx.StopHook(f.Close))
224 > }
225
226 > func managerProvider[T persistence.Closeable](newManagerFn func(Factory) (T, error)) func(Factory, fx.Lifecycle) (T, error) { fx.go
227 > return func(f Factory, lc fx.Lifecycle) (T, error) {
228 > manager, err := newManagerFn(f) // passing receiver (Factory) as first argument. fx.go
229 > if err != nil {
230 var unimpl *serviceerror.Unimplemented
231 if errors.As(err, &unimpl) {
236 return nilT, err
237 }
238 > lc.Append(fx.StopHook(manager.Close)) fx.go
239 > return manager, nil
240 }
241 }
go.temporal.io/server/service/worker/fx.go 91 covered LOC · 12 ranges

Open complete file

59 fx.Provide(schedulerpb.NewSchedulerServiceLayeredClient),
60 fx.Provide(
61 > func(c resource.HistoryClient) dlq.HistoryClient { fx.go
62 > return c
63 > },
64 > func(m cluster.Metadata) dlq.CurrentClusterName {
65 > return dlq.CurrentClusterName(m.GetCurrentClusterName())
66 > },
67 > func(b client.Bean) dlq.TaskClientDialer {
68 > return dlq.TaskClientDialerFn(func(_ context.Context, address string) (dlq.TaskClient, error) {
69 c, err := b.GetRemoteAdminClient(address)
70 if err != nil {
94 logger log.Logger,
95 testHooks testhooks.TestHooks,
96 > ) nsreplication.TaskExecutor { fx.go
97 > return nsreplication.NewTaskExecutor(
98 > clusterMetadata.GetCurrentClusterName(),
99 > metadataManager,
100 > dataMerger,
101 > admitter,
102 > logger,
103 > testHooks,
104 > )
105 > }),
106 fx.Provide(nsreplication.NewNoopDataMerger),
107 fx.Provide(nsreplication.NewDefaultAdmitter),
113 )
114
115 > func ThrottledLoggerRpsFnProvider(serviceConfig *Config) resource.ThrottledLoggerRpsFn { fx.go
116 > return func() float64 { return float64(serviceConfig.ThrottledLogRPS()) }
117 }
118
121 persistenceLazyLoadedServiceResolver service.PersistenceLazyLoadedServiceResolver,
122 logger log.SnTaggedLogger,
123 > ) service.PersistenceRateLimitingParams { fx.go
124 > return service.NewPersistenceRateLimitingParams(
125 > serviceConfig.PersistenceMaxQPS,
126 > serviceConfig.PersistenceGlobalMaxQPS,
127 > serviceConfig.PersistenceNamespaceMaxQPS,
128 > serviceConfig.PersistenceGlobalNamespaceMaxQPS,
129 > serviceConfig.PersistencePerShardNamespaceMaxQPS,
130 > serviceConfig.OperatorRPSRatio,
131 > serviceConfig.PersistenceQPSBurstRatio,
132 > serviceConfig.PersistenceDynamicRateLimitingParams,
133 > persistenceLazyLoadedServiceResolver,
134 > logger,
135 > )
136 > }
137
138 > func HostInfoProvider() (membership.HostInfo, error) { fx.go
139 > hn, err := os.Hostname()
140 > return membership.NewHostInfoFromAddress(hn), err
141 > }
142
143 func ServiceResolverProvider(
144 membershipMonitor membership.Monitor,
145 > ) (membership.ServiceResolver, error) { fx.go
146 > return membershipMonitor.GetResolver(primitives.WorkerService)
147 > }
148
149 func ConfigProvider(
150 dc *dynamicconfig.Collection,
151 persistenceConfig *config.Persistence,
152 > ) *Config { fx.go
153 > return NewConfig(
154 > dc,
155 > persistenceConfig,
156 > )
157 > }
158
159 func VisibilityManagerProvider(
169 chasmRegistry *chasm.Registry,
170 serializer serialization.Serializer,
171 > ) (manager.VisibilityManager, error) { fx.go
172 > return visibility.NewManager(
173 > *persistenceConfig,
174 > persistenceServiceResolver,
175 > customVisibilityStoreFactory,
176 > nil, // worker visibility never write
177 > saProvider,
178 > searchAttributesMapperProvider,
179 > namespaceRegistry,
180 > chasmRegistry,
181 > serviceConfig.VisibilityPersistenceMaxReadQPS,
182 > serviceConfig.VisibilityPersistenceMaxWriteQPS,
183 > serviceConfig.OperatorRPSRatio,
184 > serviceConfig.VisibilityPersistenceSlowQueryThreshold,
185 > serviceConfig.EnableReadFromSecondaryVisibility,
186 > serviceConfig.VisibilityEnableShadowReadMode,
187 > dynamicconfig.GetStringPropertyFn(visibility.SecondaryVisibilityWritingModeOff), // worker visibility never write
188 > serviceConfig.VisibilityDisableOrderByClause,
189 > serviceConfig.VisibilityEnableManualPagination,
190 > serviceConfig.VisibilityEnableUnifiedQueryConverter,
191 > metricsHandler,
192 > logger,
193 > serializer,
194 > )
195 > }
196
197 > func ServiceLifetimeHooks(lc fx.Lifecycle, svc *Service) { fx.go
198 > lc.Append(fx.StartStopHook(svc.Start, svc.Stop))
199 > }
200
201 type perNamespaceWorkerManagerInitParams struct {
210 }
211
212 > func PerNamespaceWorkerManagerProvider(params perNamespaceWorkerManagerInitParams) *PerNamespaceWorkerManager { fx.go
213 > return NewPerNamespaceWorkerManager(
214 > params.Logger,
215 > params.SdkClientFactory,
216 > params.NamespaceRegistry,
217 > params.HostName,
218 > params.Config,
219 > params.ClusterMetadata,
220 > params.Components,
221 > primitives.PerNSWorkerTaskQueue,
222 > )
223 > }
224
225 > func ServerProvider(rpcFactory common.RPCFactory, logger log.Logger) *grpc.Server { fx.go
226 > opts, err := rpcFactory.GetInternodeGRPCServerOptions()
227 > if err != nil {
228 logger.Fatal("Failed to get gRPC server options", tag.Error(err))
229 }
230 > return grpc.NewServer(opts...) fx.go
231 }
go.temporal.io/server/common/tasks/sequential_scheduler.go 90 covered LOC · 20 ranges

Open complete file

52 taskQueueFactory SequentialTaskQueueFactory[T],
53 logger log.Logger,
54 > ) *SequentialScheduler[T] { sequential_scheduler.go
55 > return &SequentialScheduler[T]{
56 > status: common.DaemonStatusInitialized,
57 > shutdownChan: make(chan struct{}),
58 > options: options,
59 >
60 > logger: logger,
61 >
62 > queueFactory: taskQueueFactory,
63 > queueChan: make(chan SequentialTaskQueue[T], options.QueueSize),
64 > queues: collection.NewShardedConcurrentTxMap(1024, taskQueueHashFn),
65 > }
66 > }
67
68 > func (s *SequentialScheduler[T]) Start() { sequential_scheduler.go
69 > if !atomic.CompareAndSwapInt32(
70 > &s.status,
71 > common.DaemonStatusInitialized,
72 > common.DaemonStatusStarted,
73 > ) {
74 return
75 }
76
77 > initialWorkerCount, workerCountSubscriptionCancelFn := s.options.WorkerCount(s.updateWorkerCount) sequential_scheduler.go
78 > s.workerCountSubscriptionCancelFn = workerCountSubscriptionCancelFn
79 > s.updateWorkerCount(initialWorkerCount)
80 >
81 > s.logger.Info("sequential scheduler started")
82 }
83
84 > func (s *SequentialScheduler[T]) Stop() { sequential_scheduler.go
85 > if !atomic.CompareAndSwapInt32(
86 > &s.status,
87 > common.DaemonStatusStarted,
88 > common.DaemonStatusStopped,
89 > ) {
90 return
91 }
92
93 > close(s.shutdownChan) sequential_scheduler.go
94 > s.workerCountSubscriptionCancelFn()
95 > s.updateWorkerCount(0)
96 > // must be called after the close of the shutdownChan
97 > s.drainTasks()
98 >
99 > go func() {
100 > if success := common.AwaitWaitGroup(&s.shutdownWG, time.Minute); !success {
101 s.logger.Warn("sequential scheduler timed out waiting for workers")
102 }
103 }()
104 > s.logger.Info("sequential scheduler stopped") sequential_scheduler.go
105 }
106
199 }
200
201 > func (s *SequentialScheduler[T]) updateWorkerCount(targetWorkerNum int) { sequential_scheduler.go
202 > s.workerLock.Lock()
203 > defer s.workerLock.Unlock()
204 >
205 > if s.isStopped() {
206 > // Always set the value to 0 when scheduler is stopped, sequential_scheduler.go
207 > // in case there's a race condition between subscription callback invocation
208 > // and the invocation made from Stop()
209 > targetWorkerNum = 0
210 > }
211
212 > if targetWorkerNum < 0 { sequential_scheduler.go
213 s.logger.Error("Target worker pool size is negative. Please fix the dynamic config.", tag.Key("worker-pool-size"), tag.Value(targetWorkerNum))
214 return
215 }
216
217 > currentWorkerNum := len(s.workerShutdownCh) sequential_scheduler.go
218 > if targetWorkerNum == currentWorkerNum {
219 return
220 }
221
222 > if targetWorkerNum > currentWorkerNum { sequential_scheduler.go
223 > s.startWorkers(targetWorkerNum - currentWorkerNum)
224 > } else {
225 > s.stopWorkers(currentWorkerNum - targetWorkerNum) sequential_scheduler.go
226 > }
227
228 > s.logger.Info("Update worker pool size", tag.Key("worker-pool-size"), tag.Value(targetWorkerNum)) sequential_scheduler.go
229 }
230
231 func (s *SequentialScheduler[T]) startWorkers(
232 count int,
234 > for range count {
235 > shutdownCh := make(chan struct{})
236 > s.workerShutdownCh = append(s.workerShutdownCh, shutdownCh)
237 >
238 > s.shutdownWG.Add(1)
239 > go s.pollTaskQueue(shutdownCh)
240 > }
241 }
242
243 func (s *SequentialScheduler[T]) stopWorkers(
244 count int,
246 > shutdownChToClose := s.workerShutdownCh[:count]
247 > s.workerShutdownCh = s.workerShutdownCh[count:]
248 >
249 > for _, shutdownCh := range shutdownChToClose {
250 > close(shutdownCh)
251 > }
252 }
253
254 > func (s *SequentialScheduler[T]) pollTaskQueue(workerShutdownCh <-chan struct{}) { sequential_scheduler.go
255 > defer s.shutdownWG.Done()
256 >
257 > for {
258 > select {
259 > case <-s.shutdownChan: sequential_scheduler.go
260 > s.drainTasks()
261 > return
262 case <-workerShutdownCh:
263 return
345 }
346
347 > func (s *SequentialScheduler[T]) drainTasks() { sequential_scheduler.go
348 > LoopDrainQueues:
349 > for {
350 > select {
351 case queue := <-s.queueChan:
352 LoopDrainSingleQueue:
362 }
363 }
364 > default: sequential_scheduler.go
365 > break LoopDrainQueues
366 }
367 }
368 }
369
370 > func (s *SequentialScheduler[T]) isStopped() bool { sequential_scheduler.go
371 > return atomic.LoadInt32(&s.status) == common.DaemonStatusStopped
372 > }
go.temporal.io/server/common/tasks/interleaved_weighted_round_robin.go 89 covered LOC · 20 ranges

Open complete file

75 fifoScheduler Scheduler[T],
76 logger log.Logger,
77 > ) *InterleavedWeightedRoundRobinScheduler[T, K] { interleaved_weighted_round_robin.go
78 > iwrrChannels := atomic.Value{}
79 > iwrrChannels.Store(WeightedChannels[T]{})
80 >
81 > return &InterleavedWeightedRoundRobinScheduler[T, K]{
82 > status: common.DaemonStatusInitialized,
83 >
84 > ts: clock.NewRealTimeSource(),
85 > fifoScheduler: fifoScheduler,
86 > logger: logger,
87 >
88 > options: options,
89 >
90 > notifyChan: make(chan struct{}, 1),
91 > shutdownChan: make(chan struct{}),
92 >
93 > numInflightTask: 0,
94 > weightedChannels: make(map[K]*WeightedChannel[T]),
95 > iwrrChannels: iwrrChannels,
96 > }
97 > }
98
99 > func (s *InterleavedWeightedRoundRobinScheduler[T, K]) Start() { interleaved_weighted_round_robin.go
100 > if !atomic.CompareAndSwapInt32(
101 > &s.status,
102 > common.DaemonStatusInitialized,
103 > common.DaemonStatusStarted,
104 > ) {
105 return
106 }
107
108 > s.fifoScheduler.Start() interleaved_weighted_round_robin.go
109 >
110 > s.shutdownWG.Add(1)
111 > go s.eventLoop()
112 >
113 > s.shutdownWG.Add(1)
114 > go s.cleanupLoop()
115 >
116 > s.logger.Info("interleaved weighted round robin task scheduler started")
117 }
118
119 > func (s *InterleavedWeightedRoundRobinScheduler[T, K]) Stop() { interleaved_weighted_round_robin.go
120 > if !atomic.CompareAndSwapInt32(
121 > &s.status,
122 > common.DaemonStatusStarted,
123 > common.DaemonStatusStopped,
124 > ) {
125 return
126 }
127
128 > close(s.shutdownChan) interleaved_weighted_round_robin.go
129 >
130 > s.fifoScheduler.Stop()
131 >
132 > s.abortTasks()
133 >
134 > if success := common.AwaitWaitGroup(&s.shutdownWG, time.Minute); !success {
135 s.logger.Warn("interleaved weighted round robin task scheduler timed out on shutdown.")
136 }
137 > s.logger.Info("interleaved weighted round robin task scheduler stopped") interleaved_weighted_round_robin.go
138 }
139
158 func (s *InterleavedWeightedRoundRobinScheduler[T, K]) TrySubmit(
159 task T,
161 > numTasks := atomic.AddInt64(&s.numInflightTask, 1)
162 > if !s.isStopped() && numTasks == 1 && s.tryDispatchTaskDirectly(task) {
164 > }
165
166 // there are tasks pending dispatching, need to respect round roubin weight
177 }
178
179 > func (s *InterleavedWeightedRoundRobinScheduler[T, K]) eventLoop() { interleaved_weighted_round_robin.go
180 > defer s.shutdownWG.Done()
181 >
182 > for {
183 > select {
184 case <-s.notifyChan:
185 s.dispatchTasksWithWeight()
186 > case <-s.shutdownChan: interleaved_weighted_round_robin.go
187 > return
188 }
189 }
190 }
191
192 > func (s *InterleavedWeightedRoundRobinScheduler[T, K]) cleanupLoop() { interleaved_weighted_round_robin.go
193 > defer s.shutdownWG.Done()
194 > if s.options.InactiveChannelDeletionDelay == nil {
196 > }
197 > ch, _ := s.ts.NewTimer(s.options.InactiveChannelDeletionDelay()) interleaved_weighted_round_robin.go
198 > for {
199 > select {
200 case <-ch:
201 s.doCleanup()
202 ch, _ = s.ts.NewTimer(s.options.InactiveChannelDeletionDelay())
203 > case <-s.shutdownChan: interleaved_weighted_round_robin.go
204 > return
205 }
206 }
381 }
382
383 > func (s *InterleavedWeightedRoundRobinScheduler[T, K]) abortTasks() { interleaved_weighted_round_robin.go
384 > s.RLock()
385 > defer s.RUnlock()
386 >
387 > numTasks := int64(0)
388 > DrainLoop:
389 > for _, channel := range s.weightedChannels {
390 for {
391 select {
go.temporal.io/server/service/matching/scale_manager.go 89 covered LOC · 17 ranges

Open complete file

76 getWritePartitions dynamicconfig.IntPropertyFn,
77 emitGaugeMetrics dynamicconfig.BoolPropertyFn,
78 > ) *scaleManager { scale_manager.go
79 > return &scaleManager{
80 > partition: partition,
81 > logger: log.With(logger, tag.ComponentPartitionScaler),
82 > metricsHandler: metricsHandler,
83 > userDataManager: userDataManager,
84 > matchingClient: matchingClient,
85 > partitionScaler: partitionScaler,
86 > batchSize: int64(settings().BatchSize),
87 > settings: settings,
88 > getWritePartitions: getWritePartitions,
89 > emitGaugeMetrics: emitGaugeMetrics,
90 > timeSource: timeSource,
91 > background: goro.NewHandle(baseCtx),
92 > wakeup: make(chan struct{}, 1),
93 > }
94 > }
95
96 > func (sm *scaleManager) Stop() { scale_manager.go
97 > if sm == nil {
98 > return scale_manager.go
99 > }
100 > sm.background.Cancel() scale_manager.go
101 > sm.partitionScaler.Stop()
102 > if sm.emitGaugeMetrics() {
103 > // this is unfortunate but at least allows max() across pods to get the right value scale_manager.go
104 > metrics.PartitionScaleRead.With(sm.metricsHandler).Record(float64(-1))
105 > metrics.PartitionScaleWrite.With(sm.metricsHandler).Record(float64(-1))
106 > metrics.PartitionScaleTarget.With(sm.metricsHandler).Record(float64(-1))
107 > }
108 }
109
110 // Start is called when the root partitions's default queue has loaded its metadata.
111 // Must be called at most once.
112 > func (sm *scaleManager) Start(scaleState *persistencespb.PartitionScaleState, scaleDB scaleDB) { scale_manager.go
113 > if sm == nil {
114 return
115 }
116 // backgroundWork can assume sm.scaleDB is set since we set it before starting it.
117 > sm.scaleDB = scaleDB scale_manager.go
118 > sm.setState(scaleState, sm.settings())
119 > sm.background.Go(sm.backgroundWork)
120 }
121
122 // AddedTasks is called on a batch of tasks added.
123 // This is called in the task add path, so it shouldn't block.
124 > func (sm *scaleManager) AddedTasks(numTasks int) { scale_manager.go
125 > if sm == nil {
126 return
127 }
128
129 // scale target batch size by numTasks (since numTasks is scaled by partitions)
130 > batchSize := int64(numTasks) * sm.batchSize scale_manager.go
131 > if sm.batch.Add(int64(numTasks)) < batchSize {
132 > return // not enough for a batch yet scale_manager.go
133 > }
134
135 // non-blocking signal
140 }
141
142 > func (sm *scaleManager) backgroundWork(ctx context.Context) error { scale_manager.go
143 > timerCh := func() <-chan time.Time {
144 > ch, _ := sm.timeSource.NewTimer(backoff.Jitter(sm.settings().BackgroundInterval, 0.05))
145 > return ch
146 > }
147 > ch := timerCh()
148 > for {
149 > select {
150 > case <-ctx.Done(): scale_manager.go
151 > return ctx.Err()
152
153 case <-sm.wakeup:
290 // This should only be called _after_ the state is persisted to the db.
291 // Called from backgroundWork or LoadedMetadata only.
292 > func (sm *scaleManager) setState(newState *persistencespb.PartitionScaleState, settings dynamicconfig.PartitionScaleManagerSettings) { scale_manager.go
293 > prevInfo := scaleStateToInfo(sm.scaleState, settings)
294 >
295 > sm.scaleState = newState
296 >
297 > newInfo := scaleStateToInfo(sm.scaleState, settings)
298 >
299 > // only push ephemeral data if _info_ changed, not on any state change
300 > if !proto.Equal(prevInfo, newInfo) {
301 sm.userDataManager.SetPartitionScale(newInfo)
302 }
303
304 > if sm.emitGaugeMetrics() { scale_manager.go
305 > metrics.PartitionScaleRead.With(sm.metricsHandler).Record(float64(newInfo.Read)) scale_manager.go
306 > metrics.PartitionScaleWrite.With(sm.metricsHandler).Record(float64(newInfo.Write))
307 > metrics.PartitionScaleTarget.With(sm.metricsHandler).Record(float64(sm.scaleState.GetTarget()))
308 > }
309 }
310
446 }
447
448 > func scaleStateToReadCount(scaleState *persistencespb.PartitionScaleState) int32 { scale_manager.go
449 > return max(scaleState.GetTarget(), bitSet(scaleState.GetBacklogState()).len())
450 > }
451
452 func scaleStateToInfo(
453 scaleState *persistencespb.PartitionScaleState,
454 settings dynamicconfig.PartitionScaleManagerSettings,
455 > ) *taskqueuespb.PartitionScaleInfo { scale_manager.go
456 > // note if scaleState == nil, read and write will both be 0
457 > read := scaleStateToReadCount(scaleState)
458 > allowedShrink := max(
459 > 1,
460 > min(
461 > int32(float32(read)*settings.ShrinkRatio),
462 > settings.ShrinkDelta,
463 > ),
464 > )
465 > write := max(
466 > scaleState.GetTarget(),
467 > read-allowedShrink,
468 > )
469 > return &taskqueuespb.PartitionScaleInfo{
470 > Read: read,
471 > Write: write,
472 > BacklogCounts: scaleState.GetBacklogCounts(),
473 > BacklogCap: scaleState.GetBacklogCap(),
474 > Version: scaleState.GetTargetVersion(),
475 > }
476 > }
go.temporal.io/server/api/persistence/v1/cluster_metadata.pb.go 88 covered LOC · 20 ranges

Open complete file

47 }
48
49 > func (x *ClusterMetadata) Reset() { cluster_metadata.pb.go
50 > *x = ClusterMetadata{}
51 > mi := &file_temporal_server_api_persistence_v1_cluster_metadata_proto_msgTypes[0]
52 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
53 > ms.StoreMessageInfo(mi)
54 > }
55
56 func (x *ClusterMetadata) String() string {
60 func (*ClusterMetadata) ProtoMessage() {}
61
62 > func (x *ClusterMetadata) ProtoReflect() protoreflect.Message { cluster_metadata.pb.go
63 > mi := &file_temporal_server_api_persistence_v1_cluster_metadata_proto_msgTypes[0]
64 > if x != nil {
65 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) cluster_metadata.pb.go
66 > if ms.LoadMessageInfo() == nil {
67 > ms.StoreMessageInfo(mi)
68 > }
69 > return ms
70 }
71 > return mi.MessageOf(x) cluster_metadata.pb.go
72 }
73
77 }
78
79 > func (x *ClusterMetadata) GetClusterName() string { cluster_metadata.pb.go
80 > if x != nil {
81 > return x.ClusterName
82 > }
83 return ""
84 }
85
86 > func (x *ClusterMetadata) GetHistoryShardCount() int32 { cluster_metadata.pb.go
87 > if x != nil {
88 > return x.HistoryShardCount
89 > }
90 return 0
91 }
92
93 > func (x *ClusterMetadata) GetClusterId() string { cluster_metadata.pb.go
94 > if x != nil {
95 > return x.ClusterId
96 > }
97 return ""
98 }
105 }
106
107 > func (x *ClusterMetadata) GetIndexSearchAttributes() map[string]*IndexSearchAttributes { cluster_metadata.pb.go
108 > if x != nil {
109 > return x.IndexSearchAttributes
110 > }
111 return nil
112 }
113
114 > func (x *ClusterMetadata) GetClusterAddress() string { cluster_metadata.pb.go
115 > if x != nil {
116 > return x.ClusterAddress
117 > }
118 return ""
119 }
120
121 > func (x *ClusterMetadata) GetHttpAddress() string { cluster_metadata.pb.go
122 > if x != nil {
123 > return x.HttpAddress
124 > }
125 return ""
126 }
133 }
134
135 > func (x *ClusterMetadata) GetInitialFailoverVersion() int64 { cluster_metadata.pb.go
136 > if x != nil {
137 > return x.InitialFailoverVersion
138 > }
139 return 0
140 }
147 }
148
149 > func (x *ClusterMetadata) GetIsConnectionEnabled() bool { cluster_metadata.pb.go
150 > if x != nil {
151 > return x.IsConnectionEnabled
152 > }
153 return false
154 }
161 }
162
163 > func (x *ClusterMetadata) GetTags() map[string]string { cluster_metadata.pb.go
164 > if x != nil {
165 > return x.Tags
166 > }
167 return nil
168 }
169
170 > func (x *ClusterMetadata) GetIsReplicationEnabled() bool { cluster_metadata.pb.go
171 > if x != nil {
172 > return x.IsReplicationEnabled
173 > }
174 return false
175 }
195 func (*IndexSearchAttributes) ProtoMessage() {}
196
197 > func (x *IndexSearchAttributes) ProtoReflect() protoreflect.Message { cluster_metadata.pb.go
198 > mi := &file_temporal_server_api_persistence_v1_cluster_metadata_proto_msgTypes[1]
199 > if x != nil {
200 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) cluster_metadata.pb.go
201 > if ms.LoadMessageInfo() == nil {
202 > ms.StoreMessageInfo(mi)
203 > }
204 > return ms
205 }
206 > return mi.MessageOf(x) cluster_metadata.pb.go
207 }
208
212 }
213
214 > func (x *IndexSearchAttributes) GetCustomSearchAttributes() map[string]v11.IndexedValueType { cluster_metadata.pb.go
215 > if x != nil {
216 > return x.CustomSearchAttributes
217 > }
218 return nil
219 }
289 }
290
291 > func init() { file_temporal_server_api_persistence_v1_cluster_metadata_proto_init() } cluster_metadata.pb.go
292 > func file_temporal_server_api_persistence_v1_cluster_metadata_proto_init() {
293 > if File_temporal_server_api_persistence_v1_cluster_metadata_proto != nil {
294 return
295 }
296 > type x struct{} cluster_metadata.pb.go
297 > out := protoimpl.TypeBuilder{
298 > File: protoimpl.DescBuilder{
299 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
300 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_cluster_metadata_proto_rawDesc), len(file_temporal_server_api_persistence_v1_cluster_metadata_proto_rawDesc)),
301 > NumEnums: 0,
302 > NumMessages: 5,
303 > NumExtensions: 0,
304 > NumServices: 0,
305 > },
306 > GoTypes: file_temporal_server_api_persistence_v1_cluster_metadata_proto_goTypes,
307 > DependencyIndexes: file_temporal_server_api_persistence_v1_cluster_metadata_proto_depIdxs,
308 > MessageInfos: file_temporal_server_api_persistence_v1_cluster_metadata_proto_msgTypes,
309 > }.Build()
310 > File_temporal_server_api_persistence_v1_cluster_metadata_proto = out.File
311 > file_temporal_server_api_persistence_v1_cluster_metadata_proto_goTypes = nil
312 > file_temporal_server_api_persistence_v1_cluster_metadata_proto_depIdxs = nil
313 }
go.temporal.io/server/client/clientfactory.go 88 covered LOC · 17 ranges

Open complete file

73
74 // NewFactoryProvider creates a default implementation of FactoryProvider.
75 > func NewFactoryProvider() FactoryProvider { clientfactory.go
76 > return &factoryProviderImpl{}
77 > }
78
79 // NewFactory creates an instance of client factory that knows how to dispatch RPC calls.
87 logger log.Logger,
88 throttledLogger log.Logger,
89 > ) Factory { clientfactory.go
90 > return &rpcClientFactory{
91 > rpcFactory: rpcFactory,
92 > monitor: monitor,
93 > metricsHandler: metricsHandler,
94 > dynConfig: dc,
95 > testHooks: testHooks,
96 > numberOfHistoryShards: numberOfHistoryShards,
97 > logger: logger,
98 > throttledLogger: throttledLogger,
99 > }
100 > }
101
102 > func (cf *rpcClientFactory) NewHistoryClientWithTimeout(timeout time.Duration) (historyservice.HistoryServiceClient, error) { clientfactory.go
103 > resolver, err := cf.monitor.GetResolver(primitives.HistoryService)
104 > if err != nil {
105 return nil, err
106 }
107 > client := history.NewClient( clientfactory.go
108 > cf.dynConfig,
109 > resolver,
110 > cf.logger,
111 > cf.numberOfHistoryShards,
112 > cf.rpcFactory,
113 > timeout,
114 > )
115 > if cf.metricsHandler != nil {
116 > client = history.NewMetricClient(client, cf.metricsHandler, cf.logger, cf.throttledLogger)
117 > }
118 > return client, nil
119 }
120
123 timeout time.Duration,
124 longPollTimeout time.Duration,
125 > ) (matchingservice.MatchingServiceClient, error) { clientfactory.go
126 > resolver, err := cf.monitor.GetResolver(primitives.MatchingService)
127 > if err != nil {
128 return nil, err
129 }
130
131 > keyResolver := newServiceKeyResolver(resolver) clientfactory.go
132 > clientProvider := func(clientKey string) (any, func() error, error) {
133 > connection := cf.rpcFactory.CreateMatchingGRPCConnection(clientKey) clientfactory.go
134 > return matchingservice.NewMatchingServiceClient(connection), connection.Close, nil
135 > }
136 > client := matching.NewClient( clientfactory.go
137 > timeout,
138 > longPollTimeout,
139 > common.NewClientCache(keyResolver, clientProvider, cf.logger),
140 > cf.metricsHandler,
141 > cf.logger,
142 > matching.NewLoadBalancer(namespaceIDToName, cf.dynConfig, cf.testHooks),
143 > dynamicconfig.MatchingSpreadRoutingBatchSize.Get(cf.dynConfig),
144 > resolver,
145 > dynamicconfig.MatchingConnectionCloseDelay.Get(cf.dynConfig),
146 > )
147 >
148 > if cf.metricsHandler != nil {
149 > client = matching.NewMetricClient(client, cf.metricsHandler, cf.logger, cf.throttledLogger)
150 > }
151 > return client, nil
152
153 }
166 timeout time.Duration,
167 longPollTimeout time.Duration,
168 > ) (grpc.ClientConnInterface, workflowservice.WorkflowServiceClient, error) { clientfactory.go
169 > connection := cf.rpcFactory.CreateLocalFrontendGRPCConnection()
170 > client := workflowservice.NewWorkflowServiceClient(connection)
171 > return connection, cf.newFrontendClient(client, timeout, longPollTimeout), nil
172 > }
173
174 func (cf *rpcClientFactory) NewRemoteAdminClientWithTimeout(
185 timeout time.Duration,
186 longPollTimeout time.Duration,
187 > ) (adminservice.AdminServiceClient, error) { clientfactory.go
188 > connection := cf.rpcFactory.CreateLocalFrontendGRPCConnection()
189 > client := adminservice.NewAdminServiceClient(connection)
190 > return cf.newAdminClient(client, timeout, longPollTimeout), nil
191 > }
192
193 func (cf *rpcClientFactory) newAdminClient(
195 timeout time.Duration,
196 longPollTimeout time.Duration,
197 > ) adminservice.AdminServiceClient { clientfactory.go
198 > client = admin.NewClient(timeout, longPollTimeout, client)
199 > if cf.metricsHandler != nil {
200 > client = admin.NewMetricClient(client, cf.metricsHandler, cf.throttledLogger)
201 > }
202 > return client
203 }
204
207 timeout time.Duration,
208 longPollTimeout time.Duration,
209 > ) workflowservice.WorkflowServiceClient { clientfactory.go
210 > client = frontend.NewClient(timeout, longPollTimeout, client)
211 > if cf.metricsHandler != nil {
212 > client = frontend.NewMetricClient(client, cf.metricsHandler, cf.throttledLogger)
213 > }
214 > return client
215 }
216
217 > func newServiceKeyResolver(resolver membership.ServiceResolver) *serviceKeyResolverImpl { clientfactory.go
218 > return &serviceKeyResolverImpl{
219 > resolver: resolver,
220 > }
221 > }
222
223 // Lookup returns the address for a node within a batch. key contains the key (including batch
224 // number), and index is the index within the batch. If not using batches, index should be 0.
225 // Note that Lookup(key) and LookupN(key, n)[0] are equal.
226 > func (r *serviceKeyResolverImpl) Lookup(key string, index int) (string, error) { clientfactory.go
227 > hosts := r.resolver.LookupN(key, index+1)
228 > if len(hosts) == 0 {
229 > return "", membership.ErrInsufficientHosts clientfactory.go
230 > }
231 > if index >= len(hosts) { clientfactory.go
232 index %= len(hosts)
233 }
234 > return hosts[index].GetAddress(), nil clientfactory.go
235 }
236
go.temporal.io/server/service/history/handler.go 88 covered LOC · 29 ranges

Open complete file

173
174 // Start starts the handler
175 > func (h *Handler) Start() { handler.go
176 > if !atomic.CompareAndSwapInt32(
177 > &h.status,
178 > common.DaemonStatusInitialized,
179 > common.DaemonStatusStarted,
180 > ) {
181 return
182 }
183
184 > h.replicationTaskFetcherFactory.Start() handler.go
185 > h.streamReceiverMonitor.Start()
186 > // events notifier must starts before controller
187 > h.eventNotifier.Start()
188 > h.controller.Start()
189 > h.dlqMetricsEmitter.Start()
190 }
191
192 // Stop stops the handler
193 > func (h *Handler) Stop() { handler.go
194 > if !atomic.CompareAndSwapInt32(
195 > &h.status,
196 > common.DaemonStatusStarted,
197 > common.DaemonStatusStopped,
198 > ) {
199 return
200 }
201
202 > h.streamReceiverMonitor.Stop() handler.go
203 > h.replicationTaskFetcherFactory.Stop()
204 > h.controller.Stop()
205 > h.eventNotifier.Stop()
206 > h.dlqMetricsEmitter.Stop()
207 }
208
356
357 // RecordWorkflowTaskStarted - Record Workflow Task started.
358 > func (h *Handler) RecordWorkflowTaskStarted(ctx context.Context, request *historyservice.RecordWorkflowTaskStartedRequest) (*historyservice.RecordWorkflowTaskStartedResponseWithRawHistory, error) { handler.go
359 > namespaceID := namespace.ID(request.GetNamespaceId())
360 > workflowExecution := request.WorkflowExecution
361 > workflowID := workflowExecution.GetWorkflowId()
362 > if namespaceID == "" {
363 return nil, h.convertError(errNamespaceNotSet)
364 }
365
366 > if request.PollRequest == nil || request.PollRequest.TaskQueue.GetName() == "" { handler.go
367 return nil, h.convertError(errTaskQueueNotSet)
368 }
369
370 > shardContext, err := h.controller.GetShardByNamespaceWorkflow(namespaceID, workflowID) handler.go
371 > if err != nil {
372 return nil, h.convertError(err)
373 }
374 > engine, err := shardContext.GetEngine(ctx) handler.go
375 > if err != nil {
376 h.logger.Error("RecordWorkflowTaskStarted failed.",
377 tag.Error(err),
383 }
384
385 > response, err := engine.RecordWorkflowTaskStarted(ctx, request) handler.go
386 > if err != nil {
387 return nil, h.convertError(err)
388 }
389 > response.Clock, err = shardContext.NewVectorClock() handler.go
390 > if err != nil {
391 return nil, h.convertError(err)
392 }
393 > return response, nil handler.go
394 }
395
548
549 // RespondWorkflowTaskCompleted - records completion of a workflow task
550 > func (h *Handler) RespondWorkflowTaskCompleted(ctx context.Context, request *historyservice.RespondWorkflowTaskCompletedRequest) (*historyservice.RespondWorkflowTaskCompletedResponse, error) { handler.go
551 > namespaceID := namespace.ID(request.GetNamespaceId())
552 > if namespaceID == "" {
553 return nil, h.convertError(errNamespaceNotSet)
554 }
555
556 > completeRequest := request.CompleteRequest handler.go
557 > token, err := h.tokenSerializer.Deserialize(completeRequest.TaskToken)
558 > if err != nil {
559 return nil, consts.ErrDeserializingToken
560 }
561
562 > h.logger.Debug("RespondWorkflowTaskCompleted", handler.go
563 > tag.WorkflowNamespaceID(token.GetNamespaceId()),
564 > tag.WorkflowID(token.GetWorkflowId()),
565 > tag.WorkflowRunID(token.GetRunId()),
566 > tag.WorkflowScheduledEventID(token.GetScheduledEventId()))
567 >
568 > err = validateTaskToken(token)
569 > if err != nil {
570 return nil, h.convertError(err)
571 }
572 > workflowID := token.GetWorkflowId() handler.go
573 >
574 > shardContext, err := h.controller.GetShardByNamespaceWorkflow(namespaceID, workflowID)
575 > if err != nil {
576 return nil, h.convertError(err)
577 }
578 > engine, err := shardContext.GetEngine(ctx) handler.go
579 > if err != nil {
580 return nil, h.convertError(err)
581 }
582
583 > response, err := engine.RespondWorkflowTaskCompleted(ctx, request) handler.go
584 > if err != nil {
585 return nil, h.convertError(err)
586 }
587
588 > return response, nil handler.go
589 }
590
632
633 // StartWorkflowExecution - creates a new workflow execution
634 > func (h *Handler) StartWorkflowExecution(ctx context.Context, request *historyservice.StartWorkflowExecutionRequest) (*historyservice.StartWorkflowExecutionResponse, error) { handler.go
635 > namespaceID := namespace.ID(request.GetNamespaceId())
636 > if namespaceID == "" {
637 return nil, h.convertError(errNamespaceNotSet)
638 }
639
640 > startRequest := request.StartRequest handler.go
641 > workflowID := startRequest.GetWorkflowId()
642 > shardContext, err := h.controller.GetShardByNamespaceWorkflow(namespaceID, workflowID)
643 > if err != nil {
644 return nil, h.convertError(err)
645 }
646
647 > engine, err := shardContext.GetEngine(ctx) handler.go
648 > if err != nil {
649 return nil, h.convertError(err)
650 }
651
652 > response, err := engine.StartWorkflowExecution(ctx, request) handler.go
653 > if err != nil {
654 return nil, h.convertError(err)
655 }
656 > if response.Clock == nil { handler.go
657 > response.Clock, err = shardContext.NewVectorClock()
658 > if err != nil {
659 return nil, h.convertError(err)
660 }
661 }
662 > return response, nil handler.go
663 }
664
1926 ctx context.Context,
1927 request *historyservice.GetWorkflowExecutionHistoryRequest,
1928 > ) (*historyservice.GetWorkflowExecutionHistoryResponseWithRaw, error) { handler.go
1929 > shardContext, err := h.controller.GetShardByNamespaceWorkflow(
1930 > namespace.ID(request.GetNamespaceId()),
1931 > request.Request.GetExecution().GetWorkflowId(),
1932 > )
1933 > if err != nil {
1934 return nil, h.convertError(err)
1935 }
1936
1937 > engine, err := shardContext.GetEngine(ctx) handler.go
1938 > if err != nil {
1939 return nil, h.convertError(err)
1940 }
1941
1942 > return engine.GetWorkflowExecutionHistory(ctx, request) handler.go
1943 }
1944
2260 }
2261
2262 > func validateTaskToken(taskToken *tokenspb.Task) error { handler.go
2263 > if len(taskToken.GetComponentRef()) == 0 && taskToken.GetWorkflowId() == "" {
2264 return errBusinessIDNotSet
2265 }
2266
2267 > return nil handler.go
2268 }
2269
go.temporal.io/server/common/persistence/query_util.go 86 covered LOC · 33 ranges

Open complete file

55 func LoadAndSplitQueryFromReaders(
56 readers []io.Reader,
57 > ) ([]string, error) { query_util.go
58 > result := make([]string, 0, querySliceDefaultSize)
59 > for _, r := range readers {
60 > content, err := io.ReadAll(r)
61 > if err != nil {
62 return nil, fmt.Errorf("error reading contents: %w", err)
63 }
64 > n := len(content) query_util.go
65 > contentStr := string(bytes.ToLower(content))
66 > for i, j := 0, 0; i < n; i = j {
67 > // stack to keep track of open parenthesis/blocks
68 > var st []byte
69 > var stmtBuilder strings.Builder
70 >
71 > stmtLoop:
72 > for ; j < n; j++ {
73 > switch contentStr[j] {
74 > case queryDelimiter: query_util.go
75 > if len(st) == 0 {
76 > j++
77 > break stmtLoop
78 }
79
80 > case sqlLeftParenthesis: query_util.go
81 > st = append(st, sqlLeftParenthesis)
82
83 > case sqlRightParenthesis: query_util.go
84 > if len(st) == 0 || st[len(st)-1] != sqlLeftParenthesis {
85 return nil, fmt.Errorf("error reading contents: unmatched right parenthesis")
86 }
87 > st = st[:len(st)-1] query_util.go
88
89 case sqlDoubleDollarKeyword[0]:
99 }
100
101 > case sqlIfKeyword[0]: query_util.go
102 > if !hasWordAt(contentStr, sqlIfKeyword, j) {
103 > continue
104 }
105 if hasWordsBefore(contentStr, j-1, sqlAddKeyword, sqlColumnKeyword) ||
112 j += len(sqlIfKeyword) - 1
113
114 > case sqlLoopKeyword[0]: query_util.go
115 > if !hasWordAt(contentStr, sqlLoopKeyword, j) {
116 > continue
117 }
118 st = append(st, sqlLoopKeyword[0])
119 j += len(sqlLoopKeyword) - 1
120
121 > case sqlBeginKeyword[0]: query_util.go
122 > if hasWordAt(contentStr, sqlBeginKeyword, j) {
123 > st = append(st, sqlBeginKeyword[0]) query_util.go
124 > j += len(sqlBeginKeyword) - 1
125 > }
126
127 > case sqlEndKeyword[0]: query_util.go
128 > if !hasWordAt(contentStr, sqlEndKeyword, j) {
129 > continue
130 }
131 > if ok, after := hasWordAfter(contentStr, sqlIfKeyword, j+len(sqlEndKeyword)); ok { query_util.go
132 if len(st) == 0 || st[len(st)-1] != sqlIfKeyword[0] {
133 return nil, errors.New("error reading contents: unmatched `END IF` keyword")
135 st = st[:len(st)-1]
136 j = after + len(sqlIfKeyword) - 1
137 > } else if ok, after := hasWordAfter(contentStr, sqlLoopKeyword, j+len(sqlEndKeyword)); ok { query_util.go
138 //nolint:revive
139 if len(st) == 0 || st[len(st)-1] != sqlLoopKeyword[0] {
142 st = st[:len(st)-1]
143 j = after + len(sqlLoopKeyword) - 1
144 > } else { query_util.go
145 > if len(st) == 0 || st[len(st)-1] != sqlBeginKeyword[0] {
146 return nil, errors.New("error reading contents: unmatched `END` keyword")
147 }
148 > st = st[:len(st)-1] query_util.go
149 > j += len(sqlEndKeyword) - 1
150 }
151
152 > case sqlSingleQuote, sqlDoubleQuote: query_util.go
153 > quote := contentStr[j]
154 > j++
155 > for j < n && contentStr[j] != quote {
156 > j++
157 > }
158 > if j == n {
159 return nil, fmt.Errorf("error reading contents: unmatched quotes")
160 }
161
162 > case sqlLineComment[0]: query_util.go
163 > if j+len(sqlLineComment) <= n && contentStr[j:j+len(sqlLineComment)] == sqlLineComment {
164 > _, _ = stmtBuilder.Write(bytes.TrimRight(content[i:j], " "))
165 > for j < n && contentStr[j] != '\n' {
166 > j++
167 > }
168 > i = j
169 }
170
171 > default: query_util.go
172 // no-op: generic character
173 }
174 }
175
176 > if len(st) > 0 { query_util.go
177 switch st[len(st)-1] {
178 case sqlLeftParenthesis:
186 }
187
188 > _, _ = stmtBuilder.Write(content[i:j]) query_util.go
189 > stmt := strings.TrimSpace(stmtBuilder.String())
190 > if stmt == "" {
191 > continue query_util.go
192 }
193 > result = append(result, stmt) query_util.go
194 }
195 }
196 > return result, nil query_util.go
197 }
198
199 // hasWordAt is a simple test to check if it matches the whole word:
200 // it checks if the adjacent characters are not alphanumeric if they exist.
201 > func hasWordAt(s, word string, pos int) bool { query_util.go
202 > if pos+len(word) > len(s) || s[pos:pos+len(word)] != word {
203 > return false
204 > }
205 > if pos > 0 && isAlphanumeric(s[pos-1]) { query_util.go
206 > return false query_util.go
207 > }
208 > if pos+len(word) < len(s) && isAlphanumeric(s[pos+len(word)]) { query_util.go
209 > return false query_util.go
210 > }
211 > return true query_util.go
212 }
213
214 // hasWordAfter checks if the given word appears after position pos in s,
215 // separated by at least one space, and is a whole word.
216 > func hasWordAfter(s, word string, pos int) (bool, int) { query_util.go
217 > after := pos
218 > for after < len(s) && unicode.IsSpace(rune(s[after])) {
219 after++
220 }
221 > if after == pos { query_util.go
222 > return false, after query_util.go
223 > }
224 return hasWordAt(s, word, after), after
225 }
254 }
255
256 > func isAlphanumeric(c byte) bool { query_util.go
257 > return unicode.IsLetter(rune(c)) || unicode.IsDigit(rune(c))
258 > }
go.temporal.io/server/common/rpc/interceptor/health_check.go 86 covered LOC · 17 ranges

Open complete file

68 )
69
70 > func initExcludedAPIs() { health_check.go
71 > excludedAPIs = make(map[string]bool)
72 > excludedCategories := map[commonspb.ApiCategory]bool{
73 > commonspb.API_CATEGORY_LONG_POLL: true,
74 > commonspb.API_CATEGORY_SYSTEM: true,
75 > }
76 >
77 > // Process HistoryService explicitly.
78 > processServiceFile(historyservice.File_temporal_server_api_historyservice_v1_service_proto, excludedCategories)
79 >
80 > // Auto-detect all registered chasm/lib service files.
81 > // New services under chasm/lib are picked up automatically without code changes here.
82 > protoregistry.GlobalFiles.RangeFiles(func(fd protoreflect.FileDescriptor) bool {
83 > path := string(fd.Path())
84 > if strings.HasPrefix(path, chasmProtoPrefix) && strings.HasSuffix(path, serviceProtoSuffix) {
85 > processServiceFile(fd, excludedCategories)
86 > }
87 > return true
88 })
89 }
90
91 // processServiceFile enumerates all methods in a service file and adds excluded categories to excludedAPIs.
92 > func processServiceFile(file protoreflect.FileDescriptor, excludedCategories map[commonspb.ApiCategory]bool) { health_check.go
93 > services := file.Services()
94 > for i := 0; i < services.Len(); i++ {
95 > service := services.Get(i)
96 > methods := service.Methods()
97 > for j := 0; j < methods.Len(); j++ {
98 > method := methods.Get(j)
99 > opts, ok := method.Options().(*descriptorpb.MethodOptions)
100 > if ok && proto.HasExtension(opts, commonspb.E_ApiCategory) {
101 > categoryOpts, ok := proto.GetExtension(opts, commonspb.E_ApiCategory).(*commonspb.ApiCategoryOptions)
102 > if ok && categoryOpts != nil && excludedCategories[categoryOpts.GetCategory()] {
103 > fullMethod := fmt.Sprintf("/%s/%s", service.FullName(), method.Name())
104 > excludedAPIs[fullMethod] = true
105 > }
106 }
107 }
110
111 // isExcludedAPI checks if an API is marked as a non-standard API via proto options.
112 > func isExcludedAPI(fullMethod string) bool { health_check.go
113 > excludedAPIsOnce.Do(initExcludedAPIs)
114 > return excludedAPIs[fullMethod]
115 > }
116
117 // NewHealthCheckInterceptor creates a new health check interceptor
118 > func NewHealthCheckInterceptor(healthSignalAggregator HealthSignalAggregator) *HealthCheckInterceptor { health_check.go
119 > return &HealthCheckInterceptor{
120 > healthSignalAggregator: healthSignalAggregator,
121 > }
122 > }
123
124 // UnaryIntercept implements the gRPC unary interceptor interface
128 info *grpc.UnaryServerInfo,
129 handler grpc.UnaryHandler,
130 > ) (any, error) { health_check.go
131 > startTime := time.Now()
132 > resp, err := handler(ctx, req)
133 > elapsed := time.Since(startTime)
134 >
135 > // Skip health signal recording for non-standard APIs
136 > if isExcludedAPI(info.FullMethod) {
137 return resp, err
138 }
139
140 > if specialCaseAPIIsPolling(req) { health_check.go
141 > return resp, err
142 > }
143
144 // Record health signal for standard APIs
145 > h.healthSignalAggregator.Record(elapsed, err) health_check.go
146 > return resp, err
147 }
148
150 // Note that this interceptor may run in multiple Temporal services, so it needs to handle every version of
151 // each special request type. (for example, historyservice GetWorkflowExecutionHistory vs. workflowservice)
152 > func specialCaseAPIIsPolling(req any) bool { health_check.go
153 > switch request := req.(type) {
154 // history
155 > case *historyservice.GetWorkflowExecutionHistoryRequest: health_check.go
156 > inner := request.GetRequest()
157 > return inner != nil && inner.GetWaitNewEvent()
158
159 // frontend
162 case *workflowservice.DescribeActivityExecutionRequest:
163 return len(request.GetLongPollToken()) > 0
164 > default: health_check.go
165 > return false
166 }
167 }
176 latencyWindowSize time.Duration,
177 latencyWindowCount int,
178 > ) *healthSignalAggregatorImpl { health_check.go
179 > latencyDistribution, err := stats.NewWindowedTDigest(stats.WindowConfig{
180 > WindowSize: latencyWindowSize,
181 > WindowCount: latencyWindowCount,
182 > })
183 > if err != nil {
184 logger.Error("failed to create latency distribution helper, falling back to default config", tag.Error(err))
185 latencyDistribution, err = stats.NewWindowedTDigest(stats.WindowConfig{
192 }
193
194 > return &healthSignalAggregatorImpl{ health_check.go
195 > logger: logger,
196 > aggregatorEnabled: aggregatorEnabled,
197 > percentilesEnabled: percentilesEnabled,
198 > latencyAverage: aggregate.NewMovingWindowAvgImpl(windowSize, maxBufferSize),
199 > latencyDistribution: latencyDistribution,
200 > errorRatio: aggregate.NewMovingWindowAvgImpl(windowSize, maxBufferSize),
201 > }
202 }
203
204 > func (s *healthSignalAggregatorImpl) Record(latency time.Duration, err error) { health_check.go
205 > if !s.aggregatorEnabled() {
206 s.logger.Debug("health signal aggregator is disabled")
207 return
208 }
209 > s.latencyAverage.Record(latency.Milliseconds()) health_check.go
210 > if s.percentilesEnabled() && s.latencyDistribution != nil {
211 s.latencyDistribution.RecordToLatestWindow(float64(latency.Milliseconds()))
212 }
213
214 > if isUnhealthyError(err) { health_check.go
215 s.errorRatio.Record(1)
216 > } else { health_check.go
217 > s.errorRatio.Record(0)
218 > }
219 }
220
247 }
248
249 > func isUnhealthyError(err error) bool { health_check.go
250 > if err == nil {
251 > return false
252 > }
253 if common.IsContextCanceledErr(err) {
254 return true
go.temporal.io/server/service/history/workflow/metrics.go 86 covered LOC · 19 ranges

Open complete file

22 historySize int,
23 historyCount int,
24 > ) { metrics.go
25 > handler := metricsHandler.WithTags(metrics.NamespaceTag(namespace.String()))
26 > executionScope := handler.WithTags(metrics.OperationTag(metrics.ExecutionStatsScope))
27 > metrics.HistorySize.With(executionScope).Record(int64(historySize))
28 > metrics.HistoryCount.With(executionScope).Record(int64(historyCount))
29 >
30 > if state == enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED {
31 > completionScope := handler.WithTags(metrics.OperationTag(metrics.WorkflowCompletionStatsScope)) metrics.go
32 > metrics.HistorySize.With(completionScope).Record(int64(historySize))
33 > metrics.HistoryCount.With(completionScope).Record(int64(historyCount))
34 > }
35 }
36
40 archetypeID chasm.ArchetypeID,
41 stats *persistence.MutableStateStatistics,
42 > ) { metrics.go
43 > if stats == nil {
44 > return metrics.go
45 > }
46
47 > mutableStateMetricsHandler := metricsHandler metrics.go
48 > if archetypeTag, ok := getArchetypeMetricTag(chasmRegistry, archetypeID); ok {
49 > mutableStateMetricsHandler = mutableStateMetricsHandler.WithTags(archetypeTag)
50 > }
51
52 > batchHandler := mutableStateMetricsHandler.StartBatch("mutable_state_status") metrics.go
53 > defer batchHandler.Close()
54 > metrics.MutableStateSize.With(batchHandler).Record(int64(stats.TotalSize))
55 > metrics.ExecutionInfoSize.With(batchHandler).Record(int64(stats.ExecutionInfoSize))
56 > metrics.ExecutionStateSize.With(batchHandler).Record(int64(stats.ExecutionStateSize))
57 > metrics.ActivityInfoSize.With(batchHandler).Record(int64(stats.ActivityInfoSize))
58 > metrics.ActivityInfoCount.With(batchHandler).Record(int64(stats.ActivityInfoCount))
59 > metrics.TotalActivityCount.With(batchHandler).Record(stats.TotalActivityCount)
60 > metrics.TimerInfoSize.With(batchHandler).Record(int64(stats.TimerInfoSize))
61 > metrics.TimerInfoCount.With(batchHandler).Record(int64(stats.TimerInfoCount))
62 > metrics.TotalUserTimerCount.With(batchHandler).Record(stats.TotalUserTimerCount)
63 > metrics.ChildInfoSize.With(batchHandler).Record(int64(stats.ChildInfoSize))
64 > metrics.ChildInfoCount.With(batchHandler).Record(int64(stats.ChildInfoCount))
65 > metrics.TotalChildExecutionCount.With(batchHandler).Record(stats.TotalChildExecutionCount)
66 > metrics.RequestCancelInfoSize.With(batchHandler).Record(int64(stats.RequestCancelInfoSize))
67 > metrics.RequestCancelInfoCount.With(batchHandler).Record(int64(stats.RequestCancelInfoCount))
68 > metrics.TotalRequestCancelExternalCount.With(batchHandler).Record(stats.TotalRequestCancelExternalCount)
69 > metrics.SignalInfoSize.With(batchHandler).Record(int64(stats.SignalInfoSize))
70 > metrics.SignalInfoCount.With(batchHandler).Record(int64(stats.SignalInfoCount))
71 > metrics.TotalSignalExternalCount.With(batchHandler).Record(stats.TotalSignalExternalCount)
72 > metrics.SignalRequestIDSize.With(batchHandler).Record(int64(stats.SignalRequestIDSize))
73 > metrics.SignalRequestIDCount.With(batchHandler).Record(int64(stats.SignalRequestIDCount))
74 > metrics.TotalSignalCount.With(batchHandler).Record(stats.TotalSignalCount)
75 > metrics.BufferedEventsSize.With(batchHandler).Record(int64(stats.BufferedEventsSize))
76 > metrics.BufferedEventsCount.With(batchHandler).Record(int64(stats.BufferedEventsCount))
77 > metrics.ChasmTotalSize.With(batchHandler).Record(int64(stats.ChasmTotalSize))
78 >
79 > if stats.HistoryStatistics != nil {
80 > metrics.HistorySize.With(metricsHandler).Record(int64(stats.HistoryStatistics.SizeDiff)) metrics.go
81 > metrics.HistoryCount.With(metricsHandler).Record(int64(stats.HistoryStatistics.CountDiff))
82 > }
83
84 > for category, taskCount := range stats.TaskCountByCategory { metrics.go
85 > metrics.TaskCount.With(batchHandler).Record(int64(taskCount), metrics.TaskCategoryTag(category)) metrics.go
86 > }
87 }
88
90 chasmRegistry *chasm.Registry,
91 archetypeID chasm.ArchetypeID,
92 > ) (metrics.Tag, bool) { metrics.go
93 > switch archetypeID {
94 case chasm.UnspecifiedArchetypeID:
95 return metrics.ArchetypeTag(""), true
96 > case chasm.WorkflowArchetypeID: metrics.go
97 > return metrics.ArchetypeTag(chasm.WorkflowComponentName), true
98 }
99
109 completion completionMetric,
110 config *configs.Config,
111 > ) { metrics.go
112 > // Only emit metrics for Workflows, not other Chasm archetypes
113 > if !completion.isWorkflow {
114 return
115 }
116
117 > handler := GetPerTaskQueueFamilyScope(metricsHandler, namespace, completion.taskQueue, config, metrics.go
118 > metrics.OperationTag(metrics.WorkflowCompletionStatsScope),
119 > metrics.NamespaceStateTag(completion.namespaceState),
120 > metrics.WorkflowTypeTag(completion.workflowTypeName),
121 > )
122 >
123 > closed := true
124 > switch completion.status {
125 > case enumspb.WORKFLOW_EXECUTION_STATUS_COMPLETED: metrics.go
126 > metrics.WorkflowSuccessCount.With(handler).Record(1)
127 case enumspb.WORKFLOW_EXECUTION_STATUS_CANCELED:
128 metrics.WorkflowCancelCount.With(handler).Record(1)
135 case enumspb.WORKFLOW_EXECUTION_STATUS_CONTINUED_AS_NEW:
136 metrics.WorkflowContinuedAsNewCount.With(handler).Record(1)
137 > case enumspb.WORKFLOW_EXECUTION_STATUS_UNSPECIFIED, enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING: metrics.go
138 > closed = false
139 }
140 > if closed && completion.startTime != nil && completion.closeTime != nil { metrics.go
141 > startTime := completion.startTime.AsTime() metrics.go
142 > closeTime := completion.closeTime.AsTime()
143 > if closeTime.After(startTime) {
144 > metrics.WorkflowScheduleToCloseLatency.With(handler).Record(closeTime.Sub(startTime)) metrics.go
145 > }
146 }
147 }
153 config *configs.Config,
154 tags ...metrics.Tag,
155 > ) metrics.Handler { metrics.go
156 > return metrics.GetPerTaskQueueFamilyScope(handler,
157 > namespaceName.String(),
158 > tqid.UnsafeTaskQueueFamily(namespaceName.String(), taskQueueFamily),
159 > config.BreakdownMetricsByTaskQueue(namespaceName.String(), taskQueueFamily, enumspb.TASK_QUEUE_TYPE_WORKFLOW),
160 > tags...,
161 > )
162 > }
163
164 type ActivityExecutionStatus int
go.temporal.io/server/service/history/workflow/update/registry.go 86 covered LOC · 27 ranges

Open complete file

108 // WithInFlightLimit provides an optional limit to the number of incomplete
109 // Updates that a Registry instance will allow.
110 > func WithInFlightLimit(f func() int) Option { registry.go
111 > return func(r *registry) {
112 > r.maxInFlightUpdateCount = f
113 > }
114 }
115
116 // WithInFlightSizeLimit provides an optional limit to the total payload size of incomplete
117 // Updates that a Registry instance will allow.
118 > func WithInFlightSizeLimit(f func() int) Option { registry.go
119 > return func(r *registry) {
120 > r.maxInFlightUpdateSize = f
121 > }
122 }
123
124 // WithTotalLimit provides an optional limit to the total number of Updates for workflow run.
125 > func WithTotalLimit(f func() int) Option { registry.go
126 > return func(r *registry) {
127 > r.maxTotal = f
128 > }
129 }
130
131 // WithTotalLimitSuggestCAN provides an optional threshold for suggesting ContinueAsNew
132 // when the total number of Updates reaches a certain percentage of the total limit.
133 > func WithTotalLimitSuggestCAN(f func() float64) Option { registry.go
134 > return func(r *registry) {
135 > r.maxTotalSuggestContinueAsNewThreshold = f
136 > }
137 }
138
139 // WithNamespace sets the namespace name to be used in Registry metrics and logs.
140 > func WithNamespace(ns string) Option { registry.go
141 > return func(r *registry) {
142 > r.instrumentation.namespace = ns
143 > }
144 }
145
146 // WithLogger sets the log.Logger to be used by Registry and its Updates.
147 > func WithLogger(l log.Logger) Option { registry.go
148 > return func(r *registry) {
149 > r.instrumentation.log = l
150 > }
151 }
152
153 // WithMetrics sets the metrics.Handler to be used by Registry and its Updates.
154 > func WithMetrics(m metrics.Handler) Option { registry.go
155 > return func(r *registry) {
156 > r.instrumentation.metrics = m
157 > }
158 }
159
160 // WithTracerProvider sets the trace.TracerProvider (and by extension the
161 // trace.Tracer) to be used by Registry and its Updates.
162 > func WithTracerProvider(t trace.TracerProvider) Option { registry.go
163 > return func(r *registry) {
164 > r.instrumentation.tracer = t.Tracer(telemetry.ComponentUpdateRegistry)
165 > }
166 }
167
169 store UpdateStore,
170 opts ...Option,
171 > ) Registry { registry.go
172 > r := &registry{
173 > updates: make(map[string]*Update),
174 > store: store,
175 > instrumentation: noopInstrumentation,
176 > failoverVersion: store.GetCurrentVersion(),
177 > maxTotal: func() int { return 0 }, // ie disabled
178 maxInFlightUpdateSize: func() int { return 0 }, // ie disabled
179 maxInFlightUpdateCount: func() int { return 0 }, // ie disabled
180 maxTotalSuggestContinueAsNewThreshold: func() float64 { return 0 }, // ie disabled
181 }
182 > r.maxTotalSuggestContinueAsNew = func() int { registry.go
183 > return int(math.Ceil(float64(r.maxTotal()) * r.maxTotalSuggestContinueAsNewThreshold())) registry.go
184 > }
185 > for _, opt := range opts { registry.go
186 > opt(r) registry.go
187 > }
188
189 > r.store.VisitUpdates(func(updID string, updInfo *persistencespb.UpdateInfo) { registry.go
190 if updInfo.GetAdmission() != nil {
191 // An Update entry in the Registry may have a request payload: we use this to write the payload to an
281 }
282
283 > func (r *registry) Abort(reason AbortReason) { registry.go
284 > for _, upd := range r.updates {
285 upd.abort(reason, effect.Immediate(context.Background()))
286 }
287 }
288
289 > func (r *registry) AbortAccepted(reason AbortReason, effects effect.Controller) { registry.go
290 > for _, upd := range r.updates {
291 if upd.state.Matches(stateSet(stateProvisionallyAccepted | stateAccepted)) {
292 upd.abort(reason, effects)
329 includeAlreadySent bool,
330 workflowTaskStartedEventID int64,
331 > ) []*protocolpb.Message { registry.go
332 > var outgoingMessages []*protocolpb.Message
333 >
334 > // TODO (alex-update): currently sequencing_id is simply pointing to the
335 > // event before WorkflowTaskStartedEvent. SDKs are supposed to respect this
336 > // and process messages (specifically, updates) after event with that ID.
337 > // In the future, sequencing_id could point to some specific event
338 > // (specifically, signal) after which the update should be processed.
339 > // Currently, it is not possible due to buffered events reordering on server
340 > // and events reordering in some SDKs.
341 > sequencingEventID := &protocolpb.Message_EventId{EventId: workflowTaskStartedEventID - 1}
342 >
343 > // Sort Updates by the time they were admitted to send them in deterministic order.
344 > var sortedUpdates []*Update
345 > for _, upd := range r.updates {
346 sortedUpdates = append(sortedUpdates, upd)
347 }
348 > slices.SortStableFunc(sortedUpdates, func(u1, u2 *Update) int { return u1.admittedTime.Compare(u2.admittedTime) }) registry.go
349
350 > for _, upd := range sortedUpdates { registry.go
351 outgoingMessage := upd.Send(includeAlreadySent, sequencingEventID)
352 if outgoingMessage != nil {
355 }
356
357 > return outgoingMessages registry.go
358 }
359
360 > func (r *registry) Clear() { registry.go
361 > r.Abort(AbortReasonRegistryCleared)
362 >
363 > r.updates = nil
364 > r.completedCount = 0
365 > }
366
367 func (r *registry) Len() int {
490 }
491
492 > func (r *registry) FailoverVersion() int64 { registry.go
493 > return r.failoverVersion
494 > }
495
496 > func (r *registry) SuggestContinueAsNew() bool { registry.go
497 > suggestContinueAsNewThreshold := r.maxTotalSuggestContinueAsNew()
498 > if suggestContinueAsNewThreshold == 0 {
499 // suggestion is disabled
500 return false
501 }
502 > if r.inFlightCount()+r.completedCount >= suggestContinueAsNewThreshold { registry.go
503 return true
504 }
505 > return false registry.go
506 }
507
508 > func (r *registry) inFlightCount() int { registry.go
509 > return len(r.updates)
510 > }
go.temporal.io/server/common/persistence/visibility/visibility_manager_impl.go 85 covered LOC · 17 ranges

Open complete file

54 searchAttributesMapperProvider searchattribute.MapperProvider,
55 chasmRegistry *chasm.Registry,
56 > ) *visibilityManagerImpl { visibility_manager_impl.go
57 > return &visibilityManagerImpl{
58 > store: store,
59 > logger: logger,
60 > searchAttributesMapperProvider: searchAttributesMapperProvider,
61 > chasmRegistry: chasmRegistry,
62 > }
63 > }
64
65 > func (p *visibilityManagerImpl) Close() { visibility_manager_impl.go
66 > p.store.Close()
67 > }
68
69 func (p *visibilityManagerImpl) GetReadStoreName(_ namespace.Name) string {
71 }
72
73 > func (p *visibilityManagerImpl) GetStoreNames() []string { visibility_manager_impl.go
74 > return []string{p.store.GetName()}
75 > }
76
77 func (p *visibilityManagerImpl) HasStoreName(stName string) bool {
79 }
80
81 > func (p *visibilityManagerImpl) GetIndexName() string { visibility_manager_impl.go
82 > return p.store.GetIndexName()
83 > }
84
85 func (p *visibilityManagerImpl) ValidateCustomSearchAttributes(
92 ctx context.Context,
93 request *manager.RecordWorkflowExecutionStartedRequest,
95 > requestBase, err := p.newInternalVisibilityRequestBase(request.VisibilityRequestBase)
96 > if err != nil {
97 return err
98 }
99 > req := &store.InternalRecordWorkflowExecutionStartedRequest{ visibility_manager_impl.go
100 > InternalVisibilityRequestBase: requestBase,
101 > }
102 > return p.store.RecordWorkflowExecutionStarted(ctx, req)
103 }
104
106 ctx context.Context,
107 request *manager.RecordWorkflowExecutionClosedRequest,
108 > ) error { visibility_manager_impl.go
109 > requestBase, err := p.newInternalVisibilityRequestBase(request.VisibilityRequestBase)
110 > if err != nil {
111 return err
112 }
113 > req := &store.InternalRecordWorkflowExecutionClosedRequest{ visibility_manager_impl.go
114 > InternalVisibilityRequestBase: requestBase,
115 > CloseTime: request.CloseTime,
116 > HistoryLength: request.HistoryLength,
117 > HistorySizeBytes: request.HistorySizeBytes,
118 > ExecutionDuration: request.ExecutionDuration,
119 > StateTransitionCount: request.StateTransitionCount,
120 > }
121 > return p.store.RecordWorkflowExecutionClosed(ctx, req)
122 }
123
394 func (p *visibilityManagerImpl) newInternalVisibilityRequestBase(
395 request *manager.VisibilityRequestBase,
396 > ) (*store.InternalVisibilityRequestBase, error) { visibility_manager_impl.go
397 > if request == nil {
398 return nil, nil
399 }
400 > memoBlob, err := serializeMemo(request.Memo) visibility_manager_impl.go
401 > if err != nil {
402 return nil, err
403 }
404
405 > var searchAttrs *commonpb.SearchAttributes visibility_manager_impl.go
406 > if len(request.SearchAttributes.GetIndexedFields()) > 0 {
407 > // Remove any system search attribute from the map. visibility_manager_impl.go
408 > // This is necessary because the validation can supress errors when trying
409 > // to set a value on a system search attribute.
410 > searchAttrs = &commonpb.SearchAttributes{
411 > IndexedFields: make(map[string]*commonpb.Payload),
412 > }
413 > for key, value := range request.SearchAttributes.IndexedFields {
414 > if !sadefs.IsSystem(key) {
415 > searchAttrs.IndexedFields[key] = value
416 > }
417 }
418 }
419
421 > parentWorkflowID *string
422 > parentRunID *string
423 > )
424 > if request.ParentExecution != nil {
425 parentWorkflowID = &request.ParentExecution.WorkflowId
426 parentRunID = &request.ParentExecution.RunId
427 }
428
429 > return &store.InternalVisibilityRequestBase{ visibility_manager_impl.go
430 > NamespaceID: request.NamespaceID.String(),
431 > WorkflowID: request.Execution.GetWorkflowId(),
432 > RunID: request.Execution.GetRunId(),
433 > WorkflowTypeName: request.WorkflowTypeName,
434 > StartTime: request.StartTime,
435 > Status: request.Status,
436 > ExecutionTime: request.ExecutionTime,
437 > TaskID: request.TaskID,
438 > ShardID: request.ShardID,
439 > TaskQueue: request.TaskQueue,
440 > Memo: memoBlob,
441 > SearchAttributes: searchAttrs,
442 > ParentWorkflowID: parentWorkflowID,
443 > ParentRunID: parentRunID,
444 > RootWorkflowID: request.RootExecution.GetWorkflowId(),
445 > RootRunID: request.RootExecution.GetRunId(),
446 > }, nil
447 }
448
556 }
557
558 > func serializeMemo(memo *commonpb.Memo) (*commonpb.DataBlob, error) { visibility_manager_impl.go
559 > if memo == nil {
560 > memo = &commonpb.Memo{}
561 > }
562
563 > data, err := proto.Marshal(memo) visibility_manager_impl.go
564 > if err != nil {
565 return nil, serviceerror.NewInternalf("Unable to serialize memo to data blob: %v", err)
566 }
567
568 > return &commonpb.DataBlob{ visibility_manager_impl.go
569 > Data: data,
570 > EncodingType: MemoEncoding,
571 > }, nil
572 }
573
go.temporal.io/server/service/history/historybuilder/history_builder.go 85 covered LOC · 9 ranges

Open complete file

66 metricsHandler metrics.Handler,
67 maxEventBatchSizeInBytes dynamicconfig.IntPropertyFn,
68 > ) *HistoryBuilder { history_builder.go
69 > return &HistoryBuilder{
70 > EventStore: EventStore{
71 > state: HistoryBuilderStateMutable,
72 > timeSource: timeSource,
73 > taskIDGenerator: taskIDGenerator,
74 >
75 > version: version,
76 > nextEventID: nextEventID,
77 >
78 > workflowFinished: false,
79 >
80 > dbBufferBatch: dbBufferBatch,
81 > dbClearBuffer: false,
82 > memEventsBatches: nil,
83 > memLatestBatch: nil,
84 > memBufferBatch: nil,
85 > scheduledIDToStartedID: make(map[int64]int64),
86 > requestIDToEventID: make(map[string]int64),
87 >
88 > maxEventBatchSizeInBytes: maxEventBatchSizeInBytes,
89 >
90 > metricsHandler: metricsHandler,
91 > },
92 > EventFactory: EventFactory{timeSource: timeSource, version: version},
93 > }
94 > }
95
96 func (b *HistoryBuilder) SetTimeSource(timeSource clock.TimeSource) {
153 }
154
155 > func (b *HistoryBuilder) IsDirty() bool { history_builder.go
156 > return b.EventStore.IsDirty()
157 > }
158
159 // AddWorkflowExecutionStartedEvent
168 firstInChainRunID string,
169 originalRunID string,
170 > ) *historypb.HistoryEvent { history_builder.go
171 > event := b.CreateWorkflowExecutionStartedEvent(
172 > startTime,
173 > request,
174 > resetPoints,
175 > prevRunID,
176 > firstInChainRunID,
177 > originalRunID,
178 > )
179 > if request.StartRequest.GetUserMetadata() != nil {
180 event.UserMetadata = request.StartRequest.GetUserMetadata()
181 }
182 > if len(request.StartRequest.GetLinks()) > 0 { history_builder.go
183 event.Links = request.StartRequest.GetLinks()
184 }
185 > event, _ = b.add(event) history_builder.go
186 > return event
187 }
188
192 attempt int32,
193 scheduleTime time.Time,
194 > ) *historypb.HistoryEvent { history_builder.go
195 > event := b.CreateWorkflowTaskScheduledEvent(taskQueue, startToCloseTimeout, attempt, scheduleTime)
196 > event, _ = b.add(event)
197 > return event
198 > }
199
200 func (b *HistoryBuilder) AddWorkflowTaskStartedEvent(
209 suggestContinueAsNewReasons []enumspb.SuggestContinueAsNewReason,
210 targetWorkerDeploymentVersionChanged bool,
211 > ) *historypb.HistoryEvent { history_builder.go
212 > event := b.CreateWorkflowTaskStartedEvent(
213 > scheduledEventID,
214 > requestID,
215 > identity,
216 > startTime,
217 > suggestContinueAsNew,
218 > historySizeBytes,
219 > versioningStamp,
220 > buildIdRedirectCounter,
221 > suggestContinueAsNewReasons,
222 > targetWorkerDeploymentVersionChanged,
223 > )
224 > event, _ = b.add(event)
225 > return event
226 > }
227
228 func (b *HistoryBuilder) AddWorkflowTaskCompletedEvent(
237 deployment *deploymentpb.Deployment,
238 behavior enumspb.VersioningBehavior,
239 > ) *historypb.HistoryEvent { history_builder.go
240 > event := b.CreateWorkflowTaskCompletedEvent(
241 > scheduledEventID,
242 > startedEventID,
243 > identity,
244 > checksum,
245 > workerVersionStamp,
246 > sdkMetadata,
247 > meteringMetadata,
248 > deploymentName,
249 > deployment,
250 > behavior,
251 > )
252 > event, _ = b.add(event)
253 > return event
254 > }
255
256 func (b *HistoryBuilder) AddWorkflowTaskTimedOutEvent(
426 command *commandpb.CompleteWorkflowExecutionCommandAttributes,
427 newExecutionRunID string,
428 > ) (*historypb.HistoryEvent, int64) { history_builder.go
429 > event := b.CreateCompletedWorkflowEvent(workflowTaskCompletedEventID, command, newExecutionRunID)
430 >
431 > return b.add(event)
432 > }
433
434 func (b *HistoryBuilder) AddFailWorkflowEvent(
go.temporal.io/server/service/matching/pri_task_writer.go 85 covered LOC · 20 ranges

Open complete file

50 func newPriTaskWriter(
51 backlogMgr *priBacklogManagerImpl,
52 > ) *priTaskWriter { pri_task_writer.go
53 > return &priTaskWriter{
54 > backlogMgr: backlogMgr,
55 > config: backlogMgr.config,
56 > db: backlogMgr.db,
57 > logger: backlogMgr.logger,
58 > appendCh: make(chan *writeTaskRequest, backlogMgr.config.OutstandingTaskAppendsThreshold()),
59 > taskIDBlock: noTaskIDs,
60 > }
61 > }
62
63 // Start priTaskWriter background goroutine.
64 > func (w *priTaskWriter) Start() { pri_task_writer.go
65 > go w.taskWriterLoop()
66 > }
67
68 func (w *priTaskWriter) appendTask(
69 subqueue subqueueIndex,
70 taskInfo *persistencespb.TaskInfo,
71 > ) error { pri_task_writer.go
72 > select {
73 case <-w.backlogMgr.tqCtx.Done():
74 return errShutdown
75 > default: pri_task_writer.go
76 // noop
77 }
78
79 > startTime := time.Now().UTC() pri_task_writer.go
80 > ch := make(chan error, 1)
81 > req := &writeTaskRequest{
82 > taskInfo: taskInfo,
83 > responseCh: ch,
84 > subqueue: subqueue,
85 > }
86 >
87 > select {
88 > case w.appendCh <- req:
89 > select {
90 > case err := <-ch:
91 > metrics.TaskWriteLatencyPerTaskQueue.With(w.backlogMgr.metricsHandler).Record(time.Since(startTime))
92 > return err
93 case <-w.backlogMgr.tqCtx.Done():
94 // if we are shutting down, this request will never make
106 }
107
108 > func (w *priTaskWriter) assignTaskIDs(reqs []*writeTaskRequest) error { pri_task_writer.go
109 > for i := range reqs {
110 > if w.taskIDBlock.start > w.taskIDBlock.end {
111 // we ran out of current allocation block
112 newBlock, err := w.allocTaskIDBlock(w.taskIDBlock.end)
116 w.taskIDBlock = newBlock
117 }
118 > reqs[i].id = w.taskIDBlock.start pri_task_writer.go
119 > w.taskIDBlock.start++
120 }
121 > return nil pri_task_writer.go
122 }
123
124 > func (w *priTaskWriter) appendTasks(reqs []*writeTaskRequest) error { pri_task_writer.go
125 > resp, err := w.db.CreateTasks(w.backlogMgr.tqCtx, reqs)
126 > if err != nil {
127 w.backlogMgr.signalIfFatal(err)
128 w.logger.Error("Persistent store operation failure",
134 }
135
136 > w.backlogMgr.signalReaders(resp) pri_task_writer.go
137 > return nil
138 }
139
140 > func (w *priTaskWriter) initState() error { pri_task_writer.go
141 > state, err := w.renewLeaseWithRetry(foreverRetryPolicy, common.IsPersistenceTransientError)
142 > if err != nil {
143 w.backlogMgr.initState(taskQueueState{}, err)
144 return err
145 }
146 > w.taskIDBlock = rangeIDToTaskIDBlock(state.rangeID, w.config.RangeSize) pri_task_writer.go
147 > w.currentTaskIDBlock = w.taskIDBlock
148 > w.backlogMgr.initState(state, nil)
149 > return nil
150 }
151
152 > func (w *priTaskWriter) taskWriterLoop() { pri_task_writer.go
153 > if w.initState() != nil {
154 return
155 }
156
157 > var reqs []*writeTaskRequest pri_task_writer.go
158 > for {
159 > atomic.StoreInt64(&w.currentTaskIDBlock.start, w.taskIDBlock.start)
160 > atomic.StoreInt64(&w.currentTaskIDBlock.end, w.taskIDBlock.end)
161 >
162 > select {
163 > case request := <-w.appendCh: pri_task_writer.go
164 > // read a batch of requests from the channel
165 > reqs = append(reqs[:0], request)
166 > reqs = w.getWriteBatch(reqs)
167 >
168 > err := w.assignTaskIDs(reqs)
169 > if err == nil {
170 > err = w.appendTasks(reqs)
171 > }
172 > for _, req := range reqs {
173 > req.responseCh <- err
174 > }
175
176 > case <-w.backlogMgr.tqCtx.Done(): pri_task_writer.go
177 > return
178 }
179 }
180 }
181
182 > func (w *priTaskWriter) getWriteBatch(reqs []*writeTaskRequest) []*writeTaskRequest { pri_task_writer.go
183 > for range w.config.MaxTaskBatchSize() - 1 {
184 > select {
185 case req := <-w.appendCh:
186 reqs = append(reqs, req)
187 > default: // channel is empty, don't block pri_task_writer.go
188 > return reqs
189 }
190 }
195 retryPolicy backoff.RetryPolicy,
196 retryErrors backoff.IsRetryable,
197 > ) (taskQueueState, error) { pri_task_writer.go
198 > var newState taskQueueState
199 > op := func(ctx context.Context) (err error) {
200 > newState, err = w.db.RenewLease(ctx)
201 > return
202 > }
203 > metrics.LeaseRequestPerTaskQueueCounter.With(w.backlogMgr.metricsHandler).Record(1)
204 > err := backoff.ThrottleRetryContext(w.backlogMgr.tqCtx, op, retryPolicy, retryErrors)
205 > if err != nil {
206 metrics.LeaseFailurePerTaskQueueCounter.With(w.backlogMgr.metricsHandler).Record(1)
207 return newState, err
208 }
209 > return newState, nil pri_task_writer.go
210 }
211
go.temporal.io/server/common/metrics/config.go 84 covered LOC · 27 ranges

Open complete file

288 // Current priority order is:
289 // statsd > prometheus
290 > func NewScope(logger log.Logger, c *Config) tally.Scope { config.go
291 > if c.Statsd != nil {
292 return newStatsdScope(logger, c)
293 }
294 > if c.Prometheus != nil { config.go
295 > sanitizeOptions, err := convertSanitizeOptionsToTally(c.Prometheus) config.go
296 > if err != nil {
297 logger.Fatal("invalid sanitize options input on prometheus config", tag.Error(err))
298 return nil
299 }
300
301 > if c.Prometheus.LoggerRPS > 0 { config.go
302 logger = log.NewThrottledLogger(logger, func() float64 { return c.Prometheus.LoggerRPS })
303 }
304
305 > return newPrometheusScope( config.go
306 > logger,
307 > convertPrometheusConfigToTally(&c.ClientConfig, c.Prometheus),
308 > sanitizeOptions,
309 > &c.ClientConfig,
310 > )
311 }
312 return tally.NoopScope
313 }
314
315 > func convertSanitizeOptionsToTally(config *PrometheusConfig) (tally.SanitizeOptions, error) { config.go
316 > if config.SanitizeOptions == nil {
317 > return defaultTallySanitizeOptions, nil config.go
318 > }
319
320 return config.SanitizeOptions.toTally()
324 clientConfig *ClientConfig,
325 config *PrometheusConfig,
326 > ) *prometheus.Configuration { config.go
327 > defaultObjectives := make([]prometheus.SummaryObjective, len(config.DefaultSummaryObjectives))
328 > for i, item := range config.DefaultSummaryObjectives {
329 defaultObjectives[i].AllowedError = item.AllowedError
330 defaultObjectives[i].Percentile = item.Percentile
331 }
332
333 > return &prometheus.Configuration{ config.go
334 > HandlerPath: config.HandlerPath,
335 > ListenNetwork: config.ListenNetwork,
336 > ListenAddress: config.ListenAddress,
337 > TimerType: "histogram",
338 > DefaultHistogramBuckets: buildTallyTimerHistogramBuckets(clientConfig, config),
339 > DefaultSummaryObjectives: defaultObjectives,
340 > OnError: config.OnError,
341 > }
342 }
343
345 clientConfig *ClientConfig,
346 config *PrometheusConfig,
347 > ) []prometheus.HistogramObjective { config.go
348 > if len(config.DefaultHistogramBuckets) > 0 {
349 result := make([]prometheus.HistogramObjective, len(config.DefaultHistogramBuckets))
350 for i, item := range config.DefaultHistogramBuckets {
354 }
355
356 > if len(config.DefaultHistogramBoundaries) > 0 { config.go
357 result := make([]prometheus.HistogramObjective, 0, len(config.DefaultHistogramBoundaries))
358 for _, value := range config.DefaultHistogramBoundaries {
364 }
365
366 > boundaries := clientConfig.PerUnitHistogramBoundaries[Milliseconds] config.go
367 > result := make([]prometheus.HistogramObjective, 0, len(boundaries))
368 > for _, boundary := range boundaries {
369 > result = append(result, prometheus.HistogramObjective{ config.go
370 > Upper: boundary / float64(time.Second/time.Millisecond), // convert milliseconds to seconds
371 > })
372 > }
373 > return result config.go
374 }
375
376 > func setDefaultPerUnitHistogramBoundaries(clientConfig *ClientConfig) { config.go
377 > buckets := maps.Clone(defaultPerUnitHistogramBoundaries)
378 >
379 > // In config, when overwrite default buckets, we use [dimensionless / miliseconds / bytes] as keys.
380 > // But in code, we use [1 / ms / By] as key (to align with otel unit definition). So we do conversion here.
381 > if bucket, ok := clientConfig.PerUnitHistogramBoundaries[UnitNameDimensionless]; ok {
382 buckets[Dimensionless] = bucket
383 }
384 > if bucket, ok := clientConfig.PerUnitHistogramBoundaries[UnitNameMilliseconds]; ok { config.go
385 buckets[Milliseconds] = bucket
386 }
387 > if bucket, ok := clientConfig.PerUnitHistogramBoundaries[UnitNameBytes]; ok { config.go
388 buckets[Bytes] = bucket
389 }
390
391 > bucketInSeconds := make([]float64, len(buckets[Milliseconds])) config.go
392 > for idx, boundary := range buckets[Milliseconds] {
393 > bucketInSeconds[idx] = boundary / float64(time.Second/time.Millisecond)
394 > }
395 > buckets[Seconds] = bucketInSeconds
396 >
397 > clientConfig.PerUnitHistogramBoundaries = buckets
398 }
399
436 sanitizeOptions tally.SanitizeOptions,
437 clientConfig *ClientConfig,
438 > ) tally.Scope { config.go
439 > reporter, err := config.NewReporter(
440 > prometheus.ConfigurationOptions{
441 > Registry: prom.NewRegistry(),
442 > OnError: func(err error) {
443 logger.Warn("error in prometheus reporter", tag.Error(err))
444 },
445 },
446 )
447 > if err != nil { config.go
448 logger.Fatal("error creating prometheus reporter", tag.Error(err))
449 }
450 > scopeOpts := tally.ScopeOptions{ config.go
451 > Tags: clientConfig.Tags,
452 > CachedReporter: reporter,
453 > Separator: prometheus.DefaultSeparator,
454 > SanitizeOptions: &sanitizeOptions,
455 > Prefix: clientConfig.Prefix,
456 > }
457 > scope, _ := tally.NewRootScope(scopeOpts, time.Second)
458 > return scope
459 }
460
461 // MetricsHandlerFromConfig is used at startup to construct a MetricsHandler
462 > func MetricsHandlerFromConfig(logger log.Logger, c *Config) (Handler, error) { config.go
463 > if c == nil {
464 return NoopMetricsHandler, nil
465 }
466
467 > setDefaultPerUnitHistogramBoundaries(&c.ClientConfig) config.go
468 >
469 > fatalOnListenerError := true
470 > if c.Statsd != nil && c.Statsd.Framework == FrameworkOpentelemetry {
471 // create opentelemetry provider with just statsd
472 otelProvider, err := NewOpenTelemetryProviderWithStatsd(logger, c.Statsd, &c.ClientConfig)
477 }
478
479 > if c.Prometheus != nil && c.Prometheus.Framework == FrameworkOpentelemetry { config.go
480 // create opentelemetry provider with just prometheus
481 otelProvider, err := NewOpenTelemetryProviderWithPrometheus(logger, c.Prometheus, &c.ClientConfig, fatalOnListenerError)
487
488 // fallback to tally if no framework is specified
489 > return NewTallyMetricsHandler( config.go
490 > c.ClientConfig,
491 > NewScope(logger, c),
492 > ), nil
493 }
494
495 > func configExcludeTags(cfg ClientConfig) map[string]map[string]struct{} { config.go
496 > tagsToFilter := make(map[string]map[string]struct{})
497 > for key, val := range cfg.ExcludeTags {
498 exclusions := make(map[string]struct{})
499 for _, val := range val {
502 tagsToFilter[key] = exclusions
503 }
504 > return tagsToFilter config.go
505 }
506
go.temporal.io/server/common/persistence/sql/metadata.go 84 covered LOC · 30 ranges

Open complete file

25 logger log.Logger,
26 serializer serialization.Serializer,
27 > ) (persistence.MetadataStore, error) { metadata.go
28 > return &sqlMetadataManagerV2{
29 > SqlStore: NewSQLStore(db, logger, serializer),
30 > activeClusterName: currentClusterName,
31 > }, nil
32 > }
33
34 func (m *sqlMetadataManagerV2) CreateNamespace(
35 ctx context.Context,
36 request *persistence.InternalCreateNamespaceRequest,
37 > ) (*persistence.CreateNamespaceResponse, error) { metadata.go
38 > idBytes, err := primitives.ParseUUID(request.ID)
39 > if err != nil {
40 return nil, err
41 }
42
43 > var resp *persistence.CreateNamespaceResponse metadata.go
44 > err = m.txExecute(ctx, "CreateNamespace", func(tx sqlplugin.Tx) error {
45 > metadata, err := lockMetadata(ctx, tx)
46 > if err != nil {
47 return err
48 }
49 > if _, err := tx.InsertIntoNamespace(ctx, &sqlplugin.NamespaceRow{ metadata.go
50 > Name: request.Name,
51 > ID: idBytes,
52 > Data: request.Namespace.Data,
53 > DataEncoding: request.Namespace.EncodingType.String(),
54 > IsGlobal: request.IsGlobal,
55 > NotificationVersion: metadata.NotificationVersion,
56 > }); err != nil {
57 if m.DB.IsDupEntryError(err) {
58 return serviceerror.NewNamespaceAlreadyExistsf("name: %v", request.Name)
60 return err
61 }
62 > if err := updateMetadata(ctx, metadata.go
63 > tx,
64 > metadata.NotificationVersion,
65 > ); err != nil {
66 return err
67 }
68 > resp = &persistence.CreateNamespaceResponse{ID: request.ID} metadata.go
69 > return nil
70 })
71 > return resp, err metadata.go
72 }
73
75 ctx context.Context,
76 request *persistence.GetNamespaceRequest,
77 > ) (*persistence.InternalGetNamespaceResponse, error) { metadata.go
78 > idBytes, err := primitives.ParseUUID(request.ID)
79 > if err != nil {
80 return nil, err
81 }
82 > filter := sqlplugin.NamespaceFilter{} metadata.go
83 > switch {
84 case request.Name != "" && request.ID != "":
85 return nil, serviceerror.NewInvalidArgument("GetNamespace operation failed. Both ID and Name specified in request.")
86 > case request.Name != "": metadata.go
87 > filter.Name = &request.Name
88 > case len(request.ID) != 0: metadata.go
89 > filter.ID = &idBytes
90 default:
91 return nil, serviceerror.NewInvalidArgument("GetNamespace operation failed. Both ID and Name are empty.")
92 }
93
94 > rows, err := m.DB.SelectFromNamespace(ctx, filter) metadata.go
95 > if err != nil {
96 > switch err { metadata.go
97 > case sql.ErrNoRows:
98 > // We did not return in the above for-loop because there were no rows.
99 > identity := request.Name
100 > if len(request.ID) > 0 {
101 identity = request.ID
102 }
103
104 > return nil, serviceerror.NewNamespaceNotFound(identity) metadata.go
105 default:
106 return nil, serviceerror.NewUnavailablef("GetNamespace operation failed. Error %v", err)
108 }
109
110 > response, err := m.namespaceRowToGetNamespaceResponse(&rows[0]) metadata.go
111 > if err != nil {
112 return nil, err
113 }
114
115 > return response, nil metadata.go
116 }
117
118 > func (m *sqlMetadataManagerV2) namespaceRowToGetNamespaceResponse(row *sqlplugin.NamespaceRow) (*persistence.InternalGetNamespaceResponse, error) { metadata.go
119 > return &persistence.InternalGetNamespaceResponse{
120 > Namespace: persistence.NewDataBlob(row.Data, row.DataEncoding),
121 > IsGlobal: row.IsGlobal,
122 > NotificationVersion: row.NotificationVersion,
123 > }, nil
124 > }
125
126 func (m *sqlMetadataManagerV2) UpdateNamespace(
224 ctx context.Context,
225 request *persistence.InternalListNamespacesRequest,
226 > ) (*persistence.InternalListNamespacesResponse, error) { metadata.go
227 > var pageToken *primitives.UUID
228 > if request.NextPageToken != nil {
229 token := primitives.UUID(request.NextPageToken)
230 pageToken = &token
231 }
232 > rows, err := m.DB.SelectFromNamespace(ctx, sqlplugin.NamespaceFilter{ metadata.go
233 > GreaterThanID: pageToken,
234 > PageSize: &request.PageSize,
235 > })
236 > if err != nil {
237 if err == sql.ErrNoRows {
238 return &persistence.InternalListNamespacesResponse{}, nil
241 }
242
243 > var namespaces []*persistence.InternalGetNamespaceResponse metadata.go
244 > for _, row := range rows {
245 > resp, err := m.namespaceRowToGetNamespaceResponse(&row) metadata.go
246 > if err != nil {
247 return nil, err
248 }
249 > namespaces = append(namespaces, resp) metadata.go
250 }
251
252 > resp := &persistence.InternalListNamespacesResponse{Namespaces: namespaces} metadata.go
253 > if len(rows) >= request.PageSize {
254 resp.NextPageToken = rows[len(rows)-1].ID
255 }
256
257 > return resp, nil metadata.go
258 }
259
262 tx sqlplugin.Tx,
263 oldNotificationVersion int64,
264 > ) error { metadata.go
265 > result, err := tx.UpdateNamespaceMetadata(ctx, &sqlplugin.NamespaceMetadataRow{
266 > NotificationVersion: oldNotificationVersion,
267 > })
268 > if err != nil {
269 return serviceerror.NewUnavailablef("Failed to update namespace metadata. Error: %v", err)
270 }
271
272 > rowsAffected, err := result.RowsAffected() metadata.go
273 > if err != nil {
274 return serviceerror.NewUnavailablef("Could not verify whether namespace metadata update occurred. Error: %v", err)
275 > } else if rowsAffected != 1 { metadata.go
276 return serviceerror.NewUnavailablef("Failed to update namespace metadata. <>1 rows affected. Error: %v", err)
277 }
278
279 > return nil metadata.go
280 }
281
283 ctx context.Context,
284 tx sqlplugin.Tx,
285 > ) (*sqlplugin.NamespaceMetadataRow, error) { metadata.go
286 > row, err := tx.LockNamespaceMetadata(ctx)
287 > if err != nil {
288 return nil, serviceerror.NewUnavailablef("Failed to lock namespace metadata. Error: %v", err)
289 }
290 > return row, nil metadata.go
291 }
go.temporal.io/server/service/history/queues/queue_immediate.go 84 covered LOC · 18 ranges

Open complete file

41 factory ExecutableFactory,
42 taskPostProcessor taskPostProcessorFn,
43 > ) *immediateQueue { queue_immediate.go
44 > paginationFnProvider := func(r Range) collection.PaginationFn[tasks.Task] {
45 > return func(paginationToken []byte) ([]tasks.Task, []byte, error) {
46 > ctx, cancel := newQueueIOContext()
47 > defer cancel()
48 >
49 > request := &persistence.GetHistoryTasksRequest{
50 > ShardID: shard.GetShardID(),
51 > TaskCategory: category,
52 > InclusiveMinTaskKey: r.InclusiveMin,
53 > ExclusiveMaxTaskKey: r.ExclusiveMax,
54 > BatchSize: options.BatchSize(),
55 > NextPageToken: paginationToken,
56 > }
57 >
58 > resp, err := shard.GetHistoryTasks(ctx, request)
59 > if err != nil {
60 > return nil, nil, err queue_immediate.go
61 > }
62
63 > if taskPostProcessor != nil { queue_immediate.go
64 > taskPostProcessor(resp.Tasks)
65 > }
66
67 > return resp.Tasks, resp.NextPageToken, nil queue_immediate.go
68 }
69 }
70
71 > return &immediateQueue{ queue_immediate.go
72 > queueBase: newQueueBase(
73 > shard,
74 > category,
75 > paginationFnProvider,
76 > scheduler,
77 > rescheduler,
78 > factory,
79 > options,
80 > hostRateLimiter,
81 > NoopReaderCompletionFn,
82 > grouper,
83 > logger,
84 > metricsHandler,
85 > ),
86 >
87 > notifyCh: make(chan struct{}, 1),
88 > }
89 }
90
91 > func (p *immediateQueue) Start() { queue_immediate.go
92 > if !atomic.CompareAndSwapInt32(&p.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
93 return
94 }
95
96 > p.logger.Info("", tag.LifeCycleStarting) queue_immediate.go
97 > defer p.logger.Info("", tag.LifeCycleStarted)
98 >
99 > p.queueBase.Start()
100 >
101 > p.shutdownWG.Add(1)
102 > go p.processEventLoop()
103 >
104 > p.notify()
105 }
106
107 > func (p *immediateQueue) Stop() { queue_immediate.go
108 > if !atomic.CompareAndSwapInt32(&p.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
109 return
110 }
111
112 > p.logger.Info("", tag.LifeCycleStopping) queue_immediate.go
113 > defer p.logger.Info("", tag.LifeCycleStopped)
114 >
115 > close(p.shutdownCh)
116 >
117 > if success := common.AwaitWaitGroup(&p.shutdownWG, time.Minute); !success {
118 p.logger.Warn("", tag.LifeCycleStopTimedout)
119 }
120
121 > p.queueBase.Stop() queue_immediate.go
122 }
123
124 > func (p *immediateQueue) NotifyNewTasks(tasks []tasks.Task) { queue_immediate.go
125 > if len(tasks) == 0 {
126 return
127 }
128
129 > p.notify() queue_immediate.go
130 }
131
132 > func (p *immediateQueue) processEventLoop() { queue_immediate.go
133 > defer p.shutdownWG.Done()
134 >
135 > pollTimer := time.NewTimer(backoff.Jitter(
136 > p.options.MaxPollInterval(),
137 > p.options.MaxPollIntervalJitterCoefficient(),
138 > ))
139 > defer pollTimer.Stop()
140 >
141 > for {
142 > select {
143 case <-p.shutdownCh:
144 return
145 > default: queue_immediate.go
146 }
147
148 > select { queue_immediate.go
149 > case <-p.shutdownCh: queue_immediate.go
150 > return
151 > case <-p.notifyCh: queue_immediate.go
152 > p.processNewRange()
153 case <-pollTimer.C:
154 p.processPollTimer(pollTimer)
169 }
170
171 > func (p *immediateQueue) notify() { queue_immediate.go
172 > select {
173 > case p.notifyCh <- struct{}{}:
174 default:
175 }
go.temporal.io/server/api/persistence/v1/predicates.pb.go 83 covered LOC · 23 ranges

Open complete file

57 func (*Predicate) ProtoMessage() {}
58
59 > func (x *Predicate) ProtoReflect() protoreflect.Message { predicates.pb.go
60 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[0]
61 > if x != nil {
62 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
63 > if ms.LoadMessageInfo() == nil {
64 > ms.StoreMessageInfo(mi)
65 > }
66 > return ms
67 }
68 > return mi.MessageOf(x) predicates.pb.go
69 }
70
261 func (*UniversalPredicateAttributes) ProtoMessage() {}
262
263 > func (x *UniversalPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
264 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[1]
265 > if x != nil {
266 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
267 if ms.LoadMessageInfo() == nil {
297 func (*EmptyPredicateAttributes) ProtoMessage() {}
298
299 > func (x *EmptyPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
300 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[2]
301 > if x != nil {
302 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
303 if ms.LoadMessageInfo() == nil {
334 func (*AndPredicateAttributes) ProtoMessage() {}
335
336 > func (x *AndPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
337 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[3]
338 > if x != nil {
339 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
340 if ms.LoadMessageInfo() == nil {
378 func (*OrPredicateAttributes) ProtoMessage() {}
379
380 > func (x *OrPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
381 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[4]
382 > if x != nil {
383 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
384 if ms.LoadMessageInfo() == nil {
422 func (*NotPredicateAttributes) ProtoMessage() {}
423
424 > func (x *NotPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
425 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[5]
426 > if x != nil {
427 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
428 if ms.LoadMessageInfo() == nil {
466 func (*NamespaceIdPredicateAttributes) ProtoMessage() {}
467
468 > func (x *NamespaceIdPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
469 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[6]
470 > if x != nil {
471 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
472 if ms.LoadMessageInfo() == nil {
510 func (*TaskTypePredicateAttributes) ProtoMessage() {}
511
512 > func (x *TaskTypePredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
513 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[7]
514 > if x != nil {
515 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
516 if ms.LoadMessageInfo() == nil {
554 func (*DestinationPredicateAttributes) ProtoMessage() {}
555
556 > func (x *DestinationPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
557 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[8]
558 > if x != nil {
559 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
560 if ms.LoadMessageInfo() == nil {
598 func (*OutboundTaskGroupPredicateAttributes) ProtoMessage() {}
599
600 > func (x *OutboundTaskGroupPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
601 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[9]
602 > if x != nil {
603 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
604 if ms.LoadMessageInfo() == nil {
642 func (*OutboundTaskPredicateAttributes) ProtoMessage() {}
643
644 > func (x *OutboundTaskPredicateAttributes) ProtoReflect() protoreflect.Message { predicates.pb.go
645 > mi := &file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[10]
646 > if x != nil {
647 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
648 if ms.LoadMessageInfo() == nil {
828 }
829
830 > func init() { file_temporal_server_api_persistence_v1_predicates_proto_init() } predicates.pb.go
831 > func file_temporal_server_api_persistence_v1_predicates_proto_init() {
832 > if File_temporal_server_api_persistence_v1_predicates_proto != nil {
833 > return
834 > }
835 > file_temporal_server_api_persistence_v1_predicates_proto_msgTypes[0].OneofWrappers = []any{
836 > (*Predicate_UniversalPredicateAttributes)(nil),
837 > (*Predicate_EmptyPredicateAttributes)(nil),
838 > (*Predicate_AndPredicateAttributes)(nil),
839 > (*Predicate_OrPredicateAttributes)(nil),
840 > (*Predicate_NotPredicateAttributes)(nil),
841 > (*Predicate_NamespaceIdPredicateAttributes)(nil),
842 > (*Predicate_TaskTypePredicateAttributes)(nil),
843 > (*Predicate_DestinationPredicateAttributes)(nil),
844 > (*Predicate_OutboundTaskGroupPredicateAttributes)(nil),
845 > (*Predicate_OutboundTaskPredicateAttributes)(nil),
846 > }
847 > type x struct{}
848 > out := protoimpl.TypeBuilder{
849 > File: protoimpl.DescBuilder{
850 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
851 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_predicates_proto_rawDesc), len(file_temporal_server_api_persistence_v1_predicates_proto_rawDesc)),
852 > NumEnums: 0,
853 > NumMessages: 12,
854 > NumExtensions: 0,
855 > NumServices: 0,
856 > },
857 > GoTypes: file_temporal_server_api_persistence_v1_predicates_proto_goTypes,
858 > DependencyIndexes: file_temporal_server_api_persistence_v1_predicates_proto_depIdxs,
859 > MessageInfos: file_temporal_server_api_persistence_v1_predicates_proto_msgTypes,
860 > }.Build()
861 > File_temporal_server_api_persistence_v1_predicates_proto = out.File
862 > file_temporal_server_api_persistence_v1_predicates_proto_goTypes = nil
863 > file_temporal_server_api_persistence_v1_predicates_proto_depIdxs = nil
864 }
go.temporal.io/server/common/persistence/visibility/store/sql/visibility_store.go 82 covered LOC · 22 ranges

Open complete file

69 metricsHandler metrics.Handler,
70 serializer serialization.Serializer,
71 > ) (*VisibilityStore, error) { visibility_store.go
72 > refDbConn := persistencesql.NewRefCountedDBConn(sqlplugin.DbKindVisibility, &cfg, r, logger, metricsHandler)
73 > db, err := refDbConn.Get()
74 > if err != nil {
75 return nil, err
76 }
77 > return &VisibilityStore{ visibility_store.go
78 > sqlStore: persistencesql.NewSQLStore(db, logger, serializer),
79 > searchAttributesProvider: searchAttributesProvider,
80 > searchAttributesMapperProvider: searchAttributesMapperProvider,
81 > chasmRegistry: chasmRegistry,
82 > metricsHandler: metricsHandler,
83 > logger: logger,
84 >
85 > enableUnifiedQueryConverter: enableUnifiedQueryConverter,
86 > }, nil
87 }
88
89 > func (s *VisibilityStore) Close() { visibility_store.go
90 > s.sqlStore.Close()
91 > }
92
93 > func (s *VisibilityStore) GetName() string { visibility_store.go
94 > return s.sqlStore.GetName()
95 > }
96
97 func convertSQLError(message string, err error) error {
102 }
103
104 > func (s *VisibilityStore) GetIndexName() string { visibility_store.go
105 > return s.sqlStore.GetDbName()
106 > }
107
108 func (s *VisibilityStore) ValidateCustomSearchAttributes(
109 searchAttributes map[string]any,
110 > ) (map[string]any, error) { visibility_store.go
111 > return searchAttributes, nil
112 > }
113
114 func (s *VisibilityStore) RecordWorkflowExecutionStarted(
115 ctx context.Context,
116 request *store.InternalRecordWorkflowExecutionStartedRequest,
117 > ) error { visibility_store.go
118 > row, err := s.generateVisibilityRow(request.InternalVisibilityRequestBase)
119 > if err != nil {
120 return err
121 }
122
123 > _, err = s.sqlStore.DB.InsertIntoVisibility(ctx, row) visibility_store.go
124 > return err
125 }
126
128 ctx context.Context,
129 request *store.InternalRecordWorkflowExecutionClosedRequest,
130 > ) error { visibility_store.go
131 > row, err := s.generateVisibilityRow(request.InternalVisibilityRequestBase)
132 > if err != nil {
133 return err
134 }
135
136 > row.CloseTime = &request.CloseTime visibility_store.go
137 > row.HistoryLength = &request.HistoryLength
138 > row.HistorySizeBytes = &request.HistorySizeBytes
139 > row.ExecutionDuration = new(request.ExecutionDuration.Nanoseconds())
140 > row.StateTransitionCount = &request.StateTransitionCount
141 >
142 > result, err := s.sqlStore.DB.ReplaceIntoVisibility(ctx, row)
143 > if err != nil {
144 return err
145 }
146 > noRowsAffected, err := result.RowsAffected() visibility_store.go
147 > if err != nil {
148 return fmt.Errorf("RecordWorkflowExecutionClosed rowsAffected error: %v", err)
149 }
150 > if noRowsAffected > 2 { // either adds a new row or deletes old row and adds new row visibility_store.go
151 return fmt.Errorf(
152 "RecordWorkflowExecutionClosed unexpected numRows (%v) updated",
753 func (s *VisibilityStore) generateVisibilityRow(
754 request *store.InternalVisibilityRequestBase,
755 > ) (*sqlplugin.VisibilityRow, error) { visibility_store.go
756 > searchAttributes, err := s.prepareSearchAttributesForDb(request)
757 > if err != nil {
758 return nil, err
759 }
760
761 > return &sqlplugin.VisibilityRow{ visibility_store.go
762 > NamespaceID: request.NamespaceID,
763 > WorkflowID: request.WorkflowID,
764 > RunID: request.RunID,
765 > StartTime: request.StartTime,
766 > ExecutionTime: request.ExecutionTime,
767 > WorkflowTypeName: request.WorkflowTypeName,
768 > Status: int32(request.Status),
769 > Memo: request.Memo.Data,
770 > Encoding: request.Memo.EncodingType.String(),
771 > TaskQueue: request.TaskQueue,
772 > SearchAttributes: searchAttributes,
773 > ParentWorkflowID: request.ParentWorkflowID,
774 > ParentRunID: request.ParentRunID,
775 > RootWorkflowID: request.RootWorkflowID,
776 > RootRunID: request.RootRunID,
777 > Version: request.TaskID,
778 > }, nil
779 }
780
781 func (s *VisibilityStore) prepareSearchAttributesForDb(
782 request *store.InternalVisibilityRequestBase,
783 > ) (*sqlplugin.VisibilitySearchAttributes, error) { visibility_store.go
784 > if request.SearchAttributes == nil {
785 > return nil, nil
786 > }
787
788 > saTypeMap, err := s.searchAttributesProvider.GetSearchAttributes(s.GetIndexName(), false) visibility_store.go
789 > if err != nil {
790 return nil, serviceerror.NewUnavailable(
791 fmt.Sprintf("Unable to read search attributes types: %v", err))
792 }
793
794 > var searchAttributes sqlplugin.VisibilitySearchAttributes visibility_store.go
795 > searchAttributes, err = searchattribute.Decode(request.SearchAttributes, &saTypeMap, false)
796 > if err != nil {
797 return nil, err
798 }
799 > if len(request.SearchAttributes.GetIndexedFields()) != len(searchAttributes) { visibility_store.go
800 for name := range request.SearchAttributes.GetIndexedFields() {
801 if _, ok := searchAttributes[name]; !ok {
806 // This is to prevent existing tasks to fail indefinitely.
807 // If it's only invalid values error, then silently continue without them.
808 > searchAttributes, err = s.ValidateCustomSearchAttributes(searchAttributes) visibility_store.go
809 > if err != nil {
810 if _, ok := err.(*serviceerror.InvalidArgument); !ok {
811 return nil, err
813 }
814
815 > for name, value := range searchAttributes { visibility_store.go
816 > if value == nil {
817 delete(searchAttributes, name)
818 continue
819 }
820 }
821 > return &searchAttributes, nil visibility_store.go
822 }
823
go.temporal.io/server/api/history/v1/message.pb.go 81 covered LOC · 25 ranges

Open complete file

46 func (*TransientWorkflowTaskInfo) ProtoMessage() {}
47
48 > func (x *TransientWorkflowTaskInfo) ProtoReflect() protoreflect.Message { message.pb.go
49 > mi := &file_temporal_server_api_history_v1_message_proto_msgTypes[0]
50 > if x != nil {
51 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
52 if ms.LoadMessageInfo() == nil {
55 return ms
56 }
57 > return mi.MessageOf(x) message.pb.go
58 }
59
92 func (*VersionHistoryItem) ProtoMessage() {}
93
94 > func (x *VersionHistoryItem) ProtoReflect() protoreflect.Message { message.pb.go
95 > mi := &file_temporal_server_api_history_v1_message_proto_msgTypes[1]
96 > if x != nil {
97 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) message.pb.go
98 > if ms.LoadMessageInfo() == nil {
99 > ms.StoreMessageInfo(mi)
100 > }
101 > return ms
102 }
103 > return mi.MessageOf(x) message.pb.go
104 }
105
145 func (*VersionHistory) ProtoMessage() {}
146
147 > func (x *VersionHistory) ProtoReflect() protoreflect.Message { message.pb.go
148 > mi := &file_temporal_server_api_history_v1_message_proto_msgTypes[2]
149 > if x != nil {
150 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) message.pb.go
151 > if ms.LoadMessageInfo() == nil {
152 > ms.StoreMessageInfo(mi)
153 > }
154 > return ms
155 }
156 > return mi.MessageOf(x) message.pb.go
157 }
158
162 }
163
164 > func (x *VersionHistory) GetBranchToken() []byte { message.pb.go
165 > if x != nil {
166 > return x.BranchToken
167 > }
168 return nil
169 }
170
171 > func (x *VersionHistory) GetItems() []*VersionHistoryItem { message.pb.go
172 > if x != nil {
173 > return x.Items
174 > }
175 return nil
176 }
198 func (*VersionHistories) ProtoMessage() {}
199
200 > func (x *VersionHistories) ProtoReflect() protoreflect.Message { message.pb.go
201 > mi := &file_temporal_server_api_history_v1_message_proto_msgTypes[3]
202 > if x != nil {
203 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) message.pb.go
204 > if ms.LoadMessageInfo() == nil {
205 > ms.StoreMessageInfo(mi)
206 > }
207 > return ms
208 }
209 > return mi.MessageOf(x) message.pb.go
210 }
211
215 }
216
217 > func (x *VersionHistories) GetCurrentVersionHistoryIndex() int32 { message.pb.go
218 > if x != nil {
219 > return x.CurrentVersionHistoryIndex
220 > }
221 return 0
222 }
302 func (*TaskRange) ProtoMessage() {}
303
304 > func (x *TaskRange) ProtoReflect() protoreflect.Message { message.pb.go
305 > mi := &file_temporal_server_api_history_v1_message_proto_msgTypes[5]
306 > if x != nil {
307 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
308 if ms.LoadMessageInfo() == nil {
311 return ms
312 }
313 > return mi.MessageOf(x) message.pb.go
314 }
315
372 }
373
374 > func (x *StrippedHistoryEvent) GetEventId() int64 { message.pb.go
375 > if x != nil {
376 > return x.EventId
377 > }
378 return 0
379 }
498 }
499
500 > func init() { file_temporal_server_api_history_v1_message_proto_init() } message.pb.go
501 > func file_temporal_server_api_history_v1_message_proto_init() {
502 > if File_temporal_server_api_history_v1_message_proto != nil {
503 return
504 }
505 > type x struct{} message.pb.go
506 > out := protoimpl.TypeBuilder{
507 > File: protoimpl.DescBuilder{
508 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
509 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_history_v1_message_proto_rawDesc), len(file_temporal_server_api_history_v1_message_proto_rawDesc)),
510 > NumEnums: 0,
511 > NumMessages: 8,
512 > NumExtensions: 0,
513 > NumServices: 0,
514 > },
515 > GoTypes: file_temporal_server_api_history_v1_message_proto_goTypes,
516 > DependencyIndexes: file_temporal_server_api_history_v1_message_proto_depIdxs,
517 > MessageInfos: file_temporal_server_api_history_v1_message_proto_msgTypes,
518 > }.Build()
519 > File_temporal_server_api_history_v1_message_proto = out.File
520 > file_temporal_server_api_history_v1_message_proto_goTypes = nil
521 > file_temporal_server_api_history_v1_message_proto_depIdxs = nil
522 }
go.temporal.io/server/common/config/loader.go 81 covered LOC · 31 ranges

Open complete file

71 // WithEnv sets the environment name for configuration loading (e.g., "development", "production").
72 // If empty, defaults to "development".
73 > func WithEnv(env string) loadOption { loader.go
74 > return func(o *loadOptions) {
75 > if env != "" {
76 > o.env = env loader.go
77 > }
78 }
79 }
81 // WithConfigDir sets the directory path where configuration files are located.
82 // If empty, defaults to "config".
83 > func WithConfigDir(configDir string) loadOption { loader.go
84 > return func(o *loadOptions) {
85 > if configDir != "" {
86 > o.configDir = configDir
87 > }
88 }
89 }
127 //
128 // Returns the loaded configuration or an error if loading or validation fails.
129 > func Load(opts ...loadOption) (*Config, error) { loader.go
130 > cfg := &Config{}
131 > options := &loadOptions{}
132 >
133 > for _, opt := range opts {
134 > opt(options)
135 > }
136
137 > if err := options.load(cfg); err != nil { loader.go
138 return nil, err
139 }
140 > return cfg, nil loader.go
141 }
142
143 > func (opts *loadOptions) load(config any) error { loader.go
144 >
145 > if opts.useEmbeddedOnly {
146 stdlog.Println("Loading configuration from environment variables only")
147 return loadAndUnmarshalContent(embeddedConfigTemplate, "config_template_embedded.yaml", config)
148 }
149
150 > if opts.configFilePath != "" { loader.go
151 content, err := readConfigFile(opts.configFilePath)
152 if err != nil {
155 return loadAndUnmarshalContent(content, filepath.Base(opts.configFilePath), config)
156 }
157 > return opts.loadLegacy(config) loader.go
158
159 }
176 // env_az.yaml -- where "zone" is another input parameter
177
178 > func (opts *loadOptions) loadLegacy(config any) error { loader.go
179 > stdlog.Printf("Loading config; env=%v,zone=%v,configDir=%v\n", opts.env, opts.zone, opts.configDir)
180 > if opts.env == "" {
181 opts.env = envDevelopment
182 }
183 > if opts.configDir == "" { loader.go
184 opts.configDir = defaultConfigDir
185 }
186
187 > stdlog.Printf("Loading config; env=%v,zone=%v,configDir=%v\n", opts.env, opts.zone, opts.configDir) loader.go
188 >
189 > files, err := getConfigFiles(opts.env, opts.configDir, opts.zone)
190 > if err != nil {
191 return fmt.Errorf("failed to get config files: %w", err)
192 }
193
194 > stdlog.Printf("Loading config files=%v\n", files) loader.go
195 >
196 > for _, f := range files {
197 > data, err := readConfigFile(f)
198 > if err != nil {
199 return err
200 }
201
202 > processedData, err := processConfigFile(data, filepath.Base(f)) loader.go
203 > if err != nil {
204 return err
205 }
206
207 > err = yaml.Unmarshal(processedData, config) loader.go
208 > if err != nil {
209 return err
210 }
211 }
212
213 > validate := newValidator() loader.go
214 > return validate.Validate(config)
215 }
216
217 > func readConfigFile(path string) ([]byte, error) { loader.go
218 > data, err := os.ReadFile(path)
219 > if err != nil {
220 return nil, fmt.Errorf("could not read config file: %s. error: %w", path, err)
221
222 }
223 > return data, nil loader.go
224 }
225
226 // processConfigFile processes a config file, rendering it as a template if enabled
227 > func processConfigFile(data []byte, filename string) ([]byte, error) { loader.go
228 > // If the config file contains "enable-template" in a comment within the first 1KB, then
229 > // we will treat the file as a template and render it.
230 > templating, err := checkTemplatingEnabled(data)
231 > if err != nil {
232 return nil, err
233 }
234
235 > if !templating { loader.go
236 > return data, nil loader.go
237 > }
238
239 stdlog.Printf("Processing config file as template; filename=%v\n", filename)
266 }
267
268 > func checkTemplatingEnabled(content []byte) (bool, error) { loader.go
269 > scanner := bufio.NewScanner(io.LimitReader(bytes.NewReader(content), commentSearchLimit))
270 > for scanner.Scan() {
271 > line := strings.TrimSpace(scanner.Text())
272 >
273 > if strings.HasPrefix(line, "#") && strings.Contains(line, enableTemplate) {
274 return true, nil
275 }
276 }
277
278 > return false, scanner.Err() loader.go
279 }
280
281 // getConfigFiles returns the list of config files to
282 // process in the hierarchy order
283 > func getConfigFiles(env string, configDir string, zone string) ([]string, error) { loader.go
284 > candidates := make([]string, 2, 3)
285 > candidates[0] = filepath.Join(configDir, baseFile)
286 > candidates[1] = filepath.Join(configDir, file(env, "yaml"))
287 >
288 > if zone != "" {
289 f := file(concat(env, zone), "yaml")
290 candidates = append(candidates, filepath.Join(configDir, f))
291 }
292
293 > result := make([]string, 0, len(candidates)) loader.go
294 >
295 > for _, c := range candidates {
296 > _, err := os.Stat(c)
297 > if errors.Is(err, os.ErrNotExist) {
298 > continue loader.go
299 }
300 > if err != nil { loader.go
301 return nil, fmt.Errorf("error accessing config file %s: %w", c, err)
302 }
303 > result = append(result, c) loader.go
304 }
305 > if len(result) == 0 { loader.go
306 return nil, fmt.Errorf("%w in directory: %s", ErrConfigFilesNotFound, configDir)
307 }
308
309 > return result, nil loader.go
310 }
311
314 }
315
316 > func file(name string, suffix string) string { loader.go
317 > return name + "." + suffix
318 > }
319
320 func loadEnvMap() map[string]string {
go.temporal.io/server/common/persistence/sql/factory.go 81 covered LOC · 28 ranges

Open complete file

50 metricsHandler metrics.Handler,
51 serializer serialization.Serializer,
52 > ) *Factory { factory.go
53 > return &Factory{
54 > cfg: cfg,
55 > clusterName: clusterName,
56 > logger: logger,
57 > serializer: serializer,
58 > mainDBConn: NewRefCountedDBConn(sqlplugin.DbKindMain, &cfg, r, logger, metricsHandler),
59 > }
60 > }
61
62 // GetDB return a new SQL DB connection
70
71 // NewTaskStore returns a new task store
72 > func (f *Factory) NewTaskStore() (p.TaskStore, error) { factory.go
73 > conn, err := f.mainDBConn.Get()
74 > if err != nil {
75 return nil, err
76 }
77 > return newTaskPersistence(conn, f.cfg.TaskScanPartitions, f.logger, false, f.serializer) factory.go
78 }
79
80 // NewFairTaskStore returns a new task store
81 > func (f *Factory) NewFairTaskStore() (p.TaskStore, error) { factory.go
82 > conn, err := f.mainDBConn.Get()
83 > if err != nil {
84 return nil, err
85 }
86 > return newTaskPersistence(conn, f.cfg.TaskScanPartitions, f.logger, true, f.serializer) factory.go
87 }
88
89 // NewShardStore returns a new shard store
90 > func (f *Factory) NewShardStore() (p.ShardStore, error) { factory.go
91 > conn, err := f.mainDBConn.Get()
92 > if err != nil {
93 return nil, err
94 }
95 > return newShardPersistence(conn, f.clusterName, f.logger, f.serializer) factory.go
96 }
97
98 // NewMetadataStore returns a new metadata store
99 > func (f *Factory) NewMetadataStore() (p.MetadataStore, error) { factory.go
100 > conn, err := f.mainDBConn.Get()
101 > if err != nil {
102 return nil, err
103 }
104 > return newMetadataPersistenceV2(conn, f.clusterName, f.logger, f.serializer) factory.go
105 }
106
107 // NewClusterMetadataStore returns a new ClusterMetadata store
108 > func (f *Factory) NewClusterMetadataStore() (p.ClusterMetadataStore, error) { factory.go
109 > conn, err := f.mainDBConn.Get()
110 > if err != nil {
111 return nil, err
112 }
113 > return newClusterMetadataPersistence(conn, f.logger, f.serializer) factory.go
114 }
115
116 // NewExecutionStore returns a new ExecutionStore
117 > func (f *Factory) NewExecutionStore() (p.ExecutionStore, error) { factory.go
118 > conn, err := f.mainDBConn.Get()
119 > if err != nil {
120 return nil, err
121 }
122 > return NewSQLExecutionStore(conn, f.logger, f.serializer) factory.go
123 }
124
125 // NewQueue returns a new queue backed by sql
126 > func (f *Factory) NewQueue(queueType p.QueueType) (p.Queue, error) { factory.go
127 > conn, err := f.mainDBConn.Get()
128 > if err != nil {
129 return nil, err
130 }
131
132 > return newQueue(conn, f.logger, queueType, f.serializer) factory.go
133 }
134
135 // NewQueueV2 returns a new data-access object for queues and messages.
136 > func (f *Factory) NewQueueV2() (p.QueueV2, error) { factory.go
137 > conn, err := f.mainDBConn.Get()
138 > if err != nil {
139 return nil, err
140 }
141 > return NewQueueV2(conn, f.logger, f.serializer), nil factory.go
142 }
143
144 // NewNexusEndpointStore returns a new NexusEndpointStore
145 > func (f *Factory) NewNexusEndpointStore() (p.NexusEndpointStore, error) { factory.go
146 > conn, err := f.mainDBConn.Get()
147 > if err != nil {
148 return nil, err
149 }
150 > return NewSqlNexusEndpointStore(conn, f.logger, f.serializer) factory.go
151 }
152
153 // Close closes the factory
154 > func (f *Factory) Close() { factory.go
155 > f.mainDBConn.ForceClose()
156 > }
157
158 // NewRefCountedDBConn returns a logical mysql connection that
166 logger log.Logger,
167 metricsHandler metrics.Handler,
168 > ) DbConn { factory.go
169 > return DbConn{
170 > dbKind: dbKind,
171 > cfg: cfg,
172 > resolver: r,
173 > metrics: metricsHandler,
174 > logger: logger,
175 > }
176 > }
177
178 // Get returns a db connection and increments a reference count.
179 // This method will create a new connection, if an existing connection
180 // does not exist
181 > func (c *DbConn) Get() (sqlplugin.DB, error) { factory.go
182 > c.Lock()
183 > defer c.Unlock()
184 > if c.refCnt == 0 {
185 > conn, err := NewSQLDB(c.dbKind, c.cfg, c.resolver, c.logger, c.metrics)
186 > if err != nil {
187 return nil, err
188 }
189 > c.DB = conn factory.go
190 }
191 > c.refCnt++ factory.go
192 > return c, nil
193 }
194
195 // ForceClose ignores reference counts and shutsdown the underlying connection pool
196 > func (c *DbConn) ForceClose() { factory.go
197 > c.Lock()
198 > defer c.Unlock()
199 > if c.DB != nil {
200 > err := c.DB.Close()
201 > if err != nil {
202 fmt.Println("failed to close database connection, may leak some connection", err)
203 }
204 }
205 > c.refCnt = 0 factory.go
206 }
207
208 // Close closes the underlying connection if the reference count becomes zero
209 > func (c *DbConn) Close() error { factory.go
210 > c.Lock()
211 > defer c.Unlock()
212 > c.refCnt--
213 > if c.refCnt == 0 {
214 > return c.DB.Close()
215 > }
216 > return nil factory.go
217 }
go.temporal.io/server/service/matching/task.go 81 covered LOC · 24 ranges

Open complete file

123 )
124
125 > func (res taskResponse) err() error { task.go
126 > if res.forwarded {
127 return res.forwardErr
128 }
129 > return res.startErr task.go
130 }
131
135 taskDispatchRevisionNumber int64,
136 targetVersion *deploymentspb.WorkerDeploymentVersion,
137 > ) *internalTask { task.go
138 > var redirectInfo *taskqueuespb.BuildIdRedirectInfo
139 > // if this task is not forwarded, source can only be history
140 > source := enumsspb.TASK_SOURCE_HISTORY
141 > if forwardInfo != nil {
142 // if task is forwarded, it may be history or backlog. setting based on forward info
143 source = forwardInfo.TaskSource
144 redirectInfo = forwardInfo.GetRedirectInfo()
145 }
146 > return &internalTask{ task.go
147 > event: &genericTaskInfo{
148 > AllocatedTaskInfo: &persistencespb.AllocatedTaskInfo{
149 > Data: info,
150 > TaskId: syncMatchTaskId,
151 > },
152 > },
153 > forwardInfo: forwardInfo,
154 > source: source,
155 > redirectInfo: redirectInfo,
156 > responseC: make(chan taskResponse, 1),
157 >
158 > taskDispatchRevisionNumber: taskDispatchRevisionNumber,
159 > targetWorkerDeploymentVersion: targetVersion,
160 >
161 > effectivePriority: effectivePriorityFactor * priorityKey(info.GetPriority().GetPriorityKey()),
162 > }
163 }
164
166 info *persistencespb.AllocatedTaskInfo,
167 completionFunc func(*internalTask, taskResponse),
168 > ) *internalTask { task.go
169 > return &internalTask{
170 > event: &genericTaskInfo{
171 > AllocatedTaskInfo: info,
172 > completionFunc: completionFunc,
173 > },
174 > source: enumsspb.TASK_SOURCE_DB_BACKLOG,
175 > effectivePriority: effectivePriorityFactor * priorityKey(info.GetData().GetPriority().GetPriorityKey()),
176 > }
177 > }
178
179 func newInternalQueryTask(
229 }
230
231 > func (task *internalTask) isPollForwarder() bool { task.go
232 > return task.pollForwarderType != notPollForwarder
233 > }
234
235 // isQuery returns true if the underlying task is a query task
236 > func (task *internalTask) isQuery() bool { task.go
237 > return task.query != nil
238 > }
239
240 // isNexus returns true if the underlying task is a nexus task
244
245 // isStarted is true when this task is already marked as started
246 > func (task *internalTask) isStarted() bool { task.go
247 > return task.started != nil
248 > }
249
250 // isForwarded returns true if the underlying task is forwarded by a remote matching host
251 // forwarded tasks are already marked as started in history
252 > func (task *internalTask) isForwarded() bool { task.go
253 > return task.forwardInfo != nil
254 > }
255
256 > func (task *internalTask) isSyncMatchTask() bool { task.go
257 > return task.responseC != nil
258 > }
259
260 > func (task *internalTask) getCreateTime() *timestamppb.Timestamp { task.go
261 > if task.forwardInfo.GetCreateTime() != nil {
262 return task.forwardInfo.GetCreateTime()
263 > } else if task.event != nil { task.go
264 > return task.event.Data.GetCreateTime() task.go
265 > } else if task.query != nil { task.go
266 return task.query.createTime
267 } else if task.nexus != nil {
272 }
273
274 > func (task *internalTask) workflowExecution() *commonpb.WorkflowExecution { task.go
275 > switch {
276 > case task.event != nil:
277 > return &commonpb.WorkflowExecution{WorkflowId: task.event.Data.GetWorkflowId(), RunId: task.event.Data.GetRunId()}
278 case task.query != nil:
279 return task.query.request.GetQueryRequest().GetExecution()
324 }
325
326 > func (task *internalTask) getPriority() *commonpb.Priority { task.go
327 > if task.event != nil {
328 > return task.event.AllocatedTaskInfo.GetData().GetPriority() task.go
329 > } else if task.query != nil { task.go
330 return task.query.request.GetPriority()
331 }
339
340 // resetMatcherState must be called before adding or re-adding a backlog task to priMatcher.
341 > func (task *internalTask) resetMatcherState() { task.go
342 > task.removeFromMatcher.Store(&removeFuncNotAddedYet)
343 > }
344
345 // setRemoveFunc sets the function to remove the task from the matcher.
346 // It returns true if the task is still valid and the function was set,
347 // false if the task was evicted already and should not be added.
348 > func (task *internalTask) setRemoveFunc(remove func()) bool { task.go
349 > return task.removeFromMatcher.CompareAndSwap(&removeFuncNotAddedYet, &remove)
350 > }
351
352 // setEvicted marks the task as evicted. If it was added to a matcher it will be removed.
368 // carried on the taskResponse and counted in tasks_dropped by the backlog completion
369 // callback (reader.completeTask).
370 > func (task *internalTask) finish(r taskFinishResult) { task.go
371 > task.finishInternal(taskResponse{
372 > startErr: r.err,
373 > dropReason: r.dropReason,
374 > }, r.consumedToken)
375 > }
376
377 // finishForward must be called after forwarding a task.
380 }
381
382 > func (task *internalTask) finishInternal(res taskResponse, consumedToken bool) { task.go
383 > if !consumedToken && task.recycleToken != nil {
384 task.recycleToken(task)
385 }
386
387 > switch { task.go
388 case task.responseC != nil:
389 task.responseC <- res
390 > case task.event.completionFunc != nil: task.go
391 > // TODO: this probably should not be done synchronously in PollWorkflow/ActivityTaskQueue
392 > task.event.completionFunc(task, res)
393 }
394 }
go.temporal.io/server/api/persistence/v1/hsm.pb.go 80 covered LOC · 23 ranges

Open complete file

147 func (*StateMachineMap) ProtoMessage() {}
148
149 > func (x *StateMachineMap) ProtoReflect() protoreflect.Message { hsm.pb.go
150 > mi := &file_temporal_server_api_persistence_v1_hsm_proto_msgTypes[1]
151 > if x != nil {
152 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
153 if ms.LoadMessageInfo() == nil {
156 return ms
157 }
158 > return mi.MessageOf(x) hsm.pb.go
159 }
160
272 func (*StateMachineRef) ProtoMessage() {}
273
274 > func (x *StateMachineRef) ProtoReflect() protoreflect.Message { hsm.pb.go
275 > mi := &file_temporal_server_api_persistence_v1_hsm_proto_msgTypes[3]
276 > if x != nil {
277 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
278 if ms.LoadMessageInfo() == nil {
281 return ms
282 }
283 > return mi.MessageOf(x) hsm.pb.go
284 }
285
349 func (*StateMachineTaskInfo) ProtoMessage() {}
350
351 > func (x *StateMachineTaskInfo) ProtoReflect() protoreflect.Message { hsm.pb.go
352 > mi := &file_temporal_server_api_persistence_v1_hsm_proto_msgTypes[4]
353 > if x != nil {
354 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
355 if ms.LoadMessageInfo() == nil {
358 return ms
359 }
360 > return mi.MessageOf(x) hsm.pb.go
361 }
362
416 func (*StateMachineTimerGroup) ProtoMessage() {}
417
418 > func (x *StateMachineTimerGroup) ProtoReflect() protoreflect.Message { hsm.pb.go
419 > mi := &file_temporal_server_api_persistence_v1_hsm_proto_msgTypes[5]
420 > if x != nil {
421 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
422 if ms.LoadMessageInfo() == nil {
425 return ms
426 }
427 > return mi.MessageOf(x) hsm.pb.go
428 }
429
478 func (*VersionedTransition) ProtoMessage() {}
479
480 > func (x *VersionedTransition) ProtoReflect() protoreflect.Message { hsm.pb.go
481 > mi := &file_temporal_server_api_persistence_v1_hsm_proto_msgTypes[6]
482 > if x != nil {
483 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) hsm.pb.go
484 > if ms.LoadMessageInfo() == nil {
485 > ms.StoreMessageInfo(mi)
486 > }
487 > return ms
488 }
489 > return mi.MessageOf(x) hsm.pb.go
490 }
491
495 }
496
497 > func (x *VersionedTransition) GetNamespaceFailoverVersion() int64 { hsm.pb.go
498 > if x != nil {
499 > return x.NamespaceFailoverVersion hsm.pb.go
500 > }
501 > return 0 hsm.pb.go
502 }
503
504 > func (x *VersionedTransition) GetTransitionCount() int64 { hsm.pb.go
505 > if x != nil {
506 > return x.TransitionCount hsm.pb.go
507 > }
508 > return 0 hsm.pb.go
509 }
510
531 func (*StateMachineTombstoneBatch) ProtoMessage() {}
532
533 > func (x *StateMachineTombstoneBatch) ProtoReflect() protoreflect.Message { hsm.pb.go
534 > mi := &file_temporal_server_api_persistence_v1_hsm_proto_msgTypes[7]
535 > if x != nil {
536 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) hsm.pb.go
537 > if ms.LoadMessageInfo() == nil {
538 > ms.StoreMessageInfo(mi)
539 > }
540 > return ms
541 }
542 > return mi.MessageOf(x) hsm.pb.go
543 }
544
592 func (*StateMachineTombstone) ProtoMessage() {}
593
594 > func (x *StateMachineTombstone) ProtoReflect() protoreflect.Message { hsm.pb.go
595 > mi := &file_temporal_server_api_persistence_v1_hsm_proto_msgTypes[8]
596 > if x != nil {
597 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
598 if ms.LoadMessageInfo() == nil {
601 return ms
602 }
603 > return mi.MessageOf(x) hsm.pb.go
604 }
605
895 }
896
897 > func init() { file_temporal_server_api_persistence_v1_hsm_proto_init() } hsm.pb.go
898 > func file_temporal_server_api_persistence_v1_hsm_proto_init() {
899 > if File_temporal_server_api_persistence_v1_hsm_proto != nil {
900 > return
901 > }
902 > file_temporal_server_api_persistence_v1_hsm_proto_msgTypes[8].OneofWrappers = []any{
903 > (*StateMachineTombstone_ActivityScheduledEventId)(nil),
904 > (*StateMachineTombstone_TimerId)(nil),
905 > (*StateMachineTombstone_ChildExecutionInitiatedEventId)(nil),
906 > (*StateMachineTombstone_RequestCancelInitiatedEventId)(nil),
907 > (*StateMachineTombstone_SignalExternalInitiatedEventId)(nil),
908 > (*StateMachineTombstone_UpdateId)(nil),
909 > (*StateMachineTombstone_StateMachinePath)(nil),
910 > (*StateMachineTombstone_ChasmNodePath)(nil),
911 > }
912 > type x struct{}
913 > out := protoimpl.TypeBuilder{
914 > File: protoimpl.DescBuilder{
915 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
916 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_hsm_proto_rawDesc), len(file_temporal_server_api_persistence_v1_hsm_proto_rawDesc)),
917 > NumEnums: 0,
918 > NumMessages: 12,
919 > NumExtensions: 0,
920 > NumServices: 0,
921 > },
922 > GoTypes: file_temporal_server_api_persistence_v1_hsm_proto_goTypes,
923 > DependencyIndexes: file_temporal_server_api_persistence_v1_hsm_proto_depIdxs,
924 > MessageInfos: file_temporal_server_api_persistence_v1_hsm_proto_msgTypes,
925 > }.Build()
926 > File_temporal_server_api_persistence_v1_hsm_proto = out.File
927 > file_temporal_server_api_persistence_v1_hsm_proto_goTypes = nil
928 > file_temporal_server_api_persistence_v1_hsm_proto_depIdxs = nil
929 }
go.temporal.io/server/common/persistence/sql/task_v1.go 80 covered LOC · 17 ranges

Open complete file

34 logger log.Logger,
35 serializer serialization.Serializer,
36 > ) (*sqlTaskManagerV1, error) { task_v1.go
37 > return &sqlTaskManagerV1{
38 > SqlStore: NewSQLStore(db, logger, serializer),
39 > userDataStore: uds,
40 > taskQueueStore: tqs,
41 > }, nil
42 > }
43
44 func (m *sqlTaskManagerV1) CreateTasks(
45 ctx context.Context,
46 request *persistence.InternalCreateTasksRequest,
47 > ) (*persistence.CreateTasksResponse, error) { task_v1.go
48 > nidBytes, err := primitives.ParseUUID(request.NamespaceID)
49 > if err != nil {
50 return nil, serviceerror.NewUnavailable(err.Error())
51 }
52
53 // cache by subqueue to minimize calls to taskQueueIdAndHash
54 > type pair struct { task_v1.go
55 > id []byte
56 > hash uint32
57 > }
58 > cache := make(map[int]pair)
59 > idAndHash := func(subqueue int) ([]byte, uint32) {
60 > if pair, ok := cache[subqueue]; ok {
61 > return pair.id, pair.hash
62 > }
63 > id, hash := taskQueueIdAndHash(nidBytes, request.TaskQueue, request.TaskType, subqueue)
64 > cache[subqueue] = pair{id: id, hash: hash}
65 > return id, hash
66 }
67
68 > tasksRows := make([]sqlplugin.TasksRow, len(request.Tasks)) task_v1.go
69 > for i, v := range request.Tasks {
70 > tqId, tqHash := idAndHash(v.Subqueue)
71 > tasksRows[i] = sqlplugin.TasksRow{
72 > RangeHash: tqHash,
73 > TaskQueueID: tqId,
74 > TaskID: v.TaskId,
75 > Data: v.Task.Data,
76 > DataEncoding: v.Task.EncodingType.String(),
77 > }
78 > }
79 > var resp *persistence.CreateTasksResponse
80 > err = m.SqlStore.txExecute(ctx, "CreateTasks", func(tx sqlplugin.Tx) error {
81 > if _, err1 := tx.InsertIntoTasks(ctx, tasksRows); err1 != nil {
82 return err1
83 }
84 // Lock task queue before committing.
85 > tqId, tqHash := idAndHash(persistence.SubqueueZero) task_v1.go
86 > if err := lockTaskQueue(ctx,
87 > tx,
88 > tqHash,
89 > tqId,
90 > request.RangeID,
91 > sqlplugin.MatchingTaskVersion1,
92 > ); err != nil {
93 return err
94 }
95 > resp = &persistence.CreateTasksResponse{UpdatedMetadata: false} task_v1.go
96 > return nil
97 })
98 > return resp, err task_v1.go
99 }
100
102 ctx context.Context,
103 request *persistence.GetTasksRequest,
104 > ) (*persistence.InternalGetTasksResponse, error) { task_v1.go
105 > if request.InclusiveMinPass != 0 {
106 return nil, serviceerror.NewInternal("invalid GetTasks request on queue: InclusiveMinPass is not supported")
107 }
108
109 > nidBytes, err := primitives.ParseUUID(request.NamespaceID) task_v1.go
110 > if err != nil {
111 return nil, serviceerror.NewUnavailable(err.Error())
112 }
113
114 > inclusiveMinTaskID := request.InclusiveMinTaskID task_v1.go
115 > exclusiveMaxTaskID := request.ExclusiveMaxTaskID
116 > if len(request.NextPageToken) != 0 {
117 token, err := deserializePageTokenJson[matchingTaskPageToken](request.NextPageToken)
118 if err != nil {
122 }
123
124 > tqId, tqHash := taskQueueIdAndHash(nidBytes, request.TaskQueue, request.TaskType, request.Subqueue) task_v1.go
125 > rows, err := m.DB.SelectFromTasks(ctx, sqlplugin.TasksFilter{
126 > RangeHash: tqHash,
127 > TaskQueueID: tqId,
128 > InclusiveMinTaskID: &inclusiveMinTaskID,
129 > ExclusiveMaxTaskID: &exclusiveMaxTaskID,
130 > PageSize: &request.PageSize,
131 > })
132 > if err != nil {
133 return nil, serviceerror.NewUnavailablef("GetTasks operation failed. Failed to get rows. Error: %v", err)
134 }
135
136 > response := &persistence.InternalGetTasksResponse{ task_v1.go
137 > Tasks: make([]*commonpb.DataBlob, len(rows)),
138 > }
139 > for i, v := range rows {
140 > response.Tasks[i] = persistence.NewDataBlob(v.Data, v.DataEncoding) task_v1.go
141 > }
142 > if len(rows) == request.PageSize { task_v1.go
143 nextTaskID := rows[len(rows)-1].TaskID + 1
144 if nextTaskID < exclusiveMaxTaskID {
153 }
154
155 > return response, nil task_v1.go
156 }
157
192 oldRangeID int64,
193 v sqlplugin.MatchingTaskVersion,
194 > ) error { task_v1.go
195 > rangeID, err := tx.LockTaskQueues(ctx, sqlplugin.TaskQueuesFilter{
196 > RangeHash: tqHash,
197 > TaskQueueID: tqId,
198 > }, v)
199 > switch err {
200 > case nil:
201 > if rangeID != oldRangeID {
202 return &persistence.ConditionFailedError{
203 Msg: fmt.Sprintf("Task queue range ID was %v when it was should have been %v", rangeID, oldRangeID),
204 }
205 }
206 > return nil task_v1.go
207
208 case sql.ErrNoRows:
go.temporal.io/server/service/history/queues/monitor.go 80 covered LOC · 14 ranges

Open complete file

87 timeSource clock.TimeSource,
88 options *MonitorOptions,
89 > ) *monitorImpl { monitor.go
90 > return &monitorImpl{
91 > readerStats: make(map[int64]readerStats),
92 > sliceStats: make(map[Slice]sliceStats),
93 > categoryType: categoryType,
94 > timeSource: timeSource,
95 > options: options,
96 > pendingAlerts: make(map[AlertType]struct{}),
97 > silencedAlerts: make(map[AlertType]time.Time),
98 > alertCh: make(chan *Alert, alertChSize),
99 > shutdownCh: make(chan struct{}),
100 > }
101 > }
102
103 > func (m *monitorImpl) GetTotalPendingTaskCount() int { monitor.go
104 > m.Lock()
105 > defer m.Unlock()
106 >
107 > return m.totalPendingTaskCount
108 > }
109
110 func (m *monitorImpl) GetSlicePendingTaskCount(slice Slice) int {
118 }
119
120 > func (m *monitorImpl) SetSlicePendingTaskCount(slice Slice, count int) { monitor.go
121 > m.Lock()
122 > defer m.Unlock()
123 >
124 > stats := m.sliceStats[slice]
125 > m.totalPendingTaskCount = m.totalPendingTaskCount - stats.pendingTaskCount + count
126 >
127 > stats.pendingTaskCount = count
128 > m.sliceStats[slice] = stats
129 >
130 > criticalTotalTasks := m.options.PendingTasksCriticalCount()
131 > if criticalTotalTasks > 0 && m.totalPendingTaskCount > criticalTotalTasks {
132 m.sendAlertLocked(&Alert{
133 AlertType: AlertTypeQueuePendingTaskCount,
152 }
153
154 > func (m *monitorImpl) SetReaderWatermark(readerID int64, watermark tasks.Key) { monitor.go
155 > // TODO: currently only tracking default reader progress for scheduled queue
156 > if readerID != DefaultReaderId || m.categoryType != tasks.CategoryTypeScheduled {
157 > return monitor.go
158 > }
159
160 m.Lock()
211 }
212
213 > func (m *monitorImpl) SetSliceCount(readerID int64, count int) { monitor.go
214 > m.Lock()
215 > defer m.Unlock()
216 >
217 > stats := m.readerStats[readerID]
218 > m.totalSliceCount = m.totalSliceCount - stats.sliceCount + count
219 >
220 > stats.sliceCount = count
221 > m.readerStats[readerID] = stats
222 >
223 > criticalSliceCount := m.options.SliceCountCriticalThreshold()
224 > if criticalSliceCount > 0 && m.totalSliceCount > criticalSliceCount {
225 m.sendAlertLocked(&Alert{
226 AlertType: AlertTypeSliceCount,
233 }
234
235 > func (m *monitorImpl) RemoveSlice(slice Slice) { monitor.go
236 > m.Lock()
237 > defer m.Unlock()
238 >
239 > stats, ok := m.sliceStats[slice]
240 > if !ok {
241 > return monitor.go
242 > }
243
244 > m.totalPendingTaskCount -= stats.pendingTaskCount monitor.go
245 > delete(m.sliceStats, slice)
246 }
247
248 > func (m *monitorImpl) RemoveReader(readerID int64) { monitor.go
249 > m.Lock()
250 > defer m.Unlock()
251 >
252 > stats, ok := m.readerStats[readerID]
253 > if !ok {
254 return
255 }
256
257 > m.totalSliceCount -= stats.sliceCount monitor.go
258 > delete(m.readerStats, readerID)
259 }
260
274 }
275
276 > func (m *monitorImpl) AlertCh() <-chan *Alert { monitor.go
277 > return m.alertCh
278 > }
279
280 > func (m *monitorImpl) Close() { monitor.go
281 > m.Lock()
282 > defer m.Unlock()
283 >
284 > close(m.shutdownCh)
285 >
286 > for {
287 > select {
288 case <-m.alertCh:
289 // drain alertCh
290 > default: monitor.go
291 > close(m.alertCh)
292 > return
293 }
294 }
go.temporal.io/server/service/history/shard/task_key_generator.go 80 covered LOC · 17 ranges

Open complete file

39 logger log.Logger,
40 renewRangeIDFn renewRangeIDFn,
41 > ) *taskKeyGenerator { task_key_generator.go
42 > return &taskKeyGenerator{
43 > nextTaskID: taskIDUninitialized,
44 > exclusiveMaxTaskID: taskIDUninitialized,
45 > rangeSizeBits: rangeSizeBits,
46 > timeSource: timeSource,
47 > logger: logger,
48 > renewRangeIDFn: renewRangeIDFn,
49 > }
50 > }
51
52 func (a *taskKeyGenerator) setTaskKeys(
53 taskMaps ...map[tasks.Category][]tasks.Task,
54 > ) error { task_key_generator.go
55 > now := a.timeSource.Now()
56 > // TODO: Truncation here is just to make sure task scheduled time has the same precision as the old logic.
57 > // Remove this truncation once we validate the rest of the code can worker correctly with higher precision.
58 > a.setTaskMinScheduledTime(now.Truncate(common.ScheduledTaskMinPrecision))
59 >
60 > for _, taskMap := range taskMaps {
61 > for category, tasksByCategory := range taskMap {
62 > isScheduledTask := category.Type() == tasks.CategoryTypeScheduled task_key_generator.go
63 > for _, task := range tasksByCategory {
64 > id, err := a.generateTaskID()
65 > if err != nil {
66 return err
67 }
68 > task.SetTaskID(id) task_key_generator.go
69 >
70 > taskScheduledTime := now
71 > if isScheduledTask {
72 > // Persistence might loss precision when saving to DB. task_key_generator.go
73 > // Make the task scheduled time to have the same precision as DB here,
74 > // so that if the comparsion in the next step passes, it's guaranteed
75 > // the task can be retrieved from DB by queue processor.
76 > taskScheduledTime = task.GetVisibilityTime().
77 > Add(common.ScheduledTaskMinPrecision).
78 > Truncate(common.ScheduledTaskMinPrecision)
79 >
80 > if taskScheduledTime.Before(a.taskMinScheduledTime) {
81 a.logger.Debug("New timer generated is less than min scheduled time",
82 tag.WorkflowNamespaceID(task.GetNamespaceID()),
94 }
95 }
96 > task.SetVisibilityTime(taskScheduledTime) task_key_generator.go
97 >
98 > a.logger.Debug("Assigning new task key",
99 > tag.WorkflowNamespaceID(task.GetNamespaceID()),
100 > tag.WorkflowID(task.GetWorkflowID()),
101 > tag.WorkflowRunID(task.GetRunID()),
102 > tag.TaskType(task.GetType()),
103 > tag.TaskID(id),
104 > tag.Timestamp(task.GetVisibilityTime()),
105 > tag.CursorTimestamp(a.taskMinScheduledTime),
106 > )
107 }
108 }
109 }
110
111 > return nil task_key_generator.go
112 }
113
114 func (a *taskKeyGenerator) peekTaskKey(
115 category tasks.Category,
116 > ) tasks.Key { task_key_generator.go
117 > switch category.Type() {
118 > case tasks.CategoryTypeImmediate: task_key_generator.go
119 > return tasks.NewImmediateKey(a.nextTaskID)
120 > case tasks.CategoryTypeScheduled: task_key_generator.go
121 > return tasks.NewKey(
122 > a.taskMinScheduledTime,
123 > a.nextTaskID,
124 > )
125 default:
126 panic(fmt.Sprintf("Unknown category type: %v", category.Type()))
130 func (a *taskKeyGenerator) generateTaskKey(
131 category tasks.Category,
132 > ) (tasks.Key, error) { task_key_generator.go
133 > id, err := a.generateTaskID()
134 > if err != nil {
135 return tasks.Key{}, err
136 }
137
138 > switch category.Type() { task_key_generator.go
139 > case tasks.CategoryTypeImmediate:
140 > return tasks.NewImmediateKey(id), nil
141 case tasks.CategoryTypeScheduled:
142 return tasks.NewKey(
149 }
150
151 > func (a *taskKeyGenerator) setRangeID(rangeID int64) { task_key_generator.go
152 > a.nextTaskID = rangeID << a.rangeSizeBits
153 > a.exclusiveMaxTaskID = (rangeID + 1) << a.rangeSizeBits
154 >
155 > a.logger.Info("Task key range updated",
156 > tag.Number(a.nextTaskID),
157 > tag.NextNumber(a.exclusiveMaxTaskID),
158 > )
159 > }
160
161 func (a *taskKeyGenerator) setTaskMinScheduledTime(
162 taskMinScheduledTime time.Time,
164 > a.taskMinScheduledTime = util.MaxTime(a.taskMinScheduledTime, taskMinScheduledTime)
165 > }
166
167 > func (a *taskKeyGenerator) generateTaskID() (int64, error) { task_key_generator.go
168 > if a.nextTaskID == taskIDUninitialized {
169 a.logger.Panic("Range id is not initialized before generating task id")
170 }
171
172 > if a.nextTaskID == a.exclusiveMaxTaskID { task_key_generator.go
173 if err := a.renewRangeIDFn(); err != nil {
174 return taskIDUninitialized, err
180 }
181
182 > taskID := a.nextTaskID task_key_generator.go
183 > a.nextTaskID++
184 > return taskID, nil
185 }
go.temporal.io/server/client/client_bean.go 79 covered LOC · 14 ranges

Open complete file

56
57 // NewClientBean provides a collection of clients
58 > func NewClientBean(factory Factory, clusterMetadata cluster.Metadata) (Bean, error) { client_bean.go
59 >
60 > historyClient, err := factory.NewHistoryClientWithTimeout(history.DefaultTimeout)
61 > if err != nil {
62 return nil, err
63 }
64
65 > adminClients := map[string]adminservice.AdminServiceClient{} client_bean.go
66 > frontendClients := map[string]frontendClient{}
67 >
68 > currentClusterName := clusterMetadata.GetCurrentClusterName()
69 > // Init local cluster client with membership info
70 > adminClient, err := factory.NewLocalAdminClientWithTimeout(
71 > admin.DefaultTimeout,
72 > admin.DefaultLargeTimeout,
73 > )
74 > if err != nil {
75 return nil, err
76 }
77 > conn, client, err := factory.NewLocalFrontendClientWithTimeout( client_bean.go
78 > frontend.DefaultTimeout,
79 > frontend.DefaultLongPollTimeout,
80 > )
81 > if err != nil {
82 return nil, err
83 }
84 > adminClients[currentClusterName] = adminClient client_bean.go
85 > frontendClients[currentClusterName] = frontendClient{
86 > connection: conn,
87 > WorkflowServiceClient: client,
88 > }
89 >
90 > bean := &clientBeanImpl{
91 > factory: factory,
92 > historyClient: historyClient,
93 > clusterMetadata: clusterMetadata,
94 > adminClients: adminClients,
95 > frontendClients: frontendClients,
96 > }
97 > bean.registerClientEviction()
98 > return bean, nil
99 }
100
101 > func (h *clientBeanImpl) registerClientEviction() { client_bean.go
102 > currentCluster := h.clusterMetadata.GetCurrentClusterName()
103 > h.clusterMetadata.RegisterMetadataChangeCallback(
104 > h,
105 > func(oldClusterMetadata map[string]*cluster.ClusterInformation, newClusterMetadata map[string]*cluster.ClusterInformation) {
106 > for clusterName := range newClusterMetadata {
107 > if clusterName == currentCluster {
108 > continue
109 }
110 h.adminClientsLock.Lock()
120 // Close releases the resources held by the bean's clients. See the Bean
121 // interface for details. It is safe to call more than once.
122 > func (h *clientBeanImpl) Close() { client_bean.go
123 > h.clusterMetadata.UnRegisterMetadataChangeCallback(h)
124 >
125 > // The history and matching client wrapper chains implement Stop();
126 > // stopping them releases their daemon goroutines and cached gRPC
127 > // connections.
128 > if s, ok := h.historyClient.(interface{ Stop() }); ok {
129 > s.Stop()
130 > }
131 > if mc := h.matchingClient.Load(); mc != nil {
132 > if s, ok := mc.(interface{ Stop() }); ok {
133 > s.Stop()
134 > }
135 }
136 }
137
138 > func (h *clientBeanImpl) GetHistoryClient() historyservice.HistoryServiceClient { client_bean.go
139 > return h.historyClient
140 > }
141
142 > func (h *clientBeanImpl) GetMatchingClient(namespaceIDToName NamespaceIDToNameFunc) (matchingservice.MatchingServiceClient, error) { client_bean.go
143 > if client := h.matchingClient.Load(); client != nil {
144 return client.(matchingservice.MatchingServiceClient), nil
145 }
146 > return h.lazyInitMatchingClient(namespaceIDToName) client_bean.go
147 }
148
149 > func (h *clientBeanImpl) GetFrontendClient() workflowservice.WorkflowServiceClient { client_bean.go
150 > return h.frontendClients[h.clusterMetadata.GetCurrentClusterName()]
151 > }
152
153 > func (h *clientBeanImpl) GetRemoteAdminClient(cluster string) (adminservice.AdminServiceClient, error) { client_bean.go
154 > h.adminClientsLock.RLock()
155 > client, ok := h.adminClients[cluster]
156 > h.adminClientsLock.RUnlock()
157 > if ok {
158 > return client, nil
159 > }
160
161 clusterInfo, clusterFound := h.clusterMetadata.GetAllClusterInfo()[cluster]
234 }
235
236 > func (h *clientBeanImpl) lazyInitMatchingClient(namespaceIDToName NamespaceIDToNameFunc) (matchingservice.MatchingServiceClient, error) { client_bean.go
237 > h.Lock()
238 > defer h.Unlock()
239 > if cached := h.matchingClient.Load(); cached != nil {
240 return cached.(matchingservice.MatchingServiceClient), nil
241 }
242 > client, err := h.factory.NewMatchingClientWithTimeout(namespaceIDToName, matching.DefaultTimeout, matching.DefaultLongPollTimeout) client_bean.go
243 > if err != nil {
244 return nil, err
245 }
246 > h.matchingClient.Store(client) client_bean.go
247 > return client, nil
248 }
go.temporal.io/server/common/namespace/namespace.go 79 covered LOC · 28 ranges

Open complete file

81 resolver ReplicationResolver,
82 mutations ...Mutation,
83 > ) (*Namespace, error) { namespace.go
84 > if resolver == nil {
85 return nil, serviceerror.NewInvalidArgument("replicationResolver must be provided")
86 }
87 > ns := &Namespace{ namespace.go
88 > info: detail.Info,
89 > config: detail.Config,
90 > configVersion: detail.ConfigVersion,
91 > customSearchAttributesMapper: CustomSearchAttributesMapper{
92 > fieldToAlias: detail.Config.CustomSearchAttributeAliases,
93 > aliasToField: util.InverseMap(detail.Config.CustomSearchAttributeAliases),
94 > },
95 > replicationResolver: resolver,
96 > }
97 >
98 > for _, m := range mutations {
99 > m.apply(ns) namespace.go
100 > }
101
102 > return ns, nil namespace.go
103 }
104
128 // VisibilityArchivalState observes the visibility archive configuration (state
129 // and URI) for this namespace.
130 > func (ns *Namespace) VisibilityArchivalState() ArchivalConfigState { namespace.go
131 > return ArchivalConfigState{
132 > State: ns.config.VisibilityArchivalState,
133 > URI: ns.config.VisibilityArchivalUri,
134 > }
135 > }
136
137 // HistoryArchivalState observes the history archive configuration (state and
138 // URI) for this namespace.
139 > func (ns *Namespace) HistoryArchivalState() ArchivalConfigState { namespace.go
140 > return ArchivalConfigState{
141 > State: ns.config.HistoryArchivalState,
142 > URI: ns.config.HistoryArchivalUri,
143 > }
144 > }
145
146 // VerifyBinaryChecksum returns an error if the provided checksum is one of this
147 // namespace's configured bad binary checksums. The returned error (if any) will
148 // be unwrappable as BadBinaryError.
149 > func (ns *Namespace) VerifyBinaryChecksum(cksum string) error { namespace.go
150 > badBinMap := ns.config.GetBadBinaries().GetBinaries()
151 > if badBinMap == nil {
152 return nil
153 }
154 > if info, ok := badBinMap[cksum]; ok { namespace.go
155 return BadBinaryError{cksum: cksum, info: info}
156 }
157 > return nil namespace.go
158 }
159
160 // ID observes this namespace's permanent unique identifier in string form.
161 > func (ns *Namespace) ID() ID { namespace.go
162 > if ns.info == nil {
163 return ID("")
164 }
165 > return ID(ns.info.Id) namespace.go
166 }
167
168 // Name observes this namespace's configured name.
169 > func (ns *Namespace) Name() Name { namespace.go
170 > if ns.info == nil {
171 return Name("")
172 }
173 > return Name(ns.info.Name) namespace.go
174 }
175
176 > func (ns *Namespace) State() enumspb.NamespaceState { namespace.go
177 > if ns.info == nil {
178 return enumspb.NAMESPACE_STATE_UNSPECIFIED
179 }
180 > return ns.info.State namespace.go
181 }
182
185 }
186
187 > func (ns *Namespace) ReplicationState(businessID string) enumspb.ReplicationState { namespace.go
188 > return ns.replicationResolver.ReplicationState(businessID)
189 > }
190
191 // ActiveClusterName observes the name of the cluster that is currently active
192 // for this namespace.
193 > func (ns *Namespace) ActiveClusterName(routingKey RoutingKey) string { namespace.go
194 > return ns.replicationResolver.ActiveClusterName(routingKey)
195 > }
196
197 // ClusterNames observes the names of the clusters to which this namespace is
198 // replicated.
199 > func (ns *Namespace) ClusterNames(businessID string) []string { namespace.go
200 > return ns.replicationResolver.ClusterNames(businessID)
201 > }
202
203 // IsOnCluster returns true is namespace is registered on cluster otherwise false.
212
213 // FailoverVersion return the namespace failover version
214 > func (ns *Namespace) FailoverVersion(businessID string) int64 { namespace.go
215 > return ns.replicationResolver.FailoverVersion(businessID)
216 > }
217
218 // IsGlobalNamespace returns whether the namespace is a global namespace.
219 // Being a global namespace doesn't necessarily mean that there are multiple registered clusters for it, only that it
220 // has a failover version. To determine whether operations should be replicated for a namespace, see ReplicationPolicy.
221 > func (ns *Namespace) IsGlobalNamespace() bool { namespace.go
222 > return ns.replicationResolver.IsGlobalNamespace()
223 > }
224
225 // FailoverNotificationVersion return the global notification version of when failover happened
256 // Note: Do not use this to determine if a workflow is active in the cluster.
257 // Use ActiveClusterName(businessID) instead.
258 > func (ns *Namespace) ActiveInCluster(clusterName string) bool { namespace.go
259 > return ns.replicationResolver.ActiveInCluster(clusterName)
260 > }
261
262 // ReplicationPolicy return the derived workflow replication policy
284
285 // Retention returns retention duration for this namespace.
286 > func (ns *Namespace) Retention() time.Duration { namespace.go
287 > if ns.config.Retention == nil {
288 return 0
289 }
290
291 > return ns.config.Retention.AsDuration() namespace.go
292 }
293
294 // CustomSearchAttributesMapper is a part of temporary solution. Do not use this method.
295 > func (ns *Namespace) CustomSearchAttributesMapper() CustomSearchAttributesMapper { namespace.go
296 > return ns.customSearchAttributesMapper
297 > }
298
299 func (ns *Namespace) GetWorkflowRules() []*rulespb.WorkflowRule {
337 }
338
339 > func (id ID) String() string { namespace.go
340 > return string(id)
341 > }
342
343 > func (id ID) IsEmpty() bool { namespace.go
344 > return id == EmptyID
345 > }
346
347 > func (n Name) String() string { namespace.go
348 > return string(n)
349 > }
350
351 > func (n Name) IsEmpty() bool { namespace.go
352 > return n == EmptyName
353 > }
354
355 func (m *CustomSearchAttributesMapper) GetAlias(fieldName string, namespace string) (string, error) {
go.temporal.io/server/common/quotas/rate_burst.go 79 covered LOC · 25 ranges

Open complete file

20 return defaultOutgoingRateBurstRatio
21 }
22 > DefaultIncomingNamespaceBurstRatioFn = func(_ string) float64 { rate_burst.go
23 > return defaultIncomingRateBurstRatio
24 > }
25 DefaultOutgoingNamespaceBurstRatioFn = func(_ string) float64 {
26 return defaultOutgoingRateBurstRatio
85 rateFn RateFn,
86 burstFn BurstFn,
87 > ) *RateBurstImpl { rate_burst.go
88 > return &RateBurstImpl{
89 > rateFn: rateFn,
90 > burstFn: burstFn,
91 > }
92 > }
93
94 func NewDefaultIncomingRateBurst(
95 rateFn RateFn,
96 > ) *RateBurstImpl { rate_burst.go
97 > return NewDefaultRateBurst(rateFn, func() float64 {
98 > return defaultIncomingRateBurstRatio rate_burst.go
99 > })
100 }
101
102 func NewDefaultOutgoingRateBurst(
103 rateFn RateFn,
104 > ) *RateBurstImpl { rate_burst.go
105 > return NewDefaultRateBurst(rateFn, func() float64 {
106 > return defaultOutgoingRateBurstRatio
107 > })
108 }
109
111 rateFn RateFn,
112 rateToBurstRatio BurstRatioFn,
113 > ) *RateBurstImpl { rate_burst.go
114 > burstFn := func() int {
115 > rate := rateFn() rate_burst.go
116 > if rate < 0 {
117 rate = 0
118 }
119
120 > ratio := rateToBurstRatio() rate_burst.go
121 > if ratio < 0 {
122 ratio = 0
123 }
124 > burst := int(rate * ratio) rate_burst.go
125 > if burst == 0 && rate > 0 && ratio > 0 {
126 > burst = 1 rate_burst.go
127 > }
128 > return burst rate_burst.go
129 }
130 > return NewRateBurst(rateFn, burstFn) rate_burst.go
131 }
132
133 > func (d *RateBurstImpl) Rate() float64 { rate_burst.go
134 > return d.rateFn()
135 > }
136
137 > func (d *RateBurstImpl) Burst() int { rate_burst.go
138 > return d.burstFn()
139 > }
140
141 func NewMutableRateBurst(
142 rate float64,
143 burst int,
144 > ) *MutableRateBurstImpl { rate_burst.go
145 > d := &MutableRateBurstImpl{}
146 > d.SetRPS(rate)
147 > d.SetBurst(burst)
148 >
149 > return d
150 > }
151
152 > func (d *MutableRateBurstImpl) SetRPS(rate float64) { rate_burst.go
153 > d.rate.Store(math.Float64bits(rate))
154 > }
155
156 > func (d *MutableRateBurstImpl) SetBurst(burst int) { rate_burst.go
157 > d.burst.Store(int64(burst))
158 > }
159
160 > func (d *MutableRateBurstImpl) Rate() float64 { rate_burst.go
161 > return math.Float64frombits(d.rate.Load())
162 > }
163
164 > func (d *MutableRateBurstImpl) Burst() int { rate_burst.go
165 > return int(d.burst.Load())
166 > }
167
168 func NewNamespaceRateBurst(
170 rateFn NamespaceRateFn,
171 burstRatioFn NamespaceBurstRatioFn,
172 > ) *NamespaceRateBurstImpl { rate_burst.go
173 > return &NamespaceRateBurstImpl{
174 > namespaceName: namespaceName,
175 > rateFn: rateFn,
176 > burstFn: func(namespace string) int {
177 > return max(1, int(math.Ceil(rateFn(namespace)*burstRatioFn(namespace))))
178 > },
179 }
180 }
181
182 > func (n *NamespaceRateBurstImpl) Rate() float64 { rate_burst.go
183 > return n.rateFn(n.namespaceName)
184 > }
185
186 > func (n *NamespaceRateBurstImpl) Burst() int { rate_burst.go
187 > return n.burstFn(n.namespaceName)
188 > }
189
190 func NewOperatorRateBurst(
191 baseRateBurstFn RateBurst,
192 operatorRateRatio func() float64,
193 > ) *OperatorRateBurstImpl { rate_burst.go
194 > return &OperatorRateBurstImpl{
195 > operatorRateRatio: operatorRateRatio,
196 > baseRateBurstFn: baseRateBurstFn,
197 > }
198 > }
199
200 > func (c *OperatorRateBurstImpl) Rate() float64 { rate_burst.go
201 > return c.operatorRateRatio() * c.baseRateBurstFn.Rate()
202 > }
203
204 > func (c *OperatorRateBurstImpl) Burst() int { rate_burst.go
205 > return c.baseRateBurstFn.Burst()
206 > }
go.temporal.io/server/service/history/queue_factory_base.go 79 covered LOC · 12 ranges

Open complete file

79 fx.Provide(
80 QueueSchedulerRateLimiterProvider,
81 > func(tqm persistence.HistoryTaskQueueManager) queues.QueueWriter { queue_factory_base.go
82 > return tqm
83 > },
84 queues.NewDLQWriter,
85 fx.Annotated{
129 outboundParams outboundQueueFactoryParams,
130 config *configs.Config,
131 > ) additionalQueueFactories { queue_factory_base.go
132 > factories := []QueueFactory{}
133 > if _, ok := registry.GetCategoryByID(tasks.CategoryIDArchival); ok {
134 > factories = append(factories, NewArchivalQueueFactory(archivalParams)) queue_factory_base.go
135 > }
136 > factories = append(factories, NewOutboundQueueFactory(outboundParams)) queue_factory_base.go
137 > return additionalQueueFactories{
138 > Factories: factories,
139 > }
140 }
141
146 timeSource clock.TimeSource,
147 logger log.SnTaggedLogger,
148 > ) (queues.SchedulerRateLimiter, error) { queue_factory_base.go
149 > return queues.NewPrioritySchedulerRateLimiter(
150 > calculator.NewLoggedNamespaceCalculator(
151 > shard.NewOwnershipAwareNamespaceQuotaCalculator(
152 > ownershipBasedQuotaScaler,
153 > serviceResolver,
154 > config.TaskSchedulerNamespaceMaxQPS,
155 > config.TaskSchedulerGlobalNamespaceMaxQPS,
156 > ),
157 > log.With(logger, tag.ComponentTaskScheduler, tag.ScopeNamespace),
158 > ).GetQuota,
159 > calculator.NewLoggedCalculator(
160 > shard.NewOwnershipAwareQuotaCalculator(
161 > ownershipBasedQuotaScaler,
162 > serviceResolver,
163 > config.TaskSchedulerMaxQPS,
164 > config.TaskSchedulerGlobalMaxQPS,
165 > ),
166 > log.With(logger, tag.ComponentTaskScheduler, tag.ScopeHost),
167 > ).GetQuota,
168 > // TODO: reuse persistence rate limit calculator in PersistenceRateLimitingParamsProvider
169 > shard.NewOwnershipAwareNamespaceQuotaCalculator(
170 > ownershipBasedQuotaScaler,
171 > serviceResolver,
172 > config.PersistenceNamespaceMaxQPS,
173 > config.PersistenceGlobalNamespaceMaxQPS,
174 > ).GetQuota,
175 > shard.NewOwnershipAwareQuotaCalculator(
176 > ownershipBasedQuotaScaler,
177 > serviceResolver,
178 > config.PersistenceMaxQPS,
179 > config.PersistenceGlobalMaxQPS,
180 > ).GetQuota,
181 > )
182 > }
183
184 func QueueFactoryLifetimeHooks(
185 params QueueFactoriesLifetimeHookParams,
187 > params.Lifecycle.Append(
188 > fx.Hook{
189 > OnStart: func(context.Context) error {
190 > for _, factory := range params.Factories { queue_factory_base.go
191 > factory.Start()
192 > }
193 > return nil
194 },
195 > OnStop: func(context.Context) error { queue_factory_base.go
196 > for _, factory := range params.Factories {
197 > factory.Stop()
198 > }
199 > return nil
200 },
201 },
203 }
204
205 > func (f *QueueFactoryBase) Start() { queue_factory_base.go
206 > if f.HostScheduler != nil {
207 > f.HostScheduler.Start()
208 > }
209 }
210
211 > func (f *QueueFactoryBase) Stop() { queue_factory_base.go
212 > if f.HostScheduler != nil {
213 > f.HostScheduler.Stop()
214 > }
215 }
216
219 persistenceMaxRPS dynamicconfig.IntPropertyFn,
220 persistenceMaxRPSRatio float64,
221 > ) quotas.RateFn { queue_factory_base.go
222 > // TODO: reuse persistence rate limit calculator in PersistenceRateLimitingParamsProvider
223 >
224 > return func() float64 {
225 > if maxPollHostRps := hostRPS(); maxPollHostRps > 0 {
226 return float64(maxPollHostRps)
227 }
228
229 > if pMaxRPS := persistenceMaxRPS(); pMaxRPS > 0 { queue_factory_base.go
230 > // ensure queue loading won't consume all persistence tokens
231 > // especially upon host restart when we need to perform a load
232 > // for all shards
233 > return float64(pMaxRPS) * persistenceMaxRPSRatio
234 > }
235
236 // persistenceMaxQPS=0 means "unlimited" — use a high default to avoid
go.temporal.io/server/common/testing/await/require_ctx.go 78 covered LOC · 28 ranges

Open complete file

40 const defaultHardDeadlockTimeout = 10 * time.Second
41
42 > func hardDeadlockTimeout() time.Duration { require_ctx.go
43 > if s := os.Getenv(hardDeadlockTimeoutEnvVar); s != "" {
44 if d, err := time.ParseDuration(s); err == nil {
45 return d
46 }
47 }
48 > return defaultHardDeadlockTimeout require_ctx.go
49 }
50
74 misuseHint string,
75 cancellable bool,
76 > ) { require_ctx.go
77 > tb.Helper()
78 >
79 > // Skip if the test already failed — no point polling.
80 > if tb.Failed() {
81 tb.Logf("%s: skipping (test already failed)", funcName)
82 return
83 }
84 // Guard: context.WithDeadline panics on a nil parent.
85 > if parentCtx == nil { require_ctx.go
86 tb.Fatalf("%s: nil context", funcName)
87 return
88 }
89
90 > deadline := time.Now().Add(cfg.totalTimeout) require_ctx.go
91 >
92 > // Cap at the parent context's deadline if it's earlier than our timeout.
93 > if parentDeadline, hasDeadline := parentCtx.Deadline(); hasDeadline && parentDeadline.Before(deadline) {
94 deadline = parentDeadline
95 }
97 // Cap at the test's deadline if it's earlier than our deadline.
98 // Ideally, the parent context already accounts for the test's deadline - but we are being defensive.
99 > if d, ok := tb.(interface{ Deadline() (time.Time, bool) }); ok { require_ctx.go
100 > if testDeadline, hasDeadline := d.Deadline(); hasDeadline && testDeadline.Before(deadline) { require_ctx.go
101 deadline = testDeadline
102 }
103 }
104
105 > effectiveTimeout := max(0, time.Until(deadline)) require_ctx.go
106 > awaitCtx, awaitCancel := context.WithDeadline(parentCtx, deadline)
107 > defer awaitCancel()
108 >
109 > report := timeoutReport{effectiveTimeout: effectiveTimeout}
110 >
111 > for {
112 > // Parent context was canceled while we were sleeping (not our deadline).
113 > if err := awaitCtx.Err(); err != nil && !deadlineReached(deadline) {
114 report.reportAttemptErrors(tb)
115 tb.Fatalf("%s: context canceled before condition was satisfied: %v", funcName, err)
117 }
118
119 > report.nextPoll() require_ctx.go
120 >
121 > // Per-attempt context: bounded by the configured attempt timeout and
122 > // further capped by the overall awaitCtx.
123 > attemptCtx, attemptCancel := context.WithTimeout(awaitCtx, cfg.attemptTimeout)
124 > t := &T{tb: tb, ctx: attemptCtx}
125 >
126 > // Run attempt.
127 > res := runAttempt(t, condition, attemptCancel, funcName, cancellable)
128 > attemptCancel()
129 > if res.panicVal != nil {
130 panic(res.panicVal) // propagate to caller
131 }
132 > if res.deadlocked { require_ctx.go
133 report.reportAttemptErrors(tb)
134 if cancellable {
141 return
142 }
143 > report.recordErrors(t.errors) require_ctx.go
144 >
145 > // Attempt-timeout expiry: attemptCtx is done but awaitCtx is not.
146 > // Record nothing special - the attempt's recorded errors (if any)
147 > // already describe what went wrong; otherwise we just retry.
148 > attemptHitOwnTimeout := attemptCtx.Err() == context.DeadlineExceeded && awaitCtx.Err() == nil
149 > if attemptHitOwnTimeout {
150 report.recordAttemptTimeout()
151 }
152
153 // Check misuse where the real test failed instead of just the attempt.
154 > if tb.Failed() { require_ctx.go
155 tb.Fatalf("%s: the test was marked failed directly — %s", funcName, misuseHint)
156 return
158
159 // Parent context was canceled during the attempt (not our deadline).
160 > if err := awaitCtx.Err(); err != nil && !deadlineReached(deadline) { require_ctx.go
161 report.reportAttemptErrors(tb)
162 tb.Fatalf("%s: context canceled before condition was satisfied: %v", funcName, err)
165
166 // Our deadline expired.
167 > if deadlineReached(deadline) { require_ctx.go
168 report.reportTimeout(tb, funcName, cfg.timeoutMsg)
169 return
171
172 // Success: attempt completed without failures.
173 > if !res.stopped && !t.Failed() && !attemptHitOwnTimeout { require_ctx.go
174 > return require_ctx.go
175 > }
176
177 // Wait for pollInterval, or context is canceled or deadline is reached.
178 > sleep(awaitCtx, deadline, cfg.pollInterval) require_ctx.go
179 }
180 }
211 funcName string,
212 cancellable bool,
213 > ) attemptResult { require_ctx.go
214 > done := make(chan attemptResult, 1)
215 >
216 > go func() {
217 > completed := false
218 > defer func() {
219 > if r := recover(); r != nil { require_ctx.go
220 if _, ok := r.(attemptFailed); ok {
221 done <- attemptResult{stopped: true}
227 // recover returned nil: either normal return (completed=true) or
228 // runtime.Goexit (completed=false; Goexit is not a panic).
229 > done <- attemptResult{stopped: !completed} require_ctx.go
230 }()
231 > condition(t) require_ctx.go
232 > completed = true
233 }()
234
235 > if cancellable { require_ctx.go
236 // Soft phase: wait for the condition, our soft timer, or parent cancel.
237 softTimer := time.NewTimer(softDeadlockTimeout())
255
256 // Hard phase: wait for the condition or the hard timer.
257 > hardTimer := time.NewTimer(hardDeadlockTimeout()) require_ctx.go
258 > defer hardTimer.Stop()
259 >
260 > select {
261 > case r := <-done: require_ctx.go
262 > return r
263 case <-hardTimer.C:
264 return attemptResult{deadlocked: true}
266 }
267
268 > func sleep(ctx context.Context, deadline time.Time, pollInterval time.Duration) { require_ctx.go
269 > remaining := time.Until(deadline)
270 > if remaining < pollInterval {
271 pollInterval = remaining
272 }
273
274 > timer := time.NewTimer(pollInterval) require_ctx.go
275 > defer timer.Stop()
276 >
277 > select {
278 case <-ctx.Done():
279 > case <-timer.C: require_ctx.go
280 }
281 }
282
283 > func deadlineReached(deadline time.Time) bool { require_ctx.go
284 > return !time.Now().Before(deadline)
285 > }
go.temporal.io/server/service/history/service.go 78 covered LOC · 13 ranges

Open complete file

50 healthServer *health.Server,
51 chasmRegistry *chasm.Registry,
52 > ) *Service { service.go
53 > return &Service{
54 > server: server,
55 > handler: handler,
56 > visibilityManager: visibilityMgr,
57 > config: serviceConfig,
58 > logger: logger,
59 > grpcListener: grpcListener,
60 > membershipMonitor: membershipMonitor,
61 > metricsHandler: metricsHandler,
62 > healthServer: healthServer,
63 > chasmRegistry: chasmRegistry,
64 > }
65 > }
66
67 // Start starts the service
68 > func (s *Service) Start() { service.go
69 > s.logger.Info("history starting")
70 >
71 > metrics.RestartCount.With(s.metricsHandler).Record(1)
72 >
73 > s.handler.Start()
74 >
75 > historyservice.RegisterHistoryServiceServer(s.server, s.handler)
76 > healthpb.RegisterHealthServer(s.server, s.healthServer)
77 > s.chasmRegistry.RegisterServices(s.server)
78 >
79 > // start as NOT_SERVING, update to SERVING after initial shards acquired
80 > s.healthServer.SetServingStatus(serviceName, healthpb.HealthCheckResponse_NOT_SERVING)
81 > readinessCtx, readinessCancel := context.WithCancel(context.Background())
82 > s.readinessCancel = readinessCancel
83 > go func() {
84 > if s.handler.controller.InitialShardsAcquired(readinessCtx) == nil {
85 > // add a few seconds for stabilization
86 > if util.InterruptibleSleep(readinessCtx, 5*time.Second) == nil {
87 s.healthServer.SetServingStatus(serviceName, healthpb.HealthCheckResponse_SERVING)
88 }
90 }()
91
92 > reflection.Register(s.server) service.go
93 >
94 > go func() {
95 > s.logger.Info("Starting to serve on history listener")
96 > if err := s.server.Serve(s.grpcListener); err != nil {
97 s.logger.Fatal("Failed to serve on history listener", tag.Error(err))
98 }
101 // As soon as we join membership, other hosts will send requests for shards that we own,
102 // so we should try to start this after starting the gRPC server.
103 > go func() { service.go
104 > if delay := s.config.StartupMembershipJoinDelay(); delay > 0 {
105 // In some situations, like rolling upgrades of the history service,
106 // pausing before joining membership can help separate the shard movement
110 time.Sleep(delay)
111 }
112 > s.membershipMonitor.Start() service.go
113 }()
114 }
115
116 // Stop stops the service
117 > func (s *Service) Stop() { service.go
118 > s.readinessCancel()
119 >
120 > // remove self from membership ring and wait for traffic to drain
121 > var err error
122 > var waitTime time.Duration
123 > if align := s.config.AlignMembershipChange(); align > 0 {
124 propagation := s.membershipMonitor.ApproximateMaxPropagationTime()
125 asOf := util.NextAlignedTime(time.Now().Add(propagation), align)
126 s.logger.Info("ShutdownHandler: Evicting self from membership ring as of", tag.Timestamp(asOf))
127 waitTime, err = s.membershipMonitor.EvictSelfAt(asOf)
128 > } else { service.go
129 > s.logger.Info("ShutdownHandler: Evicting self from membership ring immediately")
130 > err = s.membershipMonitor.EvictSelf()
131 > }
132 > if err != nil {
133 s.logger.Error("ShutdownHandler: Failed to evict self from membership ring", tag.Error(err))
134 }
135 > s.healthServer.SetServingStatus(serviceName, healthpb.HealthCheckResponse_NOT_SERVING) service.go
136 >
137 > s.logger.Info("ShutdownHandler: Waiting for drain")
138 > if waitTime > 0 {
139 time.Sleep(
140 waitTime + // wait for membership change
142 s.config.ShardFinalizerTimeout(), // and then take this long to run a finalizer
143 )
144 > } else { service.go
145 > time.Sleep(s.config.ShutdownDrainDuration())
146 > }
147
148 > enableCloseInboundReplicationStreamOnShutdown := s.config.EnableCloseInboundReplicationStreamOnShutdown() service.go
149 > // When enabled, stop handler components (including the replication stream monitor) before
150 > // waiting for gRPC handlers to return. This signals inbound stream senders on the peer to
151 > // stop, allowing their handler goroutines to unblock and return cleanly before GracefulStop.
152 > // Without this, those goroutines block indefinitely and the gRPC server falls back to a
153 > // forceful Stop(), causing unclean H2 teardowns on the peer.
154 > // Guarded by feature flag so the ordering change can be reverted if needed.
155 > if enableCloseInboundReplicationStreamOnShutdown {
156 > s.logger.Info("ShutdownHandler: Initiating handler shutdown")
157 > s.handler.Stop()
158 > } else {
159 s.logger.Info("ShutdownHandler: Initiating shardController shutdown")
160 s.handler.controller.Stop()
162
163 // All grpc handlers should be cancelled now. Give them a little time to return.
164 > t := time.AfterFunc(2*time.Second, func() { service.go
165 s.logger.Info("ShutdownHandler: Drain time expired, stopping all traffic")
166 s.server.Stop()
167 })
168 > s.server.GracefulStop() service.go
169 > t.Stop()
170 > if !enableCloseInboundReplicationStreamOnShutdown {
171 s.handler.Stop()
172 }
173 > s.visibilityManager.Close() service.go
174 >
175 > s.logger.Info("history stopped")
176 }
go.temporal.io/server/api/persistence/v1/namespaces.pb.go 77 covered LOC · 18 ranges

Open complete file

42 }
43
44 > func (x *NamespaceDetail) Reset() { namespaces.pb.go
45 > *x = NamespaceDetail{}
46 > mi := &file_temporal_server_api_persistence_v1_namespaces_proto_msgTypes[0]
47 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
48 > ms.StoreMessageInfo(mi)
49 > }
50
51 func (x *NamespaceDetail) String() string {
55 func (*NamespaceDetail) ProtoMessage() {}
56
57 > func (x *NamespaceDetail) ProtoReflect() protoreflect.Message { namespaces.pb.go
58 > mi := &file_temporal_server_api_persistence_v1_namespaces_proto_msgTypes[0]
59 > if x != nil {
60 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
61 > if ms.LoadMessageInfo() == nil {
62 > ms.StoreMessageInfo(mi)
63 > }
64 > return ms
65 }
66 return mi.MessageOf(x)
146 func (*NamespaceInfo) ProtoMessage() {}
147
148 > func (x *NamespaceInfo) ProtoReflect() protoreflect.Message { namespaces.pb.go
149 > mi := &file_temporal_server_api_persistence_v1_namespaces_proto_msgTypes[1]
150 > if x != nil {
151 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) namespaces.pb.go
152 > if ms.LoadMessageInfo() == nil {
153 > ms.StoreMessageInfo(mi)
154 > }
155 > return ms
156 }
157 > return mi.MessageOf(x) namespaces.pb.go
158 }
159
233 func (*NamespaceConfig) ProtoMessage() {}
234
235 > func (x *NamespaceConfig) ProtoReflect() protoreflect.Message { namespaces.pb.go
236 > mi := &file_temporal_server_api_persistence_v1_namespaces_proto_msgTypes[2]
237 > if x != nil {
238 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) namespaces.pb.go
239 > if ms.LoadMessageInfo() == nil {
240 > ms.StoreMessageInfo(mi)
241 > }
242 > return ms
243 }
244 > return mi.MessageOf(x) namespaces.pb.go
245 }
246
264 }
265
266 > func (x *NamespaceConfig) GetBadBinaries() *v11.BadBinaries { namespaces.pb.go
267 > if x != nil {
268 > return x.BadBinaries
269 > }
270 return nil
271 }
336 func (*NamespaceReplicationConfig) ProtoMessage() {}
337
338 > func (x *NamespaceReplicationConfig) ProtoReflect() protoreflect.Message { namespaces.pb.go
339 > mi := &file_temporal_server_api_persistence_v1_namespaces_proto_msgTypes[3]
340 > if x != nil {
341 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) namespaces.pb.go
342 > if ms.LoadMessageInfo() == nil {
343 > ms.StoreMessageInfo(mi)
344 > }
345 > return ms
346 }
347 > return mi.MessageOf(x) namespaces.pb.go
348 }
349
367 }
368
369 > func (x *NamespaceReplicationConfig) GetState() v1.ReplicationState { namespaces.pb.go
370 > if x != nil {
371 > return x.State
372 > }
373 return v1.ReplicationState(0)
374 }
375
376 > func (x *NamespaceReplicationConfig) GetFailoverHistory() []*FailoverStatus { namespaces.pb.go
377 > if x != nil {
378 > return x.FailoverHistory
379 > }
380 return nil
381 }
403 func (*FailoverStatus) ProtoMessage() {}
404
405 > func (x *FailoverStatus) ProtoReflect() protoreflect.Message { namespaces.pb.go
406 > mi := &file_temporal_server_api_persistence_v1_namespaces_proto_msgTypes[4]
407 > if x != nil {
408 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
409 if ms.LoadMessageInfo() == nil {
536 }
537
538 > func init() { file_temporal_server_api_persistence_v1_namespaces_proto_init() } namespaces.pb.go
539 > func file_temporal_server_api_persistence_v1_namespaces_proto_init() {
540 > if File_temporal_server_api_persistence_v1_namespaces_proto != nil {
541 return
542 }
543 > type x struct{} namespaces.pb.go
544 > out := protoimpl.TypeBuilder{
545 > File: protoimpl.DescBuilder{
546 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
547 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_namespaces_proto_rawDesc), len(file_temporal_server_api_persistence_v1_namespaces_proto_rawDesc)),
548 > NumEnums: 0,
549 > NumMessages: 8,
550 > NumExtensions: 0,
551 > NumServices: 0,
552 > },
553 > GoTypes: file_temporal_server_api_persistence_v1_namespaces_proto_goTypes,
554 > DependencyIndexes: file_temporal_server_api_persistence_v1_namespaces_proto_depIdxs,
555 > MessageInfos: file_temporal_server_api_persistence_v1_namespaces_proto_msgTypes,
556 > }.Build()
557 > File_temporal_server_api_persistence_v1_namespaces_proto = out.File
558 > file_temporal_server_api_persistence_v1_namespaces_proto_goTypes = nil
559 > file_temporal_server_api_persistence_v1_namespaces_proto_depIdxs = nil
560 }
go.temporal.io/server/service/worker/deletenamespace/fx.go 77 covered LOC · 10 ranges

Open complete file

57 func newComponent(
58 params componentParams,
59 > ) workercommon.WorkerComponent { fx.go
60 > return &deleteNamespaceComponent{
61 > atWorkerCfg: dynamicconfig.WorkerDeleteNamespaceActivityLimits.Get(params.DynamicCollection)(),
62 > visibilityManager: params.VisibilityManager,
63 > metadataManager: params.MetadataManager,
64 > clusterMetadata: params.ClusterMetadata,
65 > nexusEndpointManager: params.NexusEndpointManager,
66 > historyClient: params.HistoryClient,
67 > metricsHandler: params.MetricsHandler,
68 > logger: params.Logger,
69 > protectedNamespaces: dynamicconfig.ProtectedNamespaces.Get(params.DynamicCollection),
70 > allowDeleteNamespaceIfNexusEndpointTarget: dynamicconfig.AllowDeleteNamespaceIfNexusEndpointTarget.Get(params.DynamicCollection),
71 > nexusEndpointListDefaultPageSize: dynamicconfig.NexusEndpointListDefaultPageSize.Get(params.DynamicCollection),
72 > deleteActivityRPS: dynamicconfig.DeleteNamespaceDeleteActivityRPS.Subscribe(params.DynamicCollection),
73 > useChasmDeleteExecution: dynamicconfig.DeleteNamespaceUseChasmDeleteExecution.Get(params.DynamicCollection),
74 > namespaceCacheRefreshInterval: dynamicconfig.NamespaceCacheRefreshInterval.Get(params.DynamicCollection),
75 > }
76 > }
77
78 > func (wc *deleteNamespaceComponent) RegisterWorkflow(registry sdkworker.Registry) { fx.go
79 > registry.RegisterWorkflowWithOptions(DeleteNamespaceWorkflow, workflow.RegisterOptions{Name: WorkflowName})
80 > registry.RegisterActivity(wc.deleteNamespaceLocalActivities())
81 >
82 > registry.RegisterWorkflowWithOptions(reclaimresources.ReclaimResourcesWorkflow, workflow.RegisterOptions{Name: reclaimresources.WorkflowName})
83 > registry.RegisterActivity(wc.reclaimResourcesLocalActivities())
84 >
85 > registry.RegisterWorkflowWithOptions(deleteexecutions.DeleteExecutionsWorkflow, workflow.RegisterOptions{Name: deleteexecutions.WorkflowName})
86 > registry.RegisterActivity(wc.deleteExecutionsLocalActivities())
87 > }
88
89 > func (wc *deleteNamespaceComponent) DedicatedWorkflowWorkerOptions() *workercommon.DedicatedWorkerOptions { fx.go
90 > // use default worker
91 > return nil
92 > }
93
94 > func (wc *deleteNamespaceComponent) RegisterActivities(registry sdkworker.Registry) { fx.go
95 > registry.RegisterActivity(wc.reclaimResourcesActivities())
96 > registry.RegisterActivity(wc.deleteExecutionsActivities())
97 > }
98
99 > func (wc *deleteNamespaceComponent) DedicatedActivityWorkerOptions() *workercommon.DedicatedWorkerOptions { fx.go
100 > return &workercommon.DedicatedWorkerOptions{
101 > TaskQueue: primitives.DeleteNamespaceActivityTQ,
102 > Options: sdkworker.Options{
103 > BackgroundActivityContext: headers.SetCallerType(context.Background(), headers.CallerTypePreemptable),
104 > MaxConcurrentActivityExecutionSize: wc.atWorkerCfg.MaxConcurrentActivityExecutionSize,
105 > TaskQueueActivitiesPerSecond: wc.atWorkerCfg.TaskQueueActivitiesPerSecond,
106 > WorkerActivitiesPerSecond: wc.atWorkerCfg.WorkerActivitiesPerSecond,
107 > MaxConcurrentActivityTaskPollers: wc.atWorkerCfg.MaxConcurrentActivityTaskPollers,
108 > },
109 > }
110 > }
111
112 > func (wc *deleteNamespaceComponent) deleteNamespaceLocalActivities() *localActivities { fx.go
113 > return newLocalActivities(
114 > wc.metadataManager,
115 > wc.clusterMetadata,
116 > wc.nexusEndpointManager,
117 > wc.logger,
118 > wc.protectedNamespaces,
119 > wc.allowDeleteNamespaceIfNexusEndpointTarget,
120 > wc.nexusEndpointListDefaultPageSize)
121 > }
122
123 > func (wc *deleteNamespaceComponent) reclaimResourcesActivities() *reclaimresources.Activities { fx.go
124 > return reclaimresources.NewActivities(wc.visibilityManager, wc.logger)
125 > }
126
127 > func (wc *deleteNamespaceComponent) reclaimResourcesLocalActivities() *reclaimresources.LocalActivities { fx.go
128 > return reclaimresources.NewLocalActivities(wc.visibilityManager, wc.metadataManager, wc.namespaceCacheRefreshInterval, wc.logger)
129 > }
130
131 > func (wc *deleteNamespaceComponent) deleteExecutionsActivities() *deleteexecutions.Activities { fx.go
132 > return deleteexecutions.NewActivities(
133 > wc.visibilityManager,
134 > wc.historyClient,
135 > wc.deleteActivityRPS,
136 > wc.useChasmDeleteExecution,
137 > wc.metricsHandler,
138 > wc.logger,
139 > )
140 > }
141
142 > func (wc *deleteNamespaceComponent) deleteExecutionsLocalActivities() *deleteexecutions.LocalActivities { fx.go
143 > return deleteexecutions.NewLocalActivities(wc.visibilityManager, wc.metricsHandler, wc.logger)
144 > }
go.temporal.io/server/client/matching/metric_client.go 75 covered LOC · 20 ranges

Open complete file

33 logger log.Logger,
34 throttledLogger log.Logger,
35 > ) matchingservice.MatchingServiceClient { metric_client.go
36 > return &metricClient{
37 > client: client,
38 > metricsHandler: metricsHandler,
39 > logger: logger,
40 > throttledLogger: throttledLogger,
41 > }
42 > }
43
44 func (c *metricClient) AddActivityTask(
66 request *matchingservice.AddWorkflowTaskRequest,
67 opts ...grpc.CallOption,
68 > ) (_ *matchingservice.AddWorkflowTaskResponse, retError error) { metric_client.go
69 >
70 > scope, stopwatch := c.startMetricsRecording(ctx, metrics.MatchingClientAddWorkflowTaskScope)
71 > defer func() {
72 > c.finishMetricsRecording(scope, stopwatch, retError)
73 > }()
74
75 > c.emitForwardedSourceStats( metric_client.go
76 > scope,
77 > request.GetForwardInfo().GetSourcePartition(),
78 > request.TaskQueue,
79 > )
80 >
81 > return c.client.AddWorkflowTask(ctx, request, opts...)
82 }
83
86 request *matchingservice.PollActivityTaskQueueRequest,
87 opts ...grpc.CallOption,
88 > ) (_ *matchingservice.PollActivityTaskQueueResponse, retError error) { metric_client.go
89 >
90 > scope, stopwatch := c.startMetricsRecording(ctx, metrics.MatchingClientPollActivityTaskQueueScope)
91 > defer func() {
92 > c.finishMetricsRecording(scope, stopwatch, retError) metric_client.go
93 > }()
94
95 > if request.PollRequest != nil { metric_client.go
96 > c.emitForwardedSourceStats(
97 > scope,
98 > request.GetForwardedSource(),
99 > request.PollRequest.TaskQueue,
100 > )
101 > }
102
103 > return c.client.PollActivityTaskQueue(ctx, request, opts...) metric_client.go
104 }
105
108 request *matchingservice.PollWorkflowTaskQueueRequest,
109 opts ...grpc.CallOption,
110 > ) (_ *matchingservice.PollWorkflowTaskQueueResponse, retError error) { metric_client.go
111 >
112 > scope, stopwatch := c.startMetricsRecording(ctx, metrics.MatchingClientPollWorkflowTaskQueueScope)
113 > defer func() {
114 > c.finishMetricsRecording(scope, stopwatch, retError)
115 > }()
116
117 > if request.PollRequest != nil { metric_client.go
118 > c.emitForwardedSourceStats(
119 > scope,
120 > request.GetForwardedSource(),
121 > request.PollRequest.TaskQueue,
122 > )
123 > }
124
125 > return c.client.PollWorkflowTaskQueue(ctx, request, opts...) metric_client.go
126 }
127
190 forwardedFrom string,
191 taskQueue *taskqueuepb.TaskQueue,
192 > ) { metric_client.go
193 > if taskQueue == nil {
194 return
195 }
196
197 > switch { metric_client.go
198 case forwardedFrom != "":
199 metrics.MatchingClientForwardedCounter.With(metricsHandler).Record(1)
200 > default: metric_client.go
201 > // TODO: confirmed from metrics, it seems this error does happen at the moment...
202 > // it means some mangled name come here; need to check why
203 > _, err := tqid.NewTaskQueueFamily("", taskQueue.GetName())
204 > if err != nil {
205 c.logger.Info("invalid tq name", tag.Error(err), tag.String("proto", taskQueue.GetName()))
206 metrics.MatchingClientInvalidTaskQueueName.With(metricsHandler).Record(1)
212 ctx context.Context,
213 operation string,
214 > ) (metrics.Handler, time.Time) { metric_client.go
215 > caller := headers.GetCallerInfo(ctx).CallerName
216 > handler := c.metricsHandler.WithTags(metrics.OperationTag(operation), metrics.NamespaceTag(caller), metrics.ServiceRoleTag(metrics.MatchingRoleTagValue))
217 > metrics.ClientRequests.With(handler).Record(1)
218 > return handler, time.Now().UTC()
219 > }
220
221 func (c *metricClient) finishMetricsRecording(
223 startTime time.Time,
224 err error,
225 > ) { metric_client.go
226 > if err != nil {
227 > switch err.(type) {
228 case *serviceerrors.StickyWorkerUnavailable,
229 *serviceerror.Canceled,
234 *serviceerror.NewerBuildExists,
235 *serviceerror.WorkflowExecutionAlreadyStarted,
236 > *serviceerror.ResourceExhausted: metric_client.go
237 // noop - not interest and too many logs
238 > default: metric_client.go
239 > c.throttledLogger.Info("matching client encountered error", tag.Error(err), tag.ServiceErrorType(err))
240 }
241 > metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) metric_client.go
242 }
243 > metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) metric_client.go
244 }
245
257 // Stop forwards a deterministic shutdown to the wrapped client. See
258 // clientImpl.Stop. It is only invoked via client.Bean.Close.
259 > func (c *metricClient) Stop() { metric_client.go
260 > if s, ok := c.client.(interface{ Stop() }); ok {
261 > s.Stop()
262 > }
263 }
go.temporal.io/server/api/historyservice/v1/service_grpc.pb.go 74 covered LOC · 22 ranges

Open complete file

396 }
397
398 > func NewHistoryServiceClient(cc grpc.ClientConnInterface) HistoryServiceClient { service_grpc.pb.go
399 > return &historyServiceClient{cc}
400 > }
401
402 > func (c *historyServiceClient) StartWorkflowExecution(ctx context.Context, in *StartWorkflowExecutionRequest, opts ...grpc.CallOption) (*StartWorkflowExecutionResponse, error) { service_grpc.pb.go
403 > out := new(StartWorkflowExecutionResponse)
404 > err := c.cc.Invoke(ctx, HistoryService_StartWorkflowExecution_FullMethodName, in, out, opts...)
405 > if err != nil {
406 return nil, err
407 }
408 > return out, nil service_grpc.pb.go
409 }
410
436 }
437
438 > func (c *historyServiceClient) RecordWorkflowTaskStarted(ctx context.Context, in *RecordWorkflowTaskStartedRequest, opts ...grpc.CallOption) (*RecordWorkflowTaskStartedResponse, error) { service_grpc.pb.go
439 > out := new(RecordWorkflowTaskStartedResponse)
440 > err := c.cc.Invoke(ctx, HistoryService_RecordWorkflowTaskStarted_FullMethodName, in, out, opts...)
441 > if err != nil {
442 return nil, err
443 }
444 > return out, nil service_grpc.pb.go
445 }
446
454 }
455
456 > func (c *historyServiceClient) RespondWorkflowTaskCompleted(ctx context.Context, in *RespondWorkflowTaskCompletedRequest, opts ...grpc.CallOption) (*RespondWorkflowTaskCompletedResponse, error) { service_grpc.pb.go
457 > out := new(RespondWorkflowTaskCompletedResponse)
458 > err := c.cc.Invoke(ctx, HistoryService_RespondWorkflowTaskCompleted_FullMethodName, in, out, opts...)
459 > if err != nil {
460 return nil, err
461 }
462 > return out, nil service_grpc.pb.go
463 }
464
899 }
900
901 > func (c *historyServiceClient) GetWorkflowExecutionHistory(ctx context.Context, in *GetWorkflowExecutionHistoryRequest, opts ...grpc.CallOption) (*GetWorkflowExecutionHistoryResponse, error) { service_grpc.pb.go
902 > out := new(GetWorkflowExecutionHistoryResponse)
903 > err := c.cc.Invoke(ctx, HistoryService_GetWorkflowExecutionHistory_FullMethodName, in, out, opts...)
904 > if err != nil {
905 return nil, err
906 }
907 > return out, nil service_grpc.pb.go
908 }
909
1652 }
1653
1654 > func RegisterHistoryServiceServer(s grpc.ServiceRegistrar, srv HistoryServiceServer) { service_grpc.pb.go
1655 > s.RegisterService(&HistoryService_ServiceDesc, srv)
1656 > }
1657
1658 > func _HistoryService_StartWorkflowExecution_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { service_grpc.pb.go
1659 > in := new(StartWorkflowExecutionRequest)
1660 > if err := dec(in); err != nil {
1661 return nil, err
1662 }
1663 > if interceptor == nil { service_grpc.pb.go
1664 return srv.(HistoryServiceServer).StartWorkflowExecution(ctx, in)
1665 }
1666 > info := &grpc.UnaryServerInfo{ service_grpc.pb.go
1667 > Server: srv,
1668 > FullMethod: HistoryService_StartWorkflowExecution_FullMethodName,
1669 > }
1670 > handler := func(ctx context.Context, req interface{}) (interface{}, error) {
1671 > return srv.(HistoryServiceServer).StartWorkflowExecution(ctx, req.(*StartWorkflowExecutionRequest))
1672 > }
1673 > return interceptor(ctx, in, info, handler)
1674 }
1675
1728 }
1729
1730 > func _HistoryService_RecordWorkflowTaskStarted_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { service_grpc.pb.go
1731 > in := new(RecordWorkflowTaskStartedRequest)
1732 > if err := dec(in); err != nil {
1733 return nil, err
1734 }
1735 > if interceptor == nil { service_grpc.pb.go
1736 return srv.(HistoryServiceServer).RecordWorkflowTaskStarted(ctx, in)
1737 }
1738 > info := &grpc.UnaryServerInfo{ service_grpc.pb.go
1739 > Server: srv,
1740 > FullMethod: HistoryService_RecordWorkflowTaskStarted_FullMethodName,
1741 > }
1742 > handler := func(ctx context.Context, req interface{}) (interface{}, error) {
1743 > return srv.(HistoryServiceServer).RecordWorkflowTaskStarted(ctx, req.(*RecordWorkflowTaskStartedRequest))
1744 > }
1745 > return interceptor(ctx, in, info, handler)
1746 }
1747
1764 }
1765
1766 > func _HistoryService_RespondWorkflowTaskCompleted_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { service_grpc.pb.go
1767 > in := new(RespondWorkflowTaskCompletedRequest)
1768 > if err := dec(in); err != nil {
1769 return nil, err
1770 }
1771 > if interceptor == nil { service_grpc.pb.go
1772 return srv.(HistoryServiceServer).RespondWorkflowTaskCompleted(ctx, in)
1773 }
1774 > info := &grpc.UnaryServerInfo{ service_grpc.pb.go
1775 > Server: srv,
1776 > FullMethod: HistoryService_RespondWorkflowTaskCompleted_FullMethodName,
1777 > }
1778 > handler := func(ctx context.Context, req interface{}) (interface{}, error) {
1779 > return srv.(HistoryServiceServer).RespondWorkflowTaskCompleted(ctx, req.(*RespondWorkflowTaskCompletedRequest))
1780 > }
1781 > return interceptor(ctx, in, info, handler)
1782 }
1783
2618 }
2619
2620 > func _HistoryService_GetWorkflowExecutionHistory_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { service_grpc.pb.go
2621 > in := new(GetWorkflowExecutionHistoryRequest)
2622 > if err := dec(in); err != nil {
2623 return nil, err
2624 }
2625 > if interceptor == nil { service_grpc.pb.go
2626 return srv.(HistoryServiceServer).GetWorkflowExecutionHistory(ctx, in)
2627 }
2628 > info := &grpc.UnaryServerInfo{ service_grpc.pb.go
2629 > Server: srv,
2630 > FullMethod: HistoryService_GetWorkflowExecutionHistory_FullMethodName,
2631 > }
2632 > handler := func(ctx context.Context, req interface{}) (interface{}, error) {
2633 > return srv.(HistoryServiceServer).GetWorkflowExecutionHistory(ctx, req.(*GetWorkflowExecutionHistoryRequest))
2634 > }
2635 > return interceptor(ctx, in, info, handler)
2636 }
2637
go.temporal.io/server/common/deadlock/deadlock.go 74 covered LOC · 11 ranges

Open complete file

64 }
65
66 > func NewDeadlockDetector(params params) *deadlockDetector { deadlock.go
67 > return &deadlockDetector{
68 > logger: params.Logger,
69 > healthServer: params.HealthServer,
70 > metricsHandler: params.MetricsHandler.WithTags(metrics.OperationTag(metrics.DeadlockDetectorScope)),
71 > config: config{
72 > DumpGoroutines: dynamicconfig.DeadlockDumpGoroutines.Get(params.Collection),
73 > FailHealthCheck: dynamicconfig.DeadlockFailHealthCheck.Get(params.Collection),
74 > AbortProcess: dynamicconfig.DeadlockAbortProcess.Get(params.Collection),
75 > Interval: dynamicconfig.DeadlockInterval.Get(params.Collection),
76 > MaxWorkersPerRoot: dynamicconfig.DeadlockMaxWorkersPerRoot.Get(params.Collection),
77 > },
78 > roots: params.Roots,
79 > }
80 > }
81
82 > func (dd *deadlockDetector) Start() error { deadlock.go
83 > for _, root := range dd.roots {
84 > pool := goro.NewAdaptivePool(
85 > clock.NewRealTimeSource(),
86 > 0,
87 > dd.config.MaxWorkersPerRoot(),
88 > 100*time.Millisecond,
89 > 10,
90 > )
91 > dd.pools = append(dd.pools, pool)
92 > loopCtx := &loopContext{
93 > dd: dd,
94 > root: root,
95 > p: pool,
96 > }
97 > dd.loops.Go(loopCtx.run)
98 > }
99 > return nil
100 }
101
102 > func (dd *deadlockDetector) Stop() error { deadlock.go
103 > for _, pool := range dd.pools {
104 > pool.Stop()
105 > }
106 > dd.loops.Cancel()
107 > // don't wait for workers to exit, they may be blocked
108 > return nil
109 }
110
151 }
152
153 > func (lc *loopContext) run(ctx context.Context) error { deadlock.go
154 > for {
155 > // ping blocks until it has passed all checks to a worker goroutine (using an
156 > // unbuffered channel).
157 > lc.ping(ctx, []pingable.Pingable{lc.root})
158 >
159 > timer := time.NewTimer(lc.dd.config.Interval())
160 > select {
161 case <-timer.C:
162 > case <-ctx.Done(): deadlock.go
163 > timer.Stop()
164 > return ctx.Err()
165 }
166 }
167 }
168
169 > func (lc *loopContext) ping(ctx context.Context, pingables []pingable.Pingable) { deadlock.go
170 > for _, pingable := range pingables {
171 > for _, check := range pingable.GetPingChecks() { deadlock.go
172 > lc.p.Do(func() { lc.check(ctx, check) })
173 }
174 }
175 }
176
177 > func (lc *loopContext) check(ctx context.Context, check pingable.Check) { deadlock.go
178 > lc.dd.logger.Debug("starting ping check", tag.Name(check.Name))
179 > startTime := time.Now().UTC()
180 > resolved := make(chan struct{})
181 >
182 > // Using AfterFunc is cheaper than creating another goroutine to be the waiter, since
183 > // we expect to always cancel it. If the go runtime is so messed up that it can't
184 > // create a goroutine, that's a bigger problem than we can handle.
185 > t := time.AfterFunc(check.Timeout, func() {
186 if ctx.Err() != nil {
187 // deadlock detector was stopped
197 lc.dd.adjustCurrent(-1)
198 })
199 > newPingables := check.Ping() deadlock.go
200 > t.Stop()
201 > if len(check.MetricsName) > 0 {
202 > lc.dd.metricsHandler.Timer(check.MetricsName).Record(time.Since(startTime)) deadlock.go
203 > }
204 > close(resolved) deadlock.go
205 >
206 > lc.dd.logger.Debug("ping check succeeded", tag.Name(check.Name))
207 >
208 > lc.ping(ctx, newPingables)
209 }
go.temporal.io/server/common/log/tag/zap_tag.go 74 covered LOC · 18 ranges

Open complete file

26 }
27
28 > func (t ZapTag) Field() zap.Field { zap_tag.go
29 > return t.field
30 > }
31
32 func (t ZapTag) Key() string {
44 }
45
46 > func NewStringTag(key string, value string) ZapTag { zap_tag.go
47 > return ZapTag{
48 > field: zap.String(key, value),
49 > }
50 > }
51
52 > func NewStringsTag(key string, value []string) ZapTag { zap_tag.go
53 > return ZapTag{
54 > field: zap.Strings(key, value),
55 > }
56 > }
57
58 // NewStringerTag returns a tag that will lazily generate the string representation
63 // These are still useful if the String() implementation is complicated, especially if
64 // you have lots of Debug-level logs that are ignored in production.
65 > func NewStringerTag(key string, value fmt.Stringer) ZapTag { zap_tag.go
66 > return ZapTag{
67 > field: zap.Stringer(key, value),
68 > }
69 > }
70
71 // NewStringersTag returns a tag that will lazily generate the string representation
82 }
83
84 > func NewInt64(key string, value int64) ZapTag { zap_tag.go
85 > return ZapTag{
86 > field: zap.Int64(key, value),
87 > }
88 > }
89
90 > func NewInt(key string, value int) ZapTag { zap_tag.go
91 > return ZapTag{
92 > field: zap.Int(key, value),
93 > }
94 > }
95
96 > func NewInt32(key string, value int32) ZapTag { zap_tag.go
97 > return ZapTag{
98 > field: zap.Int32(key, value),
99 > }
100 > }
101
102 func NewUInt32(key string, value uint32) ZapTag {
118 }
119
120 > func NewBoolTag(key string, value bool) ZapTag { zap_tag.go
121 > return ZapTag{
122 > field: zap.Bool(key, value),
123 > }
124 > }
125
126 func NewErrorTag(key string, value error) ZapTag {
130 }
131
132 > func NewDurationTag(key string, value time.Duration) ZapTag { zap_tag.go
133 > return ZapTag{
134 > field: zap.Duration(key, value),
135 > }
136 > }
137
138 func NewDurationPtrTag(key string, value *durationpb.Duration) ZapTag {
142 }
143
144 > func NewTimeTag(key string, value time.Time) ZapTag { zap_tag.go
145 > return ZapTag{
146 > field: zap.Time(key, value),
147 > }
148 > }
149
150 func NewTimePtrTag(key string, value *timestamppb.Timestamp) ZapTag {
154 }
155
156 > func NewAnyTag(key string, value any) ZapTag { zap_tag.go
157 > return ZapTag{
158 > field: zap.Any(key, value),
159 > }
160 > }
161
162 func NewBinaryTag(key string, value []byte) ZapTag {
168 // Shorter helpers (aliases for the New* functions above)
169
170 > func String(key string, value string) ZapTag { zap_tag.go
171 > return NewStringTag(key, value)
172 > }
173
174 func Strings(key string, value []string) ZapTag {
176 }
177
178 > func Stringer(key string, value fmt.Stringer) ZapTag { zap_tag.go
179 > return NewStringerTag(key, value)
180 > }
181
182 func Stringers(key string, value []fmt.Stringer) ZapTag {
184 }
185
186 > func Int64(key string, value int64) ZapTag { zap_tag.go
187 > return NewInt64(key, value)
188 > }
189
190 > func Int(key string, value int) ZapTag { zap_tag.go
191 > return NewInt(key, value)
192 > }
193
194 func Int32(key string, value int32) ZapTag {
208 }
209
210 > func Duration(key string, value time.Duration) ZapTag { zap_tag.go
211 > return NewDurationTag(key, value)
212 > }
213
214 func DurationPtr(key string, value *durationpb.Duration) ZapTag {
224 }
225
226 > func Any(key string, value any) ZapTag { zap_tag.go
227 > return NewAnyTag(key, value)
228 > }
229
230 func Binary(key string, value []byte) ZapTag {
232 }
233
234 > func Bool(key string, b bool) ZapTag { zap_tag.go
235 > return NewBoolTag(key, b)
236 > }
237
238 func Zap(field zap.Field) ZapTag {
go.temporal.io/server/service/fx.go 74 covered LOC · 12 ranges

Open complete file

55
56 var PersistenceLazyLoadedServiceResolverModule = fx.Options(
57 > fx.Provide(func() PersistenceLazyLoadedServiceResolver { fx.go
58 > return PersistenceLazyLoadedServiceResolver{
59 > Value: &atomic.Value{},
60 > }
61 > }),
62 fx.Invoke(initPersistenceLazyLoadedServiceResolver),
63 )
68 serviceResolver membership.ServiceResolver,
69 lazyLoadedServiceResolver PersistenceLazyLoadedServiceResolver,
70 > ) { fx.go
71 > lazyLoadedServiceResolver.Store(serviceResolver)
72 > logger.Info("Initialized service resolver for persistence rate limiting", tag.Service(serviceName))
73 > }
74
75 func (p PersistenceLazyLoadedServiceResolver) AvailableMemberCount() int {
91 lazyLoadedServiceResolver PersistenceLazyLoadedServiceResolver,
92 logger log.Logger,
93 > ) PersistenceRateLimitingParams { fx.go
94 > hostCalculator := calculator.NewLoggedCalculator(
95 > calculator.ClusterAwareQuotaCalculator{
96 > MemberCounter: lazyLoadedServiceResolver,
97 > PerInstanceQuota: maxQps,
98 > GlobalQuota: globalMaxQps,
99 > },
100 > log.With(logger, tag.ComponentPersistence, tag.ScopeHost),
101 > )
102 > namespaceCalculator := calculator.NewLoggedNamespaceCalculator(
103 > calculator.ClusterAwareNamespaceQuotaCalculator{
104 > MemberCounter: lazyLoadedServiceResolver,
105 > PerInstanceQuota: namespaceMaxQps,
106 > GlobalQuota: globalNamespaceMaxQps,
107 > },
108 > log.With(logger, tag.ComponentPersistence, tag.ScopeNamespace),
109 > )
110 > return PersistenceRateLimitingParams{
111 > PersistenceMaxQps: func() int {
112 > return int(hostCalculator.GetQuota())
113 > },
114 > PersistenceNamespaceMaxQps: func(namespace string) int { fx.go
115 > return int(namespaceCalculator.GetQuota(namespace))
116 > },
117 PersistencePerShardNamespaceMaxQPS: persistenceClient.PersistencePerShardNamespaceMaxQPS(perShardNamespaceMaxQps),
118 OperatorRPSRatio: persistenceClient.OperatorRPSRatio(operatorRPSRatio),
124 func GrpcServerOptionsProvider(
125 params GrpcServerOptionsParams,
126 > ) []grpc.ServerOption { fx.go
127 >
128 > grpcServerOptions, err := params.RPCFactory.GetInternodeGRPCServerOptions()
129 > if err != nil {
130 params.Logger.Fatal("creating gRPC server options failed", tag.Error(err))
131 }
132
133 > multiStats := rpc.MultiStatsHandler{} fx.go
134 > if params.TracingStatsHandler != nil {
135 multiStats = append(multiStats, params.TracingStatsHandler)
136 }
137 > if params.MetricsStatsHandler != nil { fx.go
138 > multiStats = append(multiStats, params.MetricsStatsHandler)
139 > }
140 > if len(multiStats) > 0 {
141 > grpcServerOptions = append(grpcServerOptions, grpc.StatsHandler(multiStats))
142 > }
143
144 > streamInterceptors := []grpc.StreamServerInterceptor{ fx.go
145 > params.TelemetryInterceptor.StreamIntercept,
146 > interceptor.CustomErrorStreamInterceptor,
147 > }
148 > if len(params.AdditionalStreamInterceptors) > 0 {
149 streamInterceptors = append(streamInterceptors, params.AdditionalStreamInterceptors...)
150 }
151
152 > return append( fx.go
153 > grpcServerOptions,
154 > grpc.ChainUnaryInterceptor(getUnaryInterceptors(params)...),
155 > grpc.ChainStreamInterceptor(streamInterceptors...),
156 > )
157 }
158
159 > func getUnaryInterceptors(params GrpcServerOptionsParams) []grpc.UnaryServerInterceptor { fx.go
160 > interceptors := []grpc.UnaryServerInterceptor{
161 > params.ServiceErrorInterceptor.Intercept,
162 > metrics.NewServerMetricsContextInjectorInterceptor(),
163 > metrics.NewServerMetricsTrailerPropagatorInterceptor(params.Logger),
164 > params.TelemetryInterceptor.UnaryIntercept,
165 > }
166 >
167 > interceptors = append(interceptors, params.AdditionalInterceptors...)
168 >
169 > if params.NamespaceRateLimitInterceptor != nil {
170 > interceptors = append(interceptors, params.NamespaceRateLimitInterceptor.Intercept)
171 > }
172
173 > interceptors = append(interceptors, params.RateLimitInterceptor.Intercept) fx.go
174 >
175 > if params.ContextMetadataInterceptor != nil {
176 > interceptors = append(interceptors, params.ContextMetadataInterceptor.Intercept)
177 > }
178
179 > return append(interceptors, params.RetryableInterceptor.Intercept) fx.go
180 }
go.temporal.io/server/chasm/lib/scheduler/library.go 73 covered LOC · 5 ranges

Open complete file

40 BackfillerTaskHandler *BackfillerTaskHandler,
41 MigrateToWorkflowTaskHandler *SchedulerMigrateToWorkflowTaskHandler,
42 > ) *Library { library.go
43 > return &Library{
44 > config: config,
45 > handler: handler,
46 > SchedulerIdleTaskHandler: SchedulerIdleTaskHandler,
47 > SchedulerCallbacksTaskHandler: SchedulerCallbacksTaskHandler,
48 > GeneratorTaskHandler: GeneratorTaskHandler,
49 > InvokerExecuteTaskHandler: InvokerExecuteTaskHandler,
50 > InvokerProcessBufferTaskHandler: InvokerProcessBufferTaskHandler,
51 > BackfillerTaskHandler: BackfillerTaskHandler,
52 > MigrateToWorkflowTaskHandler: MigrateToWorkflowTaskHandler,
53 > }
54 > }
55
56 > func (l *Library) Name() string { library.go
57 > return chasm.SchedulerLibraryName
58 > }
59
60 > func (l *Library) Components() []*chasm.RegistrableComponent { library.go
61 > return []*chasm.RegistrableComponent{
62 > chasm.NewRegistrableComponent[*Scheduler](
63 > chasm.SchedulerComponentName,
64 > chasm.WithBusinessIDAlias("ScheduleId"),
65 > chasm.WithSearchAttributes(
66 > executionStatusSearchAttribute,
67 > scheduleNextActionTimeSearchAttribute,
68 > scheduleIdleCloseTimeSearchAttribute,
69 > scheduleRunningWorkflowCountSearchAttribute,
70 > scheduleBufferedStartsCountSearchAttribute,
71 > ),
72 > // Exposes Tweakables to scheduler components via the CHASM context
73 > // (see tweakablesFromContext).
74 > chasm.WithContextValues(l.config.contextValues()),
75 > ),
76 > chasm.NewRegistrableComponent[*Generator]("generator"),
77 > chasm.NewRegistrableComponent[*Invoker]("invoker"),
78 > chasm.NewRegistrableComponent[*Backfiller]("backfiller"),
79 > chasm.NewRegistrableComponent[*EventLog]("eventlog"),
80 > }
81 > }
82
83 > func (l *Library) Tasks() []*chasm.RegistrableTask { library.go
84 > return []*chasm.RegistrableTask{
85 > chasm.NewRegistrablePureTask(
86 > "idle",
87 > l.SchedulerIdleTaskHandler,
88 > ),
89 > chasm.NewRegistrableSideEffectTask(
90 > "callbacks",
91 > l.SchedulerCallbacksTaskHandler,
92 > ),
93 > chasm.NewRegistrablePureTask(
94 > "generate",
95 > l.GeneratorTaskHandler,
96 > ),
97 > chasm.NewRegistrableSideEffectTask(
98 > "execute",
99 > l.InvokerExecuteTaskHandler,
100 > ),
101 > chasm.NewRegistrablePureTask(
102 > "processBuffer",
103 > l.InvokerProcessBufferTaskHandler,
104 > ),
105 > chasm.NewRegistrablePureTask(
106 > "backfill",
107 > l.BackfillerTaskHandler,
108 > ),
109 > chasm.NewRegistrableSideEffectTask(
110 > "migrateToWorkflow",
111 > l.MigrateToWorkflowTaskHandler,
112 > ),
113 > }
114 > }
115
116 > func (l *Library) RegisterServices(server *grpc.Server) { library.go
117 > server.RegisterService(&schedulerpb.SchedulerService_ServiceDesc, l.handler)
118 > }
go.temporal.io/server/common/archiver/archival_metadata.go 73 covered LOC · 16 ranges

Open complete file

47 )
48
49 > func (a *archivalConfig) StaticClusterState() ArchivalState { archival_metadata.go
50 > return a.staticClusterState
51 > }
52
53 const (
69 visibilityReadEnabled bool,
70 namespaceDefaults *config.ArchivalNamespaceDefaults,
71 > ) ArchivalMetadata { archival_metadata.go
72 > historyConfig := NewArchivalConfig(
73 > historyState,
74 > dynamicconfig.HistoryArchivalState.WithDefault(historyState).Get(dc),
75 > dynamicconfig.EnableReadFromHistoryArchival.WithDefault(historyReadEnabled).Get(dc),
76 > namespaceDefaults.History.State,
77 > namespaceDefaults.History.URI,
78 > )
79 >
80 > visibilityConfig := NewArchivalConfig(
81 > visibilityState,
82 > dynamicconfig.VisibilityArchivalState.WithDefault(visibilityState).Get(dc),
83 > dynamicconfig.EnableReadFromVisibilityArchival.WithDefault(visibilityReadEnabled).Get(dc),
84 > namespaceDefaults.Visibility.State,
85 > namespaceDefaults.Visibility.URI,
86 > )
87 >
88 > return &archivalMetadata{
89 > historyConfig: historyConfig,
90 > visibilityConfig: visibilityConfig,
91 > }
92 > }
93
94 > func (metadata *archivalMetadata) GetHistoryConfig() ArchivalConfig { archival_metadata.go
95 > return metadata.historyConfig
96 > }
97
98 > func (metadata *archivalMetadata) GetVisibilityConfig() ArchivalConfig { archival_metadata.go
99 > return metadata.visibilityConfig
100 > }
101
102 // NewArchivalConfig constructs a new valid ArchivalConfig
107 namespaceDefaultStateStr string,
108 namespaceDefaultURI string,
109 > ) ArchivalConfig { archival_metadata.go
110 > staticClusterState, err := getClusterArchivalState(staticClusterStateStr)
111 > if err != nil {
112 panic(err)
113 }
114 > namespaceDefaultState, err := getNamespaceArchivalState(namespaceDefaultStateStr) archival_metadata.go
115 > if err != nil {
116 panic(err)
117 }
118
119 > return &archivalConfig{ archival_metadata.go
120 > staticClusterState: staticClusterState,
121 > dynamicClusterState: dynamicClusterState,
122 > enableRead: enableRead,
123 > namespaceDefaultState: namespaceDefaultState,
124 > namespaceDefaultURI: namespaceDefaultURI,
125 > }
126 }
127
149
150 // ClusterConfiguredForArchival returns true if cluster is configured to handle archival, false otherwise
151 > func (a *archivalConfig) ClusterConfiguredForArchival() bool { archival_metadata.go
152 > return a.GetClusterState() == ArchivalEnabled
153 > }
154
155 > func (a *archivalConfig) GetClusterState() ArchivalState { archival_metadata.go
156 > // Only check dynamic config when archival is enabled in static config.
157 > // If archival is disabled in static config, there will be no provider section in the static config
158 > // and the archiver provider can not create any archiver. Therefore, in that case,
159 > // even dynamic config says archival is enabled, we should ignore that.
160 > // Only when archival is enabled in static config, should we check if there's any difference between static config and dynamic config.
161 > if a.staticClusterState != ArchivalEnabled {
162 return a.staticClusterState
163 }
164
165 > dynamicStateStr := a.dynamicClusterState() archival_metadata.go
166 > dynamicState, err := getClusterArchivalState(dynamicStateStr)
167 > if err != nil {
168 return ArchivalDisabled
169 }
170 > return dynamicState archival_metadata.go
171 }
172
178 }
179
180 > func (a *archivalConfig) GetNamespaceDefaultState() enumspb.ArchivalState { archival_metadata.go
181 > return a.namespaceDefaultState
182 > }
183
184 > func (a *archivalConfig) GetNamespaceDefaultURI() string { archival_metadata.go
185 > return a.namespaceDefaultURI
186 > }
187
188 > func getClusterArchivalState(str string) (ArchivalState, error) { archival_metadata.go
189 > str = strings.TrimSpace(strings.ToLower(str))
190 > switch str {
191 case "", config.ArchivalDisabled:
192 return ArchivalDisabled, nil
193 case config.ArchivalPaused:
194 return ArchivalPaused, nil
195 > case config.ArchivalEnabled: archival_metadata.go
196 > return ArchivalEnabled, nil
197 }
198 return ArchivalDisabled, fmt.Errorf("invalid archival state of %v for cluster, valid states are: {\"\", \"disabled\", \"paused\", \"enabled\"}", str)
199 }
200
201 > func getNamespaceArchivalState(str string) (enumspb.ArchivalState, error) { archival_metadata.go
202 > str = strings.TrimSpace(strings.ToLower(str))
203 > switch str {
204 > case "", config.ArchivalDisabled:
205 > return enumspb.ARCHIVAL_STATE_DISABLED, nil
206 case config.ArchivalEnabled:
207 return enumspb.ARCHIVAL_STATE_ENABLED, nil
go.temporal.io/server/service/history/shard/task_request_tracker.go 73 covered LOC · 19 ranges

Open complete file

24 )
25
26 > func newTaskRequestTracker(registry tasks.TaskCategoryRegistry) *taskRequestTracker { task_request_tracker.go
27 > outstandingTaskKeys := make(map[tasks.Category]map[tasks.Key]struct{})
28 > for _, category := range registry.GetCategories() {
29 > outstandingTaskKeys[category] = make(map[tasks.Key]struct{})
30 > }
31 > return &taskRequestTracker{
32 > pendingTaskKeys: outstandingTaskKeys,
33 > }
34 }
35
36 func (t *taskRequestTracker) track(
37 taskMaps ...map[tasks.Category][]tasks.Task,
38 > ) taskRequestCompletionFn { task_request_tracker.go
39 > minKeyByCategory := make(map[tasks.Category]tasks.Key)
40 > for _, taskMap := range taskMaps {
41 > for category, tasksPerCategory := range taskMap {
42 > minKey := tasks.MaximumKey task_request_tracker.go
43 > for _, task := range tasksPerCategory {
44 > if task.GetKey().CompareTo(minKey) < 0 {
45 > minKey = task.GetKey()
46 > }
47 }
48 > if minKey.CompareTo(tasks.MaximumKey) == 0 { task_request_tracker.go
49 continue
50 }
51
52 > if _, ok := minKeyByCategory[category]; !ok { task_request_tracker.go
53 > minKeyByCategory[category] = minKey
54 > } else {
55 minKeyByCategory[category] = tasks.MinKey(minKeyByCategory[category], minKey)
56 }
58 }
59
60 > t.Lock() task_request_tracker.go
61 > defer t.Unlock()
62 >
63 > t.inflightRequestCount++
64 >
65 > for category, minKey := range minKeyByCategory {
66 > t.pendingTaskKeys[category][minKey] = struct{}{} task_request_tracker.go
67 > }
68
69 > return func(writeErr error) { task_request_tracker.go
70 > t.Lock() task_request_tracker.go
71 > defer t.Unlock()
72 >
73 > // Task key is not pending only when we get a definitive result from persistence.
74 > // This result can be either a success or a error that guarantees the task with that key
75 > // will not be persisted.
76 > if writeErr == nil || !persistence.OperationPossiblySucceeded(writeErr) {
77 > // we can only remove the task from the pending task list if we are sure it was inserted task_request_tracker.go
78 > // or the insertion is guaranteed to have failed
79 > for category, minKey := range minKeyByCategory {
80 > delete(t.pendingTaskKeys[category], minKey) task_request_tracker.go
81 > }
82 }
83
84 // While task key might still be pending, the request is completed and no longer inflight
85 > t.inflightRequestCount-- task_request_tracker.go
86 > if t.inflightRequestCount == 0 {
87 > t.closeWaitChannelsLocked() task_request_tracker.go
88 > }
89 }
90 }
92 func (t *taskRequestTracker) minTaskKey(
93 category tasks.Category,
94 > ) (tasks.Key, bool) { task_request_tracker.go
95 > t.Lock()
96 > defer t.Unlock()
97 >
98 > pendingTasksForCategory := t.pendingTaskKeys[category]
99 > if len(pendingTasksForCategory) == 0 {
100 > return tasks.MinimumKey, false task_request_tracker.go
101 > }
102
103 minKey := tasks.MaximumKey
115 // otherwise inflight request can fails as those requests are conditioned on
116 // the current rangeID
117 > func (t *taskRequestTracker) drain() { task_request_tracker.go
118 > t.Lock()
119 >
120 > if t.inflightRequestCount == 0 {
121 > t.Unlock()
122 > return
123 > }
124
125 waitCh := make(chan struct{})
130 }
131
132 > func (t *taskRequestTracker) clear() { task_request_tracker.go
133 > t.Lock()
134 > defer t.Unlock()
135 >
136 > for category := range t.pendingTaskKeys {
137 > t.pendingTaskKeys[category] = make(map[tasks.Key]struct{})
138 > }
139 > t.inflightRequestCount = 0
140 > t.closeWaitChannelsLocked()
141 }
142
143 > func (t *taskRequestTracker) closeWaitChannelsLocked() { task_request_tracker.go
144 > for _, waitCh := range t.waitChannels {
145 close(waitCh)
146 }
147 > t.waitChannels = nil task_request_tracker.go
148 }
go.temporal.io/server/api/persistence/v1/chasm.pb.go 71 covered LOC · 13 ranges

Open complete file

67 }
68
69 > func (x *ChasmNode) GetMetadata() *ChasmNodeMetadata { chasm.pb.go
70 > if x != nil {
71 > return x.Metadata
72 > }
73 return nil
74 }
75
76 > func (x *ChasmNode) GetData() *v1.DataBlob { chasm.pb.go
77 > if x != nil {
78 > return x.Data
79 > }
80 return nil
81 }
142 }
143
144 > func (x *ChasmNodeMetadata) GetAttributes() isChasmNodeMetadata_Attributes { chasm.pb.go
145 > if x != nil {
146 > return x.Attributes
147 > }
148 return nil
149 }
150
151 > func (x *ChasmNodeMetadata) GetComponentAttributes() *ChasmComponentAttributes { chasm.pb.go
152 > if x != nil {
153 > if x, ok := x.Attributes.(*ChasmNodeMetadata_ComponentAttributes); ok { chasm.pb.go
154 > return x.ComponentAttributes chasm.pb.go
155 > }
156 }
157 return nil
267 }
268
269 > func (x *ChasmComponentAttributes) GetTypeId() uint32 { chasm.pb.go
270 > if x != nil {
271 > return x.TypeId
272 > }
273 return 0
274 }
275
276 > func (x *ChasmComponentAttributes) GetSideEffectTasks() []*ChasmComponentAttributes_Task { chasm.pb.go
277 > if x != nil {
278 > return x.SideEffectTasks
279 > }
280 return nil
281 }
282
283 > func (x *ChasmComponentAttributes) GetPureTasks() []*ChasmComponentAttributes_Task { chasm.pb.go
284 > if x != nil {
285 > return x.PureTasks
286 > }
287 return nil
288 }
571 func (*ChasmTaskInfo) ProtoMessage() {}
572
573 > func (x *ChasmTaskInfo) ProtoReflect() protoreflect.Message { chasm.pb.go
574 > mi := &file_temporal_server_api_persistence_v1_chasm_proto_msgTypes[8]
575 > if x != nil {
576 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) chasm.pb.go
577 > if ms.LoadMessageInfo() == nil {
578 > ms.StoreMessageInfo(mi)
579 > }
580 > return ms
581 }
582 > return mi.MessageOf(x) chasm.pb.go
583 }
584
1180 }
1181
1182 > func init() { file_temporal_server_api_persistence_v1_chasm_proto_init() } chasm.pb.go
1183 > func file_temporal_server_api_persistence_v1_chasm_proto_init() {
1184 > if File_temporal_server_api_persistence_v1_chasm_proto != nil {
1185 > return
1186 > }
1187 > file_temporal_server_api_persistence_v1_hsm_proto_init()
1188 > file_temporal_server_api_persistence_v1_chasm_proto_msgTypes[1].OneofWrappers = []any{
1189 > (*ChasmNodeMetadata_ComponentAttributes)(nil),
1190 > (*ChasmNodeMetadata_DataAttributes)(nil),
1191 > (*ChasmNodeMetadata_CollectionAttributes)(nil),
1192 > (*ChasmNodeMetadata_PointerAttributes)(nil),
1193 > }
1194 > file_temporal_server_api_persistence_v1_chasm_proto_msgTypes[10].OneofWrappers = []any{
1195 > (*ChasmNexusCompletion_Success)(nil),
1196 > (*ChasmNexusCompletion_Failure)(nil),
1197 > }
1198 > type x struct{}
1199 > out := protoimpl.TypeBuilder{
1200 > File: protoimpl.DescBuilder{
1201 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1202 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_chasm_proto_rawDesc), len(file_temporal_server_api_persistence_v1_chasm_proto_rawDesc)),
1203 > NumEnums: 0,
1204 > NumMessages: 15,
1205 > NumExtensions: 0,
1206 > NumServices: 0,
1207 > },
1208 > GoTypes: file_temporal_server_api_persistence_v1_chasm_proto_goTypes,
1209 > DependencyIndexes: file_temporal_server_api_persistence_v1_chasm_proto_depIdxs,
1210 > MessageInfos: file_temporal_server_api_persistence_v1_chasm_proto_msgTypes,
1211 > }.Build()
1212 > File_temporal_server_api_persistence_v1_chasm_proto = out.File
1213 > file_temporal_server_api_persistence_v1_chasm_proto_goTypes = nil
1214 > file_temporal_server_api_persistence_v1_chasm_proto_depIdxs = nil
1215 }
go.temporal.io/server/common/rpc/interceptor/context_metadata_interceptor.go 71 covered LOC · 23 ranges

Open complete file

31
32 // NewContextMetadataInterceptor creates a new ContextMetadataInterceptor
33 > func NewContextMetadataInterceptor(setTrailer bool, logger log.Logger) *ContextMetadataInterceptor { context_metadata_interceptor.go
34 > cmi := &ContextMetadataInterceptor{
35 > setTrailer: setTrailer,
36 > }
37 > if setTrailer {
38 > cmi.logger = logger context_metadata_interceptor.go
39 > cmi.throttledLogger = log.NewThrottledLogger(logger, func() float64 {
40 > return 1.0 / 30.0 // 1 log per 30 seconds
41 > })
42 }
44 }
45
51 info *grpc.UnaryServerInfo,
52 handler grpc.UnaryHandler,
53 > ) (any, error) { context_metadata_interceptor.go
54 > ctx = contextutil.WithMetadataContext(ctx)
55 >
56 > resp, err := handler(ctx, req)
57 >
58 > if c.setTrailer {
59 > c.appendContextMetadataToTrailer(ctx, info) context_metadata_interceptor.go
60 > }
61
62 > return resp, err context_metadata_interceptor.go
63 }
64
65 > func (c *ContextMetadataInterceptor) appendContextMetadataToTrailer(ctx context.Context, info *grpc.UnaryServerInfo) { context_metadata_interceptor.go
66 > // If the context is done, the gRPC stream may already be in streamDone state,
67 > // and SetTrailer would return ErrIllegalHeaderWrite ("SendHeader called multiple times").
68 > select {
69 > case <-ctx.Done(): context_metadata_interceptor.go
70 > return
72 }
73
74 > allMetadata := contextutil.ContextMetadataGetAll(ctx) context_metadata_interceptor.go
75 > if len(allMetadata) == 0 {
76 > c.throttledLogger.Info("ContextMetadataInterceptor: No metadata in context, not setting trailer", context_metadata_interceptor.go
77 > tag.NewStringTag("fullMethod", info.FullMethod),
78 > )
79 > return
80 > }
81
82 > trailerPairs := c.buildTrailerPairs(allMetadata) context_metadata_interceptor.go
83 >
84 > trailer := metadata.Pairs(trailerPairs...)
85 > c.throttledLogger.Info("ContextMetadataInterceptor: Setting trailer",
86 > tag.NewAnyTag("trailer", trailer),
87 > tag.NewStringTag("fullMethod", info.FullMethod),
88 > )
89 >
90 > if err := grpc.SetTrailer(ctx, trailer); err != nil {
91 c.logger.Error("ContextMetadataInterceptor: Failed to set trailer",
92 tag.Error(err),
104 // "contextmetadata-<key>" entries plus unprefixed well-known keys. Old readers that
105 // don't understand the proto key will fall back to these.
106 > func (c *ContextMetadataInterceptor) buildTrailerPairs(allMetadata map[string]any) []string { context_metadata_interceptor.go
107 > var trailerPairs []string
108 >
109 > // Proto format: serialize all metadata into a single protobuf message.
110 > protoMsg := &contextpropagationspb.ContextMetadata{
111 > Entries: make(map[string]string, len(allMetadata)),
112 > }
113 > for key, value := range allMetadata {
114 > protoMsg.Entries[key] = fmt.Sprint(value) context_metadata_interceptor.go
115 > }
116 > if protoBytes, err := proto.Marshal(protoMsg); err != nil { context_metadata_interceptor.go
117 c.throttledLogger.Warn("ContextMetadataInterceptor: Failed to marshal proto metadata, falling back to legacy-only",
118 tag.Error(err),
119 )
121 > trailerPairs = append(trailerPairs, protoTrailerKey, string(protoBytes))
122 > }
123
124 // Legacy format: emit individual keys for backward compatibility with older readers.
125 // Skip entries with HTTP/2-unsafe values (the proto key handles those).
126 > for key, value := range allMetadata { context_metadata_interceptor.go
127 > valStr := fmt.Sprint(value) context_metadata_interceptor.go
128 > if !isHTTP2SafeValue(valStr) {
129 continue
130 }
131 > trailerPairs = append(trailerPairs, trailerKeyPrefix+key, valStr) context_metadata_interceptor.go
132 > // Backward compatibility: also emit unprefixed keys for older readers.
133 > if key == contextutil.MetadataKeyWorkflowType || key == contextutil.MetadataKeyWorkflowTaskQueue {
134 > trailerPairs = append(trailerPairs, key, valStr)
135 > }
136 }
137
138 > return trailerPairs context_metadata_interceptor.go
139 }
140
143 // CR (0x0D), or LF (0x0A). Additionally, Go's HTTP/2 framer rejects C0 control
144 // characters (0x00-0x1F except HTAB 0x09) and DEL (0x7F).
145 > func isHTTP2SafeValue(s string) bool { context_metadata_interceptor.go
146 > for i := 0; i < len(s); i++ {
147 > b := s[i]
148 > if b == 0x09 { // HTAB is allowed
149 continue
150 }
151 > if b < 0x20 || b == 0x7f { // C0 controls and DEL context_metadata_interceptor.go
152 return false
153 }
154 }
156 }
go.temporal.io/server/chasm/lib/nexusoperation/gen/nexusoperationpb/v1/request_response.pb.go 70 covered LOC · 25 ranges

Open complete file

46 func (*StartNexusOperationRequest) ProtoMessage() {}
47
48 > func (x *StartNexusOperationRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
49 > mi := &file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_msgTypes[0]
50 > if x != nil {
51 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
52 if ms.LoadMessageInfo() == nil {
104 func (*StartNexusOperationResponse) ProtoMessage() {}
105
106 > func (x *StartNexusOperationResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
107 > mi := &file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_msgTypes[1]
108 > if x != nil {
109 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
110 if ms.LoadMessageInfo() == nil {
149 func (*DescribeNexusOperationRequest) ProtoMessage() {}
150
151 > func (x *DescribeNexusOperationRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
152 > mi := &file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_msgTypes[2]
153 > if x != nil {
154 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
155 if ms.LoadMessageInfo() == nil {
200 func (*DescribeNexusOperationResponse) ProtoMessage() {}
201
202 > func (x *DescribeNexusOperationResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
203 > mi := &file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_msgTypes[3]
204 > if x != nil {
205 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
206 if ms.LoadMessageInfo() == nil {
245 func (*RequestCancelNexusOperationRequest) ProtoMessage() {}
246
247 > func (x *RequestCancelNexusOperationRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
248 > mi := &file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_msgTypes[4]
249 > if x != nil {
250 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
251 if ms.LoadMessageInfo() == nil {
295 func (*RequestCancelNexusOperationResponse) ProtoMessage() {}
296
297 > func (x *RequestCancelNexusOperationResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
298 > mi := &file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_msgTypes[5]
299 > if x != nil {
300 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
301 if ms.LoadMessageInfo() == nil {
333 func (*TerminateNexusOperationRequest) ProtoMessage() {}
334
335 > func (x *TerminateNexusOperationRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
336 > mi := &file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_msgTypes[6]
337 > if x != nil {
338 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
339 if ms.LoadMessageInfo() == nil {
383 func (*TerminateNexusOperationResponse) ProtoMessage() {}
384
385 > func (x *TerminateNexusOperationResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
386 > mi := &file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_msgTypes[7]
387 > if x != nil {
388 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
389 if ms.LoadMessageInfo() == nil {
421 func (*DeleteNexusOperationRequest) ProtoMessage() {}
422
423 > func (x *DeleteNexusOperationRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
424 > mi := &file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_msgTypes[8]
425 > if x != nil {
426 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
427 if ms.LoadMessageInfo() == nil {
471 func (*DeleteNexusOperationResponse) ProtoMessage() {}
472
473 > func (x *DeleteNexusOperationResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
474 > mi := &file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_msgTypes[9]
475 > if x != nil {
476 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
477 if ms.LoadMessageInfo() == nil {
509 func (*PollNexusOperationRequest) ProtoMessage() {}
510
511 > func (x *PollNexusOperationRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
512 > mi := &file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_msgTypes[10]
513 > if x != nil {
514 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
515 if ms.LoadMessageInfo() == nil {
560 func (*PollNexusOperationResponse) ProtoMessage() {}
561
562 > func (x *PollNexusOperationResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
563 > mi := &file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_msgTypes[11]
564 > if x != nil {
565 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
566 if ms.LoadMessageInfo() == nil {
672 }
673
674 > func init() { file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_init() } request_response.pb.go
675 > func file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_init() {
676 > if File_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto != nil {
677 > return
678 > }
679 > type x struct{}
680 > out := protoimpl.TypeBuilder{
681 > File: protoimpl.DescBuilder{
682 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
683 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_rawDesc), len(file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_rawDesc)),
684 > NumEnums: 0,
685 > NumMessages: 12,
686 > NumExtensions: 0,
687 > NumServices: 0,
688 > },
689 > GoTypes: file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_goTypes,
690 > DependencyIndexes: file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_depIdxs,
691 > MessageInfos: file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_msgTypes,
692 > }.Build()
693 > File_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto = out.File
694 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_goTypes = nil
695 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_depIdxs = nil
696 }
go.temporal.io/server/common/testing/testcontext/context.go 70 covered LOC · 15 ranges

Open complete file

39
40 // DefaultTimeout returns the effective default timeout for test-scoped contexts.
41 > func DefaultTimeout() time.Duration { context.go
42 > return effectiveTimeout(0)
43 > }
44
45 // For returns the test-scoped context for tb. The context is canceled
49 // return the same context, but an explicit different timeout fails instead of
50 // being silently ignored.
51 > func For(tb testing.TB, opts ...Option) context.Context { context.go
52 > tb.Helper()
53 >
54 > cfg := config{timeout: DefaultTimeout()}
55 > for _, opt := range opts {
56 opt(&cfg)
57 }
58
59 > st := getContextState(tb, cfg.timeout) context.go
60 > st.configure(tb, cfg)
61 > return st.context()
62 }
63
98 }
99
100 > func getContextState(tb testing.TB, timeout time.Duration) *contextState { context.go
101 > tb.Helper()
102 >
103 > testContexts.Lock()
104 > defer testContexts.Unlock()
105 >
106 > if st, ok := testContexts.byTest[tb]; ok {
107 return st
108 }
109
110 > ctx, cancel := context.WithTimeout(tb.Context(), timeout) context.go
111 >
112 > // Annotate gRPC requests with the test name for OTEL tracing.
113 > ctx = metadata.AppendToOutgoingContext(ctx, testNameMetadataKey, tb.Name())
114 >
115 > st := &contextState{
116 > ctx: ctx,
117 > cancel: cancel,
118 > timeout: timeout,
119 > decorators: make(map[any]struct{}),
120 > }
121 > testContexts.byTest[tb] = st
122 >
123 > tb.Cleanup(func() {
124 > err := st.err()
125 > st.cancel()
126 > testContexts.Lock()
127 > delete(testContexts.byTest, tb)
128 > testContexts.Unlock()
129 > if err == context.DeadlineExceeded {
130 tb.Errorf("test exceeded timeout of %v", st.timeout)
131 }
132 > st.release() context.go
133 })
134 > return st context.go
135 }
136
137 > func (s *contextState) configure(tb testing.TB, cfg config) { context.go
138 > tb.Helper()
139 >
140 > s.mu.Lock()
141 > defer s.mu.Unlock()
142 >
143 > if cfg.timeoutSet && cfg.timeout != s.timeout {
144 tb.Fatalf("testcontext: test context already exists with timeout %v; cannot change it to %v", s.timeout, cfg.timeout)
145 }
168 }
169
170 > func (s *contextState) context() context.Context { context.go
171 > s.mu.Lock()
172 > defer s.mu.Unlock()
173 > return s.ctx
174 > }
175
176 > func (s *contextState) err() error { context.go
177 > s.mu.Lock()
178 > defer s.mu.Unlock()
179 > return s.ctx.Err()
180 > }
181
182 > func (s *contextState) release() { context.go
183 > s.mu.Lock()
184 > defer s.mu.Unlock()
185 > s.ctx = nil
186 > }
187
188 > func effectiveTimeout(customTimeout time.Duration) (timeout time.Duration) { context.go
189 > defer func() {
190 > // Build flag TEMPORAL_DEBUG applies a timeout multiplier to all test timeouts.
191 > timeout *= debug.TimeoutMultiplier
192 > }()
193
194 // 1. Custom timeout (via WithTimeout option).
195 > if customTimeout > 0 { context.go
196 return customTimeout
197 }
198
199 // 2. TEMPORAL_TEST_TIMEOUT environment variable.
200 > if envTimeout := os.Getenv("TEMPORAL_TEST_TIMEOUT"); envTimeout != "" { context.go
201 if dur, err := time.ParseDuration(envTimeout); err == nil && dur > 0 {
202 return dur
205
206 // 3. Default timeout.
207 > return defaultTimeout context.go
208 }
go.temporal.io/server/chasm/fields_iterator.go 69 covered LOC · 33 ranges

Open complete file

41 //
42 //nolint:revive // cognitive complexity 26 (> max enabled 25)
43 > func fieldsOf(valueV reflect.Value) iter.Seq[fieldInfo] { fields_iterator.go
44 > valueT := valueV.Type()
45 > dataFieldName := ""
46 > return func(yield func(fi fieldInfo) bool) {
47 > for i := 0; i < valueT.Elem().NumField(); i++ {
48 > fieldV := valueV.Elem().Field(i)
49 > fieldT := fieldV.Type()
50 > if fieldT == UnimplementedComponentT {
51 > continue fields_iterator.go
52 }
53
54 > fieldN := fieldName(valueT.Elem().Field(i)) fields_iterator.go
55 > var fieldErr error
56 > fieldK := fieldKindUnspecified
57 > if fieldT.AssignableTo(protoMessageT) {
58 > if dataFieldName != "" { fields_iterator.go
59 fieldErr = serviceerror.NewInternalf("%s.%s: only one data field %s (implements proto.Message) allowed in component", valueT, fieldN, dataFieldName)
60 }
61 > dataFieldName = fieldN fields_iterator.go
62 > fieldK = fieldKindData
63 > } else { fields_iterator.go
64 > prefix := genericTypePrefix(fieldT)
65 > if strings.HasPrefix(prefix, "*") {
66 switch prefix[1:] {
67 case chasmFieldTypePrefix,
73 continue
74 }
75 > } else { fields_iterator.go
76 > switch prefix {
77 case chasmFieldTypePrefix:
78 fieldK = fieldKindSubField
79 > case chasmMapTypePrefix: fields_iterator.go
80 > fieldK = fieldKindSubMap
81 > case chasmMSPointerType: fields_iterator.go
82 > fieldK = fieldKindMutableState
83 case chasmParentPointerTypePrefix:
84 fieldK = fieldKindParentPtr
90 }
91
92 > if !yield(fieldInfo{val: fieldV, typ: fieldT, name: fieldN, kind: fieldK, err: fieldErr}) { fields_iterator.go
93 return
94 }
95 }
96 // If the data field is not found, generate one more fake field with only an error set.
97 > if dataFieldName == "" { fields_iterator.go
98 yield(fieldInfo{err: serviceerror.NewInternalf("%s: no data field (implements proto.Message) found", valueT)})
99 }
102
103 // unmanagedFieldsOf yields all non-CHASM managed fields of a struct.
104 > func unmanagedFieldsOf(valueT reflect.Type) iter.Seq[fieldInfo] { fields_iterator.go
105 > return func(yield func(fi fieldInfo) bool) {
106 > if valueT.Kind() == reflect.Pointer {
107 > valueT = valueT.Elem() fields_iterator.go
108 > }
109 > for field := range valueT.Fields() { fields_iterator.go
110 > fieldT := field.Type
111 > if fieldT == UnimplementedComponentT {
112 > continue fields_iterator.go
113 }
114
115 // Skip the data field, which is always CHASM-managed.
116 > if fieldT.AssignableTo(protoMessageT) { fields_iterator.go
117 > continue fields_iterator.go
118 }
119
120 > fieldN := fieldName(field) fields_iterator.go
121 > prefix := genericTypePrefix(fieldT)
122 > switch prefix {
123 case chasmFieldTypePrefix,
124 chasmMapTypePrefix,
125 chasmMSPointerType,
126 > chasmParentPointerTypePrefix: fields_iterator.go
127 > continue // Skip CHASM fields.
128 > default: fields_iterator.go
129 > if !yield(fieldInfo{typ: fieldT, name: fieldN}) {
130 return
131 }
135 }
136
137 > func genericTypePrefix(t reflect.Type) string { fields_iterator.go
138 > tn := t.String()
139 > if tn == chasmMSPointerType {
140 > return chasmMSPointerType fields_iterator.go
141 > }
142 > bracketPos := strings.Index(tn, "[") fields_iterator.go
143 > if bracketPos == -1 {
144 > return "" fields_iterator.go
145 > }
146 > return tn[:bracketPos+1] fields_iterator.go
147 }
148
149 > func fieldName(f reflect.StructField) string { fields_iterator.go
150 > if tagName := f.Tag.Get(fieldNameTag); tagName != "" {
151 return tagName
152 }
153 > return f.Name fields_iterator.go
154 }
155
161 // This is used at registration time to validate that archetypes using Visibility
162 // have configured a businessID alias.
163 > func hasVisibilityField(componentT reflect.Type) bool { fields_iterator.go
164 > if componentT.Kind() == reflect.Pointer {
165 > componentT = componentT.Elem() fields_iterator.go
166 > }
167 > if componentT.Kind() != reflect.Struct { fields_iterator.go
168 return false
169 }
170 > for field := range componentT.Fields() { fields_iterator.go
171 > fieldT := field.Type
172 > if fieldT == visibilityFieldT {
173 > return true fields_iterator.go
174 > }
175 }
176 > return false fields_iterator.go
177 }
go.temporal.io/server/chasm/registrable_component.go 69 covered LOC · 28 ranges

Open complete file

65 // If a registrable component is not detached by default, a component definition
66 // can specify its child as detached via ComponentFieldDetached() option.
67 > func WithDetached() RegistrableComponentOption { registrable_component.go
68 > return func(rc *RegistrableComponent) {
69 > rc.detached = true
70 > }
71 }
72
80 func WithBusinessIDAlias(
81 alias string,
82 > ) RegistrableComponentOption { registrable_component.go
83 > return func(rc *RegistrableComponent) {
84 > if rc.searchAttributesMapper == nil {
85 > rc.searchAttributesMapper = newVisibilitySearchAttributesMapper() registrable_component.go
86 > }
87 > if _, ok := rc.searchAttributesMapper.aliasToField[alias]; ok { registrable_component.go
88 //nolint:forbidigo
89 panic(fmt.Sprintf("registrable component validation error: business ID alias %q is already defined as a search attribute", alias))
90 }
91 > if _, ok := rc.searchAttributesMapper.systemAliasToField[alias]; ok { registrable_component.go
92 //nolint:forbidigo
93 panic(fmt.Sprintf("registrable component validation error: business ID alias %q is already defined as a system search attribute", alias))
94 }
95 > rc.searchAttributesMapper.systemAliasToField[alias] = sadefs.WorkflowID registrable_component.go
96 > rc.searchAttributesMapper.fieldToAlias[sadefs.WorkflowID] = alias
97 > rc.searchAttributesMapper.saTypeMap[sadefs.WorkflowID] = enumspb.INDEXED_VALUE_TYPE_KEYWORD
98 }
99 }
101 func WithSearchAttributes(
102 searchAttributes ...SearchAttribute,
103 > ) RegistrableComponentOption { registrable_component.go
104 > return func(rc *RegistrableComponent) {
105 > if len(searchAttributes) == 0 {
106 return
107 }
108
109 > if rc.searchAttributesMapper == nil { registrable_component.go
110 > rc.searchAttributesMapper = newVisibilitySearchAttributesMapper() registrable_component.go
111 > }
112
113 > for _, sa := range searchAttributes { registrable_component.go
114 > alias := sa.definition().alias
115 > field := sa.definition().field
116 > valueType := sa.definition().valueType
117 >
118 > // An identity-mapped system search attribute (alias == field, e.g. TaskQueue,
119 > // ExecutionTime) overrides that system column directly, so it is recorded only in
120 > // overriddenSystemFields; queries resolve via the system column.
121 > if field == alias && sadefs.IsSystem(field) {
122 > if !sadefs.IsChasmOverridableSystem(field) { registrable_component.go
123 //nolint:forbidigo
124 panic(fmt.Sprintf("registrable component validation error: system search attribute %q cannot be overridden by a CHASM component", field))
125 }
126 > if _, ok := rc.searchAttributesMapper.overriddenSystemFields[field]; ok { registrable_component.go
127 //nolint:forbidigo
128 panic(fmt.Sprintf("registrable component validation error: system search attribute override %q is already defined", field))
129 }
130 > rc.searchAttributesMapper.overriddenSystemFields[field] = valueType registrable_component.go
131 > continue
132 }
133
134 > if sadefs.IsChasmSystem(alias) { registrable_component.go
135 //nolint:forbidigo
136 panic(fmt.Sprintf("registrable component validation error: CHASM search attribute alias %q is a CHASM system search attribute", alias))
137 }
138 > if !sadefs.IsSystem(alias) && sadefs.IsReserved(alias) { registrable_component.go
139 //nolint:forbidigo
140 panic(fmt.Sprintf("registrable component validation error: CHASM search attribute alias %q is a reserved search attribute", alias))
141 }
142
143 > if _, ok := rc.searchAttributesMapper.systemAliasToField[alias]; ok { registrable_component.go
144 //nolint:forbidigo
145 panic(fmt.Sprintf("registrable component validation error: CHASM search attribute alias %q is already defined as a system search attribute alias", alias))
146 }
147 > if _, ok := rc.searchAttributesMapper.aliasToField[alias]; ok { registrable_component.go
148 //nolint:forbidigo
149 panic(fmt.Sprintf("registrable component validation error: search attribute alias %q is already defined", alias))
150 }
151 > if _, ok := rc.searchAttributesMapper.fieldToAlias[field]; ok { registrable_component.go
152 //nolint:forbidigo
153 panic(fmt.Sprintf("registrable component validation error: search attribute field %q is already defined", field))
154 }
155
156 > rc.searchAttributesMapper.aliasToField[alias] = field registrable_component.go
157 > rc.searchAttributesMapper.fieldToAlias[field] = alias
158 > rc.searchAttributesMapper.saTypeMap[field] = valueType
159 }
160 }
173 func WithContextValues(
174 keyVals map[any]any,
175 > ) RegistrableComponentOption { registrable_component.go
176 > return func(rc *RegistrableComponent) {
177 > if rc.contextValues == nil {
178 > rc.contextValues = make(map[any]any, len(keyVals))
179 > }
180 > maps.Copy(rc.contextValues, keyVals)
181 }
182 }
184 func (rc *RegistrableComponent) registerToLibrary(
185 library namer,
186 > ) (string, uint32, error) { registrable_component.go
187 > if rc.library != nil {
188 return "", 0, fmt.Errorf("component %s is already registered in library %s", rc.componentType, rc.library.Name())
189 }
190
191 > rc.library = library registrable_component.go
192 > rc.fqn = FullyQualifiedName(rc.library.Name(), rc.componentType)
193 > rc.componentID = GenerateTypeID(rc.fqn)
194 > return rc.fqn, rc.componentID, nil
195 }
196
203 // The generated ID is used to uniquely identify components and tasks within the CHASM framework. The same FQN will
204 // always produce the same ID.
205 > func GenerateTypeID(fqn string) uint32 { registrable_component.go
206 > return farm.Fingerprint32([]byte(fqn))
207 > }
208
209 // hasBusinessIDAlias returns true if the component has a businessID alias configured
210 // via WithBusinessIDAlias option.
211 > func (rc *RegistrableComponent) hasBusinessIDAlias() bool { registrable_component.go
212 > if rc.searchAttributesMapper == nil {
213 return false
214 }
215 > _, ok := rc.searchAttributesMapper.fieldToAlias[sadefs.WorkflowID] registrable_component.go
216 > return ok
217 }
218
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/plugin.go 69 covered LOC · 27 ranges

Open complete file

43 }
44
45 > func init() { plugin.go
46 > sql.RegisterPlugin(PluginName, &plugin{
47 > queryConverter: &queryConverter{},
48 > connPool: newConnPool(),
49 > })
50 > }
51
52 func (p *plugin) GetVisibilityQueryConverter() sqlplugin.VisibilityQueryConverter {
61 logger log.Logger,
62 _ metrics.Handler,
63 > ) (sqlplugin.GenericDB, error) { plugin.go
64 > conn, err := p.connPool.Allocate(cfg, r, logger, p.createDBConnection)
65 > if err != nil {
66 return nil, err
67 }
68 > db := newDB(dbKind, cfg.DatabaseName, conn, nil, logger) plugin.go
69 > db.OnClose(func() { p.connPool.Close(cfg) }) // remove reference
70 > return db, nil
71 }
72
79 _ resolver.ServiceResolver,
80 logger log.Logger,
81 > ) (*sqlx.DB, error) { plugin.go
82 > dsn, err := buildDSN(cfg)
83 > if err != nil {
84 return nil, fmt.Errorf("error building DSN: %w", err)
85 }
86
87 > db, err := sqlx.Connect(goSQLDriverName, dsn) plugin.go
88 > if err != nil {
89 return nil, err
90 }
102 // respect the user's config values when set, otherwise default to 1 for
103 // backward compatibility and safety.
104 > walEnabled := strings.EqualFold(cfg.ConnectAttributes["journal_mode"], "wal") plugin.go
105 > if cfg.MaxConns > 0 {
106 > if cfg.MaxConns > 1 && !walEnabled { plugin.go
107 logger.Warn(
108 "SQLite MaxConns > 1 without WAL mode (journal_mode=wal) may cause 'database is locked' errors. "+
111 )
112 }
113 > db.SetMaxOpenConns(cfg.MaxConns) plugin.go
114 } else {
115 db.SetMaxOpenConns(1)
116 }
117 > if cfg.MaxIdleConns > 0 { plugin.go
118 > db.SetMaxIdleConns(cfg.MaxIdleConns) plugin.go
119 > } else { plugin.go
120 db.SetMaxIdleConns(1)
121 }
122 > if cfg.MaxConnLifetime > 0 { plugin.go
123 > db.SetConnMaxLifetime(cfg.MaxConnLifetime) plugin.go
124 > }
125 // For in-memory databases, the database is deleted when the last connection
126 // closes. Set ConnMaxIdleTime to 0 (infinite) to prevent idle connections
127 // from being reaped, which would destroy the database.
128 > if cfg.ConnectAttributes["mode"] == "memory" { plugin.go
129 > db.SetConnMaxIdleTime(0) plugin.go
130 > }
131
132 // Maps struct names in CamelCase to snake without need for db struct tags.
133 > db.MapperFunc(strcase.ToSnake) plugin.go
134 >
135 > switch {
136 > case cfg.ConnectAttributes["mode"] == "memory": plugin.go
137 > // creates temporary DB overlay in order to configure database and schemas
138 > if err := p.setupSQLiteDatabase(cfg, db, logger); err != nil {
139 _ = db.Close()
140 return nil, err
147 }
148
149 > return db, nil plugin.go
150 }
151
152 > func (p *plugin) setupSQLiteDatabase(cfg *config.SQL, conn *sqlx.DB, logger log.Logger) error { plugin.go
153 > db := newDB(sqlplugin.DbKindUnknown, cfg.DatabaseName, conn, nil, logger)
154 > defer func() { _ = db.Close() }()
155
156 > err := db.CreateDatabase(cfg.DatabaseName) plugin.go
157 > if err != nil {
158 return err
159 }
160
161 // init tables
162 > return sqliteschema.SetupSchemaOnDB(db) plugin.go
163 }
164
165 > func buildDSN(cfg *config.SQL) (string, error) { plugin.go
166 > if cfg.ConnectAttributes == nil {
167 cfg.ConnectAttributes = make(map[string]string)
168 }
169 > vals, err := buildDSNAttr(cfg) plugin.go
170 > if err != nil {
171 return "", err
172 }
173 > dsn := fmt.Sprintf( plugin.go
174 > "file:%s?%v",
175 > cfg.DatabaseName,
176 > vals.Encode(),
177 > )
178 > return dsn, nil
179 }
180
181 > func buildDSNAttr(cfg *config.SQL) (url.Values, error) { plugin.go
182 > parameters := url.Values{}
183 >
184 > // sort ConnectAttributes to get a deterministic order
185 > keys := expmaps.Keys(cfg.ConnectAttributes)
186 > sort.Strings(keys)
187 >
188 > for _, k := range keys {
189 > key := strings.TrimSpace(k)
190 > value := strings.TrimSpace(cfg.ConnectAttributes[k])
191 > if parameters.Get(key) != "" {
192 return nil, fmt.Errorf("duplicate connection attr: %v:%v, %v:%v",
193 key,
197 }
198
199 > if _, isValidQueryParameter := queryParameters[key]; isValidQueryParameter { plugin.go
200 > parameters.Set(key, value)
201 > continue
202 }
203
206 }
207 // set time format
208 > parameters.Add("_time_format", "sqlite") plugin.go
209 > return parameters, nil
210 }
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/namespace.go 68 covered LOC · 17 ranges

Open complete file

45 ctx context.Context,
46 row *sqlplugin.NamespaceRow,
47 > ) (sql.Result, error) { namespace.go
48 > return mdb.conn.ExecContext(ctx,
49 > createNamespaceQuery,
50 > partitionID,
51 > row.ID,
52 > row.Name,
53 > row.IsGlobal,
54 > row.Data,
55 > row.DataEncoding,
56 > row.NotificationVersion,
57 > )
58 > }
59
60 // UpdateNamespace updates a single row in namespaces table
78 ctx context.Context,
79 filter sqlplugin.NamespaceFilter,
80 > ) ([]sqlplugin.NamespaceRow, error) { namespace.go
81 > switch {
82 > case filter.ID != nil || filter.Name != nil: namespace.go
83 > if filter.ID != nil && filter.Name != nil {
84 return nil, serviceerror.NewInternal("only ID or name filter can be specified for selection")
85 }
86 > return mdb.selectFromNamespace(ctx, filter) namespace.go
87 > case filter.PageSize != nil && *filter.PageSize > 0: namespace.go
88 > return mdb.selectAllFromNamespace(ctx, filter)
89 default:
90 return nil, errMissingArgs
95 ctx context.Context,
96 filter sqlplugin.NamespaceFilter,
97 > ) ([]sqlplugin.NamespaceRow, error) { namespace.go
98 > var err error
99 > var row sqlplugin.NamespaceRow
100 > switch {
101 > case filter.ID != nil: namespace.go
102 > err = mdb.conn.GetContext(ctx,
103 > &row,
104 > getNamespaceByIDQuery,
105 > partitionID,
106 > *filter.ID,
107 > )
108 > case filter.Name != nil: namespace.go
109 > err = mdb.conn.GetContext(ctx,
110 > &row,
111 > getNamespaceByNameQuery,
112 > partitionID,
113 > *filter.Name,
114 > )
115 }
116 > if err != nil { namespace.go
117 > return nil, err namespace.go
118 > }
119 > return []sqlplugin.NamespaceRow{row}, nil namespace.go
120 }
121
123 ctx context.Context,
124 filter sqlplugin.NamespaceFilter,
125 > ) ([]sqlplugin.NamespaceRow, error) { namespace.go
126 > var err error
127 > var rows []sqlplugin.NamespaceRow
128 > switch {
129 case filter.GreaterThanID != nil:
130 err = mdb.conn.SelectContext(ctx,
135 *filter.PageSize,
136 )
137 > default: namespace.go
138 > err = mdb.conn.SelectContext(ctx,
139 > &rows,
140 > listNamespacesQuery,
141 > partitionID,
142 > filter.PageSize,
143 > )
144 }
145 > return rows, err namespace.go
146 }
147
173 func (mdb *db) LockNamespaceMetadata(
174 ctx context.Context,
175 > ) (*sqlplugin.NamespaceMetadataRow, error) { namespace.go
176 > var row sqlplugin.NamespaceMetadataRow
177 > err := mdb.conn.GetContext(ctx,
178 > &row.NotificationVersion,
179 > lockNamespaceMetadataQuery,
180 > )
181 > if err != nil {
182 return nil, err
183 }
184 > return &row, nil namespace.go
185 }
186
201 ctx context.Context,
202 row *sqlplugin.NamespaceMetadataRow,
203 > ) (sql.Result, error) { namespace.go
204 > return mdb.conn.ExecContext(ctx,
205 > updateNamespaceMetadataQuery,
206 > row.NotificationVersion+1,
207 > row.NotificationVersion,
208 > )
209 > }
go.temporal.io/server/common/rpc/interceptor/redirection.go 68 covered LOC · 20 ranges

Open complete file

200 timeSource clock.TimeSource,
201 clusterMetadata cluster.Metadata,
202 > ) *Redirection { redirection.go
203 > dcRedirectionPolicy := RedirectionPolicyGenerator(
204 > clusterMetadata,
205 > enabledForNS,
206 > selectedAPIsOnlyForNS,
207 > namespaceCache,
208 > policy,
209 > )
210 >
211 > return &Redirection{
212 > currentClusterName: clusterMetadata.GetCurrentClusterName(),
213 > redirectionPolicy: dcRedirectionPolicy,
214 > namespaceCache: namespaceCache,
215 > logger: logger,
216 > clientBean: clientBean,
217 > metricsHandler: metricsHandler,
218 > timeSource: timeSource,
219 > }
220 > }
221
222 // WithRedirectResponses returns a copy of the interceptor that treats the given fullMethod ->
240 info *grpc.UnaryServerInfo,
241 handler grpc.UnaryHandler,
242 > ) (_ any, retError error) { redirection.go
243 > defer log.CapturePanic(i.logger, &retError)
244 > if raFn, ok := i.redirectResponsesByFullMethod[info.FullMethod]; ok {
245 if !i.RedirectionAllowed(ctx) {
246 return handler(ctx, req)
256 }
257
258 > if !strings.HasPrefix(info.FullMethod, api.WorkflowServicePrefix) { redirection.go
259 > return handler(ctx, req) redirection.go
260 > }
261 > if !i.RedirectionAllowed(ctx) { redirection.go
262 return handler(ctx, req)
263 }
264
265 > methodName := api.MethodName(info.FullMethod) redirection.go
266 > if _, ok := localAPIResponses[methodName]; ok {
267 > return i.handleLocalAPIInvocation(ctx, req, handler, methodName)
268 > }
269 > if raFn, ok := globalAPIResponses[methodName]; ok { redirection.go
270 > namespaceName, err := GetNamespaceName(i.namespaceCache, req)
271 > if err != nil {
272 return nil, err
273 }
274 > return i.handleRedirectAPIInvocation(ctx, req, info, handler, methodName, raFn, namespaceName) redirection.go
275 }
276
286 handler grpc.UnaryHandler,
287 methodName string,
288 > ) (_ any, retError error) { redirection.go
289 > scope, startTime := i.BeforeCall(dcRedirectionMetricsPrefix + methodName)
290 > defer func() {
291 > i.AfterCall(scope, startTime, i.currentClusterName, "local", retError)
292 > }()
293 > return handler(ctx, req)
294 }
295
302 respCtorFn responseConstructorFn,
303 namespaceName namespace.Name,
304 > ) (_ any, retError error) { redirection.go
305 > var resp any
306 > var targetClusterName = i.currentClusterName
307 > var err error
308 >
309 > scope, startTime := i.BeforeCall(dcRedirectionMetricsPrefix + methodName)
310 > defer func() {
311 > i.AfterCall(scope, startTime, targetClusterName, namespaceName.String(), retError)
312 > }()
313
314 > err = i.redirectionPolicy.WithNamespaceRedirect(ctx, namespaceName, methodName, req, func(targetDC string) error { redirection.go
315 > targetClusterName = targetDC redirection.go
316 > if targetClusterName == i.currentClusterName {
317 > resp, err = handler(ctx, req) redirection.go
318 > } else { redirection.go
319 remoteClient, _, err := i.clientBean.GetRemoteFrontendClient(targetClusterName)
320 if err != nil {
329 }
330 }
331 > return err redirection.go
332 })
333 > return resp, err redirection.go
334 }
335
336 func (i *Redirection) BeforeCall(
337 operation string,
338 > ) (metrics.Handler, time.Time) { redirection.go
339 > return i.metricsHandler.WithTags(metrics.OperationTag(operation), metrics.ServiceRoleTag(metrics.DCRedirectionRoleTagValue)), i.timeSource.Now()
340 > }
341
342 func (i *Redirection) AfterCall(
346 namespaceName string,
347 retError error,
348 > ) { redirection.go
349 > // Only emit redirection metrics when actual cross-cluster redirection occurred
350 > if targetClusterName != i.currentClusterName {
351 metricsHandler = metricsHandler.WithTags(metrics.TargetClusterTag(targetClusterName))
352 metrics.ClientRedirectionLatency.With(metricsHandler).Record(i.timeSource.Now().Sub(startTime))
362 func (i *Redirection) RedirectionAllowed(
363 ctx context.Context,
364 > ) bool { redirection.go
365 > // default to allow dc redirection
366 > values := metadata.ValueFromIncomingContext(ctx, DCRedirectionContextHeaderName)
367 > if len(values) == 0 {
368 > return true redirection.go
369 > }
370 allowed, err := strconv.ParseBool(values[0])
371 if err != nil {
go.temporal.io/server/service/history/shard/ownership.go 68 covered LOC · 17 ranges

Open complete file

44 logger log.Logger,
45 metricsHandler metrics.Handler,
46 > ) *ownership { ownership.go
47 > hostIdentity := hostInfoProvider.HostInfo().Identity()
48 > logger = log.With(logger, tag.ComponentShardController, tag.Address(hostIdentity))
49 > return &ownership{
50 > acquireCh: make(chan struct{}, 1),
51 > config: config,
52 > historyServiceResolver: historyServiceResolver,
53 > hostInfoProvider: hostInfoProvider,
54 > logger: logger,
55 > membershipUpdateCh: make(chan *membership.ChangedEvent, 1),
56 > metricsHandler: metricsHandler,
57 > }
58 > }
59
60 > func (o *ownership) start(controller *ControllerImpl) { ownership.go
61 > o.goros.Go(func(ctx context.Context) error {
62 > o.eventLoop(ctx)
63 > return nil
64 > })
65
66 > o.goros.Go(func(ctx context.Context) error { ownership.go
67 > o.acquireLoop(ctx, controller)
68 > return nil
69 > })
70
71 > if err := o.historyServiceResolver.AddListener( ownership.go
72 > shardControllerMembershipUpdateListenerName,
73 > o.membershipUpdateCh,
74 > ); err != nil {
75 o.logger.Fatal("Error adding listener", tag.Error(err))
76 }
77 }
78
79 > func (o *ownership) eventLoop(ctx context.Context) { ownership.go
80 > acquireTicker := time.NewTicker(o.config.AcquireShardInterval())
81 > defer acquireTicker.Stop()
82 >
83 > for {
84 > select {
85 > case <-ctx.Done(): ownership.go
86 > return
87 case <-acquireTicker.C:
88 o.scheduleAcquire()
89 > case changedEvent := <-o.membershipUpdateCh: ownership.go
90 > metrics.MembershipChangedCounter.With(o.metricsHandler).Record(1)
91 >
92 > o.logger.Info("", tag.ValueRingMembershipChangedEvent,
93 > tag.NumberProcessed(len(changedEvent.HostsAdded)),
94 > tag.NumberDeleted(len(changedEvent.HostsRemoved)),
95 > tag.NumberChanged(len(changedEvent.HostsChanged)),
96 > )
97 >
98 > o.scheduleAcquire()
99 }
100 }
101 }
102
103 > func (o *ownership) scheduleAcquire() { ownership.go
104 > select {
105 > case o.acquireCh <- struct{}{}:
106 default:
107 }
108 }
109
110 > func (o *ownership) acquireLoop(ctx context.Context, controller *ControllerImpl) { ownership.go
111 > for {
112 > select {
113 > case <-ctx.Done(): ownership.go
114 > return
115 > case <-o.acquireCh: ownership.go
116 > controller.acquireShards(ctx)
117 }
118 }
119 }
120
121 > func (o *ownership) stop() { ownership.go
122 > if err := o.historyServiceResolver.RemoveListener(
123 > shardControllerMembershipUpdateListenerName,
124 > ); err != nil {
125 o.logger.Error("Error removing membership update listener", tag.Error(err), tag.OperationFailed)
126 }
127
128 > o.goros.Cancel() ownership.go
129 > o.goros.Wait()
130 }
131
133 // controller. If membership lists another host as the owner, it returns a
134 // ShardOwnershipLost error with the correct owner.
135 > func (o *ownership) verifyOwnership(shardID int32) error { ownership.go
136 > ownerInfo, err := o.historyServiceResolver.Lookup(convert.Int32ToString(shardID))
137 > if err != nil {
138 > return err ownership.go
139 > }
140
141 > hostInfo := o.hostInfoProvider.HostInfo() ownership.go
142 > if ownerInfo.Identity() != hostInfo.Identity() {
143 return serviceerrors.NewShardOwnershipLost(ownerInfo.Identity(), hostInfo.GetAddress())
144 }
145
146 > return nil ownership.go
147 }
go.temporal.io/server/api/persistence/v1/history_tree.pb.go 67 covered LOC · 13 ranges

Open complete file

53 func (*HistoryTreeInfo) ProtoMessage() {}
54
55 > func (x *HistoryTreeInfo) ProtoReflect() protoreflect.Message { history_tree.pb.go
56 > mi := &file_temporal_server_api_persistence_v1_history_tree_proto_msgTypes[0]
57 > if x != nil {
58 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
59 > if ms.LoadMessageInfo() == nil {
60 > ms.StoreMessageInfo(mi)
61 > }
62 > return ms
63 }
64 return mi.MessageOf(x)
109 }
110
111 > func (x *HistoryBranch) Reset() { history_tree.pb.go
112 > *x = HistoryBranch{}
113 > mi := &file_temporal_server_api_persistence_v1_history_tree_proto_msgTypes[1]
114 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
115 > ms.StoreMessageInfo(mi)
116 > }
117
118 func (x *HistoryBranch) String() string {
122 func (*HistoryBranch) ProtoMessage() {}
123
124 > func (x *HistoryBranch) ProtoReflect() protoreflect.Message { history_tree.pb.go
125 > mi := &file_temporal_server_api_persistence_v1_history_tree_proto_msgTypes[1]
126 > if x != nil {
127 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
128 > if ms.LoadMessageInfo() == nil {
129 > ms.StoreMessageInfo(mi)
130 > }
131 > return ms
132 }
133 > return mi.MessageOf(x) history_tree.pb.go
134 }
135
139 }
140
141 > func (x *HistoryBranch) GetTreeId() string { history_tree.pb.go
142 > if x != nil {
143 > return x.TreeId
144 > }
145 return ""
146 }
147
148 > func (x *HistoryBranch) GetBranchId() string { history_tree.pb.go
149 > if x != nil {
150 > return x.BranchId
151 > }
152 return ""
153 }
186 func (*HistoryBranchRange) ProtoMessage() {}
187
188 > func (x *HistoryBranchRange) ProtoReflect() protoreflect.Message { history_tree.pb.go
189 > mi := &file_temporal_server_api_persistence_v1_history_tree_proto_msgTypes[2]
190 > if x != nil {
191 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
192 if ms.LoadMessageInfo() == nil {
203 }
204
205 > func (x *HistoryBranchRange) GetBranchId() string { history_tree.pb.go
206 > if x != nil {
207 > return x.BranchId
208 > }
209 return ""
210 }
211
212 > func (x *HistoryBranchRange) GetBeginNodeId() int64 { history_tree.pb.go
213 > if x != nil {
214 > return x.BeginNodeId
215 > }
216 return 0
217 }
218
219 > func (x *HistoryBranchRange) GetEndNodeId() int64 { history_tree.pb.go
220 > if x != nil {
221 > return x.EndNodeId
222 > }
223 return 0
224 }
274 }
275
276 > func init() { file_temporal_server_api_persistence_v1_history_tree_proto_init() } history_tree.pb.go
277 > func file_temporal_server_api_persistence_v1_history_tree_proto_init() {
278 > if File_temporal_server_api_persistence_v1_history_tree_proto != nil {
279 return
280 }
281 > type x struct{} history_tree.pb.go
282 > out := protoimpl.TypeBuilder{
283 > File: protoimpl.DescBuilder{
284 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
285 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_history_tree_proto_rawDesc), len(file_temporal_server_api_persistence_v1_history_tree_proto_rawDesc)),
286 > NumEnums: 0,
287 > NumMessages: 3,
288 > NumExtensions: 0,
289 > NumServices: 0,
290 > },
291 > GoTypes: file_temporal_server_api_persistence_v1_history_tree_proto_goTypes,
292 > DependencyIndexes: file_temporal_server_api_persistence_v1_history_tree_proto_depIdxs,
293 > MessageInfos: file_temporal_server_api_persistence_v1_history_tree_proto_msgTypes,
294 > }.Build()
295 > File_temporal_server_api_persistence_v1_history_tree_proto = out.File
296 > file_temporal_server_api_persistence_v1_history_tree_proto_goTypes = nil
297 > file_temporal_server_api_persistence_v1_history_tree_proto_depIdxs = nil
298 }
go.temporal.io/server/chasm/lib/activity/library.go 67 covered LOC · 6 ranges

Open complete file

44 config *Config,
45 namespaceRegistry namespace.Registry,
46 > ) *componentOnlyLibrary { library.go
47 > return &componentOnlyLibrary{
48 > config: config,
49 > namespaceRegistry: namespaceRegistry,
50 > }
51 > }
52
53 > func (l *componentOnlyLibrary) Name() string { library.go
54 > return libraryName
55 > }
56
57 > func (l *componentOnlyLibrary) Components() []*chasm.RegistrableComponent { library.go
58 > return []*chasm.RegistrableComponent{
59 > chasm.NewRegistrableComponent[*Activity](
60 > componentName,
61 > chasm.WithSearchAttributes(
62 > TypeSearchAttribute,
63 > StatusSearchAttribute,
64 > chasm.SearchAttributeTaskQueue,
65 > chasm.SearchAttributeExecutionTime,
66 > ),
67 > chasm.WithBusinessIDAlias("ActivityId"),
68 > chasm.WithContextValues(map[any]any{
69 > ctxKeyActivityContext: &activityContext{
70 > config: l.config,
71 > namespaceRegistry: l.namespaceRegistry,
72 > },
73 > }),
74 > ),
75 > }
76 > }
77
78 // NewNilLibrary creates a Library with all nil handlers. Useful for
104 config *Config,
105 namespaceRegistry namespace.Registry,
106 > ) *library { library.go
107 > return &library{
108 > componentOnlyLibrary: *newComponentOnlyLibrary(config, namespaceRegistry),
109 > handler: handler,
110 > activityDispatchTaskHandler: activityDispatchTaskHandler,
111 > scheduleToStartTimeoutTaskHandler: scheduleToStartTimeoutTaskHandler,
112 > scheduleToCloseTimeoutTaskHandler: scheduleToCloseTimeoutTaskHandler,
113 > startToCloseTimeoutTaskHandler: startToCloseTimeoutTaskHandler,
114 > heartbeatTimeoutTaskHandler: heartbeatTimeoutTaskHandler,
115 > }
116 > }
117
118 > func (l *library) RegisterServices(server *grpc.Server) { library.go
119 > server.RegisterService(&activitypb.ActivityService_ServiceDesc, l.handler)
120 > }
121
122 > func (l *library) Tasks() []*chasm.RegistrableTask { library.go
123 > return []*chasm.RegistrableTask{
124 > chasm.NewRegistrableSideEffectTask(
125 > "dispatch",
126 > l.activityDispatchTaskHandler,
127 > ),
128 > chasm.NewRegistrablePureTask(
129 > "scheduleToStartTimer",
130 > l.scheduleToStartTimeoutTaskHandler,
131 > ),
132 > chasm.NewRegistrablePureTask(
133 > "scheduleToCloseTimer",
134 > l.scheduleToCloseTimeoutTaskHandler,
135 > ),
136 > chasm.NewRegistrablePureTask(
137 > "startToCloseTimer",
138 > l.startToCloseTimeoutTaskHandler,
139 > ),
140 > chasm.NewRegistrablePureTask(
141 > "heartbeatTimer",
142 > l.heartbeatTimeoutTaskHandler,
143 > ),
144 > }
145 > }
go.temporal.io/server/common/persistence/sql/shard.go 67 covered LOC · 16 ranges

Open complete file

24 logger log.Logger,
25 serializer serialization.Serializer,
26 > ) (persistence.ShardStore, error) { shard.go
27 > return &sqlShardStore{
28 > SqlStore: NewSQLStore(db, logger, serializer),
29 > currentClusterName: currentClusterName,
30 > }, nil
31 > }
32
33 func (m *sqlShardStore) GetClusterName() string {
38 ctx context.Context,
39 request *persistence.InternalGetOrCreateShardRequest,
40 > ) (*persistence.InternalGetOrCreateShardResponse, error) { shard.go
41 > row, err := m.DB.SelectFromShards(ctx, sqlplugin.ShardsFilter{
42 > ShardID: request.ShardID,
43 > })
44 > switch err {
45 case nil:
46 return &persistence.InternalGetOrCreateShardResponse{
47 ShardInfo: persistence.NewDataBlob(row.Data, row.DataEncoding),
48 }, nil
49 > case sql.ErrNoRows: shard.go
50 default:
51 return nil, serviceerror.NewUnavailablef("GetOrCreateShard: failed to get ShardID %v. Error: %v", request.ShardID, err)
52 }
53
54 > if request.CreateShardInfo == nil { shard.go
55 return nil, serviceerror.NewNotFoundf("GetOrCreateShard: ShardID %v not found. Error: %v", request.ShardID, err)
56 }
57
58 > rangeID, shardInfo, err := request.CreateShardInfo() shard.go
59 > if err != nil {
60 return nil, serviceerror.NewUnavailablef("GetOrCreateShard: failed to encode shard info for ShardID %v. Error: %v", request.ShardID, err)
61 }
62 > row = &sqlplugin.ShardsRow{ shard.go
63 > ShardID: request.ShardID,
64 > RangeID: rangeID,
65 > Data: shardInfo.Data,
66 > DataEncoding: shardInfo.EncodingType.String(),
67 > }
68 > _, err = m.DB.InsertIntoShards(ctx, row)
69 > if err == nil {
70 > return &persistence.InternalGetOrCreateShardResponse{
71 > ShardInfo: shardInfo,
72 > }, nil
73 > } else if m.DB.IsDupEntryError(err) {
74 // conflict, try again
75 request.CreateShardInfo = nil // prevent loop
83 ctx context.Context,
84 request *persistence.InternalUpdateShardRequest,
85 > ) error { shard.go
86 > return m.txExecute(ctx, "UpdateShard", func(tx sqlplugin.Tx) error {
87 > if err := lockShard(ctx,
88 > tx,
89 > request.ShardID,
90 > request.PreviousRangeID,
91 > m.logger,
92 > ); err != nil {
93 return err
94 }
95 > result, err := tx.UpdateShards(ctx, &sqlplugin.ShardsRow{ shard.go
96 > ShardID: request.ShardID,
97 > RangeID: request.RangeID,
98 > Data: request.ShardInfo.Data,
99 > DataEncoding: request.ShardInfo.EncodingType.String(),
100 > })
101 > if err != nil {
102 return err
103 }
104 > rowsAffected, err := result.RowsAffected() shard.go
105 > if err != nil {
106 return fmt.Errorf("rowsAffected returned error for shardID %v: %v", request.ShardID, err)
107 }
108 > if rowsAffected != 1 { shard.go
109 return fmt.Errorf("rowsAffected returned %v shards instead of one", rowsAffected)
110 }
111 > return nil shard.go
112 })
113 }
116 ctx context.Context,
117 request *persistence.AssertShardOwnershipRequest,
118 > ) error { shard.go
119 > // AssertShardOwnership is not implemented for sql shard store
120 > return nil
121 > }
122
123 // initiated by the owning shard
128 oldRangeID int64,
129 logger log.Logger,
130 > ) error { shard.go
131 >
132 > rangeID, err := tx.WriteLockShards(ctx, sqlplugin.ShardsFilter{
133 > ShardID: shardID,
134 > })
135 > switch err {
136 > case nil:
137 > if rangeID != oldRangeID {
138 return &persistence.ShardOwnershipLostError{
139 ShardID: shardID,
141 }
142 }
143 > return nil shard.go
144 case sql.ErrNoRows:
145 return serviceerror.NewUnavailablef("Failed to lock shard with ID %v that does not exist.", shardID)
155 shardID int32,
156 oldRangeID int64,
157 > ) error { shard.go
158 > rangeID, err := tx.ReadLockShards(ctx, sqlplugin.ShardsFilter{
159 > ShardID: shardID,
160 > })
161 > switch err {
162 > case nil:
163 > if rangeID != oldRangeID {
164 return &persistence.ShardOwnershipLostError{
165 ShardID: shardID,
167 }
168 }
169 > return nil shard.go
170 case sql.ErrNoRows:
171 return serviceerror.NewUnavailablef("Failed to lock shard with ID %v that does not exist.", shardID)
go.temporal.io/server/api/persistence/v1/task_queues.pb.go 66 covered LOC · 30 ranges

Open complete file

425 }
426
427 > func (x *VersioningData) GetVersionSets() []*CompatibleVersionSet { task_queues.pb.go
428 > if x != nil {
429 return x.VersionSets
430 }
431 > return nil task_queues.pb.go
432 }
433
434 > func (x *VersioningData) GetAssignmentRules() []*AssignmentRule { task_queues.pb.go
435 > if x != nil {
436 return x.AssignmentRules
437 }
438 > return nil task_queues.pb.go
439 }
440
441 > func (x *VersioningData) GetRedirectRules() []*RedirectRule { task_queues.pb.go
442 > if x != nil {
443 return x.RedirectRules
444 }
445 > return nil task_queues.pb.go
446 }
447
605 func (*TaskQueueTypeUserData) ProtoMessage() {}
606
607 > func (x *TaskQueueTypeUserData) ProtoReflect() protoreflect.Message { task_queues.pb.go
608 > mi := &file_temporal_server_api_persistence_v1_task_queues_proto_msgTypes[7]
609 > if x != nil {
610 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
611 if ms.LoadMessageInfo() == nil {
622 }
623
624 > func (x *TaskQueueTypeUserData) GetDeploymentData() *DeploymentData { task_queues.pb.go
625 > if x != nil {
626 return x.DeploymentData
627 }
628 > return nil task_queues.pb.go
629 }
630
631 > func (x *TaskQueueTypeUserData) GetConfig() *v11.TaskQueueConfig { task_queues.pb.go
632 > if x != nil {
633 return x.Config
634 }
635 > return nil task_queues.pb.go
636 }
637
638 > func (x *TaskQueueTypeUserData) GetFairnessState() v14.FairnessState { task_queues.pb.go
639 > if x != nil {
640 return x.FairnessState
641 }
642 > return v14.FairnessState(0) task_queues.pb.go
643 }
644
675 func (*TaskQueueUserData) ProtoMessage() {}
676
677 > func (x *TaskQueueUserData) ProtoReflect() protoreflect.Message { task_queues.pb.go
678 > mi := &file_temporal_server_api_persistence_v1_task_queues_proto_msgTypes[8]
679 > if x != nil {
680 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
681 if ms.LoadMessageInfo() == nil {
692 }
693
694 > func (x *TaskQueueUserData) GetClock() *v1.HybridLogicalClock { task_queues.pb.go
695 > if x != nil {
696 return x.Clock
697 }
698 > return nil task_queues.pb.go
699 }
700
701 > func (x *TaskQueueUserData) GetVersioningData() *VersioningData { task_queues.pb.go
702 > if x != nil {
703 return x.VersioningData
704 }
705 > return nil task_queues.pb.go
706 }
707
708 > func (x *TaskQueueUserData) GetPerType() map[int32]*TaskQueueTypeUserData { task_queues.pb.go
709 > if x != nil {
710 return x.PerType
711 }
712 > return nil task_queues.pb.go
713 }
714
735 func (*VersionedTaskQueueUserData) ProtoMessage() {}
736
737 > func (x *VersionedTaskQueueUserData) ProtoReflect() protoreflect.Message { task_queues.pb.go
738 > mi := &file_temporal_server_api_persistence_v1_task_queues_proto_msgTypes[9]
739 > if x != nil {
740 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
741 if ms.LoadMessageInfo() == nil {
752 }
753
754 > func (x *VersionedTaskQueueUserData) GetData() *TaskQueueUserData { task_queues.pb.go
755 > if x != nil {
756 return x.Data
757 }
758 > return nil task_queues.pb.go
759 }
760
761 > func (x *VersionedTaskQueueUserData) GetVersion() int64 { task_queues.pb.go
762 > if x != nil {
763 return x.Version
764 }
765 > return 0 task_queues.pb.go
766 }
767
899 }
900
901 > func init() { file_temporal_server_api_persistence_v1_task_queues_proto_init() } task_queues.pb.go
902 > func file_temporal_server_api_persistence_v1_task_queues_proto_init() {
903 > if File_temporal_server_api_persistence_v1_task_queues_proto != nil {
904 return
905 }
906 > type x struct{} task_queues.pb.go
907 > out := protoimpl.TypeBuilder{
908 > File: protoimpl.DescBuilder{
909 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
910 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_task_queues_proto_rawDesc), len(file_temporal_server_api_persistence_v1_task_queues_proto_rawDesc)),
911 > NumEnums: 1,
912 > NumMessages: 13,
913 > NumExtensions: 0,
914 > NumServices: 0,
915 > },
916 > GoTypes: file_temporal_server_api_persistence_v1_task_queues_proto_goTypes,
917 > DependencyIndexes: file_temporal_server_api_persistence_v1_task_queues_proto_depIdxs,
918 > EnumInfos: file_temporal_server_api_persistence_v1_task_queues_proto_enumTypes,
919 > MessageInfos: file_temporal_server_api_persistence_v1_task_queues_proto_msgTypes,
920 > }.Build()
921 > File_temporal_server_api_persistence_v1_task_queues_proto = out.File
922 > file_temporal_server_api_persistence_v1_task_queues_proto_goTypes = nil
923 > file_temporal_server_api_persistence_v1_task_queues_proto_depIdxs = nil
924 }
go.temporal.io/server/common/membership/grpc_resolver.go 66 covered LOC · 19 ranges

Open complete file

53 )
54
55 > func init() { grpc_resolver.go
56 > // This must be called in init to avoid race conditions.
57 > resolver.Register(&globalGrpcBuilder)
58 > }
59
60 // Most code should not use this, this is only exposed for code that has to recognize and use a
61 // grpc membership url outside of grpc.
62 > func GetServiceResolverFromURL(u *url.URL) (ServiceResolver, error) { grpc_resolver.go
63 > return globalGrpcBuilder.getServiceResolver(u)
64 > }
65
66 // This should only be used in unit tests. For normal code, use the *GRPCResolver provided by fx.
70 }
71
72 > func newGRPCResolver(monitor Monitor) *GRPCResolver { grpc_resolver.go
73 > res := &GRPCResolver{monitor: monitor}
74 > globalGrpcBuilder.resolvers.Store(fmt.Sprintf("%p", res), res)
75 > return res
76 > }
77
78 > func (g *GRPCResolver) MakeURL(service primitives.ServiceName) string { grpc_resolver.go
79 > return fmt.Sprintf("%s://%s%s%p", grpcResolverScheme, string(service), delim, g)
80 > }
81
82 > func (m *grpcBuilder) Scheme() string { grpc_resolver.go
83 > return grpcResolverScheme
84 > }
85
86 > func (m *grpcBuilder) getServiceResolver(u *url.URL) (ServiceResolver, error) { grpc_resolver.go
87 > if u.Scheme != grpcResolverScheme {
88 return nil, errInvalidUrl
89 }
90 > service, ptr, found := strings.Cut(u.Host, delim) grpc_resolver.go
91 > if !found {
92 return nil, errInvalidUrl
93 }
94 > v, ok := m.resolvers.Load(ptr) grpc_resolver.go
95 > if !ok {
96 return nil, errNotInitialized
97 }
98 > return v.(*GRPCResolver).monitor.GetResolver(primitives.ServiceName(service)) grpc_resolver.go
99 }
100
101 > func (m *grpcBuilder) Build(target resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (resolver.Resolver, error) { grpc_resolver.go
102 > serviceResolver, err := m.getServiceResolver(&target.URL)
103 > if err != nil {
104 return nil, err
105 }
106 > grpcResolver := &grpcResolver{ grpc_resolver.go
107 > cc: cc,
108 > r: serviceResolver,
109 > notifyCh: make(chan *ChangedEvent, 1),
110 > }
111 > if err := grpcResolver.start(); err != nil {
112 return nil, err
113 }
114 > return grpcResolver, nil grpc_resolver.go
115 }
116
117 > func (m *grpcResolver) start() error { grpc_resolver.go
118 > if err := m.r.AddListener(fmt.Sprintf("%p", m), m.notifyCh); err != nil {
119 return err
120 }
121 > m.wg.Add(1) grpc_resolver.go
122 > go m.listen()
123 >
124 > // Try once to get address synchronously. If this fails, it's okay, we'll listen for
125 > // changes and update the resolver later.
126 > m.resolve()
127 > return nil
128 }
129
130 > func (m *grpcResolver) listen() { grpc_resolver.go
131 > for range m.notifyCh {
132 > m.resolve()
133 > }
134 m.wg.Done()
135 }
136
137 > func (m *grpcResolver) resolve() { grpc_resolver.go
138 > members := m.r.AvailableMembers()
139 > if len(members) == 0 {
140 > // grpc considers it an error if we report no addresses, and fails the connection eagerly. grpc_resolver.go
141 > // Instead, just poke membership and then wait until it notifies us.
142 > m.r.RequestRefresh()
143 > return
144 > }
145 > addresses := make([]resolver.Address, 0, len(members)) grpc_resolver.go
146 > for _, hostInfo := range members {
147 > addresses = append(addresses, resolver.Address{
148 > Addr: hostInfo.GetAddress(),
149 > })
150 > }
151 > if err := m.cc.UpdateState(resolver.State{Addresses: addresses}); err != nil {
152 fmt.Printf("error updating state in gRPC resolver: %v", err)
153 }
154 }
155
156 > func (m *grpcResolver) ResolveNow(_ resolver.ResolveNowOptions) { grpc_resolver.go
157 > select {
158 > case m.notifyCh <- nil:
159 default:
160 }
go.temporal.io/server/common/metrics/runtime.go 66 covered LOC · 10 ranges

Open complete file

37 logger log.Logger,
38 instanceID string,
39 > ) *RuntimeMetricsReporter { runtime.go
40 > if len(instanceID) > 0 {
41 handler = handler.WithTags(StringTag(instance, instanceID))
42 }
43 > var memstats runtime.MemStats runtime.go
44 > runtime.ReadMemStats(&memstats)
45 >
46 > return &RuntimeMetricsReporter{
47 > handler: handler,
48 > reportInterval: reportInterval,
49 > logger: logger,
50 > lastNumGC: memstats.NumGC,
51 > quit: make(chan struct{}),
52 > buildTime: build.InfoData.GitTime,
53 > buildInfoHandler: handler.WithTags(
54 > StringTag(gitRevisionTag, build.InfoData.GitRevision),
55 > StringTag(buildDateTag, build.InfoData.GitTime.Format(time.RFC3339)),
56 > StringTag(buildPlatformTag, build.InfoData.GoArch),
57 > StringTag(goVersionTag, build.InfoData.GoVersion),
58 > StringTag(buildVersionTag, headers.ServerVersion),
59 > ),
60 > }
61 }
62
63 // report Sends runtime metrics to the local metrics collector.
64 > func (r *RuntimeMetricsReporter) report() { runtime.go
65 > var memStats runtime.MemStats
66 > runtime.ReadMemStats(&memStats)
67 >
68 > NumGoRoutinesGauge.With(r.handler).Record(float64(runtime.NumGoroutine()))
69 > GoMaxProcsGauge.With(r.handler).Record(float64(runtime.GOMAXPROCS(0)))
70 > MemoryAllocatedGauge.With(r.handler).Record(float64(memStats.Alloc))
71 > MemoryHeapGauge.With(r.handler).Record(float64(memStats.HeapAlloc))
72 > MemoryHeapObjectsGauge.With(r.handler).Record(float64(memStats.HeapObjects))
73 > MemoryHeapIdleGauge.With(r.handler).Record(float64(memStats.HeapIdle))
74 > MemoryHeapInuseGauge.With(r.handler).Record(float64(memStats.HeapInuse))
75 > MemoryHeapReleasedGauge.With(r.handler).Record(float64(memStats.HeapReleased))
76 > MemoryStackGauge.With(r.handler).Record(float64(memStats.StackInuse))
77 > MemoryMallocsGauge.With(r.handler).Record(float64(memStats.Mallocs))
78 > MemoryFreesGauge.With(r.handler).Record(float64(memStats.Frees))
79 >
80 > NumGCGauge.With(r.handler).Record(float64(memStats.NumGC))
81 > GcPauseNsTotal.With(r.handler).Record(float64(memStats.PauseTotalNs))
82 >
83 > // memStats.NumGC is a perpetually incrementing counter (unless it wraps at 2^32)
84 > num := memStats.NumGC
85 > lastNum := atomic.SwapUint32(&r.lastNumGC, num) // reset for the next iteration
86 > if delta := num - lastNum; delta > 0 {
87 > NumGCCounter.With(r.handler).Record(int64(delta))
88 > if delta > 255 {
89 // too many GCs happened, the timestamps buffer got wrapped around. Report only the last 256
90 lastNum = num - 256
91 }
92 > for i := lastNum; i != num; i++ { runtime.go
93 > pause := memStats.PauseNs[i%256]
94 > GcPauseMsTimer.With(r.handler).Record(time.Duration(pause))
95 > }
96 }
97
98 // report build info
99 > r.buildInfoHandler.Gauge(buildInfoMetricName).Record(1.0) runtime.go
100 > r.buildInfoHandler.Gauge(buildAgeMetricName).Record(float64(time.Since(r.buildTime)))
101 }
102
103 // Start Starts the reporter thread that periodically emits metrics.
104 > func (r *RuntimeMetricsReporter) Start() { runtime.go
105 > if !atomic.CompareAndSwapInt32(&r.started, 0, 1) {
106 return
107 }
108 > r.report() runtime.go
109 > go func() {
110 > ticker := time.NewTicker(r.reportInterval)
111 > for {
112 > select {
113 case <-ticker.C:
114 r.report()
115 > case <-r.quit: runtime.go
116 > ticker.Stop()
117 > return
118 }
119 }
120 }()
121 > r.logger.Info("RuntimeMetricsReporter started") runtime.go
122 }
123
124 // Stop Stops reporting of runtime metrics. The reporter cannot be started again after it's been stopped.
125 > func (r *RuntimeMetricsReporter) Stop() { runtime.go
126 > close(r.quit)
127 > r.logger.Info("RuntimeMetricsReporter stopped")
128 > }
go.temporal.io/server/common/persistence/cluster_metadata_store.go 65 covered LOC · 22 ranges

Open complete file

37 currentClusterName string,
38 logger log.Logger,
39 > ) ClusterMetadataManager { cluster_metadata_store.go
40 > return &clusterMetadataManagerImpl{
41 > serializer: serializer,
42 > persistence: persistence,
43 > currentClusterName: currentClusterName,
44 > logger: logger,
45 > }
46 > }
47
48 func (m *clusterMetadataManagerImpl) GetName() string {
50 }
51
52 > func (m *clusterMetadataManagerImpl) Close() { cluster_metadata_store.go
53 > m.persistence.Close()
54 > }
55
56 func (m *clusterMetadataManagerImpl) GetClusterMembers(
57 ctx context.Context,
58 request *GetClusterMembersRequest,
59 > ) (*GetClusterMembersResponse, error) { cluster_metadata_store.go
60 > return m.persistence.GetClusterMembers(ctx, request)
61 > }
62
63 func (m *clusterMetadataManagerImpl) UpsertClusterMembership(
64 ctx context.Context,
65 request *UpsertClusterMembershipRequest,
66 > ) error { cluster_metadata_store.go
67 > if request.RecordExpiry.Seconds() < 1 {
68 return ErrInvalidMembershipExpiry
69 }
70 > if request.Role == All { cluster_metadata_store.go
71 return ErrIncompleteMembershipUpsert
72 }
73 > if request.RPCAddress == nil { cluster_metadata_store.go
74 return ErrIncompleteMembershipUpsert
75 }
76 > if request.RPCPort == 0 { cluster_metadata_store.go
77 return ErrIncompleteMembershipUpsert
78 }
79 > if request.SessionStart.IsZero() { cluster_metadata_store.go
80 return ErrIncompleteMembershipUpsert
81 }
82
83 > return m.persistence.UpsertClusterMembership(ctx, request) cluster_metadata_store.go
84 }
85
87 ctx context.Context,
88 request *PruneClusterMembershipRequest,
89 > ) error { cluster_metadata_store.go
90 > return m.persistence.PruneClusterMembership(ctx, request)
91 > }
92
93 func (m *clusterMetadataManagerImpl) ListClusterMetadata(
94 ctx context.Context,
95 request *ListClusterMetadataRequest,
96 > ) (*ListClusterMetadataResponse, error) { cluster_metadata_store.go
97 > resp, err := m.persistence.ListClusterMetadata(ctx, &InternalListClusterMetadataRequest{
98 > PageSize: request.PageSize,
99 > NextPageToken: request.NextPageToken,
100 > })
101 > if err != nil {
102 return nil, err
103 }
104
105 > clusterMetadata := make([]*GetClusterMetadataResponse, 0, len(resp.ClusterMetadata)) cluster_metadata_store.go
106 > for _, cm := range resp.ClusterMetadata {
107 > res, err := m.convertInternalGetClusterMetadataResponse(cm)
108 > if err != nil {
109 return nil, err
110 }
111 > clusterMetadata = append(clusterMetadata, res) cluster_metadata_store.go
112 }
113 > return &ListClusterMetadataResponse{ClusterMetadata: clusterMetadata, NextPageToken: resp.NextPageToken}, nil cluster_metadata_store.go
114 }
115
116 func (m *clusterMetadataManagerImpl) GetCurrentClusterMetadata(
117 ctx context.Context,
118 > ) (*GetClusterMetadataResponse, error) { cluster_metadata_store.go
119 > resp, err := m.persistence.GetClusterMetadata(ctx, &InternalGetClusterMetadataRequest{ClusterName: m.currentClusterName})
120 > if err != nil {
121 return nil, err
122 }
123
124 > mcm, err := m.serializer.DeserializeClusterMetadata(resp.ClusterMetadata) cluster_metadata_store.go
125 > if err != nil {
126 return nil, err
127 }
128 > return &GetClusterMetadataResponse{ClusterMetadata: mcm, Version: resp.Version}, nil cluster_metadata_store.go
129 }
130
132 ctx context.Context,
133 request *GetClusterMetadataRequest,
134 > ) (*GetClusterMetadataResponse, error) { cluster_metadata_store.go
135 > resp, err := m.persistence.GetClusterMetadata(ctx, &InternalGetClusterMetadataRequest{ClusterName: request.ClusterName})
136 > if err != nil {
137 > return nil, err
138 > }
139
140 mcm, err := m.serializer.DeserializeClusterMetadata(resp.ClusterMetadata)
148 ctx context.Context,
149 request *SaveClusterMetadataRequest,
150 > ) (bool, error) { cluster_metadata_store.go
151 > mcm, err := m.serializer.SerializeClusterMetadata(request.ClusterMetadata)
152 > if err != nil {
153 return false, err
154 }
155
156 > oldClusterMetadata, err := m.GetClusterMetadata(ctx, &GetClusterMetadataRequest{ClusterName: request.GetClusterName()}) cluster_metadata_store.go
157 > if _, isNotFound := err.(*serviceerror.NotFound); isNotFound {
158 > return m.persistence.SaveClusterMetadata(ctx, &InternalSaveClusterMetadataRequest{
159 > ClusterName: request.ClusterName,
160 > ClusterMetadata: mcm,
161 > Version: request.Version,
162 > })
163 > }
164 if err != nil {
165 return false, err
189 func (m *clusterMetadataManagerImpl) convertInternalGetClusterMetadataResponse(
190 resp *InternalGetClusterMetadataResponse,
191 > ) (*GetClusterMetadataResponse, error) { cluster_metadata_store.go
192 > mcm, err := m.serializer.DeserializeClusterMetadata(resp.ClusterMetadata)
193 > if err != nil {
194 return nil, err
195 }
196
197 > return &GetClusterMetadataResponse{ cluster_metadata_store.go
198 > ClusterMetadata: mcm,
199 > Version: resp.Version,
200 > }, nil
201 }
202
go.temporal.io/server/common/rpc/encryption/local_store_tls_provider.go 65 covered LOC · 13 ranges

Open complete file

54
55 func NewLocalStoreTlsProvider(tlsConfig *config.RootTLS, metricsHandler metrics.Handler, logger log.Logger, certProviderFactory CertProviderFactory,
56 > ) (TLSConfigProvider, error) { local_store_tls_provider.go
57 >
58 > internodeProvider := certProviderFactory(&tlsConfig.Internode, nil, nil, tlsConfig.RefreshInterval, logger)
59 > var workerProvider CertProvider
60 > if isSystemWorker(tlsConfig) { // explicit system worker config
61 workerProvider = certProviderFactory(nil, &tlsConfig.SystemWorker, nil, tlsConfig.RefreshInterval, logger)
62 > } else { // legacy implicit system worker config case local_store_tls_provider.go
63 > internodeWorkerProvider := certProviderFactory(&tlsConfig.Internode, nil, &tlsConfig.Frontend.Client, tlsConfig.RefreshInterval, logger)
64 > workerProvider = internodeWorkerProvider
65 > }
66
67 > remoteClusterClientCertProvider := make(map[string]CertProvider) local_store_tls_provider.go
68 > for key, groupTLS := range tlsConfig.RemoteClusters {
69 remoteClusterClientCertProvider[key] = certProviderFactory(&groupTLS, nil, nil, tlsConfig.RefreshInterval, logger)
70 }
71
72 > provider := &localStoreTlsProvider{ local_store_tls_provider.go
73 > internodeCertProvider: internodeProvider,
74 > internodeClientCertProvider: internodeProvider,
75 > frontendCertProvider: certProviderFactory(&tlsConfig.Frontend, nil, nil, tlsConfig.RefreshInterval, logger),
76 > workerCertProvider: workerProvider,
77 > frontendPerHostCertProviderMap: newLocalStorePerHostCertProviderMap(
78 > tlsConfig.Frontend.PerHostOverrides, certProviderFactory, tlsConfig.RefreshInterval, logger),
79 > remoteClusterClientCertProvider: remoteClusterClientCertProvider,
80 > RWMutex: sync.RWMutex{},
81 > settings: tlsConfig,
82 > metricsHandler: metricsHandler,
83 > logger: logger,
84 > cachedRemoteClusterClientConfig: make(map[string]*tls.Config),
85 > }
86 > provider.initialize()
87 > return provider, nil
88 }
89
90 > func (s *localStoreTlsProvider) initialize() { local_store_tls_provider.go
91 > period := s.settings.ExpirationChecks.CheckInterval
92 > if period != 0 {
93 s.stop = make(chan bool)
94 s.ticker = time.NewTicker(period)
109 }
110
111 > func (s *localStoreTlsProvider) GetInternodeClientConfig() (*tls.Config, error) { local_store_tls_provider.go
112 >
113 > client := &s.settings.Internode.Client
114 > return s.getOrCreateConfig(
115 > &s.cachedInternodeClientConfig,
116 > func() (*tls.Config, error) {
117 return newClientTLSConfig(s.internodeClientCertProvider, client.ServerName,
118 s.settings.Internode.Server.RequireClientAuth, false, !client.DisableHostVerification)
122 }
123
124 > func (s *localStoreTlsProvider) GetFrontendClientConfig() (*tls.Config, error) { local_store_tls_provider.go
125 >
126 > var client *config.ClientTLS
127 > var useTLS bool
128 > if isSystemWorker(s.settings) {
129 client = &s.settings.SystemWorker.Client
130 useTLS = true
132 > client = &s.settings.Frontend.Client
133 > useTLS = s.settings.Frontend.IsClientEnabled()
134 > }
135 > return s.getOrCreateConfig(
136 > &s.cachedFrontendClientConfig,
137 > func() (*tls.Config, error) {
138 return newClientTLSConfig(s.workerCertProvider, client.ServerName,
139 useTLS, true, !client.DisableHostVerification)
163 }
164
165 > func (s *localStoreTlsProvider) GetFrontendServerConfig() (*tls.Config, error) { local_store_tls_provider.go
166 > return s.getOrCreateConfig(
167 > &s.cachedFrontendServerConfig,
168 > func() (*tls.Config, error) {
169 return newServerTLSConfig(s.frontendCertProvider, s.frontendPerHostCertProviderMap, &s.settings.Frontend, s.logger)
170 },
172 }
173
174 > func (s *localStoreTlsProvider) GetInternodeServerConfig() (*tls.Config, error) { local_store_tls_provider.go
175 > return s.getOrCreateConfig(
176 > &s.cachedInternodeServerConfig,
177 > func() (*tls.Config, error) {
178 return newServerTLSConfig(s.internodeCertProvider, nil, &s.settings.Internode, s.logger)
179 },
473 }
474
475 > func isSystemWorker(tls *config.RootTLS) bool { local_store_tls_provider.go
476 > return tls.SystemWorker.CertData != "" || tls.SystemWorker.CertFile != "" ||
477 > len(tls.SystemWorker.Client.RootCAData) > 0 || len(tls.SystemWorker.Client.RootCAFiles) > 0 ||
478 > tls.SystemWorker.Client.ForceTLS
479 > }
480
481 // matchRemoteClusterKey checks exact matches, then finds the match with the most non-wildcard characters
go.temporal.io/server/api/replication/v1/message.pb.go 64 covered LOC · 16 ranges

Open complete file

74 func (*ReplicationTask) ProtoMessage() {}
75
76 > func (x *ReplicationTask) ProtoReflect() protoreflect.Message { message.pb.go
77 > mi := &file_temporal_server_api_replication_v1_message_proto_msgTypes[0]
78 > if x != nil {
79 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
80 if ms.LoadMessageInfo() == nil {
83 return ms
84 }
85 > return mi.MessageOf(x) message.pb.go
86 }
87
328 func (*ReplicationToken) ProtoMessage() {}
329
330 > func (x *ReplicationToken) ProtoReflect() protoreflect.Message { message.pb.go
331 > mi := &file_temporal_server_api_replication_v1_message_proto_msgTypes[1]
332 > if x != nil {
333 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
334 if ms.LoadMessageInfo() == nil {
337 return ms
338 }
339 > return mi.MessageOf(x) message.pb.go
340 }
341
442 func (*SyncReplicationState) ProtoMessage() {}
443
444 > func (x *SyncReplicationState) ProtoReflect() protoreflect.Message { message.pb.go
445 > mi := &file_temporal_server_api_replication_v1_message_proto_msgTypes[3]
446 > if x != nil {
447 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
448 if ms.LoadMessageInfo() == nil {
451 return ms
452 }
453 > return mi.MessageOf(x) message.pb.go
454 }
455
572 func (*ReplicationMessages) ProtoMessage() {}
573
574 > func (x *ReplicationMessages) ProtoReflect() protoreflect.Message { message.pb.go
575 > mi := &file_temporal_server_api_replication_v1_message_proto_msgTypes[5]
576 > if x != nil {
577 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
578 if ms.LoadMessageInfo() == nil {
581 return ms
582 }
583 > return mi.MessageOf(x) message.pb.go
584 }
585
641 func (*WorkflowReplicationMessages) ProtoMessage() {}
642
643 > func (x *WorkflowReplicationMessages) ProtoReflect() protoreflect.Message { message.pb.go
644 > mi := &file_temporal_server_api_replication_v1_message_proto_msgTypes[6]
645 > if x != nil {
646 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
647 if ms.LoadMessageInfo() == nil {
650 return ms
651 }
652 > return mi.MessageOf(x) message.pb.go
653 }
654
716 func (*ReplicationTaskInfo) ProtoMessage() {}
717
718 > func (x *ReplicationTaskInfo) ProtoReflect() protoreflect.Message { message.pb.go
719 > mi := &file_temporal_server_api_replication_v1_message_proto_msgTypes[7]
720 > if x != nil {
721 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
722 if ms.LoadMessageInfo() == nil {
725 return ms
726 }
727 > return mi.MessageOf(x) message.pb.go
728 }
729
1952 func (*VersionedTransitionArtifact) ProtoMessage() {}
1953
1954 > func (x *VersionedTransitionArtifact) ProtoReflect() protoreflect.Message { message.pb.go
1955 > mi := &file_temporal_server_api_replication_v1_message_proto_msgTypes[21]
1956 > if x != nil {
1957 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
1958 if ms.LoadMessageInfo() == nil {
1961 return ms
1962 }
1963 > return mi.MessageOf(x) message.pb.go
1964 }
1965
2441 }
2442
2443 > func init() { file_temporal_server_api_replication_v1_message_proto_init() } message.pb.go
2444 > func file_temporal_server_api_replication_v1_message_proto_init() {
2445 > if File_temporal_server_api_replication_v1_message_proto != nil {
2446 return
2447 }
2448 > file_temporal_server_api_replication_v1_message_proto_msgTypes[0].OneofWrappers = []any{ message.pb.go
2449 > (*ReplicationTask_NamespaceTaskAttributes)(nil),
2450 > (*ReplicationTask_SyncShardStatusTaskAttributes)(nil),
2451 > (*ReplicationTask_SyncActivityTaskAttributes)(nil),
2452 > (*ReplicationTask_HistoryTaskAttributes)(nil),
2453 > (*ReplicationTask_SyncWorkflowStateTaskAttributes)(nil),
2454 > (*ReplicationTask_TaskQueueUserDataAttributes)(nil),
2455 > (*ReplicationTask_SyncHsmAttributes)(nil),
2456 > (*ReplicationTask_BackfillHistoryTaskAttributes)(nil),
2457 > (*ReplicationTask_VerifyVersionedTransitionTaskAttributes)(nil),
2458 > (*ReplicationTask_SyncVersionedTransitionTaskAttributes)(nil),
2459 > }
2460 > file_temporal_server_api_replication_v1_message_proto_msgTypes[21].OneofWrappers = []any{
2461 > (*VersionedTransitionArtifact_SyncWorkflowStateMutationAttributes)(nil),
2462 > (*VersionedTransitionArtifact_SyncWorkflowStateSnapshotAttributes)(nil),
2463 > }
2464 > type x struct{}
2465 > out := protoimpl.TypeBuilder{
2466 > File: protoimpl.DescBuilder{
2467 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
2468 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_replication_v1_message_proto_rawDesc), len(file_temporal_server_api_replication_v1_message_proto_rawDesc)),
2469 > NumEnums: 0,
2470 > NumMessages: 23,
2471 > NumExtensions: 0,
2472 > NumServices: 0,
2473 > },
2474 > GoTypes: file_temporal_server_api_replication_v1_message_proto_goTypes,
2475 > DependencyIndexes: file_temporal_server_api_replication_v1_message_proto_depIdxs,
2476 > MessageInfos: file_temporal_server_api_replication_v1_message_proto_msgTypes,
2477 > }.Build()
2478 > File_temporal_server_api_replication_v1_message_proto = out.File
2479 > file_temporal_server_api_replication_v1_message_proto_goTypes = nil
2480 > file_temporal_server_api_replication_v1_message_proto_depIdxs = nil
2481 }
go.temporal.io/server/chasm/lib/nexusoperation/library.go 64 covered LOC · 6 ranges

Open complete file

36 }
37
38 > func newComponentOnlyLibrary(dc *dynamicconfig.Collection) *componentOnlyLibrary { library.go
39 > return &componentOnlyLibrary{
40 > metricTagConfig: MetricTagConfiguration.Get(dc),
41 > }
42 > }
43
44 > func (l *componentOnlyLibrary) Name() string { library.go
45 > return libraryName
46 > }
47
48 > func (l *componentOnlyLibrary) Components() []*chasm.RegistrableComponent { library.go
49 > return []*chasm.RegistrableComponent{
50 > chasm.NewRegistrableComponent[*Operation](
51 > componentName,
52 > chasm.WithSearchAttributes(
53 > EndpointSearchAttribute,
54 > ServiceSearchAttribute,
55 > OperationSearchAttribute,
56 > RequestIDSearchAttribute,
57 > StatusSearchAttribute,
58 > ),
59 > chasm.WithBusinessIDAlias("OperationId"),
60 > chasm.WithContextValues(map[any]any{
61 > OperationContextKey: &OperationContext{
62 > MetricTagConfig: l.metricTagConfig,
63 > },
64 > }),
65 > ),
66 > chasm.NewRegistrableComponent[*Cancellation]("cancellation"),
67 > }
68 > }
69
70 type Library struct {
93 cancellationBackoffTaskHandler *cancellationBackoffTaskHandler,
94 dc *dynamicconfig.Collection,
95 > ) *Library { library.go
96 > return &Library{
97 > componentOnlyLibrary: *newComponentOnlyLibrary(dc),
98 > handler: handler,
99 > operationBackoffTaskHandler: operationBackoffTaskHandler,
100 > operationInvocationTaskHandler: operationInvocationTaskHandler,
101 > operationScheduleToCloseTimeoutTaskHandler: operationScheduleToCloseTimeoutTaskHandler,
102 > operationScheduleToStartTimeoutTaskHandler: operationScheduleToStartTimeoutTaskHandler,
103 > operationStartToCloseTimeoutTaskHandler: operationStartToCloseTimeoutTaskHandler,
104 > cancellationInvocationTaskHandler: cancellationInvocationTaskHandler,
105 > cancellationBackoffTaskHandler: cancellationBackoffTaskHandler,
106 > }
107 > }
108
109 > func (l *Library) Tasks() []*chasm.RegistrableTask { library.go
110 > return []*chasm.RegistrableTask{
111 > chasm.NewRegistrableSideEffectTask(
112 > "invocation",
113 > l.operationInvocationTaskHandler,
114 > chasm.WithTaskGroup(TaskGroupName),
115 > ),
116 > chasm.NewRegistrablePureTask("invocationBackoff", l.operationBackoffTaskHandler),
117 > chasm.NewRegistrablePureTask("scheduleToStartTimeout", l.operationScheduleToStartTimeoutTaskHandler),
118 > chasm.NewRegistrablePureTask("startToCloseTimeout", l.operationStartToCloseTimeoutTaskHandler),
119 > chasm.NewRegistrablePureTask("scheduleToCloseTimeout", l.operationScheduleToCloseTimeoutTaskHandler),
120 > chasm.NewRegistrableSideEffectTask(
121 > "cancellation",
122 > l.cancellationInvocationTaskHandler,
123 > chasm.WithTaskGroup(TaskGroupName),
124 > ),
125 > chasm.NewRegistrablePureTask("cancellationBackoff", l.cancellationBackoffTaskHandler),
126 > }
127 > }
128
129 > func (l *Library) RegisterServices(server *grpc.Server) { library.go
130 > server.RegisterService(&nexusoperationpb.NexusOperationService_ServiceDesc, l.handler)
131 > }
go.temporal.io/server/common/goro/adaptive_pool.go 64 covered LOC · 24 ranges

Open complete file

32 targetDelay time.Duration,
33 shrinkFactor float64,
34 > ) *AdaptivePool { adaptive_pool.go
35 > p := &AdaptivePool{
36 > ts: ts,
37 > minWorkers: minWorkers,
38 > maxWorkers: maxWorkers,
39 > targetDelay: targetDelay,
40 > shrinkFactor: shrinkFactor,
41 > ch: make(chan func()),
42 > stopCh: make(chan struct{}),
43 > }
44 > for range minWorkers {
45 > go p.work() adaptive_pool.go
46 > }
47 > p.workers.Store(int64(minWorkers)) adaptive_pool.go
48 > return p
49 }
50
52 // When Stop is called, concurrent calls to Do may or may not call their function, and future
53 // calls definitely won't.
54 > func (p *AdaptivePool) Stop() { adaptive_pool.go
55 > close(p.stopCh)
56 > }
57
58 // Do calls f() on a worker goroutine. If the call can't be started within targetDelay, it adds
59 // another worker. If Stop is called concurrently, Do may or may not call f. If Stop has been
60 // called already, Do does nothing.
61 > func (p *AdaptivePool) Do(f func()) { adaptive_pool.go
62 > // try send first
63 > select {
64 > case p.ch <- f: adaptive_pool.go
65 > return
66 > default: adaptive_pool.go
67 }
68
69 // we might want to add a worker, send with timeout
70 > have := p.workers.Load() adaptive_pool.go
71 > if have < int64(p.maxWorkers) {
72 > timech, timer := p.ts.NewTimer(p.targetDelay) adaptive_pool.go
73 > select {
74 case <-p.stopCh:
75 timer.Stop()
76 return
77 > case p.ch <- f: adaptive_pool.go
78 > timer.Stop()
79 > return
80 > case <-timech: adaptive_pool.go
81 }
82
83 > if p.workers.CompareAndSwap(have, have+1) { adaptive_pool.go
84 > go p.work()
85 > }
86 }
87
88 // blocking send
89 > select { adaptive_pool.go
90 > case p.ch <- f:
91 case <-p.stopCh:
92 }
93 }
94
95 > func (p *AdaptivePool) work() { adaptive_pool.go
96 > for {
97 > // try receive first
98 > select {
99 > case f := <-p.ch: adaptive_pool.go
100 > f()
101 > continue
102 > default: adaptive_pool.go
103 }
104
105 > have := p.workers.Load() adaptive_pool.go
106 > if have > int64(p.minWorkers) {
107 > // we might want to exit, receive with timeout adaptive_pool.go
108 > // jitter this so we shrink slower than we grow
109 > timech, timer := p.ts.NewTimer(time.Duration(float64(p.targetDelay) * p.shrinkFactor * rand.Float64()))
110 > select {
111 case <-p.stopCh:
112 timer.Stop()
113 return
114 > case f := <-p.ch: adaptive_pool.go
115 > timer.Stop()
116 > f()
117 > continue
118 > case <-timech: adaptive_pool.go
119 }
120 > if p.workers.CompareAndSwap(have, have-1) { adaptive_pool.go
121 > return
122 > }
123 }
124
125 // blocking receive
126 > select { adaptive_pool.go
127 > case <-p.stopCh: adaptive_pool.go
128 > return
129 > case f := <-p.ch: adaptive_pool.go
130 > f()
131 }
132 }
go.temporal.io/server/common/util/util.go 64 covered LOC · 29 ranges

Open complete file

20
21 // MaxTime returns the latest of the given time.Time values.
22 > func MaxTime(first time.Time, rest ...time.Time) time.Time { util.go
23 > latest := first
24 > for _, t := range rest {
25 > if t.After(latest) {
26 > latest = t util.go
27 > }
28 }
29 > return latest util.go
30 }
31
51
52 // SliceTail returns the last n elements of s. n may be greater than len(s).
53 > func SliceTail[S ~[]E, E any](s S, n int) S { util.go
54 > if extra := len(s) - n; extra > 0 {
55 return s[extra:]
56 }
57 > return s util.go
58 }
59
60 // CloneMapNonNil is like maps.Clone except it can't return nil, it will return an empty map instead.
61 > func CloneMapNonNil[M ~map[K]V, K comparable, V any](m M) M { util.go
62 > m = maps.Clone(m)
63 > if m == nil {
64 m = make(M)
65 }
66 > return m util.go
67 }
68
69 // InverseMap creates the inverse map, ie., for a key-value map, it builds the value-key map.
70 > func InverseMap[M ~map[K]V, K, V comparable](m M) map[V]K { util.go
71 > if m == nil {
72 > return nil
73 > }
74 invm := make(map[V]K, len(m))
75 for k, v := range m {
81 // GetOrSetNew looks up k in m and returns the result. If it's not present, it uses `new` to
82 // allocate an new value type and sets that in the map, then returns it.
83 > func GetOrSetNew[M ~map[K]*V, K comparable, V any](m M, k K) *V { util.go
84 > if v, ok := m[k]; ok {
85 > return v util.go
86 > }
87 v := new(V)
88 m[k] = v
92 // GetOrSetMap looks up k in m, a two-level map, and returns the result. If it's not present,
93 // it uses `make` to allocate new second-level map and sets that in the first map, then returns it.
94 > func GetOrSetMap[M ~map[K]M2, M2 ~map[K2]V, K, K2 comparable, V any](m M, k K) M2 { util.go
95 > if m2, ok := m[k]; ok {
96 > return m2 util.go
97 > }
98 > m2 := make(M2) util.go
99 > m[k] = m2
100 > return m2
101 }
102
103 // DeleteFromMap deletes k2 from the nested map m[k]. If the inner map becomes empty
104 // after deletion, k is also removed from m to prevent memory leaks.
105 > func DeleteFromMap[M ~map[K]M2, M2 ~map[K2]V, K, K2 comparable, V any](m M, k K, k2 K2) { util.go
106 > if m2, ok := m[k]; ok {
107 > delete(m2, k2) util.go
108 > if len(m2) == 0 {
109 > delete(m, k) util.go
110 > }
111 }
112 }
133
134 // MapSlice given slice xs []T and f(T) S produces slice []S by applying f to every element of xs
135 > func MapSlice[T, S any](xs []T, f func(T) S) []S { util.go
136 > if xs == nil {
137 return nil
138 }
139 > result := make([]S, len(xs)) util.go
140 > for i, s := range xs {
141 > result[i] = f(s) util.go
142 > }
143 > return result util.go
144 }
145
146 // FilterSlice iterates over elements of a slice, returning a new slice of all elements predicate returns true for.
147 > func FilterSlice[T any](in []T, predicate func(T) bool) []T { util.go
148 > var out []T
149 > for _, elem := range in {
150 > if predicate(elem) { util.go
151 > out = append(out, elem) util.go
152 > }
153 }
154 > return out util.go
155 }
156
166 // RepeatSlice given slice and a number (n) produces a new slice containing original slice n times
167 // if n is non-positive will produce nil
168 > func RepeatSlice[T any](xs []T, n int) []T { util.go
169 > if xs == nil || n <= 0 {
170 return nil
171 }
172 > ys := make([]T, n*len(xs)) util.go
173 > for i := range n {
174 > copy(ys[i*len(xs):], xs)
175 > }
176 > return ys
177 }
178
186 // InterruptibleSleep is like time.Sleep but can be interrupted by a context.
187 // Returns context error if interrupted, otherwise nil.
188 > func InterruptibleSleep(ctx context.Context, timeout time.Duration) error { util.go
189 > timer := time.NewTimer(timeout)
190 > defer timer.Stop()
191 > select {
192 > case <-timer.C: util.go
193 > return nil
194 > case <-ctx.Done(): util.go
195 > return ctx.Err()
196 }
197 }
go.temporal.io/server/service/history/replication/task_processor_manager.go 64 covered LOC · 12 ranges

Open complete file

71 testHooks testhooks.TestHooks,
72 dlqWriter DLQWriter,
73 > ) *taskProcessorManagerImpl { task_processor_manager.go
74 > historyFetcher := eventhandler.NewHistoryPaginatedFetcher(shardContext.GetNamespaceRegistry(), clientBean, eventSerializer, shardContext.GetLogger())
75 > return &taskProcessorManagerImpl{
76 > config: config,
77 > deleteMgr: workflowDeleteManager,
78 > engine: engine,
79 > eventSerializer: eventSerializer,
80 > shard: shardContext,
81 > status: common.DaemonStatusInitialized,
82 > replicationTaskFetcherFactory: replicationTaskFetcherFactory,
83 > workflowCache: workflowCache,
84 > removeHistoryFetcher: historyFetcher,
85 > logger: shardContext.GetLogger(),
86 > metricsHandler: shardContext.GetMetricsHandler(),
87 > testHooks: testHooks,
88 > dlqWriter: dlqWriter,
89 >
90 > enableFetcher: !config.EnableReplicationStream(),
91 > taskProcessors: make(map[string][]TaskProcessor),
92 > taskExecutorProvider: taskExecutorProvider,
93 > taskPollerManager: newPollerManager(shardContext.GetShardID(), shardContext.GetClusterMetadata()),
94 > minTxAckedTaskID: persistence.EmptyQueueMessageID,
95 > shutdownChan: make(chan struct{}),
96 > }
97 > }
98
99 > func (r *taskProcessorManagerImpl) Start() { task_processor_manager.go
100 > if !atomic.CompareAndSwapInt32(
101 > &r.status,
102 > common.DaemonStatusInitialized,
103 > common.DaemonStatusStarted,
104 > ) {
105 return
106 }
107
108 // Listen to cluster metadata and dynamically update replication processor for remote clusters.
109 > if r.enableFetcher { task_processor_manager.go
110 r.listenToClusterMetadataChange()
111 }
112 > go r.completeReplicationTaskLoop() task_processor_manager.go
113 > go r.checkReplicationDLQEmptyLoop()
114 }
115
116 > func (r *taskProcessorManagerImpl) Stop() { task_processor_manager.go
117 > if !atomic.CompareAndSwapInt32(
118 > &r.status,
119 > common.DaemonStatusStarted,
120 > common.DaemonStatusStopped,
121 > ) {
122 return
123 }
124
125 > close(r.shutdownChan) task_processor_manager.go
126 >
127 > if r.enableFetcher {
128 r.shard.GetClusterMetadata().UnRegisterMetadataChangeCallback(r)
129 }
130 > r.taskProcessorLock.Lock() task_processor_manager.go
131 > for _, taskProcessors := range r.taskProcessors {
132 for _, processor := range taskProcessors {
133 processor.Stop()
134 }
135 }
136 > r.taskProcessorLock.Unlock() task_processor_manager.go
137 }
138
208 }
209
210 > func (r *taskProcessorManagerImpl) completeReplicationTaskLoop() { task_processor_manager.go
211 > shardID := r.shard.GetShardID()
212 > cleanupTimer := time.NewTimer(backoff.Jitter(
213 > r.config.ReplicationTaskProcessorCleanupInterval(shardID),
214 > r.config.ReplicationTaskProcessorCleanupJitterCoefficient(shardID),
215 > ))
216 > defer cleanupTimer.Stop()
217 > for {
218 > select {
219 case <-cleanupTimer.C:
220 if err := r.cleanupReplicationTasks(); err != nil {
229 r.config.ReplicationTaskProcessorCleanupJitterCoefficient(shardID),
230 ))
231 > case <-r.shutdownChan: task_processor_manager.go
232 > return
233 }
234 }
235 }
236
237 > func (r *taskProcessorManagerImpl) checkReplicationDLQEmptyLoop() { task_processor_manager.go
238 > for {
239 > timer := time.NewTimer(backoff.FullJitter(dlqSizeCheckInterval))
240 > select {
241 case <-timer.C:
242 if r.config.ReplicationEnableDLQMetrics() {
243 r.checkReplicationDLQSize()
244 }
245 > case <-r.shutdownChan: task_processor_manager.go
246 > timer.Stop()
247 > return
248 }
249 }
go.temporal.io/server/common/persistence/xdc_cache.go 63 covered LOC · 12 ranges

Open complete file

53 minEventID int64,
54 version int64,
55 > ) XDCCacheKey { xdc_cache.go
56 > return XDCCacheKey{
57 > WorkflowKey: workflowKey,
58 > MinEventID: minEventID,
59 > Version: version,
60 > }
61 > }
62
63 func NewXDCCacheValue(
66 eventBlobs []*commonpb.DataBlob,
67 nextEventID int64,
68 > ) XDCCacheValue { xdc_cache.go
69 > return XDCCacheValue{
70 > BaseWorkflowInfo: baseWorkflowInfo,
71 > VersionHistoryItems: versionHistoryItems,
72 > EventBlobs: eventBlobs,
73 > NextEventID: nextEventID,
74 > }
75 > }
76
77 > func (v XDCCacheValue) CacheSize() int { xdc_cache.go
78 > size := 0
79 > for _, item := range v.VersionHistoryItems {
80 > size += item.Size()
81 > }
82 > for _, blob := range v.EventBlobs {
83 > size += blob.Size()
84 > }
85 > return v.BaseWorkflowInfo.Size() + size
86 }
87
90 ttl time.Duration,
91 logger log.Logger,
92 > ) *XDCCacheImpl { xdc_cache.go
93 > return &XDCCacheImpl{
94 > cache: cache.New(
95 > max(xdcMinCacheSize, maxBytes),
96 > &cache.Options{
97 > TTL: ttl,
98 > Pin: false,
99 > },
100 > ),
101 > logger: logger,
102 > }
103 > }
104
105 func (e *XDCCacheImpl) Put(
106 key XDCCacheKey,
107 value XDCCacheValue,
108 > ) { xdc_cache.go
109 > existingValue, found := e.Get(key)
110 > if found && existingValue.NextEventID != value.NextEventID {
111 deserializeBlobs := func(blobs []*commonpb.DataBlob) [][]*historypb.HistoryEvent {
112 events := make([][]*historypb.HistoryEvent, len(blobs))
123 e.logger.Error(fmt.Sprintf("Putting duplicate key in XDC cache: wf-key: %v, existing event blobs: %v, new event blobs: %v", key.WorkflowKey, deserializeBlobs(existingValue.EventBlobs), deserializeBlobs(value.EventBlobs)))
124 }
125 > e.cache.Put(key, value) xdc_cache.go
126 }
127
128 > func (e *XDCCacheImpl) Get(key XDCCacheKey) (XDCCacheValue, bool) { xdc_cache.go
129 > value := e.cache.Get(key)
130 > if value == nil {
131 > return XDCCacheValue{}, false
132 > }
133 return value.(XDCCacheValue), true
134 }
138 eventID int64,
139 version int64,
140 > ) ([]*historyspb.VersionHistoryItem, []byte, *workflowspb.BaseExecutionInfo, error) { xdc_cache.go
141 > baseWorkflowInfo := CopyBaseWorkflowInfo(executionInfo.BaseExecutionInfo)
142 > versionHistories := executionInfo.VersionHistories
143 > versionHistoryIndex, err := versionhistory.FindFirstVersionHistoryIndexByVersionHistoryItem(
144 > versionHistories,
145 > versionhistory.NewVersionHistoryItem(
146 > eventID,
147 > version,
148 > ),
149 > )
150 > if err != nil {
151 return nil, nil, nil, err
152 }
153
154 > versionHistoryBranch, err := versionhistory.GetVersionHistory(versionHistories, versionHistoryIndex) xdc_cache.go
155 > if err != nil {
156 return nil, nil, nil, err
157 }
158 > return versionhistory.CopyVersionHistory(versionHistoryBranch).GetItems(), versionHistoryBranch.GetBranchToken(), baseWorkflowInfo, nil xdc_cache.go
159 }
160
161 func CopyBaseWorkflowInfo(
162 baseWorkflowInfo *workflowspb.BaseExecutionInfo,
163 > ) *workflowspb.BaseExecutionInfo { xdc_cache.go
164 > if baseWorkflowInfo == nil {
165 > return nil xdc_cache.go
166 > }
167 return &workflowspb.BaseExecutionInfo{
168 RunId: baseWorkflowInfo.RunId,
go.temporal.io/server/service/history/shard/task_key_manager.go 63 covered LOC · 13 ranges

Open complete file

28 logger log.Logger,
29 renewRangeIDFn renewRangeIDFn,
30 > ) *taskKeyManager { task_key_manager.go
31 > return &taskKeyManager{
32 > generator: newTaskKeyGenerator(
33 > config.RangeSizeBits,
34 > timeSource,
35 > logger,
36 > renewRangeIDFn,
37 > ),
38 > tracker: newTaskRequestTracker(taskCategoryRegistry),
39 > timeSource: timeSource,
40 > logger: logger,
41 > config: config,
42 > }
43 > }
44
45 func (m *taskKeyManager) setAndTrackTaskKeys(
46 taskMaps ...map[tasks.Category][]tasks.Task,
47 > ) (taskRequestCompletionFn, error) { task_key_manager.go
48 >
49 > if err := m.generator.setTaskKeys(taskMaps...); err != nil {
50 return nil, err
51 }
52
53 > return m.tracker.track(taskMaps...), nil task_key_manager.go
54 }
55
56 func (m *taskKeyManager) peekTaskKey(
57 category tasks.Category,
58 > ) tasks.Key { task_key_manager.go
59 > return m.generator.peekTaskKey(category)
60 > }
61
62 func (m *taskKeyManager) generateTaskKey(
63 category tasks.Category,
64 > ) (tasks.Key, error) { task_key_manager.go
65 > return m.generator.generateTaskKey(category)
66 > }
67
68 > func (m *taskKeyManager) drainTaskRequests() { task_key_manager.go
69 > m.tracker.drain()
70 > }
71
72 func (m *taskKeyManager) setRangeID(
73 rangeID int64,
75 > m.generator.setRangeID(rangeID)
76 >
77 > // rangeID update means all pending add tasks requests either already succeeded
78 > // are guaranteed to fail, so we can clear pending requests in the tracker
79 > m.tracker.clear()
80 > }
81
82 func (m *taskKeyManager) setTaskMinScheduledTime(
83 taskMinScheduledTime time.Time,
85 > m.generator.setTaskMinScheduledTime(taskMinScheduledTime)
86 > }
87
88 func (m *taskKeyManager) getExclusiveReaderHighWatermark(
89 category tasks.Category,
90 > ) tasks.Key { task_key_manager.go
91 > minTaskKey, ok := m.tracker.minTaskKey(category)
92 > if !ok {
93 > minTaskKey = tasks.MaximumKey task_key_manager.go
94 > }
95
96 // TODO: should this be moved generator.setTaskKeys() ?
97 > m.setTaskMinScheduledTime( task_key_manager.go
98 > // TODO: Truncation here is just to make sure task scheduled time has the same precision as the old logic.
99 > // Remove this truncation once we validate the rest of the code can worker correctly with higher precision.
100 > m.timeSource.Now().Add(m.config.TimerProcessorMaxTimeShift()).Truncate(common.ScheduledTaskMinPrecision),
101 > )
102 >
103 > nextTaskKey := m.generator.peekTaskKey(category)
104 >
105 > exclusiveReaderHighWatermark := tasks.MinKey(
106 > minTaskKey,
107 > nextTaskKey,
108 > )
109 > if category.Type() == tasks.CategoryTypeScheduled {
110 > exclusiveReaderHighWatermark.TaskID = 0 task_key_manager.go
111 >
112 > // TODO: Truncation here is just to make sure task scheduled time has the same precision as the old logic.
113 > // Remove this truncation once we validate the rest of the code can worker correctly with higher precision.
114 > exclusiveReaderHighWatermark.FireTime = exclusiveReaderHighWatermark.FireTime.
115 > Truncate(common.ScheduledTaskMinPrecision)
116 > }
117
118 > return exclusiveReaderHighWatermark task_key_manager.go
119 }
go.temporal.io/server/common/locks/priority_semaphore_impl.go 62 covered LOC · 19 ranges

Open complete file

67 // maximum combined weight for concurrent access, capable of handling multiple priority levels.
68 // Most of the logic is taken directly from golang's semaphore.Weighted.
69 > func NewPrioritySemaphore(n int) *PrioritySemaphoreImpl { priority_semaphore_impl.go
70 > waitLists := make([]*list.List, NumPriorities)
71 > for i := range waitLists {
72 > waitLists[i] = list.New()
73 > }
74 > return &PrioritySemaphoreImpl{
75 > size: n,
76 > waitLists: waitLists,
77 > }
78 }
79
81 // are available or ctx is done. On success, returns nil. On failure, returns
82 // ctx.Err() and leaves the semaphore unchanged.
83 > func (s *PrioritySemaphoreImpl) Acquire(ctx context.Context, priority Priority, n int) error { priority_semaphore_impl.go
84 > if priority >= NumPriorities {
85 // nolint:forbidigo
86 panic(fmt.Sprintf("semaphore: invalid priority %v, priority must be less than %v", priority, NumPriorities))
87 }
88
89 > done := ctx.Done() priority_semaphore_impl.go
90 >
91 > s.mu.Lock()
92 > select {
93 case <-done:
94 // ctx becoming done has "happened before" acquiring the semaphore,
98 s.mu.Unlock()
99 return ctx.Err()
101 }
102 // Check if acquisition can proceed without waiting
103 > if s.size-s.cur >= n && s.noWaiters(priority) { priority_semaphore_impl.go
104 > // Since we hold s.mu and haven't synchronized since checking done, if priority_semaphore_impl.go
105 > // ctx becomes done before we return here, it becoming done must have
106 > // "happened concurrently" with this call - it cannot "happen before"
107 > // we return in this branch. So, we're ok to always acquire here.
108 > s.cur += n
109 > s.mu.Unlock()
110 > return nil
111 > }
112
113 > if n > s.size { priority_semaphore_impl.go
114 s.mu.Unlock()
115 return ErrRequestTooLarge
116 }
117
118 > ready := make(chan struct{}) priority_semaphore_impl.go
119 > w := waiter{n: n, ready: ready}
120 > elem := s.waitLists[priority].PushBack(w)
121 > s.mu.Unlock()
122 >
123 > select {
124 case <-done:
125 s.mu.Lock()
141 return ctx.Err()
142
143 > case <-ready: priority_semaphore_impl.go
144 > // Acquired the semaphore. Check that ctx isn't already done.
145 > // We check the done channel instead of calling ctx.Err because we
146 > // already have the channel, and ctx.Err is O(n) with the nesting
147 > // depth of ctx.
148 > select {
149 case <-done:
150 s.Release(n)
151 return ctx.Err()
153 }
154 > return nil priority_semaphore_impl.go
155 }
156 }
173 }
174
175 > func (s *PrioritySemaphoreImpl) Release(n int) { priority_semaphore_impl.go
176 > s.mu.Lock()
177 > defer s.mu.Unlock()
178 > s.cur -= n
179 > if s.cur < 0 {
180 s.mu.Unlock()
181 panic("semaphore: released more than held")
182 }
183 > s.notifyWaiters() priority_semaphore_impl.go
184 }
185
186 > func (s *PrioritySemaphoreImpl) notifyWaiters() { priority_semaphore_impl.go
187 > for _, l := range s.waitLists {
188 > for {
189 > next := l.Front()
190 > if next == nil {
191 > break // No more waiters blocked.
192 }
193
194 > w, ok := next.Value.(waiter) priority_semaphore_impl.go
195 > if !ok {
196 panic("semaphore: failed to cast waiter")
197 }
198 > if s.size-s.cur < w.n { priority_semaphore_impl.go
199 // Not enough tokens for the next waiter. We could keep going (to try to
200 // find a waiter with a smaller request), but under load that could cause
219
220 // noWaiters returns if there is no waiter that has priority higher or equal to lowestPriority.
221 > func (s *PrioritySemaphoreImpl) noWaiters(lowestPriority Priority) bool { priority_semaphore_impl.go
222 > for _, l := range s.waitLists[:lowestPriority+1] {
223 > if l.Len() > 0 {
224 return false
225 }
226 }
227 > return true priority_semaphore_impl.go
228 }
go.temporal.io/server/common/persistence/sql/task_queues.go 62 covered LOC · 15 ranges

Open complete file

23 ctx context.Context,
24 request *persistence.InternalCreateTaskQueueRequest,
25 > ) error { task_queues.go
26 > nidBytes, err := primitives.ParseUUID(request.NamespaceID)
27 > if err != nil {
28 return serviceerror.NewInternal(err.Error())
29 }
30 > tqId, tqHash := taskQueueIdAndHash(nidBytes, request.TaskQueue, request.TaskType, persistence.SubqueueZero) task_queues.go
31 >
32 > row := sqlplugin.TaskQueuesRow{
33 > RangeHash: tqHash,
34 > TaskQueueID: tqId,
35 > RangeID: request.RangeID,
36 > Data: request.TaskQueueInfo.Data,
37 > DataEncoding: request.TaskQueueInfo.EncodingType.String(),
38 > }
39 > if _, err := m.DB.InsertIntoTaskQueues(ctx, &row, m.version); err != nil {
40 if m.DB.IsDupEntryError(err) {
41 return &persistence.ConditionFailedError{Msg: err.Error()}
50 ctx context.Context,
51 request *persistence.InternalGetTaskQueueRequest,
52 > ) (*persistence.InternalGetTaskQueueResponse, error) { task_queues.go
53 > nidBytes, err := primitives.ParseUUID(request.NamespaceID)
54 > if err != nil {
55 return nil, serviceerror.NewInternal(err.Error())
56 }
57 > tqId, tqHash := taskQueueIdAndHash(nidBytes, request.TaskQueue, request.TaskType, persistence.SubqueueZero) task_queues.go
58 > rows, err := m.DB.SelectFromTaskQueues(ctx, sqlplugin.TaskQueuesFilter{
59 > RangeHash: tqHash,
60 > TaskQueueID: tqId,
61 > }, m.version)
62 >
63 > switch err {
64 > case nil: task_queues.go
65 > if len(rows) != 1 {
66 return nil, serviceerror.NewUnavailablef(
67 "GetTaskQueue operation failed. Expect exactly one result row, but got %d for task queue %v of type %v",
68 len(rows), request.TaskQueue, request.TaskType)
69 }
70 > row := rows[0] task_queues.go
71 > return &persistence.InternalGetTaskQueueResponse{
72 > RangeID: row.RangeID,
73 > TaskQueueInfo: persistence.NewDataBlob(row.Data, row.DataEncoding),
74 > }, nil
75 > case sql.ErrNoRows: task_queues.go
76 > return nil, serviceerror.NewNotFoundf(
77 > "GetTaskQueue operation failed. TaskQueue: %v, TaskQueueType: %v, Error: %v",
78 > request.TaskQueue, request.TaskType, err)
79 default:
80 return nil, serviceerror.NewUnavailablef(
87 ctx context.Context,
88 request *persistence.InternalUpdateTaskQueueRequest,
89 > ) (*persistence.UpdateTaskQueueResponse, error) { task_queues.go
90 > nidBytes, err := primitives.ParseUUID(request.NamespaceID)
91 > if err != nil {
92 return nil, serviceerror.NewInternal(err.Error())
93 }
94
95 > tqId, tqHash := taskQueueIdAndHash(nidBytes, request.TaskQueue, request.TaskType, persistence.SubqueueZero) task_queues.go
96 > var resp *persistence.UpdateTaskQueueResponse
97 > err = m.txExecute(ctx, "UpdateTaskQueue", func(tx sqlplugin.Tx) error {
98 > if err := lockTaskQueue(ctx,
99 > tx,
100 > tqHash,
101 > tqId,
102 > request.PrevRangeID,
103 > m.version,
104 > ); err != nil {
105 return err
106 }
107 > result, err := tx.UpdateTaskQueues(ctx, &sqlplugin.TaskQueuesRow{ task_queues.go
108 > RangeHash: tqHash,
109 > TaskQueueID: tqId,
110 > RangeID: request.RangeID,
111 > Data: request.TaskQueueInfo.Data,
112 > DataEncoding: request.TaskQueueInfo.EncodingType.String(),
113 > }, m.version)
114 > if err != nil {
115 return err
116 }
117 > rowsAffected, err := result.RowsAffected() task_queues.go
118 > if err != nil {
119 return err
120 }
121 > if rowsAffected != 1 { task_queues.go
122 return fmt.Errorf("%v rows were affected instead of 1", rowsAffected)
123 }
124 > resp = &persistence.UpdateTaskQueueResponse{} task_queues.go
125 > return nil
126 })
127 > return resp, err task_queues.go
128 }
129
go.temporal.io/server/common/quotas/priority_rate_limiter_impl.go 62 covered LOC · 14 ranges

Open complete file

28 requestPriorityFn RequestPriorityFn,
29 prioritiesOrdered []int,
30 > ) RequestRateLimiter { priority_rate_limiter_impl.go
31 > rateLimiters := make(map[int]RequestRateLimiter)
32 > for _, priority := range prioritiesOrdered {
33 > if priority == OperatorPriority {
34 > rateLimiters[priority] = NewRequestRateLimiterAdapter(
35 > NewDynamicRateLimiter(
36 > NewOperatorRateBurst(rateBurstFn, operatorRPSRatio),
37 > defaultRefreshInterval,
38 > ),
39 > )
40 > } else {
41 > rateLimiters[priority] = NewRequestRateLimiterAdapter(
42 > NewDynamicRateLimiter(
43 > rateBurstFn,
44 > defaultRefreshInterval,
45 > ),
46 > )
47 > }
48 }
49 > return NewPriorityRateLimiter(requestPriorityFn, rateLimiters) priority_rate_limiter_impl.go
50 }
51
55 requestPriorityFn RequestPriorityFn,
56 priorityToRateLimiters map[int]RequestRateLimiter,
57 > ) *PriorityRateLimiterImpl { priority_rate_limiter_impl.go
58 > priorities := make([]int, 0, len(priorityToRateLimiters))
59 > for priority := range priorityToRateLimiters {
60 > priorities = append(priorities, priority)
61 > }
62 > slices.Sort(priorities)
63 > priorityToIndex := make(map[int]int, len(priorityToRateLimiters))
64 > rateLimiters := make([]RequestRateLimiter, 0, len(priorityToRateLimiters))
65 > for index, priority := range priorities {
66 > priorityToIndex[priority] = index
67 > rateLimiters = append(rateLimiters, priorityToRateLimiters[priority])
68 > }
69
70 > return &PriorityRateLimiterImpl{ priority_rate_limiter_impl.go
71 > requestPriorityFn: requestPriorityFn,
72 > priorityToRateLimiters: priorityToRateLimiters,
73 >
74 > priorityToIndex: priorityToIndex,
75 > rateLimiters: rateLimiters,
76 > }
77 }
78
97 now time.Time,
98 request Request,
99 > ) Reservation { priority_rate_limiter_impl.go
100 > decidingRateLimiter, consumeRateLimiters := p.getRateLimiters(request)
101 >
102 > decidingReservation := decidingRateLimiter.Reserve(now, request)
103 > if !decidingReservation.OK() {
104 return decidingReservation
105 }
106
107 > otherReservations := make([]Reservation, len(consumeRateLimiters)) priority_rate_limiter_impl.go
108 > for index, limiter := range consumeRateLimiters {
109 > otherReservations[index] = limiter.Reserve(now, request) priority_rate_limiter_impl.go
110 > }
111 > return NewPriorityReservation(decidingReservation, otherReservations) priority_rate_limiter_impl.go
112 }
113
155 func (p *PriorityRateLimiterImpl) getRateLimiters(
156 request Request,
157 > ) (RequestRateLimiter, []RequestRateLimiter) { priority_rate_limiter_impl.go
158 > priority := p.requestPriorityFn(request)
159 > if _, ok := p.priorityToRateLimiters[priority]; !ok {
160 panic("Request to priority & priority to rate limiter does not match")
161 }
162
163 > rateLimiterIndex := p.priorityToIndex[priority] priority_rate_limiter_impl.go
164 > return p.rateLimiters[rateLimiterIndex], p.rateLimiters[rateLimiterIndex+1:]
165 }
go.temporal.io/server/common/rpc/interceptor/trailer_to_context_metadata_interceptor.go 62 covered LOC · 19 ranges

Open complete file

19 // Requires the context to be pre-wrapped with contextutil.WithMetadataContext() before the RPC call.
20 // This is typically done by server-side interceptors (e.g., ContextMetadataInterceptor).
21 > func TrailerToContextMetadataInterceptor(logger log.Logger) grpc.UnaryClientInterceptor { trailer_to_context_metadata_interceptor.go
22 > throttledLogger := log.NewThrottledLogger(logger, func() float64 {
23 > return 1.0 / 30.0 // 1 log per 30 seconds
24 > })
25 > return func(
26 > ctx context.Context,
27 > method string,
28 > req, reply any,
29 > cc *grpc.ClientConn,
30 > invoker grpc.UnaryInvoker,
31 > opts ...grpc.CallOption,
32 > ) error {
33 > var trailer metadata.MD trailer_to_context_metadata_interceptor.go
34 > opts = append(opts, grpc.Trailer(&trailer))
35 >
36 > err := invoker(ctx, method, req, reply, cc, opts...)
37 >
38 > trailerMetadata, propagatedMetadata := extractMetadataFromTrailer(ctx, trailer, throttledLogger)
39 >
40 > logMetadataPropagationStatus(ctx, method, trailerMetadata, propagatedMetadata, throttledLogger)
41 >
42 > return err
43 > }
44 }
45
54 trailer metadata.MD,
55 throttledLogger log.ThrottledLogger,
56 > ) (trailerMetadata map[string]string, propagatedMetadata map[string]string) { trailer_to_context_metadata_interceptor.go
57 > trailerMetadata = make(map[string]string)
58 > propagatedMetadata = make(map[string]string)
59 >
60 > // Try proto format first (authoritative).
61 > if values := trailer[protoTrailerKey]; len(values) > 0 {
62 > protoMsg := &contextpropagationspb.ContextMetadata{} trailer_to_context_metadata_interceptor.go
63 > err := proto.Unmarshal([]byte(values[0]), protoMsg)
64 > if err != nil {
65 throttledLogger.Warn("TrailerToContextMetadataInterceptor: Failed to unmarshal proto trailer, falling back to legacy",
66 tag.Error(err),
67 )
68 }
70 > for key, value := range protoMsg.GetEntries() { trailer_to_context_metadata_interceptor.go
71 > trailerMetadata[key] = value trailer_to_context_metadata_interceptor.go
72 > if contextutil.ContextMetadataSet(ctx, key, value) {
73 > propagatedMetadata[key] = value
74 > }
75 }
76 > return trailerMetadata, propagatedMetadata trailer_to_context_metadata_interceptor.go
77 }
78 }
79
80 // Fallback: legacy per-key format for backward compatibility with older writers.
81 > for prefixedKey, values := range trailer { trailer_to_context_metadata_interceptor.go
82 > // Skip the proto trailer key itself in the legacy path. trailer_to_context_metadata_interceptor.go
83 > if prefixedKey == protoTrailerKey {
84 continue
85 }
86 > key, ok := strings.CutPrefix(prefixedKey, trailerKeyPrefix) trailer_to_context_metadata_interceptor.go
87 > if !ok {
88 > // Backward compatibility: accept unprefixed keys from older writers. trailer_to_context_metadata_interceptor.go
89 > if prefixedKey != contextutil.MetadataKeyWorkflowType && prefixedKey != contextutil.MetadataKeyWorkflowTaskQueue {
91 }
92 key = prefixedKey
111 propagatedMetadata map[string]string,
112 throttledLogger log.ThrottledLogger,
114 > contextWrapped := contextutil.ContextHasMetadata(ctx)
115 >
116 > if len(trailerMetadata) == 0 {
117 > throttledLogger.Info("TrailerToContextMetadataInterceptor: No metadata in trailer", trailer_to_context_metadata_interceptor.go
118 > tag.NewBoolTag("contextWrapped", contextWrapped),
119 > tag.NewStringTag("method", method))
120 > return
121 > }
122
123 > if !contextWrapped { trailer_to_context_metadata_interceptor.go
124 throttledLogger.Warn("TrailerToContextMetadataInterceptor: Trailer had metadata but context not wrapped",
125 tag.NewAnyTag("trailer", trailerMetadata),
128 }
129
130 > if len(propagatedMetadata) < len(trailerMetadata) { trailer_to_context_metadata_interceptor.go
131 throttledLogger.Warn("TrailerToContextMetadataInterceptor: Failed to propagate some metadata from trailer",
132 tag.NewAnyTag("trailer", trailerMetadata),
136 }
137
138 > throttledLogger.Info("TrailerToContextMetadataInterceptor: Propagated metadata from trailer", trailer_to_context_metadata_interceptor.go
139 > tag.NewAnyTag("trailer", propagatedMetadata),
140 > tag.NewStringTag("method", method))
141 }
go.temporal.io/server/service/history/memory_scheduled_queue_factory.go 62 covered LOC · 5 ranges

Open complete file

55 func NewMemoryScheduledQueueFactory(
56 params memoryScheduledQueueFactoryParams,
57 > ) QueueFactory { memory_scheduled_queue_factory.go
58 > logger := log.With(params.Logger, tag.ComponentMemoryScheduledQueue)
59 > metricsHandler := params.MetricsHandler.WithTags(metrics.OperationTag(metrics.OperationMemoryScheduledQueueProcessorScope))
60 >
61 > hostScheduler := ctasks.NewFIFOScheduler[ctasks.Task](
62 > &ctasks.FIFOSchedulerOptions{
63 > QueueSize: 0, // Don't buffer tasks in scheduler. If all workers are busy memoryScheduledQueue reschedules tasks into itself.
64 > WorkerCount: params.Config.MemoryTimerProcessorSchedulerWorkerCount,
65 > },
66 > logger,
67 > )
68 >
69 > return &memoryScheduledQueueFactory{
70 > scheduler: hostScheduler,
71 > priorityAssigner: queues.NewPriorityAssigner(
72 > params.NamespaceRegistry,
73 > params.ClusterMetadata.GetCurrentClusterName(),
74 > ),
75 > namespaceRegistry: params.NamespaceRegistry,
76 > clusterMetadata: params.ClusterMetadata,
77 > workflowCache: params.WorkflowCache,
78 > timeSource: params.TimeSource,
79 > chasmRegistry: params.ChasmRegistry,
80 > metricsHandler: metricsHandler,
81 > tracer: params.TracerProvider.Tracer(telemetry.ComponentQueueMemory),
82 > logger: logger,
83 > executorWrapper: params.ExecutorWrapper,
84 > }
85 > }
86
87 > func (f *memoryScheduledQueueFactory) Start() { memory_scheduled_queue_factory.go
88 > f.scheduler.Start()
89 > }
90
91 > func (f *memoryScheduledQueueFactory) Stop() { memory_scheduled_queue_factory.go
92 > f.scheduler.Stop()
93 > }
94
95 func (f *memoryScheduledQueueFactory) CreateQueue(
96 shardCtx historyi.ShardContext,
97 > ) queues.Queue { memory_scheduled_queue_factory.go
98 >
99 > // Reuse TimerQueueActiveTaskExecutor only to executeWorkflowTaskTimeoutTask.
100 > // Unused dependencies are nil.
101 > speculativeWorkflowTaskTimeoutExecutor := newTimerQueueActiveTaskExecutor(
102 > shardCtx,
103 > f.workflowCache,
104 > nil,
105 > f.logger,
106 > f.metricsHandler,
107 > shardCtx.GetConfig(),
108 > nil,
109 > nil,
110 > )
111 > if f.executorWrapper != nil {
112 speculativeWorkflowTaskTimeoutExecutor = f.executorWrapper.Wrap(speculativeWorkflowTaskTimeoutExecutor)
113 }
114
115 > return queues.NewSpeculativeWorkflowTaskTimeoutQueue( memory_scheduled_queue_factory.go
116 > f.scheduler,
117 > f.priorityAssigner,
118 > speculativeWorkflowTaskTimeoutExecutor,
119 > f.namespaceRegistry,
120 > f.clusterMetadata,
121 > f.timeSource,
122 > f.chasmRegistry,
123 > f.metricsHandler,
124 > f.tracer,
125 > f.logger,
126 > )
127 }
go.temporal.io/server/service/matching/service.go 61 covered LOC · 7 ranges

Open complete file

44 healthServer *health.Server,
45 visibilityManager manager.VisibilityManager,
46 > ) *Service { service.go
47 > return &Service{
48 > config: serviceConfig,
49 > server: server,
50 > handler: handler,
51 > logger: logger,
52 > membershipMonitor: membershipMonitor,
53 > grpcListener: grpcListener,
54 > runtimeMetricsReporter: runtimeMetricsReporter,
55 > metricsHandler: metricsHandler,
56 > healthServer: healthServer,
57 > visibilityManager: visibilityManager,
58 > }
59 > }
60
61 // Start starts the service
62 > func (s *Service) Start() { service.go
63 > s.logger.Info("matching starting")
64 >
65 > // must start base service first
66 > metrics.RestartCount.With(s.metricsHandler).Record(1)
67 >
68 > s.handler.Start()
69 >
70 > matchingservice.RegisterMatchingServiceServer(s.server, s.handler)
71 > healthpb.RegisterHealthServer(s.server, s.healthServer)
72 > s.healthServer.SetServingStatus(serviceName, healthpb.HealthCheckResponse_SERVING)
73 >
74 > reflection.Register(s.server)
75 >
76 > go func() {
77 > s.logger.Info("Starting to serve on matching listener")
78 > if err := s.server.Serve(s.grpcListener); err != nil {
79 s.logger.Fatal("Failed to serve on matching listener", tag.Error(err))
80 }
81 }()
82
83 > go s.membershipMonitor.Start() service.go
84 }
85
86 // Stop stops the service
87 > func (s *Service) Stop() { service.go
88 > // remove self from membership ring and wait for traffic to drain
89 > var err error
90 > var waitTime time.Duration
91 > if align := s.config.AlignMembershipChange(); align > 0 {
92 propagation := s.membershipMonitor.ApproximateMaxPropagationTime()
93 asOf := util.NextAlignedTime(time.Now().Add(propagation), align)
94 s.logger.Info("ShutdownHandler: Evicting self from membership ring as of", tag.Timestamp(asOf))
95 waitTime, err = s.membershipMonitor.EvictSelfAt(asOf)
96 > } else { service.go
97 > s.logger.Info("ShutdownHandler: Evicting self from membership ring immediately")
98 > err = s.membershipMonitor.EvictSelf()
99 > }
100 > if err != nil {
101 s.logger.Error("ShutdownHandler: Failed to evict self from membership ring", tag.Error(err))
102 }
103 > s.healthServer.SetServingStatus(serviceName, healthpb.HealthCheckResponse_NOT_SERVING) service.go
104 >
105 > s.logger.Info("ShutdownHandler: Waiting for others to discover I am unhealthy")
106 > time.Sleep(max(s.config.ShutdownDrainDuration(), waitTime))
107 >
108 > // At this point we should not get any new rpcs since we removed ourself from the ring.
109 > // Additionally, the engine will notice the membership change and stop all task queues
110 > // after a delay. However, we can do it immediately by stopping the handler (which stops
111 > // the engine which stops all task queues).
112 > s.handler.Stop()
113 >
114 > // All grpc handlers should be cancelled now. Give them a little time to return.
115 > t := time.AfterFunc(2*time.Second, func() {
116 s.logger.Info("ShutdownHandler: Drain time expired, stopping all traffic")
117 s.server.Stop()
118 })
119 > s.server.GracefulStop() service.go
120 > t.Stop()
121 >
122 > s.visibilityManager.Close()
123 >
124 > s.logger.Info("matching stopped")
125 }
go.temporal.io/server/service/worker/migration/fx.go 61 covered LOC · 7 ranges

Open complete file

57 )
58
59 > func NewResult(params initParams) fxResult { fx.go
60 > component := &replicationWorkerComponent{
61 > initParams: params,
62 > }
63 > return fxResult{
64 > Component: component,
65 > }
66 > }
67
68 > func (wc *replicationWorkerComponent) RegisterWorkflow(registry sdkworker.Registry) { fx.go
69 > registry.RegisterWorkflowWithOptions(CatchupWorkflow, workflow.RegisterOptions{Name: catchupWorkflowName})
70 > registry.RegisterWorkflowWithOptions(ForceReplicationWorkflow, workflow.RegisterOptions{Name: forceReplicationWorkflowName})
71 > registry.RegisterWorkflowWithOptions(ForceReplicationWorkflowV2, workflow.RegisterOptions{Name: forceReplicationWorkflowV2Name})
72 > registry.RegisterWorkflowWithOptions(NamespaceHandoverWorkflow, workflow.RegisterOptions{Name: namespaceHandoverWorkflowName})
73 > registry.RegisterWorkflowWithOptions(NamespaceHandoverWorkflowV2, workflow.RegisterOptions{Name: namespaceHandoverWorkflowV2Name})
74 > registry.RegisterWorkflowWithOptions(ForceTaskQueueUserDataReplicationWorkflow, workflow.RegisterOptions{Name: forceTaskQueueUserDataReplicationWorkflow})
75 > }
76
77 > func (wc *replicationWorkerComponent) DedicatedWorkflowWorkerOptions() *workercommon.DedicatedWorkerOptions { fx.go
78 > // Use default worker
79 > return nil
80 > }
81
82 > func (wc *replicationWorkerComponent) RegisterActivities(registry sdkworker.Registry) { fx.go
83 > registry.RegisterActivity(wc.activities())
84 > }
85
86 > func (wc *replicationWorkerComponent) DedicatedActivityWorkerOptions() *workercommon.DedicatedWorkerOptions { fx.go
87 > return &workercommon.DedicatedWorkerOptions{
88 > TaskQueue: primitives.MigrationActivityTQ,
89 > Options: sdkworker.Options{
90 > BackgroundActivityContext: headers.SetCallerType(context.Background(), headers.CallerTypePreemptable),
91 > },
92 > }
93 > }
94
95 > func workflowVerifierProvider() WorkflowVerifier { fx.go
96 > return func(
97 > _ context.Context,
98 > _ *verifyReplicationTasksRequest,
99 > _ adminservice.AdminServiceClient,
100 > _ adminservice.AdminServiceClient,
101 > _ *namespace.Namespace,
102 > _ *ExecutionInfo,
103 > _ *adminservice.DescribeMutableStateResponse,
104 > ) (verifyResult, error) {
105 return verifyResult{
106 status: verified,
109 }
110
111 > func (wc *replicationWorkerComponent) activities() *activities { fx.go
112 > return &activities{
113 > HistoryShardCount: wc.PersistenceConfig.NumHistoryShards,
114 > executionManager: wc.ExecutionManager,
115 > NamespaceRegistry: wc.NamespaceRegistry,
116 > HistoryClient: wc.HistoryClient,
117 > frontendClient: wc.FrontendClient,
118 > clientFactory: wc.ClientFactory,
119 > clientBean: wc.ClientBean,
120 > namespaceReplicationQueue: wc.NamespaceReplicationQueue,
121 > taskManager: wc.TaskManager,
122 > Logger: wc.Logger,
123 > MetricsHandler: wc.MetricsHandler,
124 > forceReplicationMetricsHandler: wc.MetricsHandler.WithTags(metrics.WorkflowTypeTag(forceReplicationWorkflowName)),
125 > generateMigrationTaskViaFrontend: dynamicconfig.WorkerGenerateMigrationTaskViaFrontend.Get(wc.DynamicCollection),
126 > enableHistoryRateLimiter: dynamicconfig.WorkerEnableHistoryRateLimiter.Get(wc.DynamicCollection),
127 > workflowVerifier: wc.WorkflowVerifier,
128 > chasmRegistry: wc.ChasmRegistry,
129 > }
130 > }
go.temporal.io/server/client/history/client_gen.go 60 covered LOC · 11 ranges

Open complete file

404 request *historyservice.GetWorkflowExecutionHistoryRequest,
405 opts ...grpc.CallOption,
406 > ) (*historyservice.GetWorkflowExecutionHistoryResponse, error) { client_gen.go
407 > shardID := c.shardIDFromWorkflowID(request.GetNamespaceId(), request.GetRequest().GetExecution().GetWorkflowId())
408 > var response *historyservice.GetWorkflowExecutionHistoryResponse
409 > op := func(ctx context.Context, client historyservice.HistoryServiceClient) error {
410 > var err error
411 > ctx, cancel := c.createContext(ctx)
412 > defer cancel()
413 > response, err = client.GetWorkflowExecutionHistory(ctx, request, opts...)
414 > return err
415 > }
416 > if err := c.executeWithRedirect(ctx, shardID, op); err != nil {
417 return nil, err
418 }
419 > return response, nil client_gen.go
420 }
421
842 request *historyservice.RecordWorkflowTaskStartedRequest,
843 opts ...grpc.CallOption,
844 > ) (*historyservice.RecordWorkflowTaskStartedResponse, error) { client_gen.go
845 > shardID := c.shardIDFromWorkflowID(request.GetNamespaceId(), request.GetWorkflowExecution().GetWorkflowId())
846 > var response *historyservice.RecordWorkflowTaskStartedResponse
847 > op := func(ctx context.Context, client historyservice.HistoryServiceClient) error {
848 > var err error
849 > ctx, cancel := c.createContext(ctx)
850 > defer cancel()
851 > response, err = client.RecordWorkflowTaskStarted(ctx, request, opts...)
852 > return err
853 > }
854 > if err := c.executeWithRedirect(ctx, shardID, op); err != nil {
855 return nil, err
856 }
857 > return response, nil client_gen.go
858 }
859
1156 request *historyservice.RespondWorkflowTaskCompletedRequest,
1157 opts ...grpc.CallOption,
1158 > ) (*historyservice.RespondWorkflowTaskCompletedResponse, error) { client_gen.go
1159 > taskToken, err := c.tokenSerializer.Deserialize(request.GetCompleteRequest().GetTaskToken())
1160 > if err != nil {
1161 return nil, serviceerror.NewInvalidArgument("error deserializing task token")
1162 }
1163 > var namespaceID string client_gen.go
1164 > var businessID string
1165 > if len(taskToken.GetComponentRef()) > 0 {
1166 ref, err := c.tokenSerializer.DeserializeChasmComponentRef(taskToken.GetComponentRef())
1167 if err != nil {
1170 namespaceID = ref.GetNamespaceId()
1171 businessID = ref.GetBusinessId()
1172 > } else { client_gen.go
1173 > namespaceID = request.GetNamespaceId()
1174 > businessID = taskToken.GetWorkflowId()
1175 > }
1176 > shardID := c.shardIDFromWorkflowID(namespaceID, businessID)
1177 >
1178 > var response *historyservice.RespondWorkflowTaskCompletedResponse
1179 > op := func(ctx context.Context, client historyservice.HistoryServiceClient) error {
1180 > var err error
1181 > ctx, cancel := c.createContext(ctx)
1182 > defer cancel()
1183 > response, err = client.RespondWorkflowTaskCompleted(ctx, request, opts...)
1184 > return err
1185 > }
1186 > if err := c.executeWithRedirect(ctx, shardID, op); err != nil {
1187 return nil, err
1188 }
1189 > return response, nil client_gen.go
1190 }
1191
1312 request *historyservice.StartWorkflowExecutionRequest,
1313 opts ...grpc.CallOption,
1314 > ) (*historyservice.StartWorkflowExecutionResponse, error) { client_gen.go
1315 > shardID := c.shardIDFromWorkflowID(request.GetNamespaceId(), request.GetStartRequest().GetWorkflowId())
1316 > var response *historyservice.StartWorkflowExecutionResponse
1317 > op := func(ctx context.Context, client historyservice.HistoryServiceClient) error {
1318 > var err error
1319 > ctx, cancel := c.createContext(ctx)
1320 > defer cancel()
1321 > response, err = client.StartWorkflowExecution(ctx, request, opts...)
1322 > return err
1323 > }
1324 > if err := c.executeWithRedirect(ctx, shardID, op); err != nil {
1325 > return nil, err client_gen.go
1326 > }
1327 > return response, nil client_gen.go
1328 }
1329
go.temporal.io/server/client/matching/partition_counts.go 60 covered LOC · 18 ranges

Open complete file

33 }
34
35 > func (pc PartitionCounts) encode(includeBacklogInfo bool) (string, error) { partition_counts.go
36 > cpc := taskqueuespb.ClientPartitionCounts{
37 > Read: pc.Read,
38 > Write: pc.Write,
39 > }
40 > if includeBacklogInfo {
41 > cpc.BacklogCap = int32(pc.BacklogCap) partition_counts.go
42 > cpc.BacklogCount = pc.BacklogCount
43 > }
44 > b, err := proto.Marshal(&cpc) partition_counts.go
45 > if err != nil {
46 return "", err
47 }
48 > return string(b), nil partition_counts.go
49 }
50
51 > func (pc PartitionCounts) appendToOutgoingContext(ctx context.Context) context.Context { partition_counts.go
52 > v, err := pc.encode(false) // don't include backlog info in header (client -> server)
53 > if err != nil {
54 return ctx
55 }
56 > return metadata.AppendToOutgoingContext(ctx, partitionCountsHeaderName, v) partition_counts.go
57 }
58
59 > func (pc PartitionCounts) SetTrailer(ctx context.Context) error { partition_counts.go
60 > v, err := pc.encode(true) // include backlog info in trailer (server -> client)
61 > if err != nil {
62 return err
63 }
64 > return grpc.SetTrailer(ctx, metadata.Pairs(partitionCountsTrailerName, v)) partition_counts.go
65 }
66
67 > func (pc PartitionCounts) Equal(other PartitionCounts) bool { partition_counts.go
68 > return pc.Read == other.Read &&
69 > pc.Write == other.Write &&
70 > pc.BacklogCap == other.BacklogCap &&
71 > bytes.Equal(pc.BacklogCount, other.BacklogCount)
72 > }
73
74 > func parsePartitionCounts(hdr string) (PartitionCounts, error) { partition_counts.go
75 > var cpc taskqueuespb.ClientPartitionCounts
76 > err := proto.Unmarshal([]byte(hdr), &cpc)
77 > if err != nil {
78 return PartitionCounts{}, err
79 }
80 > return PartitionCounts{ partition_counts.go
81 > Read: cpc.Read,
82 > Write: cpc.Write,
83 > }, nil
84 }
85
92 }
93
94 > func parsePartitionCountsFromTrailer(trailer metadata.MD) (PartitionCounts, error) { partition_counts.go
95 > vals := trailer.Get(partitionCountsTrailerName)
96 > if len(vals) == 0 {
97 > return PartitionCounts{}, nil partition_counts.go
98 > }
99 > return parsePartitionCounts(vals[0]) partition_counts.go
100 }
101
117 opts []grpc.CallOption,
118 ) (Res, error),
119 > ) (Res, error) { partition_counts.go
120 > // capture trailer
121 > var trailer metadata.MD
122 > opts = append(slices.Clone(opts), grpc.Trailer(&trailer))
123 >
124 > // get current idea of partition counts. if missing from the cache, this will send zeros
125 > // for counts, which the server will always accept as not-stale.
126 > pc := cache.lookup(pkey)
127 >
128 > for attempt := 0; ; attempt++ {
129 > res, err := op(pc.appendToOutgoingContext(ctx), pc, request, opts)
130 >
131 > // update cache on trailer on both success and error. if the trailer has no data,
132 > // this removes the key from the cache.
133 > newPc, parseErr := parsePartitionCountsFromTrailer(trailer)
134 > trailer = nil
135 > if parseErr != nil {
136 logger.Info("partition count trailer parse error", tag.Error(parseErr))
137 // continue with zero value for newPc
138 }
139 > if !newPc.Equal(pc) { partition_counts.go
140 cache.put(pkey, newPc)
141 pc = newPc
142 }
143
144 > if _, ok := errors.AsType[*serviceerrors.StalePartitionCounts](err); ok && attempt == 0 { partition_counts.go
145 // if we got a StalePartitionCounts on the first attempt, retry once
146 continue
147 }
148
149 > return res, err partition_counts.go
150 }
151 }
go.temporal.io/server/common/finalizer/finalizer.go 60 covered LOC · 14 ranges

Open complete file

31 logger log.Logger,
32 metricsHandler metrics.Handler,
33 > ) *Finalizer { finalizer.go
34 > return &Finalizer{
35 > logger: logger,
36 > metricsHandler: metricsHandler,
37 > callbacks: make(map[string]func(context.Context) error),
38 > }
39 > }
40
41 // Register adds a callback to the finalizer.
44 id string,
45 callback func(context.Context) error,
46 > ) error { finalizer.go
47 > f.mu.Lock()
48 > defer f.mu.Unlock()
49 >
50 > if f.finalized {
51 // aborting immediately once the finalizer is/was running
52 return FinalizerAlreadyDoneErr
53 }
54
55 > if _, ok := f.callbacks[id]; ok { finalizer.go
56 return FinalizerDuplicateIdErr
57 }
58 > f.callbacks[id] = callback finalizer.go
59 > return nil
60 }
61
85 func (f *Finalizer) Run(
86 timeout time.Duration,
87 > ) int { finalizer.go
88 > if timeout == 0 {
89 f.logger.Debug("finalizer skipped: zero timeout")
90 return 0
91 }
92
93 > f.mu.Lock() finalizer.go
94 > if f.finalized {
95 f.logger.Warn("finalizer skipped: called more than once")
96 f.mu.Unlock()
97 return 0
98 }
99 > f.finalized = true finalizer.go
100 > f.mu.Unlock() // unlocking immediately to unblock any calls to Register/Deregister
101 >
102 > totalCount := len(f.callbacks)
103 > if totalCount == 0 {
104 f.logger.Debug("finalizer skipped: no callbacks")
105 return 0
106 }
107
108 > f.logger.Debug("finalizer starting", finalizer.go
109 > tag.Int("items", totalCount),
110 > tag.Duration("timeout", timeout))
111 >
112 > startTime := time.Now()
113 > defer func() { metrics.FinalizerLatency.With(f.metricsHandler).Record(time.Since(startTime)) }()
114
115 > ctx, cancel := context.WithTimeout(context.Background(), timeout) finalizer.go
116 > defer cancel()
117 >
118 > pool := goro.NewAdaptivePool(cclock.NewRealTimeSource(), 5, 15, 10*time.Millisecond, 10)
119 > defer pool.Stop()
120 >
121 > completionChannel := make(chan struct{})
122 > go func() {
123 > for _, callback := range f.callbacks {
124 > // NOTE: Once `pool.Stop` is called, any remaining calls to `pool.Do` will do nothing.
125 > pool.Do(func() {
126 > defer func() { completionChannel <- struct{}{} }()
127 > _ = callback(ctx)
128 })
129 }
131 // prevent holding on to the callbacks for longer than needed and allow garbage collection
132 // (safe since any calls to Register/Deregister will be aborted now that the finalizer ran)
133 > f.callbacks = nil finalizer.go
134 }()
135
136 > var completedCallbacks int finalizer.go
137 > defer func() {
138 > unfinishedItems := int64(totalCount - completedCallbacks)
139 > metrics.FinalizerRuns.With(f.metricsHandler).Record(1)
140 > if unfinishedItems > 0 {
141 metrics.FinalizerRunTimeouts.With(f.metricsHandler).Record(1)
142 }
143 > metrics.FinalizerItemsCompleted.With(f.metricsHandler).Record(int64(completedCallbacks)) finalizer.go
144 > metrics.FinalizerItemsUnfinished.With(f.metricsHandler).Record(unfinishedItems)
145 }()
146
147 > for { finalizer.go
148 > select {
149 > case <-completionChannel:
150 > completedCallbacks += 1
151 > if completedCallbacks == totalCount {
152 > f.logger.Debug("finalizer completed", finalizer.go
153 > tag.Int("completed", completedCallbacks))
154 > return completedCallbacks
155 > }
156
157 case <-ctx.Done():
go.temporal.io/server/common/persistence/health_signal_aggregator.go 60 covered LOC · 21 ranges

Open complete file

60 latencyWindowSize time.Duration,
61 latencyWindowCount int,
62 > ) *healthSignalAggregatorImpl { health_signal_aggregator.go
63 > latencyDistribution, err := stats.NewWindowedTDigest(stats.WindowConfig{
64 > WindowSize: latencyWindowSize,
65 > WindowCount: latencyWindowCount,
66 > })
67 > if err != nil {
68 logger.Error("failed to create latency distribution helper, falling back to default config", tag.Error(err))
69 latencyDistribution, err = stats.NewWindowedTDigest(stats.WindowConfig{
76 }
77
78 > ret := &healthSignalAggregatorImpl{ health_signal_aggregator.go
79 > status: common.DaemonStatusInitialized,
80 > shutdownCh: make(chan struct{}),
81 > requestCounts: make(map[int32]int64),
82 > metricsHandler: metricsHandler,
83 > emitMetricsTimer: time.NewTicker(emitMetricsInterval),
84 > logger: logger,
85 > aggregationEnabled: aggregationEnabled,
86 > percentilesEnabled: percentilesEnabled,
87 > latencyDistribution: latencyDistribution,
88 > }
89 >
90 > if aggregationEnabled {
91 > ret.latencyAverage = aggregate.NewMovingWindowAvgImpl(windowSize, maxBufferSize)
92 > ret.errorRatio = aggregate.NewMovingWindowAvgImpl(windowSize, maxBufferSize)
93 > } else {
94 ret.latencyAverage = aggregate.NoopMovingWindowAverage
95 ret.errorRatio = aggregate.NoopMovingWindowAverage
96 }
97
98 > return ret health_signal_aggregator.go
99 }
100
101 > func (s *healthSignalAggregatorImpl) Start() { health_signal_aggregator.go
102 > if !atomic.CompareAndSwapInt32(&s.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
103 return
104 }
105 > go s.emitMetricsLoop() health_signal_aggregator.go
106 }
107
108 > func (s *healthSignalAggregatorImpl) Stop() { health_signal_aggregator.go
109 > if !atomic.CompareAndSwapInt32(&s.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
110 return
111 }
112 > close(s.shutdownCh) health_signal_aggregator.go
113 > s.emitMetricsTimer.Stop()
114 }
115
116 > func (s *healthSignalAggregatorImpl) Record(callerSegment int32, latency time.Duration, err error) { health_signal_aggregator.go
117 > if s.aggregationEnabled {
118 > s.latencyAverage.Record(latency.Milliseconds())
119 >
120 > if s.percentilesEnabled() && s.latencyDistribution != nil {
121 s.latencyDistribution.RecordToLatestWindow(float64(latency.Milliseconds()))
122 }
123
124 > if isUnhealthyError(err) { health_signal_aggregator.go
125 s.errorRatio.Record(1)
127 > s.errorRatio.Record(0) health_signal_aggregator.go
128 > }
129 }
130
131 > if callerSegment != CallerSegmentMissing { health_signal_aggregator.go
132 > s.incrementShardRequestCount(callerSegment)
133 > }
134 }
135
154 }
155
156 > func (s *healthSignalAggregatorImpl) incrementShardRequestCount(shardID int32) { health_signal_aggregator.go
157 > s.requestsLock.Lock()
158 > defer s.requestsLock.Unlock()
159 > s.requestCounts[shardID]++
160 > }
161
162 // Traverse through all shards and get the per-namespace persistence RPS for all shards.
164 // is configured in dynamic config. This will allow us to see if some namespaces had hit
165 // this limit in any of the shards.
166 > func (s *healthSignalAggregatorImpl) emitMetricsLoop() { health_signal_aggregator.go
167 > for {
168 > select {
169 > case <-s.shutdownCh: health_signal_aggregator.go
170 > return
171 case <-s.emitMetricsTimer.C:
172 s.requestsLock.Lock()
183 }
184
185 > func isUnhealthyError(err error) bool { health_signal_aggregator.go
186 > if err == nil {
187 > return false health_signal_aggregator.go
188 > }
189 > if common.IsContextCanceledErr(err) { health_signal_aggregator.go
190 return true
191 }
192 > if common.IsContextDeadlineExceededErr(err) { health_signal_aggregator.go
193 return true
194 }
195
196 > switch err.(type) { health_signal_aggregator.go
197 case *AppendHistoryTimeoutError,
198 *TimeoutError:
199 return true
200 }
201 > return false health_signal_aggregator.go
202 }
go.temporal.io/server/service/matching/task_tracker.go 60 covered LOC · 10 ranges

Open complete file

13 }
14
15 > func newCircularTaskBuffer(size int) circularTaskBuffer { task_tracker.go
16 > return circularTaskBuffer{
17 > buffer: make([]int32, size),
18 > }
19 > }
20
21 > func (cb *circularTaskBuffer) inc(n int) { task_tracker.go
22 > cb.buffer[cb.currentPos] += int32(n)
23 > }
24
25 func (cb *circularTaskBuffer) advance() {
29
30 // returns the total number of tasks in the buffer
31 > func (cb *circularTaskBuffer) totalTasks() int { task_tracker.go
32 > totalTasks := 0
33 > for _, count := range cb.buffer {
34 > totalTasks += int(count)
35 > }
36 > return totalTasks
37 }
38
53 bucketSize time.Duration,
54 totalInterval time.Duration,
55 > ) *taskTracker { task_tracker.go
56 > bucketSize = max(bucketSize, time.Millisecond)
57 > buckets := int(totalInterval/bucketSize) + 1
58 > return &taskTracker{
59 > clock: timeSource,
60 > startTime: timeSource.Now(),
61 > bucketStartTime: timeSource.Now(),
62 > bucketSize: bucketSize,
63 > buckets: buckets,
64 > totalInterval: totalInterval,
65 > tasks: newCircularTaskBuffer(buckets),
66 > }
67 > }
68
69 // advanceAndReset advances the trackers position and clears out any expired intervals.
70 > func (s *taskTracker) advanceAndReset(elapsed time.Duration) { task_tracker.go
71 > // Calculate the number of intervals elapsed since the start interval time
72 > intervalsElapsed := int(elapsed / s.bucketSize)
73 >
74 > for range min(intervalsElapsed, s.buckets) {
75 s.tasks.advance() // advancing our circular buffer's position until we land on the right interval
76 }
77 > s.bucketStartTime = s.bucketStartTime.Add(time.Duration(intervalsElapsed) * s.bucketSize) task_tracker.go
78 }
79
80 // inc increments the count of tasks by n at the current time
81 > func (s *taskTracker) inc(n int) { task_tracker.go
82 > currentTime := s.clock.Now()
83 >
84 > // Calculate elapsed time from the latest start interval time
85 > elapsed := currentTime.Sub(s.bucketStartTime)
86 > s.advanceAndReset(elapsed)
87 > s.tasks.inc(n)
88 > }
89
90 // rate returns the rate of increments in a given interval
91 > func (s *taskTracker) rate() float32 { task_tracker.go
92 > rate, _ := s.rateAndFull()
93 > return rate
94 > }
95
96 // rateAndFull returns the rate of increments in a given interval, plus whether the full
97 // interval has elapsed.
98 > func (s *taskTracker) rateAndFull() (float32, bool) { task_tracker.go
99 > currentTime := s.clock.Now()
100 >
101 > // Calculate elapsed time from the latest start interval time
102 > elapsed := currentTime.Sub(s.bucketStartTime)
103 > s.advanceAndReset(elapsed)
104 > totalTasks := s.tasks.totalTasks()
105 >
106 > elapsedTime := min(
107 > currentTime.Sub(s.bucketStartTime)+s.totalInterval,
108 > currentTime.Sub(s.startTime))
109 >
110 > if elapsedTime <= 0 {
111 return 0, false
112 }
113
114 // rate per second
115 > full := elapsedTime >= s.totalInterval task_tracker.go
116 > return float32(totalTasks) / float32(elapsedTime.Seconds()), full
117 }
go.temporal.io/server/chasm/registrable_task.go 59 covered LOC · 12 ranges

Open complete file

50 handler SideEffectTaskHandler[C, T],
51 opts ...RegistrableTaskOption,
52 > ) *RegistrableTask { registrable_task.go
53 > return newRegistrableTask(
54 > taskType,
55 > reflect.TypeFor[T](),
56 > reflect.TypeFor[C](),
57 > func(
58 > ctx Context,
59 > component any,
60 > taskInvocation TaskInvocation,
61 > taskData any,
62 > registry *Registry,
63 > ) (bool, error) {
64 return handler.Validate(
65 ctx,
90 handler PureTaskHandler[C, T],
91 opts ...RegistrableTaskOption,
92 > ) *RegistrableTask { registrable_task.go
93 > return newRegistrableTask(
94 > taskType,
95 > reflect.TypeFor[T](),
96 > reflect.TypeFor[C](),
97 > func(
98 > ctx Context,
99 > component any,
100 > taskInvocation TaskInvocation,
101 > taskData any,
102 > registry *Registry,
103 > ) (bool, error) {
104 return handler.Validate(
105 ctx,
139 sideEffectTaskDiscardFn sideEffectTaskDiscardFn,
140 opts ...RegistrableTaskOption,
141 > ) *RegistrableTask { registrable_task.go
142 > rt := &RegistrableTask{
143 > taskType: taskType,
144 > goType: goType,
145 > componentGoType: componentGoType,
146 > validateFn: validateFn,
147 > pureTaskExecuteFn: pureTaskExecuteFn,
148 > sideEffectTaskExecuteFn: sideEffectTaskExecuteFn,
149 > sideEffectTaskDiscardFn: sideEffectTaskDiscardFn,
150 > isPureTask: isPureTask,
151 > }
152 >
153 > for _, opt := range opts {
154 > opt(rt) registrable_task.go
155 > }
156
157 > return rt registrable_task.go
158 }
159
160 func (rt *RegistrableTask) registerToLibrary(
161 library namer,
162 > ) (string, uint32, error) { registrable_task.go
163 > if rt.library != nil {
164 return "", 0, fmt.Errorf("task %s is already registered in library %s", rt.taskType, rt.library.Name())
165 }
166
167 > rt.library = library registrable_task.go
168 >
169 > fqn := rt.fqType()
170 > rt.taskTypeID = GenerateTypeID(fqn)
171 > // If outboundTaskGroup wasn't set on creation default it here,
172 > // since this is the first place we will have the fqn.
173 > if rt.outboundTaskGroup == "" {
174 > rt.outboundTaskGroup = fqn registrable_task.go
175 > }
176 > return fqn, rt.taskTypeID, nil registrable_task.go
177 }
178
190 // the library name and the task type. This is used to uniquely identify
191 // the task in the registry.
192 > func (rt *RegistrableTask) fqType() string { registrable_task.go
193 > if rt.library == nil {
194 // this should never happen because the task is only accessible from the library.
195 panic("task is not registered to a library")
196 }
197 > return FullyQualifiedName(rt.library.Name(), rt.taskType) registrable_task.go
198 }
199
202 // affects multi-cursor and the circuit breaker.
203 // If task group isn't provided, the task group will default to the fully qualified name at library registration.
204 > func WithTaskGroup(taskgroup string) RegistrableTaskOption { registrable_task.go
205 > return func(rt *RegistrableTask) {
206 > rt.outboundTaskGroup = taskgroup
207 > }
208 }
209
go.temporal.io/server/common/config/persistence.go 59 covered LOC · 27 ranges

Open complete file

25
26 // DefaultStoreType returns the storeType for the default persistence store
27 > func (c *Persistence) DefaultStoreType() string { persistence.go
28 > if c.DataStores[c.DefaultStore].SQL != nil {
29 > return StoreTypeSQL persistence.go
30 > }
31 return StoreTypeNoSQL
32 }
33
34 // Validate validates the persistence config
35 > func (c *Persistence) Validate() error { persistence.go
36 > stores := []string{c.DefaultStore}
37 > if c.VisibilityStore != "" {
38 > stores = append(stores, c.VisibilityStore)
39 > }
40 > if c.SecondaryVisibilityStore != "" {
41 stores = append(stores, c.SecondaryVisibilityStore)
42 }
57 // - visibilityStore (es), secondaryVisibilityStore (advanced sql)
58
59 > if c.VisibilityStore == "" { persistence.go
60 return fmt.Errorf("%w: visibilityStore must be specified", ErrPersistenceConfig)
61 }
62 > if c.SecondaryVisibilityStore != "" { persistence.go
63 isAnyCustom := c.DataStores[c.VisibilityStore].CustomDataStoreConfig != nil ||
64 c.DataStores[c.SecondaryVisibilityStore].CustomDataStoreConfig != nil
84 }
85
86 > for _, st := range stores { persistence.go
87 > ds, ok := c.DataStores[st]
88 > if !ok {
89 return fmt.Errorf("%w: missing config for datastore %q", ErrPersistenceConfig, st)
90 }
91 > if err := ds.Validate(); err != nil { persistence.go
92 return fmt.Errorf("%w: datastore %q: %s", ErrPersistenceConfig, st, err.Error())
93 }
94 }
95 > return nil persistence.go
96 }
97
98 // VisibilityConfigExist returns whether user specified visibilityStore in config
99 > func (c *Persistence) VisibilityConfigExist() bool { persistence.go
100 > return c.VisibilityStore != ""
101 > }
102
103 // SecondaryVisibilityConfigExist returns whether user specified secondaryVisibilityStore in config
104 > func (c *Persistence) SecondaryVisibilityConfigExist() bool { persistence.go
105 > return c.SecondaryVisibilityStore != ""
106 > }
107
108 func (c *Persistence) IsSQLVisibilityStore() bool {
116 }
117
118 > func (c *Persistence) GetVisibilityStoreConfig() DataStore { persistence.go
119 > return c.DataStores[c.VisibilityStore]
120 > }
121
122 > func (c *Persistence) GetSecondaryVisibilityStoreConfig() DataStore { persistence.go
123 > if c.SecondaryVisibilityStore != "" {
124 return c.DataStores[c.SecondaryVisibilityStore]
125 }
126 > if c.VisibilityStore != "" { persistence.go
127 > ds := c.DataStores[c.VisibilityStore]
128 > if ds.Elasticsearch != nil && ds.Elasticsearch.GetSecondaryVisibilityIndex() != "" {
129 esConfig := *ds.Elasticsearch
130 esConfig.Indices = map[string]string{
135 }
136 }
137 > return DataStore{} persistence.go
138 }
139
140 > func (ds *DataStore) GetIndexName() string { persistence.go
141 > switch {
142 > case ds.SQL != nil:
143 > return ds.SQL.DatabaseName
144 case ds.Cassandra != nil:
145 return ds.Cassandra.Keyspace
148 case ds.CustomDataStoreConfig != nil:
149 return ds.CustomDataStoreConfig.IndexName
150 > default: persistence.go
151 > return ""
152 }
153 }
154
155 // Validate validates the data store config
156 > func (ds *DataStore) Validate() error { persistence.go
157 > storeConfigCount := 0
158 > if ds.SQL != nil {
159 > storeConfigCount++
160 > }
161 > if ds.Cassandra != nil {
162 storeConfigCount++
163 }
164 > if ds.CustomDataStoreConfig != nil { persistence.go
165 storeConfigCount++
166 }
167 > if ds.Elasticsearch != nil { persistence.go
168 storeConfigCount++
169 }
170 > if storeConfigCount != 1 { persistence.go
171 return errors.New(
172 "must provide config for one and only one datastore: " +
175 }
176
177 > if ds.SQL != nil { persistence.go
178 > if ds.SQL.TaskScanPartitions == 0 {
179 > ds.SQL.TaskScanPartitions = 1
180 > }
181 > if err := ds.SQL.validate(); err != nil {
182 return err
183 }
184 }
185 > if ds.Cassandra != nil { persistence.go
186 if err := ds.Cassandra.validate(); err != nil {
187 return err
188 }
189 }
190 > if ds.Elasticsearch != nil { persistence.go
191 if err := ds.Elasticsearch.Validate(); err != nil {
192 return err
193 }
194 }
195 > return nil persistence.go
196 }
197
282 }
283
284 > func (c *SQL) validate() error { persistence.go
285 > if c.PasswordCommand != nil && c.Password != "" {
286 return errors.New("passwordCommand and password are mutually exclusive")
287 }
288 > if c.PasswordCommand != nil && c.PasswordCommand.Command == "" { persistence.go
289 return errors.New("passwordCommand.command must not be empty")
290 }
291 > return nil persistence.go
292 }
293
go.temporal.io/server/common/sdk/factory.go 59 covered LOC · 12 ranges

Open complete file

56 logger log.Logger,
57 stickyCacheSize dynamicconfig.IntPropertyFn,
58 > ) *clientFactory { factory.go
59 > return &clientFactory{
60 > hostPort: hostPort,
61 > tlsConfig: tlsConfig,
62 > metricsHandler: NewMetricsHandler(metricsHandler),
63 > logger: logger,
64 > sdklogger: log.NewSdkLogger(logger),
65 > stickyCacheSize: stickyCacheSize,
66 > }
67 > }
68
69 > func (f *clientFactory) options(options sdkclient.Options) sdkclient.Options { factory.go
70 > options.HostPort = f.hostPort
71 > options.MetricsHandler = f.metricsHandler
72 > options.Logger = f.sdklogger
73 > options.ConnectionOptions = sdkclient.ConnectionOptions{
74 > TLS: f.tlsConfig,
75 > DialOptions: []grpc.DialOption{
76 > grpc.WithUnaryInterceptor(sdkClientNameHeadersInjectorInterceptor()),
77 > },
78 > }
79 > return options
80 > }
81
82 > func (f *clientFactory) NewClient(options sdkclient.Options) sdkclient.Client { factory.go
83 > // this shouldn't fail if the first client was created successfully
84 > client, err := sdkclient.NewClientFromExisting(f.GetSystemClient(), f.options(options))
85 > if err != nil {
86 f.logger.Fatal("error creating sdk client", tag.Error(err))
87 }
88 > return client factory.go
89 }
90
91 > func (f *clientFactory) GetSystemClient() sdkclient.Client { factory.go
92 > f.once.Do(func() {
93 > err := backoff.ThrottleRetry(func() error {
94 > sdkClient, err := sdkclient.Dial(f.options(sdkclient.Options{
95 > Namespace: primitives.SystemLocalNamespace,
96 > }))
97 > if err != nil {
98 f.logger.Warn("error creating sdk client", tag.Error(err))
99 return err
100 }
101 > f.systemSdkClient = sdkClient factory.go
102 > return nil
103 }, common.CreateSdkClientFactoryRetryPolicy(), func(err error) bool {
104 // note err is wrapped by sdk
106 return common.IsContextDeadlineExceededErr(err) || errors.As(err, &unavail)
107 })
108 > if err != nil { factory.go
109 f.logger.Fatal("error creating sdk client", tag.Error(err))
110 }
111
112 > if size := f.stickyCacheSize(); size > 0 { factory.go
113 f.logger.Info("setting sticky workflow cache size", tag.Int("size", size))
114 sdkworker.SetStickyWorkflowCacheSize(size)
115 }
116 })
117 > return f.systemSdkClient factory.go
118 }
119
122 taskQueue string,
123 options sdkworker.Options,
124 > ) sdkworker.Worker { factory.go
125 > return sdkworker.New(client, taskQueue, options)
126 > }
127
128 // Overwrite the 'client-name' and 'client-version' headers on gRPC requests sent using the Go SDK
129 // so they clearly indicate that the request is coming from the Temporal server.
130 > func sdkClientNameHeadersInjectorInterceptor() grpc.UnaryClientInterceptor { factory.go
131 > return func(
132 > ctx context.Context,
133 > method string,
134 > req, reply any,
135 > cc *grpc.ClientConn,
136 > invoker grpc.UnaryInvoker,
137 > opts ...grpc.CallOption,
138 > ) error {
139 > // Can't use headers.SetVersions() here because it is _appending_ headers to the context
140 > // rather than _replacing_ them, which means Go SDK's default headers would still be present.
141 > md, mdExist := metadata.FromOutgoingContext(ctx)
142 > if !mdExist {
143 md = metadata.New(nil)
144 }
145 > md.Set(headers.ClientNameHeaderName, headers.ClientNameServer) factory.go
146 > md.Set(headers.ClientVersionHeaderName, headers.ServerVersion)
147 > ctx = metadata.NewOutgoingContext(ctx, md)
148 > return invoker(ctx, method, req, reply, cc, opts...)
149 }
150 }
go.temporal.io/server/common/searchattribute/manager.go 59 covered LOC · 15 ranges

Open complete file

53 logger log.Logger,
54 forceRefresh dynamicconfig.BoolPropertyFn,
55 > ) *managerImpl { manager.go
56 > var saCache atomic.Value
57 > saCache.Store(cache{
58 > searchAttributes: map[string]NameTypeMap{},
59 > dbVersion: 0,
60 > expireOn: time.Time{},
61 > })
62 >
63 > return &managerImpl{
64 > logger: logger,
65 > timeSource: timeSource,
66 > cache: saCache,
67 > clusterMetadataManager: clusterMetadataManager,
68 > forceRefresh: forceRefresh,
69 > }
70 > }
71
72 // GetSearchAttributes returns all search attributes (including system and build-in) for specified index.
75 indexName string,
76 forceRefreshCache bool,
77 > ) (NameTypeMap, error) { manager.go
78 > now := m.timeSource.Now()
79 > result := NewNameTypeMap(nil)
80 > saCache, err := m.refreshCache(forceRefreshCache, now)
81 > if err != nil {
82 m.logger.Error("failed to refresh search attributes cache", tag.Error(err))
83 return result, err
84 }
85 > if indexSearchAttributes, ok := saCache.searchAttributes[indexName]; ok { manager.go
86 > result.customSearchAttributes = maps.Clone(indexSearchAttributes.customSearchAttributes) manager.go
87 > }
88 > return result, nil manager.go
89 }
90
91 > func (m *managerImpl) needRefreshCache(saCache cache, forceRefreshCache bool, now time.Time) bool { manager.go
92 > return forceRefreshCache || saCache.expireOn.Before(now) || m.forceRefresh()
93 > }
94
95 > func (m *managerImpl) refreshCache(forceRefreshCache bool, now time.Time) (cache, error) { manager.go
96 > //nolint:revive // cache value is always of type `cache`
97 > saCache := m.cache.Load().(cache)
98 > if !m.needRefreshCache(saCache, forceRefreshCache, now) {
99 > return saCache, nil manager.go
100 > }
101
102 > m.cacheUpdateMutex.Lock() manager.go
103 > defer m.cacheUpdateMutex.Unlock()
104 > //nolint:revive // cache value is always of type `cache`
105 > saCache = m.cache.Load().(cache)
106 > if !m.needRefreshCache(saCache, forceRefreshCache, now) {
107 > return saCache, nil manager.go
108 > }
109
110 > return m.refreshCacheLocked(saCache, now) manager.go
111 }
112
113 > func (m *managerImpl) refreshCacheLocked(saCache cache, now time.Time) (cache, error) { manager.go
114 > ctx, cancel := context.WithTimeout(context.Background(), cacheRefreshTimeout)
115 > defer cancel()
116 > if saCache.dbVersion == 0 {
117 > // if cache is cold, use the highest priority caller
118 > ctx = headers.SetCallerInfo(ctx, headers.SystemOperatorCallerInfo)
119 > } else {
120 ctx = headers.SetCallerInfo(ctx, headers.SystemBackgroundHighCallerInfo)
121 }
122
123 > clusterMetadata, err := m.clusterMetadataManager.GetCurrentClusterMetadata(ctx) manager.go
124 > if err != nil {
125 switch err.(type) {
126 case *serviceerror.NotFound:
146
147 // clusterMetadata.Version <= saCache.dbVersion means DB is not changed.
148 > if clusterMetadata.Version <= saCache.dbVersion { manager.go
149 saCache.expireOn = now.Add(cacheRefreshInterval)
150 m.cache.Store(saCache)
152 }
153
154 > saCache = cache{ manager.go
155 > searchAttributes: buildIndexNameTypeMap(clusterMetadata.GetIndexSearchAttributes()),
156 > expireOn: now.Add(cacheRefreshInterval),
157 > dbVersion: clusterMetadata.Version,
158 > }
159 > m.cache.Store(saCache)
160 > return saCache, nil
161 }
162
go.temporal.io/server/api/token/v1/message.pb.go 58 covered LOC · 11 ranges

Open complete file

258 }
259
260 > func (x *Task) Reset() { message.pb.go
261 > *x = Task{}
262 > mi := &file_temporal_server_api_token_v1_message_proto_msgTypes[2]
263 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
264 > ms.StoreMessageInfo(mi)
265 > }
266
267 func (x *Task) String() string {
271 func (*Task) ProtoMessage() {}
272
273 > func (x *Task) ProtoReflect() protoreflect.Message { message.pb.go
274 > mi := &file_temporal_server_api_token_v1_message_proto_msgTypes[2]
275 > if x != nil {
276 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
277 > if ms.LoadMessageInfo() == nil {
278 > ms.StoreMessageInfo(mi)
279 > }
280 > return ms
281 }
282 return mi.MessageOf(x)
288 }
289
290 > func (x *Task) GetNamespaceId() string { message.pb.go
291 > if x != nil {
292 > return x.NamespaceId
293 > }
294 return ""
295 }
296
297 > func (x *Task) GetWorkflowId() string { message.pb.go
298 > if x != nil {
299 > return x.WorkflowId
300 > }
301 return ""
302 }
303
304 > func (x *Task) GetRunId() string { message.pb.go
305 > if x != nil {
306 > return x.RunId
307 > }
308 return ""
309 }
310
311 > func (x *Task) GetScheduledEventId() int64 { message.pb.go
312 > if x != nil {
313 > return x.ScheduledEventId
314 > }
315 return 0
316 }
379 }
380
381 > func (x *Task) GetComponentRef() []byte { message.pb.go
382 > if x != nil {
383 > return x.ComponentRef
384 > }
385 return nil
386 }
610 func (*NexusOperationCompletion) ProtoMessage() {}
611
612 > func (x *NexusOperationCompletion) ProtoReflect() protoreflect.Message { message.pb.go
613 > mi := &file_temporal_server_api_token_v1_message_proto_msgTypes[6]
614 > if x != nil {
615 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
616 if ms.LoadMessageInfo() == nil {
619 return ms
620 }
621 > return mi.MessageOf(x) message.pb.go
622 }
623
785 }
786
787 > func init() { file_temporal_server_api_token_v1_message_proto_init() } message.pb.go
788 > func file_temporal_server_api_token_v1_message_proto_init() {
789 > if File_temporal_server_api_token_v1_message_proto != nil {
790 return
791 }
792 > type x struct{} message.pb.go
793 > out := protoimpl.TypeBuilder{
794 > File: protoimpl.DescBuilder{
795 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
796 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_token_v1_message_proto_rawDesc), len(file_temporal_server_api_token_v1_message_proto_rawDesc)),
797 > NumEnums: 0,
798 > NumMessages: 7,
799 > NumExtensions: 0,
800 > NumServices: 0,
801 > },
802 > GoTypes: file_temporal_server_api_token_v1_message_proto_goTypes,
803 > DependencyIndexes: file_temporal_server_api_token_v1_message_proto_depIdxs,
804 > MessageInfos: file_temporal_server_api_token_v1_message_proto_msgTypes,
805 > }.Build()
806 > File_temporal_server_api_token_v1_message_proto = out.File
807 > file_temporal_server_api_token_v1_message_proto_goTypes = nil
808 > file_temporal_server_api_token_v1_message_proto_depIdxs = nil
809 }
go.temporal.io/server/common/persistence/versionhistory/version_history.go 58 covered LOC · 23 ranges

Open complete file

8
9 // NewVersionHistory create a new instance of VersionHistory.
10 > func NewVersionHistory(branchToken []byte, items []*historyspb.VersionHistoryItem) *historyspb.VersionHistory { version_history.go
11 > return &historyspb.VersionHistory{
12 > BranchToken: branchToken,
13 > Items: items,
14 > }
15 > }
16
17 // CopyVersionHistory copies VersionHistory.
18 > func CopyVersionHistory(v *historyspb.VersionHistory) *historyspb.VersionHistory { version_history.go
19 > token := make([]byte, len(v.BranchToken))
20 > copy(token, v.BranchToken)
21 >
22 > items := CopyVersionHistoryItems(v.Items)
23 >
24 > return NewVersionHistory(token, items)
25 > }
26
27 > func CopyVersionHistoryItems(items []*historyspb.VersionHistoryItem) []*historyspb.VersionHistoryItem { version_history.go
28 > var result []*historyspb.VersionHistoryItem
29 > for _, item := range items {
30 > result = append(result, CopyVersionHistoryItem(item)) version_history.go
31 > }
32 > return result version_history.go
33 }
34
58
59 // SetVersionHistoryBranchToken sets the branch token.
60 > func SetVersionHistoryBranchToken(v *historyspb.VersionHistory, branchToken []byte) { version_history.go
61 > v.BranchToken = make([]byte, len(branchToken))
62 > copy(v.BranchToken, branchToken)
63 > }
64
65 // AddOrUpdateVersionHistoryItem updates the VersionHistory with new VersionHistoryItem.
66 > func AddOrUpdateVersionHistoryItem(v *historyspb.VersionHistory, item *historyspb.VersionHistoryItem) error { version_history.go
67 > if len(v.Items) == 0 {
68 > v.Items = []*historyspb.VersionHistoryItem{CopyVersionHistoryItem(item)} version_history.go
69 > return nil
70 > }
71
72 > lastItem := v.Items[len(v.Items)-1] version_history.go
73 > if item.Version < lastItem.Version {
74 return serviceerror.NewInternalf("cannot update version history with a lower version %v. Last version: %v", item.Version, lastItem.Version)
75 }
76
77 > if item.GetEventId() <= lastItem.GetEventId() { version_history.go
78 return serviceerror.NewInternalf("cannot add version history with a lower event id %v. Last event id: %v", item.GetEventId(), lastItem.GetEventId())
79 }
80
81 > if item.Version > lastItem.Version { version_history.go
82 // Add a new history
83 v.Items = append(v.Items, CopyVersionHistoryItem(item))
84 > } else { version_history.go
85 > // item.Version == lastItem.Version && item.EventID > lastItem.EventID version_history.go
86 > // Update event ID
87 > lastItem.EventId = item.GetEventId()
88 > }
89 > return nil version_history.go
90 }
91
92 // ContainsVersionHistoryItem check whether VersionHistory has given VersionHistoryItem.
93 > func ContainsVersionHistoryItem(v *historyspb.VersionHistory, item *historyspb.VersionHistoryItem) bool { version_history.go
94 > prevEventID := common.FirstEventID - 1
95 > for _, currentItem := range v.Items {
96 > if item.GetVersion() == currentItem.GetVersion() {
97 > if prevEventID < item.GetEventId() && item.GetEventId() <= currentItem.GetEventId() { version_history.go
98 > return true version_history.go
99 > }
100 } else if item.GetVersion() < currentItem.GetVersion() {
101 return false
207
208 // GetFirstVersionHistoryItem return the first VersionHistoryItem.
209 > func GetFirstVersionHistoryItem(v *historyspb.VersionHistory) (*historyspb.VersionHistoryItem, error) { version_history.go
210 > if len(v.Items) == 0 {
211 return nil, serviceerror.NewInternal("version history is empty.")
212 }
213 > return CopyVersionHistoryItem(v.Items[0]), nil version_history.go
214 }
215
216 // GetLastVersionHistoryItem return the last VersionHistoryItem.
217 > func GetLastVersionHistoryItem(v *historyspb.VersionHistory) (*historyspb.VersionHistoryItem, error) { version_history.go
218 > return getLastVersionHistoryItem(v.Items)
219 > }
220
221 > func getLastVersionHistoryItem(v []*historyspb.VersionHistoryItem) (*historyspb.VersionHistoryItem, error) { version_history.go
222 > if len(v) == 0 {
223 return nil, serviceerror.NewInternal("version history is empty.")
224 }
225 > return CopyVersionHistoryItem(v[len(v)-1]), nil version_history.go
226 }
227
248
249 // IsEmptyVersionHistory indicate whether version history is empty
250 > func IsEmptyVersionHistory(v *historyspb.VersionHistory) bool { version_history.go
251 > return len(v.Items) == 0
252 > }
253
254 // CompareVersionHistory compares 2 version history items
go.temporal.io/server/client/history/connections.go 57 covered LOC · 16 ranges

Open complete file

56 logger log.Logger,
57 connectionCloseDelay dynamicconfig.DurationPropertyFn,
58 > ) *connectionPoolImpl[C] { connections.go
59 > conns := &sync.Map{}
60 >
61 > c := &connectionPoolImpl[C]{
62 > conns: conns,
63 > historyServiceResolver: historyServiceResolver,
64 > rpcFactory: rpcFactory,
65 > clientCtor: clientCtor,
66 > logger: logger,
67 > connectionCloseDelay: connectionCloseDelay,
68 > }
69 >
70 > // Close cached conns whose host leaves the membership ring.
71 > c.watcher = goro.NewHandle(context.Background()).Go(c.watchMembership)
72 > return c
73 > }
74
75 // Close stops the watcher and closes all pooled connections.
76 > func (c *connectionPoolImpl[C]) Close() { connections.go
77 > if !c.closed.CompareAndSwap(false, true) {
78 return
79 }
80 > c.watcher.Cancel() connections.go
81 > <-c.watcher.Done()
82 > // Set closed before reaping so a concurrent create can't re-cache a conn.
83 > c.conns.Range(func(key, value any) bool {
84 > c.conns.Delete(key) connections.go
85 > if err := value.(clientConnection[C]).grpcConn.Close(); err != nil {
86 c.logger.Warn("Error closing gRPC connection on shutdown", tag.Error(err))
87 }
88 > return true connections.go
89 })
90 }
91
92 > func (c *connectionPoolImpl[C]) watchMembership(ctx context.Context) error { connections.go
93 > listenerName := fmt.Sprintf("%p", c.conns)
94 > ch := make(chan *membership.ChangedEvent, 1)
95 > if err := c.historyServiceResolver.AddListener(listenerName, ch); err != nil {
96 c.logger.Error("Failed to subscribe history connection pool to membership", tag.Error(err))
97 return err
98 }
99 > defer func() { _ = c.historyServiceResolver.RemoveListener(listenerName) }() connections.go
100
101 // Reap departed hosts via a per-address deadline checked by a single ticker;
102 // a re-add resets it to the latest removal.
103 > evictAt := make(map[rpcAddress]time.Time) connections.go
104 > ticker := time.NewTicker(evictionCheckInterval)
105 > defer ticker.Stop()
106 > for {
107 > select {
108 > case <-ctx.Done(): connections.go
109 > return nil
110 > case event := <-ch: connections.go
111 > for _, h := range event.HostsRemoved {
112 > evictAt[rpcAddress(h.GetAddress())] = time.Now().Add(c.connectionCloseDelay()) connections.go
113 > }
114 > for _, h := range event.HostsAdded { connections.go
115 > delete(evictAt, rpcAddress(h.GetAddress()))
116 > }
117 case <-ticker.C:
118 c.reapClosableConns(evictAt)
147 }
148
149 > func (c *connectionPoolImpl[C]) getOrCreateClientConn(addr rpcAddress) clientConnection[C] { connections.go
150 > if v, ok := c.conns.Load(addr); ok {
151 > return v.(clientConnection[C]) // nolint:revive // unchecked-type-assertion
152 > }
153
154 > grpcConn := c.rpcFactory.CreateHistoryGRPCConnection(string(addr)) connections.go
155 > cc := clientConnection[C]{
156 > grpcClient: c.clientCtor(grpcConn),
157 > grpcConn: grpcConn,
158 > }
159 >
160 > if actual, loaded := c.conns.LoadOrStore(addr, cc); loaded {
161 _ = grpcConn.Close()
162 return actual.(clientConnection[C]) // nolint:revive // unchecked-type-assertion
163 }
164 // Lost the race with Close; drop the conn we just cached.
165 > if c.closed.Load() { connections.go
166 if v, ok := c.conns.LoadAndDelete(addr); ok {
167 _ = v.(clientConnection[C]).grpcConn.Close()
168 }
169 }
170 > return cc connections.go
171 }
172
go.temporal.io/server/common/rpc/grpc.go 56 covered LOC · 8 ranges

Open complete file

54 metricsHandler metrics.Handler,
55 opts ...grpc.DialOption,
56 > ) (*grpc.ClientConn, error) { grpc.go
57 > var grpcSecureOpt grpc.DialOption
58 > if tlsConfig == nil {
59 > grpcSecureOpt = grpc.WithTransportCredentials(insecure.NewCredentials()) grpc.go
60 > } else { grpc.go
61 grpcSecureOpt = grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))
62 }
67 // https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md.
68 // Default MaxDelay is 120 seconds which is too high.
69 > var cp = grpc.ConnectParams{ grpc.go
70 > Backoff: backoff.DefaultConfig,
71 > MinConnectTimeout: minConnectTimeout,
72 > }
73 > cp.Backoff.MaxDelay = MaxBackoffDelay
74 >
75 > dtrace := newDialTracer(hostName, metricsHandler, logger)
76 >
77 > contextDialer := func(ctx context.Context, s string) (net.Conn, error) {
78 > // Keep the existing gRPC behavior by using OS defaults for TCP keepalive settings. grpc.go
79 > // We are on Go 1.23+ and can use KeepAliveConfig directly instead of the old KeepAlive/Control hacks.
80 > dialer := &net.Dialer{
81 > KeepAliveConfig: net.KeepAliveConfig{
82 > Enable: true,
83 > },
84 > }
85 >
86 > var ndt *networkDialTrace
87 > ctx, ndt = dtrace.beginNetworkDial(ctx)
88 > conn, dialErr := dialer.DialContext(ctx, "tcp", s)
89 > dtrace.endNetworkDial(ndt, dialErr)
90 > return conn, dialErr
91 > }
92
93 > dialOptions := []grpc.DialOption{ grpc.go
94 > grpcSecureOpt,
95 > grpc.WithContextDialer(contextDialer),
96 > grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxInternodeRecvPayloadSize)),
97 > grpc.WithChainUnaryInterceptor(
98 > headersInterceptor,
99 > metrics.NewClientMetricsTrailerPropagatorInterceptor(logger),
100 > errorInterceptor,
101 > ),
102 > grpc.WithChainStreamInterceptor(
103 > interceptor.StreamErrorInterceptor,
104 > ),
105 > grpc.WithDefaultServiceConfig(DefaultServiceConfig),
106 > grpc.WithDisableServiceConfig(),
107 > grpc.WithConnectParams(cp),
108 > }
109 > dialOptions = append(dialOptions, opts...)
110 >
111 > return grpc.NewClient(hostName, dialOptions...)
112 }
113
119 invoker grpc.UnaryInvoker,
120 opts ...grpc.CallOption,
121 > ) error { grpc.go
122 > err := invoker(ctx, method, req, reply, cc, opts...)
123 > err = serviceerrors.FromStatus(status.Convert(err))
124 > return err
125 > }
126
127 func headersInterceptor(
132 invoker grpc.UnaryInvoker,
133 opts ...grpc.CallOption,
134 > ) error { grpc.go
135 > ctx = headers.Propagate(ctx)
136 > return invoker(ctx, method, req, reply, cc, opts...)
137 > }
go.temporal.io/server/service/matching/physical_task_queue_key.go 56 covered LOC · 24 ranges

Open complete file

47 )
48
49 > func (q *PhysicalTaskQueueKey) NamespaceId() string { physical_task_queue_key.go
50 > return q.partition.NamespaceId()
51 > }
52
53 > func (q *PhysicalTaskQueueKey) TaskQueueFamily() *tqid.TaskQueueFamily { physical_task_queue_key.go
54 > return q.partition.TaskQueue().Family()
55 > }
56
57 > func (q *PhysicalTaskQueueKey) TaskType() enumspb.TaskQueueType { physical_task_queue_key.go
58 > return q.partition.TaskType()
59 > }
60
61 > func (q *PhysicalTaskQueueKey) Partition() tqid.Partition { physical_task_queue_key.go
62 > return q.partition
63 > }
64
65 // UnversionedQueueKey returns the unversioned PhysicalTaskQueueKey of a task queue partition
66 > func UnversionedQueueKey(p tqid.Partition) *PhysicalTaskQueueKey { physical_task_queue_key.go
67 > return &PhysicalTaskQueueKey{
68 > partition: p,
69 > }
70 > }
71
72 // VersionSetQueueKey returns a PhysicalTaskQueueKey of a task queue partition with the given version set id.
114 // with build ID: /_sys/<base name>/<build ID base64 URL encoded>#<partition id>
115 // with version set: /_sys/<base name>/<version set id>:<partition id>
116 > func (q *PhysicalTaskQueueKey) PersistenceName() string { physical_task_queue_key.go
117 > switch p := q.Partition().(type) {
118 > case *tqid.StickyPartition: physical_task_queue_key.go
119 > return p.StickyName()
120 case *tqid.WorkerCommandsPartition:
121 return p.TaskQueue().Name()
122 > case *tqid.NormalPartition: physical_task_queue_key.go
123 > baseName := q.TaskQueueFamily().Name()
124 >
125 > if len(q.version.versionSet) > 0 {
126 return nonRootPartitionPrefix + baseName + partitionDelimiter + q.version.versionSet + versionSetDelimiter + strconv.Itoa(p.PartitionId())
127 }
128
129 > if len(q.version.deploymentSeriesName) > 0 { physical_task_queue_key.go
130 encodedBuildId := base64.RawURLEncoding.EncodeToString([]byte(q.version.buildId))
131 encodedDeploymentName := base64.RawURLEncoding.EncodeToString([]byte(q.version.deploymentSeriesName))
132 return nonRootPartitionPrefix + baseName + partitionDelimiter + encodedDeploymentName + deploymentNameDelimiter + encodedBuildId + buildIdDelimiter + strconv.Itoa(p.PartitionId())
133 > } else if len(q.version.buildId) > 0 { physical_task_queue_key.go
134 encodedBuildId := base64.URLEncoding.EncodeToString([]byte(q.version.buildId))
135 return nonRootPartitionPrefix + baseName + partitionDelimiter + encodedBuildId + buildIdDelimiter + strconv.Itoa(p.PartitionId())
146 }
147
148 > func (q *PhysicalTaskQueueKey) IsVersioned() bool { physical_task_queue_key.go
149 > return q.version.IsVersioned()
150 > }
151
152 // Version returns a pointer to the physical queue version key. Caller must not manipulate the
153 // returned value.
154 > func (q *PhysicalTaskQueueKey) Version() PhysicalTaskQueueVersion { physical_task_queue_key.go
155 > return q.version
156 > }
157
158 > func (v PhysicalTaskQueueVersion) IsVersioned() bool { physical_task_queue_key.go
159 > return v.versionSet != "" || v.buildId != ""
160 > }
161
162 > func (v PhysicalTaskQueueVersion) Deployment() *deploymentpb.Deployment { physical_task_queue_key.go
163 > if len(v.deploymentSeriesName) > 0 {
164 return &deploymentpb.Deployment{
165 SeriesName: v.deploymentSeriesName,
167 }
168 }
169 > return nil physical_task_queue_key.go
170 }
171
172 // WorkerDeploymentVersionS returns the internal server api WorkerDeploymentVersion
173 // (different from the public api WorkerDeploymentVersion).
174 > func (v PhysicalTaskQueueVersion) WorkerDeploymentVersionS() *deploymentspb.WorkerDeploymentVersion { physical_task_queue_key.go
175 > if len(v.deploymentSeriesName) > 0 {
176 return &deploymentspb.WorkerDeploymentVersion{
177 BuildId: v.buildId,
179 }
180 }
181 > return nil physical_task_queue_key.go
182 }
183
184 // BuildId returns empty if this is not a Versioning v2 queue.
185 > func (v PhysicalTaskQueueVersion) BuildId() string { physical_task_queue_key.go
186 > if len(v.deploymentSeriesName) > 0 {
187 return ""
188 }
189 > return v.buildId physical_task_queue_key.go
190 }
191
192 > func (v PhysicalTaskQueueVersion) VersionSet() string { physical_task_queue_key.go
193 > return v.versionSet
194 > }
195
196 // MetricsTagValue returns the build ID tag value for this version.
197 > func (v PhysicalTaskQueueVersion) MetricsTagValue() string { physical_task_queue_key.go
198 > if v.versionSet != "" {
199 return v.versionSet
200 > } else if v.deploymentSeriesName == "" { physical_task_queue_key.go
201 > return v.buildId
202 > }
203 return v.deploymentSeriesName + worker_versioning.WorkerDeploymentVersionDelimiter + v.buildId
204 }
go.temporal.io/server/common/rpc/interceptor/concurrent_request_limit.go 55 covered LOC · 11 ranges

Open complete file

50 globalQuota func(ns string) int,
51 tokens map[string]int,
52 > ) *ConcurrentRequestLimitInterceptor { concurrent_request_limit.go
53 > return &ConcurrentRequestLimitInterceptor{
54 > namespaceRegistry: namespaceRegistry,
55 > logger: logger,
56 > quotaCalculator: calculator.NewLoggedNamespaceCalculator(
57 > calculator.ClusterAwareNamespaceQuotaCalculator{
58 > MemberCounter: memberCounter,
59 > PerInstanceQuota: perInstanceQuota,
60 > GlobalQuota: globalQuota,
61 > },
62 > log.With(logger, tag.ComponentLongPollHandler, tag.ScopeNamespace),
63 > ),
64 > tokens: tokens,
65 > activeTokensCount: make(map[string]*int32),
66 > }
67 > }
68
69 func (ni *ConcurrentRequestLimitInterceptor) Intercept(
72 info *grpc.UnaryServerInfo,
73 handler grpc.UnaryHandler,
74 > ) (any, error) { concurrent_request_limit.go
75 > nsName := MustGetNamespaceName(ni.namespaceRegistry, req)
76 > mh := GetMetricsHandlerFromContext(ctx, ni.logger)
77 > cleanup, err := ni.Allow(nsName, info.FullMethod, mh, req)
78 > defer cleanup()
79 > if err != nil {
80 return nil, err
81 }
82
83 > return handler(ctx, req) concurrent_request_limit.go
84 }
85
89 mh metrics.Handler,
90 req any,
91 > ) (func(), error) { concurrent_request_limit.go
92 > // token will default to 0
93 > token := ni.tokens[methodName]
94 >
95 > if token == 0 {
96 > return func() {}, nil concurrent_request_limit.go
97 }
98 // for GetWorkflowExecutionHistoryRequest, we only care about long poll requests
99 > longPollReq, ok := req.(*workflowservice.GetWorkflowExecutionHistoryRequest) concurrent_request_limit.go
100 > if ok && !longPollReq.WaitNewEvent {
101 // ignore non-long-poll GetHistory calls.
102 return func() {}, nil
103 }
104
105 > counter := ni.counter(namespaceName, methodName) concurrent_request_limit.go
106 > count := atomic.AddInt32(counter, int32(token))
107 > cleanup := func() { atomic.AddInt32(counter, -int32(token)) }
108
109 > mh.Gauge(metrics.ServicePendingRequests.Name()).Record(float64(count)) concurrent_request_limit.go
110 >
111 > // frontend.namespaceCount is applied per poller type temporarily to prevent
112 > // one poller type to take all token waiting in the long poll.
113 > if float64(count) > ni.quotaCalculator.GetQuota(namespaceName.String()) {
114 return cleanup, ErrNamespaceCountLimitServerBusy
115 }
116 > return cleanup, nil concurrent_request_limit.go
117 }
118
120 namespace namespace.Name,
121 methodName string,
122 > ) *int32 { concurrent_request_limit.go
123 > key := ni.getTokenKey(namespace, methodName)
124 >
125 > ni.Lock()
126 > defer ni.Unlock()
127 >
128 > counter, ok := ni.activeTokensCount[key]
129 > if !ok {
130 > counter = new(int32)
131 > ni.activeTokensCount[key] = counter
132 > }
133 > return counter
134 }
135
137 namespace namespace.Name,
138 methodName string,
139 > ) string { concurrent_request_limit.go
140 > return namespace.String() + "/" + methodName
141 > }
go.temporal.io/server/service/frontend/configs/quotas.go 55 covered LOC · 16 ranges

Open complete file

274 namespaceReplicationInducingRateBurstFn quotas.RateBurst,
275 operatorRPSRatio dynamicconfig.FloatPropertyFn,
276 > ) quotas.RequestRateLimiter { quotas.go
277 > mapping := make(map[string]quotas.RequestRateLimiter)
278 >
279 > executionRateLimiter := NewExecutionPriorityRateLimiter(executionRateBurstFn, operatorRPSRatio)
280 > visibilityRateLimiter := NewVisibilityPriorityRateLimiter(visibilityRateBurstFn, operatorRPSRatio)
281 > namespaceReplicationInducingRateLimiter := NewNamespaceReplicationInducingAPIPriorityRateLimiter(namespaceReplicationInducingRateBurstFn, operatorRPSRatio)
282 >
283 > for api := range APIToPriority {
284 > mapping[api] = executionRateLimiter
285 > }
286 > for api := range VisibilityAPIToPriority {
287 > mapping[api] = visibilityRateLimiter
288 > }
289 > for api := range NamespaceReplicationInducingAPIToPriority {
290 > mapping[api] = namespaceReplicationInducingRateLimiter
291 > }
292
293 > return quotas.NewRoutingRateLimiter(mapping) quotas.go
294 }
295
297 rateBurstFn quotas.RateBurst,
298 operatorRPSRatio dynamicconfig.FloatPropertyFn,
299 > ) quotas.RequestRateLimiter { quotas.go
300 > return quotas.NewPriorityRateLimiterHelper(
301 > rateBurstFn,
302 > operatorRPSRatio,
303 > func(req quotas.Request) int {
304 > if req.CallerType == headers.CallerTypeOperator { quotas.go
305 return quotas.OperatorPriority
306 }
307 > if priority, ok := APIToPriority[req.API]; ok { quotas.go
308 > return priority quotas.go
309 > }
310 return ExecutionAPIPrioritiesOrdered[len(ExecutionAPIPrioritiesOrdered)-1]
311 },
317 rateBurstFn quotas.RateBurst,
318 operatorRPSRatio dynamicconfig.FloatPropertyFn,
319 > ) quotas.RequestRateLimiter { quotas.go
320 > return quotas.NewPriorityRateLimiterHelper(
321 > rateBurstFn,
322 > operatorRPSRatio,
323 > func(req quotas.Request) int {
324 if req.CallerType == headers.CallerTypeOperator {
325 return quotas.OperatorPriority
337 rateBurstFn quotas.RateBurst,
338 operatorRPSRatio dynamicconfig.FloatPropertyFn,
339 > ) quotas.RequestRateLimiter { quotas.go
340 > return quotas.NewPriorityRateLimiterHelper(
341 > rateBurstFn,
342 > operatorRPSRatio,
343 > func(req quotas.Request) int {
344 > if req.CallerType == headers.CallerTypeOperator { quotas.go
345 return quotas.OperatorPriority
346 }
347 > if priority, ok := NamespaceReplicationInducingAPIToPriority[req.API]; ok { quotas.go
348 > return priority quotas.go
349 > }
350 return NamespaceReplicationInducingAPIPrioritiesOrdered[len(NamespaceReplicationInducingAPIPrioritiesOrdered)-1]
351 },
361 globalQuotaBurstRatio dynamicconfig.FloatPropertyFnWithNamespaceFilter,
362 logger log.Logger,
363 > ) quotas.RequestRateLimiter { quotas.go
364 > rateFn := calculator.NewLoggedNamespaceCalculator(
365 > calculator.ClusterAwareNamespaceQuotaCalculator{
366 > MemberCounter: memberCounter,
367 > PerInstanceQuota: func(ns string) int { return 0 },
368 GlobalQuota: globalQuota,
369 },
371 ).GetQuota
372
373 > return quotas.NewNamespaceRequestRateLimiter( quotas.go
374 > func(req quotas.Request) quotas.RequestRateLimiter {
375 return quotas.NewRequestRateLimiterAdapter(
376 quotas.NewDynamicRateLimiter(
386 }
387
388 > func IsAPIOperation(apiFullName string) bool { quotas.go
389 > if _, ok := operationExcludedAPIs[apiFullName]; ok {
390 > return false quotas.go
391 > }
392
393 > _, inAPI := APIToPriority[apiFullName] quotas.go
394 > _, inNamespaceReplicationInducingAPI := NamespaceReplicationInducingAPIToPriority[apiFullName]
395 >
396 > return inAPI || inNamespaceReplicationInducingAPI
397 }
go.temporal.io/server/service/history/hsm/tree.go 55 covered LOC · 16 ranges

Open complete file

204 children map[string]*persistencespb.StateMachineMap,
205 backend NodeBackend,
206 > ) (*Node, error) { tree.go
207 > def, ok := registry.Machine(t)
208 > if !ok {
209 return nil, fmt.Errorf("%w: state machine for type: %v", ErrNotRegistered, t)
210 }
211 > serialized, err := def.Serialize(data) tree.go
212 > if err != nil {
213 return nil, err
214 }
215 > return &Node{ tree.go
216 > definition: def,
217 > registry: registry,
218 > persistence: &persistencespb.StateMachineNode{
219 > Children: children,
220 > Data: serialized,
221 > InitialVersionedTransition: &persistencespb.VersionedTransition{},
222 > LastUpdateVersionedTransition: &persistencespb.VersionedTransition{},
223 > TransitionCount: 0,
224 > },
225 > cache: &cachedMachine{
226 > dataLoaded: true,
227 > data: data,
228 > children: make(map[Key]*Node),
229 > },
230 > backend: backend,
231 > opLog: make(OperationLog, 0),
232 > }, nil
233 }
234
235 // Dirty returns true if any of the tree's state machines have transitioned.
236 > func (n *Node) Dirty() bool { tree.go
237 > if n.cache.dirty {
238 return true
239 }
240 > for _, child := range n.cache.children { tree.go
241 if child.Dirty() {
242 return true
243 }
244 }
245 > return false tree.go
246 }
247
262 // deleted. For details on compaction rules, see OperationLog.compact().
263 // This method must be called on the root node only.
264 > func (n *Node) OpLog() (OperationLog, error) { tree.go
265 > if n.Parent != nil {
266 return nil, fmt.Errorf("can only be called from root node")
267 }
268
269 > compacted := n.opLog.compact() tree.go
270 > return compacted, nil
271 }
272
274 // This should be called at the end of every transaction where the transitions are performed to avoid emitting duplicate
275 // transition outputs.
276 > func (n *Node) ClearTransactionState() { tree.go
277 > n.root().opLog = nil
278 >
279 > n.cache.dirty = false
280 > for _, child := range n.cache.children {
281 child.ClearTransactionState()
282 }
643
644 // NewCollection creates a new [Collection].
645 > func NewCollection[T any](node *Node, stateMachineType string) Collection[T] { tree.go
646 > return Collection[T]{
647 > Type: stateMachineType,
648 > node: node,
649 > }
650 > }
651
652 // Node gets an [Node] for a given state machine ID.
656
657 // List returns all nodes in this collection.
658 > func (c Collection[T]) List() []*Node { tree.go
659 > machines, ok := c.node.persistence.Children[c.Type]
660 > if !ok {
661 > return nil tree.go
662 > }
663 nodes := make([]*Node, 0, len(machines.MachinesById))
664 for id := range machines.MachinesById {
705 }
706
707 > func (n *Node) root() *Node { tree.go
708 > root := n
709 > for root.Parent != nil {
710 root = root.Parent
711 }
712 > return root tree.go
713 }
714
727 // - If the target of the operation is deleted, only its DeleteOperation is kept
728 // - Otherwise, the operation is included
729 > func (ol OperationLog) compact() OperationLog { tree.go
730 > if len(ol) == 0 {
731 > return ol tree.go
732 > }
733
734 root := newOpNode(Key{})
go.temporal.io/server/service/worker/worker.go 55 covered LOC · 9 ranges

Open complete file

35 sdkClientFactory sdk.ClientFactory,
36 hostInfo membership.HostInfo,
37 > ) *workerManager { worker.go
38 > return &workerManager{
39 > hostInfo: hostInfo,
40 > logger: logger,
41 > sdkClientFactory: sdkClientFactory,
42 > workerComponents: workerComponents,
43 > }
44 > }
45
46 > func (wm *workerManager) Start() { worker.go
47 > if !atomic.CompareAndSwapInt32(
48 > &wm.status,
49 > common.DaemonStatusInitialized,
50 > common.DaemonStatusStarted,
51 > ) {
52 return
53 }
54
55 > defaultWorkerOptions := sdkworker.Options{ worker.go
56 > Identity: "temporal-system@" + wm.hostInfo.Identity(),
57 > // TODO: add dynamic config for worker options
58 > BackgroundActivityContext: headers.SetCallerType(context.Background(), headers.CallerTypeBackgroundHigh),
59 > }
60 > sdkClient := wm.sdkClientFactory.GetSystemClient()
61 > defaultWorker := wm.sdkClientFactory.NewWorker(sdkClient, primitives.DefaultWorkerTaskQueue, defaultWorkerOptions)
62 > wm.workers = []sdkworker.Worker{defaultWorker}
63 >
64 > for _, wc := range wm.workerComponents {
65 > wfWorkerOptions := wc.DedicatedWorkflowWorkerOptions()
66 > if wfWorkerOptions == nil {
67 > // use default worker
68 > wc.RegisterWorkflow(defaultWorker)
69 > } else {
70 wfWorkerOptions.Options.Identity = "temporal-system@" + wm.hostInfo.Identity()
71 // this worker component requires a dedicated worker
75 }
76
77 > activityWorkerOptions := wc.DedicatedActivityWorkerOptions() worker.go
78 > if activityWorkerOptions == nil {
79 // use default worker
80 wc.RegisterActivities(defaultWorker)
81 > } else { worker.go
82 > // TODO: This is to prevent issues during upgrade/downgrade. Remove in 1.24 release.
83 > wc.RegisterActivities(defaultWorker)
84 >
85 > // this worker component requires a dedicated worker for activities
86 > activityWorkerOptions.Options.DisableWorkflowWorker = true
87 > activityWorkerOptions.Options.Identity = "temporal-system@" + wm.hostInfo.Identity()
88 > activityWorker := wm.sdkClientFactory.NewWorker(sdkClient, activityWorkerOptions.TaskQueue, activityWorkerOptions.Options)
89 > wc.RegisterActivities(activityWorker)
90 > wm.workers = append(wm.workers, activityWorker)
91 > }
92 }
93
94 > for _, w := range wm.workers { worker.go
95 > if err := w.Start(); err != nil {
96 wm.logger.Fatal("Unable to start worker", tag.Error(err))
97 }
98 }
99
100 > wm.logger.Info("", tag.ComponentWorkerManager, tag.LifeCycleStarted) worker.go
101 }
102
103 > func (wm *workerManager) Stop() { worker.go
104 > if !atomic.CompareAndSwapInt32(
105 > &wm.status,
106 > common.DaemonStatusStarted,
107 > common.DaemonStatusStopped,
108 > ) {
109 return
110 }
111
112 > for _, w := range wm.workers { worker.go
113 > w.Stop()
114 > }
115 > wm.logger.Info("", tag.ComponentWorkerManager, tag.LifeCycleStopped)
116 }
go.temporal.io/server/client/matching/retryable_client_gen.go 54 covered LOC · 6 ranges

Open complete file

61 request *matchingservice.CancelOutstandingPollRequest,
62 opts ...grpc.CallOption,
63 > ) (*matchingservice.CancelOutstandingPollResponse, error) { retryable_client_gen.go
64 > var resp *matchingservice.CancelOutstandingPollResponse
65 > op := func(ctx context.Context) error {
66 > var err error
67 > resp, err = c.client.CancelOutstandingPoll(ctx, request, opts...)
68 > return err
69 > }
70 > err := backoff.ThrottleRetryContext(ctx, op, c.policy, c.isRetryable)
71 > return resp, err
72 }
73
286 request *matchingservice.ForceUnloadTaskQueuePartitionRequest,
287 opts ...grpc.CallOption,
288 > ) (*matchingservice.ForceUnloadTaskQueuePartitionResponse, error) { retryable_client_gen.go
289 > var resp *matchingservice.ForceUnloadTaskQueuePartitionResponse
290 > op := func(ctx context.Context) error {
291 > var err error
292 > resp, err = c.client.ForceUnloadTaskQueuePartition(ctx, request, opts...)
293 > return err
294 > }
295 > err := backoff.ThrottleRetryContext(ctx, op, c.policy, c.isRetryable)
296 > return resp, err
297 }
298
361 request *matchingservice.ListNexusEndpointsRequest,
362 opts ...grpc.CallOption,
363 > ) (*matchingservice.ListNexusEndpointsResponse, error) { retryable_client_gen.go
364 > var resp *matchingservice.ListNexusEndpointsResponse
365 > op := func(ctx context.Context) error {
366 > var err error
367 > resp, err = c.client.ListNexusEndpoints(ctx, request, opts...)
368 > return err
369 > }
370 > err := backoff.ThrottleRetryContext(ctx, op, c.policy, c.isRetryable)
371 > return resp, err
372 }
373
406 request *matchingservice.PollActivityTaskQueueRequest,
407 opts ...grpc.CallOption,
408 > ) (*matchingservice.PollActivityTaskQueueResponse, error) { retryable_client_gen.go
409 > var resp *matchingservice.PollActivityTaskQueueResponse
410 > op := func(ctx context.Context) error {
411 > var err error
412 > resp, err = c.client.PollActivityTaskQueue(ctx, request, opts...)
413 > return err
414 > }
415 > err := backoff.ThrottleRetryContext(ctx, op, c.pollPolicy, c.isRetryable)
416 > return resp, err
417 }
418
436 request *matchingservice.PollWorkflowTaskQueueRequest,
437 opts ...grpc.CallOption,
438 > ) (*matchingservice.PollWorkflowTaskQueueResponse, error) { retryable_client_gen.go
439 > var resp *matchingservice.PollWorkflowTaskQueueResponse
440 > op := func(ctx context.Context) error {
441 > var err error
442 > resp, err = c.client.PollWorkflowTaskQueue(ctx, request, opts...)
443 > return err
444 > }
445 > err := backoff.ThrottleRetryContext(ctx, op, c.pollPolicy, c.isRetryable)
446 > return resp, err
447 }
448
466 request *matchingservice.RecordWorkerHeartbeatRequest,
467 opts ...grpc.CallOption,
468 > ) (*matchingservice.RecordWorkerHeartbeatResponse, error) { retryable_client_gen.go
469 > var resp *matchingservice.RecordWorkerHeartbeatResponse
470 > op := func(ctx context.Context) error {
471 > var err error
472 > resp, err = c.client.RecordWorkerHeartbeat(ctx, request, opts...)
473 > return err
474 > }
475 > err := backoff.ThrottleRetryContext(ctx, op, c.policy, c.isRetryable)
476 > return resp, err
477 }
478
go.temporal.io/server/common/dynamicconfig/gradual_change.go 54 covered LOC · 13 ranges

Open complete file

25 // StaticGradualChange returns a GradualChange whose Value always returns def and whose When
26 // always returns a time in the past.
27 > func StaticGradualChange[T any](def T) GradualChange[T] { gradual_change.go
28 > return GradualChange[T]{New: def}
29 > }
30
31 // Value returns the value for the given key at the given time.
32 > func (c *GradualChange[T]) Value(key []byte, now time.Time) T { gradual_change.go
33 > if !now.Before(c.End) {
34 > return c.New gradual_change.go
35 > } else if !now.After(c.Start) { gradual_change.go
36 return c.Old
37 }
46 // When returns the time when the value for key will switch from old to new. It may be the zero
47 // time for a static GradualChange.
48 > func (c *GradualChange[T]) When(key []byte) time.Time { gradual_change.go
49 > fraction := float64(farm.Fingerprint32(key)) / float64(math.MaxUint32)
50 > when := time.Duration(fraction * float64(c.End.Sub(c.Start)))
51 > return c.Start.Add(when)
52 > }
53
54 // ConvertGradualChange is a conversion function that can handle a plain T (which represents a
56 // of type GradualChange into a GradualChange.
57 // nolint:revive // cognitive-complexity // this looks complicated but each case is fairly simple
58 > func ConvertGradualChange[T any](def T) func(v any) (GradualChange[T], error) { gradual_change.go
59 > changeConverter := ConvertStructure(StaticGradualChange(def))
60 >
61 > // Call this once so that if it's going to panic, it panics at static init time.
62 > _, _ = changeConverter(nil)
63 >
64 > switch reflect.TypeFor[T]() {
65 > case reflect.TypeFor[bool]():
66 > return func(v any) (GradualChange[T], error) {
67 if b, err := convertBool(v); err == nil {
68 var change GradualChange[T]
72 return changeConverter(v)
73 }
74 > case reflect.TypeFor[int](): gradual_change.go
75 > return func(v any) (GradualChange[T], error) {
76 if i, err := convertInt(v); err == nil {
77 var change GradualChange[T]
121 callback func(T),
122 timeSource clock.TimeSource,
123 > ) (T, func()) { gradual_change.go
124 > w := &gradualChangeSubscribeWrapper[T]{changeKey: changeKey, callback: callback, clock: timeSource}
125 >
126 > w.lock.Lock()
127 > w.change, w.cancelSub = subscribable(w.changeCallback)
128 > val, _ := w.reevalLocked()
129 > w.lock.Unlock()
130 >
131 > return val, w.cancel
132 > }
133
134 type gradualChangeSubscribeWrapper[T any] struct {
166 }
167
168 > func (w *gradualChangeSubscribeWrapper[T]) cancel() { gradual_change.go
169 > w.lock.Lock()
170 > defer w.lock.Unlock()
171 >
172 > w.cancelSub()
173 > w.setTimerLocked(nil)
174 > }
175
176 > func (w *gradualChangeSubscribeWrapper[T]) reevalLocked() (T, bool) { gradual_change.go
177 > now := w.clock.Now()
178 >
179 > var newTmr clock.Timer
180 > if at := w.change.When(w.changeKey); at.After(now) {
181 newTmr = w.clock.AfterFunc(at.Sub(now), w.timerCallback)
182 }
183 > w.setTimerLocked(newTmr) gradual_change.go
184 >
185 > newVal := w.change.Value(w.changeKey, now)
186 > changed := !reflect.DeepEqual(w.val, newVal)
187 > w.val = newVal
188 > return w.val, changed
189 }
190
191 > func (w *gradualChangeSubscribeWrapper[T]) setTimerLocked(newTmr clock.Timer) { gradual_change.go
192 > if w.tmr != nil {
193 w.tmr.Stop()
194 }
195 > w.tmr = newTmr gradual_change.go
196 }
go.temporal.io/server/common/future/future_impl.go 54 covered LOC · 15 ranges

Open complete file

29 )
30
31 > func NewFuture[T any]() *FutureImpl[T] { future_impl.go
32 > var value T
33 > return &FutureImpl[T]{
34 > status: pending,
35 > readyCh: make(chan struct{}),
36 >
37 > value: value,
38 > err: nil,
39 > }
40 > }
41
42 func (f *FutureImpl[T]) Get(
43 ctx context.Context,
44 > ) (T, error) { future_impl.go
45 > if f.Ready() {
46 > return f.value, f.err future_impl.go
47 > }
48
49 > select { future_impl.go
50 > case <-f.readyCh: future_impl.go
51 > return f.value, f.err
52 > case <-ctx.Done(): future_impl.go
53 > var value T
54 > return value, ctx.Err()
55 }
56 }
57
58 > func (f *FutureImpl[T]) GetIfReady() (T, error) { future_impl.go
59 > if f.Ready() {
60 > return f.value, f.err future_impl.go
61 > }
62 > var value T future_impl.go
63 > return value, errorFutureNotReady
64 }
65
67 value T,
68 err error,
69 > ) { future_impl.go
70 > // cannot directly set status to `ready`, to prevent data race in case multiple `Get` occurs
71 > // instead set status to `setting` to prevent concurrent completion of this future
72 > if !atomic.CompareAndSwapInt32(
73 > &f.status,
74 > pending,
75 > setting,
76 > ) {
77 panic("future has already been completed")
78 }
79
80 > f.value = value future_impl.go
81 > f.err = err
82 > atomic.CompareAndSwapInt32(&f.status, setting, ready)
83 > close(f.readyCh)
84 }
85
88 value T,
89 err error,
90 > ) bool { future_impl.go
91 > if !atomic.CompareAndSwapInt32(
92 > &f.status,
93 > pending,
94 > setting,
95 > ) {
96 > return false future_impl.go
97 > }
98
99 > f.value = value future_impl.go
100 > f.err = err
101 > atomic.CompareAndSwapInt32(&f.status, setting, ready)
102 > close(f.readyCh)
103 > return true
104 }
105
106 > func (f *FutureImpl[T]) Ready() bool { future_impl.go
107 > return atomic.LoadInt32(&f.status) == ready
108 > }
go.temporal.io/server/service/worker/workerdeployment/fx.go 54 covered LOC · 9 ranges

Open complete file

79 testHooks testhooks.TestHooks,
80 metricsHandler metrics.Handler,
81 > ) Client { fx.go
82 > highestRevSignaledToVersionWf := cache.New(dynamicconfig.ReactivationSignalDedupCacheMaxSize.Get(dc)(), nil)
83 > lc.Append(fx.Hook{
84 > OnStop: func(context.Context) error {
85 > highestRevSignaledToVersionWf.Stop() fx.go
86 > return nil
87 > },
88 })
89 > return &ClientImpl{ fx.go
90 > logger: logger,
91 > historyClient: historyClient,
92 > visibilityManager: visibilityManager,
93 > matchingClient: matchingClient,
94 > workerControllerInstanceClient: workerControllerInstanceClient,
95 > maxIDLengthLimit: dynamicconfig.MaxIDLengthLimit.Get(dc),
96 > visibilityMaxPageSize: dynamicconfig.FrontendVisibilityMaxPageSize.Get(dc),
97 > maxTaskQueuesInDeploymentVersion: dynamicconfig.MatchingMaxTaskQueuesInDeploymentVersion.Get(dc),
98 > maxDeployments: dynamicconfig.MatchingMaxDeployments.Get(dc),
99 > testHooks: testHooks,
100 > metricsHandler: metricsHandler,
101 > highestRevSignaledToVersionWf: highestRevSignaledToVersionWf,
102 > }
103 }
104
106 dc *dynamicconfig.Collection,
107 params activityDeps,
108 > ) fxResult { fx.go
109 > return fxResult{
110 > Component: &workerComponent{
111 > activityDeps: params,
112 > dynamicConfig: dc,
113 > },
114 > }
115 > }
116
117 > func (s *workerComponent) DedicatedWorkerOptions(ns *namespace.Namespace) *workercommon.PerNSDedicatedWorkerOptions { fx.go
118 > return &workercommon.PerNSDedicatedWorkerOptions{
119 > Enabled: true,
120 > }
121 > }
122
123 > func (s *workerComponent) Register(registry sdkworker.Registry, ns *namespace.Namespace, details workercommon.RegistrationDetails) func() { fx.go
124 > workflowVersionGetter := func() DeploymentWorkflowVersion {
125 val := DeploymentWorkflowVersion(dynamicconfig.MatchingDeploymentWorkflowVersion.Get(s.dynamicConfig)(ns.Name().String()))
126 return val
127 }
128
129 > versionWorkflow := func(ctx workflow.Context, args *deploymentspb.WorkerDeploymentVersionWorkflowArgs) error { fx.go
130 refreshIntervalGetter := func() time.Duration {
131 return dynamicconfig.VersionDrainageStatusRefreshInterval.Get(s.dynamicConfig)(ns.Name().String())
136 return VersionWorkflow(ctx, workflowVersionGetter, refreshIntervalGetter, visibilityGracePeriodGetter, args)
137 }
138 > registry.RegisterWorkflowWithOptions(versionWorkflow, workflow.RegisterOptions{Name: WorkerDeploymentVersionWorkflowType}) fx.go
139 >
140 > deploymentWorkflow := func(ctx workflow.Context, args *deploymentspb.WorkerDeploymentWorkflowArgs) error {
141 maxVersionsGetter := func() int {
142 return dynamicconfig.MatchingMaxVersionsInDeployment.Get(s.dynamicConfig)(ns.Name().String())
144 return Workflow(ctx, workflowVersionGetter, maxVersionsGetter, args)
145 }
146 > registry.RegisterWorkflowWithOptions(deploymentWorkflow, workflow.RegisterOptions{Name: WorkerDeploymentWorkflowType}) fx.go
147 >
148 > versionActivities := &VersionActivities{
149 > activityDeps: s.activityDeps,
150 > namespace: ns,
151 > }
152 > registry.RegisterActivity(versionActivities)
153 >
154 > activities := &Activities{
155 > activityDeps: s.activityDeps,
156 > namespace: ns,
157 > }
158 > registry.RegisterActivity(activities)
159 > return nil
160 }
go.temporal.io/server/common/backoff/retry.go 53 covered LOC · 23 ranges

Open complete file

39 // ThrottleRetry is a resource aware version of Retry.
40 // Resource exhausted error will be retried using a different throttle retry policy, instead of the specified one.
41 > func ThrottleRetry(operation Operation, policy RetryPolicy, isRetryable IsRetryable) error { retry.go
42 > ctxOp := func(context.Context) error { return operation() }
43 > return ThrottleRetryContext(context.Background(), ctxOp, policy, isRetryable)
44 }
45
53 policy RetryPolicy,
54 isRetryable IsRetryable,
55 > ) error { retry.go
56 > var err error
57 > var next time.Duration
58 >
59 > if isRetryable == nil {
60 > isRetryable = func(error) bool { return true } retry.go
61 }
62
63 > deadline, hasDeadline := ctx.Deadline() retry.go
64 >
65 > timeSrc := clock.NewRealTimeSource()
66 > r := NewRetrier(policy, timeSrc)
67 > t := NewRetrier(throttleRetryPolicy, timeSrc)
68 > for ctx.Err() == nil {
69 > if err = operation(ctx); err == nil { retry.go
70 > return nil retry.go
71 > }
72
73 > if next = r.NextBackOff(err); next == done { retry.go
74 > return err retry.go
75 > }
76
77 > if err == ctx.Err() || !isRetryable(err) { retry.go
78 > return err retry.go
79 > }
80
81 > if _, ok := err.(*serviceerror.ResourceExhausted); ok { retry.go
82 next = max(next, t.NextBackOff(err))
83 }
84
85 > if hasDeadline && timeSrc.Now().Add(next).After(deadline) { retry.go
86 break
87 }
88
89 > timer := time.NewTimer(next) retry.go
90 > select {
91 > case <-timer.C: retry.go
92 > case <-ctx.Done(): retry.go
93 > timer.Stop()
94 }
95 }
96 // always return the last error we got from operation, even if it is not useful
97 // this retry utility does not have enough information to do any filtering/mapping
98 > if err != nil { retry.go
99 > return err retry.go
100 > }
101 return ctx.Err()
102 }
111 policy RetryPolicy,
112 isRetryable IsRetryable,
113 > ) (T, error) { retry.go
114 > var zero T
115 > var result T
116 > var err error
117 > var next time.Duration
118 >
119 > if isRetryable == nil {
120 isRetryable = func(error) bool { return true }
121 }
122
123 > deadline, hasDeadline := ctx.Deadline() retry.go
124 >
125 > timeSrc := clock.NewRealTimeSource()
126 > r := NewRetrier(policy, timeSrc)
127 > t := NewRetrier(throttleRetryPolicy, timeSrc)
128 > for ctx.Err() == nil {
129 > result, err = fn(ctx) retry.go
130 > if err == nil {
131 return result, nil
132 }
133
134 > if next = r.NextBackOff(err); next == done { retry.go
135 return zero, err
136 }
137
138 > if err == ctx.Err() || !isRetryable(err) { retry.go
139 > return zero, err retry.go
140 > }
141
142 if _, ok := err.(*serviceerror.ResourceExhausted); ok {
go.temporal.io/server/common/collection/concurrent_tx_map.go 53 covered LOC · 11 ranges

Open complete file

55 //
56 // The hash function to use for sharding
57 > func NewShardedConcurrentTxMap(initialCap int, hashfn HashFunc) ConcurrentTxMap { concurrent_tx_map.go
58 > cmap := new(ShardedConcurrentTxMap)
59 > cmap.hashfn = hashfn
60 > cmap.initialCap = max(nShards, initialCap/nShards)
61 > return cmap
62 > }
63
64 // Get returns the value corresponding to the key, if it exist
125 // GetAndDo returns the value corresponding to the key, and apply fn to key value before return value
126 // return (value, value exist or not, error when evaluation fn)
127 > func (cmap *ShardedConcurrentTxMap) GetAndDo(key any, fn ActionFunc) (any, bool, error) { concurrent_tx_map.go
128 > shard := cmap.getShard(key)
129 > var value any
130 > var ok bool
131 > var err error
132 > shard.Lock()
133 > if shard.items != nil {
134 > value, ok = shard.items[key] concurrent_tx_map.go
135 > if ok {
136 > err = fn(key, value)
137 > }
138 }
139 > shard.Unlock() concurrent_tx_map.go
140 > return value, ok, err
141 }
142
143 // PutOrDo put the key value in the map, if key does not exists, otherwise, call fn with existing key and value
144 // return (value, fn evaluated or not, error when evaluation fn)
145 > func (cmap *ShardedConcurrentTxMap) PutOrDo(key any, value any, fn ActionFunc) (any, bool, error) { concurrent_tx_map.go
146 > shard := cmap.getShard(key)
147 > var err error
148 > shard.Lock()
149 > cmap.lazyInitShard(shard)
150 > v, ok := shard.items[key]
151 > if !ok {
152 > shard.items[key] = value
153 > v = value
154 > atomic.AddInt32(&cmap.size, 1)
155 > } else {
156 err = fn(key, v)
157 }
158 > shard.Unlock() concurrent_tx_map.go
159 > return v, ok, err
160 }
161
162 // RemoveIf deletes the given key from the map if fn return true
163 > func (cmap *ShardedConcurrentTxMap) RemoveIf(key any, fn PredicateFunc) bool { concurrent_tx_map.go
164 > shard := cmap.getShard(key)
165 > var removed bool
166 > shard.Lock()
167 > if shard.items != nil {
168 > value, ok := shard.items[key] concurrent_tx_map.go
169 > if ok && fn(key, value) {
170 > removed = true
171 > delete(shard.items, key)
172 > atomic.AddInt32(&cmap.size, -1)
173 > }
174 }
175 > shard.Unlock() concurrent_tx_map.go
176 > return removed
177 }
178
222 }
223
224 > func (cmap *ShardedConcurrentTxMap) getShard(key any) *mapShard { concurrent_tx_map.go
225 > shardIdx := cmap.hashfn(key) % nShards
226 > return &cmap.shards[shardIdx]
227 > }
228
229 > func (cmap *ShardedConcurrentTxMap) lazyInitShard(shard *mapShard) { concurrent_tx_map.go
230 > if shard.items == nil {
231 > shard.items = make(map[any]any, cmap.initialCap)
232 > }
233 }
go.temporal.io/server/service/history/ndc_task_util.go 53 covered LOC · 17 ranges

Open complete file

37 taskVersion int64,
38 task any,
39 > ) error { ndc_task_util.go
40 >
41 > if !shard.GetClusterMetadata().IsGlobalNamespaceEnabled() {
42 > return nil ndc_task_util.go
43 > }
44
45 // the first return value is whether this task is valid for further processing
64 metricsHandler metrics.Handler,
65 logger log.Logger,
66 > ) (historyi.MutableState, error) { ndc_task_util.go
67 > logger = tasks.InitializeLogger(transferTask, logger)
68 > mutableState, err := loadMutableStateForTask(
69 > ctx,
70 > shardContext,
71 > wfContext,
72 > transferTask,
73 > tasks.GetTransferTaskEventID,
74 > transferTaskMutableStateStaleChecker,
75 > metricsHandler.WithTags(metrics.OperationTag(metrics.OperationTransferQueueProcessorScope)),
76 > queues.GetActiveTransferTaskTypeTagValue(transferTask, shardContext.ChasmRegistry()),
77 > logger,
78 > )
79 > if err != nil {
80 // When standby task executor executes task in active cluster (and vice versa),
81 // mutable state might be already deleted by active task executor and NotFound is a valid case which shouldn't be logged.
137 taskTypeTag string,
138 logger log.Logger,
139 > ) (historyi.MutableState, error) { ndc_task_util.go
140 >
141 > if err := validateTaskByClock(shardContext, task); err != nil {
142 return nil, err
143 }
144
145 > mutableState, err := wfContext.LoadMutableState(ctx, shardContext) ndc_task_util.go
146 > if err != nil {
147 return nil, err
148 }
149
150 > if task.GetRunID() == mutableState.GetWorkflowKey().RunID { ndc_task_util.go
151 > // Task generation is scoped to a specific run, so only perform the validation if runID matches. ndc_task_util.go
152 > // Tasks targeting the current run (e.g. workflow execution timeout timer) should bypass the validation.
153 > if err := validateTaskGeneration(ctx, shardContext, wfContext, mutableState, task.GetTaskID()); err != nil {
154 return nil, err
155 }
165 //
166 // Some tasks don't have an associated eventID (CHASM tasks).
167 > eventID, eidOk := getEventID(task) ndc_task_util.go
168 > if !eidOk || eventID < mutableState.GetNextEventID() {
169 > return mutableState, nil ndc_task_util.go
170 > }
171
172 // Depending on task type, there are exceptions when mutable state can't be stale.
210 shardContext historyi.ShardContext,
211 task tasks.Task,
212 > ) error { ndc_task_util.go
213 > shardID := shardContext.GetShardID()
214 > taskClock := vclock.NewVectorClock(
215 > shardContext.GetClusterMetadata().GetClusterID(),
216 > shardContext.GetShardID(),
217 > task.GetTaskID(),
218 > )
219 > currentClock := shardContext.CurrentVectorClock()
220 > result, err := vclock.Compare(taskClock, currentClock)
221 > if err != nil {
222 return err
223 }
224 > if result >= 0 { ndc_task_util.go
225 shardContext.UnloadForOwnershipLost()
226 return &persistence.ShardOwnershipLostError{
239 mutableState historyi.MutableState,
240 taskID int64,
241 > ) error { ndc_task_util.go
242 > tgClock := mutableState.GetExecutionInfo().TaskGenerationShardClockTimestamp
243 > if tgClock != 0 && taskID != 0 && taskID < tgClock {
244
245 currentClock := shardContext.CurrentVectorClock().Clock
253 return fmt.Errorf("%w: task was generated before mutable state rebuild", consts.ErrStaleReference)
254 }
255 > return nil ndc_task_util.go
256 }
257
322 namespaceID string,
323 businessID string,
324 > ) (metrics.Tag, enumspb.ReplicationState) { ndc_task_util.go
325 > namespaceName, err := registry.GetNamespaceByID(namespace.ID(namespaceID))
326 > if err != nil {
327 return metrics.NamespaceUnknownTag(), enumspb.REPLICATION_STATE_UNSPECIFIED
328 }
329
330 > return metrics.NamespaceTag(namespaceName.Name().String()), namespaceName.ReplicationState(businessID) ndc_task_util.go
331 }
go.temporal.io/server/service/history/transfer_queue_task_executor_base.go 53 covered LOC · 6 ranges

Open complete file

69 visibilityManager manager.VisibilityManager,
70 chasmEngine chasm.Engine,
71 > ) *transferQueueTaskExecutorBase { transfer_queue_task_executor_base.go
72 > return &transferQueueTaskExecutorBase{
73 > currentClusterName: shardContext.GetClusterMetadata().GetCurrentClusterName(),
74 > shardContext: shardContext,
75 > registry: shardContext.GetNamespaceRegistry(),
76 > cache: workflowCache,
77 > logger: logger,
78 > metricHandler: metricHandler,
79 > historyRawClient: historyRawClient,
80 > matchingRawClient: matchingRawClient,
81 > config: shardContext.GetConfig(),
82 > searchAttributesProvider: shardContext.GetSearchAttributesProvider(),
83 > visibilityManager: visibilityManager,
84 > workflowDeleteManager: deletemanager.NewDeleteManager(
85 > shardContext,
86 > workflowCache,
87 > shardContext.GetConfig(),
88 > shardContext.GetTimeSource(),
89 > visibilityManager,
90 > ),
91 > chasmEngine: chasmEngine,
92 > }
93 > }
94
95 func (t *transferQueueTaskExecutorBase) pushActivity(
153 priority *commonpb.Priority,
154 transactionPolicy historyi.TransactionPolicy,
156 > var sst *durationpb.Duration
157 > if workflowTaskScheduleToStartTimeout > 0 {
158 sst = durationpb.New(workflowTaskScheduleToStartTimeout)
159 }
160 > resp, err := t.matchingRawClient.AddWorkflowTask(ctx, &matchingservice.AddWorkflowTaskRequest{ transfer_queue_task_executor_base.go
161 > NamespaceId: task.NamespaceID,
162 > Execution: &commonpb.WorkflowExecution{
163 > WorkflowId: task.WorkflowID,
164 > RunId: task.RunID,
165 > },
166 > TaskQueue: taskqueue,
167 > ScheduledEventId: task.ScheduledEventID,
168 > ScheduleToStartTimeout: sst,
169 > Clock: vclock.NewVectorClock(t.shardContext.GetClusterMetadata().GetClusterID(), t.shardContext.GetShardID(), task.TaskID),
170 > VersionDirective: directive,
171 > Priority: priority,
172 > Stamp: task.Stamp,
173 > })
174 > if _, isNotFound := err.(*serviceerror.NotFound); isNotFound {
175 // NotFound error is not expected for AddTasks calls
176 // but will be ignored by task error handling logic, so log it here
178 }
179
180 > if err != nil { transfer_queue_task_executor_base.go
181 return err
182 }
183
184 > if directive.GetUseAssignmentRules() == nil { transfer_queue_task_executor_base.go
185 // assignment rules are not used, so no need to update MS
186 return nil
187 }
188
189 > return initializeWorkflowAssignedBuildId( transfer_queue_task_executor_base.go
190 > ctx,
191 > task,
192 > resp.AssignedBuildId,
193 > t.shardContext,
194 > transactionPolicy,
195 > t.cache,
196 > t.metricHandler,
197 > t.logger,
198 > )
199 }
200
go.temporal.io/server/common/rpc/interceptor/request_error_handler.go 52 covered LOC · 15 ranges

Open complete file

45 logger log.Logger,
46 logAllReqErrors dynamicconfig.BoolPropertyFnWithNamespaceFilter,
47 > ) *RequestErrorHandler { request_error_handler.go
48 > return &RequestErrorHandler{
49 > logger: logger,
50 > workflowTags: logtags.NewWorkflowTags(tasktoken.NewSerializer(), logger),
51 > logAllReqErrors: logAllReqErrors,
52 > }
53 > }
54
55 // HandleError handles error recording and logging
61 err error,
62 nsName namespace.Name,
64 > statusCode := serviceerror.ToStatus(err).Code()
65 > if statusCode == codes.OK {
66 return
67 }
68
69 > isExpectedError := isExpectedErrorByStatusCode(statusCode) || isExpectedErrorByType(err) request_error_handler.go
70 >
71 > recordErrorMetrics(metricsHandler, err, isExpectedError)
72 > eh.logError(req, fullMethod, nsName, err, statusCode, isExpectedError, logTags)
73 }
74
81 isExpectedError bool,
82 logTags []tag.Tag,
84 > logAllErrors := nsName != "" && eh.logAllReqErrors(nsName.String())
85 > // context errors may not be user errors, but still too noisy to log by default
86 > if !logAllErrors && (isExpectedError ||
87 > common.IsContextDeadlineExceededErr(err) ||
88 > common.IsContextCanceledErr(err) ||
89 > common.IsResourceExhausted(err)) {
91 > }
92
93 > logTags = append(logTags, tag.Stringer("grpc_code", statusCode)) request_error_handler.go
94 > logTags = append(logTags, eh.workflowTags.Extract(req, fullMethod)...)
95 >
96 > eh.logger.Error("service failures", append(logTags, tag.Error(err))...)
97 }
98
99 > func recordErrorMetrics(metricsHandler metrics.Handler, err error, isExpectedError bool) { request_error_handler.go
100 > metrics.ServiceErrorWithType.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err))
101 >
102 > var resourceExhaustedErr *serviceerror.ResourceExhausted
103 > if errors.As(err, &resourceExhaustedErr) {
104 metrics.ServiceErrResourceExhaustedCounter.With(metricsHandler).Record(
105 1,
126 codes.FailedPrecondition,
127 codes.OutOfRange,
128 > codes.Unauthenticated: request_error_handler.go
129 > return true
130 // We could just return false here, but making it explicit what codes are
131 // considered (potentially) server errors.
139 codes.Internal,
140 codes.Unavailable,
141 > codes.DataLoss: request_error_handler.go
142 > return false
143 default:
144 return false
146 }
147
148 > func isExpectedErrorByType(err error) bool { request_error_handler.go
149 > // This is not a full list of service errors.
150 > // Only errors with status code that fails the isExpectedErrorByStatusCode() check
151 > // but are actually expected need to be explicitly handled here.
152 > //
153 > // Some of the errors listed below does not failed the isExpectedErrorByStatusCode() check
154 > // but are listed nonetheless.
155 > switch err := err.(type) {
156 case *serviceerror.ResourceExhausted:
157 return err.Scope == enumspb.RESOURCE_EXHAUSTED_SCOPE_NAMESPACE
go.temporal.io/server/common/headers/headers.go 51 covered LOC · 22 ranges

Open complete file

45 // GetValues returns header values for passed header names.
46 // It always returns slice of the same size as number of passed header names.
47 > func GetValues(ctx context.Context, headerNames ...string) []string { headers.go
48 > headerValues := make([]string, len(headerNames))
49 >
50 > for i, headerName := range headerNames {
51 > if values := metadata.ValueFromIncomingContext(ctx, headerName); len(values) > 0 {
52 > headerValues[i] = values[0] headers.go
53 > }
54 }
55
56 > return headerValues headers.go
57 }
58
60 // It copies all headers to outgoing context only if they are exist in incoming context
61 // and doesn't exist in outgoing context already.
62 > func Propagate(ctx context.Context) context.Context { headers.go
63 > headersToAppend := make([]string, 0, len(propagateHeaders)*2)
64 > mdOutgoing, mdOutgoingExist := metadata.FromOutgoingContext(ctx)
65 > for _, headerName := range propagateHeaders {
66 > if incomingValue := metadata.ValueFromIncomingContext(ctx, headerName); len(incomingValue) > 0 && len(mdOutgoing.Get(headerName)) == 0 {
67 > headersToAppend = append(headersToAppend, headerName, incomingValue[0]) headers.go
68 > }
69 }
70 > if headersToAppend != nil { headers.go
71 > if mdOutgoingExist {
72 > ctx = metadata.AppendToOutgoingContext(ctx, headersToAppend...) headers.go
73 > } else { headers.go
74 > ctx = metadata.NewOutgoingContext(ctx, metadata.Pairs(headersToAppend...)) headers.go
75 > }
76 }
77 > return ctx headers.go
78 }
79
88 }
89
90 > func NewGRPCHeaderGetter(ctx context.Context) GRPCHeaderGetter { headers.go
91 > return GRPCHeaderGetter{ctx: ctx}
92 > }
93
94 // Get a single value from the underlying gRPC metadata.
95 // Returns an empty string if the metadata key is unset.
96 > func (h GRPCHeaderGetter) Get(key string) string { headers.go
97 > if values := metadata.ValueFromIncomingContext(h.ctx, key); len(values) > 0 {
98 > return values[0] headers.go
99 > }
100 > return "" headers.go
101 }
102
125 // StripPrincipal removes principal headers from incoming metadata to prevent
126 // external callers from spoofing principal identity.
127 > func StripPrincipal(ctx context.Context) context.Context { headers.go
128 > mdIncoming, ok := metadata.FromIncomingContext(ctx)
129 > if !ok {
130 return ctx
131 }
132 > mdIncoming.Delete(PrincipalTypeHeaderName) headers.go
133 > mdIncoming.Delete(PrincipalNameHeaderName)
134 > return metadata.NewIncomingContext(ctx, mdIncoming)
135 }
136
144
145 // GetPrincipal retrieves the principal from the context headers. Returns nil if principal is not set.
146 > func GetPrincipal(ctx context.Context) *commonpb.Principal { headers.go
147 > values := GetValues(ctx, PrincipalTypeHeaderName, PrincipalNameHeaderName)
148 > if values[0] == "" && values[1] == "" {
149 > return nil headers.go
150 > }
151 return &commonpb.Principal{Type: values[0], Name: values[1]}
152 }
154 // setIncomingMD sets the key-value pairs in the incoming metadata.
155 // Empty values are ignored.
156 > func setIncomingMD(ctx context.Context, kv map[string]string) context.Context { headers.go
157 > mdIncoming, ok := metadata.FromIncomingContext(ctx)
158 > if !ok {
159 > mdIncoming = metadata.MD{} headers.go
160 > }
161 > for k, v := range kv { headers.go
162 > if v != "" {
163 > mdIncoming.Set(k, v)
164 > }
165 }
166 > return metadata.NewIncomingContext(ctx, mdIncoming) headers.go
167 }
go.temporal.io/server/common/rpc/dial_tracer.go 51 covered LOC · 12 ranges

Open complete file

22 mh metrics.Handler,
23 logger log.Logger,
24 > ) *dialTracer { dial_tracer.go
25 > l := log.With(
26 > logger,
27 > tag.String("service", "client"),
28 > tag.String("address", address),
29 > )
30 >
31 > return &dialTracer{
32 > address: address,
33 > metricsHandler: mh,
34 > logger: l,
35 > }
36 > }
37
38 > func (d *dialTracer) beginNetworkDial(ctx context.Context) (context.Context, *networkDialTrace) { dial_tracer.go
39 > ndt := &networkDialTrace{startedAt: time.Now()}
40 >
41 > // Build a ClientTrace capturing TCP connections.
42 > trace := &httptrace.ClientTrace{
43 > ConnectStart: func(_, _ string) {
44 > ndt.connectStart = time.Now() dial_tracer.go
45 > },
46 > ConnectDone: func(_ string, addr string, err error) { dial_tracer.go
47 > // ConnectStart may not have been called if the address is reused
48 > if !ndt.connectStart.IsZero() {
49 > ndt.connectDuration = time.Since(ndt.connectStart) dial_tracer.go
50 > }
51 > ndt.connectAddr = addr dial_tracer.go
52 > ndt.connectErr = err
53 },
54 }
55
56 > return httptrace.WithClientTrace(ctx, trace), ndt dial_tracer.go
57 }
58
59 > func (d *dialTracer) endNetworkDial(ndt *networkDialTrace, dialErr error) { dial_tracer.go
60 > total := time.Since(ndt.startedAt)
61 >
62 > if dialErr != nil {
63 > fields := []tag.Tag{ dial_tracer.go
64 > tag.Duration("totalDuration", total),
65 > tag.Error(dialErr),
66 > tag.ErrorType(dialErr),
67 > tag.Duration("connectDuration", ndt.connectDuration),
68 > tag.String("connectAddr", ndt.connectAddr),
69 > }
70 > if ndt.connectErr != nil {
71 > fields = append(fields, tag.String("connectErr", ndt.connectErr.Error()))
72 > }
73 > d.logger.Warn("network dial error", fields...)
74 > metrics.ServiceDialErrorCount.With(d.metricsHandler).Record(1)
75 > } else { dial_tracer.go
76 > metrics.ServiceDialSuccessCount.With(d.metricsHandler).Record(1)
77 > }
78
79 > if ndt.connectDuration > 0 { dial_tracer.go
80 > metrics.ServiceDialLatency.With(d.metricsHandler).Record(ndt.connectDuration) dial_tracer.go
81 > }
82 }
83
go.temporal.io/server/common/searchattribute/sadefs/constants.go 51 covered LOC · 17 ranges

Open complete file

261 }
262
263 > dbCustomSearchAttributeFieldNameRE = func() map[enumspb.IndexedValueType]*regexp.Regexp { constants.go
264 > res := map[enumspb.IndexedValueType]*regexp.Regexp{}
265 > for t := range defaultNumDBCustomSearchAttributes {
266 > res[t] = regexp.MustCompile(fmt.Sprintf(`^%s(0[1-9]|[1-9][0-9])$`, t.String()))
267 > }
268 > return res
269 }()
270 )
271
272 // System returns a clone of the system search attributes map.
273 > func System() map[string]enumspb.IndexedValueType { constants.go
274 > return maps.Clone(system)
275 > }
276
277 // Predefined returns a clone of the predefined search attributes map.
278 > func Predefined() map[string]enumspb.IndexedValueType { constants.go
279 > return maps.Clone(predefined)
280 > }
281
282 // PredefinedWhiteList returns a clone of the predefined whitelist search attributes map.
283 > func PredefinedWhiteList() map[string]enumspb.IndexedValueType { constants.go
284 > return maps.Clone(predefinedWhiteList)
285 > }
286
287 // Reserved returns a clone of the reserved field names map.
291
292 // IsSystem returns true if name is system search attribute
293 > func IsSystem(name string) bool { constants.go
294 > _, ok := system[name]
295 > return ok
296 > }
297
298 // IsReserved returns true if name is system reserved and can't be used as custom search attribute name.
299 > func IsReserved(name string) bool { constants.go
300 > if _, ok := system[name]; ok {
301 return true
302 }
303 > if _, ok := predefined[name]; ok { constants.go
304 return true
305 }
306 > if _, ok := reserved[name]; ok { constants.go
307 return true
308 }
309 > return strings.HasPrefix(name, ReservedPrefix) constants.go
310 }
311
323
324 // IsChasmSystem returns true if name is a system search attribute used by CHASM
325 > func IsChasmSystem(name string) bool { constants.go
326 > _, ok := chasmSystemSearchAttributes[name]
327 > return ok
328 > }
329
330 // IsChasmOverridableSystem returns true if name is a system search attribute whose dedicated
331 // visibility column a CHASM component may override with its own value. See
332 // chasmOverridableSystemSearchAttributes for the semantics and exclusions.
333 > func IsChasmOverridableSystem(name string) bool { constants.go
334 > _, ok := chasmOverridableSystemSearchAttributes[name]
335 > return ok
336 > }
337
338 // ChasmOverridableSystem returns a clone of the CHASM-overridable system search attributes set.
343 // GetSqlDbColName maps system and reserved search attributes to column names for SQL tables.
344 // If the input is not a system or reserved search attribute, then it returns the input.
345 > func GetSqlDbColName(name string) string { constants.go
346 > if fieldName, ok := sqlDbSystemNameToColName[name]; ok {
347 > return fieldName constants.go
348 > }
349 return name
350 }
352 func GetDBIndexSearchAttributes(
353 override map[enumspb.IndexedValueType]int,
354 > ) *persistencespb.IndexSearchAttributes { constants.go
355 > csa := map[string]enumspb.IndexedValueType{}
356 > for saType, defaultNumAttrs := range defaultNumDBCustomSearchAttributes {
357 > numAttrs := defaultNumAttrs
358 > if value, ok := override[saType]; ok {
359 numAttrs = value
360 }
361 > for i := range numAttrs { constants.go
362 > csa[fmt.Sprintf("%s%02d", saType.String(), i+1)] = saType
363 > }
364 }
365 > return &persistencespb.IndexSearchAttributes{ constants.go
366 > CustomSearchAttributes: csa,
367 > }
368 }
369
370 > func IsPreallocatedCSAFieldName(name string, valueType enumspb.IndexedValueType) bool { constants.go
371 > re := dbCustomSearchAttributeFieldNameRE[valueType]
372 > return re != nil && re.MatchString(name)
373 > }
374
375 var chasmSearchAttributePattern = regexp.MustCompile(`^Temporal(Bool|Datetime|Int|Double|Text|Keyword|LowCardinalityKeyword|KeywordList)(0[1-9]|[1-9][0-9])$`)
go.temporal.io/server/service/history/queues/reader_group.go 51 covered LOC · 15 ranges

Open complete file

30 func NewReaderGroup(
31 initializer ReaderInitializer,
32 > ) *ReaderGroup { reader_group.go
33 > return &ReaderGroup{
34 > initializer: initializer,
35 >
36 > status: common.DaemonStatusInitialized,
37 > readerMap: make(map[int64]Reader),
38 > }
39 > }
40
41 > func (g *ReaderGroup) Start() { reader_group.go
42 > if !atomic.CompareAndSwapInt32(&g.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
43 return
44 }
45
46 > g.Lock() reader_group.go
47 > defer g.Unlock()
48 >
49 > for _, reader := range g.readerMap {
50 reader.Start()
51 }
52 }
53
54 > func (g *ReaderGroup) Stop() { reader_group.go
55 > if !atomic.CompareAndSwapInt32(&g.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
56 return
57 }
58
59 > g.Lock() reader_group.go
60 > defer g.Unlock()
61 >
62 > for _, reader := range g.readerMap {
63 > reader.Stop() reader_group.go
64 > }
65 }
66
100 }
101
102 > func (g *ReaderGroup) ReaderByID(readerID int64) (Reader, bool) { reader_group.go
103 > g.Lock()
104 > defer g.Unlock()
105 >
106 > return g.getReaderByIDLocked(readerID)
107 > }
108
109 > func (g *ReaderGroup) getReaderByIDLocked(readerID int64) (Reader, bool) { reader_group.go
110 > if g.readerMap == nil {
111 return nil, false
112 }
113
114 > reader, ok := g.readerMap[readerID] reader_group.go
115 > return reader, ok
116 }
117
118 > func (g *ReaderGroup) NewReader(readerID int64, slices ...Slice) Reader { reader_group.go
119 > g.Lock()
120 > defer g.Unlock()
121 >
122 > return g.newReaderLocked(readerID, slices...)
123 > }
124
125 > func (g *ReaderGroup) newReaderLocked(readerID int64, slices ...Slice) Reader { reader_group.go
126 > reader := g.initializer(readerID, slices)
127 >
128 > if _, ok := g.readerMap[readerID]; ok {
129 panic(fmt.Sprintf("reader with ID %v already exists", readerID))
130 }
131
132 > g.readerMap[readerID] = reader reader_group.go
133 >
134 > if g.isStarted() {
135 > reader.Start() reader_group.go
136 > }
137 > return reader reader_group.go
138 }
139
151 }
152
153 > func (g *ReaderGroup) isStarted() bool { reader_group.go
154 > return atomic.LoadInt32(&g.status) == common.DaemonStatusStarted
155 > }
go.temporal.io/server/service/matching/pri_metrics_handler.go 51 covered LOC · 14 ranges

Open complete file

43
44 // TODO(pri): cleanup; delete this
45 > func newPriMetricsHandler(handler metrics.Handler) priMetricHandler { pri_metrics_handler.go
46 > return priMetricHandler{
47 > handler: handler,
48 > }
49 > }
50
51 func (p priMetricHandler) Stop(logger log.Logger) {
53 }
54
55 > func (p priMetricHandler) Counter(name string) metrics.CounterIface { pri_metrics_handler.go
56 > return priMetricsCounter{name: name, handler: p.handler}
57 > }
58 > func (p priMetricHandler) Timer(name string) metrics.TimerIface { pri_metrics_handler.go
59 > return priMetricsTimer{name: name, handler: p.handler}
60 > }
61
62 > func (p priMetricHandler) Gauge(name string) metrics.GaugeIface { pri_metrics_handler.go
63 > return priMetricsGauge{name: name, handler: p.handler}
64 > }
65
66 func (p priMetricHandler) WithTags(...metrics.Tag) metrics.Handler {
76 }
77
78 > func (c priMetricsCounter) Record(i int64, tag ...metrics.Tag) { pri_metrics_handler.go
79 > c.handler.Counter(c.name).Record(i, tag...)
80 > c.handler.Counter(withPriPrefix(c.name)).Record(i, tag...)
81 > }
82
83 > func (t priMetricsTimer) Record(duration time.Duration, tag ...metrics.Tag) { pri_metrics_handler.go
84 > t.handler.Timer(t.name).Record(duration, tag...)
85 > t.handler.Timer(withPriPrefix(t.name)).Record(duration, tag...)
86 > }
87
88 > func (t priMetricsGauge) Record(v float64, tag ...metrics.Tag) { pri_metrics_handler.go
89 > t.handler.Gauge(t.name).Record(v, tag...)
90 > t.handler.Gauge(withPriPrefix(t.name)).Record(v, tag...)
91 > }
92
93 > func withPriPrefix(name string) string { pri_metrics_handler.go
94 > return "pri_" + name
95 > }
96
97 > func newFairMetricsHandler(handler metrics.Handler) fairMetricHandler { pri_metrics_handler.go
98 > return fairMetricHandler{
99 > handler: handler,
100 > }
101 > }
102
103 func (p fairMetricHandler) Stop(logger log.Logger) {
105 }
106
107 > func (p fairMetricHandler) Counter(name string) metrics.CounterIface { pri_metrics_handler.go
108 > return fairMetricsCounter{name: name, handler: p.handler}
109 > }
110 func (p fairMetricHandler) Timer(name string) metrics.TimerIface {
111 return fairMetricsTimer{name: name, handler: p.handler}
112 }
113
114 > func (p fairMetricHandler) Gauge(name string) metrics.GaugeIface { pri_metrics_handler.go
115 > return fairMetricsGauge{name: name, handler: p.handler}
116 > }
117
118 func (p fairMetricHandler) WithTags(...metrics.Tag) metrics.Handler {
128 }
129
130 > func (c fairMetricsCounter) Record(i int64, tag ...metrics.Tag) { pri_metrics_handler.go
131 > c.handler.Counter(c.name).Record(i, tag...)
132 > c.handler.Counter(withFairPrefix(c.name)).Record(i, tag...)
133 > }
134
135 func (t fairMetricsTimer) Record(duration time.Duration, tag ...metrics.Tag) {
138 }
139
140 > func (t fairMetricsGauge) Record(v float64, tag ...metrics.Tag) { pri_metrics_handler.go
141 > t.handler.Gauge(t.name).Record(v, tag...)
142 > t.handler.Gauge(withFairPrefix(t.name)).Record(v, tag...)
143 > }
144
145 > func withFairPrefix(name string) string { pri_metrics_handler.go
146 > return "fair_" + name
147 > }
go.temporal.io/server/common/persistence/sql/queue.go 50 covered LOC · 16 ranges

Open complete file

27 queueType persistence.QueueType,
28 serializer serialization.Serializer,
29 > ) (persistence.Queue, error) { queue.go
30 > queue := &sqlQueue{
31 > SqlStore: NewSQLStore(db, logger, serializer),
32 > queueType: queueType,
33 > logger: logger,
34 > }
35 > return queue, nil
36 > }
37
38 func (q *sqlQueue) Init(
39 ctx context.Context,
40 blob *commonpb.DataBlob,
41 > ) error { queue.go
42 > if err := q.initializeQueueMetadata(ctx, blob); err != nil {
43 return err
44 }
45 > return q.initializeDLQMetadata(ctx, blob) queue.go
46 }
47
309 }
310
311 > func (q *sqlQueue) getDLQTypeFromQueueType() persistence.QueueType { queue.go
312 > return -q.queueType
313 > }
314
315 func (q *sqlQueue) initializeQueueMetadata(
316 ctx context.Context,
317 blob *commonpb.DataBlob,
318 > ) error { queue.go
319 > _, err := q.DB.SelectFromQueueMetadata(ctx, sqlplugin.QueueMetadataFilter{
320 > QueueType: q.queueType,
321 > })
322 > switch err {
323 > case nil: queue.go
324 > return nil
325 > case sql.ErrNoRows: queue.go
326 > result, err := q.DB.InsertIntoQueueMetadata(ctx, &sqlplugin.QueueMetadataRow{
327 > QueueType: q.queueType,
328 > Data: blob.Data,
329 > DataEncoding: blob.EncodingType.String(),
330 > })
331 > if err != nil {
332 return serviceerror.NewUnavailablef("initializeQueueMetadata operation failed. Error %v", err)
333 }
334 > rowsAffected, err := result.RowsAffected() queue.go
335 > if err != nil {
336 return fmt.Errorf("rowsAffected returned error when initializing queue metadata %v: %v", q.queueType, err)
337 }
338 > if rowsAffected != 1 { queue.go
339 return fmt.Errorf("rowsAffected returned %v queue metadata instead of one", rowsAffected)
340 }
341 > return nil queue.go
342 default:
343 return err
348 ctx context.Context,
349 blob *commonpb.DataBlob,
350 > ) error { queue.go
351 > _, err := q.DB.SelectFromQueueMetadata(ctx, sqlplugin.QueueMetadataFilter{
352 > QueueType: q.getDLQTypeFromQueueType(),
353 > })
354 > switch err {
355 > case nil: queue.go
356 > return nil
357 > case sql.ErrNoRows: queue.go
358 > result, err := q.DB.InsertIntoQueueMetadata(ctx, &sqlplugin.QueueMetadataRow{
359 > QueueType: q.getDLQTypeFromQueueType(),
360 > Data: blob.Data,
361 > DataEncoding: blob.EncodingType.String(),
362 > })
363 > if err != nil {
364 return serviceerror.NewUnavailablef("initializeDLQMetadata operation failed. Error %v", err)
365 }
366 > rowsAffected, err := result.RowsAffected() queue.go
367 > if err != nil {
368 return fmt.Errorf("rowsAffected returned error when initializing DLQ metadata %v: %v", q.queueType, err)
369 }
370 > if rowsAffected != 1 { queue.go
371 return fmt.Errorf("rowsAffected returned %v DLQ metadata instead of one", rowsAffected)
372 }
373 > return nil queue.go
374 default:
375 return err
go.temporal.io/server/service/history/api/consistency_checker.go 50 covered LOC · 15 ranges

Open complete file

84 shardContext historyi.ShardContext,
85 workflowCache wcache.Cache,
86 > ) *WorkflowConsistencyCheckerImpl { consistency_checker.go
87 > return &WorkflowConsistencyCheckerImpl{
88 > shardContext: shardContext,
89 > workflowCache: workflowCache,
90 > }
91 > }
92
93 > func (c *WorkflowConsistencyCheckerImpl) GetWorkflowCache() wcache.Cache { consistency_checker.go
94 > return c.workflowCache
95 > }
96
97 func (c *WorkflowConsistencyCheckerImpl) GetCurrentWorkflowRunID(
117 workflowKey definition.WorkflowKey,
118 lockPriority locks.Priority,
119 > ) (WorkflowLease, error) { consistency_checker.go
120 > return c.getWorkflowLeaseImpl(ctx, reqClock, nil, workflowKey, chasm.WorkflowArchetypeID, lockPriority)
121 > }
122
123 // The code below should be used when custom workflow state validation is required.
130 workflowKey definition.WorkflowKey,
131 lockPriority locks.Priority,
132 > ) (WorkflowLease, error) { consistency_checker.go
133 > return c.getWorkflowLeaseImpl(ctx, reqClock, consistencyPredicate, workflowKey, chasm.WorkflowArchetypeID, lockPriority)
134 > }
135
136 func (c *WorkflowConsistencyCheckerImpl) GetCurrentChasmRunID(
180 archetypeID chasm.ArchetypeID,
181 lockPriority locks.Priority,
182 > ) (WorkflowLease, error) { consistency_checker.go
183 > if err := c.clockConsistencyCheck(reqClock); err != nil {
184 return nil, err
185 }
186
187 > if len(workflowKey.RunID) != 0 { consistency_checker.go
188 > return c.getWorkflowLease(ctx, consistencyPredicate, workflowKey, archetypeID, lockPriority) consistency_checker.go
189 > }
190
191 return c.getCurrentWorkflowLease(
201 func (c *WorkflowConsistencyCheckerImpl) clockConsistencyCheck(
202 reqClock *clockspb.VectorClock,
203 > ) error { consistency_checker.go
204 > if reqClock == nil {
205 > return nil
206 > }
207 > currentClock := c.shardContext.CurrentVectorClock() consistency_checker.go
208 > if !vclock.Comparable(reqClock, currentClock) {
209 // request vector clock is not comparable with current shard vector clock
210 return nil
211 }
212
213 > cmpResult, err := vclock.Compare(reqClock, currentClock) consistency_checker.go
214 > if err != nil {
215 return err
216 }
217 > if cmpResult <= 0 { consistency_checker.go
218 > return nil
219 > }
220 shardID := c.shardContext.GetShardID()
221 c.shardContext.UnloadForOwnershipLost()
279 archetypeID chasm.ArchetypeID,
280 lockPriority locks.Priority,
281 > ) (WorkflowLease, error) { consistency_checker.go
282 >
283 > wfContext, release, err := c.workflowCache.GetOrCreateChasmExecution(
284 > ctx,
285 > c.shardContext,
286 > namespace.ID(workflowKey.NamespaceID),
287 > &commonpb.WorkflowExecution{
288 > WorkflowId: workflowKey.WorkflowID,
289 > RunId: workflowKey.RunID,
290 > },
291 > archetypeID,
292 > lockPriority,
293 > )
294 > if err != nil {
295 return nil, err
296 }
297
298 > mutableState, err := wfContext.LoadMutableState(ctx, c.shardContext) consistency_checker.go
299 > if err != nil {
300 release(err)
301 return nil, err
303
304 // if consistencyPredicate is nil we assume it is not needed
305 > if consistencyPredicate == nil || consistencyPredicate(mutableState) { consistency_checker.go
306 > return NewWorkflowLease(wfContext, release, mutableState), nil consistency_checker.go
307 > }
308 wfContext.Clear()
309
go.temporal.io/server/service/matching/fair_task_writer.go 50 covered LOC · 9 ranges

Open complete file

40 backlogMgr *fairBacklogManagerImpl,
41 counterFactory func(subqueueIndex) counter.Counter,
42 > ) *fairTaskWriter { fair_task_writer.go
43 > return &fairTaskWriter{
44 > backlogMgr: backlogMgr,
45 > config: backlogMgr.config,
46 > db: backlogMgr.db,
47 > logger: backlogMgr.logger,
48 > counterFactory: counterFactory,
49 > appendCh: make(chan *writeTaskRequest, backlogMgr.config.OutstandingTaskAppendsThreshold()),
50 >
51 > taskIDBlock: noTaskIDs,
52 > counters: make(map[subqueueIndex]counter.Counter),
53 > ditherSeed: maphash.MakeSeed(),
54 > }
55 > }
56
57 // Start fairTaskWriter background goroutine.
58 > func (w *fairTaskWriter) Start() { fair_task_writer.go
59 > go w.taskWriterLoop()
60 > }
61
62 func (w *fairTaskWriter) appendTask(
141 }
142
143 > func (w *fairTaskWriter) initState() error { fair_task_writer.go
144 > state, err := w.renewLeaseWithRetry(foreverRetryPolicy, common.IsPersistenceTransientError)
145 > if err != nil {
146 w.backlogMgr.initState(taskQueueState{}, err)
147 return err
148 }
149 > w.taskIDBlock = rangeIDToTaskIDBlock(state.rangeID, w.config.RangeSize) fair_task_writer.go
150 > w.currentTaskIDBlock = w.taskIDBlock
151 > w.backlogMgr.initState(state, nil)
152 > return nil
153 }
154
155 > func (w *fairTaskWriter) taskWriterLoop() { fair_task_writer.go
156 > if w.initState() != nil {
157 return
158 }
160 // TODO: this will be out of phase with the timer in fairBacklogManagerImpl.periodicSync.
161 // can we align them better?
162 > persistFairnessKeys := time.NewTicker(w.config.UpdateAckInterval()).C fair_task_writer.go
163 >
164 > var reqs []*writeTaskRequest
165 > for {
166 > atomic.StoreInt64(&w.currentTaskIDBlock.start, w.taskIDBlock.start)
167 > atomic.StoreInt64(&w.currentTaskIDBlock.end, w.taskIDBlock.end)
168 >
169 > // prepare slice for reuse
170 > clear(reqs)
171 > reqs = reqs[:0]
172 >
173 > select {
174 > case <-w.backlogMgr.tqCtx.Done(): fair_task_writer.go
175 > return
176 case req := <-w.appendCh:
177 // read a batch of requests from the channel
230 retryPolicy backoff.RetryPolicy,
231 retryErrors backoff.IsRetryable,
232 > ) (taskQueueState, error) { fair_task_writer.go
233 > var newState taskQueueState
234 > op := func(ctx context.Context) (err error) {
235 > newState, err = w.db.RenewLease(ctx)
236 > return
237 > }
238 > metrics.LeaseRequestPerTaskQueueCounter.With(w.backlogMgr.metricsHandler).Record(1)
239 > err := backoff.ThrottleRetryContext(w.backlogMgr.tqCtx, op, retryPolicy, retryErrors)
240 > if err != nil {
241 metrics.LeaseFailurePerTaskQueueCounter.With(w.backlogMgr.metricsHandler).Record(1)
242 return newState, err
243 }
244 > return newState, nil fair_task_writer.go
245 }
246
go.temporal.io/server/api/enums/v1/task.pb.go 49 covered LOC · 15 ranges

Open complete file

55 }
56
57 > func (x TaskSource) String() string { task.pb.go
58 > switch x {
59 case TASK_SOURCE_UNSPECIFIED:
60 return "Unspecified"
61 case TASK_SOURCE_HISTORY:
62 return "History"
63 > case TASK_SOURCE_DB_BACKLOG: task.pb.go
64 > return "DbBacklog"
65 default:
66 return strconv.Itoa(int(x))
69 }
70
71 > func (TaskSource) Descriptor() protoreflect.EnumDescriptor { task.pb.go
72 > return file_temporal_server_api_enums_v1_task_proto_enumTypes[0].Descriptor()
73 > }
74
75 func (TaskSource) Type() protoreflect.EnumType {
217 }
218
219 > func (x TaskType) String() string { task.pb.go
220 > switch x {
221 case TASK_TYPE_UNSPECIFIED:
222 return "Unspecified"
225 case TASK_TYPE_REPLICATION_SYNC_ACTIVITY:
226 return "ReplicationSyncActivity"
227 > case TASK_TYPE_TRANSFER_WORKFLOW_TASK: task.pb.go
228 > return "TransferWorkflowTask"
229 case TASK_TYPE_TRANSFER_ACTIVITY_TASK:
230 return "TransferActivityTask"
231 > case TASK_TYPE_TRANSFER_CLOSE_EXECUTION: task.pb.go
232 > return "TransferCloseExecution"
233 case TASK_TYPE_TRANSFER_CANCEL_EXECUTION:
234 return "TransferCancelExecution"
243 // TaskPriority is only used for replication task as of May 2024
244 return "TransferResetWorkflow"
245 > case TASK_TYPE_WORKFLOW_TASK_TIMEOUT: task.pb.go
246 > return "WorkflowTaskTimeout"
247 case TASK_TYPE_ACTIVITY_TIMEOUT:
248 return "ActivityTimeout"
253 case TASK_TYPE_WORKFLOW_RUN_TIMEOUT:
254 return "WorkflowRunTimeout"
255 > case TASK_TYPE_DELETE_HISTORY_EVENT: task.pb.go
256 > return "DeleteHistoryEvent"
257
258 // Enum value maps for TaskPriority.
259 case TASK_TYPE_ACTIVITY_RETRY_TIMER:
260 return "ActivityRetryTimer"
261 > case TASK_TYPE_WORKFLOW_BACKOFF_TIMER: task.pb.go
262 > return "WorkflowBackoffTimer"
263 > case TASK_TYPE_VISIBILITY_START_EXECUTION: task.pb.go
264 > return "VisibilityStartExecution"
265 case TASK_TYPE_VISIBILITY_UPSERT_EXECUTION:
266 return "VisibilityUpsertExecution"
267 > case TASK_TYPE_VISIBILITY_CLOSE_EXECUTION: task.pb.go
268 > return "VisibilityCloseExecution"
269 case TASK_TYPE_VISIBILITY_DELETE_EXECUTION:
270 return "VisibilityDeleteExecution"
303 }
304
305 > func (TaskType) Descriptor() protoreflect.EnumDescriptor { task.pb.go
306 > return file_temporal_server_api_enums_v1_task_proto_enumTypes[1].Descriptor()
307 > }
308
309 func (TaskType) Type() protoreflect.EnumType {
361 }
362
363 > func (TaskPriority) Descriptor() protoreflect.EnumDescriptor { task.pb.go
364 > return file_temporal_server_api_enums_v1_task_proto_enumTypes[2].Descriptor()
365 > }
366
367 func (TaskPriority) Type() protoreflect.EnumType {
456 }
457
458 > func init() { file_temporal_server_api_enums_v1_task_proto_init() } task.pb.go
459 > func file_temporal_server_api_enums_v1_task_proto_init() {
460 > if File_temporal_server_api_enums_v1_task_proto != nil {
461 return
462 }
463 > type x struct{} task.pb.go
464 > out := protoimpl.TypeBuilder{
465 > File: protoimpl.DescBuilder{
466 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
467 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_task_proto_rawDesc), len(file_temporal_server_api_enums_v1_task_proto_rawDesc)),
468 > NumEnums: 3,
469 > NumMessages: 0,
470 > NumExtensions: 0,
471 > NumServices: 0,
472 > },
473 > GoTypes: file_temporal_server_api_enums_v1_task_proto_goTypes,
474 > DependencyIndexes: file_temporal_server_api_enums_v1_task_proto_depIdxs,
475 > EnumInfos: file_temporal_server_api_enums_v1_task_proto_enumTypes,
476 > }.Build()
477 > File_temporal_server_api_enums_v1_task_proto = out.File
478 > file_temporal_server_api_enums_v1_task_proto_goTypes = nil
479 > file_temporal_server_api_enums_v1_task_proto_depIdxs = nil
480 }
go.temporal.io/server/client/matching/client_gen.go 49 covered LOC · 16 ranges

Open complete file

38 request *matchingservice.CancelOutstandingPollRequest,
39 opts ...grpc.CallOption,
40 > ) (*matchingservice.CancelOutstandingPollResponse, error) { client_gen.go
41 >
42 > p, err := tqid.PartitionFromProto(request.GetTaskQueue(), request.GetNamespaceId(), request.GetTaskQueueType())
43 > if err != nil {
44 return nil, err
45 }
46
47 > client, err := c.getClientForTaskQueuePartition(p) client_gen.go
48 > if err != nil {
49 return nil, err
50 }
51 > ctx, cancel := c.createContext(ctx) client_gen.go
52 > defer cancel()
53 > return client.CancelOutstandingPoll(ctx, request, opts...)
54 }
55
309 request *matchingservice.ForceUnloadTaskQueuePartitionRequest,
310 opts ...grpc.CallOption,
311 > ) (*matchingservice.ForceUnloadTaskQueuePartitionResponse, error) { client_gen.go
312 >
313 > p := tqid.PartitionFromPartitionProto(request.GetTaskQueuePartition(), request.GetNamespaceId())
314 >
315 > client, err := c.getClientForTaskQueuePartition(p)
316 > if err != nil {
317 return nil, err
318 }
319 > ctx, cancel := c.createContext(ctx) client_gen.go
320 > defer cancel()
321 > return client.ForceUnloadTaskQueuePartition(ctx, request, opts...)
322 }
323
346 request *matchingservice.GetTaskQueueUserDataRequest,
347 opts ...grpc.CallOption,
348 > ) (*matchingservice.GetTaskQueueUserDataResponse, error) { client_gen.go
349 >
350 > p, err := tqid.NormalPartitionFromRpcName(request.GetTaskQueue(), request.GetNamespaceId(), request.GetTaskQueueType())
351 > if err != nil {
352 return nil, err
353 }
354
355 > client, err := c.getClientForTaskQueuePartition(p) client_gen.go
356 > if err != nil {
357 > return nil, err client_gen.go
358 > }
359 > ctx, cancel := c.createLongPollContext(ctx) client_gen.go
360 > defer cancel()
361 > return client.GetTaskQueueUserData(ctx, request, opts...)
362 }
363
406 request *matchingservice.ListNexusEndpointsRequest,
407 opts ...grpc.CallOption,
408 > ) (*matchingservice.ListNexusEndpointsResponse, error) { client_gen.go
409 >
410 > p, err := tqid.NormalPartitionFromRpcName("not-applicable", "not-applicable", enumspb.TASK_QUEUE_TYPE_UNSPECIFIED)
411 > if err != nil {
412 return nil, err
413 }
414
415 > client, err := c.getClientForTaskQueuePartition(p) client_gen.go
416 > if err != nil {
417 > return nil, err client_gen.go
418 > }
419 > ctx, cancel := c.createLongPollContext(ctx) client_gen.go
420 > defer cancel()
421 > return client.ListNexusEndpoints(ctx, request, opts...)
422 }
423
466 request *matchingservice.RecordWorkerHeartbeatRequest,
467 opts ...grpc.CallOption,
468 > ) (*matchingservice.RecordWorkerHeartbeatResponse, error) { client_gen.go
469 >
470 > p, err := tqid.NormalPartitionFromRpcName("not-applicable", request.GetNamespaceId(), enumspb.TASK_QUEUE_TYPE_UNSPECIFIED)
471 > if err != nil {
472 return nil, err
473 }
474
475 > client, err := c.getClientForTaskQueuePartition(p) client_gen.go
476 > if err != nil {
477 return nil, err
478 }
479 > ctx, cancel := c.createContext(ctx) client_gen.go
480 > defer cancel()
481 > return client.RecordWorkerHeartbeat(ctx, request, opts...)
482 }
483
go.temporal.io/server/service/history/queues/rescheduler.go 49 covered LOC · 10 ranges

Open complete file

75 logger log.Logger,
76 metricsHandler metrics.Handler,
77 > ) *reschedulerImpl { rescheduler.go
78 > return &reschedulerImpl{
79 > scheduler: scheduler,
80 > timeSource: timeSource,
81 > logger: logger,
82 > metricsHandler: metricsHandler,
83 >
84 > status: common.DaemonStatusInitialized,
85 > shutdownCh: make(chan struct{}),
86 >
87 > timerGate: timer.NewLocalGate(timeSource),
88 > taskChannelKeyFn: scheduler.TaskChannelKeyFn(),
89 >
90 > pqMap: make(map[TaskChannelKey]collection.Queue[rescheduledExecuable]),
91 > }
92 > }
93
94 > func (r *reschedulerImpl) Start() { rescheduler.go
95 > if !atomic.CompareAndSwapInt32(&r.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
96 return
97 }
98
99 > r.shutdownWG.Add(1) rescheduler.go
100 > go r.rescheduleLoop()
101 >
102 > r.logger.Info("Task rescheduler started.", tag.LifeCycleStarted)
103 }
104
105 > func (r *reschedulerImpl) Stop() { rescheduler.go
106 > if !atomic.CompareAndSwapInt32(&r.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
107 return
108 }
109
110 > close(r.shutdownCh) rescheduler.go
111 > r.timerGate.Close()
112 >
113 > if success := common.AwaitWaitGroup(&r.shutdownWG, time.Minute); !success {
114 r.logger.Warn("Task rescheduler timedout on shutdown.", tag.LifeCycleStopTimedout)
115 }
116
117 > r.logger.Info("Task rescheduler stopped.", tag.LifeCycleStopped) rescheduler.go
118 }
119
179 }
180
181 > func (r *reschedulerImpl) rescheduleLoop() { rescheduler.go
182 > defer r.shutdownWG.Done()
183 >
184 > cleanupTimer := time.NewTimer(backoff.Jitter(
185 > reschedulerPQCleanupDuration,
186 > reschedulerPQCleanupJitterCoefficient,
187 > ))
188 > defer cleanupTimer.Stop()
189 >
190 > for {
191 > select {
192 > case <-r.shutdownCh: rescheduler.go
193 > r.drain()
194 > return
195 case <-r.timerGate.FireCh():
196 r.reschedule()
252 }
253
254 > func (r *reschedulerImpl) drain() { rescheduler.go
255 > r.Lock()
256 > defer r.Unlock()
257 >
258 > for key, pq := range r.pqMap {
259 for !pq.IsEmpty() {
260 pq.Remove()
go.temporal.io/server/common/persistence/shard_manager.go 48 covered LOC · 13 ranges

Open complete file

19 shardStore ShardStore,
20 serializer serialization.Serializer,
21 > ) ShardManager { shard_manager.go
22 > return &shardManagerImpl{
23 > shardStore: shardStore,
24 > serializer: serializer,
25 > }
26 > }
27
28 > func (m *shardManagerImpl) Close() { shard_manager.go
29 > m.shardStore.Close()
30 > }
31
32 func (m *shardManagerImpl) GetName() string {
37 ctx context.Context,
38 request *GetOrCreateShardRequest,
39 > ) (*GetOrCreateShardResponse, error) { shard_manager.go
40 > createShardInfo := func() (int64, *commonpb.DataBlob, error) {
41 > shardInfo := request.InitialShardInfo shard_manager.go
42 > if shardInfo == nil {
43 > shardInfo = &persistencespb.ShardInfo{} shard_manager.go
44 > }
45 > shardInfo.ShardId = request.ShardID shard_manager.go
46 > shardInfo.UpdateTime = timestamp.TimeNowPtrUtc()
47 > data, err := m.serializer.ShardInfoToBlob(shardInfo)
48 > if err != nil {
49 return 0, nil, err
50 }
51 > return shardInfo.GetRangeId(), data, nil shard_manager.go
52 }
53 > internalResp, err := m.shardStore.GetOrCreateShard(ctx, &InternalGetOrCreateShardRequest{ shard_manager.go
54 > ShardID: request.ShardID,
55 > CreateShardInfo: createShardInfo,
56 > LifecycleContext: request.LifecycleContext,
57 > })
58 > if err != nil {
59 return nil, err
60 }
61 > shardInfo, err := m.serializer.ShardInfoFromBlob(internalResp.ShardInfo) shard_manager.go
62 > if err != nil {
63 return nil, err
64 }
65 > return &GetOrCreateShardResponse{ shard_manager.go
66 > ShardInfo: shardInfo,
67 > }, nil
68 }
69
71 ctx context.Context,
72 request *UpdateShardRequest,
73 > ) error { shard_manager.go
74 > shardInfo := request.ShardInfo
75 > shardInfo.UpdateTime = timestamp.TimeNowPtrUtc()
76 >
77 > shardInfoBlob, err := m.serializer.ShardInfoToBlob(shardInfo)
78 > if err != nil {
79 return err
80 }
81 > internalRequest := &InternalUpdateShardRequest{ shard_manager.go
82 > ShardID: request.ShardInfo.GetShardId(),
83 > RangeID: request.ShardInfo.GetRangeId(),
84 > Owner: request.ShardInfo.GetOwner(),
85 > ShardInfo: shardInfoBlob,
86 > PreviousRangeID: request.PreviousRangeID,
87 > }
88 > return m.shardStore.UpdateShard(ctx, internalRequest)
89 }
90
92 ctx context.Context,
93 request *AssertShardOwnershipRequest,
94 > ) error { shard_manager.go
95 > return m.shardStore.AssertShardOwnership(ctx, request)
96 > }
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/db.go 48 covered LOC · 13 ranges

Open complete file

39 tx *sqlx.Tx,
40 logger log.Logger,
41 > ) *db { db.go
42 > mdb := &db{
43 > dbKind: dbKind,
44 > dbName: dbName,
45 > onClose: make([]func(), 0),
46 > db: xdb,
47 > tx: tx,
48 > logger: logger,
49 > }
50 > mdb.conn = xdb
51 > if tx != nil {
52 > mdb.conn = tx db.go
53 > }
54 > mdb.converter = &converter{} db.go
55 > return mdb
56 }
57
58 // BeginTx starts a new transaction and returns a reference to the Tx object
59 > func (mdb *db) BeginTx(ctx context.Context) (sqlplugin.Tx, error) { db.go
60 > xtx, err := mdb.db.BeginTxx(ctx, nil)
61 > if err != nil {
62 return nil, err
63 }
64 > return newDB(mdb.dbKind, mdb.dbName, mdb.db, xtx, mdb.logger), nil db.go
65 }
66
67 // Commit commits a previously started transaction
68 > func (mdb *db) Commit() error { db.go
69 > return mdb.tx.Commit()
70 > }
71
72 // Rollback triggers rollback of a previously started transaction
75 }
76
77 > func (mdb *db) OnClose(hook func()) { db.go
78 > mdb.mu.Lock()
79 > mdb.onClose = append(mdb.onClose, hook)
80 > mdb.mu.Unlock()
81 > }
82
83 // Close closes the connection to the sqlite db
84 > func (mdb *db) Close() error { db.go
85 > mdb.mu.RLock()
86 > defer mdb.mu.RUnlock()
87 >
88 > for _, hook := range mdb.onClose {
89 > // de-registers the database from conn pool db.go
90 > hook()
91 > }
92
93 // database connection will be automatically closed by the hook handler when all references are removed
94 > return nil db.go
95 }
96
97 // PluginName returns the name of the plugin
98 > func (mdb *db) PluginName() string { db.go
99 > return PluginName
100 > }
101
102 // DbName returns the name of the database
103 > func (mdb *db) DbName() string { db.go
104 > return mdb.dbName
105 > }
106
107 // ExpectedVersion returns expected version.
118
119 // VerifyVersion verify schema version is up to date
120 > func (mdb *db) VerifyVersion() error { db.go
121 > return nil
122 > // TODO(jlegrone): implement this
123 > // expectedVersion := mdb.ExpectedVersion()
124 > // return schema.VerifyCompatibleVersion(mdb, mdb.dbName, expectedVersion)
125 > }
go.temporal.io/server/common/quotas/calculator/logged_calculator.go 48 covered LOC · 10 ranges

Open complete file

38 calculator Calculator,
39 logger log.Logger,
40 > ) *LoggedCalculator { logged_calculator.go
41 > return &LoggedCalculator{
42 > quotaLogger: newQuotaLogger(logger),
43 > calculator: calculator,
44 > }
45 > }
46
47 > func (c *LoggedCalculator) GetQuota() float64 { logged_calculator.go
48 > quota := c.calculator.GetQuota()
49 > c.quotaLogger.updateQuota(quota)
50 > return quota
51 > }
52
53 func NewLoggedNamespaceCalculator(
54 calculator NamespaceCalculator,
55 logger log.Logger,
56 > ) *LoggedNamespaceCalculator { logged_calculator.go
57 > return &LoggedNamespaceCalculator{
58 > calculator: calculator,
59 > logger: logger,
60 > quotaLoggers: make(map[string]*quotaLogger[float64]),
61 > }
62 > }
63
64 > func (c *LoggedNamespaceCalculator) GetQuota(namespace string) float64 { logged_calculator.go
65 > quota := c.calculator.GetQuota(namespace)
66 > c.getOrCreateQuotaLogger(namespace).updateQuota(quota)
67 > return quota
68 > }
69
70 func (c *LoggedNamespaceCalculator) getOrCreateQuotaLogger(
71 namespace string,
72 > ) *quotaLogger[float64] { logged_calculator.go
73 > c.quotaLoggersLock.Lock()
74 > defer c.quotaLoggersLock.Unlock()
75 >
76 > quotaLogger, ok := c.quotaLoggers[namespace]
77 > if !ok {
78 > quotaLogger = newQuotaLogger(log.With(c.logger, tag.WorkflowNamespace(namespace)))
79 > c.quotaLoggers[namespace] = quotaLogger
80 > }
81
82 > return quotaLogger logged_calculator.go
83 }
84
85 func newQuotaLogger(
86 logger log.Logger,
87 > ) *quotaLogger[float64] { logged_calculator.go
88 > return &quotaLogger[float64]{
89 > logger: logger,
90 > }
91 > }
92
93 > func (l *quotaLogger[T]) updateQuota(newQuota T) { logged_calculator.go
94 > currentQuota := l.currentValue.Swap(newQuota)
95 >
96 > if currentQuota != nil && newQuota == currentQuota.(T) {
97 > return logged_calculator.go
98 > }
99
100 > l.logger.Info("Quota changed", logged_calculator.go
101 > tag.Any("current-quota", currentQuota),
102 > tag.Any("new-quota", newQuota),
103 > )
104 }
go.temporal.io/server/common/quotas/map_request_rate_limiter_impl.go 48 covered LOC · 11 ranges

Open complete file

40 rateLimiterGenFn RequestRateLimiterFn,
41 rateLimiterKeyFn RequestRateLimiterKeyFn[K],
42 > ) *MapRequestRateLimiterImpl[K] { map_request_rate_limiter_impl.go
43 > return &MapRequestRateLimiterImpl[K]{
44 > rateLimiterGenFn: rateLimiterGenFn,
45 > rateLimiterKeyFn: rateLimiterKeyFn,
46 > rateLimiters: make(map[K]*rateLimiterEntry),
47 > ttlNano: int64(rateLimiterTTL),
48 > cleanupTicker: time.NewTicker(rateLimiterCleanupInterval),
49 > }
50 > }
51
52 > func namespaceRequestRateLimiterKeyFn(req Request) string { map_request_rate_limiter_impl.go
53 > return req.Caller
54 > }
55
56 func NewNamespaceRequestRateLimiter(
57 rateLimiterGenFn RequestRateLimiterFn,
58 > ) *MapRequestRateLimiterImpl[string] { map_request_rate_limiter_impl.go
59 > return NewMapRequestRateLimiter(rateLimiterGenFn, namespaceRequestRateLimiterKeyFn)
60 > }
61
62 // Allow attempts to allow a request to go through. The method returns
66 now time.Time,
67 request Request,
69 > rateLimiter := r.getOrInitRateLimiter(now, request)
70 > return rateLimiter.Allow(now, request)
71 > }
72
73 // Reserve returns a Reservation that indicates how long the caller
94 now time.Time,
95 req Request,
96 > ) RequestRateLimiter { map_request_rate_limiter_impl.go
97 > r.maybeCleanup(now)
98 >
99 > key := r.rateLimiterKeyFn(req)
100 > nowNano := now.UnixNano()
101 >
102 > r.RLock()
103 > entry, ok := r.rateLimiters[key]
104 > r.RUnlock()
105 >
106 > if ok {
107 > entry.lastAccess.Store(nowNano) map_request_rate_limiter_impl.go
108 > return entry.rateLimiter
109 > }
110
111 > newRateLimiter := r.rateLimiterGenFn(req) map_request_rate_limiter_impl.go
112 > r.Lock()
113 > defer r.Unlock()
114 >
115 > if entry, ok := r.rateLimiters[key]; ok {
116 > entry.lastAccess.Store(nowNano) map_request_rate_limiter_impl.go
117 > return entry.rateLimiter
118 > }
119
120 > entry = &rateLimiterEntry{rateLimiter: newRateLimiter} map_request_rate_limiter_impl.go
121 > entry.lastAccess.Store(nowNano)
122 > r.rateLimiters[key] = entry
123 > return newRateLimiter
124 }
125
127 // receive drains at most one ticker tick, so only one sweeper starts even if many
128 // callers reach here at once.
129 > func (r *MapRequestRateLimiterImpl[K]) maybeCleanup(now time.Time) { map_request_rate_limiter_impl.go
130 > select {
131 case <-r.cleanupTicker.C:
132 go r.cleanup(now)
134 }
135 }
go.temporal.io/server/service/worker/batcher/fx.go 48 covered LOC · 5 ranges

Open complete file

63 serviceResolver membership.ServiceResolver,
64 logger log.Logger,
65 > ) AdminBatcherRateLimiter { fx.go
66 > return quotas.NewRequestRateLimiterAdapter(
67 > quotas.NewDefaultOutgoingRateLimiter(
68 > calculator.NewLoggedCalculator(
69 > calculator.ClusterAwareQuotaCalculator{
70 > MemberCounter: serviceResolver,
71 > PerInstanceQuota: dynamicconfig.AdminBatcherHostRPS.Get(dc),
72 > GlobalQuota: dynamicconfig.AdminBatcherGlobalRPS.Get(dc),
73 > },
74 > log.With(logger, tag.ComponentAdminBatcher, tag.ScopeHost),
75 > ).GetQuota,
76 > ),
77 > )
78 > }
79
80 func NewResult(
81 dc *dynamicconfig.Collection,
82 params activityDeps,
83 > ) fxResult { fx.go
84 > return fxResult{
85 > Component: &workerComponent{
86 > activityDeps: params,
87 > dc: dc,
88 > enabledFeature: dynamicconfig.EnableBatcherNamespace.Get(dc),
89 > },
90 > }
91 > }
92
93 > func (s *workerComponent) DedicatedWorkerOptions(ns *namespace.Namespace) *workercommon.PerNSDedicatedWorkerOptions { fx.go
94 > namespaceName := ns.Name().String()
95 > enableFeature := s.enabledFeature(namespaceName)
96 > return &workercommon.PerNSDedicatedWorkerOptions{
97 > Enabled: enableFeature,
98 > }
99 > }
100
101 > func (s *workerComponent) Register(registry sdkworker.Registry, ns *namespace.Namespace, _ workercommon.RegistrationDetails) func() { fx.go
102 > // Register the batch workflow with both the proto-qualified and unqualified types.
103 > // TODO(spkane31): Remove the proto-qualified type and call the unqualified type from the frontend after the 1.30 release.
104 > registry.RegisterWorkflowWithOptions(BatchWorkflowProtobuf, workflow.RegisterOptions{Name: BatchWFTypeName})
105 > // Newer version of the batch workflow which was rewritten to accept a proto struct as input.
106 > registry.RegisterWorkflowWithOptions(BatchWorkflowProtobuf, workflow.RegisterOptions{Name: BatchWFTypeProtobufName})
107 > registry.RegisterActivity(s.activities(ns.Name(), ns.ID()))
108 > return nil
109 > }
110
111 > func (s *workerComponent) activities(name namespace.Name, id namespace.ID) *activities { fx.go
112 > return &activities{
113 > activityDeps: s.activityDeps,
114 > namespace: name,
115 > namespaceID: id,
116 > rps: dynamicconfig.BatcherRPS.Get(s.dc),
117 > concurrency: dynamicconfig.BatcherConcurrency.Get(s.dc),
118 > }
119 > }
go.temporal.io/server/client/matching/partition_cache.go 47 covered LOC · 12 ranges

Open complete file

37 func newPartitionCache(
38 metricsHandler metrics.Handler,
39 > ) *partitionCache { partition_cache.go
40 > return &partitionCache{
41 > metricsHandler: metricsHandler,
42 > }
43 > }
44
45 > func (c *partitionCache) Start() { partition_cache.go
46 > for i := range c.shards {
47 > c.shards[i].rotate()
48 > }
49 > c.rotate = goro.NewHandle(context.Background()).Go(func(ctx context.Context) error {
50 > t := time.NewTicker(partitionCacheRotateInterval / partitionCacheNumShards)
51 > defer t.Stop()
52 > for i := 0; ; i = (i + 1) % partitionCacheNumShards {
53 > select {
54 case <-t.C:
55 c.shards[i].rotate()
56 c.emitMetrics()
57 > case <-ctx.Done(): partition_cache.go
58 > return ctx.Err()
59 }
60 }
62 }
63
64 > func (c *partitionCache) Stop() { partition_cache.go
65 > c.rotate.Cancel()
66 > <-c.rotate.Done()
67 > }
68
69 func (c *partitionCache) emitMetrics() {
77 func (*partitionCache) makeKey(
78 nsid, tqname string, tqtype enumspb.TaskQueueType,
79 > ) string { partition_cache.go
80 > // note we don't need delimiters to make unambiguous keys: nsid is always the same length,
81 > // the last byte is tqtype, and everything in between is the name.
82 > nsidBytes, err := uuid.Parse(nsid)
83 > if err != nil {
84 // this shouldn't fail, but use the string form as a backup, append a 0xff to differentiate
85 return nsid + string([]byte{0xff}) + tqname + string([]byte{byte(tqtype), 0xff})
86 }
87 > return string(nsidBytes[:]) + tqname + string([]byte{byte(tqtype)}) partition_cache.go
88 }
89
90 > func (*partitionCache) shardFromKey(key string) int { partition_cache.go
91 > // mix a few bits to pick a shard
92 > l := len(key)
93 > shard := int(key[min(14, l-3)] ^ key[l-2] ^ key[l-1])
94 > return shard % partitionCacheNumShards
95 > }
96
97 > func (c *partitionCache) lookup(key string) PartitionCounts { partition_cache.go
98 > return c.shards[c.shardFromKey(key)].lookup(key)
99 > }
100
101 func (c *partitionCache) put(key string, pc PartitionCounts) {
103 }
104
105 > func (s *partitionCacheShard) lookup(key string) PartitionCounts { partition_cache.go
106 > s.lock.RLock()
107 > if pc, ok := s.active[key]; ok {
108 s.lock.RUnlock()
109 return pc
110 > } else if pc, ok := s.prev[key]; ok { partition_cache.go
111 s.lock.RUnlock()
112 s.put(key, pc) // promote to active
113 return pc
114 }
115 > s.lock.RUnlock() partition_cache.go
116 > return PartitionCounts{}
117 }
118
129 }
130
131 > func (s *partitionCacheShard) rotate() { partition_cache.go
132 > s.lock.Lock()
133 > defer s.lock.Unlock()
134 > s.prev = s.active
135 > s.active = make(map[string]PartitionCounts)
136 > }
137
138 func (s *partitionCacheShard) size() int {
go.temporal.io/server/common/metrics/defs.go 47 covered LOC · 9 ranges

Open complete file

20 )
21
22 > func NewTimerDef(name string, opts ...Option) timerDefinition { defs.go
23 > // This line cannot be combined with others!
24 > // This ensures the stack trace has information of the caller.
25 > def := newMetricDefinition(name, opts...)
26 > globalRegistry.register(def)
27 > return timerDefinition{def}
28 > }
29
30 > func NewBytesHistogramDef(name string, opts ...Option) histogramDefinition { defs.go
31 > // This line cannot be combined with others!
32 > // This ensures the stack trace has information of the caller.
33 > def := newMetricDefinition(name, append(opts, WithUnit(Bytes))...)
34 > globalRegistry.register(def)
35 > return histogramDefinition{def}
36 > }
37
38 > func NewDimensionlessHistogramDef(name string, opts ...Option) histogramDefinition { defs.go
39 > // This line cannot be combined with others!
40 > // This ensures the stack trace has information of the caller.
41 > def := newMetricDefinition(name, append(opts, WithUnit(Dimensionless))...)
42 > globalRegistry.register(def)
43 > return histogramDefinition{def}
44 > }
45
46 > func NewCounterDef(name string, opts ...Option) counterDefinition { defs.go
47 > // This line cannot be combined with others!
48 > // This ensures the stack trace has information of the caller.
49 > def := newMetricDefinition(name, opts...)
50 > globalRegistry.register(def)
51 > return counterDefinition{def}
52 > }
53
54 > func NewGaugeDef(name string, opts ...Option) gaugeDefinition { defs.go
55 > // This line cannot be combined with others!
56 > // This ensures the stack trace has information of the caller.
57 > def := newMetricDefinition(name, opts...)
58 > globalRegistry.register(def)
59 > return gaugeDefinition{def}
60 > }
61
62 > func (d histogramDefinition) With(handler Handler) HistogramIface { defs.go
63 > return handler.Histogram(d.name, d.unit)
64 > }
65
66 > func (d counterDefinition) With(handler Handler) CounterIface { defs.go
67 > return handler.Counter(d.name)
68 > }
69
70 > func (d gaugeDefinition) With(handler Handler) GaugeIface { defs.go
71 > return handler.Gauge(d.name)
72 > }
73
74 > func (d timerDefinition) With(handler Handler) TimerIface { defs.go
75 > return handler.Timer(d.name)
76 > }
go.temporal.io/server/common/quotas/dynamic_rate_limiter_impl.go 47 covered LOC · 10 ranges

Open complete file

29 rateBurstFn RateBurst,
30 refreshInterval time.Duration,
31 > ) *DynamicRateLimiterImpl { dynamic_rate_limiter_impl.go
32 > rateLimiter := &DynamicRateLimiterImpl{
33 > rateBurstFn: rateBurstFn,
34 > refreshInterval: refreshInterval,
35 >
36 > refreshTimer: time.NewTimer(refreshInterval),
37 > rateLimiter: NewRateLimiter(rateBurstFn.Rate(), rateBurstFn.Burst()),
38 > }
39 > return rateLimiter
40 > }
41
42 // NewDefaultIncomingRateLimiter returns a default rate limiter
45 func NewDefaultIncomingRateLimiter(
46 rateFn RateFn,
47 > ) *DynamicRateLimiterImpl { dynamic_rate_limiter_impl.go
48 > return NewDynamicRateLimiter(
49 > NewDefaultIncomingRateBurst(rateFn),
50 > defaultRefreshInterval,
51 > )
52 > }
53
54 // NewDefaultOutgoingRateLimiter returns a default rate limiter
57 func NewDefaultOutgoingRateLimiter(
58 rateFn RateFn,
59 > ) *DynamicRateLimiterImpl { dynamic_rate_limiter_impl.go
60 > return NewDynamicRateLimiter(
61 > NewDefaultOutgoingRateBurst(rateFn),
62 > defaultRefreshInterval,
63 > )
64 > }
65
66 // NewDefaultRateLimiter returns a default rate limiter with a dynamic burst ratio
69 rateFn RateFn,
70 burstRatioFn BurstRatioFn,
71 > ) *DynamicRateLimiterImpl { dynamic_rate_limiter_impl.go
72 > return NewDynamicRateLimiter(
73 > NewDefaultRateBurst(rateFn, burstRatioFn),
74 > defaultRefreshInterval,
75 > )
76 > }
77
78 // Allow immediately returns with true or false indicating if a rate limit
79 // token is available or not
80 > func (d *DynamicRateLimiterImpl) Allow() bool { dynamic_rate_limiter_impl.go
81 > d.maybeRefresh()
82 > return d.rateLimiter.Allow()
83 > }
84
85 // AllowN immediately returns with true or false indicating if n rate limit
86 // token is available or not
87 > func (d *DynamicRateLimiterImpl) AllowN(now time.Time, numToken int) bool { dynamic_rate_limiter_impl.go
88 > d.maybeRefresh()
89 > return d.rateLimiter.AllowN(now, numToken)
90 > }
91
92 // Reserve reserves a rate limit token
93 > func (d *DynamicRateLimiterImpl) Reserve() Reservation { dynamic_rate_limiter_impl.go
94 > d.maybeRefresh()
95 > return d.rateLimiter.Reserve()
96 > }
97
98 // ReserveN reserves n rate limit token
99 > func (d *DynamicRateLimiterImpl) ReserveN(now time.Time, numToken int) Reservation { dynamic_rate_limiter_impl.go
100 > d.maybeRefresh()
101 > return d.rateLimiter.ReserveN(now, numToken)
102 > }
103
104 // Wait waits up till deadline for a rate limit token
go.temporal.io/server/common/collection/paging_iterator.go 46 covered LOC · 16 ranges

Open complete file

18 func NewPagingIterator[V any](
19 paginationFn PaginationFn[V],
20 > ) Iterator[V] { paging_iterator.go
21 > iter := &PagingIteratorImpl[V]{
22 > paginationFn: paginationFn,
23 > pageToken: nil,
24 > pageErr: nil,
25 > pageItems: nil,
26 > nextPageItemIndex: 0,
27 > }
28 > iter.getNextPage() // this will initialize the paging iterator
29 > return iter
30 > }
31
32 // NewPagingIteratorWithToken create a new paging iterator with initial token
47
48 // HasNext return whether has next item or err
49 > func (iter *PagingIteratorImpl[V]) HasNext() bool { paging_iterator.go
50 > // pagination encounters error
51 > if iter.pageErr != nil {
52 > return true paging_iterator.go
53 > }
54
55 // still have local cached item to return
56 > if iter.nextPageItemIndex < len(iter.pageItems) { paging_iterator.go
57 > return true paging_iterator.go
58 > }
59
60 > if len(iter.pageToken) != 0 { paging_iterator.go
61 iter.getNextPage()
62 return iter.HasNext()
63 }
64
65 > return false paging_iterator.go
66 }
67
68 // Next return next item or err
69 > func (iter *PagingIteratorImpl[V]) Next() (V, error) { paging_iterator.go
70 > if !iter.HasNext() {
71 panic("HistoryEventIterator Next() called without checking HasNext()")
72 }
73
74 > if iter.pageErr != nil { paging_iterator.go
75 > err := iter.pageErr paging_iterator.go
76 > iter.pageErr = nil
77 > var v V
78 > return v, err
79 > }
80
81 // we have cached events
82 > if iter.nextPageItemIndex < len(iter.pageItems) { paging_iterator.go
83 > index := iter.nextPageItemIndex
84 > iter.nextPageItemIndex++
85 > return iter.pageItems[index], nil
86 > }
87
88 panic("HistoryEventIterator Next() should return either a history event or a err")
89 }
90
91 > func (iter *PagingIteratorImpl[V]) getNextPage() { paging_iterator.go
92 > items, token, err := iter.paginationFn(iter.pageToken)
93 > if err == nil {
94 > iter.pageItems = items paging_iterator.go
95 > iter.pageToken = token
96 > iter.pageErr = nil
97 > } else { paging_iterator.go
98 > iter.pageItems = nil paging_iterator.go
99 > iter.pageToken = nil
100 > iter.pageErr = err
101 > }
102 > iter.nextPageItemIndex = 0 paging_iterator.go
103 }
go.temporal.io/server/common/headers/version_checker.go 46 covered LOC · 14 ranges

Open complete file

76
77 // NewDefaultVersionChecker constructs a new VersionChecker using default versions from const.
78 > func NewDefaultVersionChecker() *versionChecker { version_checker.go
79 > return NewVersionChecker(SupportedClients, ServerVersion)
80 > }
81
82 // NewVersionChecker constructs a new VersionChecker
83 > func NewVersionChecker(supportedClients map[string]string, serverVersion string) *versionChecker { version_checker.go
84 > return &versionChecker{
85 > serverVersion: semver.MustParse(serverVersion),
86 > supportedClients: supportedClients,
87 > supportedClientsRange: mustParseRanges(supportedClients),
88 > }
89 > }
90
91 // GetClientNameAndVersion extracts SDK name and version from context headers
92 > func GetClientNameAndVersion(ctx context.Context) (string, string) { version_checker.go
93 > headers := GetValues(ctx, ClientNameHeaderName, ClientVersionHeaderName)
94 > clientName := headers[0]
95 > clientVersion := headers[1]
96 > return clientName, clientVersion
97 > }
98
99 // SetVersions sets headers for internal communications.
114
115 // ClientSupported returns an error if client is unsupported, nil otherwise.
116 > func (vc *versionChecker) ClientSupported(ctx context.Context) error { version_checker.go
117 >
118 > headers := GetValues(ctx, ClientNameHeaderName, ClientVersionHeaderName, SupportedServerVersionsHeaderName)
119 > clientName := headers[0]
120 > clientVersion := headers[1]
121 > supportedServerVersions := headers[2]
122 >
123 > // Validate client version only if it is provided and server knows about this client.
124 > if clientName != "" && clientVersion != "" {
125 > if supportedClientRange, ok := vc.supportedClientsRange[clientName]; ok { version_checker.go
126 > clientVersionParsed, parseErr := semver.Parse(clientVersion)
127 > if parseErr != nil {
128 return serviceerror.NewInvalidArgumentf("Unable to parse client version: %v", parseErr)
129 }
130 > if !supportedClientRange(clientVersionParsed) { version_checker.go
131 return serviceerror.NewClientVersionNotSupported(clientVersion, clientName, vc.supportedClients[clientName])
132 }
135
136 // Validate supported server version if it is provided.
137 > if supportedServerVersions != "" { version_checker.go
138 > supportedServerVersionsParsed, parseErr := semver.ParseRange(supportedServerVersions) version_checker.go
139 > if parseErr != nil {
140 return serviceerror.NewInvalidArgumentf("Unable to parse supported server versions: %v", parseErr)
141 }
142 > if !supportedServerVersionsParsed(vc.serverVersion) { version_checker.go
143 return serviceerror.NewServerVersionNotSupported(vc.serverVersion.String(), supportedServerVersions)
144 }
145 }
146
147 > return nil version_checker.go
148 }
149
150 // ClientSupportsFeature returns true if the client reports support for the
151 // given feature (which should be one of the Feature... constants above).
152 > func (vc *versionChecker) ClientSupportsFeature(ctx context.Context, feature string) bool { version_checker.go
153 > headers := GetValues(ctx, SupportedFeaturesHeaderName)
154 > if len(headers) == 0 {
155 return false
156 }
157 > for clientFeature := range strings.SplitSeq(headers[0], SupportedFeaturesHeaderDelim) { version_checker.go
158 > if clientFeature == feature {
159 return true
160 }
161 }
162 > return false version_checker.go
163 }
164
165 > func mustParseRanges(ranges map[string]string) map[string]semver.Range { version_checker.go
166 > out := make(map[string]semver.Range, len(ranges))
167 > for c, r := range ranges {
168 > out[c] = semver.MustParseRange(r)
169 > }
170 > return out
171 }
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/shard.go 46 covered LOC · 6 ranges

Open complete file

28 ctx context.Context,
29 row *sqlplugin.ShardsRow,
30 > ) (sql.Result, error) { shard.go
31 > return mdb.conn.ExecContext(ctx,
32 > createShardQry,
33 > row.ShardID,
34 > row.RangeID,
35 > row.Data,
36 > row.DataEncoding,
37 > )
38 > }
39
40 // UpdateShards updates one or more rows into shards table
42 ctx context.Context,
43 row *sqlplugin.ShardsRow,
44 > ) (sql.Result, error) { shard.go
45 > return mdb.conn.ExecContext(ctx,
46 > updateShardQry,
47 > row.RangeID,
48 > row.Data,
49 > row.DataEncoding,
50 > row.ShardID,
51 > )
52 > }
53
54 // SelectFromShards reads one or more rows from shards table
56 ctx context.Context,
57 filter sqlplugin.ShardsFilter,
58 > ) (*sqlplugin.ShardsRow, error) { shard.go
59 > var row sqlplugin.ShardsRow
60 > err := mdb.conn.GetContext(ctx,
61 > &row,
62 > getShardQry,
63 > filter.ShardID,
64 > )
65 > if err != nil {
66 > return nil, err shard.go
67 > }
68 return &row, err
69 }
73 ctx context.Context,
74 filter sqlplugin.ShardsFilter,
75 > ) (int64, error) { shard.go
76 > var rangeID int64
77 > err := mdb.conn.GetContext(ctx,
78 > &rangeID,
79 > readLockShardQry,
80 > filter.ShardID,
81 > )
82 > return rangeID, err
83 > }
84
85 // WriteLockShards acquires a write lock on a single row in shards table
87 ctx context.Context,
88 filter sqlplugin.ShardsFilter,
89 > ) (int64, error) { shard.go
90 > var rangeID int64
91 > err := mdb.conn.GetContext(ctx,
92 > &rangeID,
93 > lockShardQry,
94 > filter.ShardID,
95 > )
96 > return rangeID, err
97 > }
go.temporal.io/server/service/frontend/nexus_operation_http_handler.go 46 covered LOC · 2 ranges

Open complete file

65 logger log.Logger,
66 httpTraceProvider commonnexus.HTTPClientTraceProvider,
67 > ) *NexusOperationHTTPHandler { nexus_operation_http_handler.go
68 > return &NexusOperationHTTPHandler{
69 > base: nexusrpc.BaseHTTPHandler{
70 > Logger: log.NewSlogLogger(logger),
71 > FailureConverter: nexusrpc.DefaultFailureConverter(),
72 > },
73 > logger: logger,
74 > enpointRegistry: endpointRegistry,
75 > namespaceRegistry: namespaceRegistry,
76 > auth: authInterceptor,
77 > namespaceValidationInterceptor: namespaceValidationInterceptor,
78 > namespaceRateLimitInterceptor: namespaceRateLimitInterceptor,
79 > namespaceConcurrencyLimitInterceptor: namespaceConcurrencyLimitInterceptor,
80 > rateLimitInterceptor: rateLimitInterceptor,
81 > preprocessErrorCounter: metricsHandler.Counter(metrics.NexusRequestPreProcessErrors.Name()).Record,
82 > nexusHandler: nexusrpc.NewHTTPHandler(nexusrpc.HandlerOptions{
83 > Handler: &nexusHandler{
84 > logger: logger,
85 > metricsHandler: metricsHandler,
86 > clusterMetadata: clusterMetadata,
87 > namespaceRegistry: namespaceRegistry,
88 > matchingClient: matchingservice.MatchingServiceClient(matchingClient),
89 > auth: authInterceptor,
90 > telemetryInterceptor: telemetryInterceptor,
91 > requestErrorHandler: requestErrorHandler,
92 > redirectionInterceptor: redirectionInterceptor,
93 > forwardingEnabledForNamespace: serviceConfig.EnableNamespaceNotActiveAutoForwarding,
94 > forwardingClients: clientCache,
95 > payloadSizeLimit: serviceConfig.BlobSizeLimitError,
96 > headersBlacklist: serviceConfig.NexusRequestHeadersBlacklist,
97 > useForwardByEndpoint: serviceConfig.NexusForwardRequestUseEndpoint,
98 > metricTagConfig: serviceConfig.NexusOperationsMetricTagConfig,
99 > httpTraceProvider: httpTraceProvider,
100 > },
101 > GetResultTimeout: serviceConfig.KeepAliveMaxConnectionIdle(),
102 > Logger: log.NewSlogLogger(logger),
103 > Serializer: commonnexus.PayloadSerializer,
104 > }),
105 > }
106 > }
107
108 > func (h *NexusOperationHTTPHandler) RegisterRoutes(r *mux.Router) { nexus_operation_http_handler.go
109 > r.PathPrefix("/" + commonnexus.RouteDispatchNexusTaskByNamespaceAndTaskQueue.Representation() + "/").
110 > HandlerFunc(h.dispatchNexusTaskByNamespaceAndTaskQueue)
111 > r.PathPrefix("/" + commonnexus.RouteDispatchNexusTaskByEndpoint.Representation() + "/").
112 > HandlerFunc(h.dispatchNexusTaskByEndpoint)
113 > }
114
115 func (h *NexusOperationHTTPHandler) writeFailure(writer http.ResponseWriter, r *http.Request, err error) {
go.temporal.io/server/service/worker/scheduler/fx.go 46 covered LOC · 5 ranges

Open complete file

85 specBuilder *SpecBuilder,
86 params activityDeps,
87 > ) fxResult { fx.go
88 > return fxResult{
89 > Component: &workerComponent{
90 > specBuilder: specBuilder,
91 > activityDeps: params,
92 > enabledForNs: dynamicconfig.WorkerEnableScheduler.Get(dc),
93 > enableCHASMMigration: dynamicconfig.EnableCHASMSchedulerMigration.Get(dc),
94 > chasmMigrationRolloutPercent: dynamicconfig.CHASMSchedulerMigrationRolloutPercent.Get(dc),
95 > migrateWithRunningWorkflows: dynamicconfig.EnableCHASMSchedulerMigrationWithRunningWorkflows.Get(dc),
96 > globalNSStartWorkflowRPS: dynamicconfig.SchedulerNamespaceStartWorkflowRPS.Subscribe(dc),
97 > maxBlobSize: dynamicconfig.BlobSizeLimitError.Get(dc),
98 > localActivitySleepLimit: dynamicconfig.SchedulerLocalActivitySleepLimit.Get(dc),
99 > },
100 > }
101 > }
102
103 > func (s *workerComponent) DedicatedWorkerOptions(ns *namespace.Namespace) *workercommon.PerNSDedicatedWorkerOptions { fx.go
104 > return &workercommon.PerNSDedicatedWorkerOptions{
105 > Enabled: s.enabledForNs(ns.Name().String()),
106 > }
107 > }
108
109 > func (s *workerComponent) Register(registry sdkworker.Registry, ns *namespace.Namespace, details workercommon.RegistrationDetails) func() { fx.go
110 > nsName := ns.Name().String()
111 > wfFunc := func(ctx workflow.Context, args *schedulespb.StartScheduleArgs) error {
112 key := fmt.Appendf(nil, "%s\x00%s", nsName, args.State.ScheduleId)
113 enableMigration := func() bool {
120 return schedulerWorkflowWithSpecBuilder(ctx, args, s.specBuilder, enableMigration, migrateWithRunningWorkflows)
121 }
122 > registry.RegisterWorkflowWithOptions(wfFunc, workflow.RegisterOptions{Name: WorkflowType}) fx.go
123 >
124 > activities, cleanup := s.newActivities(ns.Name(), ns.ID(), details)
125 > registry.RegisterActivity(activities)
126 > return cleanup
127 }
128
129 > func (s *workerComponent) newActivities(name namespace.Name, id namespace.ID, details workercommon.RegistrationDetails) (*activities, func()) { fx.go
130 > const burstRatio = 1.0
131 >
132 > lim := quotas.NewRateLimiter(1, 1)
133 > cb := func(rps float64) {
134 > localRPS := rps * float64(details.Multiplicity) / float64(details.TotalWorkers)
135 > burst := max(1, int(math.Ceil(localRPS*burstRatio)))
136 > lim.SetRateBurst(localRPS, burst)
137 > }
138 > initialRPS, cancel := s.globalNSStartWorkflowRPS(name.String(), cb)
139 > cb(initialRPS)
140 >
141 > return &activities{
142 > activityDeps: s.activityDeps,
143 > namespace: name,
144 > namespaceID: id,
145 > startWorkflowRateLimiter: lim,
146 > maxBlobSize: func() int { return s.maxBlobSize(name.String()) },
147 localActivitySleepLimit: func() time.Duration { return s.localActivitySleepLimit(name.String()) },
148 }, cancel
go.temporal.io/server/api/clock/v1/message.pb.go 45 covered LOC · 10 ranges

Open complete file

45 func (*VectorClock) ProtoMessage() {}
46
47 > func (x *VectorClock) ProtoReflect() protoreflect.Message { message.pb.go
48 > mi := &file_temporal_server_api_clock_v1_message_proto_msgTypes[0]
49 > if x != nil {
50 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) message.pb.go
51 > if ms.LoadMessageInfo() == nil {
52 > ms.StoreMessageInfo(mi)
53 > }
54 > return ms
55 }
56 > return mi.MessageOf(x) message.pb.go
57 }
58
62 }
63
64 > func (x *VectorClock) GetShardId() int32 { message.pb.go
65 > if x != nil {
66 > return x.ShardId
67 > }
68 return 0
69 }
70
71 > func (x *VectorClock) GetClock() int64 { message.pb.go
72 > if x != nil {
73 > return x.Clock
74 > }
75 return 0
76 }
77
78 > func (x *VectorClock) GetClusterId() int64 { message.pb.go
79 > if x != nil {
80 > return x.ClusterId
81 > }
82 return 0
83 }
113 func (*HybridLogicalClock) ProtoMessage() {}
114
115 > func (x *HybridLogicalClock) ProtoReflect() protoreflect.Message { message.pb.go
116 > mi := &file_temporal_server_api_clock_v1_message_proto_msgTypes[1]
117 > if x != nil {
118 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
119 if ms.LoadMessageInfo() == nil {
122 return ms
123 }
124 > return mi.MessageOf(x) message.pb.go
125 }
126
193 }
194
195 > func init() { file_temporal_server_api_clock_v1_message_proto_init() } message.pb.go
196 > func file_temporal_server_api_clock_v1_message_proto_init() {
197 > if File_temporal_server_api_clock_v1_message_proto != nil {
198 return
199 }
200 > type x struct{} message.pb.go
201 > out := protoimpl.TypeBuilder{
202 > File: protoimpl.DescBuilder{
203 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
204 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_clock_v1_message_proto_rawDesc), len(file_temporal_server_api_clock_v1_message_proto_rawDesc)),
205 > NumEnums: 0,
206 > NumMessages: 2,
207 > NumExtensions: 0,
208 > NumServices: 0,
209 > },
210 > GoTypes: file_temporal_server_api_clock_v1_message_proto_goTypes,
211 > DependencyIndexes: file_temporal_server_api_clock_v1_message_proto_depIdxs,
212 > MessageInfos: file_temporal_server_api_clock_v1_message_proto_msgTypes,
213 > }.Build()
214 > File_temporal_server_api_clock_v1_message_proto = out.File
215 > file_temporal_server_api_clock_v1_message_proto_goTypes = nil
216 > file_temporal_server_api_clock_v1_message_proto_depIdxs = nil
217 }
go.temporal.io/server/common/contextutil/metadata.go 45 covered LOC · 13 ranges

Open complete file

99
100 // ContextMetadataGetMarkedActivityIDs returns the marked activity IDs from the context.
101 > func ContextMetadataGetMarkedActivityIDs(ctx context.Context) []string { metadata.go
102 > metadataCtx := getMetadataContext(ctx)
103 > if metadataCtx == nil {
104 return nil
105 }
106
107 > metadataCtx.Lock() metadata.go
108 > defer metadataCtx.Unlock()
109 >
110 > if len(metadataCtx.MarkedActivityIDs) == 0 {
111 > return nil metadata.go
112 > }
113 ids := make([]string, 0, len(metadataCtx.MarkedActivityIDs))
114 for id := range metadataCtx.MarkedActivityIDs {
119
120 // getMetadataContext extracts metadata context from golang context.
121 > func getMetadataContext(ctx context.Context) *metadataContext { metadata.go
122 > metadataCtx := ctx.Value(metadataCtxKey)
123 > if metadataCtx == nil {
124 > return nil metadata.go
125 > }
126 > mc, ok := metadataCtx.(*metadataContext) metadata.go
127 > if !ok {
128 return nil
129 }
130 > return mc metadata.go
131 }
132
133 // WithMetadataContext adds a metadata context to the given context.
134 > func WithMetadataContext(ctx context.Context) context.Context { metadata.go
135 > metadataCtx := &metadataContext{
136 > Metadata: make(map[string]any),
137 > MarkedActivityIDs: make(map[string]struct{}),
138 > }
139 > return context.WithValue(ctx, metadataCtxKey, metadataCtx)
140 > }
141
142 // ContextHasMetadata returns true if the context has metadata support.
143 // This can be used to debug whether a context has been properly initialized with metadata.
144 > func ContextHasMetadata(ctx context.Context) bool { metadata.go
145 > return getMetadataContext(ctx) != nil
146 > }
147
148 // ContextMetadataSet sets a metadata key-value pair in the context, overwriting any existing value.
149 > func ContextMetadataSet(ctx context.Context, key string, value any) bool { metadata.go
150 > metadataCtx := getMetadataContext(ctx)
151 > if metadataCtx == nil {
152 return false
153 }
154
155 > metadataCtx.Lock() metadata.go
156 > defer metadataCtx.Unlock()
157 >
158 > metadataCtx.Metadata[key] = value
159 > return true
160 }
161
175
176 // ContextMetadataGetAll retrieves all metadata from the context as a map copy.
177 > func ContextMetadataGetAll(ctx context.Context) map[string]any { metadata.go
178 > metadataCtx := getMetadataContext(ctx)
179 > if metadataCtx == nil {
180 return nil
181 }
182
183 > metadataCtx.Lock() metadata.go
184 > defer metadataCtx.Unlock()
185 >
186 > // Return a copy to prevent external modifications
187 > result := make(map[string]any, len(metadataCtx.Metadata))
188 > maps.Copy(result, metadataCtx.Metadata)
189 > return result
190 }
go.temporal.io/server/common/persistence/visibility/visiblity_manager_metrics.go 45 covered LOC · 8 ranges

Open complete file

35 visibilityPluginNameMetricsTag metrics.Tag,
36 visibilityIndexNameMetricsTag metrics.Tag,
37 > ) *visibilityManagerMetrics { visiblity_manager_metrics.go
38 > return &visibilityManagerMetrics{
39 > metricHandler: metricHandler,
40 > logger: logger,
41 > delegate: delegate,
42 >
43 > slowQueryThreshold: slowQueryThreshold,
44 > visibilityPluginNameMetricsTag: visibilityPluginNameMetricsTag,
45 > visibilityIndexNameMetricsTag: visibilityIndexNameMetricsTag,
46 > }
47 > }
48
49 > func (m *visibilityManagerMetrics) Close() { visiblity_manager_metrics.go
50 > m.delegate.Close()
51 > }
52
53 func (m *visibilityManagerMetrics) GetReadStoreName(nsName namespace.Name) string {
55 }
56
57 > func (m *visibilityManagerMetrics) GetStoreNames() []string { visiblity_manager_metrics.go
58 > return m.delegate.GetStoreNames()
59 > }
60
61 func (m *visibilityManagerMetrics) HasStoreName(stName string) bool {
63 }
64
65 > func (m *visibilityManagerMetrics) GetIndexName() string { visiblity_manager_metrics.go
66 > return m.delegate.GetIndexName()
67 > }
68
69 func (m *visibilityManagerMetrics) ValidateCustomSearchAttributes(
76 ctx context.Context,
77 request *manager.RecordWorkflowExecutionStartedRequest,
79 > handler, startTime := m.tagScope(metrics.VisibilityPersistenceRecordWorkflowExecutionStartedScope)
80 > err := m.delegate.RecordWorkflowExecutionStarted(ctx, request)
81 > elapsed := time.Since(startTime)
82 > metrics.VisibilityPersistenceLatency.With(handler).Record(elapsed)
83 > metrics.ContextCounterAdd(ctx, metrics.TaskPersistenceLatency.Name(), elapsed.Nanoseconds())
84 > return m.updateErrorMetric(handler, err)
85 > }
86
87 func (m *visibilityManagerMetrics) RecordWorkflowExecutionClosed(
88 ctx context.Context,
89 request *manager.RecordWorkflowExecutionClosedRequest,
91 > handler, startTime := m.tagScope(metrics.VisibilityPersistenceRecordWorkflowExecutionClosedScope)
92 > err := m.delegate.RecordWorkflowExecutionClosed(ctx, request)
93 > elapsed := time.Since(startTime)
94 > metrics.VisibilityPersistenceLatency.With(handler).Record(elapsed)
95 > metrics.ContextCounterAdd(ctx, metrics.TaskPersistenceLatency.Name(), elapsed.Nanoseconds())
96 > return m.updateErrorMetric(handler, err)
97 > }
98
99 func (m *visibilityManagerMetrics) UpsertWorkflowExecution(
207 }
208
209 > func (m *visibilityManagerMetrics) tagScope(operation string) (metrics.Handler, time.Time) { visiblity_manager_metrics.go
210 > taggedHandler := m.metricHandler.WithTags(metrics.OperationTag(operation), m.visibilityPluginNameMetricsTag, m.visibilityIndexNameMetricsTag)
211 > metrics.VisibilityPersistenceRequests.With(taggedHandler).Record(1)
212 > return taggedHandler, time.Now().UTC()
213 > }
214
215 > func (m *visibilityManagerMetrics) updateErrorMetric(handler metrics.Handler, err error) error { visiblity_manager_metrics.go
216 > if err == nil {
217 > return nil
218 > }
219
220 metrics.VisibilityPersistenceErrorWithType.With(handler).Record(1, metrics.ServiceErrorTypeTag(err))
go.temporal.io/server/service/history/queues/executable_factory.go 44 covered LOC · 2 ranges

Open complete file

64 dlqInternalErrors dynamicconfig.BoolPropertyFn,
65 dlqErrorPattern dynamicconfig.StringPropertyFn,
66 > ) *executableFactoryImpl { executable_factory.go
67 > return &executableFactoryImpl{
68 > executor: executor,
69 > scheduler: scheduler,
70 > rescheduler: rescheduler,
71 > priorityAssigner: priorityAssigner,
72 > timeSource: timeSource,
73 > namespaceRegistry: namespaceRegistry,
74 > clusterMetadata: clusterMetadata,
75 > chasmRegistry: chasmRegistry,
76 > taskTypeTagProvider: taskTypeTagProvider,
77 > logger: logger,
78 > metricsHandler: metricsHandler,
79 > tracer: tracer,
80 > dlqWriter: dlqWriter,
81 > dlqEnabled: dlqEnabled,
82 > attemptsBeforeSendingToDlq: attemptsBeforeSendingToDlq,
83 > dlqInternalErrors: dlqInternalErrors,
84 > dlqErrorPattern: dlqErrorPattern,
85 > }
86 > }
87
88 > func (f *executableFactoryImpl) NewExecutable(task tasks.Task, readerID int64) Executable { executable_factory.go
89 > return NewExecutable(
90 > readerID,
91 > task,
92 > f.executor,
93 > f.scheduler,
94 > f.rescheduler,
95 > f.priorityAssigner,
96 > f.timeSource,
97 > f.namespaceRegistry,
98 > f.clusterMetadata,
99 > f.chasmRegistry,
100 > f.taskTypeTagProvider,
101 > f.logger,
102 > f.metricsHandler,
103 > f.tracer,
104 > func(params *ExecutableParams) {
105 > params.DLQEnabled = f.dlqEnabled
106 > params.DLQWriter = f.dlqWriter
107 > params.MaxUnexpectedErrorAttempts = f.attemptsBeforeSendingToDlq
108 > params.DLQInternalErrors = f.dlqInternalErrors
109 > params.DLQErrorPattern = f.dlqErrorPattern
110 > },
111 )
112 }
go.temporal.io/server/common/routing/route.go 43 covered LOC · 13 ranges

Open complete file

36
37 // NewRoute returns a new [Route] instance with the given components.
38 > func NewRoute[T any](components ...Component[T]) Route[T] { route.go
39 > return Route[T]{components: components}
40 > }
41
42 // RouteBuilder is a builder for the [Route] interface.
46
47 // NewBuilder creates a new [RouteBuilder] instance, which can be used to define a new [Route] via a fluent API.
48 > func NewBuilder[T any]() *RouteBuilder[T] { route.go
49 > return &RouteBuilder[T]{}
50 > }
51
52 // With adds a series of [Component] instances to the [Route].
53 > func (r *RouteBuilder[T]) With(c ...Component[T]) *RouteBuilder[T] { route.go
54 > r.components = append(r.components, c...)
55 > return r
56 > }
57
58 // Constant adds a [Constant] component to the [Route].
59 > func (r *RouteBuilder[T]) Constant(values ...string) *RouteBuilder[T] { route.go
60 > return r.With(Constant[T](values...))
61 > }
62
63 // StringVariable adds a [StringVariable] component to the [Route].
64 > func (r *RouteBuilder[T]) StringVariable(name string, getter func(*T) *string) *RouteBuilder[T] { route.go
65 > return r.With(StringVariable[T](name, getter))
66 > }
67
68 // Build returns a read-only [Route].
69 > func (r *RouteBuilder[T]) Build() Route[T] { route.go
70 > return NewRoute[T](r.components...)
71 > }
72
73 // Representation returns the [github.com/gorilla/mux] compatible string representation of the route for usage in a
75 // they're present in the components. We do this because it's easier to add a slash depending on the context than to
76 // remove it.
77 > func (r Route[T]) Representation() string { route.go
78 > return r.serialize(func(c Component[T]) string {
79 > return c.Representation()
80 > })
81 }
82
89 }
90
91 > func (r Route[T]) serialize(f func(c Component[T]) string) string { route.go
92 > var sb strings.Builder
93 > for i, c := range r.components {
94 > if i > 0 {
95 > sb.WriteString("/")
96 > }
97 > sb.WriteString(f(c))
98 }
99 > return sb.String() route.go
100 }
101
111 // Constant returns a [Component] that represents a series of constant HTTP path components in a Route.
112 // They will be joined via strings when used to construct a path or path representation.
113 > func Constant[T any](values ...string) constant[T] { route.go
114 > return values
115 > }
116
117 type constant[T any] []string
118
119 > func (s constant[T]) Representation() string { route.go
120 > return strings.Join(s, "/")
121 > }
122
123 func (s constant[T]) Serialize(T) string {
128
129 // StringVariable returns a [Component] that represents a string variable in a Route.
130 > func StringVariable[T any](name string, getter func(*T) *string) stringVariable[T] { route.go
131 > return stringVariable[T]{name, getter}
132 > }
133
134 type stringVariable[T any] struct {
137 }
138
139 > func (s stringVariable[T]) Representation() string { route.go
140 > return "{" + s.name + "}"
141 > }
142
143 func (s stringVariable[T]) Serialize(t T) string {
go.temporal.io/server/service/history/hsm/registry.go 43 covered LOC · 12 ranges

Open complete file

47
48 // NewRegistry creates a new [Registry].
49 > func NewRegistry() *Registry { registry.go
50 > return &Registry{
51 > machines: make(map[string]StateMachineDefinition),
52 > tasks: make(map[string]TaskSerializer),
53 > immediateExecutors: make(map[string]any),
54 > timerExecutors: make(map[string]any),
55 > remoteExecutors: make(map[string]remoteMethodDefinition),
56 > events: make(map[enumspb.EventType]EventDefinition),
57 > }
58 > }
59
60 // RegisterMachine registers a [StateMachineDefinition] by its type.
61 // Returns an [ErrDuplicateRegistration] if the state machine type has already been registered.
62 > func (r *Registry) RegisterMachine(sm StateMachineDefinition) error { registry.go
63 > t := sm.Type()
64 > if existing, ok := r.machines[t]; ok {
65 return fmt.Errorf("%w: state machine already registered for %v - %v", ErrDuplicateRegistration, sm.Type(), existing.Type())
66 }
67 > r.machines[t] = sm registry.go
68 > return nil
69 }
70
71 // Machine returns a [StateMachineDefinition] for a given type and a boolean indicating whether it was found.
72 > func (r *Registry) Machine(t string) (def StateMachineDefinition, ok bool) { registry.go
73 > def, ok = r.machines[t]
74 > return
75 > }
76
77 // RegisterTaskSerializer registers a [TaskSerializer] for a given type.
78 // Returns an [ErrDuplicateRegistration] if a serializer for this task type has already been registered.
79 > func (r *Registry) RegisterTaskSerializer(t string, def TaskSerializer) error { registry.go
80 > if exising, ok := r.tasks[t]; ok {
81 return fmt.Errorf("%w: task already registered for %v: %v", ErrDuplicateRegistration, t, exising)
82 }
83 > r.tasks[t] = def registry.go
84 > return nil
85 }
86
93 // RegisterImmediateExecutor registers an [ImmediateExecutor] for the given task type.
94 // Returns an [ErrDuplicateRegistration] if an executor for the type has already been registered.
95 > func RegisterImmediateExecutor[T Task](r *Registry, executor ImmediateExecutor[T]) error { registry.go
96 > var task T
97 > taskType := task.Type()
98 > // The executors are registered in pairs, so only need to check in one map.
99 > if existing, ok := r.immediateExecutors[taskType]; ok {
100 return fmt.Errorf(
101 "%w: executor already registered for task type %v: %v",
105 )
106 }
107 > r.immediateExecutors[taskType] = executor registry.go
108 > return nil
109 }
110
131 // RegisterTimerExecutor registers a [TimerExecutor] for the given task type.
132 // Returns an [ErrDuplicateRegistration] if an executor for the type has already been registered.
133 > func RegisterTimerExecutor[T Task](r *Registry, executor TimerExecutor[T]) error { registry.go
134 > var task T
135 > taskType := task.Type()
136 > // The executors are registered in pairs, so only need to check in one map.
137 > if existing, ok := r.timerExecutors[taskType]; ok {
138 return fmt.Errorf(
139 "%w: executor already registered for task type %v: %v",
143 )
144 }
145 > r.timerExecutors[taskType] = executor registry.go
146 > return nil
147 }
148
262 // RegisterEventDefinition registers an [EventDefinition] for the given event type.
263 // Returns an [ErrDuplicateRegistration] if a definition for the type has already been registered.
264 > func (r *Registry) RegisterEventDefinition(def EventDefinition) error { registry.go
265 > t := def.Type()
266 > prev, ok := r.events[t]
267 > if ok {
268 return fmt.Errorf("%w: event definition for event type %v: %v", ErrDuplicateRegistration, t, prev)
269 }
270 > r.events[t] = def registry.go
271 > return nil
272 }
273
go.temporal.io/server/common/timer/local_gate.go 42 covered LOC · 11 ranges

Open complete file

27
28 // NewLocalGate create a new timer gate instance
29 > func NewLocalGate(timeSource clock.TimeSource) LocalGate { local_gate.go
30 > lg := &LocalGateImpl{
31 > timer: time.NewTimer(0),
32 > nextWakeupTime: time.Time{},
33 > fireCh: make(chan struct{}, 1),
34 > closeCh: make(chan struct{}),
35 > timeSource: timeSource,
36 > }
37 > // the timer should be stopped when initialized
38 > if !lg.timer.Stop() {
39 // drain the existing signal if exist
40 <-lg.timer.C
41 }
42
43 > go func() { local_gate.go
44 > defer close(lg.fireCh)
45 > defer lg.timer.Stop()
46 > loop:
47 > for {
48 > select {
49 > case <-lg.timer.C: local_gate.go
50 > select {
51 // re-transmit on gateC
52 > case lg.fireCh <- struct{}{}: local_gate.go
53 default:
54 }
55
56 > case <-lg.closeCh: local_gate.go
57 > // closed; cleanup and quit
58 > break loop
59 }
60 }
61 }()
62
63 > return lg local_gate.go
64 }
65
66 // FireCh return the channel which will be fired when time is up
67 > func (lg *LocalGateImpl) FireCh() <-chan struct{} { local_gate.go
68 > return lg.fireCh
69 > }
70
71 // FireAfter check will the timer get fired after a certain time
76 // Update the timer gate, return true if update is a success.
77 // Success means timer is idle or timer is set with a sooner time to fire
78 > func (lg *LocalGateImpl) Update(nextTime time.Time) bool { local_gate.go
79 > // NOTE: negative duration will make the timer fire immediately
80 > now := lg.timeSource.Now()
81 >
82 > if lg.timer.Stop() && lg.nextWakeupTime.Before(nextTime) {
83 > // this means the timer, before stopped, is active && next wake-up time do not have to be updated local_gate.go
84 > lg.timer.Reset(lg.nextWakeupTime.Sub(now))
85 > return false
86 > }
87
88 // this means the timer, before stopped, is active && next wake-up time has to be updated
89 // or this means the timer, before stopped, is already fired / never active
90 > lg.nextWakeupTime = nextTime local_gate.go
91 > lg.timer.Reset(nextTime.Sub(now))
92 > // Notifies caller that next notification is reset to fire at passed in 'next' visibility time
93 > return true
94 }
95
96 // Close shutdown the timer
97 > func (lg *LocalGateImpl) Close() { local_gate.go
98 > close(lg.closeCh)
99 > }
go.temporal.io/server/service/history/queues/memory_scheduled_queue.go 42 covered LOC · 10 ranges

Open complete file

42 logger log.Logger,
43 metricsHandler metrics.Handler,
44 > ) *memoryScheduledQueue { memory_scheduled_queue.go
45 >
46 > nextTaskTimer := time.NewTimer(0)
47 > if !nextTaskTimer.Stop() {
48 <-nextTaskTimer.C
49 }
50
51 > return &memoryScheduledQueue{ memory_scheduled_queue.go
52 > taskQueue: collection.NewPriorityQueue[Executable](executableVisibilityTimeCompareLess),
53 > nextTaskTimer: nextTaskTimer,
54 > newTaskCh: make(chan Executable),
55 >
56 > timeSource: timeSource,
57 > logger: logger,
58 > metricsHandler: metricsHandler,
59 >
60 > status: common.DaemonStatusInitialized,
61 > shutdownCh: make(chan struct{}),
62 >
63 > scheduler: scheduler,
64 > }
65 }
66
72 }
73
74 > func (q *memoryScheduledQueue) Start() { memory_scheduled_queue.go
75 > if !atomic.CompareAndSwapInt32(&q.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
76 return
77 }
78
79 > q.logger.Info("", tag.LifeCycleStarting) memory_scheduled_queue.go
80 > defer q.logger.Info("", tag.LifeCycleStarted)
81 >
82 > q.shutdownWG.Add(1)
83 > go q.processQueueLoop()
84 }
85
86 > func (q *memoryScheduledQueue) Stop() { memory_scheduled_queue.go
87 > if !atomic.CompareAndSwapInt32(&q.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
88 return
89 }
90
91 > q.logger.Info("", tag.LifeCycleStopping) memory_scheduled_queue.go
92 > defer q.logger.Info("", tag.LifeCycleStopped)
93 >
94 > close(q.shutdownCh)
95 >
96 > if success := common.AwaitWaitGroup(&q.shutdownWG, time.Minute); !success {
97 q.logger.Warn("", tag.LifeCycleStopTimedout)
98 }
go.temporal.io/server/common/collection/sync_map.go 41 covered LOC · 10 ranges

Open complete file

15 }
16
17 > func NewSyncMap[K comparable, V any]() SyncMap[K, V] { sync_map.go
18 > return SyncMap[K, V]{
19 > RWMutex: &sync.RWMutex{},
20 > contents: make(map[K]V),
21 > }
22 > }
23
24 > func (m *SyncMap[K, V]) Get(key K) (value V, ok bool) { sync_map.go
25 > m.RLock()
26 > defer m.RUnlock()
27 > value, ok = m.contents[key]
28 > return
29 > }
30
31 > func (m *SyncMap[K, V]) GetOrSet(key K, value V) (v V, exist bool) { sync_map.go
32 > m.RLock()
33 > currentValue, ok := m.contents[key]
34 > m.RUnlock()
35 > if ok {
36 return currentValue, ok
37 }
38
39 > m.Lock() sync_map.go
40 > defer m.Unlock()
41 > currentValue, ok = m.contents[key]
42 > if ok {
43 return currentValue, ok
44 }
45 > m.contents[key] = value sync_map.go
46 > return value, false
47 }
48
49 > func (m *SyncMap[K, V]) Set(key K, value V) { sync_map.go
50 > m.Lock()
51 > defer m.Unlock()
52 > m.contents[key] = value
53 > }
54
55 > func (m *SyncMap[K, V]) Delete(key K) { sync_map.go
56 > m.Lock()
57 > defer m.Unlock()
58 > delete(m.contents, key)
59 > }
60
61 > func (m *SyncMap[K, V]) Pop(key K) (value V, ok bool) { sync_map.go
62 > m.Lock()
63 > defer m.Unlock()
64 > value, ok = m.contents[key]
65 > if ok {
66 > delete(m.contents, key) sync_map.go
67 > }
68 > return value, ok sync_map.go
69 }
70
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/events.go 41 covered LOC · 11 ranges

Open complete file

52 ctx context.Context,
53 row *sqlplugin.HistoryNodeRow,
54 > ) (sql.Result, error) { events.go
55 > // NOTE: txn_id is *= -1 within DB
56 > row.TxnID = -row.TxnID
57 > return mdb.conn.NamedExecContext(ctx,
58 > replaceHistoryNodesQuery,
59 > row,
60 > )
61 > }
62
63 // DeleteFromHistoryNode delete a row from history_node table
82 ctx context.Context,
83 filter sqlplugin.HistoryNodeSelectFilter,
84 > ) ([]sqlplugin.HistoryNodeRow, error) { events.go
85 > var query string
86 > if filter.MetadataOnly {
87 query = getHistoryNodeMetadataQuery
88 > } else if filter.ReverseOrder { events.go
89 query = getHistoryNodesReverseQuery
90 > } else { events.go
91 > query = getHistoryNodesQuery
92 > }
93
94 > var args []any events.go
95 > if filter.ReverseOrder {
96 args = []any{
97 filter.ShardID,
104 filter.PageSize,
105 }
106 > } else { events.go
107 > args = []any{
108 > filter.ShardID,
109 > filter.TreeID,
110 > filter.BranchID,
111 > filter.MinNodeID,
112 > -filter.MinTxnID, // NOTE: transaction ID is *= -1 when stored
113 > filter.MinNodeID,
114 > filter.MaxNodeID,
115 > filter.PageSize,
116 > }
117 > }
118
119 > var rows []sqlplugin.HistoryNodeRow events.go
120 > if err := mdb.conn.SelectContext(ctx, &rows, query, args...); err != nil {
121 return nil, err
122 }
123
124 > for index := range rows { events.go
125 > rows[index].TxnID = -rows[index].TxnID events.go
126 > }
127
128 > return rows, nil events.go
129 }
130
149 ctx context.Context,
150 row *sqlplugin.HistoryTreeRow,
151 > ) (sql.Result, error) { events.go
152 > return mdb.conn.NamedExecContext(ctx,
153 > addHistoryTreeQuery,
154 > row,
155 > )
156 > }
157
158 // SelectFromHistoryTree reads one or more rows from history_tree table
go.temporal.io/server/common/primitives/uuid.go 41 covered LOC · 15 ranges

Open complete file

17 // returns nil if the input is empty string
18 // panics if the given input is malformed
19 > func MustParseUUID(s string) UUID { uuid.go
20 > if s == "" {
21 return nil
22 }
23 > u := guuid.MustParse(s) uuid.go
24 > return u[:]
25 }
26
30 // - error if input is malformed
31 // - UUID object if input can be parsed and is valid
32 > func ParseUUID(s string) (UUID, error) { uuid.go
33 > if s == "" {
34 > return nil, nil uuid.go
35 > }
36 > u, err := guuid.Parse(s) uuid.go
37 >
38 > if err != nil {
39 return nil, err
40 }
41 > return u[:], nil uuid.go
42 }
43
68
69 // NewUUID generates a new random UUID
70 > func NewUUID() UUID { uuid.go
71 > u, err := guuid.NewV7()
72 > if err != nil {
73 // Should never happen, but this matches the behavior of google/uuid.NewRandom
74 return nil
75 }
76 > return u[:] uuid.go
77 }
78
91 // String returns the 36 byte hexstring representation of this uuid
92 // return empty string if this uuid is nil
93 > func (u UUID) String() string { uuid.go
94 > if len(u) != 16 {
95 return ""
96 }
97 > var buf [36]byte uuid.go
98 > u.encodeHex(buf[:])
99 > return string(buf[:])
100 }
101
122 // Scan implements sql.Scanner interface to allow this type to be
123 // parsed transparently by database drivers
124 > func (u *UUID) Scan(src any) error { uuid.go
125 > if src == nil {
126 return nil
127 }
128 > guuid := &guuid.UUID{} uuid.go
129 > if err := guuid.Scan(src); err != nil {
130 return err
131 }
132 > *u = (*guuid)[:] uuid.go
133 > return nil
134 }
135
136 // Value implements sql.Valuer so that UUIDs can be written to databases
137 // transparently. This method returns a byte slice representation of uuid
138 > func (u UUID) Value() (driver.Value, error) { uuid.go
139 > return []byte(u), nil
140 > }
141
142 > func (u UUID) encodeHex(dst []byte) { uuid.go
143 > hex.Encode(dst, u[:4])
144 > dst[8] = '-'
145 > hex.Encode(dst[9:13], u[4:6])
146 > dst[13] = '-'
147 > hex.Encode(dst[14:18], u[6:8])
148 > dst[18] = '-'
149 > hex.Encode(dst[19:23], u[8:10])
150 > dst[23] = '-'
151 > hex.Encode(dst[24:], u[10:])
152 > }
go.temporal.io/server/common/rpc/interceptor/namespace_rate_limit.go 41 covered LOC · 16 ranges

Open complete file

58 pollWaitForToken dynamicconfig.BoolPropertyFnWithNamespaceFilter,
59 metricsHandler metrics.Handler,
60 > ) NamespaceRateLimitInterceptor { namespace_rate_limit.go
61 > return &NamespaceRateLimitInterceptorImpl{
62 > namespaceRegistry: namespaceRegistry,
63 > rateLimiter: rateLimiter,
64 > tokens: tokens,
65 > pollMethods: pollMethods,
66 > pollWaitForToken: pollWaitForToken,
67 > metricsHandler: metricsHandler,
68 > }
69 > }
70
71 func (ni *NamespaceRateLimitInterceptorImpl) Intercept(
74 info *grpc.UnaryServerInfo,
75 handler grpc.UnaryHandler,
76 > ) (any, error) { namespace_rate_limit.go
77 > if ns := MustGetNamespaceName(ni.namespaceRegistry, req); ns != namespace.EmptyName {
78 > method := info.FullMethod namespace_rate_limit.go
79 > if IsLongPollGetWorkflowExecutionHistoryRequest(req) {
80 > method = configs.PollWorkflowHistoryAPIName namespace_rate_limit.go
81 > } else if IsLongPollDescribeActivityExecutionRequest(req) { namespace_rate_limit.go
82 method = configs.PollActivityExecutionAPIName
83 }
84 > if ni.pollWaitForToken(ns.String()) { namespace_rate_limit.go
85 if _, ok := ni.pollMethods[info.FullMethod]; ok {
86 if err := ni.Wait(ctx, ns, method, headers.NewGRPCHeaderGetter(ctx)); err != nil {
140 }
141
142 > func (ni *NamespaceRateLimitInterceptorImpl) Allow(namespaceName namespace.Name, methodName string, headerGetter headers.HeaderGetter) error { namespace_rate_limit.go
143 > token, ok := ni.tokens[methodName]
144 > if !ok {
145 > token = NamespaceRateLimitDefaultToken
146 > }
147
148 > if !ni.rateLimiter.Allow(time.Now().UTC(), quotas.NewRequest( namespace_rate_limit.go
149 > methodName,
150 > token,
151 > namespaceName.String(),
152 > headerGetter.Get(headers.CallerTypeHeaderName),
153 > 0, // this interceptor layer does not throttle based on caller segment
154 > "", // this interceptor layer does not throttle based on call initiation
155 > )) {
156 return ErrNamespaceRateLimitServerBusy
157 }
158 > return nil namespace_rate_limit.go
159 }
160
161 func IsLongPollGetWorkflowExecutionHistoryRequest(
162 req any,
163 > ) bool { namespace_rate_limit.go
164 > switch request := req.(type) {
165 > case *workflowservice.GetWorkflowExecutionHistoryRequest: namespace_rate_limit.go
166 > return request.GetWaitNewEvent()
167 }
168 > return false namespace_rate_limit.go
169 }
170
171 func IsLongPollDescribeActivityExecutionRequest(
172 req any,
173 > ) bool { namespace_rate_limit.go
174 > switch request := req.(type) {
175 case *workflowservice.DescribeActivityExecutionRequest:
176 return len(request.GetLongPollToken()) > 0
177 }
178 > return false namespace_rate_limit.go
179 }
go.temporal.io/server/service/history/replication/task_fetcher.go 41 covered LOC · 7 ranges

Open complete file

93 clusterMetadata cluster.Metadata,
94 clientBean client.Bean,
95 > ) TaskFetcherFactory { task_fetcher.go
96 > return &taskFetcherFactoryImpl{
97 > clusterMetadata: clusterMetadata,
98 > clientBean: clientBean,
99 > config: config,
100 > fetchers: make(map[string]taskFetcher),
101 > status: common.DaemonStatusInitialized,
102 > logger: logger,
103 > }
104 > }
105
106 // Start starts the fetchers
107 > func (f *taskFetcherFactoryImpl) Start() { task_fetcher.go
108 > if !atomic.CompareAndSwapInt32(
109 > &f.status,
110 > common.DaemonStatusInitialized,
111 > common.DaemonStatusStarted,
112 > ) {
113 return
114 }
115
116 > f.listenClusterMetadataChange() task_fetcher.go
117 > f.logger.Info("Replication task fetchers started.")
118 }
119
120 // Stop stops the fetchers
121 > func (f *taskFetcherFactoryImpl) Stop() { task_fetcher.go
122 > if !atomic.CompareAndSwapInt32(
123 > &f.status,
124 > common.DaemonStatusStarted,
125 > common.DaemonStatusStopped,
126 > ) {
127 return
128 }
129
130 > f.clusterMetadata.UnRegisterMetadataChangeCallback(f) task_fetcher.go
131 > f.fetchersLock.Lock()
132 > defer f.fetchersLock.Unlock()
133 > for _, fetcher := range f.fetchers {
134 fetcher.Stop()
135 }
136 > f.logger.Info("Replication task fetchers stopped.") task_fetcher.go
137 }
138
162 }
163
164 > func (f *taskFetcherFactoryImpl) listenClusterMetadataChange() { task_fetcher.go
165 > f.clusterMetadata.RegisterMetadataChangeCallback(
166 > f,
167 > func(oldClusterMetadata map[string]*cluster.ClusterInformation, newClusterMetadata map[string]*cluster.ClusterInformation) {
168 > f.fetchersLock.Lock()
169 > defer f.fetchersLock.Unlock()
170 >
171 > currentCluster := f.clusterMetadata.GetCurrentClusterName()
172 > // Fetcher is lazy init. The callback only need to handle remove case.
173 > for clusterName, newClusterInfo := range newClusterMetadata {
174 > if clusterName == currentCluster {
175 > continue
176 }
177 if fetcher, ok := f.fetchers[clusterName]; ok {
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/task_queues.go 40 covered LOC · 8 ranges

Open complete file

47 row *sqlplugin.TaskQueuesRow,
48 v sqlplugin.MatchingTaskVersion,
49 > ) (sql.Result, error) { task_queues.go
50 > return mdb.conn.NamedExecContext(ctx,
51 > sqlplugin.SwitchTaskQueuesTable(createTaskQueueQry, v),
52 > row,
53 > )
54 > }
55
56 // UpdateTaskQueues updates a row in task_queues[_v2] table
59 row *sqlplugin.TaskQueuesRow,
60 v sqlplugin.MatchingTaskVersion,
61 > ) (sql.Result, error) { task_queues.go
62 > return mdb.conn.NamedExecContext(ctx,
63 > sqlplugin.SwitchTaskQueuesTable(updateTaskQueueQry, v),
64 > row,
65 > )
66 > }
67
68 // SelectFromTaskQueues reads one or more rows from task_queues[_v2] table
71 filter sqlplugin.TaskQueuesFilter,
72 v sqlplugin.MatchingTaskVersion,
73 > ) ([]sqlplugin.TaskQueuesRow, error) { task_queues.go
74 > switch {
75 > case filter.TaskQueueID != nil:
76 > if filter.RangeHashLessThanEqualTo != 0 || filter.RangeHashGreaterThanEqualTo != 0 {
77 return nil, serviceerror.NewInternal("range of hashes not supported for specific selection")
78 }
79 > return mdb.selectFromTaskQueues(ctx, filter, v) task_queues.go
80 case filter.RangeHashLessThanEqualTo != 0 && filter.PageSize != nil:
81 if filter.RangeHashLessThanEqualTo < filter.RangeHashGreaterThanEqualTo {
94 filter sqlplugin.TaskQueuesFilter,
95 v sqlplugin.MatchingTaskVersion,
96 > ) ([]sqlplugin.TaskQueuesRow, error) { task_queues.go
97 > var err error
98 > var row sqlplugin.TaskQueuesRow
99 > err = mdb.conn.GetContext(ctx,
100 > &row,
101 > sqlplugin.SwitchTaskQueuesTable(getTaskQueueQry, v),
102 > filter.RangeHash,
103 > filter.TaskQueueID,
104 > )
105 > if err != nil {
106 > return nil, err task_queues.go
107 > }
108 > return []sqlplugin.TaskQueuesRow{row}, nil task_queues.go
109 }
110
160 filter sqlplugin.TaskQueuesFilter,
161 v sqlplugin.MatchingTaskVersion,
162 > ) (int64, error) { task_queues.go
163 > var rangeID int64
164 > err := mdb.conn.GetContext(ctx,
165 > &rangeID,
166 > sqlplugin.SwitchTaskQueuesTable(lockTaskQueueQry, v),
167 > filter.RangeHash,
168 > filter.TaskQueueID,
169 > )
170 > return rangeID, err
171 > }
go.temporal.io/server/common/quotas/rate_limiter_impl.go 40 covered LOC · 10 ranges

Open complete file

24 // NewRateLimiter returns a new rate limiter that can handle dynamic
25 // configuration updates
26 > func NewRateLimiter(newRPS float64, newBurst int) *RateLimiterImpl { rate_limiter_impl.go
27 > limiter := rate.NewLimiter(rate.Limit(newRPS), newBurst)
28 > ts := clock.NewRealTimeSource()
29 > rl := &RateLimiterImpl{
30 > rps: newRPS,
31 > burst: newBurst,
32 > timeSource: ts,
33 > ClockedRateLimiter: NewClockedRateLimiter(limiter, ts),
34 > }
35 >
36 > return rl
37 > }
38
39 // SetRPS sets the rate of the rate limiter
47 }
48
49 > func (rl *RateLimiterImpl) Reserve() Reservation { rate_limiter_impl.go
50 > return rl.ClockedRateLimiter.Reserve()
51 > }
52
53 > func (rl *RateLimiterImpl) ReserveN(now time.Time, n int) Reservation { rate_limiter_impl.go
54 > return rl.ClockedRateLimiter.ReserveN(now, n)
55 > }
56
57 // SetRateBurst sets the rps & burst of the rate limiter
58 > func (rl *RateLimiterImpl) SetRateBurst(rps float64, burst int) { rate_limiter_impl.go
59 > rl.refreshInternalRateLimiterImpl(&rps, &burst)
60 > }
61
62 // Rate returns the rps for this rate limiter
87 newRate *float64,
88 newBurst *int,
90 > rl.Lock()
91 > defer rl.Unlock()
92 >
93 > refresh := false
94 >
95 > if newRate != nil && rl.rps != *newRate {
96 > rl.rps = *newRate rate_limiter_impl.go
97 > refresh = true
98 > }
99
100 > if newBurst != nil && rl.burst != *newBurst { rate_limiter_impl.go
101 > rl.burst = *newBurst rate_limiter_impl.go
102 > refresh = true
103 > }
104
105 > if refresh { rate_limiter_impl.go
106 > now := rl.timeSource.Now() rate_limiter_impl.go
107 > rl.SetLimitAt(now, rate.Limit(rl.rps))
108 > rl.SetBurstAt(now, rl.burst)
109 > }
110 }
111
go.temporal.io/server/service/history/events/cache.go 40 covered LOC · 11 ranges

Open complete file

60 logger log.Logger,
61 disabled bool,
62 > ) Cache { cache.go
63 > return newEventsCache(executionManager, handler, logger, config.EventsHostLevelCacheMaxSizeBytes(), config.EventsCacheTTL(), disabled)
64 > }
65
66 func NewShardLevelEventsCache(
70 logger log.Logger,
71 disabled bool,
72 > ) Cache { cache.go
73 > return newEventsCache(executionManager, handler, logger, config.EventsShardLevelCacheMaxSizeBytes(), config.EventsCacheTTL(), disabled)
74 > }
75
76 func newEventsCache(
81 ttl time.Duration,
82 disabled bool,
83 > ) *CacheImpl { cache.go
84 > opts := &cache.Options{}
85 > opts.TTL = ttl
86 >
87 > taggedMetricHandler := metricsHandler.WithTags(metrics.CacheTypeTag(metrics.EventsCacheTypeTagValue))
88 > return &CacheImpl{
89 > Cache: cache.NewWithMetrics(maxSize, opts, taggedMetricHandler),
90 > executionManager: executionManager,
91 > metricsHandler: taggedMetricHandler,
92 > logger: logger,
93 > disabled: disabled,
94 > }
95 > }
96
97 > func (e *CacheImpl) validateKey(key EventKey) bool { cache.go
98 > if len(key.NamespaceID) == 0 || len(key.WorkflowID) == 0 || len(key.RunID) == 0 || key.EventID < common.FirstEventID {
99 // This is definitely a bug, but just warn and don't crash so we can find anywhere this happens.
100 e.logger.Warn("one or more ids is invalid in event cache",
105 return false
106 }
107 > return true cache.go
108 }
109
144 }
145
146 > func (e *CacheImpl) PutEvent(key EventKey, event *historypb.HistoryEvent) { cache.go
147 > handler := e.metricsHandler.WithTags(metrics.OperationTag(metrics.EventsCachePutEventScope), metrics.NamespaceIDTag(key.NamespaceID.String()))
148 > metrics.CacheRequests.With(handler).Record(1)
149 > startTime := time.Now().UTC()
150 > defer func() { metrics.CacheLatency.With(handler).Record(time.Since(startTime)) }()
151
152 > if !e.validateKey(key) { cache.go
153 return
154 }
155 > e.put(key, event) cache.go
156 }
157
213 }
214
215 > func (e *CacheImpl) put(key EventKey, event *historypb.HistoryEvent) any { cache.go
216 > return e.Put(key, newHistoryEventCacheItem(event))
217 > }
218
219 var _ cache.SizeGetter = (*historyEventCacheItemImpl)(nil)
221 func newHistoryEventCacheItem(
222 event *historypb.HistoryEvent,
223 > ) *historyEventCacheItemImpl { cache.go
224 > return &historyEventCacheItemImpl{
225 > event: event,
226 > }
227 > }
228
229 > func (h *historyEventCacheItemImpl) CacheSize() int { cache.go
230 > return h.event.Size()
231 > }
go.temporal.io/server/chasm/lib/workflow/validator.go 39 covered LOC · 21 ranges

Open complete file

41 saMapperProvider searchattribute.MapperProvider,
42 saValidator *searchattribute.Validator,
43 > ) *RequestValidator { validator.go
44 > return &RequestValidator{
45 > config: config,
46 > saMapperProvider: saMapperProvider,
47 > saValidator: saValidator,
48 > }
49 > }
50
51 func (v *RequestValidator) ValidateWorkflowID(
52 workflowID string,
53 > ) error { validator.go
54 > if workflowID == "" {
55 return ErrWorkflowIDNotSet
56 }
57 > if len(workflowID) > v.config.maxIDLengthLimit() { validator.go
58 return serviceerror.NewInvalidArgumentf("WorkflowId exceeds maximum allowed length (%d/%d)", len(workflowID), v.config.maxIDLengthLimit())
59 }
60 > return nil validator.go
61 }
62
69 func (v *RequestValidator) ValidateWorkflowTimeouts(
70 request StartWorkflowTimeoutLikeRequest,
71 > ) error { validator.go
72 > if err := timestamp.ValidateAndCapProtoDuration(request.GetWorkflowExecutionTimeout()); err != nil {
73 return fmt.Errorf("%w cause: %v", errInvalidWorkflowExecutionTimeoutSeconds, err)
74 }
75
76 > if err := timestamp.ValidateAndCapProtoDuration(request.GetWorkflowRunTimeout()); err != nil { validator.go
77 return fmt.Errorf("%w cause: %v", errInvalidWorkflowRunTimeoutSeconds, err)
78 }
79
80 > if err := timestamp.ValidateAndCapProtoDuration(request.GetWorkflowTaskTimeout()); err != nil { validator.go
81 return fmt.Errorf("%w cause: %v", errInvalidWorkflowTaskTimeoutSeconds, err)
82 }
83
84 > return nil validator.go
85 }
86
87 > func (v *RequestValidator) ValidateRetryPolicy(namespaceName string, retryPolicy *commonpb.RetryPolicy) error { validator.go
88 > if retryPolicy == nil {
89 > // By default, if the user does not explicitly set a retry policy for a Workflow, do not perform any retries. validator.go
90 > return nil
91 > }
92
93 retrypolicy.EnsureDefaults(retryPolicy, v.config.defaultWorkflowRetrySettings(namespaceName))
98 cronSchedule string,
99 startDelay *durationpb.Duration,
100 > ) error { validator.go
101 > if len(cronSchedule) > 0 && startDelay != nil {
102 return ErrCronAndStartDelaySet
103 }
104
105 > if err := timestamp.ValidateAndCapProtoDuration(startDelay); err != nil { validator.go
106 return fmt.Errorf("%w cause: %v", ErrInvalidWorkflowStartDelaySeconds, err)
107 }
108
109 > return nil validator.go
110 }
111 func (v *RequestValidator) ValidateWorkflowIDReusePolicy(
112 reusePolicy enumspb.WorkflowIdReusePolicy,
113 conflictPolicy enumspb.WorkflowIdConflictPolicy,
114 > ) error { validator.go
115 > if conflictPolicy != enumspb.WORKFLOW_ID_CONFLICT_POLICY_UNSPECIFIED &&
116 > reusePolicy == enumspb.WORKFLOW_ID_REUSE_POLICY_TERMINATE_IF_RUNNING { //nolint:staticcheck // SA1019: kept for backwards compatibility
117 return errIncompatibleIDReusePolicyTerminateIfRunning
118 }
119 > if conflictPolicy == enumspb.WORKFLOW_ID_CONFLICT_POLICY_TERMINATE_EXISTING && validator.go
120 > reusePolicy == enumspb.WORKFLOW_ID_REUSE_POLICY_REJECT_DUPLICATE {
121 return errIncompatibleIDReusePolicyRejectDuplicate
122 }
123 > return nil validator.go
124 }
125
127 attributes *commonpb.SearchAttributes,
128 namespaceName string,
129 > ) (*commonpb.SearchAttributes, error) { validator.go
130 > sa, err := searchattribute.UnaliasFields(v.saMapperProvider, attributes, namespaceName)
131 > if err != nil {
132 return nil, err
133 }
134
135 > if err = v.ValidateSearchAttributes(sa, namespaceName); err != nil { validator.go
136 return nil, err
137 }
138 > return sa, nil validator.go
139 }
140
141 > func (v *RequestValidator) ValidateSearchAttributes(searchAttributes *commonpb.SearchAttributes, namespaceName string) error { validator.go
142 > if err := v.saValidator.Validate(searchAttributes, namespaceName); err != nil {
143 return err
144 }
145 > return v.saValidator.ValidateSize(searchAttributes, namespaceName) validator.go
146 }
147
go.temporal.io/server/service/history/shard/context_factory.go 39 covered LOC · 3 ranges

Open complete file

74 )
75
76 > func ContextFactoryProvider(params ContextFactoryParams) ContextFactory { context_factory.go
77 > return &contextFactoryImpl{
78 > ContextFactoryParams: &params,
79 > }
80 > }
81
82 func (c *contextFactoryImpl) CreateContext(
83 shardID int32,
84 closeCallback CloseCallback,
85 > ) (historyi.ControllableContext, error) { context_factory.go
86 > shard, err := newContext(
87 > shardID,
88 > c.EngineFactory,
89 > c.Config,
90 > c.PersistenceConfig,
91 > closeCallback,
92 > c.Logger,
93 > c.ThrottledLogger,
94 > c.PersistenceExecutionManager,
95 > c.PersistenceShardManager,
96 > c.ClientBean,
97 > c.HistoryClient,
98 > c.MetricsHandler,
99 > c.EventLogger,
100 > c.PayloadSerializer,
101 > c.TimeSource,
102 > c.NamespaceRegistry,
103 > c.SaProvider,
104 > c.SaMapperProvider,
105 > c.ClusterMetadata,
106 > c.ArchivalMetadata,
107 > c.HostInfoProvider,
108 > c.TaskCategoryRegistry,
109 > c.EventsCache,
110 > c.StateMachineRegistry,
111 > c.ChasmRegistry,
112 > c.ChasmWorkflowRegistry,
113 > c.EndpointRegistry,
114 > c.HandoverTrackerFactory,
115 > )
116 > if err != nil {
117 return nil, err
118 }
119 > shard.start() context_factory.go
120 > return shard, nil
121 }
go.temporal.io/server/api/contextpropagation/v1/message.pb.go 38 covered LOC · 5 ranges

Open complete file

35 }
36
37 > func (x *ContextMetadata) Reset() { message.pb.go
38 > *x = ContextMetadata{}
39 > mi := &file_temporal_server_api_contextpropagation_v1_message_proto_msgTypes[0]
40 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
41 > ms.StoreMessageInfo(mi)
42 > }
43
44 func (x *ContextMetadata) String() string {
48 func (*ContextMetadata) ProtoMessage() {}
49
50 > func (x *ContextMetadata) ProtoReflect() protoreflect.Message { message.pb.go
51 > mi := &file_temporal_server_api_contextpropagation_v1_message_proto_msgTypes[0]
52 > if x != nil {
53 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
54 > if ms.LoadMessageInfo() == nil {
55 > ms.StoreMessageInfo(mi)
56 > }
57 > return ms
58 }
59 return mi.MessageOf(x)
65 }
66
67 > func (x *ContextMetadata) GetEntries() map[string]string { message.pb.go
68 > if x != nil {
69 > return x.Entries
70 > }
71 return nil
72 }
109 }
110
111 > func init() { file_temporal_server_api_contextpropagation_v1_message_proto_init() } message.pb.go
112 > func file_temporal_server_api_contextpropagation_v1_message_proto_init() {
113 > if File_temporal_server_api_contextpropagation_v1_message_proto != nil {
114 return
115 }
116 > type x struct{} message.pb.go
117 > out := protoimpl.TypeBuilder{
118 > File: protoimpl.DescBuilder{
119 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
120 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_contextpropagation_v1_message_proto_rawDesc), len(file_temporal_server_api_contextpropagation_v1_message_proto_rawDesc)),
121 > NumEnums: 0,
122 > NumMessages: 2,
123 > NumExtensions: 0,
124 > NumServices: 0,
125 > },
126 > GoTypes: file_temporal_server_api_contextpropagation_v1_message_proto_goTypes,
127 > DependencyIndexes: file_temporal_server_api_contextpropagation_v1_message_proto_depIdxs,
128 > MessageInfos: file_temporal_server_api_contextpropagation_v1_message_proto_msgTypes,
129 > }.Build()
130 > File_temporal_server_api_contextpropagation_v1_message_proto = out.File
131 > file_temporal_server_api_contextpropagation_v1_message_proto_goTypes = nil
132 > file_temporal_server_api_contextpropagation_v1_message_proto_depIdxs = nil
133 }
go.temporal.io/server/api/deployment/v1/message.pb.go 38 covered LOC · 12 ranges

Open complete file

54 func (*WorkerDeploymentVersion) ProtoMessage() {}
55
56 > func (x *WorkerDeploymentVersion) ProtoReflect() protoreflect.Message { message.pb.go
57 > mi := &file_temporal_server_api_deployment_v1_message_proto_msgTypes[0]
58 > if x != nil {
59 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
60 if ms.LoadMessageInfo() == nil {
63 return ms
64 }
65 > return mi.MessageOf(x) message.pb.go
66 }
67
71 }
72
73 > func (x *WorkerDeploymentVersion) GetDeploymentName() string { message.pb.go
74 > if x != nil {
75 return x.DeploymentName
76 }
77 > return "" message.pb.go
78 }
79
80 > func (x *WorkerDeploymentVersion) GetBuildId() string { message.pb.go
81 > if x != nil {
82 return x.BuildId
83 }
84 > return "" message.pb.go
85 }
86
128 func (*DeploymentVersionData) ProtoMessage() {}
129
130 > func (x *DeploymentVersionData) ProtoReflect() protoreflect.Message { message.pb.go
131 > mi := &file_temporal_server_api_deployment_v1_message_proto_msgTypes[1]
132 > if x != nil {
133 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
134 if ms.LoadMessageInfo() == nil {
137 return ms
138 }
139 > return mi.MessageOf(x) message.pb.go
140 }
141
223 func (*WorkerDeploymentVersionData) ProtoMessage() {}
224
225 > func (x *WorkerDeploymentVersionData) ProtoReflect() protoreflect.Message { message.pb.go
226 > mi := &file_temporal_server_api_deployment_v1_message_proto_msgTypes[2]
227 > if x != nil {
228 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
229 if ms.LoadMessageInfo() == nil {
232 return ms
233 }
234 > return mi.MessageOf(x) message.pb.go
235 }
236
4626 }
4627
4628 > func init() { file_temporal_server_api_deployment_v1_message_proto_init() } message.pb.go
4629 > func file_temporal_server_api_deployment_v1_message_proto_init() {
4630 > if File_temporal_server_api_deployment_v1_message_proto != nil {
4631 return
4632 }
4633 > type x struct{} message.pb.go
4634 > out := protoimpl.TypeBuilder{
4635 > File: protoimpl.DescBuilder{
4636 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
4637 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_deployment_v1_message_proto_rawDesc), len(file_temporal_server_api_deployment_v1_message_proto_rawDesc)),
4638 > NumEnums: 0,
4639 > NumMessages: 75,
4640 > NumExtensions: 0,
4641 > NumServices: 0,
4642 > },
4643 > GoTypes: file_temporal_server_api_deployment_v1_message_proto_goTypes,
4644 > DependencyIndexes: file_temporal_server_api_deployment_v1_message_proto_depIdxs,
4645 > MessageInfos: file_temporal_server_api_deployment_v1_message_proto_msgTypes,
4646 > }.Build()
4647 > File_temporal_server_api_deployment_v1_message_proto = out.File
4648 > file_temporal_server_api_deployment_v1_message_proto_goTypes = nil
4649 > file_temporal_server_api_deployment_v1_message_proto_depIdxs = nil
4650 }
go.temporal.io/server/api/workflow/v1/message.pb.go 38 covered LOC · 12 ranges

Open complete file

57 func (*ParentExecutionInfo) ProtoMessage() {}
58
59 > func (x *ParentExecutionInfo) ProtoReflect() protoreflect.Message { message.pb.go
60 > mi := &file_temporal_server_api_workflow_v1_message_proto_msgTypes[0]
61 > if x != nil {
62 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
63 if ms.LoadMessageInfo() == nil {
66 return ms
67 }
68 > return mi.MessageOf(x) message.pb.go
69 }
70
102 }
103
104 > func (x *ParentExecutionInfo) GetClock() *v11.VectorClock { message.pb.go
105 > if x != nil {
106 return x.Clock
107 }
108 > return nil message.pb.go
109 }
110
143 func (*RootExecutionInfo) ProtoMessage() {}
144
145 > func (x *RootExecutionInfo) ProtoReflect() protoreflect.Message { message.pb.go
146 > mi := &file_temporal_server_api_workflow_v1_message_proto_msgTypes[1]
147 > if x != nil {
148 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
149 if ms.LoadMessageInfo() == nil {
152 return ms
153 }
154 > return mi.MessageOf(x) message.pb.go
155 }
156
160 }
161
162 > func (x *RootExecutionInfo) GetExecution() *v1.WorkflowExecution { message.pb.go
163 > if x != nil {
164 return x.Execution
165 }
166 > return nil message.pb.go
167 }
168
189 func (*BaseExecutionInfo) ProtoMessage() {}
190
191 > func (x *BaseExecutionInfo) ProtoReflect() protoreflect.Message { message.pb.go
192 > mi := &file_temporal_server_api_workflow_v1_message_proto_msgTypes[2]
193 > if x != nil {
194 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
195 if ms.LoadMessageInfo() == nil {
198 return ms
199 }
200 > return mi.MessageOf(x) message.pb.go
201 }
202
278 }
279
280 > func init() { file_temporal_server_api_workflow_v1_message_proto_init() } message.pb.go
281 > func file_temporal_server_api_workflow_v1_message_proto_init() {
282 > if File_temporal_server_api_workflow_v1_message_proto != nil {
283 return
284 }
285 > type x struct{} message.pb.go
286 > out := protoimpl.TypeBuilder{
287 > File: protoimpl.DescBuilder{
288 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
289 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_workflow_v1_message_proto_rawDesc), len(file_temporal_server_api_workflow_v1_message_proto_rawDesc)),
290 > NumEnums: 0,
291 > NumMessages: 3,
292 > NumExtensions: 0,
293 > NumServices: 0,
294 > },
295 > GoTypes: file_temporal_server_api_workflow_v1_message_proto_goTypes,
296 > DependencyIndexes: file_temporal_server_api_workflow_v1_message_proto_depIdxs,
297 > MessageInfos: file_temporal_server_api_workflow_v1_message_proto_msgTypes,
298 > }.Build()
299 > File_temporal_server_api_workflow_v1_message_proto = out.File
300 > file_temporal_server_api_workflow_v1_message_proto_goTypes = nil
301 > file_temporal_server_api_workflow_v1_message_proto_depIdxs = nil
302 }
go.temporal.io/server/chasm/lib/tests/library.go 38 covered LOC · 5 ranges

Open complete file

24 var Library = &library{}
25
26 > func (l *library) Name() string { library.go
27 > return libraryName
28 > }
29
30 > func (l *library) NexusServices() []*nexus.Service { library.go
31 > return []*nexus.Service{NewTestServiceNexusService()}
32 > }
33
34 > func (l *library) NexusServiceProcessors() []*chasm.NexusServiceProcessor { library.go
35 > return []*chasm.NexusServiceProcessor{NewTestServiceNexusServiceProcessor()}
36 > }
37
38 > func (l *library) Components() []*chasm.RegistrableComponent { library.go
39 > return []*chasm.RegistrableComponent{
40 > chasm.NewRegistrableComponent[*PayloadStore](
41 > componentName,
42 > chasm.WithBusinessIDAlias("PayloadStoreId"),
43 > chasm.WithSearchAttributes(
44 > PayloadTotalCountSearchAttribute,
45 > PayloadTotalSizeSearchAttribute,
46 > ExecutionStatusSearchAttribute,
47 > chasm.SearchAttributeTaskQueue,
48 > ),
49 > chasm.WithContextValues(map[any]any{
50 > componentCtxKey: componentCtxVal,
51 > }),
52 > ),
53 > }
54 > }
55
56 > func (l *library) Tasks() []*chasm.RegistrableTask { library.go
57 > return []*chasm.RegistrableTask{
58 > chasm.NewRegistrablePureTask(
59 > "payloadTTLPureTask",
60 > &PayloadTTLPureTaskHandler{},
61 > ),
62 > chasm.NewRegistrableSideEffectTask(
63 > "payloadTTLSideEffectTask",
64 > &PayloadTTLSideEffectTaskHandler{},
65 > ),
66 > }
67 > }
go.temporal.io/server/common/client_cache.go 38 covered LOC · 8 ranges

Open complete file

52 clientProvider clientProvider,
53 logger log.Logger,
54 > ) ClientCache { client_cache.go
55 >
56 > return &clientCacheImpl{
57 > keyResolver: keyResolver,
58 > clientProvider: clientProvider,
59 >
60 > clients: make(map[string]cachedEntry),
61 > logger: logger,
62 > }
63 > }
64
65 > func (c *clientCacheImpl) Lookup(key string, index int) (string, error) { client_cache.go
66 > return c.keyResolver.Lookup(key, index)
67 > }
68
69 func (c *clientCacheImpl) GetClientForKey(key string, index int) (any, error) {
75 }
76
77 > func (c *clientCacheImpl) GetClientForClientKey(clientKey string) (any, error) { client_cache.go
78 > c.cacheLock.RLock()
79 > entry, ok := c.clients[clientKey]
80 > c.cacheLock.RUnlock()
81 > if ok {
82 > return entry.client, nil
83 > }
84
85 > c.cacheLock.Lock() client_cache.go
86 > defer c.cacheLock.Unlock()
87 >
88 > entry, ok = c.clients[clientKey]
89 > if ok {
90 return entry.client, nil
91 }
92
93 > client, release, err := c.clientProvider(clientKey) client_cache.go
94 > if err != nil {
95 return nil, err
96 }
97 > c.clients[clientKey] = cachedEntry{client: client, release: release} client_cache.go
98 > return client, nil
99 }
100
131 }
132
133 > func (c *clientCacheImpl) EvictAll() { client_cache.go
134 > c.cacheLock.Lock()
135 > entries := c.clients
136 > c.clients = make(map[string]cachedEntry)
137 > c.cacheLock.Unlock()
138 >
139 > for _, entry := range entries {
140 > if entry.release != nil { client_cache.go
141 > if err := entry.release(); err != nil {
142 c.logger.Warn("Error releasing evicted client resource", tag.Error(err))
143 }
go.temporal.io/server/common/namespace/replication_resolver.go 38 covered LOC · 12 ranges

Open complete file

49 }
50
51 > func NewDefaultReplicationResolverFactory() ReplicationResolverFactory { replication_resolver.go
52 > return func(detail *persistencespb.NamespaceDetail) ReplicationResolver {
53 > // By convention, a namespace with non-zero failover version is a global namespace
54 > // This can be overridden by WithGlobalFlag mutation if needed
55 > isGlobal := detail.FailoverVersion != 0
56 > return &defaultReplicationResolver{
57 > replicationConfig: detail.ReplicationConfig,
58 > isGlobalNamespace: isGlobal,
59 > failoverVersion: detail.FailoverVersion,
60 > failoverNotificationVersion: detail.FailoverNotificationVersion,
61 > }
62 > }
63 }
64
65 > func (r *defaultReplicationResolver) ActiveClusterName(_ RoutingKey) string { replication_resolver.go
66 > if r.replicationConfig == nil {
67 return ""
68 }
69 > return r.replicationConfig.ActiveClusterName replication_resolver.go
70 }
71
72 > func (r *defaultReplicationResolver) ActiveInCluster(clusterName string) bool { replication_resolver.go
73 > if !r.IsGlobalNamespace() {
74 > // namespace is not a global namespace, meaning namespace is always replication_resolver.go
75 > // "active" within each cluster
76 > return true
77 > }
78 return r.replicationConfig.ActiveClusterName == clusterName
79 }
80
81 > func (r *defaultReplicationResolver) ClusterNames(businessID string) []string { replication_resolver.go
82 > if r.replicationConfig == nil {
83 return nil
84 }
85 // copy slice to preserve immutability
86 > out := make([]string, len(r.replicationConfig.Clusters)) replication_resolver.go
87 > copy(out, r.replicationConfig.Clusters)
88 > return out
89 }
90
91 > func (r *defaultReplicationResolver) ReplicationState(_ string) enumspb.ReplicationState { replication_resolver.go
92 > if r.replicationConfig == nil {
93 return enumspb.REPLICATION_STATE_UNSPECIFIED
94 }
95 > return r.replicationConfig.State replication_resolver.go
96 }
97
98 > func (r *defaultReplicationResolver) IsGlobalNamespace() bool { replication_resolver.go
99 > return r.isGlobalNamespace
100 > }
101
102 > func (r *defaultReplicationResolver) FailoverVersion(businessID string) int64 { replication_resolver.go
103 > return r.failoverVersion
104 > }
105
106 func (r *defaultReplicationResolver) FailoverNotificationVersion() int64 {
112 }
113
114 > func (r *defaultReplicationResolver) SetGlobalFlag(isGlobal bool) { replication_resolver.go
115 > r.isGlobalNamespace = isGlobal
116 > }
117
118 func (r *defaultReplicationResolver) SetActiveCluster(clusterName string) {
go.temporal.io/server/service/worker/dlq/workflow.go 38 covered LOC · 5 ranges

Open complete file

192 )
193
194 > func newComponent(params workerComponentParams) workercommon.WorkerComponent { workflow.go
195 > return &workerComponent{
196 > historyClient: params.HistoryClient,
197 > currentClusterName: string(params.CurrentClusterName),
198 > taskClientDialer: params.TaskClientDialer,
199 > }
200 > }
201
202 //revive:disable:import-shadowing this doesn't actually shadow imports because it's a method, not a function
449 }
450
451 > func (c *workerComponent) RegisterWorkflow(registry sdkworker.Registry) { workflow.go
452 > registry.RegisterWorkflowWithOptions(c.workflow, workflow.RegisterOptions{
453 > Name: WorkflowName,
454 > })
455 > }
456
457 > func (c *workerComponent) DedicatedWorkflowWorkerOptions() *workercommon.DedicatedWorkerOptions { workflow.go
458 > // use default worker
459 > return nil
460 > }
461
462 > func (c *workerComponent) RegisterActivities(registry sdkworker.Registry) { workflow.go
463 > registry.RegisterActivityWithOptions(c.deleteTasks, activity.RegisterOptions{
464 > Name: deleteTasksActivityName,
465 > })
466 > registry.RegisterActivityWithOptions(c.readTasks, activity.RegisterOptions{
467 > Name: readTasksActivityName,
468 > })
469 > registry.RegisterActivityWithOptions(c.reEnqueueTasks, activity.RegisterOptions{
470 > Name: reEnqueueTasksActivityName,
471 > })
472 > }
473
474 > func (c *workerComponent) DedicatedActivityWorkerOptions() *workercommon.DedicatedWorkerOptions { workflow.go
475 > return &workercommon.DedicatedWorkerOptions{
476 > TaskQueue: primitives.DLQActivityTQ,
477 > Options: sdkworker.Options{
478 > BackgroundActivityContext: headers.SetCallerType(
479 > context.Background(),
480 > headers.CallerTypePreemptable,
481 > ),
482 > },
483 > }
484 > }
485
486 // Dial implements [TaskClientDialer] by calling the [TaskClientDialerFn] with the cluster name.
go.temporal.io/server/common/membership/ringpop/hostinfo.go 37 covered LOC · 11 ranges

Open complete file

23
24 // newHostInfo creates a new *hostInfo instance
25 > func newHostInfo(addr string, labels map[string]string) *hostInfo { hostinfo.go
26 > return &hostInfo{
27 > addr: addr,
28 > labels: labels,
29 > labelsChecksum: checksumLabels(labels),
30 > }
31 > }
32
33 // GetAddress returns the ip:port address
34 > func (hi *hostInfo) GetAddress() string { hostinfo.go
35 > return hi.addr
36 > }
37
38 // Identity implements ringpop's Membership interface
39 > func (hi *hostInfo) Identity() string { hostinfo.go
40 > // For now, we just use the address as the identity.
41 > return hi.addr
42 > }
43
44 // Label implements ringpop's Membership interface
45 > func (hi *hostInfo) Label(key string) (string, bool) { hostinfo.go
46 > value, ok := hi.labels[key]
47 > return value, ok
48 > }
49
50 // summary returns a shorthand summary string suitable for logging.
51 > func (hi *hostInfo) summary() string { hostinfo.go
52 > var s strings.Builder
53 > s.WriteString(hi.GetAddress())
54 > for k, v := range hi.labels {
55 > switch k {
56 > case roleKey, portKey: hostinfo.go
57 // skip these, they can be determined from context
58 > default: hostinfo.go
59 > s.WriteString(fmt.Sprintf("[%s=%s]", k, v))
60 }
61 }
62 > return s.String() hostinfo.go
63 }
64
65 // checksumLabels returns a checksum of a labels map
66 > func checksumLabels(labels map[string]string) uint64 { hostinfo.go
67 > var c uint64
68 > for k, v := range labels {
69 > kfp := farm.Fingerprint64([]byte(k)) hostinfo.go
70 > vfp := farm.Fingerprint64([]byte(v))
71 > // use xor to combine different labels so that it comes out the same with any iteration
72 > // order, without needing to sort.
73 > c ^= kfp + bits.RotateLeft64(vfp, 3)
74 > }
75 > return c hostinfo.go
76 }
go.temporal.io/server/common/rpc/interceptor/caller_info.go 37 covered LOC · 10 ranges

Open complete file

20 func NewCallerInfoInterceptor(
21 namespaceRegistry namespace.Registry,
22 > ) *CallerInfoInterceptor { caller_info.go
23 > return &CallerInfoInterceptor{
24 > namespaceRegistry: namespaceRegistry,
25 > }
26 > }
27
28 func (i *CallerInfoInterceptor) Intercept(
31 info *grpc.UnaryServerInfo,
32 handler grpc.UnaryHandler,
33 > ) (any, error) { caller_info.go
34 > ctx = PopulateCallerInfo(
35 > ctx,
36 > func() string { return string(MustGetNamespaceName(i.namespaceRegistry, req)) },
37 > func() string { return api.MethodName(info.FullMethod) },
38 )
39
40 > return handler(ctx, req) caller_info.go
41 }
42
47 nsNameGetter func() string,
48 methodGetter func() string,
49 > ) context.Context { caller_info.go
50 > callerInfo := headers.GetCallerInfo(ctx)
51 >
52 > infoUpdated := false
53 >
54 > nsName := nsNameGetter()
55 > if callerInfo.CallerName != nsName {
56 > callerInfo.CallerName = nsName caller_info.go
57 > infoUpdated = true
58 > }
59
60 > _, isValidCallerType := headers.ValidCallerTypes[callerInfo.CallerType] caller_info.go
61 > if !isValidCallerType {
62 > callerInfo.CallerType = headers.CallerTypeAPI
63 > infoUpdated = true
64 > }
65
66 > if callerInfo.CallerType == headers.CallerTypeAPI || caller_info.go
67 > callerInfo.CallerType == headers.CallerTypeOperator {
68 > methodName := methodGetter()
69 > if callerInfo.CallOrigin != methodName {
70 > callerInfo.CallOrigin = methodName caller_info.go
71 > infoUpdated = true
72 > }
73 }
74
75 > if infoUpdated { caller_info.go
76 > ctx = headers.SetCallerInfo(ctx, callerInfo)
77 > }
78
79 > return ctx caller_info.go
80 }
go.temporal.io/server/components/nexusoperations/events.go 37 covered LOC · 18 ranges

Open complete file

17 }
18
19 > func (d ScheduledEventDefinition) Type() enumspb.EventType { events.go
20 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_SCHEDULED
21 > }
22
23 func (d ScheduledEventDefinition) Apply(root *hsm.Node, event *historypb.HistoryEvent) error {
41 }
42
43 > func (d CancelRequestedEventDefinition) Type() enumspb.EventType { events.go
44 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUESTED
45 > }
46
47 func (d CancelRequestedEventDefinition) Apply(root *hsm.Node, event *historypb.HistoryEvent) error {
64 }
65
66 > func (d CancelRequestCompletedEventDefinition) Type() enumspb.EventType { events.go
67 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUEST_COMPLETED
68 > }
69
70 func (d CancelRequestCompletedEventDefinition) Apply(root *hsm.Node, event *historypb.HistoryEvent) error {
98 }
99
100 > func (d CancelRequestFailedEventDefinition) Type() enumspb.EventType { events.go
101 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUEST_FAILED
102 > }
103
104 func (d CancelRequestFailedEventDefinition) Apply(root *hsm.Node, event *historypb.HistoryEvent) error {
133 }
134
135 > func (d StartedEventDefinition) Type() enumspb.EventType { events.go
136 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_STARTED
137 > }
138
139 func (d StartedEventDefinition) Apply(root *hsm.Node, event *historypb.HistoryEvent) error {
176 }
177
178 > func (d CompletedEventDefinition) Type() enumspb.EventType { events.go
179 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_COMPLETED
180 > }
181
182 func (d CompletedEventDefinition) CherryPick(root *hsm.Node, event *historypb.HistoryEvent, excludeTypes map[enumspb.ResetReapplyExcludeType]struct{}) error {
193 }
194
195 > func (d FailedEventDefinition) Type() enumspb.EventType { events.go
196 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_FAILED
197 > }
198
199 func (d FailedEventDefinition) Apply(root *hsm.Node, event *historypb.HistoryEvent) error {
225 }
226
227 > func (d CanceledEventDefinition) Type() enumspb.EventType { events.go
228 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCELED
229 > }
230
231 func (d CanceledEventDefinition) Apply(root *hsm.Node, event *historypb.HistoryEvent) error {
256 }
257
258 > func (d TimedOutEventDefinition) Type() enumspb.EventType { events.go
259 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_TIMED_OUT
260 > }
261
262 func (d TimedOutEventDefinition) Apply(root *hsm.Node, event *historypb.HistoryEvent) error {
280 }
281
282 > func RegisterEventDefinitions(reg *hsm.Registry) error { events.go
283 > if err := reg.RegisterEventDefinition(ScheduledEventDefinition{}); err != nil {
284 return err
285 }
286 > if err := reg.RegisterEventDefinition(CancelRequestedEventDefinition{}); err != nil { events.go
287 return err
288 }
289 > if err := reg.RegisterEventDefinition(CancelRequestCompletedEventDefinition{}); err != nil { events.go
290 return err
291 }
292 > if err := reg.RegisterEventDefinition(CancelRequestFailedEventDefinition{}); err != nil { events.go
293 return err
294 }
295 > if err := reg.RegisterEventDefinition(StartedEventDefinition{}); err != nil { events.go
296 return err
297 }
298 > if err := reg.RegisterEventDefinition(CompletedEventDefinition{}); err != nil { events.go
299 return err
300 }
301 > if err := reg.RegisterEventDefinition(FailedEventDefinition{}); err != nil { events.go
302 return err
303 }
304 > if err := reg.RegisterEventDefinition(CanceledEventDefinition{}); err != nil { events.go
305 return err
306 }
307 > return reg.RegisterEventDefinition(TimedOutEventDefinition{}) events.go
308 }
309
go.temporal.io/server/service/frontend/operator_handler.go 37 covered LOC · 3 ranges

Open complete file

92 func NewOperatorHandlerImpl(
93 args NewOperatorHandlerImplArgs,
94 > ) *OperatorHandlerImpl { operator_handler.go
95 >
96 > handler := &OperatorHandlerImpl{
97 > logger: args.Logger,
98 > status: common.DaemonStatusInitialized,
99 > config: args.config,
100 > sdkClientFactory: args.sdkClientFactory,
101 > metricsHandler: args.MetricsHandler,
102 > visibilityMgr: args.VisibilityMgr,
103 > saManager: args.SaManager,
104 > healthServer: args.healthServer,
105 > historyClient: args.historyClient,
106 > clusterMetadataManager: args.clusterMetadataManager,
107 > clusterMetadata: args.clusterMetadata,
108 > clientFactory: args.clientFactory,
109 > namespaceRegistry: args.namespaceRegistry,
110 > nexusEndpointClient: args.nexusEndpointClient,
111 > }
112 >
113 > return handler
114 > }
115
116 // Start starts the handler
117 > func (h *OperatorHandlerImpl) Start() { operator_handler.go
118 > if atomic.CompareAndSwapInt32(
119 > &h.status,
120 > common.DaemonStatusInitialized,
121 > common.DaemonStatusStarted,
122 > ) {
123 > h.healthServer.SetServingStatus(OperatorServiceName, healthpb.HealthCheckResponse_SERVING)
124 > }
125 }
126
127 // Stop stops the handler
128 > func (h *OperatorHandlerImpl) Stop() { operator_handler.go
129 > if atomic.CompareAndSwapInt32(
130 > &h.status,
131 > common.DaemonStatusStarted,
132 > common.DaemonStatusStopped,
133 > ) {
134 > h.healthServer.SetServingStatus(OperatorServiceName, healthpb.HealthCheckResponse_NOT_SERVING)
135 > }
136 }
137
go.temporal.io/server/service/history/workflow/timer_sequence.go 37 covered LOC · 10 ranges

Open complete file

61 func NewTimerSequence(
62 mutableState historyi.MutableState,
63 > ) *timerSequenceImpl { timer_sequence.go
64 > return &timerSequenceImpl{
65 > mutableState: mutableState,
66 > }
67 > }
68
69 > func (t *timerSequenceImpl) CreateNextUserTimer() (bool, error) { timer_sequence.go
70 >
71 > sequenceIDs := t.LoadAndSortUserTimers()
72 > if len(sequenceIDs) == 0 {
73 > return false, nil timer_sequence.go
74 > }
75
76 firstTimerTask := sequenceIDs[0]
107 }
108
109 > func (t *timerSequenceImpl) CreateNextActivityTimer() (bool, error) { timer_sequence.go
110 >
111 > sequenceIDs := t.LoadAndSortActivityTimers()
112 > if len(sequenceIDs) == 0 {
113 > return false, nil timer_sequence.go
114 > }
115
116 firstTimerTask := sequenceIDs[0]
156 }
157
158 > func (t *timerSequenceImpl) LoadAndSortUserTimers() []TimerSequenceID { timer_sequence.go
159 >
160 > pendingTimers := t.mutableState.GetPendingTimerInfos()
161 > timers := make(TimerSequenceIDs, 0, len(pendingTimers))
162 >
163 > for _, timerInfo := range pendingTimers {
164
165 if sequenceID := t.getUserTimerTimeout(
170 }
171
172 > sort.Sort(timers) timer_sequence.go
173 > return timers
174 }
175
176 > func (t *timerSequenceImpl) LoadAndSortActivityTimers() []TimerSequenceID { timer_sequence.go
177 > // there can be 4 timer per activity
178 > // see TimerType
179 > pendingActivities := t.mutableState.GetPendingActivityInfos()
180 > activityTimers := make(TimerSequenceIDs, 0, len(pendingActivities)*4)
181 >
182 > for _, activityInfo := range pendingActivities {
183 // skip activities that are paused
184 if activityInfo.Paused {
210 }
211
212 > sort.Sort(activityTimers) timer_sequence.go
213 > return activityTimers
214 }
215
381
382 // Len implements sort.Interface
383 > func (s TimerSequenceIDs) Len() int { timer_sequence.go
384 > return len(s)
385 > }
386
387 // Swap implements sort.Interface.
go.temporal.io/server/client/history/retryable_client_gen.go 36 covered LOC · 4 ranges

Open complete file

361 request *historyservice.GetWorkflowExecutionHistoryRequest,
362 opts ...grpc.CallOption,
363 > ) (*historyservice.GetWorkflowExecutionHistoryResponse, error) { retryable_client_gen.go
364 > var resp *historyservice.GetWorkflowExecutionHistoryResponse
365 > op := func(ctx context.Context) error {
366 > var err error
367 > resp, err = c.client.GetWorkflowExecutionHistory(ctx, request, opts...)
368 > return err
369 > }
370 > err := backoff.ThrottleRetryContext(ctx, op, c.policy, c.isRetryable)
371 > return resp, err
372 }
373
691 request *historyservice.RecordWorkflowTaskStartedRequest,
692 opts ...grpc.CallOption,
693 > ) (*historyservice.RecordWorkflowTaskStartedResponse, error) { retryable_client_gen.go
694 > var resp *historyservice.RecordWorkflowTaskStartedResponse
695 > op := func(ctx context.Context) error {
696 > var err error
697 > resp, err = c.client.RecordWorkflowTaskStarted(ctx, request, opts...)
698 > return err
699 > }
700 > err := backoff.ThrottleRetryContext(ctx, op, c.policy, c.isRetryable)
701 > return resp, err
702 }
703
886 request *historyservice.RespondWorkflowTaskCompletedRequest,
887 opts ...grpc.CallOption,
888 > ) (*historyservice.RespondWorkflowTaskCompletedResponse, error) { retryable_client_gen.go
889 > var resp *historyservice.RespondWorkflowTaskCompletedResponse
890 > op := func(ctx context.Context) error {
891 > var err error
892 > resp, err = c.client.RespondWorkflowTaskCompleted(ctx, request, opts...)
893 > return err
894 > }
895 > err := backoff.ThrottleRetryContext(ctx, op, c.policy, c.isRetryable)
896 > return resp, err
897 }
898
976 request *historyservice.StartWorkflowExecutionRequest,
977 opts ...grpc.CallOption,
978 > ) (*historyservice.StartWorkflowExecutionResponse, error) { retryable_client_gen.go
979 > var resp *historyservice.StartWorkflowExecutionResponse
980 > op := func(ctx context.Context) error {
981 > var err error
982 > resp, err = c.client.StartWorkflowExecution(ctx, request, opts...)
983 > return err
984 > }
985 > err := backoff.ThrottleRetryContext(ctx, op, c.policy, c.isRetryable)
986 > return resp, err
987 }
988
go.temporal.io/server/common/namespace/archival_config_state_machine.go 36 covered LOC · 18 ranges

Open complete file

37 )
38
39 > func NeverEnabledState() *ArchivalConfigState { archival_config_state_machine.go
40 > return &ArchivalConfigState{
41 > URI: "",
42 > State: enumspb.ARCHIVAL_STATE_DISABLED,
43 > }
44 > }
45
46 > func (e *ArchivalConfigEvent) Validate() error { archival_config_state_machine.go
47 > if len(e.DefaultURI) == 0 {
48 return errInvalidEvent
49 }
51 }
52
53 > func (s *ArchivalConfigState) validate() error { archival_config_state_machine.go
54 > if s.State == enumspb.ARCHIVAL_STATE_ENABLED && len(s.URI) == 0 {
55 return errInvalidState
56 }
58 }
59
61 e *ArchivalConfigEvent,
62 URIValidationFunc func(URI string) error,
63 > ) (nextState *ArchivalConfigState, changed bool, err error) { archival_config_state_machine.go
64 > defer func() {
65 > // ensure that any existing URI name was not mutated
66 > if nextState != nil && len(s.URI) != 0 && s.URI != nextState.URI {
67 nextState = nil
68 changed = false
72
73 // ensure that next state is valid
74 > if nextState != nil { archival_config_state_machine.go
75 > if nextStateErr := nextState.validate(); nextStateErr != nil {
76 nextState = nil
77 changed = false
81 }
82
83 > if nextState != nil && nextState.URI != "" { archival_config_state_machine.go
84 if validateURIErr := URIValidationFunc(nextState.URI); validateURIErr != nil {
85 nextState = nil
118 */
119
120 > stateURISet := len(s.URI) != 0 archival_config_state_machine.go
121 > eventURISet := len(e.URI) != 0
122 >
123 > // factor this case out to ensure that URI is immutable
124 > if stateURISet && eventURISet && s.URI != e.URI {
125 return nil, false, errURIUpdate
126 }
127
128 // state 1
129 > if s.State == enumspb.ARCHIVAL_STATE_ENABLED && stateURISet { archival_config_state_machine.go
130 if e.State == enumspb.ARCHIVAL_STATE_ENABLED && eventURISet {
131 return s, false, nil
155
156 // state 2
157 > if s.State == enumspb.ARCHIVAL_STATE_DISABLED && stateURISet { archival_config_state_machine.go
158 if e.State == enumspb.ARCHIVAL_STATE_ENABLED && eventURISet {
159 return &ArchivalConfigState{
183
184 // state 3
185 > if s.State == enumspb.ARCHIVAL_STATE_DISABLED && !stateURISet { archival_config_state_machine.go
186 > if e.State == enumspb.ARCHIVAL_STATE_ENABLED && eventURISet {
187 return &ArchivalConfigState{
188 State: enumspb.ARCHIVAL_STATE_ENABLED,
190 }, true, nil
191 }
192 > if e.State == enumspb.ARCHIVAL_STATE_ENABLED && !eventURISet { archival_config_state_machine.go
193 return &ArchivalConfigState{
194 State: enumspb.ARCHIVAL_STATE_ENABLED,
196 }, true, nil
197 }
198 > if e.State == enumspb.ARCHIVAL_STATE_DISABLED && eventURISet { archival_config_state_machine.go
199 return &ArchivalConfigState{
200 State: enumspb.ARCHIVAL_STATE_DISABLED,
202 }, true, nil
203 }
204 > if e.State == enumspb.ARCHIVAL_STATE_DISABLED && !eventURISet { archival_config_state_machine.go
205 > return s, false, nil
206 > }
207 if e.State == enumspb.ARCHIVAL_STATE_UNSPECIFIED && eventURISet {
208 return &ArchivalConfigState{
go.temporal.io/server/common/namespace/testconstructors.go 36 covered LOC · 8 ranges

Open complete file

13 config *persistencespb.NamespaceConfig,
14 targetCluster string,
15 > ) *Namespace { testconstructors.go
16 > detail := &persistencespb.NamespaceDetail{
17 > Info: ensureInfo(info),
18 > Config: ensureConfig(config),
19 > ReplicationConfig: &persistencespb.NamespaceReplicationConfig{
20 > ActiveClusterName: targetCluster,
21 > Clusters: []string{targetCluster},
22 > },
23 > FailoverVersion: common.EmptyVersion,
24 > }
25 > factory := NewDefaultReplicationResolverFactory()
26 > resolver := factory(detail)
27 > ns, _ := FromPersistentState(detail, resolver, WithGlobalFlag(false))
28 > return ns
29 > }
30
31 // NewNamespaceForTest returns an entry with test data
55 repConfig *persistencespb.NamespaceReplicationConfig,
56 failoverVersion int64,
57 > ) *Namespace { testconstructors.go
58 > detail := &persistencespb.NamespaceDetail{
59 > Info: ensureInfo(info),
60 > Config: ensureConfig(config),
61 > ReplicationConfig: ensureRepConfig(repConfig),
62 > FailoverVersion: failoverVersion,
63 > }
64 > factory := NewDefaultReplicationResolverFactory()
65 > resolver := factory(detail)
66 > ns, _ := FromPersistentState(detail, resolver, WithGlobalFlag(true))
67 > return ns
68 > }
69
70 > func ensureInfo(proto *persistencespb.NamespaceInfo) *persistencespb.NamespaceInfo { testconstructors.go
71 > if proto == nil {
72 return &persistencespb.NamespaceInfo{}
73 }
74 > return proto testconstructors.go
75 }
76
77 > func ensureConfig(proto *persistencespb.NamespaceConfig) *persistencespb.NamespaceConfig { testconstructors.go
78 > if proto == nil {
79 return &persistencespb.NamespaceConfig{}
80 }
81 > return proto testconstructors.go
82 }
83
84 > func ensureRepConfig(proto *persistencespb.NamespaceReplicationConfig) *persistencespb.NamespaceReplicationConfig { testconstructors.go
85 > if proto == nil {
86 return &persistencespb.NamespaceReplicationConfig{}
87 }
88 > return proto testconstructors.go
89 }
go.temporal.io/server/common/quotas/clocked_rate_limiter.go 36 covered LOC · 11 ranges

Open complete file

25 )
26
27 > func NewClockedRateLimiter(rateLimiter *rate.Limiter, timeSource clock.TimeSource) ClockedRateLimiter { clocked_rate_limiter.go
28 > return ClockedRateLimiter{
29 > rateLimiter: rateLimiter,
30 > timeSource: timeSource,
31 > recycleCh: make(chan struct{}),
32 > }
33 > }
34
35 > func (l ClockedRateLimiter) Allow() bool { clocked_rate_limiter.go
36 > return l.AllowN(l.timeSource.Now(), 1)
37 > }
38
39 > func (l ClockedRateLimiter) AllowN(now time.Time, token int) bool { clocked_rate_limiter.go
40 > return l.rateLimiter.AllowN(now, token)
41 > }
42
43 // ClockedReservation wraps a rate.Reservation with a clockwork.Clock. It is used to ensure that the reservation
48 }
49
50 > func (r ClockedReservation) OK() bool { clocked_rate_limiter.go
51 > return r.reservation.OK()
52 > }
53
54 > func (r ClockedReservation) Delay() time.Duration { clocked_rate_limiter.go
55 > return r.DelayFrom(r.timeSource.Now())
56 > }
57
58 > func (r ClockedReservation) DelayFrom(t time.Time) time.Duration { clocked_rate_limiter.go
59 > return r.reservation.DelayFrom(t)
60 > }
61
62 func (r ClockedReservation) Cancel() {
68 }
69
70 > func (l ClockedRateLimiter) Reserve() ClockedReservation { clocked_rate_limiter.go
71 > return l.ReserveN(l.timeSource.Now(), 1)
72 > }
73
74 > func (l ClockedRateLimiter) ReserveN(now time.Time, token int) ClockedReservation { clocked_rate_limiter.go
75 > reservation := l.rateLimiter.ReserveN(now, token)
76 > return ClockedReservation{reservation, l.timeSource}
77 > }
78
79 func (l ClockedRateLimiter) Wait(ctx context.Context) error {
142 }
143
144 > func (l ClockedRateLimiter) SetLimitAt(t time.Time, newLimit rate.Limit) { clocked_rate_limiter.go
145 > l.rateLimiter.SetLimitAt(t, newLimit)
146 > }
147
148 > func (l ClockedRateLimiter) SetBurstAt(t time.Time, newBurst int) { clocked_rate_limiter.go
149 > // Clamp burst to >=1 when rate is positive; burst=0 with rate=0 is allowed for pause.
150 > if newBurst < 1 && l.rateLimiter.Limit() > 0 {
151 newBurst = 1
152 }
153 > l.rateLimiter.SetBurstAt(t, newBurst) clocked_rate_limiter.go
154 }
155
go.temporal.io/server/common/tasks/execution_aware_scheduler.go 36 covered LOC · 7 ranges

Open complete file

50 metricsHandler metrics.Handler,
51 timeSource clock.TimeSource,
52 > ) *ExecutionAwareScheduler[T] { execution_aware_scheduler.go
53 > return &ExecutionAwareScheduler[T]{
54 > baseScheduler: baseScheduler,
55 > executionQueueScheduler: newExecutionQueueScheduler(
56 > options.MaxQueues,
57 > options.QueueTTL,
58 > options.QueueConcurrency,
59 > queueKeyFn,
60 > logger,
61 > metricsHandler,
62 > timeSource,
63 > ),
64 > queueKeyFn: queueKeyFn,
65 > options: options,
66 > logger: logger,
67 > }
68 > }
69
70 > func (s *ExecutionAwareScheduler[T]) Start() { execution_aware_scheduler.go
71 > s.baseScheduler.Start()
72 > // Always start the executionQueueScheduler regardless of current config.
73 > // The Enabled check gates task routing, so an idle scheduler has minimal
74 > // overhead. This ensures if the config changes from disabled to enabled,
75 > // tasks will be processed correctly.
76 > s.executionQueueScheduler.Start()
77 > }
78
79 > func (s *ExecutionAwareScheduler[T]) Stop() { execution_aware_scheduler.go
80 > s.baseScheduler.Stop()
81 > s.executionQueueScheduler.Stop()
82 > }
83
84 func (s *ExecutionAwareScheduler[T]) Submit(task T) {
92 }
93
94 > func (s *ExecutionAwareScheduler[T]) TrySubmit(task T) bool { execution_aware_scheduler.go
95 > if s.shouldRouteToExecutionQueueScheduler(task) {
96 if s.executionQueueScheduler.TrySubmit(task) {
97 return true
99 // executionQueueScheduler is full, fall through to base scheduler.
100 }
101 > return s.baseScheduler.TrySubmit(task) execution_aware_scheduler.go
102 }
103
122 }
123
124 > func (s *ExecutionAwareScheduler[T]) shouldRouteToExecutionQueueScheduler(task T) bool { execution_aware_scheduler.go
125 > if !s.options.Enabled() {
126 > return false execution_aware_scheduler.go
127 > }
128 return s.executionQueueScheduler.HasQueue(s.queueKeyFn(task))
129 }
go.temporal.io/server/service/history/statemachine_environment.go 36 covered LOC · 7 ranges

Open complete file

25 )
26
27 > func taskWorkflowKey(task tasks.Task) definition.WorkflowKey { statemachine_environment.go
28 > return definition.NewWorkflowKey(task.GetNamespaceID(), task.GetWorkflowID(), task.GetRunID())
29 > }
30
31 > func getTaskArchetypeID(task tasks.Task) chasm.ArchetypeID { statemachine_environment.go
32 > archetypeID := chasm.WorkflowArchetypeID
33 > if hasArchetypeID, ok := task.(tasks.HasArchetypeID); ok {
34 archetypeID = hasArchetypeID.GetArchetypeID()
35
48 workflowCache wcache.Cache,
49 task tasks.Task,
50 > ) (historyi.WorkflowContext, historyi.ReleaseWorkflowContextFunc, error) { statemachine_environment.go
51 > return getWorkflowExecutionContext(
52 > ctx,
53 > shardContext,
54 > workflowCache,
55 > taskWorkflowKey(task),
56 > getTaskArchetypeID(task),
57 > locks.PriorityLow,
58 > )
59 > }
60
61 func getWorkflowExecutionContext(
66 archetypeID chasm.ArchetypeID,
67 lockPriority locks.Priority,
68 > ) (historyi.WorkflowContext, historyi.ReleaseWorkflowContextFunc, error) { statemachine_environment.go
69 > if key.GetRunID() == "" {
70 return getCurrentWorkflowExecutionContext(
71 ctx,
79 }
80
81 > namespaceID := namespace.ID(key.GetNamespaceID()) statemachine_environment.go
82 > execution := &commonpb.WorkflowExecution{
83 > WorkflowId: key.GetWorkflowID(),
84 > RunId: key.GetRunID(),
85 > }
86 > // workflowCache will automatically use short context timeout when
87 > // locking workflow for all background calls, we don't need a separate context here
88 > weContext, release, err := workflowCache.GetOrCreateChasmExecution(
89 > ctx,
90 > shardContext,
91 > namespaceID,
92 > execution,
93 > archetypeID,
94 > lockPriority,
95 > )
96 > if common.IsContextDeadlineExceededErr(err) {
97 // TODO: make sure this doesn't count against our SLA if this happens while handling an API request.
98 err = consts.ErrResourceExhaustedBusyWorkflow
99 }
100 > return weContext, release, err statemachine_environment.go
101 }
102
go.temporal.io/server/service/history/tasks/key.go 36 covered LOC · 18 ranges

Open complete file

28 )
29
30 > func NewImmediateKey(taskID int64) Key { key.go
31 > return Key{
32 > FireTime: DefaultFireTime,
33 > TaskID: taskID,
34 > }
35 > }
36
37 > func NewKey(fireTime time.Time, taskID int64) Key { key.go
38 > return Key{
39 > FireTime: fireTime,
40 > TaskID: taskID,
41 > }
42 > }
43
44 func ValidateKey(key Key) error {
54 }
55
56 > func (left Key) CompareTo(right Key) int { key.go
57 > if left.FireTime.Before(right.FireTime) {
58 > return -1 key.go
59 > } else if left.FireTime.After(right.FireTime) { key.go
60 > return 1 key.go
61 > }
62
63 > if left.TaskID < right.TaskID { key.go
64 > return -1 key.go
65 > } else if left.TaskID > right.TaskID { key.go
66 > return 1 key.go
67 > }
68 > return 0 key.go
69 }
70
79 }
80
81 > func (k Key) Next() Key { key.go
82 > if k.TaskID == math.MaxInt64 {
83 if k.FireTime.UnixNano() == math.MaxInt64 {
84 panic("Key encountered positive overflow")
86 return NewKey(k.FireTime.Add(time.Nanosecond), 0)
87 }
88 > return NewKey(k.FireTime, k.TaskID+1) key.go
89 }
90
109 }
110
111 > func MinKey(this Key, that Key) Key { key.go
112 > if this.CompareTo(that) < 0 {
113 > return this key.go
114 > }
115 > return that key.go
116 }
117
118 > func MaxKey(this Key, that Key) Key { key.go
119 > if this.CompareTo(that) < 0 {
120 > return that key.go
121 > }
122 return this
123 }
go.temporal.io/server/api/common/v1/api_category.pb.go 35 covered LOC · 5 ranges

Open complete file

119 func (*ApiCategoryOptions) ProtoMessage() {}
120
121 > func (x *ApiCategoryOptions) ProtoReflect() protoreflect.Message { api_category.pb.go
122 > mi := &file_temporal_server_api_common_v1_api_category_proto_msgTypes[0]
123 > if x != nil {
124 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
125 > if ms.LoadMessageInfo() == nil {
126 > ms.StoreMessageInfo(mi)
127 > }
128 > return ms
129 }
130 > return mi.MessageOf(x) api_category.pb.go
131 }
132
136 }
137
138 > func (x *ApiCategoryOptions) GetCategory() ApiCategory { api_category.pb.go
139 > if x != nil {
140 > return x.Category
141 > }
142 return API_CATEGORY_UNSPECIFIED
143 }
204 }
205
206 > func init() { file_temporal_server_api_common_v1_api_category_proto_init() } api_category.pb.go
207 > func file_temporal_server_api_common_v1_api_category_proto_init() {
208 > if File_temporal_server_api_common_v1_api_category_proto != nil {
209 return
210 }
211 > type x struct{} api_category.pb.go
212 > out := protoimpl.TypeBuilder{
213 > File: protoimpl.DescBuilder{
214 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
215 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_common_v1_api_category_proto_rawDesc), len(file_temporal_server_api_common_v1_api_category_proto_rawDesc)),
216 > NumEnums: 1,
217 > NumMessages: 1,
218 > NumExtensions: 1,
219 > NumServices: 0,
220 > },
221 > GoTypes: file_temporal_server_api_common_v1_api_category_proto_goTypes,
222 > DependencyIndexes: file_temporal_server_api_common_v1_api_category_proto_depIdxs,
223 > EnumInfos: file_temporal_server_api_common_v1_api_category_proto_enumTypes,
224 > MessageInfos: file_temporal_server_api_common_v1_api_category_proto_msgTypes,
225 > ExtensionInfos: file_temporal_server_api_common_v1_api_category_proto_extTypes,
226 > }.Build()
227 > File_temporal_server_api_common_v1_api_category_proto = out.File
228 > file_temporal_server_api_common_v1_api_category_proto_goTypes = nil
229 > file_temporal_server_api_common_v1_api_category_proto_depIdxs = nil
230 }
go.temporal.io/server/api/persistence/v1/update.pb.go 35 covered LOC · 3 ranges

Open complete file

222 func (*UpdateInfo) ProtoMessage() {}
223
224 > func (x *UpdateInfo) ProtoReflect() protoreflect.Message { update.pb.go
225 > mi := &file_temporal_server_api_persistence_v1_update_proto_msgTypes[3]
226 > if x != nil {
227 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
228 if ms.LoadMessageInfo() == nil {
231 return ms
232 }
233 > return mi.MessageOf(x) update.pb.go
234 }
235
422 }
423
424 > func init() { file_temporal_server_api_persistence_v1_update_proto_init() } update.pb.go
425 > func file_temporal_server_api_persistence_v1_update_proto_init() {
426 > if File_temporal_server_api_persistence_v1_update_proto != nil {
427 > return
428 > }
429 > file_temporal_server_api_persistence_v1_hsm_proto_init()
430 > file_temporal_server_api_persistence_v1_update_proto_msgTypes[0].OneofWrappers = []any{
431 > (*UpdateAdmissionInfo_HistoryPointer_)(nil),
432 > }
433 > file_temporal_server_api_persistence_v1_update_proto_msgTypes[3].OneofWrappers = []any{
434 > (*UpdateInfo_Acceptance)(nil),
435 > (*UpdateInfo_Completion)(nil),
436 > (*UpdateInfo_Admission)(nil),
437 > }
438 > type x struct{}
439 > out := protoimpl.TypeBuilder{
440 > File: protoimpl.DescBuilder{
441 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
442 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_update_proto_rawDesc), len(file_temporal_server_api_persistence_v1_update_proto_rawDesc)),
443 > NumEnums: 0,
444 > NumMessages: 5,
445 > NumExtensions: 0,
446 > NumServices: 0,
447 > },
448 > GoTypes: file_temporal_server_api_persistence_v1_update_proto_goTypes,
449 > DependencyIndexes: file_temporal_server_api_persistence_v1_update_proto_depIdxs,
450 > MessageInfos: file_temporal_server_api_persistence_v1_update_proto_msgTypes,
451 > }.Build()
452 > File_temporal_server_api_persistence_v1_update_proto = out.File
453 > file_temporal_server_api_persistence_v1_update_proto_goTypes = nil
454 > file_temporal_server_api_persistence_v1_update_proto_depIdxs = nil
455 }
go.temporal.io/server/chasm/lib/nexusoperation/config.go 35 covered LOC · 2 ranges

Open complete file

160 }
161
162 > func (cfg RetryPolicyConfig) build() backoff.RetryPolicy { config.go
163 > return backoff.NewExponentialRetryPolicy(cfg.InitialInterval).
164 > WithMaximumInterval(cfg.MaxInterval).
165 > WithExpirationInterval(backoff.NoInterval)
166 > }
167
168 var defaultRetryPolicyConfig = RetryPolicyConfig{
248 }
249
250 > func configProvider(dc *dynamicconfig.Collection, cfg *config.Persistence) *Config { config.go
251 > return &Config{
252 > Enabled: Enabled.Get(dc),
253 > EnableChasm: dynamicconfig.EnableChasm.Get(dc),
254 > EnableChasmNexusWorkflowOperations: EnableChasmWorkflowOperations.Get(dc),
255 > NumHistoryShards: cfg.NumHistoryShards,
256 > LongPollBuffer: LongPollBuffer.Get(dc),
257 > LongPollTimeout: LongPollTimeout.Get(dc),
258 > RequestTimeout: RequestTimeout.Get(dc),
259 > MinRequestTimeout: MinRequestTimeout.Get(dc),
260 > MaxConcurrentOperationsPerWorkflow: MaxConcurrentOperationsPerWorkflow.Get(dc),
261 > MaxServiceNameLength: MaxServiceNameLength.Get(dc),
262 > MaxOperationNameLength: MaxOperationNameLength.Get(dc),
263 > MaxOperationTokenLength: MaxOperationTokenLength.Get(dc),
264 > MaxOperationHeaderSize: MaxOperationHeaderSize.Get(dc),
265 > DisallowedOperationHeaders: DisallowedOperationHeaders.Get(dc),
266 > MaxOperationScheduleToCloseTimeout: MaxOperationScheduleToCloseTimeout.Get(dc),
267 > PayloadSizeLimit: dynamicconfig.BlobSizeLimitError.Get(dc),
268 > PayloadSizeLimitWarn: dynamicconfig.BlobSizeLimitWarn.Get(dc),
269 > MaxUserMetadataSummarySize: dynamicconfig.MaxUserMetadataSummarySize.Get(dc),
270 > MaxUserMetadataDetailsSize: dynamicconfig.MaxUserMetadataDetailsSize.Get(dc),
271 > CallbackURLTemplate: CallbackURLTemplate.Get(dc),
272 > UseSystemCallbackURL: UseSystemCallbackURL.Get(dc),
273 > UseNewFailureWireFormat: UseNewFailureWireFormat.Get(dc),
274 > VisibilityMaxPageSize: dynamicconfig.FrontendVisibilityMaxPageSize.Get(dc),
275 > MaxIDLengthLimit: dynamicconfig.MaxIDLengthLimit.Get(dc),
276 > MaxReasonLength: MaxReasonLength.Get(dc),
277 > RetryPolicy: RetryPolicy.Get(dc),
278 > }
279 > }
go.temporal.io/server/client/matching/metric_client_gen.go 35 covered LOC · 10 ranges

Open complete file

28 request *matchingservice.CancelOutstandingPollRequest,
29 opts ...grpc.CallOption,
30 > ) (_ *matchingservice.CancelOutstandingPollResponse, retError error) { metric_client_gen.go
31 >
32 > metricsHandler, startTime := c.startMetricsRecording(ctx, "MatchingClientCancelOutstandingPoll")
33 > defer func() {
34 > c.finishMetricsRecording(metricsHandler, startTime, retError)
35 > }()
36
37 > return c.client.CancelOutstandingPoll(ctx, request, opts...) metric_client_gen.go
38 }
39
224 request *matchingservice.ForceUnloadTaskQueuePartitionRequest,
225 opts ...grpc.CallOption,
226 > ) (_ *matchingservice.ForceUnloadTaskQueuePartitionResponse, retError error) { metric_client_gen.go
227 >
228 > metricsHandler, startTime := c.startMetricsRecording(ctx, "MatchingClientForceUnloadTaskQueuePartition")
229 > defer func() {
230 > c.finishMetricsRecording(metricsHandler, startTime, retError)
231 > }()
232
233 > return c.client.ForceUnloadTaskQueuePartition(ctx, request, opts...) metric_client_gen.go
234 }
235
252 request *matchingservice.GetTaskQueueUserDataRequest,
253 opts ...grpc.CallOption,
254 > ) (_ *matchingservice.GetTaskQueueUserDataResponse, retError error) { metric_client_gen.go
255 >
256 > metricsHandler, startTime := c.startMetricsRecording(ctx, "MatchingClientGetTaskQueueUserData")
257 > defer func() {
258 > c.finishMetricsRecording(metricsHandler, startTime, retError)
259 > }()
260
261 > return c.client.GetTaskQueueUserData(ctx, request, opts...) metric_client_gen.go
262 }
263
294 request *matchingservice.ListNexusEndpointsRequest,
295 opts ...grpc.CallOption,
296 > ) (_ *matchingservice.ListNexusEndpointsResponse, retError error) { metric_client_gen.go
297 >
298 > metricsHandler, startTime := c.startMetricsRecording(ctx, "MatchingClientListNexusEndpoints")
299 > defer func() {
300 > c.finishMetricsRecording(metricsHandler, startTime, retError)
301 > }()
302
303 > return c.client.ListNexusEndpoints(ctx, request, opts...) metric_client_gen.go
304 }
305
336 request *matchingservice.RecordWorkerHeartbeatRequest,
337 opts ...grpc.CallOption,
338 > ) (_ *matchingservice.RecordWorkerHeartbeatResponse, retError error) { metric_client_gen.go
339 >
340 > metricsHandler, startTime := c.startMetricsRecording(ctx, "MatchingClientRecordWorkerHeartbeat")
341 > defer func() {
342 > c.finishMetricsRecording(metricsHandler, startTime, retError)
343 > }()
344
345 > return c.client.RecordWorkerHeartbeat(ctx, request, opts...) metric_client_gen.go
346 }
347
go.temporal.io/server/common/authorization/interceptor.go 35 covered LOC · 10 ranges

Open complete file

56
57 // TLSInfoFromContext extracts TLS information from the context's peer value.
58 > func TLSInfoFromContext(ctx context.Context) *credentials.TLSInfo { interceptor.go
59 > p, ok := peer.FromContext(ctx)
60 > if !ok {
61 return nil
62 }
63 > if tlsInfo, ok := p.AuthInfo.(credentials.TLSInfo); ok { interceptor.go
64 return &tlsInfo
65 }
66 > return nil interceptor.go
67 }
68
110 enablePrincipalPropagation dynamicconfig.BoolPropertyFnWithNamespaceFilter,
111 disableStreamingAuthorizer dynamicconfig.BoolPropertyFn,
112 > ) *Interceptor { interceptor.go
113 > return &Interceptor{
114 > claimMapper: claimMapper,
115 > authorizer: authorizer,
116 > logger: logger,
117 > namespaceChecker: namespaceChecker,
118 > metricsHandler: metricsHandler,
119 > authHeaderName: cmp.Or(authHeaderName, defaultAuthHeaderName),
120 > authExtraHeaderName: cmp.Or(authExtraHeaderName, defaultAuthExtraHeaderName),
121 > audienceGetter: audienceGetter,
122 > exposeAuthorizerErrors: exposeAuthorizerErrors,
123 > enableCrossNamespaceCommands: enableCrossNamespaceCommands,
124 > enablePrincipalPropagation: enablePrincipalPropagation,
125 > disableStreamingAuthorizer: disableStreamingAuthorizer,
126 > }
127 > }
128
129 func (a *Interceptor) Intercept(
132 info *grpc.UnaryServerInfo,
133 handler grpc.UnaryHandler,
134 > ) (any, error) { interceptor.go
135 > tlsConnection := TLSInfoFromContext(ctx)
136 >
137 > authInfo := a.GetAuthInfo(tlsConnection, headers.NewGRPCHeaderGetter(ctx), func() string {
138 if a.audienceGetter != nil {
139 return a.audienceGetter.Audience(ctx, req, info)
142 })
143
144 > var claims *Claims interceptor.go
145 > if authInfo != nil {
146 var err error
147 claims, err = a.GetClaims(authInfo)
156 // Always strip inbound principal headers to prevent external callers from
157 // spoofing principal identity, regardless of whether the authorizer is enabled.
158 > ctx = headers.StripPrincipal(ctx) interceptor.go
159 >
160 > if a.authorizer != nil {
161 var namespace string
162 requestWithNamespace, ok := req.(hasNamespace)
249 // Returns nil if either the policy's claimMapper or authorizer are nil or when there is no auth information in the
250 // provided TLS info or headers.
251 > func (a *Interceptor) GetAuthInfo(tlsConnection *credentials.TLSInfo, header headers.HeaderGetter, audienceGetter func() string) *AuthInfo { interceptor.go
252 > if a.claimMapper == nil || a.authorizer == nil {
253 > return nil interceptor.go
254 > }
255 var tlsSubject *pkix.Name
256 var authHeader string
go.temporal.io/server/service/frontend/nexus_completion_http_handler.go 35 covered LOC · 4 ranges

Open complete file

85 forwardingClients *cluster.FrontendHTTPClientCache,
86 httpTraceProvider commonnexus.HTTPClientTraceProvider,
87 > ) *nexusCompletionHandler { nexus_completion_http_handler.go
88 > return &nexusCompletionHandler{
89 > ClusterMetadata: clusterMetadata,
90 > NamespaceRegistry: namespaceRegistry,
91 > Logger: logger,
92 > MetricsHandler: metricsHandler,
93 > Config: serviceConfig,
94 > CallbackTokenGenerator: callbackTokenGenerator,
95 > HistoryClient: historyClient,
96 > TelemetryInterceptor: telemetryInterceptor,
97 > RequestErrorHandler: requestErrorHandler,
98 > NamespaceValidationInterceptor: namespaceValidationInterceptor,
99 > NamespaceRateLimitInterceptor: namespaceRateLimitInterceptor,
100 > NamespaceConcurrencyLimitInterceptor: namespaceConcurrencyLimitInterceptor,
101 > RateLimitInterceptor: rateLimitInterceptor,
102 > AuthInterceptor: authInterceptor,
103 > RedirectionInterceptor: redirectionInterceptor,
104 > ForwardingClients: forwardingClients,
105 > HTTPTraceProvider: httpTraceProvider,
106 > clientVersionChecker: headers.NewDefaultVersionChecker(),
107 > preProcessErrorsCounter: metricsHandler.Counter(metrics.NexusCompletionRequestPreProcessErrors.Name()),
108 > }
109 > }
110
111 > func newNexusCompletionHTTPHandler(handler *nexusCompletionHandler, logger log.Logger) *nexusCompletionHTTPHandler { nexus_completion_http_handler.go
112 > return &nexusCompletionHTTPHandler{
113 > httpHandler: nexusrpc.NewCompletionHTTPHandler(nexusrpc.CompletionHandlerOptions{
114 > Handler: handler,
115 > Logger: log.NewSlogLogger(logger),
116 > Serializer: commonnexus.PayloadSerializer,
117 > }),
118 > }
119 > }
120
121 // CompleteOperation implements nexus.CompletionHandler.
393 }
394
395 > func (h *nexusCompletionHTTPHandler) RegisterRoutes(r *mux.Router) { nexus_completion_http_handler.go
396 > r.Path("/" + commonnexus.RouteCompletionCallback.Representation()).HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
397 r.Body = http.MaxBytesReader(w, r.Body, rpc.MaxNexusAPIRequestBodyBytes)
398 h.httpHandler.ServeHTTP(w, r)
399 })
400 > r.Path(commonnexus.PathCompletionCallbackNoIdentifier).HandlerFunc(func(w http.ResponseWriter, r *http.Request) { nexus_completion_http_handler.go
401 r.Body = http.MaxBytesReader(w, r.Body, rpc.MaxNexusAPIRequestBodyBytes)
402 h.httpHandler.ServeHTTP(w, r)
go.temporal.io/server/api/metrics/v1/message.pb.go 34 covered LOC · 4 ranges

Open complete file

30 }
31
32 > func (x *Baggage) Reset() { message.pb.go
33 > *x = Baggage{}
34 > mi := &file_temporal_server_api_metrics_v1_message_proto_msgTypes[0]
35 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
36 > ms.StoreMessageInfo(mi)
37 > }
38
39 func (x *Baggage) String() string {
43 func (*Baggage) ProtoMessage() {}
44
45 > func (x *Baggage) ProtoReflect() protoreflect.Message { message.pb.go
46 > mi := &file_temporal_server_api_metrics_v1_message_proto_msgTypes[0]
47 > if x != nil {
48 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
49 > if ms.LoadMessageInfo() == nil {
50 > ms.StoreMessageInfo(mi)
51 > }
52 > return ms
53 }
54 return mi.MessageOf(x)
104 }
105
106 > func init() { file_temporal_server_api_metrics_v1_message_proto_init() } message.pb.go
107 > func file_temporal_server_api_metrics_v1_message_proto_init() {
108 > if File_temporal_server_api_metrics_v1_message_proto != nil {
109 return
110 }
111 > type x struct{} message.pb.go
112 > out := protoimpl.TypeBuilder{
113 > File: protoimpl.DescBuilder{
114 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
115 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_metrics_v1_message_proto_rawDesc), len(file_temporal_server_api_metrics_v1_message_proto_rawDesc)),
116 > NumEnums: 0,
117 > NumMessages: 2,
118 > NumExtensions: 0,
119 > NumServices: 0,
120 > },
121 > GoTypes: file_temporal_server_api_metrics_v1_message_proto_goTypes,
122 > DependencyIndexes: file_temporal_server_api_metrics_v1_message_proto_depIdxs,
123 > MessageInfos: file_temporal_server_api_metrics_v1_message_proto_msgTypes,
124 > }.Build()
125 > File_temporal_server_api_metrics_v1_message_proto = out.File
126 > file_temporal_server_api_metrics_v1_message_proto_goTypes = nil
127 > file_temporal_server_api_metrics_v1_message_proto_depIdxs = nil
128 }
go.temporal.io/server/chasm/lib/nexusoperation/operation_tasks.go 34 covered LOC · 5 ranges

Open complete file

52 }
53
54 > func newOperationInvocationTaskHandler(opts operationInvocationTaskHandlerOptions) *operationInvocationTaskHandler { operation_tasks.go
55 > return &operationInvocationTaskHandler{
56 > nexusTaskHandlerBase: opts.toBase(),
57 > callbackTokenGenerator: opts.CallbackTokenGenerator,
58 > }
59 > }
60
61 func (h *operationInvocationTaskHandler) Validate(
264 }
265
266 > func newOperationBackoffTaskHandler(opts operationTaskHandlerOptions) *operationBackoffTaskHandler { operation_tasks.go
267 > return &operationBackoffTaskHandler{
268 > config: opts.Config,
269 > metricsHandler: opts.MetricsHandler,
270 > logger: opts.Logger,
271 > }
272 > }
273
274 func (h *operationBackoffTaskHandler) Validate(
298 }
299
300 > func newOperationScheduleToStartTimeoutTaskHandler(opts operationTaskHandlerOptions) *operationScheduleToStartTimeoutTaskHandler { operation_tasks.go
301 > return &operationScheduleToStartTimeoutTaskHandler{
302 > config: opts.Config,
303 > metricsHandler: opts.MetricsHandler,
304 > logger: opts.Logger,
305 > }
306 > }
307
308 func (h *operationScheduleToStartTimeoutTaskHandler) Validate(
339 }
340
341 > func newOperationStartToCloseTimeoutTaskHandler(opts operationTaskHandlerOptions) *operationStartToCloseTimeoutTaskHandler { operation_tasks.go
342 > return &operationStartToCloseTimeoutTaskHandler{
343 > config: opts.Config,
344 > metricsHandler: opts.MetricsHandler,
345 > logger: opts.Logger,
346 > }
347 > }
348
349 func (h *operationStartToCloseTimeoutTaskHandler) Validate(
380 }
381
382 > func newOperationScheduleToCloseTimeoutTaskHandler(opts operationTaskHandlerOptions) *operationScheduleToCloseTimeoutTaskHandler { operation_tasks.go
383 > return &operationScheduleToCloseTimeoutTaskHandler{
384 > config: opts.Config,
385 > metricsHandler: opts.MetricsHandler,
386 > logger: opts.Logger,
387 > }
388 > }
389
390 func (h *operationScheduleToCloseTimeoutTaskHandler) Validate(
go.temporal.io/server/common/backoff/cron.go 34 covered LOC · 14 ranges

Open complete file

13
14 // ValidateSchedule validates a cron schedule spec
15 > func ValidateSchedule(cronSchedule string) error { cron.go
16 > if cronSchedule == "" {
17 > return nil cron.go
18 > }
19 > schedule, err := cron.ParseStandard(cronSchedule) cron.go
20 > if err != nil {
21 return serviceerror.NewInvalidArgument("invalid CronSchedule.")
22 }
23 > nextTime := schedule.Next(time.Now().UTC()) cron.go
24 > if nextTime.IsZero() {
25 // no time can be found to satisfy the schedule
26 return serviceerror.NewInvalidArgument("invalid CronSchedule, no time can be found to satisfy the schedule")
27 }
28 > return nil cron.go
29 }
30
31 // GetBackoffForNextSchedule calculates the backoff time for the next run given
32 // a cronSchedule, current scheduled time, and now.
33 > func GetBackoffForNextSchedule(cronSchedule string, scheduledTime time.Time, now time.Time) time.Duration { cron.go
34 > if len(cronSchedule) == 0 {
35 > return NoBackoff cron.go
36 > }
37
38 > schedule, err := cron.ParseStandard(cronSchedule) cron.go
39 > if err != nil {
40 return NoBackoff
41 }
42
43 > scheduledUTCTime := scheduledTime.UTC() cron.go
44 > nowUTC := now.UTC()
45 >
46 > var nextScheduleTime time.Time
47 > if nowUTC.Before(scheduledUTCTime) {
48 nextScheduleTime = scheduledUTCTime
49 > } else { cron.go
50 > nextScheduleTime = schedule.Next(scheduledUTCTime) cron.go
51 > // Calculate the next schedule start time which is nearest to now (right after now).
52 > for !nextScheduleTime.IsZero() && nextScheduleTime.Before(nowUTC) {
53 nextScheduleTime = schedule.Next(nextScheduleTime)
54 }
55 }
56 > if nextScheduleTime.IsZero() { cron.go
57 // no time can be found to satisfy the schedule
58 return NoBackoff
59 }
60
61 > backoffInterval := nextScheduleTime.Sub(nowUTC) cron.go
62 > roundedInterval := time.Second * time.Duration(convert.Int64Ceil(backoffInterval.Seconds()))
63 > return roundedInterval
64 }
65
66 // GetBackoffForNextScheduleNonNegative calculates the backoff time and ensures a non-negative duration.
67 > func GetBackoffForNextScheduleNonNegative(cronSchedule string, scheduledTime time.Time, now time.Time) time.Duration { cron.go
68 > backoffDuration := GetBackoffForNextSchedule(cronSchedule, scheduledTime, now)
69 > if backoffDuration == NoBackoff || backoffDuration < 0 {
70 > backoffDuration = 0
71 > }
72 > return backoffDuration
73 }
go.temporal.io/server/common/persistence/sql/execution_state_non_map.go 34 covered LOC · 11 ranges

Open complete file

22 workflowID string,
23 runID primitives.UUID,
25 >
26 > if len(signalRequestedIDs) > 0 {
27 rows := make([]sqlplugin.SignalsRequestedSetsRow, 0, len(signalRequestedIDs))
28 for signalRequestedID := range signalRequestedIDs {
40 }
41
42 > if len(deleteIDs) > 0 { execution_state_non_map.go
43 if _, err := tx.DeleteFromSignalsRequestedSets(ctx, sqlplugin.SignalsRequestedSetsFilter{
44 ShardID: shardID,
61 workflowID string,
62 runID primitives.UUID,
63 > ) ([]string, error) { execution_state_non_map.go
64 >
65 > rows, err := db.SelectAllFromSignalsRequestedSets(ctx, sqlplugin.SignalsRequestedSetsAllFilter{
66 > ShardID: shardID,
67 > NamespaceID: namespaceID,
68 > WorkflowID: workflowID,
69 > RunID: runID,
70 > })
71 > if err != nil && err != sql.ErrNoRows {
72 return nil, serviceerror.NewUnavailablef("Failed to get signals requested. Error: %v", err)
73 }
74 > var ret = make([]string, len(rows)) execution_state_non_map.go
75 > for i, s := range rows {
76 ret[i] = s.SignalID
77 }
78 > return ret, nil execution_state_non_map.go
79 }
80
134 workflowID string,
135 runID primitives.UUID,
136 > ) ([]*commonpb.DataBlob, error) { execution_state_non_map.go
137 >
138 > rows, err := db.SelectFromBufferedEvents(ctx, sqlplugin.BufferedEventsFilter{
139 > ShardID: shardID,
140 > NamespaceID: namespaceID,
141 > WorkflowID: workflowID,
142 > RunID: runID,
143 > })
144 > if err != nil && err != sql.ErrNoRows {
145 return nil, serviceerror.NewUnavailablef("getBufferedEvents operation failed. Select failed: %v", err)
146 }
147 > var result []*commonpb.DataBlob execution_state_non_map.go
148 > for _, row := range rows {
149 result = append(result, p.NewDataBlob(row.Data, row.DataEncoding))
150 }
151 > return result, nil execution_state_non_map.go
152 }
153
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/visibility.go 34 covered LOC · 10 ranges

Open complete file

42 )
43
44 > func buildOnDuplicateKeyUpdate(fields ...string) string { visibility.go
45 > items := make([]string, len(fields))
46 > for i, field := range fields {
47 > items[i] = fmt.Sprintf("%s = excluded.%s", field, field)
48 > }
49 > return fmt.Sprintf(
50 > // The WHERE clause ensures that no update occurs if the version is behind the saved version.
51 > "ON CONFLICT (namespace_id, run_id) DO UPDATE SET %s WHERE executions_visibility.%s < EXCLUDED.%s",
52 > strings.Join(items, ", "), sqlplugin.VersionColumnName, sqlplugin.VersionColumnName,
53 > )
54 }
55
59 ctx context.Context,
60 row *sqlplugin.VisibilityRow,
61 > ) (sql.Result, error) { visibility.go
62 > finalRow := mdb.prepareRowForDB(row)
63 > return mdb.conn.NamedExecContext(ctx, templateInsertWorkflowExecution, finalRow)
64 > }
65
66 // ReplaceIntoVisibility replaces an existing row if it exist or creates a new row in visibility table
68 ctx context.Context,
69 row *sqlplugin.VisibilityRow,
70 > ) (sql.Result, error) { visibility.go
71 > finalRow := mdb.prepareRowForDB(row)
72 > return mdb.conn.NamedExecContext(ctx, templateUpsertWorkflowExecution, finalRow)
73 > }
74
75 // DeleteFromVisibility deletes a row from visibility table if it exist
153 }
154
155 > func (mdb *db) prepareRowForDB(row *sqlplugin.VisibilityRow) *sqlplugin.VisibilityRow { visibility.go
156 > if row == nil {
157 return nil
158 }
159 > finalRow := *row visibility.go
160 > finalRow.StartTime = mdb.converter.ToSQLiteDateTime(finalRow.StartTime)
161 > finalRow.ExecutionTime = mdb.converter.ToSQLiteDateTime(finalRow.ExecutionTime)
162 > if finalRow.CloseTime != nil {
163 > *finalRow.CloseTime = mdb.converter.ToSQLiteDateTime(*finalRow.CloseTime) visibility.go
164 > }
165 > if finalRow.SearchAttributes != nil { visibility.go
166 > finalSearchAttributes := sqlplugin.VisibilitySearchAttributes{} visibility.go
167 > for name, value := range *finalRow.SearchAttributes {
168 > switch v := value.(type) {
169 > case []string:
170 > finalSearchAttributes[name] = strings.Join(v, keywordListSeparator)
171 case time.Time:
172 finalSearchAttributes[name] = v.Format(time.RFC3339Nano)
175 }
176 }
177 > finalRow.SearchAttributes = &finalSearchAttributes visibility.go
178 }
179 > return &finalRow visibility.go
180 }
181
go.temporal.io/server/common/persistence/visibility/visibility_manager_rate_limited.go 34 covered LOC · 9 ranges

Open complete file

31 writeMaxQPS dynamicconfig.IntPropertyFn,
32 operatorRPSRatio dynamicconfig.FloatPropertyFn,
33 > ) *visibilityManagerRateLimited { visibility_manager_rate_limited.go
34 > return &visibilityManagerRateLimited{
35 > delegate: delegate,
36 > readRateLimiter: newPriorityRateLimiter(readMaxQPS, operatorRPSRatio),
37 > writeRateLimiter: newPriorityRateLimiter(writeMaxQPS, operatorRPSRatio),
38 > }
39 > }
40
41 > func (m *visibilityManagerRateLimited) Close() { visibility_manager_rate_limited.go
42 > m.delegate.Close()
43 > }
44
45 func (m *visibilityManagerRateLimited) GetReadStoreName(nsName namespace.Name) string {
47 }
48
49 > func (m *visibilityManagerRateLimited) GetStoreNames() []string { visibility_manager_rate_limited.go
50 > return m.delegate.GetStoreNames()
51 > }
52
53 func (m *visibilityManagerRateLimited) HasStoreName(stName string) bool {
55 }
56
57 > func (m *visibilityManagerRateLimited) GetIndexName() string { visibility_manager_rate_limited.go
58 > return m.delegate.GetIndexName()
59 > }
60
61 func (m *visibilityManagerRateLimited) ValidateCustomSearchAttributes(
70 ctx context.Context,
71 request *manager.RecordWorkflowExecutionStartedRequest,
73 > if ok := allow(ctx, "RecordWorkflowExecutionStarted", m.writeRateLimiter); !ok {
74 return persistence.ErrPersistenceSystemLimitExceeded
75 }
76 > return m.delegate.RecordWorkflowExecutionStarted(ctx, request) visibility_manager_rate_limited.go
77 }
78
80 ctx context.Context,
81 request *manager.RecordWorkflowExecutionClosedRequest,
83 > if ok := allow(ctx, "RecordWorkflowExecutionClosed", m.writeRateLimiter); !ok {
84 return persistence.ErrPersistenceSystemLimitExceeded
85 }
86 > return m.delegate.RecordWorkflowExecutionClosed(ctx, request) visibility_manager_rate_limited.go
87 }
88
172 api string,
173 rateLimiter quotas.RequestRateLimiter,
175 > callerInfo := headers.GetCallerInfo(ctx)
176 > // Currently only CallerType is used. See common/persistence/visibility/quotas.go for rate limiter details.
177 > return rateLimiter.Allow(time.Now().UTC(), quotas.NewRequest(
178 > api,
179 > RateLimitDefaultToken,
180 > callerInfo.CallerName,
181 > callerInfo.CallerType,
182 > -1,
183 > callerInfo.CallOrigin,
184 > ))
185 > }
go.temporal.io/server/common/rpc/encryption/tls_factory.go 34 covered LOC · 24 ranges

Open complete file

66 logger log.Logger,
67 certProviderFactory CertProviderFactory,
68 > ) (TLSConfigProvider, error) { tls_factory.go
69 > if err := validateRootTLS(&encryptionSettings); err != nil {
70 return nil, err
71 }
72 > if certProviderFactory == nil { tls_factory.go
73 > certProviderFactory = NewLocalStoreCertProvider
74 > }
75 > return NewLocalStoreTlsProvider(&encryptionSettings, metricsHandler.WithTags(metrics.OperationTag(metrics.ServerTlsScope)), logger, certProviderFactory)
76 }
77
78 > func validateRootTLS(cfg *config.RootTLS) error { tls_factory.go
79 > if err := validateGroupTLS(&cfg.Internode); err != nil {
80 return err
81 }
82 > if err := validateGroupTLS(&cfg.Frontend); err != nil { tls_factory.go
83 return err
84 }
85 > return validateWorkerTLS(&cfg.SystemWorker) tls_factory.go
86 }
87
88 > func validateGroupTLS(cfg *config.GroupTLS) error { tls_factory.go
89 > if err := validateServerTLS(&cfg.Server); err != nil {
90 return err
91 }
92 > if err := validateClientTLS(&cfg.Client); err != nil { tls_factory.go
93 return err
94 }
95 > for host, hostConfig := range cfg.PerHostOverrides { tls_factory.go
96
97 if strings.TrimSpace(host) == "" {
102 }
103 }
104 > return nil tls_factory.go
105 }
106
107 > func validateWorkerTLS(cfg *config.WorkerTLS) error { tls_factory.go
108 > if cfg.CertFile != "" && cfg.CertData != "" {
109 return fmt.Errorf("cannot specify CertFile and CertData at the same time")
110 }
111 > if cfg.KeyFile != "" && cfg.KeyData != "" { tls_factory.go
112 return fmt.Errorf("cannot specify KeyFile and KeyData at the same time")
113 }
114 > return validateClientTLS(&cfg.Client) tls_factory.go
115 }
116
117 > func validateServerTLS(cfg *config.ServerTLS) error { tls_factory.go
118 > if cfg.CertFile != "" && cfg.CertData != "" {
119 return fmt.Errorf("cannot specify CertFile and CertData at the same time")
120 }
121 > if cfg.KeyFile != "" && cfg.KeyData != "" { tls_factory.go
122 return fmt.Errorf("cannot specify KeyFile and KeyData at the same time")
123 }
124 > if err := validateCAs(cfg.ClientCAData); err != nil { tls_factory.go
125 return fmt.Errorf("invalid ServerTLS.ClientCAData: %w", err)
126 }
127 > if err := validateCAs(cfg.ClientCAFiles); err != nil { tls_factory.go
128 return fmt.Errorf("invalid ServerTLS.ClientCAFiles: %w", err)
129 }
130 > if len(cfg.ClientCAFiles) > 0 && len(cfg.ClientCAData) > 0 { tls_factory.go
131 return fmt.Errorf("cannot specify ClientCAFiles and ClientCAData at the same time")
132 }
133 > return nil tls_factory.go
134 }
135
136 > func validateClientTLS(cfg *config.ClientTLS) error { tls_factory.go
137 > if err := validateCAs(cfg.RootCAData); err != nil {
138 return fmt.Errorf("invalid ClientTLS.RootCAData: %w", err)
139 }
140 > if err := validateCAs(cfg.RootCAFiles); err != nil { tls_factory.go
141 return fmt.Errorf("invalid ClientTLS.RootCAFiles: %w", err)
142 }
143 > if len(cfg.RootCAData) > 0 && len(cfg.RootCAFiles) > 0 { tls_factory.go
144 return fmt.Errorf("cannot specify RootCAFiles and RootCAData at the same time")
145 }
146 > return nil tls_factory.go
147 }
148
149 > func validateCAs(cas []string) error { tls_factory.go
150 > for _, ca := range cas {
151 if strings.TrimSpace(ca) == "" {
152 return fmt.Errorf("CA cannot be empty string")
153 }
154 }
155 > return nil tls_factory.go
156 }
go.temporal.io/server/common/searchattribute/sadefs/encode_value.go 34 covered LOC · 13 ranges

Open complete file

13
14 // EncodeValue encodes search attribute value and IndexedValueType to Payload.
15 > func EncodeValue(val any, t enumspb.IndexedValueType) (*commonpb.Payload, error) { encode_value.go
16 > valPayload, err := payload.Encode(val)
17 > if err != nil {
18 return nil, err
19 }
20
21 > SetMetadataType(valPayload, t) encode_value.go
22 > return valPayload, nil
23 }
24
42 t enumspb.IndexedValueType,
43 allowList bool,
44 > ) (any, error) { encode_value.go
45 > if t == enumspb.INDEXED_VALUE_TYPE_UNSPECIFIED {
46 t = GetMetadataType(value)
47 }
48 > if t == enumspb.INDEXED_VALUE_TYPE_UNSPECIFIED { encode_value.go
49 return nil, fmt.Errorf("%w: %v", ErrInvalidType, t)
50 }
51
52 > switch t { encode_value.go
53 case enumspb.INDEXED_VALUE_TYPE_BOOL:
54 return decodeValueTyped[bool](value, allowList)
63 case enumspb.INDEXED_VALUE_TYPE_TEXT:
64 return validateStrings(decodeValueTyped[string](value, allowList))
65 > case enumspb.INDEXED_VALUE_TYPE_KEYWORD_LIST: encode_value.go
66 > return validateStrings(decodeValueTyped[[]string](value, false))
67 default:
68 return nil, fmt.Errorf("%w: %v", ErrInvalidType, t)
70 }
71
72 > func validateStrings(anyValue any, err error) (any, error) { encode_value.go
73 > if err != nil {
74 return anyValue, err
75 }
76
77 // validate strings
78 > switch value := anyValue.(type) { encode_value.go
79 case string:
80 if !utf8.ValidString(value) {
81 return nil, fmt.Errorf("%w: %s", ErrInvalidString, value)
82 }
83 > case []string: encode_value.go
84 > for _, item := range value {
85 > if !utf8.ValidString(item) {
86 return nil, fmt.Errorf("%w: %s", ErrInvalidString, item)
87 }
88 }
89 }
90 > return anyValue, err encode_value.go
91 }
92
96 //
97 //nolint:revive // allowList is a control flag
98 > func decodeValueTyped[T any](value *commonpb.Payload, allowList bool) (any, error) { encode_value.go
99 > // At first, it tries to decode to pointer of actual type (i.e. `*string` for `string`).
100 > // This is to ensure that `nil` values are decoded back as `nil` using `NilPayloadConverter`.
101 > // If value is not `nil` but some value of expected type, the code relies on the fact that
102 > // search attributes are always encoded with `JsonPayloadConverter`, which uses standard
103 > // `json.Unmarshal` function, which works fine with pointer types when decoding values.
104 > // If decoding to pointer type fails, it tries to decode to array of the same type because
105 > // search attributes support polymorphism: field of specific type may also have an array of that type.
106 > // If resulting slice has zero length, it gets substitute with `nil` to treat nils and empty slices equally.
107 > // If allowList is true, it returns the list as it is. If allowList is false and the list has
108 > // only one element, then return it. Otherwise, return an error.
109 > // If search attribute value is `nil`, it means that search attribute needs to be removed from the document.
110 > var val *T
111 > if err := payload.Decode(value, &val); err == nil {
112 > if val == nil { encode_value.go
113 return nil, nil
114 }
115 > return *val, nil encode_value.go
116 }
117 var listVal []T
go.temporal.io/server/service/history/queues/reader_quotas.go 34 covered LOC · 4 ranges

Open complete file

15 rateFn quotas.RateFn,
16 maxReaders int64,
17 > ) quotas.RequestRateLimiter { reader_quotas.go
18 > rateLimiters := make(map[int]quotas.RequestRateLimiter, maxReaders)
19 > readerCallerToPriority := make(map[string]int, maxReaders)
20 > for readerId := DefaultReaderId; readerId != DefaultReaderId+maxReaders; readerId++ {
21 > // use readerId as priority
22 > rateLimiters[int(readerId)] = quotas.NewRequestRateLimiterAdapter(quotas.NewDefaultOutgoingRateLimiter(rateFn))
23 > // reader will use readerId (in string type) as caller when using the rate limiter
24 > readerCallerToPriority[newReaderRequest(readerId).Caller] = int(readerId)
25 > }
26 > lowestPriority := int(DefaultReaderId + maxReaders - 1)
27 >
28 > return quotas.NewPriorityRateLimiter(
29 > func(req quotas.Request) int {
30 > if priority, ok := readerCallerToPriority[req.Caller]; ok { reader_quotas.go
31 > return priority
32 > }
33 return lowestPriority
34 },
41 hostReaderRateLimiter quotas.RequestRateLimiter,
42 maxReaders int64,
43 > ) quotas.RequestRateLimiter { reader_quotas.go
44 > return quotas.NewMultiRequestRateLimiter(
45 > NewReaderPriorityRateLimiter(
46 > func() float64 { return float64(shardMaxPollRPS()) },
47 maxReaders,
48 ),
53 func newReaderRequest(
54 readerID int64,
55 > ) quotas.Request { reader_quotas.go
56 > // The priority is only based on readerID (caller),
57 > // api, caller type, caller segment, and call initiation (origin)
58 > // are the same for all the readers, and not related to
59 > // priority so leaving those fields empty.
60 > return quotas.NewRequest(
61 > "",
62 > readerRequestToken,
63 > strconv.FormatInt(readerID, 10),
64 > "",
65 > 0,
66 > "",
67 > )
68 > }
go.temporal.io/server/service/history/queues/speculative_workflow_task_timeout_queue.go 34 covered LOC · 5 ranges

Open complete file

40 tracer trace.Tracer,
41 logger log.SnTaggedLogger,
42 > ) *SpeculativeWorkflowTaskTimeoutQueue { speculative_workflow_task_timeout_queue.go
43 >
44 > timeoutQueue := newMemoryScheduledQueue(
45 > scheduler,
46 > timeSource,
47 > logger,
48 > metricsHandler,
49 > )
50 >
51 > return &SpeculativeWorkflowTaskTimeoutQueue{
52 > timeoutQueue: timeoutQueue,
53 > executor: executor,
54 > priorityAssigner: priorityAssigner,
55 > namespaceRegistry: namespaceRegistry,
56 > clusterMetadata: clusterMetadata,
57 > timeSource: timeSource,
58 > chasmRegistry: chasmRegistry,
59 > metricsHandler: metricsHandler,
60 > tracer: tracer,
61 > logger: logger,
62 > }
63 > }
64
65 > func (q SpeculativeWorkflowTaskTimeoutQueue) Start() { speculative_workflow_task_timeout_queue.go
66 > q.timeoutQueue.Start()
67 > }
68
69 > func (q SpeculativeWorkflowTaskTimeoutQueue) Stop() { speculative_workflow_task_timeout_queue.go
70 > q.timeoutQueue.Stop()
71 > }
72
73 > func (q SpeculativeWorkflowTaskTimeoutQueue) Category() tasks.Category { speculative_workflow_task_timeout_queue.go
74 > return tasks.CategoryMemoryTimer
75 > }
76
77 > func (q SpeculativeWorkflowTaskTimeoutQueue) NotifyNewTasks(ts []tasks.Task) { speculative_workflow_task_timeout_queue.go
78 > for _, task := range ts {
79 > if wttt, ok := task.(*tasks.WorkflowTaskTimeoutTask); ok {
80 executable := newSpeculativeWorkflowTaskTimeoutExecutable(NewExecutable(
81 0,
go.temporal.io/server/service/matching/task_validation.go 34 covered LOC · 12 ranges

Open complete file

55 namespaceRegistry namespace.Registry,
56 historyClient historyservice.HistoryServiceClient,
57 > ) *taskValidatorImpl { task_validation.go
58 > return &taskValidatorImpl{
59 > tqCtx: tqCtx,
60 > clusterMetadata: clusterMetadata,
61 > namespaceRegistry: namespaceRegistry,
62 > historyClient: historyClient,
63 > }
64 > }
65
66 func (v *taskValidatorImpl) maybeValidate(
67 task *persistencespb.AllocatedTaskInfo,
68 taskType enumspb.TaskQueueType,
69 > ) bool { task_validation.go
70 > if IsTaskExpired(task) {
71 return false
72 }
73 > if !v.preValidate(task) { task_validation.go
74 > return true
75 > }
76 valid, err := v.isTaskValid(task, taskType)
77 if err != nil {
85 func (v *taskValidatorImpl) preValidate(
86 task *persistencespb.AllocatedTaskInfo,
87 > ) bool { task_validation.go
88 > namespaceID := task.Data.NamespaceId
89 > namespaceEntry, err := v.namespaceRegistry.GetNamespaceByID(namespace.ID(namespaceID))
90 > if err != nil {
91 // if cannot find the namespace entry, treat task as active
92 return v.preValidateActive(task)
93 }
94 > if v.clusterMetadata.GetCurrentClusterName() == namespaceEntry.ActiveClusterName(namespace.RoutingKey{ID: task.Data.WorkflowId}) { task_validation.go
95 > return v.preValidateActive(task) task_validation.go
96 > }
97 return v.preValidatePassive(task)
98 }
101 func (v *taskValidatorImpl) preValidateActive(
102 task *persistencespb.AllocatedTaskInfo,
103 > ) bool { task_validation.go
104 > if v.lastValidatedTaskInfo.taskID != task.TaskId {
105 > // first time seen the task, caller should try to dispatch first task_validation.go
106 > if task.Data.CreateTime != nil {
107 > v.lastValidatedTaskInfo = taskValidationInfo{ task_validation.go
108 > taskID: task.TaskId,
109 > validationTime: task.Data.CreateTime.AsTime(), // task is valid when created
110 > }
111 > } else { task_validation.go
112 v.lastValidatedTaskInfo = taskValidationInfo{
113 taskID: task.TaskId,
215 // 1. if task has valid TTL -> TTL reached -> delete
216 // 2. if task has 0 TTL / no TTL -> logic need to additionally check if corresponding workflow still exists
217 > func IsTaskExpired(t *persistencespb.AllocatedTaskInfo) bool { task_validation.go
218 > expiry := timestamp.TimeValue(t.GetData().GetExpiryTime())
219 > return expiry.Unix() > 0 && expiry.Before(time.Now())
220 > }
go.temporal.io/server/chasm/lib/workflow/library.go 33 covered LOC · 7 ranges

Open complete file

24 saMapperProvider searchattribute.MapperProvider,
25 saValidator *searchattribute.Validator,
26 > ) *library { library.go
27 > return &library{
28 > registry: registry,
29 > config: config,
30 > saMapperProvider: saMapperProvider,
31 > saValidator: saValidator,
32 > workflowServiceNexusHandler: &workflowServiceNexusHandler{
33 > config: config,
34 > namespaceRegistry: namespaceRegistry,
35 > },
36 > }
37 > }
38
39 // NewLibrary creates a new CHASM library for the workflow package.
43 }
44
45 > func (l *library) Name() string { library.go
46 > return chasm.WorkflowLibraryName
47 > }
48
49 type workflowContext struct {
63 }
64
65 > func (l *library) Components() []*chasm.RegistrableComponent { library.go
66 > return []*chasm.RegistrableComponent{
67 > chasm.NewRegistrableComponent[*Workflow](chasm.WorkflowComponentName, chasm.WithContextValues(map[any]any{
68 > ctxKeyWorkflowContext: &workflowContext{registry: l.registry},
69 > })),
70 > chasm.NewRegistrableComponent[*WorkflowUpdate]("update"),
71 > }
72 > }
73
74 // SetEventRegistryOnContext injects the event registry into a CHASM context. This is primarily
78 }
79
80 > func (l *library) NexusServices() []*nexus.Service { library.go
81 > if l.workflowServiceNexusHandler == nil {
82 return nil
83 }
84 > return []*nexus.Service{ library.go
85 > mustNewWorkflowServiceNexusHandler(l.workflowServiceNexusHandler),
86 > }
87 }
88
89 > func (l *library) NexusServiceProcessors() []*chasm.NexusServiceProcessor { library.go
90 > if l.workflowServiceNexusHandler == nil {
91 return nil
92 }
93 > return []*chasm.NexusServiceProcessor{ library.go
94 > NewWorkflowServiceNexusServiceProcessor(l.config, l.saMapperProvider, l.saValidator),
95 > }
96 }
go.temporal.io/server/common/headers/caller_info.go 33 covered LOC · 6 ranges

Open complete file

79 func NewBackgroundHighCallerInfo(
80 callerName string,
81 > ) CallerInfo { caller_info.go
82 > return CallerInfo{
83 > CallerName: callerName,
84 > CallerType: CallerTypeBackgroundHigh,
85 > }
86 > }
87
88 // NewBackgroundLowCallerInfo creates a new CallerInfo with BackgroundLow callerType
91 func NewBackgroundLowCallerInfo(
92 callerName string,
93 > ) CallerInfo { caller_info.go
94 > return CallerInfo{
95 > CallerName: callerName,
96 > CallerType: CallerTypeBackgroundLow,
97 > }
98 > }
99
100 // NewPreemptableCallerInfo creates a new CallerInfo with Preemptable callerType
117 ctx context.Context,
118 info CallerInfo,
119 > ) context.Context { caller_info.go
120 > return setIncomingMD(ctx, map[string]string{
121 > CallerNameHeaderName: info.CallerName,
122 > CallerTypeHeaderName: info.CallerType,
123 > CallOriginHeaderName: info.CallOrigin,
124 > })
125 > }
126
127 // SetCallerName set caller name in the context.
130 ctx context.Context,
131 callerName string,
132 > ) context.Context { caller_info.go
133 > return setIncomingMD(ctx, map[string]string{CallerNameHeaderName: callerName})
134 > }
135
136 // SetCallerType set caller type in the context.
139 ctx context.Context,
140 callerType string,
141 > ) context.Context { caller_info.go
142 > return setIncomingMD(ctx, map[string]string{CallerTypeHeaderName: callerType})
143 > }
144
145 // SetOrigin set call origin in the context.
156 func GetCallerInfo(
157 ctx context.Context,
158 > ) CallerInfo { caller_info.go
159 > values := GetValues(ctx, CallerNameHeaderName, CallerTypeHeaderName, CallOriginHeaderName)
160 > return CallerInfo{
161 > CallerName: values[0],
162 > CallerType: values[1],
163 > CallOrigin: values[2],
164 > }
165 > }
go.temporal.io/server/common/quotas/multi_request_rate_limiter_impl.go 33 covered LOC · 12 ranges

Open complete file

17 func NewMultiRequestRateLimiter(
18 requestRateLimiters ...RequestRateLimiter,
19 > ) *MultiRequestRateLimiterImpl { multi_request_rate_limiter_impl.go
20 > if len(requestRateLimiters) == 0 {
21 panic("expect at least one rate limiter")
22 }
23 > return &MultiRequestRateLimiterImpl{ multi_request_rate_limiter_impl.go
24 > requestRateLimiters: requestRateLimiters,
25 > }
26 }
27
28 > func (rl *MultiRequestRateLimiterImpl) Allow(now time.Time, request Request) bool { multi_request_rate_limiter_impl.go
29 > length := len(rl.requestRateLimiters)
30 > reservations := make([]Reservation, 0, length)
31 >
32 > for _, requestRateLimiter := range rl.requestRateLimiters {
33 > reservation := requestRateLimiter.Reserve(now, request)
34 > if !reservation.OK() || reservation.DelayFrom(now) > 0 {
35 if reservation.OK() {
36 reservation.CancelAt(now)
43 return false
44 }
45 > reservations = append(reservations, reservation) multi_request_rate_limiter_impl.go
46 }
47
49 }
50
51 > func (rl *MultiRequestRateLimiterImpl) Reserve(now time.Time, request Request) Reservation { multi_request_rate_limiter_impl.go
52 > length := len(rl.requestRateLimiters)
53 > reservations := make([]Reservation, 0, length)
54 >
55 > for _, requestRateLimiter := range rl.requestRateLimiters {
56 > reservation := requestRateLimiter.Reserve(now, request)
57 > if !reservation.OK() {
58 // cancel all existing reservation
59 for _, reservation := range reservations {
62 return NewMultiReservation(false, nil)
63 }
64 > reservations = append(reservations, reservation) multi_request_rate_limiter_impl.go
65 }
66
67 > return NewMultiReservation(true, reservations) multi_request_rate_limiter_impl.go
68 }
69
70 > func (rl *MultiRequestRateLimiterImpl) Wait(ctx context.Context, request Request) error { multi_request_rate_limiter_impl.go
71 > select {
72 case <-ctx.Done():
73 return ctx.Err()
75 }
76
77 > now := time.Now().UTC() multi_request_rate_limiter_impl.go
78 > reservation := rl.Reserve(now, request)
79 > if !reservation.OK() {
80 return fmt.Errorf("rate: Wait(n=%d) would exceed context deadline", request.Token)
81 }
82
83 > delay := reservation.DelayFrom(now) multi_request_rate_limiter_impl.go
84 > if delay == 0 {
85 > return nil
86 > }
87 waitLimit := InfDuration
88 if deadline, ok := ctx.Deadline(); ok {
go.temporal.io/server/common/rpc/interceptor/routing_key_extractor.go 33 covered LOC · 13 ranges

Open complete file

18 }
19
20 > func NewRoutingKeyExtractor() RoutingKeyExtractor { routing_key_extractor.go
21 > return RoutingKeyExtractor{
22 > serializer: *tasktoken.NewSerializer(),
23 > }
24 > }
25
26 // WorkflowServiceExtractor returns a RoutingKeyExtractorFunc that extracts the
27 // routing key from WorkflowService API requests using the provided
28 // RoutingKeyExtractor.
29 > func WorkflowServiceExtractor(extractor RoutingKeyExtractor) RoutingKeyExtractorFunc { routing_key_extractor.go
30 > return func(_ context.Context, req any, fullMethod string) namespace.RoutingKey {
31 > // Only process WorkflowService APIs
32 > if !strings.HasPrefix(fullMethod, api.WorkflowServicePrefix) {
33 > return namespace.RoutingKey{} routing_key_extractor.go
34 > }
35
36 // Prefer the generated extractor driven by temporal-resource-id proto
37 // annotations.
38 > if key := workflowServiceRequestRoutingKey(req); key.ID != "" { routing_key_extractor.go
39 > return key routing_key_extractor.go
40 > }
41
42 // Fall back to pattern-based logic as a compatibility path for methods
43 // whose callers haven't populated the resource_id field yet.
44 > methodName := api.MethodName(fullMethod) routing_key_extractor.go
45 > pattern, hasPattern := methodToPattern[methodName]
46 > if !hasPattern {
47 > return namespace.RoutingKey{} routing_key_extractor.go
48 > }
49
50 > return extractor.Extract(req, pattern) routing_key_extractor.go
51 }
52 }
73 // Extract extracts routing key from the request using the specified pattern.
74 // Returns a zero-value namespace.RoutingKey if not found.
75 > func (e RoutingKeyExtractor) Extract(req any, pattern RoutingKeyPattern) namespace.RoutingKey { routing_key_extractor.go
76 > if req == nil {
77 return namespace.RoutingKey{}
78 }
79
80 > switch pattern { routing_key_extractor.go
81 case PatternWorkflowID:
82 if getter, ok := req.(workflowIDGetter); ok {
91 }
92
93 > case PatternTaskToken: routing_key_extractor.go
94 > if getter, ok := req.(taskTokenGetter); ok {
95 > if tokenBytes := getter.GetTaskToken(); len(tokenBytes) > 0 {
96 > if taskToken, err := e.serializer.Deserialize(tokenBytes); err == nil {
97 > return namespace.RoutingKey{ID: taskToken.GetWorkflowId()} routing_key_extractor.go
98 > }
99 }
100 }
151 // routingIDFromResourceID extracts the routing ID from a resource_id field value.
152 // The resource_id field has the format "prefix:<routingID>".
153 > func routingIDFromResourceID(resourceID string) string { routing_key_extractor.go
154 > _, routingID, _ := strings.Cut(resourceID, ":")
155 > return routingID
156 > }
go.temporal.io/server/common/searchattribute/mapper.go 33 covered LOC · 12 ranges

Open complete file

93 searchAttributesProvider Provider,
94 fallbackIndexName string,
95 > ) MapperProvider { mapper.go
96 > return &mapperProviderImpl{
97 > customMapper: customMapper,
98 > namespaceRegistry: namespaceRegistry,
99 > searchAttributesProvider: searchAttributesProvider,
100 > fallbackIndexName: fallbackIndexName,
101 > }
102 > }
103
104 > func (m *mapperProviderImpl) GetMapper(nsName namespace.Name) (Mapper, error) { mapper.go
105 > if m.customMapper != nil {
106 return m.customMapper, nil
107 }
108 > saMapper, err := m.namespaceRegistry.GetCustomSearchAttributesMapper(nsName) mapper.go
109 > if err != nil {
110 return nil, err
111 }
112 > fallbackNameTypeMap := NameTypeMap{} mapper.go
113 > if m.fallbackIndexName != "" {
114 > nameTypeMap, err := m.searchAttributesProvider.GetSearchAttributes(m.fallbackIndexName, false)
115 > if err != nil {
116 return nil, fmt.Errorf("failed to load search attributes for fallback index %q: %w", m.fallbackIndexName, err)
117 }
118 > fallbackNameTypeMap = legacyCustomSearchAttributes(nameTypeMap) mapper.go
119 }
120 > return &backCompMapper{ mapper.go
121 > mapper: &saMapper,
122 > fallbackNameTypeMap: fallbackNameTypeMap,
123 > }, nil
124 }
125
126 > func legacyCustomSearchAttributes(nameTypeMap NameTypeMap) NameTypeMap { mapper.go
127 > legacyCustomSearchAttributes := make(map[string]enumspb.IndexedValueType)
128 > for name, valueType := range nameTypeMap.Custom() {
129 > if sadefs.IsPreallocatedCSAFieldName(name, valueType) {
130 > continue mapper.go
131 }
132 legacyCustomSearchAttributes[name] = valueType
133 }
134 > return NewNameTypeMap(legacyCustomSearchAttributes) mapper.go
135 }
136
188 searchAttributes *commonpb.SearchAttributes,
189 namespaceName string,
190 > ) (*commonpb.SearchAttributes, error) { mapper.go
191 > mapper, err := mapperProvider.GetMapper(namespace.Name(namespaceName))
192 > if err != nil {
193 return nil, err
194 }
195
196 > if len(searchAttributes.GetIndexedFields()) == 0 || mapper == nil { mapper.go
197 > return searchAttributes, nil mapper.go
198 > }
199
200 newIndexedFields := make(map[string]*commonpb.Payload, len(searchAttributes.GetIndexedFields()))
go.temporal.io/server/common/testing/freeport/freeport.go 33 covered LOC · 7 ranges

Open complete file

22 // in this regard; on that platform, `SO_REUSEADDR` has a different meaning and
23 // should not be set (setting it may have unpredictable consequences).
24 > func MustGetFreePort() int { freeport.go
25 > port, err := getFreePort("127.0.0.1")
26 > if err != nil {
27 // try ipv6
28 port, err = getFreePort("[::1]")
31 }
32 }
33 > return port freeport.go
34 }
35
36 > func getFreePort(host string) (int, error) { freeport.go
37 > l, err := net.Listen("tcp", host+":0")
38 > if err != nil {
39 return 0, fmt.Errorf("failed to assign a free port: %v", err)
40 }
41 > defer l.Close() freeport.go
42 > port := l.Addr().(*net.TCPAddr).Port
43 >
44 > // On Linux and some BSD variants, ephemeral ports are randomized, and may
45 > // consequently repeat within a short time frame after the listening end
46 > // has been closed. To avoid this, we make a connection to the port, then
47 > // close that connection from the server's side (this is very important),
48 > // which puts the connection in TIME_WAIT state for some time (by default,
49 > // 60s on Linux). While it remains in that state, the OS will not reallocate
50 > // that port number for bind(:0) syscalls, yet we are not prevented from
51 > // explicitly binding to it (thanks to SO_REUSEADDR).
52 > //
53 > // On macOS and Windows, the above technique is not necessary, as the OS
54 > // allocates ephemeral ports sequentially, meaning a port number will only
55 > // be reused after the entire range has been exhausted. Quite the opposite,
56 > // given that these OSes use a significantly smaller range for ephemeral
57 > // ports, making an extra connection just to reserve a port might actually
58 > // be harmful (by hastening ephemeral port exhaustion).
59 > if runtime.GOOS != "darwin" && runtime.GOOS != "windows" {
60 > r, err := net.DialTCP("tcp", nil, l.Addr().(*net.TCPAddr))
61 > if err != nil {
62 return 0, fmt.Errorf("failed to assign a free port: %v", err)
63 }
64 > c, err := l.Accept() freeport.go
65 > if err != nil {
66 return 0, fmt.Errorf("failed to assign a free port: %v", err)
67 }
68 // Closing the socket from the server side
69 > _ = c.Close() freeport.go
70 > defer r.Close()
71 }
72
73 > return port, nil freeport.go
74 }
go.temporal.io/server/service/history/tasks/utils.go 33 covered LOC · 9 ranges

Open complete file

10 func Tags(
11 task Task,
12 > ) []tag.Tag { utils.go
13 > // TODO: convert this to a method GetEventID on task interface
14 > // or remove this tag as the value is visible in the Task tag value.
15 > taskEventID := common.EmptyEventID
16 > taskEidOk := false
17 > taskCategory := task.GetCategory()
18 > switch taskCategory.ID() {
19 > case CategoryIDTransfer: utils.go
20 > taskEventID, taskEidOk = GetTransferTaskEventID(task)
21 case CategoryIDTimer, CategoryIDMemoryTimer:
22 taskEventID, taskEidOk = GetTimerTaskEventID(task)
25 }
26
27 > if !taskEidOk { utils.go
28 taskEventID = common.EmptyEventID
29 }
30
31 > return []tag.Tag{ utils.go
32 > tag.WorkflowNamespaceID(task.GetNamespaceID()),
33 > tag.WorkflowID(task.GetWorkflowID()),
34 > tag.WorkflowRunID(task.GetRunID()),
35 > tag.TaskKey(task.GetKey()),
36 > tag.TaskType(task.GetType()),
37 > tag.Task(task),
38 > tag.WorkflowEventID(taskEventID),
39 > }
40 }
41
44 task Task,
45 logger log.Logger,
46 > ) log.Logger { utils.go
47 > return log.With(
48 > logger,
49 > Tags(task)...,
50 > )
51 > }
52
53 // GetChasmTaskEventID is a dummy getter for CHASM tasks, as Components don't have events.
58 func GetTransferTaskEventID(
59 transferTask Task,
60 > ) (int64, bool) { utils.go
61 > eventID := int64(0)
62 > switch task := transferTask.(type) {
63 case *ActivityTask:
64 eventID = task.ScheduledEventID
65 > case *WorkflowTask: utils.go
66 > eventID = task.ScheduledEventID
67 > case *CloseExecutionTask: utils.go
68 > eventID = common.FirstEventID
69 case *DeleteExecutionTask:
70 return getChasmTaskEventID()
84 panic(serviceerror.NewInternal("unknown transfer task"))
85 }
86 > return eventID, true utils.go
87 }
88
go.temporal.io/server/api/common/v1/dlq.pb.go 32 covered LOC · 8 ranges

Open complete file

98 func (*HistoryDLQTaskMetadata) ProtoMessage() {}
99
100 > func (x *HistoryDLQTaskMetadata) ProtoReflect() protoreflect.Message { dlq.pb.go
101 > mi := &file_temporal_server_api_common_v1_dlq_proto_msgTypes[1]
102 > if x != nil {
103 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
104 if ms.LoadMessageInfo() == nil {
107 return ms
108 }
109 > return mi.MessageOf(x) dlq.pb.go
110 }
111
146 func (*HistoryDLQTask) ProtoMessage() {}
147
148 > func (x *HistoryDLQTask) ProtoReflect() protoreflect.Message { dlq.pb.go
149 > mi := &file_temporal_server_api_common_v1_dlq_proto_msgTypes[2]
150 > if x != nil {
151 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
152 if ms.LoadMessageInfo() == nil {
155 return ms
156 }
157 > return mi.MessageOf(x) dlq.pb.go
158 }
159
207 func (*HistoryDLQKey) ProtoMessage() {}
208
209 > func (x *HistoryDLQKey) ProtoReflect() protoreflect.Message { dlq.pb.go
210 > mi := &file_temporal_server_api_common_v1_dlq_proto_msgTypes[3]
211 > if x != nil {
212 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
213 if ms.LoadMessageInfo() == nil {
216 return ms
217 }
218 > return mi.MessageOf(x) dlq.pb.go
219 }
220
295 }
296
297 > func init() { file_temporal_server_api_common_v1_dlq_proto_init() } dlq.pb.go
298 > func file_temporal_server_api_common_v1_dlq_proto_init() {
299 > if File_temporal_server_api_common_v1_dlq_proto != nil {
300 return
301 }
302 > type x struct{} dlq.pb.go
303 > out := protoimpl.TypeBuilder{
304 > File: protoimpl.DescBuilder{
305 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
306 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_common_v1_dlq_proto_rawDesc), len(file_temporal_server_api_common_v1_dlq_proto_rawDesc)),
307 > NumEnums: 0,
308 > NumMessages: 4,
309 > NumExtensions: 0,
310 > NumServices: 0,
311 > },
312 > GoTypes: file_temporal_server_api_common_v1_dlq_proto_goTypes,
313 > DependencyIndexes: file_temporal_server_api_common_v1_dlq_proto_depIdxs,
314 > MessageInfos: file_temporal_server_api_common_v1_dlq_proto_msgTypes,
315 > }.Build()
316 > File_temporal_server_api_common_v1_dlq_proto = out.File
317 > file_temporal_server_api_common_v1_dlq_proto_goTypes = nil
318 > file_temporal_server_api_common_v1_dlq_proto_depIdxs = nil
319 }
go.temporal.io/server/api/persistence/v1/nexus.pb.go 32 covered LOC · 6 ranges

Open complete file

54 func (*NexusEndpointSpec) ProtoMessage() {}
55
56 > func (x *NexusEndpointSpec) ProtoReflect() protoreflect.Message { nexus.pb.go
57 > mi := &file_temporal_server_api_persistence_v1_nexus_proto_msgTypes[0]
58 > if x != nil {
59 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
60 if ms.LoadMessageInfo() == nil {
63 return ms
64 }
65 > return mi.MessageOf(x) nexus.pb.go
66 }
67
269 func (*NexusEndpointEntry) ProtoMessage() {}
270
271 > func (x *NexusEndpointEntry) ProtoReflect() protoreflect.Message { nexus.pb.go
272 > mi := &file_temporal_server_api_persistence_v1_nexus_proto_msgTypes[3]
273 > if x != nil {
274 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
275 if ms.LoadMessageInfo() == nil {
278 return ms
279 }
280 > return mi.MessageOf(x) nexus.pb.go
281 }
282
481 }
482
483 > func init() { file_temporal_server_api_persistence_v1_nexus_proto_init() } nexus.pb.go
484 > func file_temporal_server_api_persistence_v1_nexus_proto_init() {
485 > if File_temporal_server_api_persistence_v1_nexus_proto != nil {
486 return
487 }
488 > file_temporal_server_api_persistence_v1_nexus_proto_msgTypes[1].OneofWrappers = []any{ nexus.pb.go
489 > (*NexusEndpointTarget_Worker_)(nil),
490 > (*NexusEndpointTarget_External_)(nil),
491 > }
492 > type x struct{}
493 > out := protoimpl.TypeBuilder{
494 > File: protoimpl.DescBuilder{
495 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
496 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_nexus_proto_rawDesc), len(file_temporal_server_api_persistence_v1_nexus_proto_rawDesc)),
497 > NumEnums: 0,
498 > NumMessages: 6,
499 > NumExtensions: 0,
500 > NumServices: 0,
501 > },
502 > GoTypes: file_temporal_server_api_persistence_v1_nexus_proto_goTypes,
503 > DependencyIndexes: file_temporal_server_api_persistence_v1_nexus_proto_depIdxs,
504 > MessageInfos: file_temporal_server_api_persistence_v1_nexus_proto_msgTypes,
505 > }.Build()
506 > File_temporal_server_api_persistence_v1_nexus_proto = out.File
507 > file_temporal_server_api_persistence_v1_nexus_proto_goTypes = nil
508 > file_temporal_server_api_persistence_v1_nexus_proto_depIdxs = nil
509 }
go.temporal.io/server/client/history/client.go 32 covered LOC · 9 ranges

Open complete file

52 rpcFactory RPCFactory,
53 timeout time.Duration,
54 > ) historyservice.HistoryServiceClient { client.go
55 > connections := NewConnectionPool(historyServiceResolver, rpcFactory, historyservice.NewHistoryServiceClient, logger, dynamicconfig.HistoryConnectionCloseDelay.Get(dc))
56 >
57 > var redirector Redirector[historyservice.HistoryServiceClient]
58 > if dynamicconfig.HistoryClientOwnershipCachingEnabled.Get(dc)() {
59 logger.Info("historyClient: ownership caching enabled")
60 redirector = NewCachingRedirector(
64 dynamicconfig.HistoryClientOwnershipCachingStaleTTL.Get(dc),
65 )
66 > } else { client.go
67 > logger.Info("historyClient: ownership caching disabled")
68 > redirector = NewBasicRedirector(connections, historyServiceResolver)
69 > }
70
71 > return &clientImpl{ client.go
72 > connections: connections,
73 > logger: logger,
74 > numberOfShards: numberOfShards,
75 > redirector: redirector,
76 > timeout: timeout,
77 > tokenSerializer: tasktoken.NewSerializer(),
78 > }
79 }
80
285 }
286
287 > func (c *clientImpl) createContext(parent context.Context) (context.Context, context.CancelFunc) { client.go
288 > return context.WithTimeout(parent, c.timeout)
289 > }
290
291 > func (c *clientImpl) shardIDFromWorkflowID(namespaceID, workflowID string) int32 { client.go
292 > return common.WorkflowIDToHistoryShard(namespaceID, workflowID, c.numberOfShards)
293 > }
294
295 // Stop stops the membership watcher and closes pooled connections.
296 > func (c *clientImpl) Stop() { client.go
297 > c.redirector.Close()
298 > }
299
300 > func checkShardID(shardID int32) error { client.go
301 > if shardID <= 0 {
302 return serviceerror.NewInvalidArgumentf("Invalid ShardID: %d", shardID)
303 }
304 > return nil client.go
305 }
306
309 shardID int32,
310 op ClientOperation[historyservice.HistoryServiceClient],
311 > ) error { client.go
312 > return c.redirector.Execute(ctx, shardID, op)
313 > }
go.temporal.io/server/common/persistence/size_util.go 32 covered LOC · 14 ranges

Open complete file

7 func sizeOfBlob(
8 blob *commonpb.DataBlob,
9 > ) int { size_util.go
10 > return blob.Size()
11 > }
12
13 func sizeOfInt64Set(
14 int64Set map[int64]struct{},
15 > ) int { size_util.go
16 > // 8 == 64 bit / 8 bit per byte
17 > return 8 * len(int64Set)
18 > }
19
20 func sizeOfStringSet(
21 stringSet map[string]struct{},
22 > ) int { size_util.go
23 > size := 0
24 > for requestID := range stringSet {
25 size += len(requestID)
26 }
27 > return size size_util.go
28 }
29
30 func sizeOfInt64BlobMap(
31 kvBlob map[int64]*commonpb.DataBlob,
32 > ) int { size_util.go
33 > // 8 == 64 bit / 8 bit per byte
34 > size := 8 * len(kvBlob)
35 > for _, blob := range kvBlob {
36 size += blob.Size()
37 }
38 > return size size_util.go
39 }
40
43 func sizeOfChasmNodeMap(
44 nodeMap map[string]InternalChasmNode,
45 > ) int { size_util.go
46 > size := 0
47 > for path, node := range nodeMap {
48 size += len(path) + node.Metadata.Size() + node.Data.Size()
49 }
50 > return size size_util.go
51 }
52
53 func sizeOfStringBlobMap(
54 kvBlob map[string]*commonpb.DataBlob,
55 > ) int { size_util.go
56 > size := 0
57 > for id, blob := range kvBlob {
58 // 8 == 64 bit / 8 bit per byte
59 size += len(id) + blob.Size()
60 }
61 > return size size_util.go
62 }
63
64 func sizeOfStringSlice(
65 stringSlice []string,
66 > ) int { size_util.go
67 > size := 0
68 > for _, str := range stringSlice {
69 size += len(str)
70 }
71 > return size size_util.go
72 }
73
74 func sizeOfBlobSlice(
75 blobSlice []*commonpb.DataBlob,
76 > ) int { size_util.go
77 > size := 0
78 > for _, blob := range blobSlice {
79 size += blob.Size()
80 }
81 > return size size_util.go
82 }
go.temporal.io/server/service/history/history_engine_factory.go 32 covered LOC · 1 range

Open complete file

65 func (f *historyEngineFactory) CreateEngine(
66 shard historyi.ShardContext,
67 > ) historyi.Engine { history_engine_factory.go
68 > return NewEngineWithShardContext(
69 > shard,
70 > f.ClientBean,
71 > f.MatchingClient,
72 > f.SdkClientFactory,
73 > f.EventNotifier,
74 > f.Config,
75 > f.VersionMembershipCache,
76 > f.WorkerDeploymentClient,
77 > f.RoutingInfoCache,
78 > f.RawMatchingClient,
79 > f.WorkflowCache,
80 > f.ReplicationProgressCache,
81 > f.Serializer,
82 > f.QueueFactories,
83 > f.ReplicationTaskFetcherFactory,
84 > f.ReplicationTaskExecutorProvider,
85 > api.NewWorkflowConsistencyChecker(shard, f.WorkflowCache),
86 > f.TracerProvider,
87 > f.PersistenceVisibilityMgr,
88 > f.EventBlobCache,
89 > f.TaskCategoryRegistry,
90 > f.ReplicationDLQWriter,
91 > f.CommandHandlerRegistry,
92 > f.ChasmWorkflowRegistry,
93 > f.OutboundQueueCBPool,
94 > f.PersistenceRateLimiter,
95 > f.TestHooks,
96 > f.ChasmEngine,
97 > )
98 > }
go.temporal.io/server/service/worker/parentclosepolicy/processor.go 32 covered LOC · 3 ranges

Open complete file

57
58 // New returns a new instance as daemon
59 > func New(params *BootstrapParams) *Processor { processor.go
60 > return &Processor{
61 > sdkClientFactory: params.SdkClientFactory,
62 > metricsHandler: params.MetricsHandler.WithTags(metrics.OperationTag(metrics.ParentClosePolicyProcessorScope)),
63 > cfg: params.Config,
64 > logger: log.With(params.Logger, tag.ComponentBatcher),
65 > clientBean: params.ClientBean,
66 > currentCluster: params.CurrentCluster,
67 > hostInfo: params.HostInfo,
68 > }
69 > }
70
71 // Start starts the scanner
72 > func (s *Processor) Start() error { processor.go
73 > svcClient := s.sdkClientFactory.GetSystemClient()
74 > processorWorker := s.sdkClientFactory.NewWorker(svcClient, processorTaskQueueName, getWorkerOptions(s))
75 > processorWorker.RegisterWorkflowWithOptions(ProcessorWorkflow, workflow.RegisterOptions{Name: processorWFTypeName})
76 > processorWorker.RegisterActivityWithOptions(ProcessorActivity, activity.RegisterOptions{Name: processorActivityName})
77 >
78 > return processorWorker.Start()
79 > }
80
81 > func getWorkerOptions(p *Processor) worker.Options { processor.go
82 > ctx := context.WithValue(context.Background(), processorContextKey, p)
83 > ctx = headers.SetCallerInfo(ctx, headers.SystemBackgroundHighCallerInfo)
84 >
85 > return worker.Options{
86 > MaxConcurrentActivityExecutionSize: p.cfg.MaxConcurrentActivityExecutionSize(),
87 > MaxConcurrentWorkflowTaskExecutionSize: p.cfg.MaxConcurrentWorkflowTaskExecutionSize(),
88 > MaxConcurrentActivityTaskPollers: p.cfg.MaxConcurrentActivityTaskPollers(),
89 > MaxConcurrentWorkflowTaskPollers: p.cfg.MaxConcurrentWorkflowTaskPollers(),
90 > BackgroundActivityContext: ctx,
91 > Identity: "temporal-system@" + p.hostInfo.Identity(),
92 > }
93 > }
go.temporal.io/server/chasm/lib/callback/library.go 31 covered LOC · 5 ranges

Open complete file

24 InvocationTaskHandler *invocationTaskHandler,
25 BackoffTaskHandler *backoffTaskHandler,
26 > ) *Library { library.go
27 > return &Library{
28 > InvocationTaskHandler: InvocationTaskHandler,
29 > BackoffTaskHandler: BackoffTaskHandler,
30 > }
31 > }
32
33 > func (l *Library) Name() string { library.go
34 > return chasm.CallbackLibraryName
35 > }
36
37 > func (l *Library) Components() []*chasm.RegistrableComponent { library.go
38 > return []*chasm.RegistrableComponent{
39 > chasm.NewRegistrableComponent[*Callback](
40 > chasm.CallbackComponentName,
41 > chasm.WithDetached(),
42 > ),
43 > }
44 > }
45
46 > func (l *Library) Tasks() []*chasm.RegistrableTask { library.go
47 > return []*chasm.RegistrableTask{
48 > chasm.NewRegistrableSideEffectTask(
49 > "invoke",
50 > l.InvocationTaskHandler,
51 > ),
52 > chasm.NewRegistrablePureTask(
53 > "backoff",
54 > l.BackoffTaskHandler,
55 > ),
56 > }
57 > }
58
59 > func (l *Library) RegisterServices(server *grpc.Server) { library.go
60 > }
go.temporal.io/server/client/history/redirector.go 31 covered LOC · 11 ranges

Open complete file

30 )
31
32 > func shardLookup(resolver membership.ServiceResolver, shardID int32) (rpcAddress, error) { redirector.go
33 > hostInfo, err := resolver.Lookup(convert.Int32ToString(shardID))
34 > if err != nil {
35 > return "", err redirector.go
36 > }
37 > return rpcAddress(hostInfo.GetAddress()), nil redirector.go
38 }
39
41 connections connectionPool[C],
42 historyServiceResolver membership.ServiceResolver,
43 > ) *BasicRedirector[C] { redirector.go
44 > return &BasicRedirector[C]{
45 > connections: connections,
46 > historyServiceResolver: historyServiceResolver,
47 > }
48 > }
49
50 > func (r *BasicRedirector[C]) Close() { redirector.go
51 > r.connections.Close()
52 > }
53
54 func (r *BasicRedirector[C]) clientForShardID(shardID int32) (C, error) {
65 }
66
67 > func (r *BasicRedirector[C]) Execute(ctx context.Context, shardID int32, op ClientOperation[C]) error { redirector.go
68 > if err := checkShardID(shardID); err != nil {
69 return err
70 }
71 > address, err := shardLookup(r.historyServiceResolver, shardID) redirector.go
72 > if err != nil {
73 > return err redirector.go
74 > }
75 > return r.redirectLoop(ctx, address, op) redirector.go
76 }
77
78 > func (r *BasicRedirector[C]) redirectLoop(ctx context.Context, address rpcAddress, op ClientOperation[C]) error { redirector.go
79 > for {
80 > if err := common.IsValidContext(ctx); err != nil {
81 return err
82 }
83 > clientConn := r.connections.getOrCreateClientConn(address) redirector.go
84 > err := op(ctx, clientConn.grpcClient)
85 > var solErr *serviceerrors.ShardOwnershipLost
86 > if !errors.As(err, &solErr) || len(solErr.OwnerHost) == 0 {
87 > return err
88 > }
89 // TODO: consider emitting a metric for number of redirects
90 address = rpcAddress(solErr.OwnerHost)
go.temporal.io/server/common/dynamicconfig/deepcopy.go 31 covered LOC · 6 ranges

Open complete file

9 // deepCopyForMapstructure does a simple deep copy of T. Fancy cases (anything other than plain old data)
10 // is not handled and will panic.
11 > func deepCopyForMapstructure[T any](t T) T { deepcopy.go
12 > // nolint:revive // this will be triggered from a static initializer before it can be triggered from production code
13 > return deepCopyValue(reflect.ValueOf(t)).Interface().(T)
14 > }
15
16 > func deepCopyValue(v reflect.Value) reflect.Value { deepcopy.go
17 > switch v.Kind() {
18 case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
19 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
20 > reflect.Uintptr, reflect.Float32, reflect.Float64, reflect.String: deepcopy.go
21 > nv := reflect.New(v.Type()).Elem()
22 > nv.Set(v)
23 > return nv
24 case reflect.Array:
25 nv := reflect.New(v.Type()).Elem()
42 }
43 return deepCopyValue(v.Elem()).Addr()
44 > case reflect.Slice: deepcopy.go
45 > if v.IsNil() {
46 > return v
47 > }
48 nv := reflect.MakeSlice(v.Type(), v.Len(), v.Len())
49 for i := range v.Len() {
51 }
52 return nv
53 > case reflect.Struct: deepcopy.go
54 > // Special case for time.Time: it has unexported fields so we can't copy it field by
55 > // field, but we can copy zero values (which is all we need for default values).
56 > if v.Type() == reflect.TypeFor[time.Time]() {
57 > if v.Interface().(time.Time).IsZero() {
58 > return reflect.ValueOf(time.Time{})
59 > }
60 // nolint:forbidigo // this will be triggered from a static initializer before it can be triggered from production code
61 panic(fmt.Sprintf("Can't deep copy non-zero time.Time: %v", v.Interface()))
62 }
63 > nv := reflect.New(v.Type()).Elem() deepcopy.go
64 > for i := range v.Type().NumField() {
65 > nv.Field(i).Set(deepCopyValue(v.Field(i)))
66 > }
67 > return nv
68 > case reflect.Interface, reflect.Func, reflect.Chan:
69 > // only nil values of any other reference types allowed!
70 > if v.IsNil() {
71 > return v
72 > }
73 fallthrough
74 default:
go.temporal.io/server/common/persistence/client/health_request_rate_limiter.go 31 covered LOC · 5 ranges

Open complete file

50 metricsHandler metrics.Handler,
51 logger log.Logger,
52 > ) *HealthRequestRateLimiterImpl { health_request_rate_limiter.go
53 > rateBurst := quotas.NewDefaultRateBurst(rateFn, quotas.BurstRatioFn(burstRatio))
54 > limiter := &HealthRequestRateLimiterImpl{
55 > enabled: atomic.Bool{},
56 > rateLimiter: quotas.NewRateLimiter(rateBurst.Rate(), rateBurst.Burst()),
57 > healthSignals: healthSignals,
58 > rateBurst: rateBurst,
59 > params: params,
60 > refreshTimer: time.NewTicker(DefaultRefreshInterval),
61 > metricsHandler: metricsHandler,
62 > logger: logger,
63 > }
64 > curRateMultiplier := new(float64)
65 > *curRateMultiplier = DefaultInitialRateMultiplier
66 > limiter.curRateMultiplier.Store(curRateMultiplier)
67 > limiter.refreshDynamicParams()
68 > return limiter
69 > }
70
71 func (rl *HealthRequestRateLimiterImpl) Allow(now time.Time, request quotas.Request) bool {
77 }
78
79 > func (rl *HealthRequestRateLimiterImpl) Reserve(now time.Time, request quotas.Request) quotas.Reservation { health_request_rate_limiter.go
80 > rl.maybeRefresh()
81 > if !rl.enabled.Load() {
82 > return quotas.NoopReservation
83 > }
84 return rl.rateLimiter.ReserveN(now, request.Token)
85 }
93 }
94
95 > func (rl *HealthRequestRateLimiterImpl) maybeRefresh() { health_request_rate_limiter.go
96 > select {
97 case <-rl.refreshTimer.C:
98 rl.refreshDynamicParams()
139 }
140
141 > func (rl *HealthRequestRateLimiterImpl) refreshDynamicParams() { health_request_rate_limiter.go
142 > options := rl.params()
143 > rl.enabled.Store(options.Enabled)
144 > rl.curOptions.Store(&options)
145 > }
146
147 func (rl *HealthRequestRateLimiterImpl) updateRefreshTimer() {
go.temporal.io/server/common/persistence/operation_mode_validator.go 31 covered LOC · 12 ranges

Open complete file

15 mode CreateWorkflowMode,
16 newWorkflowSnapshot WorkflowSnapshot,
18 >
19 > workflowState := newWorkflowSnapshot.ExecutionState.State
20 > if err := checkWorkflowState(workflowState); err != nil {
21 return err
22 }
23
24 > switch mode { operation_mode_validator.go
25 case CreateWorkflowModeBrandNew,
26 > CreateWorkflowModeUpdateCurrent: operation_mode_validator.go
27 > if workflowState == enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE {
28 return newInvalidCreateWorkflowMode(
29 mode,
53 currentWorkflowMutation WorkflowMutation,
54 newWorkflowSnapshot *WorkflowSnapshot,
56 >
57 > currentWorkflowState := currentWorkflowMutation.ExecutionState.State
58 > if err := checkWorkflowState(currentWorkflowState); err != nil {
59 return err
60 }
61 > var newWorkflowState *enumsspb.WorkflowExecutionState operation_mode_validator.go
62 > if newWorkflowSnapshot != nil {
63 newWorkflowState = &newWorkflowSnapshot.ExecutionState.State
64 if err := checkWorkflowState(*newWorkflowState); err != nil {
67 }
68
69 > switch mode { operation_mode_validator.go
70 > case UpdateWorkflowModeUpdateCurrent: operation_mode_validator.go
71 > // update current record
72 > // 1. current workflow only ->
73 > // current workflow cannot be zombie
74 > // 2. current workflow & new workflow ->
75 > // current workflow cannot be created / running,
76 > // new workflow cannot be zombie
77 >
78 > // case 1
79 > if newWorkflowState == nil {
80 > if currentWorkflowState == enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE { operation_mode_validator.go
81 return newInvalidUpdateWorkflowMode(mode, currentWorkflowState)
82 }
83 > return nil operation_mode_validator.go
84 }
85
290 }
291
292 > func checkWorkflowState(state enumsspb.WorkflowExecutionState) error { operation_mode_validator.go
293 > switch state {
294 case enumsspb.WORKFLOW_EXECUTION_STATE_CREATED,
295 enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING,
296 enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE,
297 enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED,
298 > enumsspb.WORKFLOW_EXECUTION_STATE_CORRUPTED: operation_mode_validator.go
299 > return nil
300 default:
301 return serviceerror.NewInternalf("unknown workflow state: %v", state)
go.temporal.io/server/common/persistence/sql/nexus_endpoint_store.go 31 covered LOC · 11 ranges

Open complete file

34 logger log.Logger,
35 serializer serialization.Serializer,
36 > ) (p.NexusEndpointStore, error) { nexus_endpoint_store.go
37 > return &sqlNexusEndpointStore{
38 > SqlStore: NewSQLStore(db, logger, serializer),
39 > }, nil
40 > }
41
42 func (s *sqlNexusEndpointStore) CreateOrUpdateNexusEndpoint(
118 ctx context.Context,
119 request *p.ListNexusEndpointsRequest,
120 > ) (*p.InternalListNexusEndpointsResponse, error) { nexus_endpoint_store.go
121 > lastID := emptyID
122 > if len(request.NextPageToken) > 0 {
123 token, err := deserializePageTokenJson[listEndpointsNextPageToken](request.NextPageToken)
124 if err != nil {
128 }
129
130 > var response p.InternalListNexusEndpointsResponse nexus_endpoint_store.go
131 > var rows []sqlplugin.NexusEndpointsRow
132 > retErr := s.txExecute(ctx, "ListNexusEndpoints", func(tx sqlplugin.Tx) error {
133 > curTableVersion, err := tx.GetNexusEndpointsTableVersion(ctx)
134 > if err != nil {
135 return err
136 }
137 > response.TableVersion = curTableVersion nexus_endpoint_store.go
138 > if request.LastKnownTableVersion != 0 && request.LastKnownTableVersion != curTableVersion {
139 return p.ErrNexusTableVersionConflict
140 }
141
142 > if request.PageSize > 0 { nexus_endpoint_store.go
143 > // PageSize could be zero when fetching just the table version. nexus_endpoint_store.go
144 > rows, err = tx.ListNexusEndpoints(ctx, &sqlplugin.ListNexusEndpointsRequest{
145 > LastID: lastID,
146 > Limit: request.PageSize,
147 > })
148 > }
149
150 > return err nexus_endpoint_store.go
151 })
152
153 > if retErr != nil { nexus_endpoint_store.go
154 return &response, retErr
155 }
156
157 > var nextPageToken []byte nexus_endpoint_store.go
158 > if len(rows) > 0 && len(rows) == request.PageSize {
159 // len(rows) could be zero when fetching just the table version.
160 nextPageToken, retErr = serializePageTokenJson(&listEndpointsNextPageToken{
166 }
167 }
168 > response.NextPageToken = nextPageToken nexus_endpoint_store.go
169 >
170 > response.Endpoints = make([]p.InternalNexusEndpoint, len(rows))
171 > for i, row := range rows {
172 response.Endpoints[i].ID = primitives.UUIDString(row.ID)
173 response.Endpoints[i].Version = row.Version
go.temporal.io/server/common/persistence/sql/task_v2.go 31 covered LOC · 9 ranges

Open complete file

28 logger log.Logger,
29 serializer serialization.Serializer,
30 > ) (*sqlTaskManagerV2, error) { task_v2.go
31 > return &sqlTaskManagerV2{
32 > SqlStore: NewSQLStore(db, logger, serializer),
33 > userDataStore: uds,
34 > taskQueueStore: tqs,
35 > }, nil
36 > }
37
38 func (m *sqlTaskManagerV2) CreateTasks(
99 ctx context.Context,
100 request *persistence.GetTasksRequest,
101 > ) (*persistence.InternalGetTasksResponse, error) { task_v2.go
102 > if request.InclusiveMinPass < 1 {
103 return nil, serviceerror.NewInternal("invalid GetTasks request on fair queue: InclusiveMinPass must be >= 1")
104 }
105 > if request.ExclusiveMaxTaskID != math.MaxInt64 { task_v2.go
106 // ExclusiveMaxTaskID is not supported in fair queue.
107 return nil, serviceerror.NewInternal("invalid GetTasks request on fair queue: ExclusiveMaxTaskID is not supported")
108 }
109 > nidBytes, err := primitives.ParseUUID(request.NamespaceID) task_v2.go
110 > if err != nil {
111 return nil, serviceerror.NewUnavailable(err.Error())
112 }
113
114 > inclusiveMinLevel := sqlplugin.FairLevel{ task_v2.go
115 > TaskPass: request.InclusiveMinPass,
116 > TaskID: request.InclusiveMinTaskID,
117 > }
118 > if len(request.NextPageToken) != 0 {
119 token, err := deserializePageTokenJson[matchingTaskPageToken](request.NextPageToken)
120 if err != nil {
129 }
130
131 > tqId, tqHash := taskQueueIdAndHash(nidBytes, request.TaskQueue, request.TaskType, request.Subqueue) task_v2.go
132 > rows, err := m.DB.SelectFromTasksV2(ctx, sqlplugin.TasksFilterV2{
133 > RangeHash: tqHash,
134 > TaskQueueID: tqId,
135 > InclusiveMinLevel: &inclusiveMinLevel,
136 > PageSize: &request.PageSize,
137 > })
138 > if err != nil {
139 return nil, serviceerror.NewUnavailablef("GetTasks operation failed. Failed to get rows. Error: %v", err)
140 }
141
142 > response := &persistence.InternalGetTasksResponse{ task_v2.go
143 > Tasks: make([]*commonpb.DataBlob, len(rows)),
144 > }
145 > for i, v := range rows {
146 response.Tasks[i] = persistence.NewDataBlob(v.Data, v.DataEncoding)
147 }
148 > if len(rows) == request.PageSize { task_v2.go
149 token, err := serializePageTokenJson(&matchingTaskPageToken{
150 TaskPass: rows[len(rows)-1].TaskPass,
157 }
158
159 > return response, nil task_v2.go
160 }
161
go.temporal.io/server/common/rpc/interceptor/namespace_handover.go 31 covered LOC · 9 ranges

Open complete file

52 requestErrorHandler ErrorHandler,
53 additionalAllowedMethodsDuringHandover []string,
54 > ) *NamespaceHandoverInterceptor { namespace_handover.go
55 >
56 > additional := make(map[string]struct{}, len(additionalAllowedMethodsDuringHandover))
57 > for _, m := range additionalAllowedMethodsDuringHandover {
58 additional[m] = struct{}{}
59 }
60
61 > return &NamespaceHandoverInterceptor{ namespace_handover.go
62 > enabledForNS: dynamicconfig.EnableNamespaceHandoverWait.Get(dc),
63 > nsCacheRefreshInterval: dynamicconfig.NamespaceCacheRefreshInterval.Get(dc),
64 > namespaceRegistry: namespaceRegistry,
65 > metricsHandler: metricsHandler,
66 > logger: logger,
67 > timeSource: timeSource,
68 > requestErrorHandler: requestErrorHandler,
69 > additionalAllowedMethodsDuringHandover: additional,
70 > }
71 }
72
82 // handlesMethod reports whether the handover gate applies to fullMethod: always for WorkflowService,
83 // plus any embedder-configured service prefixes.
84 > func (i *NamespaceHandoverInterceptor) handlesMethod(fullMethod string) bool { namespace_handover.go
85 > if strings.HasPrefix(fullMethod, api.WorkflowServicePrefix) {
86 > return true
87 > }
88 > for _, prefix := range i.additionalServicePrefixes { namespace_handover.go
89 if strings.HasPrefix(fullMethod, prefix) {
90 return true
91 }
92 }
93 > return false namespace_handover.go
94 }
95
99 info *grpc.UnaryServerInfo,
100 handler grpc.UnaryHandler,
101 > ) (_ any, retError error) { namespace_handover.go
102 > defer log.CapturePanic(i.logger, &retError)
103 >
104 > if !i.handlesMethod(info.FullMethod) {
105 > return handler(ctx, req) namespace_handover.go
106 > }
107
108 // review which method is allowed
109 > methodName := api.MethodName(info.FullMethod) namespace_handover.go
110 > namespaceName := MustGetNamespaceName(i.namespaceRegistry, req)
111 >
112 > if namespaceName != namespace.EmptyName && i.enabledForNS(namespaceName.String()) {
113 var waitTime *time.Duration
114 defer func() {
go.temporal.io/server/api/routing/v1/extension.pb.go 30 covered LOC · 4 ranges

Open complete file

50 func (*RoutingOptions) ProtoMessage() {}
51
52 > func (x *RoutingOptions) ProtoReflect() protoreflect.Message { extension.pb.go
53 > mi := &file_temporal_server_api_routing_v1_extension_proto_msgTypes[0]
54 > if x != nil {
55 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
56 > if ms.LoadMessageInfo() == nil {
57 > ms.StoreMessageInfo(mi)
58 > }
59 > return ms
60 }
61 > return mi.MessageOf(x) extension.pb.go
62 }
63
144 }
145
146 > func init() { file_temporal_server_api_routing_v1_extension_proto_init() } extension.pb.go
147 > func file_temporal_server_api_routing_v1_extension_proto_init() {
148 > if File_temporal_server_api_routing_v1_extension_proto != nil {
149 return
150 }
151 > type x struct{} extension.pb.go
152 > out := protoimpl.TypeBuilder{
153 > File: protoimpl.DescBuilder{
154 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
155 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_routing_v1_extension_proto_rawDesc), len(file_temporal_server_api_routing_v1_extension_proto_rawDesc)),
156 > NumEnums: 0,
157 > NumMessages: 1,
158 > NumExtensions: 1,
159 > NumServices: 0,
160 > },
161 > GoTypes: file_temporal_server_api_routing_v1_extension_proto_goTypes,
162 > DependencyIndexes: file_temporal_server_api_routing_v1_extension_proto_depIdxs,
163 > MessageInfos: file_temporal_server_api_routing_v1_extension_proto_msgTypes,
164 > ExtensionInfos: file_temporal_server_api_routing_v1_extension_proto_extTypes,
165 > }.Build()
166 > File_temporal_server_api_routing_v1_extension_proto = out.File
167 > file_temporal_server_api_routing_v1_extension_proto_goTypes = nil
168 > file_temporal_server_api_routing_v1_extension_proto_depIdxs = nil
169 }
go.temporal.io/server/chasm/lib/tests/gen/testspb/v1/request_response.pb.go 30 covered LOC · 5 ranges

Open complete file

43 func (*TestRequest) ProtoMessage() {}
44
45 > func (x *TestRequest) ProtoReflect() protoreflect.Message { request_response.pb.go
46 > mi := &file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_msgTypes[0]
47 > if x != nil {
48 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
49 if ms.LoadMessageInfo() == nil {
88 func (*TestResponse) ProtoMessage() {}
89
90 > func (x *TestResponse) ProtoReflect() protoreflect.Message { request_response.pb.go
91 > mi := &file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_msgTypes[1]
92 > if x != nil {
93 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
94 if ms.LoadMessageInfo() == nil {
157 }
158
159 > func init() { file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_init() } request_response.pb.go
160 > func file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_init() {
161 > if File_temporal_server_chasm_lib_tests_proto_v1_request_response_proto != nil {
162 > return
163 > }
164 > type x struct{}
165 > out := protoimpl.TypeBuilder{
166 > File: protoimpl.DescBuilder{
167 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
168 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_rawDesc), len(file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_rawDesc)),
169 > NumEnums: 0,
170 > NumMessages: 2,
171 > NumExtensions: 0,
172 > NumServices: 0,
173 > },
174 > GoTypes: file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_goTypes,
175 > DependencyIndexes: file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_depIdxs,
176 > MessageInfos: file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_msgTypes,
177 > }.Build()
178 > File_temporal_server_chasm_lib_tests_proto_v1_request_response_proto = out.File
179 > file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_goTypes = nil
180 > file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_depIdxs = nil
181 }
go.temporal.io/server/common/persistence/sql/sqlplugin/mysql/execution_maps.go 30 covered LOC · 5 ranges

Open complete file

53 )
54
55 > func stringMap(a []string, f func(string) string) []string { execution_maps.go
56 > b := make([]string, len(a))
57 > for i, v := range a {
58 > b[i] = f(v)
59 > }
60 > return b
61 }
62
63 > func makeDeleteMapQry(tableName string) string { execution_maps.go
64 > return fmt.Sprintf(deleteMapQryTemplate, tableName)
65 > }
66
67 > func makeSetKeyInMapQry(tableName string, nonPrimaryKeyColumns []string, mapKeyName string) string { execution_maps.go
68 > return fmt.Sprintf(setKeyInMapQryTemplate,
69 > tableName,
70 > strings.Join(nonPrimaryKeyColumns, ","),
71 > strings.Join(stringMap(nonPrimaryKeyColumns, func(x string) string {
72 > return ":" + x
73 > }), ","),
74 > strings.Join(stringMap(nonPrimaryKeyColumns, func(x string) string {
75 > return x + "=VALUES(" + x + ")"
76 > }), ","),
77 mapKeyName)
78 }
79
80 > func makeDeleteKeyInMapQry(tableName string, mapKeyName string) string { execution_maps.go
81 > return fmt.Sprintf(deleteKeyInMapQryTemplate,
82 > tableName,
83 > mapKeyName)
84 > }
85
86 > func makeGetMapQryTemplate(tableName string, nonPrimaryKeyColumns []string, mapKeyName string) string { execution_maps.go
87 > return fmt.Sprintf(getMapQryTemplate,
88 > tableName,
89 > mapKeyName,
90 > strings.Join(nonPrimaryKeyColumns, ","))
91 > }
92
93 var (
go.temporal.io/server/common/persistence/sql/sqlplugin/postgresql/execution_maps.go 30 covered LOC · 6 ranges

Open complete file

86 )
87
88 > func stringMap(a []string, f func(string) string) []string { execution_maps.go
89 > b := make([]string, len(a))
90 > for i, v := range a {
91 > b[i] = f(v)
92 > }
93 > return b
94 }
95
96 > func makeDeleteMapQry(tableName string) string { execution_maps.go
97 > return fmt.Sprintf(deleteMapQueryTemplate, tableName)
98 > }
99
100 > func makeSetKeyInMapQry(tableName string, nonPrimaryKeyColumns []string, mapKeyName string) string { execution_maps.go
101 > return fmt.Sprintf(setKeyInMapQueryTemplate,
102 > tableName,
103 > strings.Join(nonPrimaryKeyColumns, ","),
104 > strings.Join(stringMap(nonPrimaryKeyColumns, func(x string) string {
105 > return ":" + x
106 > }), ","),
107 mapKeyName,
108 > strings.Join(stringMap(nonPrimaryKeyColumns, func(x string) string { execution_maps.go
109 > return "excluded." + x
110 > }), ","))
111 }
112
113 > func makeDeleteKeyInMapQry(tableName string, mapKeyName string) string { execution_maps.go
114 > return fmt.Sprintf(deleteKeyInMapQueryTemplate,
115 > tableName,
116 > mapKeyName)
117 > }
118
119 > func makeGetMapQryTemplate(tableName string, nonPrimaryKeyColumns []string, mapKeyName string) string { execution_maps.go
120 > return fmt.Sprintf(getMapQueryTemplate,
121 > tableName,
122 > mapKeyName,
123 > strings.Join(nonPrimaryKeyColumns, ","))
124 > }
125
126 var (
go.temporal.io/server/common/persistence/versionhistory/version_histories.go 30 covered LOC · 12 ranges

Open complete file

7
8 // NewVersionHistories create a new instance of VersionHistories.
9 > func NewVersionHistories(versionHistory *historyspb.VersionHistory) *historyspb.VersionHistories { version_histories.go
10 > if versionHistory == nil {
11 panic("version history cannot be null")
12 }
13
14 > return &historyspb.VersionHistories{ version_histories.go
15 > CurrentVersionHistoryIndex: 0,
16 > Histories: []*historyspb.VersionHistory{versionHistory},
17 > }
18 }
19
20 // Copy VersionHistories.
21 > func CopyVersionHistories(h *historyspb.VersionHistories) *historyspb.VersionHistories { version_histories.go
22 > var histories []*historyspb.VersionHistory
23 > for _, history := range h.Histories {
24 > histories = append(histories, CopyVersionHistory(history)) version_histories.go
25 > }
26
27 > return &historyspb.VersionHistories{ version_histories.go
28 > CurrentVersionHistoryIndex: h.CurrentVersionHistoryIndex,
29 > Histories: histories,
30 > }
31 }
32
33 // GetVersionHistory gets the VersionHistory according to index provided.
34 > func GetVersionHistory(h *historyspb.VersionHistories, index int32) (*historyspb.VersionHistory, error) { version_histories.go
35 > if index < 0 || index >= int32(len(h.Histories)) {
36 return nil, serviceerror.NewInternal("version histories index is out of range.")
37 }
38
39 > return h.Histories[index], nil version_histories.go
40 }
41
159
160 // FindFirstVersionHistoryIndexByVersionHistoryItem find the first VersionHistory index which contains the given version history item.
161 > func FindFirstVersionHistoryIndexByVersionHistoryItem(h *historyspb.VersionHistories, item *historyspb.VersionHistoryItem) (int32, error) { version_histories.go
162 > for versionHistoryIndex, history := range h.Histories {
163 > if ContainsVersionHistoryItem(history, item) {
164 > return int32(versionHistoryIndex), nil version_histories.go
165 > }
166 }
167 return 0, serviceerror.NewInternalf("version histories does not contains given item: %v, %v", item, h)
179
180 // GetCurrentVersionHistory gets the current VersionHistory.
181 > func GetCurrentVersionHistory(h *historyspb.VersionHistories) (*historyspb.VersionHistory, error) { version_histories.go
182 > return GetVersionHistory(h, h.GetCurrentVersionHistoryIndex())
183 > }
184
185 // IsCurrentVersionHistoryEmpty checks if the current VersionHistory is empty.
186 > func IsCurrentVersionHistoryEmpty(h *historyspb.VersionHistories) (bool, error) { version_histories.go
187 > currentVersionHistory, err := GetCurrentVersionHistory(h)
188 > if err != nil {
189 return false, err
190 }
191 > return IsEmptyVersionHistory(currentVersionHistory), nil version_histories.go
192 }
go.temporal.io/server/components/nexusoperations/executors.go 30 covered LOC · 7 ranges

Open complete file

74 registry *hsm.Registry,
75 options TaskExecutorOptions,
76 > ) error { executors.go
77 > exec := taskExecutor{options}
78 > if err := hsm.RegisterImmediateExecutor(
79 > registry,
80 > exec.executeInvocationTask,
81 > ); err != nil {
82 return err
83 }
84 > if err := hsm.RegisterTimerExecutor( executors.go
85 > registry,
86 > exec.executeBackoffTask,
87 > ); err != nil {
88 return err
89 }
90 > if err := hsm.RegisterTimerExecutor( executors.go
91 > registry,
92 > exec.executeScheduleToCloseTimeoutTask,
93 > ); err != nil {
94 return err
95 }
96 > if err := hsm.RegisterTimerExecutor( executors.go
97 > registry,
98 > exec.executeScheduleToStartTimeoutTask,
99 > ); err != nil {
100 return err
101 }
102 > if err := hsm.RegisterTimerExecutor( executors.go
103 > registry,
104 > exec.executeStartToCloseTimeoutTask,
105 > ); err != nil {
106 return err
107 }
108 > if err := hsm.RegisterImmediateExecutor( executors.go
109 > registry,
110 > exec.executeCancelationTask,
111 > ); err != nil {
112 return err
113 }
114 > return hsm.RegisterTimerExecutor( executors.go
115 > registry,
116 > exec.executeCancelationBackoffTask,
117 > )
118 }
119
go.temporal.io/server/api/enums/v1/common.pb.go 29 covered LOC · 5 ranges

Open complete file

66 }
67
68 > func (DeadLetterQueueType) Descriptor() protoreflect.EnumDescriptor { common.pb.go
69 > return file_temporal_server_api_enums_v1_common_proto_enumTypes[0].Descriptor()
70 > }
71
72 func (DeadLetterQueueType) Type() protoreflect.EnumType {
120 }
121
122 > func (ChecksumFlavor) Descriptor() protoreflect.EnumDescriptor { common.pb.go
123 > return file_temporal_server_api_enums_v1_common_proto_enumTypes[1].Descriptor()
124 > }
125
126 func (ChecksumFlavor) Type() protoreflect.EnumType {
201 }
202
203 > func (CallbackState) Descriptor() protoreflect.EnumDescriptor { common.pb.go
204 > return file_temporal_server_api_enums_v1_common_proto_enumTypes[2].Descriptor()
205 > }
206
207 func (CallbackState) Type() protoreflect.EnumType {
264 }
265
266 > func init() { file_temporal_server_api_enums_v1_common_proto_init() } common.pb.go
267 > func file_temporal_server_api_enums_v1_common_proto_init() {
268 > if File_temporal_server_api_enums_v1_common_proto != nil {
269 return
270 }
271 > type x struct{} common.pb.go
272 > out := protoimpl.TypeBuilder{
273 > File: protoimpl.DescBuilder{
274 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
275 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_common_proto_rawDesc), len(file_temporal_server_api_enums_v1_common_proto_rawDesc)),
276 > NumEnums: 3,
277 > NumMessages: 0,
278 > NumExtensions: 0,
279 > NumServices: 0,
280 > },
281 > GoTypes: file_temporal_server_api_enums_v1_common_proto_goTypes,
282 > DependencyIndexes: file_temporal_server_api_enums_v1_common_proto_depIdxs,
283 > EnumInfos: file_temporal_server_api_enums_v1_common_proto_enumTypes,
284 > }.Build()
285 > File_temporal_server_api_enums_v1_common_proto = out.File
286 > file_temporal_server_api_enums_v1_common_proto_goTypes = nil
287 > file_temporal_server_api_enums_v1_common_proto_depIdxs = nil
288 }
go.temporal.io/server/api/enums/v1/workflow_task_type.pb.go 29 covered LOC · 6 ranges

Open complete file

72 }
73
74 > func (WorkflowTaskType) Descriptor() protoreflect.EnumDescriptor { workflow_task_type.pb.go
75 > return file_temporal_server_api_enums_v1_workflow_task_type_proto_enumTypes[0].Descriptor()
76 > }
77
78 func (WorkflowTaskType) Type() protoreflect.EnumType {
124 }
125
126 > func init() { file_temporal_server_api_enums_v1_workflow_task_type_proto_init() } workflow_task_type.pb.go
127 > func file_temporal_server_api_enums_v1_workflow_task_type_proto_init() {
128 > if File_temporal_server_api_enums_v1_workflow_task_type_proto != nil {
129 return
130 }
131 > type x struct{} workflow_task_type.pb.go
132 > out := protoimpl.TypeBuilder{
133 > File: protoimpl.DescBuilder{
134 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
135 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_workflow_task_type_proto_rawDesc), len(file_temporal_server_api_enums_v1_workflow_task_type_proto_rawDesc)),
136 > NumEnums: 1,
137 > NumMessages: 0,
138 > NumExtensions: 0,
139 > NumServices: 0,
140 > },
141 > GoTypes: file_temporal_server_api_enums_v1_workflow_task_type_proto_goTypes,
142 > DependencyIndexes: file_temporal_server_api_enums_v1_workflow_task_type_proto_depIdxs,
143 > EnumInfos: file_temporal_server_api_enums_v1_workflow_task_type_proto_enumTypes,
144 > }.Build()
145 > File_temporal_server_api_enums_v1_workflow_task_type_proto = out.File
146 > file_temporal_server_api_enums_v1_workflow_task_type_proto_goTypes = nil
147 > file_temporal_server_api_enums_v1_workflow_task_type_proto_depIdxs = nil
148 }
go.temporal.io/server/common/log/sdk_logger.go 29 covered LOC · 13 ranges

Open complete file

19 var _ log.Logger = (*SdkLogger)(nil)
20
21 > func NewSdkLogger(logger Logger) *SdkLogger { sdk_logger.go
22 > if sl, ok := logger.(SkipLogger); ok {
23 logger = sl.Skip(extraSkipForSdkLogger)
24 }
25
26 > return &SdkLogger{ sdk_logger.go
27 > logger: logger,
28 > }
29 }
30
31 > func (l *SdkLogger) tags(keyvals []any) []tag.Tag { sdk_logger.go
32 > var tags []tag.Tag
33 > for i := 0; i < len(keyvals); i++ {
34 > if t, keyvalIsTag := keyvals[i].(tag.Tag); keyvalIsTag { sdk_logger.go
35 tags = append(tags, t)
36 continue
37 }
38
39 > key, keyIsString := keyvals[i].(string) sdk_logger.go
40 > if !keyIsString {
41 key = fmt.Sprintf("%v", keyvals[i])
42 }
43 > var val any sdk_logger.go
44 > if i+1 == len(keyvals) {
45 val = noValue
46 > } else { sdk_logger.go
47 > val = keyvals[i+1] sdk_logger.go
48 > i++
49 > }
50
51 > tags = append(tags, tag.Any(key, val)) sdk_logger.go
52 }
53
54 > return tags sdk_logger.go
55 }
56
59 }
60
61 > func (l *SdkLogger) Info(msg string, keyvals ...any) { sdk_logger.go
62 > l.logger.Info(msg, l.tags(keyvals)...)
63 > }
64
65 > func (l *SdkLogger) Warn(msg string, keyvals ...any) { sdk_logger.go
66 > l.logger.Warn(msg, l.tags(keyvals)...)
67 > }
68
69 func (l *SdkLogger) Error(msg string, keyvals ...any) {
71 }
72
73 > func (l *SdkLogger) With(keyvals ...any) log.Logger { sdk_logger.go
74 > return NewSdkLogger(
75 > With(l.logger, l.tags(keyvals)...))
76 > }
go.temporal.io/server/common/payload/payload.go 29 covered LOC · 13 ranges

Open complete file

30 }
31
32 > func Encode(value any) (*commonpb.Payload, error) { payload.go
33 > return defaultDataConverter.ToPayload(value)
34 > }
35
36 > func Decode(p *commonpb.Payload, valuePtr any) error { payload.go
37 > return defaultDataConverter.FromPayload(p, valuePtr)
38 > }
39
40 func ToString(p *commonpb.Payload) string {
67 dst map[string]*commonpb.Payload,
68 src map[string]*commonpb.Payload,
69 > ) map[string]*commonpb.Payload { payload.go
70 > if src == nil {
71 return maps.Clone(dst)
72 }
73 > res := util.CloneMapNonNil(dst) payload.go
74 > for k, v := range src {
75 > if isNilPayload(v) { payload.go
76 delete(res, k)
77 > } else { payload.go
78 > res[k] = v payload.go
79 > }
80 }
81 > return res payload.go
82 }
83
88 // - payload's data is "null" (json encoded value for nil objects)
89 // - payload's data is "[]" (empty slice for backwards compatibility)
90 > func isNilPayload(p *commonpb.Payload) bool { payload.go
91 > return p == nil ||
92 > bytes.Equal(p.Data, nilPayload.Data) ||
93 > bytes.Equal(p.Data, nilSlicePayload.Data) ||
94 > bytes.Equal(p.Data, emptySlicePayload.Data)
95 > }
96
97 // FilterNilSearchAttributes returns a new SearchAttributes with nil/empty payload values filtered out.
99 // This is used to filter out nil search attributes from workflow start and continue-as-new events.
100 // Reuses MergeMapOfPayload which already handles nil payload filtering.
101 > func FilterNilSearchAttributes(sa *commonpb.SearchAttributes) *commonpb.SearchAttributes { payload.go
102 > if sa == nil || len(sa.GetIndexedFields()) == 0 {
103 > return nil payload.go
104 > }
105
106 filtered := MergeMapOfPayload(nil, sa.GetIndexedFields())
115 // This is used to filter out nil memo fields from workflow start, continue-as-new, and modify-properties events.
116 // Reuses MergeMapOfPayload which already handles nil payload filtering.
117 > func FilterNilMemo(memo *commonpb.Memo) *commonpb.Memo { payload.go
118 > if memo == nil || len(memo.GetFields()) == 0 {
119 > return nil payload.go
120 > }
121
122 filtered := MergeMapOfPayload(nil, memo.GetFields())
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/conn_pool.go 29 covered LOC · 9 ranges

Open complete file

23 }
24
25 > func newConnPool() *connPool { conn_pool.go
26 > return &connPool{
27 > pool: make(map[string]entry),
28 > }
29 > }
30
31 // Allocate allocates the shared database in the pool or returns already exists instance with the same DSN. If instance
36 logger log.Logger,
37 create func(*config.SQL, resolver.ServiceResolver, log.Logger) (*sqlx.DB, error),
38 > ) (db *sqlx.DB, err error) { conn_pool.go
39 > cp.mu.Lock()
40 > defer cp.mu.Unlock()
41 >
42 > dsn, err := buildDSN(cfg)
43 > if err != nil {
44 return nil, err
45 }
46
47 > if entry, ok := cp.pool[dsn]; ok { conn_pool.go
48 > entry.refCount++ conn_pool.go
49 > return entry.db, nil
50 > }
51
52 > db, err = create(cfg, resolver, logger) conn_pool.go
53 > if err != nil {
54 return nil, err
55 }
56
57 > cp.pool[dsn] = entry{db: db, refCount: 1} conn_pool.go
58 >
59 > return db, nil
60 }
61
62 // Close virtual connection to database. Only closes for real once no references left.
63 > func (cp *connPool) Close(cfg *config.SQL) { conn_pool.go
64 > cp.mu.Lock()
65 > defer cp.mu.Unlock()
66 >
67 > dsn, err := buildDSN(cfg)
68 > if err != nil {
69 return
70 }
71
72 > e, ok := cp.pool[dsn] conn_pool.go
73 > if !ok {
74 // no such database
75 return
76 }
77
78 > e.refCount-- conn_pool.go
79 // todo: at the moment pool will persist a single connection to the DB for the whole duration of application
80 // temporal will start and stop DB connections multiple times, which will cause the loss of the cache
go.temporal.io/server/common/rpc/interceptor/rate_limit.go 29 covered LOC · 9 ranges

Open complete file

37 rateLimiter quotas.RequestRateLimiter,
38 tokens map[string]int,
39 > ) *RateLimitInterceptor { rate_limit.go
40 > return &RateLimitInterceptor{
41 > rateLimiter: rateLimiter,
42 > tokens: tokens,
43 > }
44 > }
45
46 func (i *RateLimitInterceptor) Intercept(
49 info *grpc.UnaryServerInfo,
50 handler grpc.UnaryHandler,
51 > ) (any, error) { rate_limit.go
52 > methodName := info.FullMethod
53 >
54 > // for DescribeTaskQueueRequest, we want to use visibility rate limit only if reachability is queried
55 > describeTQReq, ok := req.(*workflowservice.DescribeTaskQueueRequest)
56 > if ok && describeTQReq.GetReportTaskReachability() {
57 methodName += "WithReachability"
58 }
59
60 > if err := i.Allow(methodName, headers.NewGRPCHeaderGetter(ctx)); err != nil { rate_limit.go
61 return nil, err
62 }
63
64 > return handler(ctx, req) rate_limit.go
65 }
66
68 methodName string,
69 headerGetter headers.HeaderGetter,
70 > ) error { rate_limit.go
71 > token, ok := i.tokens[methodName]
72 > if !ok {
73 > token = RateLimitDefaultToken rate_limit.go
74 > }
75
76 // we don't want to apply rate limiter if a method is configured with 0 tokens.
77 > if token < 1 { rate_limit.go
78 return nil
79 }
80
81 > if !i.rateLimiter.Allow(time.Now().UTC(), quotas.NewRequest( rate_limit.go
82 > methodName,
83 > token,
84 > headerGetter.Get(headers.CallerNameHeaderName),
85 > headerGetter.Get(headers.CallerTypeHeaderName),
86 > 0, // this interceptor layer does not throttle based on caller segment
87 > "", // this interceptor layer does not throttle based on call initiation
88 > )) {
89 return RateLimitServerBusy
90 }
91 > return nil rate_limit.go
92 }
go.temporal.io/server/components/nexusoperations/tasks.go 29 covered LOC · 14 ranges

Open complete file

35 var _ hsm.Task = ScheduleToCloseTimeoutTask{}
36
37 > func (ScheduleToCloseTimeoutTask) Type() string { tasks.go
38 > return TaskTypeScheduleToCloseTimeout
39 > }
40
41 func (t ScheduleToCloseTimeoutTask) Deadline() time.Time {
84 var _ hsm.Task = InvocationTask{}
85
86 > func (InvocationTask) Type() string { tasks.go
87 > return TaskTypeInvocation
88 > }
89
90 func (InvocationTask) Deadline() time.Time {
129 var _ hsm.Task = BackoffTask{}
130
131 > func (BackoffTask) Type() string { tasks.go
132 > return TaskTypeBackoff
133 > }
134
135 func (t BackoffTask) Deadline() time.Time {
165 var _ hsm.Task = CancelationTask{}
166
167 > func (CancelationTask) Type() string { tasks.go
168 > return TaskTypeCancelation
169 > }
170
171 func (CancelationTask) Deadline() time.Time {
210 var _ hsm.Task = CancelationBackoffTask{}
211
212 > func (CancelationBackoffTask) Type() string { tasks.go
213 > return TaskTypeCancelationBackoff
214 > }
215
216 func (t CancelationBackoffTask) Deadline() time.Time {
245 var _ hsm.Task = ScheduleToStartTimeoutTask{}
246
247 > func (ScheduleToStartTimeoutTask) Type() string { tasks.go
248 > return TaskTypeScheduleToStartTimeout
249 > }
250
251 func (t ScheduleToStartTimeoutTask) Deadline() time.Time {
299 var _ hsm.Task = StartToCloseTimeoutTask{}
300
301 > func (StartToCloseTimeoutTask) Type() string { tasks.go
302 > return TaskTypeStartToCloseTimeout
303 > }
304
305 func (t StartToCloseTimeoutTask) Deadline() time.Time {
343 }
344
345 > func RegisterTaskSerializers(reg *hsm.Registry) error { tasks.go
346 > if err := reg.RegisterTaskSerializer(TaskTypeScheduleToCloseTimeout, TimeoutTaskSerializer{}); err != nil {
347 return err
348 }
349 > if err := reg.RegisterTaskSerializer(TaskTypeInvocation, InvocationTaskSerializer{}); err != nil { tasks.go
350 return err
351 }
352 > if err := reg.RegisterTaskSerializer(TaskTypeBackoff, BackoffTaskSerializer{}); err != nil { tasks.go
353 return err
354 }
355 > if err := reg.RegisterTaskSerializer(TaskTypeCancelation, CancelationTaskSerializer{}); err != nil { tasks.go
356 return err
357 }
358 > if err := reg.RegisterTaskSerializer(TaskTypeCancelationBackoff, CancelationBackoffTaskSerializer{}); err != nil { // nolint:revive tasks.go
359 return err
360 }
361 > if err := reg.RegisterTaskSerializer(TaskTypeScheduleToStartTimeout, ScheduleToStartTimeoutTaskSerializer{}); err != nil { tasks.go
362 return err
363 }
364 > return reg.RegisterTaskSerializer(TaskTypeStartToCloseTimeout, StartToCloseTimeoutTaskSerializer{}) tasks.go
365 }
go.temporal.io/server/service/history/queues/range.go 29 covered LOC · 10 ranges

Open complete file

17 inclusiveMin tasks.Key,
18 exclusiveMax tasks.Key,
19 > ) Range { range.go
20 > if inclusiveMin.CompareTo(exclusiveMax) > 0 {
21 panic(fmt.Sprintf("invalid task range, min %v is larger than max %v", inclusiveMin, exclusiveMax))
22 }
23
24 > return Range{ range.go
25 > InclusiveMin: inclusiveMin,
26 > ExclusiveMax: exclusiveMax,
27 > }
28 }
29
30 > func (r *Range) IsEmpty() bool { range.go
31 > return r.InclusiveMin.CompareTo(r.ExclusiveMax) == 0
32 > }
33
34 func (r *Range) ContainsKey(
35 key tasks.Key,
36 > ) bool { range.go
37 > return key.CompareTo(r.InclusiveMin) >= 0 &&
38 > key.CompareTo(r.ExclusiveMax) < 0
39 > }
40
41 func (r *Range) ContainsRange(
48 func (r *Range) CanSplit(
49 key tasks.Key,
50 > ) bool { range.go
51 > return r.ContainsKey(key) || r.ExclusiveMax.CompareTo(key) == 0
52 > }
53
54 func (r *Range) Split(
55 key tasks.Key,
56 > ) (left Range, right Range) { range.go
57 > if !r.CanSplit(key) {
58 panic(fmt.Sprintf("Unable to split range %v at %v", r, key))
59 }
60
61 > return NewRange(r.InclusiveMin, key), NewRange(key, r.ExclusiveMax) range.go
62 }
63
64 func (r *Range) CanMerge(
65 input Range,
66 > ) bool { range.go
67 > return r.InclusiveMin.CompareTo(input.ExclusiveMax) <= 0 &&
68 > r.ExclusiveMax.CompareTo(input.InclusiveMin) >= 0
69 > }
70
71 func (r *Range) Merge(
72 input Range,
73 > ) Range { range.go
74 > if !r.CanMerge(input) {
75 panic(fmt.Sprintf("Unable to merge range %v with incoming range %v", r, input))
76 }
77
78 > return NewRange( range.go
79 > tasks.MinKey(r.InclusiveMin, input.InclusiveMin),
80 > tasks.MaxKey(r.ExclusiveMax, input.ExclusiveMax),
81 > )
82 }
83
go.temporal.io/server/service/history/shard/ownership_based_quota_calculator.go 29 covered LOC · 8 ranges

Open complete file

24 perInstanceQuota func() int,
25 globalQuota func() int,
26 > ) *OwnershipAwareQuotaCalculator { ownership_based_quota_calculator.go
27 > return &OwnershipAwareQuotaCalculator{
28 > ClusterAwareQuotaCalculator: calculator.ClusterAwareQuotaCalculator{
29 > MemberCounter: memberCounter,
30 > PerInstanceQuota: perInstanceQuota,
31 > GlobalQuota: globalQuota,
32 > },
33 > scaler: scaler,
34 > }
35 > }
36
37 > func (c *OwnershipAwareQuotaCalculator) GetQuota() float64 { ownership_based_quota_calculator.go
38 > if quota, ok := getOwnershipScaledQuota(c.scaler, c.GlobalQuota()); ok {
39 return quota
40 }
41 > return c.ClusterAwareQuotaCalculator.GetQuota() ownership_based_quota_calculator.go
42 }
43
47 perInstanceQuota func(namespace string) int,
48 globalQuota func(namespace string) int,
49 > ) *OwnershipAwareNamespaceQuotaCalculator { ownership_based_quota_calculator.go
50 > return &OwnershipAwareNamespaceQuotaCalculator{
51 > ClusterAwareNamespaceQuotaCalculator: calculator.ClusterAwareNamespaceQuotaCalculator{
52 > MemberCounter: memberCounter,
53 > PerInstanceQuota: perInstanceQuota,
54 > GlobalQuota: globalQuota,
55 > },
56 > scaler: scaler,
57 > }
58 > }
59
60 > func (c *OwnershipAwareNamespaceQuotaCalculator) GetQuota(namespace string) float64 { ownership_based_quota_calculator.go
61 > if quota, ok := getOwnershipScaledQuota(c.scaler, c.GlobalQuota(namespace)); ok {
62 return quota
63 }
64 > return c.ClusterAwareNamespaceQuotaCalculator.GetQuota(namespace) ownership_based_quota_calculator.go
65 }
66
go.temporal.io/server/service/matching/configs/quotas.go 29 covered LOC · 5 ranges

Open complete file

65 rateFn quotas.RateFn,
66 operatorRPSRatio dynamicconfig.FloatPropertyFn,
67 > ) quotas.RequestRateLimiter { quotas.go
68 > return quotas.NewPriorityRateLimiterHelper(
69 > quotas.NewDefaultIncomingRateBurst(rateFn),
70 > operatorRPSRatio,
71 > RequestToPriority,
72 > APIPrioritiesOrdered,
73 > )
74 > }
75
76 func NewNamespaceRateLimiter(
77 namespaceRateFn quotas.NamespaceRateFn,
78 operatorRPSRatio dynamicconfig.FloatPropertyFn,
79 > ) quotas.RequestRateLimiter { quotas.go
80 > return quotas.NewNamespaceRequestRateLimiter(
81 > func(req quotas.Request) quotas.RequestRateLimiter {
82 > return quotas.NewPriorityRateLimiterHelper( quotas.go
83 > quotas.NewNamespaceRateBurst(
84 > req.Caller,
85 > namespaceRateFn,
86 > // TODO: We can consider adding a separate burst ratio dynamic config
87 > // on namespace level rate limiter if needed.
88 > quotas.DefaultIncomingNamespaceBurstRatioFn,
89 > ),
90 > operatorRPSRatio,
91 > RequestToPriority,
92 > APIPrioritiesOrdered,
93 > )
94 > },
95 )
96 }
97
98 > func RequestToPriority(req quotas.Request) int { quotas.go
99 > if req.CallerType == headers.CallerTypeOperator {
100 return quotas.OperatorPriority
101 }
102 > if priority, ok := APIToPriority[req.API]; ok { quotas.go
103 > return priority
104 > }
105 return APIPrioritiesOrdered[len(APIPrioritiesOrdered)-1]
106 }
go.temporal.io/server/api/cluster/v1/message.pb.go 28 covered LOC · 6 ranges

Open complete file

151 func (*MembershipInfo) ProtoMessage() {}
152
153 > func (x *MembershipInfo) ProtoReflect() protoreflect.Message { message.pb.go
154 > mi := &file_temporal_server_api_cluster_v1_message_proto_msgTypes[2]
155 > if x != nil {
156 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
157 if ms.LoadMessageInfo() == nil {
160 return ms
161 }
162 > return mi.MessageOf(x) message.pb.go
163 }
164
215 func (*ClusterMember) ProtoMessage() {}
216
217 > func (x *ClusterMember) ProtoReflect() protoreflect.Message { message.pb.go
218 > mi := &file_temporal_server_api_cluster_v1_message_proto_msgTypes[3]
219 > if x != nil {
220 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
221 if ms.LoadMessageInfo() == nil {
224 return ms
225 }
226 > return mi.MessageOf(x) message.pb.go
227 }
228
342 }
343
344 > func init() { file_temporal_server_api_cluster_v1_message_proto_init() } message.pb.go
345 > func file_temporal_server_api_cluster_v1_message_proto_init() {
346 > if File_temporal_server_api_cluster_v1_message_proto != nil {
347 return
348 }
349 > type x struct{} message.pb.go
350 > out := protoimpl.TypeBuilder{
351 > File: protoimpl.DescBuilder{
352 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
353 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_cluster_v1_message_proto_rawDesc), len(file_temporal_server_api_cluster_v1_message_proto_rawDesc)),
354 > NumEnums: 0,
355 > NumMessages: 4,
356 > NumExtensions: 0,
357 > NumServices: 0,
358 > },
359 > GoTypes: file_temporal_server_api_cluster_v1_message_proto_goTypes,
360 > DependencyIndexes: file_temporal_server_api_cluster_v1_message_proto_depIdxs,
361 > MessageInfos: file_temporal_server_api_cluster_v1_message_proto_msgTypes,
362 > }.Build()
363 > File_temporal_server_api_cluster_v1_message_proto = out.File
364 > file_temporal_server_api_cluster_v1_message_proto_goTypes = nil
365 > file_temporal_server_api_cluster_v1_message_proto_depIdxs = nil
366 }
go.temporal.io/server/api/health/v1/message.pb.go 28 covered LOC · 6 ranges

Open complete file

63 func (*HealthCheck) ProtoMessage() {}
64
65 > func (x *HealthCheck) ProtoReflect() protoreflect.Message { message.pb.go
66 > mi := &file_temporal_server_api_health_v1_message_proto_msgTypes[0]
67 > if x != nil {
68 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
69 if ms.LoadMessageInfo() == nil {
72 return ms
73 }
74 > return mi.MessageOf(x) message.pb.go
75 }
76
201 func (*ServiceHealthDetail) ProtoMessage() {}
202
203 > func (x *ServiceHealthDetail) ProtoReflect() protoreflect.Message { message.pb.go
204 > mi := &file_temporal_server_api_health_v1_message_proto_msgTypes[2]
205 > if x != nil {
206 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
207 if ms.LoadMessageInfo() == nil {
210 return ms
211 }
212 > return mi.MessageOf(x) message.pb.go
213 }
214
300 }
301
302 > func init() { file_temporal_server_api_health_v1_message_proto_init() } message.pb.go
303 > func file_temporal_server_api_health_v1_message_proto_init() {
304 > if File_temporal_server_api_health_v1_message_proto != nil {
305 return
306 }
307 > type x struct{} message.pb.go
308 > out := protoimpl.TypeBuilder{
309 > File: protoimpl.DescBuilder{
310 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
311 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_health_v1_message_proto_rawDesc), len(file_temporal_server_api_health_v1_message_proto_rawDesc)),
312 > NumEnums: 0,
313 > NumMessages: 3,
314 > NumExtensions: 0,
315 > NumServices: 0,
316 > },
317 > GoTypes: file_temporal_server_api_health_v1_message_proto_goTypes,
318 > DependencyIndexes: file_temporal_server_api_health_v1_message_proto_depIdxs,
319 > MessageInfos: file_temporal_server_api_health_v1_message_proto_msgTypes,
320 > }.Build()
321 > File_temporal_server_api_health_v1_message_proto = out.File
322 > file_temporal_server_api_health_v1_message_proto_goTypes = nil
323 > file_temporal_server_api_health_v1_message_proto_depIdxs = nil
324 }
go.temporal.io/server/api/persistence/v1/queue_metadata.pb.go 28 covered LOC · 3 ranges

Open complete file

44 func (*QueueMetadata) ProtoMessage() {}
45
46 > func (x *QueueMetadata) ProtoReflect() protoreflect.Message { queue_metadata.pb.go
47 > mi := &file_temporal_server_api_persistence_v1_queue_metadata_proto_msgTypes[0]
48 > if x != nil {
49 > ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
50 > if ms.LoadMessageInfo() == nil {
51 > ms.StoreMessageInfo(mi)
52 > }
53 > return ms
54 }
55 return mi.MessageOf(x)
105 }
106
107 > func init() { file_temporal_server_api_persistence_v1_queue_metadata_proto_init() } queue_metadata.pb.go
108 > func file_temporal_server_api_persistence_v1_queue_metadata_proto_init() {
109 > if File_temporal_server_api_persistence_v1_queue_metadata_proto != nil {
110 return
111 }
112 > type x struct{} queue_metadata.pb.go
113 > out := protoimpl.TypeBuilder{
114 > File: protoimpl.DescBuilder{
115 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
116 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_queue_metadata_proto_rawDesc), len(file_temporal_server_api_persistence_v1_queue_metadata_proto_rawDesc)),
117 > NumEnums: 0,
118 > NumMessages: 2,
119 > NumExtensions: 0,
120 > NumServices: 0,
121 > },
122 > GoTypes: file_temporal_server_api_persistence_v1_queue_metadata_proto_goTypes,
123 > DependencyIndexes: file_temporal_server_api_persistence_v1_queue_metadata_proto_depIdxs,
124 > MessageInfos: file_temporal_server_api_persistence_v1_queue_metadata_proto_msgTypes,
125 > }.Build()
126 > File_temporal_server_api_persistence_v1_queue_metadata_proto = out.File
127 > file_temporal_server_api_persistence_v1_queue_metadata_proto_goTypes = nil
128 > file_temporal_server_api_persistence_v1_queue_metadata_proto_depIdxs = nil
129 }
go.temporal.io/server/api/persistence/v1/workflow_mutable_state.pb.go 28 covered LOC · 4 ranges

Open complete file

55 func (*WorkflowMutableState) ProtoMessage() {}
56
57 > func (x *WorkflowMutableState) ProtoReflect() protoreflect.Message { workflow_mutable_state.pb.go
58 > mi := &file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_msgTypes[0]
59 > if x != nil {
60 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
61 if ms.LoadMessageInfo() == nil {
532 }
533
534 > func init() { file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_init() } workflow_mutable_state.pb.go
535 > func file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_init() {
536 > if File_temporal_server_api_persistence_v1_workflow_mutable_state_proto != nil {
537 return
538 }
539 > file_temporal_server_api_persistence_v1_chasm_proto_init() workflow_mutable_state.pb.go
540 > file_temporal_server_api_persistence_v1_executions_proto_init()
541 > file_temporal_server_api_persistence_v1_hsm_proto_init()
542 > file_temporal_server_api_persistence_v1_update_proto_init()
543 > type x struct{}
544 > out := protoimpl.TypeBuilder{
545 > File: protoimpl.DescBuilder{
546 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
547 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_rawDesc), len(file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_rawDesc)),
548 > NumEnums: 0,
549 > NumMessages: 16,
550 > NumExtensions: 0,
551 > NumServices: 0,
552 > },
553 > GoTypes: file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_goTypes,
554 > DependencyIndexes: file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_depIdxs,
555 > MessageInfos: file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_msgTypes,
556 > }.Build()
557 > File_temporal_server_api_persistence_v1_workflow_mutable_state_proto = out.File
558 > file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_goTypes = nil
559 > file_temporal_server_api_persistence_v1_workflow_mutable_state_proto_depIdxs = nil
560 }
go.temporal.io/server/chasm/lib/nexusoperation/fx.go 28 covered LOC · 7 ranges

Open complete file

62 registry *chasm.Registry,
63 library *Library,
64 > ) error { fx.go
65 > return registry.Register(library)
66 > }
67
68 func endpointRegistryProvider(
72 logger log.Logger,
73 metricsHandler metrics.Handler,
74 > ) commonnexus.EndpointRegistry { fx.go
75 > registryConfig := commonnexus.NewEndpointRegistryConfig(dc)
76 > return commonnexus.NewEndpointRegistry(
77 > registryConfig,
78 > matchingClient,
79 > endpointManager,
80 > logger,
81 > metricsHandler,
82 > )
83 > }
84
85 > func endpointRegistryLifetimeHooks(lc fx.Lifecycle, registry commonnexus.EndpointRegistry) { fx.go
86 > lc.Append(fx.StartStopHook(registry.StartLifecycle, registry.StopLifecycle))
87 > }
88
89 // NexusTransportProvider allows customization of the HTTP transport used for Nexus requests.
90 type NexusTransportProvider func(namespaceID, serviceName string) http.RoundTripper
91
92 > func defaultNexusTransportProvider() NexusTransportProvider { fx.go
93 > return func(namespaceID, serviceName string) http.RoundTripper {
94 return http.DefaultTransport
95 }
119 clusterMetadata cluster.Metadata,
120 rpcFactory common.RPCFactory,
121 > ) (ClientProvider, error) { fx.go
122 > cl, err := rpcFactory.CreateLocalFrontendHTTPClient()
123 > if err != nil {
124 return nil, fmt.Errorf("cannot create local frontend HTTP client: %w", err)
125 }
126 > var clusterID string fx.go
127 >
128 > if clusterInfo, ok := clusterMetadata.GetAllClusterInfo()[clusterMetadata.GetCurrentClusterName()]; ok {
129 > clusterID = clusterInfo.ClusterID
130 > }
131 > m := collection.NewFallibleOnceMap(func(key clientProviderCacheKey) (*http.Client, error) {
132 transport := httpTransportProvider(key.namespaceID, key.endpointID)
133 return &http.Client{
136 })
137
138 > return func(ctx context.Context, namespaceID string, entry *persistencespb.NexusEndpointEntry, service string) (*nexusrpc.HTTPClient, error) { fx.go
139 var url string
140 var httpClient *http.Client
go.temporal.io/server/chasm/nexus_operation_processor.go 28 covered LOC · 9 ranges

Open complete file

79 }
80
81 > func nexusOperationProcessorAdapter[I any](processor NexusOperationProcessor[I]) func(ctx NexusOperationProcessorContext, input *commonpb.Payload) (*NexusOperationProcessorResult, error) { nexus_operation_processor.go
82 > return func(ctx NexusOperationProcessorContext, input *commonpb.Payload) (*NexusOperationProcessorResult, error) {
83 var i I
84 if err := sdkconverter.PreferProtoDataConverter.FromPayloads(&commonpb.Payloads{Payloads: []*commonpb.Payload{input}}, &i); err != nil {
105
106 // NewRegisterableNexusOperationProcessor wraps a typed NexusOperationProcessor and returns a registerable adapter.
107 > func NewRegisterableNexusOperationProcessor[I any](op NexusOperationProcessor[I]) RegisterableNexusOperationProcessor { nexus_operation_processor.go
108 > return RegisterableNexusOperationProcessor{
109 > processInput: nexusOperationProcessorAdapter(op),
110 > }
111 > }
112
113 // NexusServiceProcessor handles input processing for operations within a specific Nexus service.
120 // NewNexusServiceProcessor constructs a processor for a single Nexus service that can register and invoke operation
121 // processors by name.
122 > func NewNexusServiceProcessor(name string) *NexusServiceProcessor { nexus_operation_processor.go
123 > return &NexusServiceProcessor{
124 > name: name,
125 > operations: make(map[string]RegisterableNexusOperationProcessor),
126 > }
127 > }
128
129 // RegisterOperation registers a named operation with this service processor.
130 // Returns an error if an operation with the same name is already registered.
131 > func (p *NexusServiceProcessor) RegisterOperation(name string, op RegisterableNexusOperationProcessor) error { nexus_operation_processor.go
132 > if _, exists := p.operations[name]; exists {
133 return fmt.Errorf("operation %q already registered", name)
134 }
135 > p.operations[name] = op nexus_operation_processor.go
136 > return nil
137 }
138
139 // MustRegisterOperation registers a named operation and panics if registration fails.
140 > func (p *NexusServiceProcessor) MustRegisterOperation(name string, op RegisterableNexusOperationProcessor) { nexus_operation_processor.go
141 > if err := p.RegisterOperation(name, op); err != nil {
142 // nolint:forbidigo // Panic is acceptable here for Must-style method.
143 panic(err)
165
166 // NewNexusEndpointProcessor creates a new NexusEndpointProcessor.
167 > func NewNexusEndpointProcessor() *NexusEndpointProcessor { nexus_operation_processor.go
168 > return &NexusEndpointProcessor{
169 > serviceProcessors: make(map[string]*NexusServiceProcessor),
170 > }
171 > }
172
173 // RegisterServiceProcessor adds a service-level processor to the endpoint keyed by its name.
174 // Returns an error if a processor with the same name is already registered.
175 > func (p *NexusEndpointProcessor) RegisterServiceProcessor(processor *NexusServiceProcessor) error { nexus_operation_processor.go
176 > if _, exists := p.serviceProcessors[processor.name]; exists {
177 return fmt.Errorf("service processor %q already registered", processor.name)
178 }
179 > p.serviceProcessors[processor.name] = processor nexus_operation_processor.go
180 > return nil
181 }
182
go.temporal.io/server/client/history/metric_client_gen.go 28 covered LOC · 8 ranges

Open complete file

322 request *historyservice.GetWorkflowExecutionHistoryRequest,
323 opts ...grpc.CallOption,
324 > ) (_ *historyservice.GetWorkflowExecutionHistoryResponse, retError error) { metric_client_gen.go
325 >
326 > metricsHandler, startTime := c.startMetricsRecording(ctx, "HistoryClientGetWorkflowExecutionHistory")
327 > defer func() {
328 > c.finishMetricsRecording(metricsHandler, startTime, retError)
329 > }()
330
331 > return c.client.GetWorkflowExecutionHistory(ctx, request, opts...) metric_client_gen.go
332 }
333
630 request *historyservice.RecordWorkflowTaskStartedRequest,
631 opts ...grpc.CallOption,
632 > ) (_ *historyservice.RecordWorkflowTaskStartedResponse, retError error) { metric_client_gen.go
633 >
634 > metricsHandler, startTime := c.startMetricsRecording(ctx, "HistoryClientRecordWorkflowTaskStarted")
635 > defer func() {
636 > c.finishMetricsRecording(metricsHandler, startTime, retError)
637 > }()
638
639 > return c.client.RecordWorkflowTaskStarted(ctx, request, opts...) metric_client_gen.go
640 }
641
812 request *historyservice.RespondWorkflowTaskCompletedRequest,
813 opts ...grpc.CallOption,
814 > ) (_ *historyservice.RespondWorkflowTaskCompletedResponse, retError error) { metric_client_gen.go
815 >
816 > metricsHandler, startTime := c.startMetricsRecording(ctx, "HistoryClientRespondWorkflowTaskCompleted")
817 > defer func() {
818 > c.finishMetricsRecording(metricsHandler, startTime, retError)
819 > }()
820
821 > return c.client.RespondWorkflowTaskCompleted(ctx, request, opts...) metric_client_gen.go
822 }
823
882 request *historyservice.StartWorkflowExecutionRequest,
883 opts ...grpc.CallOption,
884 > ) (_ *historyservice.StartWorkflowExecutionResponse, retError error) { metric_client_gen.go
885 >
886 > metricsHandler, startTime := c.startMetricsRecording(ctx, "HistoryClientStartWorkflowExecution")
887 > defer func() {
888 > c.finishMetricsRecording(metricsHandler, startTime, retError)
889 > }()
890
891 > return c.client.StartWorkflowExecution(ctx, request, opts...) metric_client_gen.go
892 }
893
go.temporal.io/server/common/persistence/sql/common.go 28 covered LOC · 9 ranges

Open complete file

25 }
26
27 > func NewSQLStore(db sqlplugin.DB, logger log.Logger, serializer serialization.Serializer) SqlStore { common.go
28 > return SqlStore{
29 > DB: db,
30 > logger: logger,
31 > serializer: serializer,
32 > }
33 > }
34
35 > func (m *SqlStore) GetName() string { common.go
36 > return m.DB.PluginName()
37 > }
38
39 > func (m *SqlStore) GetDbName() string { common.go
40 > return m.DB.DbName()
41 > }
42
43 > func (m *SqlStore) Close() { common.go
44 > if m.DB != nil {
45 > err := m.DB.Close()
46 > if err != nil {
47 m.logger.Error("Error closing SQL database", tag.Error(err))
48 }
50 }
51
52 > func (m *SqlStore) txExecute(ctx context.Context, operation string, f func(tx sqlplugin.Tx) error) error { common.go
53 > tx, err := m.DB.BeginTx(ctx)
54 > if err != nil {
55 return serviceerror.NewUnavailablef("%s failed. Failed to start transaction. Error: %v", operation, err)
56 }
57 > err = f(tx) common.go
58 > if err != nil {
59 rollBackErr := tx.Rollback()
60 if rollBackErr != nil {
75 }
76 }
77 > if err := tx.Commit(); err != nil { common.go
78 return serviceerror.NewUnavailablef("%s operation failed. Failed to commit transaction. Error: %v", operation, err)
79 }
80 > return nil common.go
81 }
82
129 operation string,
130 err error,
131 > ) error { common.go
132 > if err == sql.ErrNoRows {
133 > return serviceerror.NewNotFoundf("%v failed. Error: %v ", operation, err)
134 > }
135
136 return serviceerror.NewUnavailablef("%v operation failed. Error: %v", operation, err)
go.temporal.io/server/service/history/configs/quotas.go 28 covered LOC · 4 ranges

Open complete file

22 rateFn quotas.RateFn,
23 operatorRPSRatio dynamicconfig.FloatPropertyFn,
24 > ) quotas.RequestRateLimiter { quotas.go
25 > return quotas.NewPriorityRateLimiterHelper(
26 > quotas.NewDefaultIncomingRateBurst(rateFn),
27 > operatorRPSRatio,
28 > RequestToPriority,
29 > APIPrioritiesOrdered,
30 > )
31 > }
32
33 func NewNamespaceRateLimiter(
34 namespaceRateFn quotas.NamespaceRateFn,
35 operatorRPSRatio dynamicconfig.FloatPropertyFn,
36 > ) quotas.RequestRateLimiter { quotas.go
37 > return quotas.NewNamespaceRequestRateLimiter(
38 > func(req quotas.Request) quotas.RequestRateLimiter {
39 > return quotas.NewPriorityRateLimiterHelper( quotas.go
40 > quotas.NewNamespaceRateBurst(
41 > req.Caller,
42 > namespaceRateFn,
43 > // TODO: We can consider adding a separate burst ratio dynamic config
44 > // on namespace level rate limiter if needed.
45 > quotas.DefaultIncomingNamespaceBurstRatioFn,
46 > ),
47 > operatorRPSRatio,
48 > RequestToPriority,
49 > APIPrioritiesOrdered,
50 > )
51 > },
52 )
53 }
54
55 > func RequestToPriority(req quotas.Request) int { quotas.go
56 > if priority, ok := CallerTypeToPriority[req.CallerType]; ok {
57 > return priority
58 > }
59 // unknown caller type, default to api to be consistent with existing behavior
60 return CallerTypeToPriority[headers.CallerTypeAPI]
go.temporal.io/server/service/history/queues/iterator.go 28 covered LOC · 8 ranges

Open complete file

33 paginationFnProvider PaginationFnProvider,
34 r Range,
35 > ) *IteratorImpl { iterator.go
36 > return &IteratorImpl{
37 > paginationFnProvider: paginationFnProvider,
38 > remainingRange: r,
39 >
40 > // lazy initialized to prevent task pre-fetching on creating the iterator
41 > pagingIterator: nil,
42 > }
43 > }
44
45 > func (i *IteratorImpl) HasNext() bool { iterator.go
46 > if i.pagingIterator == nil {
47 > i.pagingIterator = collection.NewPagingIterator(i.paginationFnProvider(i.remainingRange))
48 > }
49
50 > return i.pagingIterator.HasNext() iterator.go
51 }
52
53 > func (i *IteratorImpl) Next() (tasks.Task, error) { iterator.go
54 > if !i.HasNext() {
55 panic("Iterator encountered Next call when there is no next item")
56 }
57
58 > task, err := i.pagingIterator.Next() iterator.go
59 > if err != nil {
60 > return nil, err iterator.go
61 > }
62
63 > i.remainingRange.InclusiveMin = task.GetKey().Next() iterator.go
64 > return task, nil
65 }
66
105 }
106
107 > func (i *IteratorImpl) Remaining() Iterator { iterator.go
108 > return NewIterator(
109 > i.paginationFnProvider,
110 > i.remainingRange,
111 > )
112 > }
go.temporal.io/server/service/history/workflow/query_registry.go 28 covered LOC · 7 ranges

Open complete file

25 )
26
27 > func NewQueryRegistry() historyi.QueryRegistry { query_registry.go
28 > return &queryRegistryImpl{
29 > buffered: make(map[string]query),
30 > completed: make(map[string]query),
31 > unblocked: make(map[string]query),
32 > failed: make(map[string]query),
33 > }
34 > }
35
36 > func (r *queryRegistryImpl) HasBufferedQuery() bool { query_registry.go
37 > r.RLock()
38 > defer r.RUnlock()
39 > return len(r.buffered) > 0
40 > }
41
42 > func (r *queryRegistryImpl) GetBufferedIDs() []string { query_registry.go
43 > r.RLock()
44 > defer r.RUnlock()
45 > return r.getIDs(r.buffered)
46 > }
47
48 func (r *queryRegistryImpl) HasCompletedQuery() bool {
152 }
153
154 > func (r *queryRegistryImpl) Clear() { query_registry.go
155 > r.Lock()
156 > defer r.Unlock()
157 > for id, q := range r.buffered {
158 _ = q.setCompletionState(&historyi.QueryCompletionState{
159 Type: QueryCompletionTypeFailed,
162 r.failed[id] = q
163 }
164 > r.buffered = make(map[string]query) query_registry.go
165 }
166
181 }
182
183 > func (r *queryRegistryImpl) getIDs(m map[string]query) []string { query_registry.go
184 > result := make([]string, len(m))
185 > index := 0
186 > for id := range m {
187 result[index] = id
188 index++
189 }
190 > return result query_registry.go
191 }
go.temporal.io/server/service/history/workflow/timeskipping.go 28 covered LOC · 7 ranges

Open complete file

181 }
182
183 > func accumulatedSkippedDuration(source *persistencespb.WorkflowExecutionInfo) time.Duration { timeskipping.go
184 > return source.GetTimeSkippingInfo().GetAccumulatedSkippedDuration().AsDuration()
185 > }
186
187 // =============================================================================
201 }
202
203 > func (ms *MutableStateImpl) accumulatedSkippedDuration() time.Duration { timeskipping.go
204 > return accumulatedSkippedDuration(ms.executionInfo)
205 > }
206
207 // =============================================================================
306 // and if the workflow is at the correct state and status to skip time.
307 // And if there is a time point to skip to is not the scope of this method.
308 > func (ms *MutableStateImpl) isWorkflowSkippable() bool { timeskipping.go
309 > noSkippingReason := ""
310 > defer func() {
311 > if noSkippingReason != "" {
312 > ms.logger.Debug(fmt.Sprintf("time skipping skipped for: %s", noSkippingReason),
313 > tag.WorkflowID(ms.GetExecutionInfo().WorkflowId),
314 > tag.WorkflowRunID(ms.GetExecutionState().RunId),
315 > )
316 > }
317 }()
318
319 // (1) gate by time skipping configuration
320 > tsc := ms.GetExecutionInfo().GetTimeSkippingInfo().GetConfig() timeskipping.go
321 > if tsc == nil || !tsc.Enabled {
322 > noSkippingReason = "time skipping is not enabled"
323 > return false
324 > }
325
326 // (2) gate by workflow state and status
433 ctx context.Context,
434 transactionPolicy historyi.TransactionPolicy,
435 > ) (needRegenTasks bool) { timeskipping.go
436 > if !ms.IsWorkflow() {
437 return false
438 }
439 > switch transactionPolicy { timeskipping.go
440 > case historyi.TransactionPolicyActive: timeskipping.go
441 > // 1. gate: only a running, time-skipping-enabled, idle workflow may skip time
442 > if !ms.isWorkflowSkippable() {
443 > return false
444 > }
445 // 2. find the next skip target; if there is none, time skipping is not needed
446 transition := ms.findNextSkipTarget()
go.temporal.io/server/api/persistence/v1/queues.pb.go 27 covered LOC · 3 ranges

Open complete file

98 func (*QueueState) ProtoMessage() {}
99
100 > func (x *QueueState) ProtoReflect() protoreflect.Message { queues.pb.go
101 > mi := &file_temporal_server_api_persistence_v1_queues_proto_msgTypes[1]
102 > if x != nil {
103 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
104 if ms.LoadMessageInfo() == nil {
107 return ms
108 }
109 > return mi.MessageOf(x) queues.pb.go
110 }
111
616 }
617
618 > func init() { file_temporal_server_api_persistence_v1_queues_proto_init() } queues.pb.go
619 > func file_temporal_server_api_persistence_v1_queues_proto_init() {
620 > if File_temporal_server_api_persistence_v1_queues_proto != nil {
621 > return
622 > }
623 > file_temporal_server_api_persistence_v1_predicates_proto_init()
624 > type x struct{}
625 > out := protoimpl.TypeBuilder{
626 > File: protoimpl.DescBuilder{
627 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
628 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_queues_proto_rawDesc), len(file_temporal_server_api_persistence_v1_queues_proto_rawDesc)),
629 > NumEnums: 0,
630 > NumMessages: 12,
631 > NumExtensions: 0,
632 > NumServices: 0,
633 > },
634 > GoTypes: file_temporal_server_api_persistence_v1_queues_proto_goTypes,
635 > DependencyIndexes: file_temporal_server_api_persistence_v1_queues_proto_depIdxs,
636 > MessageInfos: file_temporal_server_api_persistence_v1_queues_proto_msgTypes,
637 > }.Build()
638 > File_temporal_server_api_persistence_v1_queues_proto = out.File
639 > file_temporal_server_api_persistence_v1_queues_proto_goTypes = nil
640 > file_temporal_server_api_persistence_v1_queues_proto_depIdxs = nil
641 }
go.temporal.io/server/chasm/lib/workflow/nexus_events.go 27 covered LOC · 9 ranges

Open complete file

19 }
20
21 > func (d ScheduledEventDefinition) Type() enumspb.EventType { nexus_events.go
22 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_SCHEDULED
23 > }
24
25 func (d ScheduledEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
75 }
76
77 > func (d CancelRequestedEventDefinition) Type() enumspb.EventType { nexus_events.go
78 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUESTED
79 > }
80
81 func (d CancelRequestedEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
113 }
114
115 > func (d CancelRequestCompletedEventDefinition) Type() enumspb.EventType { nexus_events.go
116 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUEST_COMPLETED
117 > }
118
119 func (d CancelRequestCompletedEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
143 }
144
145 > func (d CancelRequestFailedEventDefinition) Type() enumspb.EventType { nexus_events.go
146 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUEST_FAILED
147 > }
148
149 func (d CancelRequestFailedEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
175 }
176
177 > func (d StartedEventDefinition) Type() enumspb.EventType { nexus_events.go
178 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_STARTED
179 > }
180
181 func (d StartedEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
209 }
210
211 > func (d CompletedEventDefinition) Type() enumspb.EventType { nexus_events.go
212 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_COMPLETED
213 > }
214
215 func (d CompletedEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
247 }
248
249 > func (d FailedEventDefinition) Type() enumspb.EventType { nexus_events.go
250 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_FAILED
251 > }
252
253 func (d FailedEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
285 }
286
287 > func (d CanceledEventDefinition) Type() enumspb.EventType { nexus_events.go
288 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_CANCELED
289 > }
290
291 func (d CanceledEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
323 }
324
325 > func (d TimedOutEventDefinition) Type() enumspb.EventType { nexus_events.go
326 > return enumspb.EVENT_TYPE_NEXUS_OPERATION_TIMED_OUT
327 > }
328
329 func (d TimedOutEventDefinition) Apply(ctx chasm.MutableContext, wf *Workflow, event *historypb.HistoryEvent) error {
go.temporal.io/server/common/goro/goro.go 27 covered LOC · 8 ranges

Open complete file

22 // the goroutine starts, which makes it possible for the goroutine to call
23 // Done() on itself (maybe indirectly) without a race condition.
24 > func NewHandle(ctx context.Context) *Handle { goro.go
25 > ctx, cancel := context.WithCancel(ctx)
26 > return &Handle{
27 > context: ctx,
28 > cancel: cancel,
29 > done: make(chan struct{}),
30 > }
31 > }
32
33 // Go launches the supplied function in its own goroutine. Go should be called
34 // exactly once on each *Handle.
35 > func (h *Handle) Go(f func(context.Context) error) *Handle { goro.go
36 > go func() {
37 > // use defer here so that the channel is closed even if the func calls
38 > // runtime.Goexit()
39 > defer close(h.done)
40 > if err := f(h.context); err != nil {
41 > h.err.Store(err) goro.go
42 > }
43 }()
44 > return h goro.go
45 }
46
49 // the Done() channel closing is the time taken by the goroutine to shut itself
50 // down.
51 > func (h *Handle) Done() <-chan struct{} { goro.go
52 > return h.done
53 > }
54
55 // Cancel requests that this goroutine stop by cancelling the associated context
56 // object. This function is threadsafe and idempotent. Note that this function
57 // _requests_ termination, it does not forcefully kill the goroutine.
58 > func (h *Handle) Cancel() { goro.go
59 > h.cancel()
60 > }
61
62 // Error observes the error returned by the func passed to Go (if any). There is
63 // never any error (i.e. this function returns nil) while the goroutine is
64 // running.
65 > func (h *Handle) Err() error { goro.go
66 > v := h.err.Load()
67 > if v == nil {
68 return nil
69 }
70 > return v.(error) goro.go
71 }
go.temporal.io/server/common/log/with_logger.go 27 covered LOC · 9 ranges

Open complete file

14 // With returns Logger instance that prepend every log entry with tags. If logger implements
15 // WithLogger it is used, otherwise every log call will be intercepted.
16 > func With(logger Logger, tags ...tag.Tag) Logger { with_logger.go
17 > if wl, ok := logger.(WithLogger); ok {
18 > return wl.With(tags...) with_logger.go
19 > }
20 > return newWithLogger(logger, tags...) with_logger.go
21 }
22
23 > func newWithLogger(logger Logger, tags ...tag.Tag) *withLogger { with_logger.go
24 > return &withLogger{logger: logger, tags: tags}
25 > }
26
27 > func (l *withLogger) prependTags(tags []tag.Tag) []tag.Tag { with_logger.go
28 > allTags := make([]tag.Tag, len(l.tags)+len(tags))
29 > copy(allTags, l.tags)
30 > copy(allTags[len(l.tags):], tags)
31 >
32 > return allTags
33 > }
34
35 // Debug writes message to the log (if enabled).
36 > func (l *withLogger) Debug(msg string, tags ...tag.Tag) { with_logger.go
37 > l.logger.Debug(msg, l.prependTags(tags)...)
38 > }
39
40 // Info writes message to the log (if enabled).
41 > func (l *withLogger) Info(msg string, tags ...tag.Tag) { with_logger.go
42 > l.logger.Info(msg, l.prependTags(tags)...)
43 > }
44
45 // Warn writes message to the log (if enabled).
46 > func (l *withLogger) Warn(msg string, tags ...tag.Tag) { with_logger.go
47 > l.logger.Warn(msg, l.prependTags(tags)...)
48 > }
49
50 // Error writes message to the log (if enabled).
51 > func (l *withLogger) Error(msg string, tags ...tag.Tag) { with_logger.go
52 > l.logger.Error(msg, l.prependTags(tags)...)
53 > }
54
55 // DPanic writes message to the log (if enabled), then calls panic() in development mode
go.temporal.io/server/common/metrics/task_queues.go 27 covered LOC · 10 ranges

Open complete file

17 taskQueueBreakdown bool,
18 tags ...Tag,
19 > ) Handler { task_queues.go
20 > metricTaskQueueName := omitted
21 > if taskQueueBreakdown {
22 > metricTaskQueueName = taskQueueFamily.Name() task_queues.go
23 > }
24
25 > tags = append(tags, NamespaceTag(namespaceName), UnsafeTaskQueueTag(metricTaskQueueName)) task_queues.go
26 > return handler.WithTags(tags...)
27 }
28
34 taskQueueBreakdown bool,
35 tags ...Tag,
36 > ) Handler { task_queues.go
37 > return GetPerTaskQueueFamilyScope(handler, namespaceName, taskQueue.Family(), taskQueueBreakdown,
38 > append(tags, TaskQueueTypeTag(taskQueue.TaskType()))...)
39 > }
40
41 // GetPerTaskQueuePartitionIDScope is similar to GetPerTaskQueuePartitionTypeScope, except that the partition tag will
48 partitionIDBreakdown bool,
49 tags ...Tag,
50 > ) Handler { task_queues.go
51 > var value string
52 > if partition == nil {
53 value = unknownValue
54 > } else { task_queues.go
55 > value = partition.MetricTag(partitionIDBreakdown)
56 > }
57
58 > return GetPerTaskQueueScope(handler, namespaceName, partition.TaskQueue(), taskQueueBreakdown, task_queues.go
59 > append(tags, PartitionTag(value))...)
60 }
61
68 taskQueueBreakdown bool,
69 tags ...Tag,
70 > ) Handler { task_queues.go
71 > var value string
72 > if partition == nil {
73 value = unknownValue
74 > } else { task_queues.go
75 > value = partition.MetricTag(false)
76 > }
77
78 > return GetPerTaskQueueScope(handler, namespaceName, partition.TaskQueue(), taskQueueBreakdown, task_queues.go
79 > append(tags, PartitionTag(value))...)
80 }
go.temporal.io/server/common/rpc/interceptor/mask_internal_error.go 27 covered LOC · 7 ranges

Open complete file

32 namespaceRegistry namespace.Registry,
33 logger log.Logger,
34 > ) *MaskInternalErrorDetailsInterceptor { mask_internal_error.go
35 >
36 > return &MaskInternalErrorDetailsInterceptor{
37 > maskInternalError: maskErrorSetting,
38 > namespaceRegistry: namespaceRegistry,
39 > workflowTags: logtags.NewWorkflowTags(tasktoken.NewSerializer(), logger),
40 > logger: logger,
41 > }
42 > }
43
44 func (mi *MaskInternalErrorDetailsInterceptor) Intercept(
47 info *grpc.UnaryServerInfo,
48 handler grpc.UnaryHandler,
49 > ) (any, error) { mask_internal_error.go
50 >
51 > resp, err := handler(ctx, req)
52 >
53 > if err != nil && mi.shouldMaskErrors(req) {
54 > err = mi.maskUnknownOrInternalErrors(req, info.FullMethod, err) mask_internal_error.go
55 > }
56 > return resp, err mask_internal_error.go
57 }
58
59 > func (mi *MaskInternalErrorDetailsInterceptor) shouldMaskErrors(req any) bool { mask_internal_error.go
60 > ns := MustGetNamespaceName(mi.namespaceRegistry, req)
61 > if ns.IsEmpty() {
62 return false
63 }
64 > return mi.maskInternalError(ns.String()) mask_internal_error.go
65 }
66
67 func (mi *MaskInternalErrorDetailsInterceptor) maskUnknownOrInternalErrors(
68 req any, fullMethodName string, err error,
69 > ) error { mask_internal_error.go
70 > statusCode := serviceerror.ToStatus(err).Code()
71 >
72 > if statusCode != codes.Unknown && statusCode != codes.Internal {
73 > return err
74 > }
75
76 // we need to log the original error with hash.
go.temporal.io/server/common/sdk/metrics_handler.go 27 covered LOC · 9 ranges

Open complete file

31 var _ sdkclient.MetricsHandler = &MetricsHandler{}
32
33 > func NewMetricsHandler(provider metrics.Handler) *MetricsHandler { metrics_handler.go
34 > return &MetricsHandler{provider: provider}
35 > }
36
37 > func (m *MetricsHandler) WithTags(tags map[string]string) sdkclient.MetricsHandler { metrics_handler.go
38 > t := make([]metrics.Tag, 0, len(tags))
39 > for k, v := range tags {
40 > t = append(t, metrics.StringTag(k, v))
41 > }
42
43 > return NewMetricsHandler(m.provider.WithTags(t...)) metrics_handler.go
44 }
45
46 > func (m *MetricsHandler) Counter(name string) sdkclient.MetricsCounter { metrics_handler.go
47 > return &metricsCounter{name: name, provider: m.provider}
48 > }
49
50 > func (m *MetricsHandler) Gauge(name string) sdkclient.MetricsGauge { metrics_handler.go
51 > return &metricsGauge{name: name, provider: m.provider}
52 > }
53
54 > func (m *MetricsHandler) Timer(name string) sdkclient.MetricsTimer { metrics_handler.go
55 > return &metricsTimer{name: name, provider: m.provider}
56 > }
57
58 > func (m metricsCounter) Inc(i int64) { metrics_handler.go
59 > m.provider.Counter(m.name).Record(i)
60 > }
61
62 > func (m metricsGauge) Update(f float64) { metrics_handler.go
63 > m.provider.Gauge(m.name).Record(f)
64 > }
65
66 > func (m metricsTimer) Record(duration time.Duration) { metrics_handler.go
67 > m.provider.Timer(m.name).Record(duration)
68 > }
go.temporal.io/server/common/searchattribute/name_type_map.go 27 covered LOC · 10 ranges

Open complete file

42 func buildIndexNameTypeMap(
43 indexSearchAttributes map[string]*persistencespb.IndexSearchAttributes,
44 > ) map[string]NameTypeMap { name_type_map.go
45 > indexNameTypeMap := make(map[string]NameTypeMap, len(indexSearchAttributes))
46 > for indexName, customSearchAttributes := range indexSearchAttributes {
47 > indexNameTypeMap[indexName] = NewNameTypeMap(customSearchAttributes.GetCustomSearchAttributes())
48 > }
49 > return indexNameTypeMap
50 }
51
52 // NewNameTypeMap creates a new NameTypeMap with the given custom search attributes.
53 > func NewNameTypeMap(customSearchAttributes map[string]enumspb.IndexedValueType) NameTypeMap { name_type_map.go
54 > return NameTypeMap{
55 > systemSearchAttributes: system,
56 > predefinedSearchAttributes: predefined,
57 > customSearchAttributes: customSearchAttributes,
58 > }
59 > }
60
61 // WithSystemSearchAttributes returns a new NameTypeMap overriding the system search
102 }
103
104 > func (m NameTypeMap) predefined() map[string]enumspb.IndexedValueType { name_type_map.go
105 > if len(m.predefinedSearchAttributes) == 0 {
106 return predefined
107 }
108 > return m.predefinedSearchAttributes name_type_map.go
109 }
110
121 }
122
123 > func (m NameTypeMap) Custom() map[string]enumspb.IndexedValueType { name_type_map.go
124 > return m.customSearchAttributes
125 > }
126
127 func (m NameTypeMap) All() map[string]enumspb.IndexedValueType {
144
145 // GetType returns type of search attribute from type map.
146 > func (m NameTypeMap) getType(name string, cat category) (enumspb.IndexedValueType, error) { name_type_map.go
147 > if cat|customCategory == cat && len(m.customSearchAttributes) != 0 {
148 > if t, isCustom := m.customSearchAttributes[name]; isCustom { name_type_map.go
149 return t, nil
150 }
151 }
152 > if cat|predefinedCategory == cat { name_type_map.go
153 > predefinedSearchAttributes := m.predefined() name_type_map.go
154 > if t, isPredefined := predefinedSearchAttributes[name]; isPredefined {
155 > return t, nil name_type_map.go
156 > }
157 }
158 if cat|systemCategory == cat {
go.temporal.io/server/service/history/replication/dlq_handler.go 27 covered LOC · 3 ranges

Open complete file

64 clientBean client.Bean,
65 taskExecutorProvider TaskExecutorProvider,
66 > ) DLQHandler { dlq_handler.go
67 > return newDLQHandler(
68 > shard,
69 > deleteManager,
70 > workflowCache,
71 > clientBean,
72 > make(map[string]TaskExecutor),
73 > taskExecutorProvider,
74 > )
75 > }
76
77 func newDLQHandler(
82 taskExecutors map[string]TaskExecutor,
83 taskExecutorProvider TaskExecutorProvider,
84 > ) *dlqHandlerImpl { dlq_handler.go
85 >
86 > if taskExecutors == nil {
87 panic("Failed to initialize replication DLQ handler due to nil task executors")
88 }
89 > return &dlqHandlerImpl{ dlq_handler.go
90 > shard: shard,
91 > deleteManager: deleteManager,
92 > workflowCache: workflowCache,
93 > remoteHistoryFetcher: eventhandler.NewHistoryPaginatedFetcher(
94 > shard.GetNamespaceRegistry(),
95 > clientBean,
96 > shard.GetPayloadSerializer(),
97 > shard.GetLogger(),
98 > ),
99 > taskExecutors: taskExecutors,
100 > taskExecutorProvider: taskExecutorProvider,
101 > logger: shard.GetLogger(),
102 > }
103 }
104
go.temporal.io/server/service/history/shard/fx.go 27 covered LOC · 7 ranges

Open complete file

16 fx.Provide(
17 ControllerProvider,
18 > func(impl *ControllerImpl) Controller { return impl }, fx.go
19 ContextFactoryProvider,
20 NewDefaultHandoverTrackerFactory,
21 fx.Annotate(
22 > func(p Controller) pingable.Pingable { return p }, fx.go
23 fx.ResultTags(`group:"deadlockDetectorRoots"`),
24 ),
31 impl *ControllerImpl,
32 cfg *configs.Config,
33 > ) (*OwnershipBasedQuotaScalerImpl, error) { fx.go
34 > return NewOwnershipBasedQuotaScaler(
35 > impl,
36 > int(cfg.NumberOfShards),
37 > nil,
38 > )
39 > }),
40 fx.Provide(func(
41 impl *OwnershipBasedQuotaScalerImpl,
42 > ) OwnershipBasedQuotaScaler { fx.go
43 > return impl
44 > }),
45 > fx.Provide(func() LazyLoadedOwnershipBasedQuotaScaler {
46 > return LazyLoadedOwnershipBasedQuotaScaler{
47 > Value: &atomic.Value{},
48 > }
49 > }),
50 fx.Invoke(initLazyLoadedOwnershipBasedQuotaScaler),
51 fx.Invoke(func(
52 lc fx.Lifecycle,
53 impl *OwnershipBasedQuotaScalerImpl,
54 > ) { fx.go
55 > lc.Append(fx.Hook{
56 > OnStop: func(_ context.Context) error {
57 > impl.Close() fx.go
58 > return nil
59 > },
60 })
61 }),
67 ownershipBasedQuotaScaler OwnershipBasedQuotaScaler,
68 lazyLoadedOwnershipBasedQuotaScaler LazyLoadedOwnershipBasedQuotaScaler,
69 > ) { fx.go
70 > lazyLoadedOwnershipBasedQuotaScaler.Store(ownershipBasedQuotaScaler)
71 > logger.Info("Initialized lazy loaded OwnershipBasedQuotaScaler", tag.Service(serviceName))
72 > }
go.temporal.io/server/temporal/cluster_metadata_loader.go 27 covered LOC · 8 ranges

Open complete file

20
21 // NewClusterMetadataLoader creates a new [ClusterMetadataLoader] that loads cluster metadata from the database.
22 > func NewClusterMetadataLoader(manager persistence.ClusterMetadataManager, logger log.Logger) *ClusterMetadataLoader { cluster_metadata_loader.go
23 > return &ClusterMetadataLoader{
24 > manager: manager,
25 > logger: logger,
26 > }
27 > }
28
29 // LoadAndMergeWithStaticConfig loads cluster metadata from the database and merges it with the static config.
30 > func (c *ClusterMetadataLoader) LoadAndMergeWithStaticConfig(ctx context.Context, svc *config.Config) error { cluster_metadata_loader.go
31 > iter := cluster.GetAllClustersIter(ctx, c.manager)
32 >
33 > for iter.HasNext() {
34 > item, err := iter.Next()
35 > if err != nil {
36 return err
37 }
38 > newMetadata := cluster.ClusterInformationFromDB(item) cluster_metadata_loader.go
39 > c.mergeMetadataFromDBWithStaticConfig(svc, item.ClusterName, newMetadata)
40 }
41 > return nil cluster_metadata_loader.go
42 }
43
44 > func (c *ClusterMetadataLoader) mergeMetadataFromDBWithStaticConfig(svc *config.Config, clusterName string, newMetadata *cluster.ClusterInformation) { cluster_metadata_loader.go
45 > c.backfillShardCount(svc, newMetadata)
46 > if currentMetadata, ok := svc.ClusterMetadata.ClusterInformation[clusterName]; ok {
47 > c.reconcileMetadata(svc, clusterName, currentMetadata, newMetadata)
48 > }
49 > svc.ClusterMetadata.ClusterInformation[clusterName] = *newMetadata
50 }
51
56 currentMetadata cluster.ClusterInformation,
57 newMetadata *cluster.ClusterInformation,
59 > if clusterName != svc.ClusterMetadata.CurrentClusterName {
60 c.logger.Warn(
61 "ClusterInformation in static config is deprecated. Please use TCTL tool to configure remote cluster connections",
65 return
66 }
67 > newMetadata.RPCAddress = currentMetadata.RPCAddress cluster_metadata_loader.go
68 > c.logger.Info(fmt.Sprintf("Use rpc address %v for cluster %v.", newMetadata.RPCAddress, clusterName))
69 }
70
71 // backfillShardCount is to add backward compatibility to the svc based cluster connection. It sets the shard count for
72 // newMetadata to the number of shards in the current cluster, if the shard count is not set in the database.
73 > func (c *ClusterMetadataLoader) backfillShardCount(svc *config.Config, newMetadata *cluster.ClusterInformation) { cluster_metadata_loader.go
74 > if newMetadata.ShardCount == 0 {
75 newMetadata.ShardCount = svc.Persistence.NumHistoryShards
76 }
go.temporal.io/server/api/enums/v1/cluster.pb.go 26 covered LOC · 4 ranges

Open complete file

76 }
77
78 > func (ClusterMemberRole) Descriptor() protoreflect.EnumDescriptor { cluster.pb.go
79 > return file_temporal_server_api_enums_v1_cluster_proto_enumTypes[0].Descriptor()
80 > }
81
82 func (ClusterMemberRole) Type() protoreflect.EnumType {
149 }
150
151 > func (HealthState) Descriptor() protoreflect.EnumDescriptor { cluster.pb.go
152 > return file_temporal_server_api_enums_v1_cluster_proto_enumTypes[1].Descriptor()
153 > }
154
155 func (HealthState) Type() protoreflect.EnumType {
209 }
210
211 > func init() { file_temporal_server_api_enums_v1_cluster_proto_init() } cluster.pb.go
212 > func file_temporal_server_api_enums_v1_cluster_proto_init() {
213 > if File_temporal_server_api_enums_v1_cluster_proto != nil {
214 return
215 }
216 > type x struct{} cluster.pb.go
217 > out := protoimpl.TypeBuilder{
218 > File: protoimpl.DescBuilder{
219 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
220 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_cluster_proto_rawDesc), len(file_temporal_server_api_enums_v1_cluster_proto_rawDesc)),
221 > NumEnums: 2,
222 > NumMessages: 0,
223 > NumExtensions: 0,
224 > NumServices: 0,
225 > },
226 > GoTypes: file_temporal_server_api_enums_v1_cluster_proto_goTypes,
227 > DependencyIndexes: file_temporal_server_api_enums_v1_cluster_proto_depIdxs,
228 > EnumInfos: file_temporal_server_api_enums_v1_cluster_proto_enumTypes,
229 > }.Build()
230 > File_temporal_server_api_enums_v1_cluster_proto = out.File
231 > file_temporal_server_api_enums_v1_cluster_proto_goTypes = nil
232 > file_temporal_server_api_enums_v1_cluster_proto_depIdxs = nil
233 }
go.temporal.io/server/api/enums/v1/dlq.pb.go 26 covered LOC · 4 ranges

Open complete file

66 }
67
68 > func (DLQOperationType) Descriptor() protoreflect.EnumDescriptor { dlq.pb.go
69 > return file_temporal_server_api_enums_v1_dlq_proto_enumTypes[0].Descriptor()
70 > }
71
72 func (DLQOperationType) Type() protoreflect.EnumType {
130 }
131
132 > func (DLQOperationState) Descriptor() protoreflect.EnumDescriptor { dlq.pb.go
133 > return file_temporal_server_api_enums_v1_dlq_proto_enumTypes[1].Descriptor()
134 > }
135
136 func (DLQOperationState) Type() protoreflect.EnumType {
187 }
188
189 > func init() { file_temporal_server_api_enums_v1_dlq_proto_init() } dlq.pb.go
190 > func file_temporal_server_api_enums_v1_dlq_proto_init() {
191 > if File_temporal_server_api_enums_v1_dlq_proto != nil {
192 return
193 }
194 > type x struct{} dlq.pb.go
195 > out := protoimpl.TypeBuilder{
196 > File: protoimpl.DescBuilder{
197 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
198 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_dlq_proto_rawDesc), len(file_temporal_server_api_enums_v1_dlq_proto_rawDesc)),
199 > NumEnums: 2,
200 > NumMessages: 0,
201 > NumExtensions: 0,
202 > NumServices: 0,
203 > },
204 > GoTypes: file_temporal_server_api_enums_v1_dlq_proto_goTypes,
205 > DependencyIndexes: file_temporal_server_api_enums_v1_dlq_proto_depIdxs,
206 > EnumInfos: file_temporal_server_api_enums_v1_dlq_proto_enumTypes,
207 > }.Build()
208 > File_temporal_server_api_enums_v1_dlq_proto = out.File
209 > file_temporal_server_api_enums_v1_dlq_proto_goTypes = nil
210 > file_temporal_server_api_enums_v1_dlq_proto_depIdxs = nil
211 }
go.temporal.io/server/api/enums/v1/workflow.pb.go 26 covered LOC · 4 ranges

Open complete file

86 }
87
88 > func (WorkflowExecutionState) Descriptor() protoreflect.EnumDescriptor { workflow.pb.go
89 > return file_temporal_server_api_enums_v1_workflow_proto_enumTypes[0].Descriptor()
90 > }
91
92 func (WorkflowExecutionState) Type() protoreflect.EnumType {
150 }
151
152 > func (WorkflowBackoffType) Descriptor() protoreflect.EnumDescriptor { workflow.pb.go
153 > return file_temporal_server_api_enums_v1_workflow_proto_enumTypes[1].Descriptor()
154 > }
155
156 func (WorkflowBackoffType) Type() protoreflect.EnumType {
275 }
276
277 > func init() { file_temporal_server_api_enums_v1_workflow_proto_init() } workflow.pb.go
278 > func file_temporal_server_api_enums_v1_workflow_proto_init() {
279 > if File_temporal_server_api_enums_v1_workflow_proto != nil {
280 return
281 }
282 > type x struct{} workflow.pb.go
283 > out := protoimpl.TypeBuilder{
284 > File: protoimpl.DescBuilder{
285 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
286 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_workflow_proto_rawDesc), len(file_temporal_server_api_enums_v1_workflow_proto_rawDesc)),
287 > NumEnums: 3,
288 > NumMessages: 0,
289 > NumExtensions: 0,
290 > NumServices: 0,
291 > },
292 > GoTypes: file_temporal_server_api_enums_v1_workflow_proto_goTypes,
293 > DependencyIndexes: file_temporal_server_api_enums_v1_workflow_proto_depIdxs,
294 > EnumInfos: file_temporal_server_api_enums_v1_workflow_proto_enumTypes,
295 > }.Build()
296 > File_temporal_server_api_enums_v1_workflow_proto = out.File
297 > file_temporal_server_api_enums_v1_workflow_proto_goTypes = nil
298 > file_temporal_server_api_enums_v1_workflow_proto_depIdxs = nil
299 }
go.temporal.io/server/chasm/lib/scheduler/gen/schedulerpb/v1/message.pb.go 26 covered LOC · 1 range

Open complete file

843 }
844
845 > func init() { file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_init() } message.pb.go
846 > func file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_init() {
847 > if File_temporal_server_chasm_lib_scheduler_proto_v1_message_proto != nil {
848 > return
849 > }
850 > file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_msgTypes[4].OneofWrappers = []any{
851 > (*BackfillerState_BackfillRequest)(nil),
852 > (*BackfillerState_TriggerRequest)(nil),
853 > }
854 > type x struct{}
855 > out := protoimpl.TypeBuilder{
856 > File: protoimpl.DescBuilder{
857 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
858 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_rawDesc), len(file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_rawDesc)),
859 > NumEnums: 0,
860 > NumMessages: 12,
861 > NumExtensions: 0,
862 > NumServices: 0,
863 > },
864 > GoTypes: file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_goTypes,
865 > DependencyIndexes: file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_depIdxs,
866 > MessageInfos: file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_msgTypes,
867 > }.Build()
868 > File_temporal_server_chasm_lib_scheduler_proto_v1_message_proto = out.File
869 > file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_goTypes = nil
870 > file_temporal_server_chasm_lib_scheduler_proto_v1_message_proto_depIdxs = nil
871 }
go.temporal.io/server/common/persistence/serialization/codec.go 26 covered LOC · 12 ranges

Open complete file

26 // encodingTypeFromEnv returns an EncodingType based on the environment variable `TEMPORAL_TEST_DATA_ENCODING`.
27 // It defaults to "ENCODING_TYPE_PROTO3" codec if the environment variable is not set.
28 > func encodingTypeFromEnv() enumspb.EncodingType { codec.go
29 > codecType := os.Getenv(SerializerDataEncodingEnvVar)
30 > switch strings.ToLower(codecType) {
31 case "", "proto3":
32 return enumspb.ENCODING_TYPE_PROTO3
33 > case "json": codec.go
34 > return enumspb.ENCODING_TYPE_JSON
35 default:
36 //nolint:forbidigo // should fail fast and hard if used incorrectly
65 encoding enumspb.EncodingType,
66 options ...EncodeOption,
67 > ) (*commonpb.DataBlob, error) { codec.go
68 > opts := encodeOptions{}
69 > for _, option := range options {
70 option(&opts)
71 }
72
73 > if m == nil { codec.go
74 return &commonpb.DataBlob{
75 Data: nil,
78 }
79
80 > switch encoding { codec.go
81 > case enumspb.ENCODING_TYPE_JSON: codec.go
82 > blob, err := codec.NewJSONPBEncoder().Encode(m)
83 > if err != nil {
84 return nil, err
85 }
86 > return &commonpb.DataBlob{ codec.go
87 > Data: blob,
88 > EncodingType: enumspb.ENCODING_TYPE_JSON,
89 > }, nil
90 case enumspb.ENCODING_TYPE_PROTO3:
91 data, err := proto.MarshalOptions{Deterministic: opts.deterministic}.Marshal(m)
102 }
103
104 > func Decode(data *commonpb.DataBlob, result proto.Message) error { codec.go
105 > if data == nil {
106 return NewDeserializationError(enumspb.ENCODING_TYPE_UNSPECIFIED, errors.New("cannot decode nil"))
107 }
108
109 > switch data.EncodingType { codec.go
110 > case enumspb.ENCODING_TYPE_JSON: codec.go
111 > return codec.NewJSONPBEncoder().Decode(data.Data, result)
112 > case enumspb.ENCODING_TYPE_PROTO3: codec.go
113 > err := proto.Unmarshal(data.Data, result)
114 > if err != nil {
115 return NewDeserializationError(enumspb.ENCODING_TYPE_PROTO3, err)
116 }
117 > return nil codec.go
118 default:
119 return NewUnknownEncodingTypeError(data.EncodingType.String(), enumspb.ENCODING_TYPE_JSON, enumspb.ENCODING_TYPE_PROTO3)
go.temporal.io/server/common/persistence/workflow_state_status_validator.go 26 covered LOC · 15 ranges

Open complete file

32 state enumsspb.WorkflowExecutionState,
33 status enumspb.WorkflowExecutionStatus,
35 >
36 > if err := validateWorkflowState(state); err != nil {
37 return err
38 }
39 > if err := validateWorkflowStatus(status); err != nil { workflow_state_status_validator.go
40 return err
41 }
42
43 // validate workflow state & status
44 > if state == enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED { workflow_state_status_validator.go
45 if status == enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING || status == enumspb.WORKFLOW_EXECUTION_STATUS_PAUSED {
46 return serviceerror.NewInternalf("Create workflow with invalid state: %v or status: %v", state, status)
47 }
49 > if status != enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING {
50 return serviceerror.NewInternalf("Create workflow with invalid state: %v or status: %v", state, status)
51 }
52 }
54 }
55
58 state enumsspb.WorkflowExecutionState,
59 status enumspb.WorkflowExecutionStatus,
61 >
62 > if err := validateWorkflowState(state); err != nil {
63 return err
64 }
65 > if err := validateWorkflowStatus(status); err != nil { workflow_state_status_validator.go
66 return err
67 }
68
69 // validate workflow state & status
71 > case enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING, enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE: workflow_state_status_validator.go
72 > if status != enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING && status != enumspb.WORKFLOW_EXECUTION_STATUS_PAUSED {
73 return serviceerror.NewInternalf("Update workflow with invalid state: %v or status: %v", state, status)
74 }
77 return serviceerror.NewInternalf("Update workflow with invalid state: %v or status: %v", state, status)
78 }
80 > if status == enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING || status == enumspb.WORKFLOW_EXECUTION_STATUS_PAUSED {
81 return serviceerror.NewInternalf("Update workflow with invalid state: %v or status: %v", state, status)
82 }
83 }
85 }
86
go.temporal.io/server/common/primitives/timestamp/duration.go 26 covered LOC · 13 ranges

Open complete file

19 )
20
21 > func DurationValue(d *durationpb.Duration) time.Duration { duration.go
22 > if d == nil {
23 > return 0 duration.go
24 > }
25 > return d.AsDuration() duration.go
26 }
27
28 > func DurationPtr(td time.Duration) *durationpb.Duration { duration.go
29 > return durationpb.New(td)
30 > }
31
32 func MinDurationPtr(d1 *durationpb.Duration, d2 *durationpb.Duration) *durationpb.Duration {
35 }
36
37 > func DurationFromSeconds(s int64) *durationpb.Duration { duration.go
38 > return durationMultipleOf(s, time.Second)
39 > }
40
41 func DurationFromMinutes(m int64) *durationpb.Duration {
47 }
48
49 > func DurationFromDays(d int32) *durationpb.Duration { duration.go
50 > return durationMultipleOf(int64(d), time.Hour*24)
51 > }
52
53 > func durationMultipleOf(amt int64, mult time.Duration) *durationpb.Duration { duration.go
54 > return DurationPtr(time.Duration(amt) * mult)
55 > }
56
57 // ValidateAndCapProtoDuration validates protobuf durations for two conditions:
65 // durationpb.CheckValid cannot be used directly because it will return an error for
66 // very large durations, but we are okay with truncating these.
67 > func ValidateAndCapProtoDuration(d *durationpb.Duration) error { duration.go
68 > if d == nil {
69 > // nil durations are converted to 0 value duration.go
70 > return nil
71 > }
72
73 > if (d.GetSeconds() > 0 && d.GetNanos() < 0) || (d.GetSeconds() < 0 && d.GetNanos() > 0) { duration.go
74 return errMismatchedSigns
75 }
76
77 // this is a best effort conversion and will return the closest value in the event of overflow.
78 > if d.AsDuration() < 0 { duration.go
79 return errNegativeDuration
80 }
81
82 > if d.AsDuration() > maxAllowedDuration { duration.go
83 d.Seconds = maxSeconds
84 d.Nanos = 0 // A year is always a round number of seconds.
85 }
86
87 > return nil duration.go
88 }
go.temporal.io/server/common/rpc/interceptor/sdk_version.go 26 covered LOC · 4 ranges

Open complete file

20
21 // NewSDKVersionInterceptor creates a new SDKVersionInterceptor with default max set size
22 > func NewSDKVersionInterceptor() *SDKVersionInterceptor { sdk_version.go
23 > return &SDKVersionInterceptor{
24 > sdkInfoSet: make(map[versioninfo.SDKInfo]struct{}),
25 > versionChecker: headers.NewDefaultVersionChecker(),
26 > maxSetSize: defaultMaxSetSize,
27 > }
28 > }
29
30 // Intercept a grpc request
34 info *grpc.UnaryServerInfo,
35 handler grpc.UnaryHandler,
36 > ) (any, error) { sdk_version.go
37 > sdkName, sdkVersion := headers.GetClientNameAndVersion(ctx)
38 > if sdkName != "" && sdkVersion != "" {
39 > vi.RecordSDKInfo(sdkName, sdkVersion)
40 > if err := vi.versionChecker.ClientSupported(ctx); err != nil {
41 return nil, err
42 }
43 }
44 > return handler(ctx, req) sdk_version.go
45 }
46
47 // RecordSDKInfo records name and version tuple in memory
48 > func (vi *SDKVersionInterceptor) RecordSDKInfo(name, version string) { sdk_version.go
49 > info := versioninfo.SDKInfo{Name: name, Version: version}
50 >
51 > vi.RLock()
52 > overCap := len(vi.sdkInfoSet) >= vi.maxSetSize
53 > _, found := vi.sdkInfoSet[info]
54 > vi.RUnlock()
55 >
56 > if !overCap && !found {
57 > vi.Lock()
58 > vi.sdkInfoSet[info] = struct{}{}
59 > vi.Unlock()
60 > }
61 }
62
go.temporal.io/server/service/frontend/protojson_marshaler.go 26 covered LOC · 3 ranges

Open complete file

32 }
33
34 > func newTemporalProtoMarshaler(indent string, enablePayloadShorthand bool) (string, temporalProtoMarshaler) { protojson_marshaler.go
35 > metadata := map[string]any{}
36 > if enablePayloadShorthand {
37 > metadata[commonpb.EnablePayloadShorthandMetadataKey] = true
38 > }
39 // Shorthand is enabled by default
40 > contentType := runtime.MIMEWildcard protojson_marshaler.go
41 > if enablePayloadShorthand {
42 > if indent != "" {
43 > contentType = "application/json+pretty"
44 > }
45 > } else {
46 > if indent != "" {
47 > contentType = "application/json+pretty+no-payload-shorthand"
48 > } else {
49 > contentType = "application/json+no-payload-shorthand"
50 > }
51 }
52 > return contentType, temporalProtoMarshaler{ protojson_marshaler.go
53 > contentType: contentType,
54 > mOpts: temporalproto.CustomJSONMarshalOptions{
55 > Indent: indent,
56 > Metadata: metadata,
57 > },
58 > uOpts: temporalproto.CustomJSONUnmarshalOptions{
59 > Metadata: metadata,
60 > },
61 > }
62 }
63
go.temporal.io/server/service/history/api/respondworkflowtaskcompleted/workflow_size_checker.go 26 covered LOC · 3 ranges

Open complete file

42 metricsHandler metrics.Handler,
43 logger log.Logger,
44 > ) *workflowSizeChecker { workflow_size_checker.go
45 > return &workflowSizeChecker{
46 > workflowSizeLimits: limits,
47 > mutableState: mutableState,
48 > searchAttributesValidator: searchAttributesValidator,
49 > metricsHandler: metricsHandler,
50 > logger: logger,
51 > }
52 > }
53
54 func (c *workflowSizeChecker) checkIfPayloadSizeExceedsLimit(
56 payloadSize int,
57 message string,
58 > ) error { workflow_size_checker.go
59 >
60 > executionInfo := c.mutableState.GetExecutionInfo()
61 > executionState := c.mutableState.GetExecutionState()
62 > err := common.CheckEventBlobSizeLimit(
63 > payloadSize,
64 > c.blobSizeLimitWarn,
65 > c.blobSizeLimitError,
66 > executionInfo.NamespaceId,
67 > executionInfo.WorkflowId,
68 > executionState.RunId,
69 > c.metricsHandler.WithTags(commandTypeTag),
70 > c.logger,
71 > commandTypeTag.Value,
72 > )
73 > if err != nil {
74 return fmt.Errorf("%s", message) // nolint:err113
75 }
76 > return nil workflow_size_checker.go
77 }
78
go.temporal.io/server/service/history/api/update_workflow_util.go 26 covered LOC · 11 ranges

Open complete file

20 shard historyi.ShardContext,
21 workflowConsistencyChecker WorkflowConsistencyChecker,
22 > ) (retError error) { update_workflow_util.go
23 > workflowLease, err := workflowConsistencyChecker.GetWorkflowLease(
24 > ctx,
25 > reqClock,
26 > workflowKey,
27 > locks.PriorityHigh,
28 > )
29 > if err != nil {
30 return err
31 }
32 > defer func() { workflowLease.GetReleaseFn()(retError) }() update_workflow_util.go
33
34 > return UpdateWorkflowWithNew(shard, ctx, workflowLease, action, newWorkflowFn) update_workflow_util.go
35 }
36
66 action UpdateWorkflowActionFunc,
67 newWorkflowFn func() (historyi.WorkflowContext, historyi.MutableState, error),
68 > ) (retError error) { update_workflow_util.go
69 >
70 > // conduct caller action
71 > postActions, err := action(workflowLease)
72 > if err != nil {
73 return err
74 }
75 > if postActions.Noop { update_workflow_util.go
76 return nil
77 }
78
79 > mutableState := workflowLease.GetMutableState() update_workflow_util.go
80 > if postActions.CreateWorkflowTask {
81 // Create a transfer task to schedule a workflow task only if the workflow is not paused and there is no pending workflow task.
82 if !mutableState.HasPendingWorkflowTask() && !mutableState.IsWorkflowExecutionStatusPaused() {
90 }
91
92 > var updateErr error update_workflow_util.go
93 > if newWorkflowFn != nil {
94 newContext, newMutableState, err := newWorkflowFn()
95 if err != nil {
110 newMutableState,
111 )
112 > } else { update_workflow_util.go
113 > updateErr = workflowLease.GetContext().UpdateWorkflowExecutionAsActive(ctx, shardContext)
114 > }
115
116 > if updateErr != nil { update_workflow_util.go
117 return updateErr
118 }
119
120 > if postActions.AbortUpdates { update_workflow_util.go
121 workflowLease.GetContext().UpdateRegistry(ctx).Abort(update.AbortReasonWorkflowCompleted)
122 }
123
124 > return nil update_workflow_util.go
125 }
go.temporal.io/server/service/history/queues/scheduler_quotas.go 26 covered LOC · 8 ranges

Open complete file

13 persistenceNamespaceRateFn quotas.NamespaceRateFn,
14 persistenceHostRateFn quotas.RateFn,
15 > ) (SchedulerRateLimiter, error) { scheduler_quotas.go
16 >
17 > namespaceRateFnWithFallback := func(namespace string) float64 {
18 if rate := namespaceRateFn(namespace); rate > 0 {
19 return rate
23 }
24
25 > hostRateFnWithFallback := func() float64 { scheduler_quotas.go
26 > if rate := hostRateFn(); rate > 0 {
27 return rate
28 }
29
30 > return persistenceHostRateFn() scheduler_quotas.go
31 }
32
33 > requestPriorityFn := func(req quotas.Request) int { scheduler_quotas.go
34 // NOTE: task scheduler will use the string format for task priority as the caller type.
35 // see channelQuotaRequestFn in scheduler.go
43 }
44
45 > priorityToRateLimiters := make(map[int]quotas.RequestRateLimiter, len(tasks.PriorityName)) scheduler_quotas.go
46 > for priority := range tasks.PriorityName {
47 > priorityToRateLimiters[int(priority)] = newTaskRequestRateLimiter(
48 > namespaceRateFnWithFallback,
49 > hostRateFnWithFallback,
50 > )
51 > }
52
53 > priorityLimiter := quotas.NewPriorityRateLimiter(requestPriorityFn, priorityToRateLimiters) scheduler_quotas.go
54 >
55 > return priorityLimiter, nil
56 }
57
59 namespaceRateFn quotas.NamespaceRateFn,
60 hostRateFn quotas.RateFn,
61 > ) quotas.RequestRateLimiter { scheduler_quotas.go
62 > hostRequestRateLimiter := quotas.NewRequestRateLimiterAdapter(
63 > quotas.NewDefaultIncomingRateLimiter(hostRateFn),
64 > )
65 > namespaceRequestRateLimiterFn := func(req quotas.Request) quotas.RequestRateLimiter {
66 if len(req.Caller) == 0 {
67 return quotas.NoopRequestRateLimiter
81 }
82
83 > return quotas.NewMultiRequestRateLimiter( scheduler_quotas.go
84 > quotas.NewNamespaceRequestRateLimiter(namespaceRequestRateLimiterFn),
85 > hostRequestRateLimiter,
86 > )
87 }
go.temporal.io/server/service/history/queues/scope.go 26 covered LOC · 11 ranges

Open complete file

18 r Range,
19 predicate tasks.Predicate,
20 > ) Scope { scope.go
21 > return Scope{
22 > Range: r,
23 > Predicate: predicate,
24 > }
25 > }
26
27 func (s *Scope) Contains(task tasks.Task) bool {
32 func (s *Scope) CanSplitByRange(
33 key tasks.Key,
34 > ) bool { scope.go
35 > return s.Range.CanSplit(key)
36 > }
37
38 func (s *Scope) SplitByRange(
39 key tasks.Key,
40 > ) (left Scope, right Scope) { scope.go
41 > if !s.CanSplitByRange(key) {
42 panic(fmt.Sprintf("Unable to split scope with range %v at %v", s.Range, key))
43 }
44
45 > leftRange, rightRange := s.Range.Split(key) scope.go
46 > return NewScope(leftRange, s.Predicate), NewScope(rightRange, s.Predicate)
47 }
48
63 func (s *Scope) CanMergeByRange(
64 incomingScope Scope,
65 > ) bool { scope.go
66 > return s.Range.CanMerge(incomingScope.Range) &&
67 > s.Predicate.Equals(incomingScope.Predicate)
68 > }
69
70 func (s *Scope) MergeByRange(
71 incomingScope Scope,
72 > ) Scope { scope.go
73 > if !s.CanMergeByRange(incomingScope) {
74 panic(fmt.Sprintf("Unable to merge scope with range %v with range %v by range", s.Range, incomingScope.Range))
75 }
76
77 > return NewScope(s.Range.Merge(incomingScope.Range), s.Predicate) scope.go
78 }
79
94 }
95
96 > func (s *Scope) IsEmpty() bool { scope.go
97 > if s.Range.IsEmpty() {
98 > return true scope.go
99 > }
100
101 > if _, ok := s.Predicate.(*predicates.EmptyImpl[tasks.Task]); ok { scope.go
102 return true
103 }
104
105 > return false scope.go
106 }
107
go.temporal.io/server/chasm/lib/activity/gen/activitypb/v1/activity_state.pb.go 25 covered LOC · 2 ranges

Open complete file

1382 }
1383
1384 > func init() { file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_init() } activity_state.pb.go
1385 > func file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_init() {
1386 > if File_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto != nil {
1387 return
1388 }
1389 > file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_msgTypes[7].OneofWrappers = []any{ activity_state.pb.go
1390 > (*ActivityOutcome_Successful_)(nil),
1391 > (*ActivityOutcome_Failed_)(nil),
1392 > }
1393 > type x struct{}
1394 > out := protoimpl.TypeBuilder{
1395 > File: protoimpl.DescBuilder{
1396 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1397 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_rawDesc), len(file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_rawDesc)),
1398 > NumEnums: 2,
1399 > NumMessages: 11,
1400 > NumExtensions: 0,
1401 > NumServices: 0,
1402 > },
1403 > GoTypes: file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_goTypes,
1404 > DependencyIndexes: file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_depIdxs,
1405 > EnumInfos: file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_enumTypes,
1406 > MessageInfos: file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_msgTypes,
1407 > }.Build()
1408 > File_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto = out.File
1409 > file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_goTypes = nil
1410 > file_temporal_server_chasm_lib_activity_proto_v1_activity_state_proto_depIdxs = nil
1411 }
go.temporal.io/server/chasm/lib/nexusoperation/gen/nexusoperationpb/v1/operation.pb.go 25 covered LOC · 2 ranges

Open complete file

998 }
999
1000 > func init() { file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_init() } operation.pb.go
1001 > func file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_init() {
1002 > if File_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto != nil {
1003 return
1004 }
1005 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_msgTypes[2].OneofWrappers = []any{ operation.pb.go
1006 > (*OperationOutcome_Successful_)(nil),
1007 > (*OperationOutcome_Failed_)(nil),
1008 > }
1009 > type x struct{}
1010 > out := protoimpl.TypeBuilder{
1011 > File: protoimpl.DescBuilder{
1012 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1013 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_rawDesc), len(file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_rawDesc)),
1014 > NumEnums: 2,
1015 > NumMessages: 8,
1016 > NumExtensions: 0,
1017 > NumServices: 0,
1018 > },
1019 > GoTypes: file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_goTypes,
1020 > DependencyIndexes: file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_depIdxs,
1021 > EnumInfos: file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_enumTypes,
1022 > MessageInfos: file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_msgTypes,
1023 > }.Build()
1024 > File_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto = out.File
1025 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_goTypes = nil
1026 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_operation_proto_depIdxs = nil
1027 }
go.temporal.io/server/client/history/metric_client.go 25 covered LOC · 8 ranges

Open complete file

29 logger log.Logger,
30 throttledLogger log.Logger,
31 > ) historyservice.HistoryServiceClient { metric_client.go
32 > return &metricClient{
33 > client: client,
34 > metricsHandler: metricsHandler,
35 > logger: logger,
36 > throttledLogger: throttledLogger,
37 > }
38 > }
39
40 > func (c *metricClient) Stop() { metric_client.go
41 > if s, ok := c.client.(interface{ Stop() }); ok {
42 > s.Stop()
43 > }
44 }
45
88 ctx context.Context,
89 operation string,
90 > ) (metrics.Handler, time.Time) { metric_client.go
91 > caller := headers.GetCallerInfo(ctx).CallerName
92 > metricsHandler := c.metricsHandler.WithTags(metrics.OperationTag(operation), metrics.NamespaceTag(caller), metrics.ServiceRoleTag(metrics.HistoryRoleTagValue))
93 > metrics.ClientRequests.With(metricsHandler).Record(1)
94 > return metricsHandler, time.Now().UTC()
95 > }
96
97 func (c *metricClient) finishMetricsRecording(
99 startTime time.Time,
100 err error,
101 > ) { metric_client.go
102 > if err != nil {
103 > switch err.(type) { metric_client.go
104 case *serviceerror.Canceled,
105 *serviceerror.DeadlineExceeded,
111 *serviceerror.ResourceExhausted:
112 // noop - not interest and too many logs
113 > default: metric_client.go
114 > c.throttledLogger.Info("history client encountered error", tag.Error(err), tag.ServiceErrorType(err))
115 }
116 > metrics.ClientFailures.With(metricsHandler).Record(1, metrics.ServiceErrorTypeTag(err)) metric_client.go
117 }
118 > metrics.ClientLatency.With(metricsHandler).Record(time.Since(startTime)) metric_client.go
119 }
go.temporal.io/server/common/metrics/grpc_stats.go 25 covered LOC · 7 ranges

Open complete file

17 }
18
19 > func NewServerStatsHandler(mh Handler) ServerStatsHandler { grpc_stats.go
20 > return &grpcStatsHandler{
21 > mh: mh,
22 > }
23 > }
24
25 > func (h *grpcStatsHandler) TagConn(ctx context.Context, _ *stats.ConnTagInfo) context.Context { grpc_stats.go
26 > return ctx
27 > }
28
29 > func (h *grpcStatsHandler) HandleConn(_ context.Context, stat stats.ConnStats) { grpc_stats.go
30 > switch stat.(type) {
31 > case *stats.ConnBegin:
32 > ServiceConnAccepted.With(h.mh).Record(1)
33 > newVal := h.activeConns.Add(1)
34 > ServiceConnActive.With(h.mh).Record(float64(newVal))
35 > case *stats.ConnEnd: grpc_stats.go
36 > ServiceConnClosed.With(h.mh).Record(1)
37 > newVal := h.activeConns.Add(-1)
38 > if newVal < 0 { // should never happen, but just in case
39 h.activeConns.Store(0)
40 newVal = 0
41 }
42 > ServiceConnActive.With(h.mh).Record(float64(newVal)) grpc_stats.go
43 }
44 }
45
46 > func (h *grpcStatsHandler) TagRPC(ctx context.Context, _ *stats.RPCTagInfo) context.Context { grpc_stats.go
47 > return ctx
48 > }
49
50 > func (h *grpcStatsHandler) HandleRPC(ctx context.Context, stat stats.RPCStats) { grpc_stats.go
51 > // nothing to do here
52 > }
go.temporal.io/server/common/persistence/dlq_metrics_emitter.go 25 covered LOC · 7 ranges

Open complete file

43 hostInfoProvider membership.HostInfoProvider,
44 taskCategoryRegistry tasks.TaskCategoryRegistry,
45 > ) *DLQMetricsEmitter { dlq_metrics_emitter.go
46 > return &DLQMetricsEmitter{
47 > status: common.DaemonStatusInitialized,
48 > shutdownCh: make(chan struct{}),
49 > metricsHandler: metricsHandler,
50 > emitMetricsTimer: time.NewTicker(emitDLQMetricsInterval),
51 > logger: logger,
52 > historyTaskQueueManager: manager,
53 > historyServiceResolver: historyServiceResolver,
54 > hostInfoProvider: hostInfoProvider,
55 > taskCategoryRegistry: taskCategoryRegistry,
56 > }
57 > }
58
59 > func (s *DLQMetricsEmitter) Start() { dlq_metrics_emitter.go
60 > if !atomic.CompareAndSwapInt32(&s.status, common.DaemonStatusInitialized, common.DaemonStatusStarted) {
61 return
62 }
63 > go s.emitMetricsLoop() dlq_metrics_emitter.go
64 }
65
66 > func (s *DLQMetricsEmitter) Stop() { dlq_metrics_emitter.go
67 > if !atomic.CompareAndSwapInt32(&s.status, common.DaemonStatusStarted, common.DaemonStatusStopped) {
68 return
69 }
70 > close(s.shutdownCh) dlq_metrics_emitter.go
71 > s.emitMetricsTimer.Stop()
72 }
73
74 > func (s *DLQMetricsEmitter) emitMetricsLoop() { dlq_metrics_emitter.go
75 > for {
76 > select {
77 > case <-s.shutdownCh: dlq_metrics_emitter.go
78 > return
79 case <-s.emitMetricsTimer.C:
80 if s.shouldEmitMetrics() {
go.temporal.io/server/common/rpc/interceptor/routing_key_interceptor.go 25 covered LOC · 8 ranges

Open complete file

81 extractors []RoutingKeyExtractorFunc,
82 logger log.Logger,
83 > ) *RoutingKeyInterceptor { routing_key_interceptor.go
84 > return &RoutingKeyInterceptor{
85 > extractors: extractors,
86 > logger: logger,
87 > }
88 > }
89
90 // WithExtractors returns a new interceptor with additional extractors prepended.
106 info *grpc.UnaryServerInfo,
107 handler grpc.UnaryHandler,
108 > ) (any, error) { routing_key_interceptor.go
109 > // Try each extractor until one returns a non-empty businessID
110 > for _, extractor := range i.extractors {
111 > if key := extractor(ctx, req, info.FullMethod); key.ID != "" || key.Strategy != namespace.RoutingStrategyDefault {
112 > i.logger.Debug("routing key extraction: adding routing key to context", routing_key_interceptor.go
113 > tag.WorkflowID(key.ID),
114 > tag.String("grpc-method", info.FullMethod),
115 > )
116 > ctx = AddRoutingKeyToContext(ctx, key)
117 > break
118 }
119 }
120
121 > return handler(ctx, req) routing_key_interceptor.go
122 }
123
124 // AddRoutingKeyToContext adds the routing Key to the context
125 > func AddRoutingKeyToContext(ctx context.Context, routingKey namespace.RoutingKey) context.Context { routing_key_interceptor.go
126 > return context.WithValue(ctx, routingKeyCtxKey, routingKey)
127 > }
128
129 // GetRoutingKeyFromContext retrieves the routing Key from the context.
130 // Returns a zero-value RoutingKey if not found.
131 > func GetRoutingKeyFromContext(ctx context.Context) namespace.RoutingKey { routing_key_interceptor.go
132 > if key, ok := ctx.Value(routingKeyCtxKey).(namespace.RoutingKey); ok {
133 > return key routing_key_interceptor.go
134 > }
135 > return namespace.RoutingKey{} routing_key_interceptor.go
136 }
go.temporal.io/server/common/tasks/execution_queue_scheduler.go 25 covered LOC · 6 ranges

Open complete file

71 metricsHandler metrics.Handler,
72 timeSource clock.TimeSource,
73 > ) *executionQueueScheduler[T] { execution_queue_scheduler.go
74 > s := &executionQueueScheduler[T]{
75 > shutdownChan: make(chan struct{}),
76 > maxQueues: maxQueues,
77 > queueTTL: queueTTL,
78 > queueConcurrency: queueConcurrency,
79 > queueKeyFn: queueKeyFn,
80 > logger: logger,
81 > metricsHandler: metricsHandler,
82 > timeSource: timeSource,
83 > queues: make(map[any]*executionQueue[T]),
84 > }
85 > s.status.Store(common.DaemonStatusInitialized)
86 > return s
87 > }
88
89 > func (s *executionQueueScheduler[T]) Start() { execution_queue_scheduler.go
90 > if !s.status.CompareAndSwap(common.DaemonStatusInitialized, common.DaemonStatusStarted) {
91 return
92 }
93 > s.logger.Info("execution queue scheduler started") execution_queue_scheduler.go
94 }
95
96 > func (s *executionQueueScheduler[T]) Stop() { execution_queue_scheduler.go
97 > if !s.status.CompareAndSwap(common.DaemonStatusStarted, common.DaemonStatusStopped) {
98 return
99 }
100
101 > close(s.shutdownChan) execution_queue_scheduler.go
102 >
103 > go func() {
104 > if success := common.AwaitWaitGroup(&s.shutdownWG, time.Minute); !success {
105 s.logger.Warn("execution queue scheduler timed out waiting for goroutines")
106 }
107 }()
108
109 > s.logger.Info("execution queue scheduler stopped") execution_queue_scheduler.go
110 }
111
go.temporal.io/server/common/tasks/rate_limited_scheduler.go 25 covered LOC · 6 ranges

Open complete file

44 logger log.Logger,
45 metricsHandler metrics.Handler,
46 > ) *RateLimitedScheduler[T] { rate_limited_scheduler.go
47 > return &RateLimitedScheduler[T]{
48 > scheduler: scheduler,
49 > rateLimiter: rateLimiter,
50 > timeSource: timeSource,
51 > quotaRequestFn: quotaRequestFn,
52 > metricTagsFn: metricTagsFn,
53 > options: options,
54 > logger: logger,
55 > metricsHandler: metricsHandler,
56 > }
57 > }
58
59 func (s *RateLimitedScheduler[T]) Submit(task T) {
62 }
63
64 > func (s *RateLimitedScheduler[T]) TrySubmit(task T) bool { rate_limited_scheduler.go
65 > if !s.allow(task) {
66 return false
67 }
70 // Because when that happens, the underlying scheduler is already busy and overloaded.
71 // There's no point in cancelling the token, which allows more tasks to be submitted the underlying scheduler.
72 > return s.scheduler.TrySubmit(task) rate_limited_scheduler.go
73 }
74
75 > func (s *RateLimitedScheduler[T]) Start() { rate_limited_scheduler.go
76 > s.scheduler.Start()
77 > }
78
79 > func (s *RateLimitedScheduler[T]) Stop() { rate_limited_scheduler.go
80 > s.scheduler.Stop()
81 > }
82
83 func (s *RateLimitedScheduler[T]) wait(task T) {
112 }
113
114 > func (s *RateLimitedScheduler[T]) allow(task T) bool { rate_limited_scheduler.go
115 > if !s.options.Enabled() {
116 > return true
117 > }
118 if allow := s.rateLimiter.Allow(
119 s.timeSource.Now(),
go.temporal.io/server/service/history/api/command_attr_validator.go 25 covered LOC · 8 ranges

Open complete file

42 config *configs.Config,
43 searchAttributesValidator *searchattribute.Validator,
44 > ) *CommandAttrValidator { command_attr_validator.go
45 > return &CommandAttrValidator{
46 > namespaceRegistry: namespaceRegistry,
47 > config: config,
48 > maxIDLengthLimit: config.MaxIDLengthLimit(),
49 > searchAttributesValidator: searchAttributesValidator,
50 > getDefaultActivityRetrySettings: config.DefaultActivityRetryPolicy,
51 > getDefaultWorkflowRetrySettings: config.DefaultWorkflowRetryPolicy,
52 > enableCrossNamespaceCommands: config.EnableCrossNamespaceCommands,
53 > }
54 > }
55
56 func (v *CommandAttrValidator) ValidateProtocolMessageAttributes(
219 func (v *CommandAttrValidator) ValidateCompleteWorkflowExecutionAttributes(
220 attributes *commandpb.CompleteWorkflowExecutionCommandAttributes,
221 > ) (enumspb.WorkflowTaskFailedCause, error) { command_attr_validator.go
222 >
223 > const failedCause = enumspb.WORKFLOW_TASK_FAILED_CAUSE_BAD_COMPLETE_WORKFLOW_EXECUTION_ATTRIBUTES
224 > if attributes == nil {
225 return failedCause, serviceerror.NewInvalidArgument("CompleteWorkflowExecutionCommandAttributes is not set on CompleteWorkflowExecutionCommand.")
226 }
227 > return enumspb.WORKFLOW_TASK_FAILED_CAUSE_UNSPECIFIED, nil command_attr_validator.go
228 }
229
637 func (v *CommandAttrValidator) ValidateCommandSequence(
638 commands []*commandpb.Command,
639 > ) error { command_attr_validator.go
640 > closeCommand := enumspb.COMMAND_TYPE_UNSPECIFIED
641 >
642 > for _, command := range commands {
643 > if closeCommand != enumspb.COMMAND_TYPE_UNSPECIFIED { command_attr_validator.go
644 return serviceerror.NewInvalidArgumentf(
645 "invalid command sequence: [%v], command %s must be the last command.",
649
650 // nolint:exhaustive
651 > switch command.GetCommandType() { command_attr_validator.go
652 case enumspb.COMMAND_TYPE_SCHEDULE_ACTIVITY_TASK,
653 enumspb.COMMAND_TYPE_REQUEST_CANCEL_ACTIVITY_TASK,
667 enumspb.COMMAND_TYPE_COMPLETE_WORKFLOW_EXECUTION,
668 enumspb.COMMAND_TYPE_FAIL_WORKFLOW_EXECUTION,
669 > enumspb.COMMAND_TYPE_CANCEL_WORKFLOW_EXECUTION: command_attr_validator.go
670 > closeCommand = command.GetCommandType()
671 default:
672 // The default is to fail with invalid argument to force authors of new commands to consider whether it's a
go.temporal.io/server/service/matching/backlog_age_tracker.go 25 covered LOC · 11 ranges

Open complete file

17 }
18
19 > func newBacklogAgeTracker() backlogAgeTracker { backlog_age_tracker.go
20 > return backlogAgeTracker{tree: *treemap.NewWith(godsutils.Int64Comparator)}
21 > }
22
23 // record adds or removes a task from the tracker.
24 > func (b backlogAgeTracker) record(ts *timestamppb.Timestamp, delta int) { backlog_age_tracker.go
25 > if ts == nil {
26 return
27 }
28
29 > createTime := ts.AsTime().UnixNano() backlog_age_tracker.go
30 > count := delta
31 > if prev, ok := b.tree.Get(createTime); ok {
32 > count += prev.(int) // nolint:revive backlog_age_tracker.go
33 > }
34 > if count = max(0, count); count == 0 { backlog_age_tracker.go
35 > b.tree.Remove(createTime) backlog_age_tracker.go
36 > } else { backlog_age_tracker.go
37 > b.tree.Put(createTime, count)
38 > }
39 }
40
41 // oldestTime returns the time of the oldest task in this backlog, or
42 // the zero Time if empty.
43 > func (b backlogAgeTracker) oldestTime() time.Time { backlog_age_tracker.go
44 > if b.tree.Empty() {
45 > return time.Time{} backlog_age_tracker.go
46 > }
47 > k, _ := b.tree.Min() backlog_age_tracker.go
48 > return time.Unix(0, k.(int64)) // nolint:revive
49 }
50
51 // minNonZeroTime returns the minimum time of a and b, ignoring zero times.
52 // If both a and b are zero, it returns zero.
53 > func minNonZeroTime(a, b time.Time) time.Time { backlog_age_tracker.go
54 > if a.IsZero() {
55 > return b
56 > } else if b.IsZero() {
57 return a
58 }
go.temporal.io/server/api/namespace/v1/message.pb.go 24 covered LOC · 4 ranges

Open complete file

50 func (*NamespaceCacheInfo) ProtoMessage() {}
51
52 > func (x *NamespaceCacheInfo) ProtoReflect() protoreflect.Message { message.pb.go
53 > mi := &file_temporal_server_api_namespace_v1_message_proto_msgTypes[0]
54 > if x != nil {
55 ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
56 if ms.LoadMessageInfo() == nil {
59 return ms
60 }
61 > return mi.MessageOf(x) message.pb.go
62 }
63
114 }
115
116 > func init() { file_temporal_server_api_namespace_v1_message_proto_init() } message.pb.go
117 > func file_temporal_server_api_namespace_v1_message_proto_init() {
118 > if File_temporal_server_api_namespace_v1_message_proto != nil {
119 return
120 }
121 > type x struct{} message.pb.go
122 > out := protoimpl.TypeBuilder{
123 > File: protoimpl.DescBuilder{
124 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
125 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_namespace_v1_message_proto_rawDesc), len(file_temporal_server_api_namespace_v1_message_proto_rawDesc)),
126 > NumEnums: 0,
127 > NumMessages: 1,
128 > NumExtensions: 0,
129 > NumServices: 0,
130 > },
131 > GoTypes: file_temporal_server_api_namespace_v1_message_proto_goTypes,
132 > DependencyIndexes: file_temporal_server_api_namespace_v1_message_proto_depIdxs,
133 > MessageInfos: file_temporal_server_api_namespace_v1_message_proto_msgTypes,
134 > }.Build()
135 > File_temporal_server_api_namespace_v1_message_proto = out.File
136 > file_temporal_server_api_namespace_v1_message_proto_goTypes = nil
137 > file_temporal_server_api_namespace_v1_message_proto_depIdxs = nil
138 }
go.temporal.io/server/api/schedule/v1/message.pb.go 24 covered LOC · 2 ranges

Open complete file

1224 }
1225
1226 > func init() { file_temporal_server_api_schedule_v1_message_proto_init() } message.pb.go
1227 > func file_temporal_server_api_schedule_v1_message_proto_init() {
1228 > if File_temporal_server_api_schedule_v1_message_proto != nil {
1229 return
1230 }
1231 > file_temporal_server_api_schedule_v1_message_proto_msgTypes[7].OneofWrappers = []any{ message.pb.go
1232 > (*WatchWorkflowResponse_Result)(nil),
1233 > (*WatchWorkflowResponse_Failure)(nil),
1234 > }
1235 > type x struct{}
1236 > out := protoimpl.TypeBuilder{
1237 > File: protoimpl.DescBuilder{
1238 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
1239 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_schedule_v1_message_proto_rawDesc), len(file_temporal_server_api_schedule_v1_message_proto_rawDesc)),
1240 > NumEnums: 0,
1241 > NumMessages: 13,
1242 > NumExtensions: 0,
1243 > NumServices: 0,
1244 > },
1245 > GoTypes: file_temporal_server_api_schedule_v1_message_proto_goTypes,
1246 > DependencyIndexes: file_temporal_server_api_schedule_v1_message_proto_depIdxs,
1247 > MessageInfos: file_temporal_server_api_schedule_v1_message_proto_msgTypes,
1248 > }.Build()
1249 > File_temporal_server_api_schedule_v1_message_proto = out.File
1250 > file_temporal_server_api_schedule_v1_message_proto_goTypes = nil
1251 > file_temporal_server_api_schedule_v1_message_proto_depIdxs = nil
1252 }
go.temporal.io/server/chasm/interceptors.go 24 covered LOC · 4 ranges

Open complete file

24 info *grpc.UnaryServerInfo,
25 handler grpc.UnaryHandler,
26 > ) (resp any, retError error) { interceptors.go
27 > // Capture panics for any handler method, not just CHASM-specific ones. This could have gone into a separate
28 > // interceptor, but having it here avoids the overhead of adding another layer to the interceptor chain.
29 > defer metrics.CapturePanic(i.logger, i.metricsHandler, &retError)
30 >
31 > ctx = NewEngineContext(ctx, i.engine)
32 > return handler(ctx, req)
33 > }
34
35 func ChasmEngineInterceptorProvider(
37 logger log.Logger,
38 metricsHandler metrics.Handler,
39 > ) *ChasmEngineInterceptor { interceptors.go
40 > return &ChasmEngineInterceptor{
41 > engine: engine,
42 > logger: logger,
43 > metricsHandler: metricsHandler,
44 > }
45 > }
46
47 // ChasmVisibilityInterceptor intercepts RPC requests and adds the CHASM
56 info *grpc.UnaryServerInfo,
57 handler grpc.UnaryHandler,
58 > ) (resp any, retError error) { interceptors.go
59 > ctx = NewVisibilityManagerContext(ctx, i.visibilityMgr)
60 > return handler(ctx, req)
61 > }
62
63 > func ChasmVisibilityInterceptorProvider(visibilityMgr VisibilityManager) *ChasmVisibilityInterceptor { interceptors.go
64 > return &ChasmVisibilityInterceptor{
65 > visibilityMgr: visibilityMgr,
66 > }
67 > }
go.temporal.io/server/chasm/lib/callback/gen/callbackpb/v1/message.pb.go 24 covered LOC · 2 ranges

Open complete file

462 }
463
464 > func init() { file_temporal_server_chasm_lib_callback_proto_v1_message_proto_init() } message.pb.go
465 > func file_temporal_server_chasm_lib_callback_proto_v1_message_proto_init() {
466 > if File_temporal_server_chasm_lib_callback_proto_v1_message_proto != nil {
467 return
468 }
469 > file_temporal_server_chasm_lib_callback_proto_v1_message_proto_msgTypes[1].OneofWrappers = []any{ message.pb.go
470 > (*Callback_Nexus_)(nil),
471 > }
472 > type x struct{}
473 > out := protoimpl.TypeBuilder{
474 > File: protoimpl.DescBuilder{
475 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
476 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_callback_proto_v1_message_proto_rawDesc), len(file_temporal_server_chasm_lib_callback_proto_v1_message_proto_rawDesc)),
477 > NumEnums: 1,
478 > NumMessages: 5,
479 > NumExtensions: 0,
480 > NumServices: 0,
481 > },
482 > GoTypes: file_temporal_server_chasm_lib_callback_proto_v1_message_proto_goTypes,
483 > DependencyIndexes: file_temporal_server_chasm_lib_callback_proto_v1_message_proto_depIdxs,
484 > EnumInfos: file_temporal_server_chasm_lib_callback_proto_v1_message_proto_enumTypes,
485 > MessageInfos: file_temporal_server_chasm_lib_callback_proto_v1_message_proto_msgTypes,
486 > }.Build()
487 > File_temporal_server_chasm_lib_callback_proto_v1_message_proto = out.File
488 > file_temporal_server_chasm_lib_callback_proto_v1_message_proto_goTypes = nil
489 > file_temporal_server_chasm_lib_callback_proto_v1_message_proto_depIdxs = nil
490 }
go.temporal.io/server/common/persistence/nexus_endpoint_manager.go 24 covered LOC · 6 ranges

Open complete file

32 serializer serialization.Serializer,
33 logger log.Logger,
34 > ) NexusEndpointManager { nexus_endpoint_manager.go
35 > return &nexusEndpointManagerImpl{
36 > persistence: persistence,
37 > serializer: serializer,
38 > logger: logger,
39 > }
40 > }
41
42 func (m *nexusEndpointManagerImpl) GetName() string {
44 }
45
46 > func (m *nexusEndpointManagerImpl) Close() { nexus_endpoint_manager.go
47 > m.persistence.Close()
48 > }
49
50 func (m *nexusEndpointManagerImpl) GetNexusEndpoint(
73 ctx context.Context,
74 request *ListNexusEndpointsRequest,
75 > ) (*ListNexusEndpointsResponse, error) { nexus_endpoint_manager.go
76 > if request.PageSize < 0 {
77 return nil, ErrNegativeListNexusEndpointsPageSize
78 }
79
80 > result := &ListNexusEndpointsResponse{} nexus_endpoint_manager.go
81 >
82 > resp, err := m.persistence.ListNexusEndpoints(ctx, request)
83 > if resp != nil {
84 > result.TableVersion = resp.TableVersion
85 > }
86 > if err != nil {
87 return result, err
88 }
89
90 > entries := make([]*persistencespb.NexusEndpointEntry, len(resp.Endpoints)) nexus_endpoint_manager.go
91 > for i, entry := range resp.Endpoints {
92 endpoint, err := m.serializer.NexusEndpointFromBlob(entry.Data)
93 if err != nil {
102 }
103
104 > result.NextPageToken = resp.NextPageToken nexus_endpoint_manager.go
105 > result.Entries = entries
106 > return result, nil
107 }
108
go.temporal.io/server/common/persistence/transitionhistory/transition_history.go 24 covered LOC · 13 ranges

Open complete file

12 func CopyVersionedTransitions(
13 transitions []*persistencespb.VersionedTransition,
14 > ) []*persistencespb.VersionedTransition { transition_history.go
15 > if transitions == nil {
16 return nil
17 }
18 > copied := make([]*persistencespb.VersionedTransition, len(transitions)) transition_history.go
19 > for i, t := range transitions {
20 > copied[i] = CopyVersionedTransition(t)
21 > }
22 > return copied
23 }
24
25 func CopyVersionedTransition(
26 transition *persistencespb.VersionedTransition,
27 > ) *persistencespb.VersionedTransition { transition_history.go
28 > if transition == nil {
29 return nil
30 }
31 > return common.CloneProto(transition) transition_history.go
32 }
33
34 func LastVersionedTransition(
35 transitions []*persistencespb.VersionedTransition,
36 > ) *persistencespb.VersionedTransition { transition_history.go
37 > if len(transitions) == 0 {
38 > // transition history is not enabled transition_history.go
39 > return nil
40 > }
41 > return transitions[len(transitions)-1] transition_history.go
42 }
43
51 func Compare(
52 a, b *persistencespb.VersionedTransition,
53 > ) int { transition_history.go
54 > if a.GetNamespaceFailoverVersion() < b.GetNamespaceFailoverVersion() {
55 return -1
56 }
57 > if a.GetNamespaceFailoverVersion() > b.GetNamespaceFailoverVersion() { transition_history.go
58 return 1
59 }
60
61 > if a.GetTransitionCount() < b.GetTransitionCount() { transition_history.go
62 > return -1 transition_history.go
63 > }
64 > if a.GetTransitionCount() > b.GetTransitionCount() { transition_history.go
65 return 1
66 }
67
68 > return 0 transition_history.go
69 }
70
go.temporal.io/server/common/rpc/interceptor/namespace.go 24 covered LOC · 10 ranges

Open complete file

25 namespaceRegistry namespace.Registry,
26 req any,
27 > ) namespace.Name { namespace.go
28 > namespaceName, err := GetNamespaceName(namespaceRegistry, req)
29 > if err != nil {
30 > return namespace.EmptyName namespace.go
31 > }
32 > return namespaceName namespace.go
33 }
34
36 namespaceRegistry namespace.Registry,
37 req any,
38 > ) (namespace.Name, error) { namespace.go
39 > switch request := req.(type) {
40 > case *workflowservice.RegisterNamespaceRequest: namespace.go
41 > // For namespace registration requests, we don't expect to find namespace so skip checking caches
42 > // to avoid caching a NotFound error from persistence readthrough
43 > return namespace.Name(request.GetNamespace()), nil
44 > case NamespaceNameGetter: namespace.go
45 > namespaceName := namespace.Name(request.GetNamespace())
46 > _, err := namespaceRegistry.GetNamespace(namespaceName)
47 > if err != nil {
48 return namespace.EmptyName, err
49 }
50 > return namespaceName, nil namespace.go
51
52 > case NamespaceIDGetter: namespace.go
53 > namespaceID := namespace.ID(request.GetNamespaceId())
54 > namespaceName, err := namespaceRegistry.GetNamespaceName(namespaceID)
55 > if err != nil {
56 return namespace.EmptyName, err
57 }
58 > return namespaceName, nil namespace.go
59
60 > default: namespace.go
61 > return namespace.EmptyName, serviceerror.NewInternalf("unable to extract namespace info from request of type %T", req)
62 }
63 }
go.temporal.io/server/api/adminservice/v1/service_grpc.pb.go 23 covered LOC · 7 ranges

Open complete file

168 }
169
170 > func NewAdminServiceClient(cc grpc.ClientConnInterface) AdminServiceClient { service_grpc.pb.go
171 > return &adminServiceClient{cc}
172 > }
173
174 func (c *adminServiceClient) RebuildMutableState(ctx context.Context, in *RebuildMutableStateRequest, opts ...grpc.CallOption) (*RebuildMutableStateResponse, error) {
424 }
425
426 > func (c *adminServiceClient) GetTaskQueueTasks(ctx context.Context, in *GetTaskQueueTasksRequest, opts ...grpc.CallOption) (*GetTaskQueueTasksResponse, error) { service_grpc.pb.go
427 > out := new(GetTaskQueueTasksResponse)
428 > err := c.cc.Invoke(ctx, AdminService_GetTaskQueueTasks_FullMethodName, in, out, opts...)
429 > if err != nil {
430 return nil, err
431 }
432 > return out, nil service_grpc.pb.go
433 }
434
855 }
856
857 > func RegisterAdminServiceServer(s grpc.ServiceRegistrar, srv AdminServiceServer) { service_grpc.pb.go
858 > s.RegisterService(&AdminService_ServiceDesc, srv)
859 > }
860
861 func _AdminService_RebuildMutableState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
1363 }
1364
1365 > func _AdminService_GetTaskQueueTasks_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { service_grpc.pb.go
1366 > in := new(GetTaskQueueTasksRequest)
1367 > if err := dec(in); err != nil {
1368 return nil, err
1369 }
1370 > if interceptor == nil { service_grpc.pb.go
1371 return srv.(AdminServiceServer).GetTaskQueueTasks(ctx, in)
1372 }
1373 > info := &grpc.UnaryServerInfo{ service_grpc.pb.go
1374 > Server: srv,
1375 > FullMethod: AdminService_GetTaskQueueTasks_FullMethodName,
1376 > }
1377 > handler := func(ctx context.Context, req interface{}) (interface{}, error) {
1378 > return srv.(AdminServiceServer).GetTaskQueueTasks(ctx, req.(*GetTaskQueueTasksRequest))
1379 > }
1380 > return interceptor(ctx, in, info, handler)
1381 }
1382
go.temporal.io/server/api/enums/v1/fairness_state.pb.go 23 covered LOC · 3 ranges

Open complete file

71 }
72
73 > func (FairnessState) Descriptor() protoreflect.EnumDescriptor { fairness_state.pb.go
74 > return file_temporal_server_api_enums_v1_fairness_state_proto_enumTypes[0].Descriptor()
75 > }
76
77 func (FairnessState) Type() protoreflect.EnumType {
123 }
124
125 > func init() { file_temporal_server_api_enums_v1_fairness_state_proto_init() } fairness_state.pb.go
126 > func file_temporal_server_api_enums_v1_fairness_state_proto_init() {
127 > if File_temporal_server_api_enums_v1_fairness_state_proto != nil {
128 return
129 }
130 > type x struct{} fairness_state.pb.go
131 > out := protoimpl.TypeBuilder{
132 > File: protoimpl.DescBuilder{
133 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
134 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_fairness_state_proto_rawDesc), len(file_temporal_server_api_enums_v1_fairness_state_proto_rawDesc)),
135 > NumEnums: 1,
136 > NumMessages: 0,
137 > NumExtensions: 0,
138 > NumServices: 0,
139 > },
140 > GoTypes: file_temporal_server_api_enums_v1_fairness_state_proto_goTypes,
141 > DependencyIndexes: file_temporal_server_api_enums_v1_fairness_state_proto_depIdxs,
142 > EnumInfos: file_temporal_server_api_enums_v1_fairness_state_proto_enumTypes,
143 > }.Build()
144 > File_temporal_server_api_enums_v1_fairness_state_proto = out.File
145 > file_temporal_server_api_enums_v1_fairness_state_proto_goTypes = nil
146 > file_temporal_server_api_enums_v1_fairness_state_proto_depIdxs = nil
147 }
go.temporal.io/server/api/enums/v1/nexus.pb.go 23 covered LOC · 3 ranges

Open complete file

102 }
103
104 > func (NexusOperationState) Descriptor() protoreflect.EnumDescriptor { nexus.pb.go
105 > return file_temporal_server_api_enums_v1_nexus_proto_enumTypes[0].Descriptor()
106 > }
107
108 func (NexusOperationState) Type() protoreflect.EnumType {
158 }
159
160 > func init() { file_temporal_server_api_enums_v1_nexus_proto_init() } nexus.pb.go
161 > func file_temporal_server_api_enums_v1_nexus_proto_init() {
162 > if File_temporal_server_api_enums_v1_nexus_proto != nil {
163 return
164 }
165 > type x struct{} nexus.pb.go
166 > out := protoimpl.TypeBuilder{
167 > File: protoimpl.DescBuilder{
168 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
169 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_nexus_proto_rawDesc), len(file_temporal_server_api_enums_v1_nexus_proto_rawDesc)),
170 > NumEnums: 1,
171 > NumMessages: 0,
172 > NumExtensions: 0,
173 > NumServices: 0,
174 > },
175 > GoTypes: file_temporal_server_api_enums_v1_nexus_proto_goTypes,
176 > DependencyIndexes: file_temporal_server_api_enums_v1_nexus_proto_depIdxs,
177 > EnumInfos: file_temporal_server_api_enums_v1_nexus_proto_enumTypes,
178 > }.Build()
179 > File_temporal_server_api_enums_v1_nexus_proto = out.File
180 > file_temporal_server_api_enums_v1_nexus_proto_goTypes = nil
181 > file_temporal_server_api_enums_v1_nexus_proto_depIdxs = nil
182 }
go.temporal.io/server/api/enums/v1/predicate.pb.go 23 covered LOC · 3 ranges

Open complete file

111 }
112
113 > func (PredicateType) Descriptor() protoreflect.EnumDescriptor { predicate.pb.go
114 > return file_temporal_server_api_enums_v1_predicate_proto_enumTypes[0].Descriptor()
115 > }
116
117 func (PredicateType) Type() protoreflect.EnumType {
170 }
171
172 > func init() { file_temporal_server_api_enums_v1_predicate_proto_init() } predicate.pb.go
173 > func file_temporal_server_api_enums_v1_predicate_proto_init() {
174 > if File_temporal_server_api_enums_v1_predicate_proto != nil {
175 return
176 }
177 > type x struct{} predicate.pb.go
178 > out := protoimpl.TypeBuilder{
179 > File: protoimpl.DescBuilder{
180 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
181 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_predicate_proto_rawDesc), len(file_temporal_server_api_enums_v1_predicate_proto_rawDesc)),
182 > NumEnums: 1,
183 > NumMessages: 0,
184 > NumExtensions: 0,
185 > NumServices: 0,
186 > },
187 > GoTypes: file_temporal_server_api_enums_v1_predicate_proto_goTypes,
188 > DependencyIndexes: file_temporal_server_api_enums_v1_predicate_proto_depIdxs,
189 > EnumInfos: file_temporal_server_api_enums_v1_predicate_proto_enumTypes,
190 > }.Build()
191 > File_temporal_server_api_enums_v1_predicate_proto = out.File
192 > file_temporal_server_api_enums_v1_predicate_proto_goTypes = nil
193 > file_temporal_server_api_enums_v1_predicate_proto_depIdxs = nil
194 }
go.temporal.io/server/chasm/lib/activity/config.go 23 covered LOC · 2 ranges

Open complete file

57 }
58
59 > func ConfigProvider(dc *dynamicconfig.Collection) *Config { config.go
60 > return &Config{
61 > BlobSizeLimitError: dynamicconfig.BlobSizeLimitError.Get(dc),
62 > BlobSizeLimitWarn: dynamicconfig.BlobSizeLimitWarn.Get(dc),
63 > BreakdownMetricsByTaskQueue: dynamicconfig.MetricsBreakdownByTaskQueue.Get(dc),
64 > DefaultActivityRetryPolicy: dynamicconfig.DefaultActivityRetryPolicy.Get(dc),
65 > EnableCallbacks: EnableCallbacks.Get(dc),
66 > Enabled: Enabled.Get(dc),
67 > LongPollBuffer: LongPollBuffer.Get(dc),
68 > LongPollTimeout: LongPollTimeout.Get(dc),
69 > MaxIDLengthLimit: dynamicconfig.MaxIDLengthLimit.Get(dc),
70 > StartDelayEnabled: StartDelayEnabled.Get(dc),
71 > MaxCallbacksPerExecution: callback.MaxPerExecution.Get(dc),
72 > VisibilityMaxPageSize: dynamicconfig.FrontendVisibilityMaxPageSize.Get(dc),
73 > }
74 > }
75
76 // linkValidatorProvider builds the linkValidator from dynamic config.
77 > func linkValidatorProvider(dc *dynamicconfig.Collection) *linkValidator { config.go
78 > return newLinkValidator(
79 > dynamicconfig.FrontendMaxLinksPerRequest.Get(dc),
80 > dynamicconfig.MaxLinksPerComponent.Get(dc),
81 > dynamicconfig.FrontendLinkMaxSize.Get(dc),
82 > )
83 > }
go.temporal.io/server/chasm/lib/workflow/nexus_library.go 23 covered LOC · 3 ranges

Open complete file

12 }
13
14 > func newNexusLibrary(config *nexusoperation.Config, nexusProcessor *chasm.NexusEndpointProcessor) *nexusLibrary { nexus_library.go
15 > return &nexusLibrary{config: config, nexusProcessor: nexusProcessor}
16 > }
17
18 > func (l *nexusLibrary) CommandHandlers() map[enumspb.CommandType]CommandHandler { nexus_library.go
19 > h := &nexusCommandHandler{config: l.config, nexusProcessor: l.nexusProcessor}
20 > return map[enumspb.CommandType]CommandHandler{
21 > enumspb.COMMAND_TYPE_SCHEDULE_NEXUS_OPERATION: h.handleScheduleCommand,
22 > enumspb.COMMAND_TYPE_REQUEST_CANCEL_NEXUS_OPERATION: h.handleCancelCommand,
23 > }
24 > }
25
26 > func (l *nexusLibrary) EventDefinitions() []EventDefinition { nexus_library.go
27 > return []EventDefinition{
28 > ScheduledEventDefinition{},
29 > CancelRequestedEventDefinition{},
30 > CancelRequestCompletedEventDefinition{},
31 > CancelRequestFailedEventDefinition{},
32 > StartedEventDefinition{},
33 > CompletedEventDefinition{},
34 > FailedEventDefinition{},
35 > CanceledEventDefinition{},
36 > TimedOutEventDefinition{},
37 > }
38 > }
go.temporal.io/server/common/config/config.go 23 covered LOC · 8 ranges

Open complete file

693
694 // Validate validates this config
695 > func (c *Config) Validate() error { config.go
696 > if err := c.Persistence.Validate(); err != nil {
697 return err
698 }
699
700 > if err := c.Archival.Validate(&c.NamespaceDefaults.Archival); err != nil { config.go
701 return err
702 }
703
704 > _, hasIFE := c.Services[string(primitives.InternalFrontendService)] config.go
705 > if hasIFE && (c.PublicClient.HostPort != "" || c.PublicClient.ForceTLSConfig != "" || c.PublicClient.HTTPHostPort != "") {
706 return fmt.Errorf("when using internal-frontend, publicClient must be empty")
707 }
708
709 > switch c.PublicClient.ForceTLSConfig { config.go
710 > case ForceTLSConfigAuto, ForceTLSConfigInternode, ForceTLSConfigFrontend:
711 default:
712 return fmt.Errorf("invalid value for publicClient.forceTLSConfig: %q", c.PublicClient.ForceTLSConfig)
713 }
714
715 > return nil config.go
716 }
717
718 // String converts the config object into a string
719 > func (c *Config) String() string { config.go
720 > var buf bytes.Buffer
721 > encoder := yaml.NewEncoder(&buf)
722 > encoder.SetIndent(2)
723 > _ = encoder.Encode(c)
724 > maskedYaml, _ := masker.MaskYaml(buf.String(), masker.DefaultYAMLFieldNames)
725 > return maskedYaml
726 > }
727
728 > func (r *GroupTLS) IsServerEnabled() bool { config.go
729 > return r.Server.KeyFile != "" || r.Server.KeyData != ""
730 > }
731
732 > func (r *GroupTLS) IsClientEnabled() bool { config.go
733 > return len(r.Client.RootCAFiles) > 0 || len(r.Client.RootCAData) > 0 ||
734 > r.Client.ForceTLS
735 > }
736
737 func (p *JWTKeyProvider) HasSourceURIsConfigured() bool {
go.temporal.io/server/common/dynamicconfig/shared_structure.go 23 covered LOC · 6 ranges

Open complete file

17 )
18
19 > func warnDefaultSharedStructure(key string, def any) { shared_structure.go
20 > if path := hasSharedStructure(reflect.ValueOf(def), "root"); path != "" {
21 sharedStructureWarnings.Store(key, path)
22 }
23 }
24
25 > func logSharedStructureWarnings(logger log.Logger) { shared_structure.go
26 > // If you see this warning, it means that a default value used in New*TypedSetting has a
27 > // non-nil slice or map in it. That can lead to confusing behavior since the value from
28 > // dynamic config will be merged over the default value (e.g. the slice will be appended
29 > // to, not replaced). If that behavior is desired, you can avoid this warning by using
30 > // New*TypedSettingWithConverter and referring to dynamicconfig.ConvertStructure
31 > // explicitly. Otherwise use nil slices and maps, including at the top level
32 > // (so `[]string(nil)` instead of `[]string{}`).
33 > logSharedStructureWarningsOnce.Do(func() {
34 > sharedStructureWarnings.Range(func(key, path any) bool {
35 softassert.Fail(logger,
36 "default value contains shared structure",
42 }
43
44 > func hasSharedStructure(v reflect.Value, path string) string { shared_structure.go
45 > // nolint:exhaustive // deliberately not exhaustive
46 > switch v.Kind() {
47 > case reflect.Map, reflect.Slice, reflect.Pointer:
48 > if !v.IsNil() {
49 return path
50 }
51 > case reflect.Interface: shared_structure.go
52 > if !v.IsNil() {
53 return hasSharedStructure(v.Elem(), path)
54 }
55 > case reflect.Struct: shared_structure.go
56 > for i := range v.NumField() {
57 > if p := hasSharedStructure(v.Field(i), path+"."+v.Type().Field(i).Name); p != "" {
58 return p
59 }
go.temporal.io/server/common/log/throttle_logger.go 23 covered LOC · 5 ranges

Open complete file

21 //
22 // Fatal/Panic/DPanic logs are always emitted without any throttling
23 > func NewThrottledLogger(logger Logger, rps quotas.RateFn) *throttledLogger { throttle_logger.go
24 > if sl, ok := logger.(SkipLogger); ok {
25 logger = sl.Skip(extraSkipForThrottleLogger)
26 }
27
28 > limiter := quotas.NewDefaultOutgoingRateLimiter(rps) throttle_logger.go
29 > tl := &throttledLogger{
30 > limiter: limiter,
31 > logger: logger,
32 > }
33 > return tl
34 }
35
40 }
41
42 > func (tl *throttledLogger) Info(msg string, tags ...tag.Tag) { throttle_logger.go
43 > tl.rateLimit(func() {
44 > tl.logger.Info(msg, tags...)
45 > })
46 }
47
81
82 // Return a logger with the specified key-value pairs set, to be included in a subsequent normal logging call
83 > func (tl *throttledLogger) With(tags ...tag.Tag) Logger { throttle_logger.go
84 > result := &throttledLogger{
85 > limiter: tl.limiter,
86 > logger: With(tl.logger, tags...),
87 > }
88 > return result
89 > }
90
91 > func (tl *throttledLogger) rateLimit(f func()) { throttle_logger.go
92 > if tl.limiter.Allow() {
93 > f()
94 > }
95 }
96
go.temporal.io/server/common/pprof/pprof.go 23 covered LOC · 5 ranges

Open complete file

31
32 // NewInitializer create a new instance of PProf Initializer
33 > func NewInitializer(cfg *config.PProf, logger log.Logger) *PProfInitializerImpl { pprof.go
34 > return &PProfInitializerImpl{
35 > PProf: cfg,
36 > Logger: logger,
37 > }
38 > }
39
40 // Start the pprof based on config
41 > func (initializer *PProfInitializerImpl) Start() error { pprof.go
42 > port := initializer.PProf.Port
43 > if port == 0 {
44 initializer.Logger.Info("PProf not started due to port not set")
45 return nil
46 }
47 > host := initializer.PProf.Host pprof.go
48 > if host == "" {
49 > // default to localhost which will favor ipv4 on dual stack
50 > // environments - configure host as `::1` to bind on ipv6 localhost
51 > host = "localhost"
52 > }
53
54 > hostPort := net.JoinHostPort(host, fmt.Sprint(port)) pprof.go
55 >
56 > if atomic.CompareAndSwapInt32(&pprofStatus, pprofNotInitialized, pprofInitialized) {
57 > go func() {
58 > initializer.Logger.Info("PProf listen on ", tag.Host(host), tag.Port(port))
59 > err := http.ListenAndServe(hostPort, nil)
60 > if err != nil {
61 initializer.Logger.Error("listen and serve err", tag.Error(err))
62 }
63 }()
64 }
65 > return nil pprof.go
66 }
go.temporal.io/server/common/searchattribute/validator.go 23 covered LOC · 5 ranges

Open complete file

59 metricsHandler metrics.Handler,
60 logger log.Logger,
61 > ) *Validator { validator.go
62 > return &Validator{
63 > searchAttributesProvider: searchAttributesProvider,
64 > searchAttributesMapperProvider: searchAttributesMapperProvider,
65 > searchAttributesNumberOfKeysLimit: searchAttributesNumberOfKeysLimit,
66 > searchAttributesSizeOfValueLimit: searchAttributesSizeOfValueLimit,
67 > searchAttributesTotalSizeLimit: searchAttributesTotalSizeLimit,
68 > visibilityManager: visibilityManager,
69 > allowList: allowList,
70 > suppressErrorSetSystemSearchAttribute: suppressErrorSetSystemSearchAttribute,
71 >
72 > metricsHandler: metricsHandler,
73 > logger: logger,
74 > }
75 > }
76
77 // Validate search attributes are valid for writing.
78 // The search attributes must be unaliased before calling validation.
79 > func (v *Validator) Validate(searchAttributes *commonpb.SearchAttributes, namespace string) error { validator.go
80 > if len(searchAttributes.GetIndexedFields()) == 0 {
81 > return nil validator.go
82 > }
83
84 lengthOfFields := len(searchAttributes.GetIndexedFields())
201 // ValidateSize validate search attributes are valid for writing and not exceed limits.
202 // The search attributes must be unaliased before calling validation.
203 > func (v *Validator) ValidateSize(searchAttributes *commonpb.SearchAttributes, namespace string) error { validator.go
204 > if searchAttributes == nil {
205 > return nil validator.go
206 > }
207
208 for saFieldName, saPayload := range searchAttributes.GetIndexedFields() {
go.temporal.io/server/common/tqid/task_queue_validator.go 23 covered LOC · 13 ranges

Open complete file

57 defaultName string,
58 maxIDLengthLimit int,
59 > ) error { task_queue_validator.go
60 > return normalizeAndValidate(taskQueue, defaultName, maxIDLengthLimit, true)
61 > }
62
63 // NormalizeAndValidateUserDefined is like NormalizeAndValidate, but specifically for external
77 parentTaskQueue string,
78 maxIDLengthLimit int,
79 > ) error { task_queue_validator.go
80 > if err := normalizeAndValidate(taskQueue, defaultName, maxIDLengthLimit, true); err != nil {
81 return err
82 }
83 // reminder: if this check goes first, taskQueue.GetName() may not be normalized yet.
84 > return primitives.CheckInternalPerNsTaskQueueAllowed(taskQueue.GetName(), parentTaskQueue) task_queue_validator.go
85 }
86
90 maxIDLengthLimit int,
91 expectRootPartition bool,
92 > ) error { task_queue_validator.go
93 > if taskQueue == nil {
94 return serviceerror.NewInvalidArgument("taskQueue is not set")
95 }
96
97 > enums.SetDefaultTaskQueueKind(&taskQueue.Kind) task_queue_validator.go
98 >
99 > if taskQueue.GetName() == "" {
100 if defaultName == "" {
101 return serviceerror.NewInvalidArgument("missing task queue name")
104 }
105
106 > if err := validate(taskQueue.GetName(), maxIDLengthLimit, expectRootPartition); err != nil { task_queue_validator.go
107 return err
108 }
109
110 > if taskQueue.GetKind() == enumspb.TASK_QUEUE_KIND_STICKY { task_queue_validator.go
111 > normalName := taskQueue.GetNormalName() task_queue_validator.go
112 > // Old SDKs might not send the normal name, so we accept empty normal names for the time being.
113 > if normalName != "" {
114 > if err := validate(normalName, maxIDLengthLimit, false); err != nil {
115 return err
116 }
134 }
135
136 > func validate(taskQueueName string, maxLength int, expectRootPartition bool) error { task_queue_validator.go
137 > if taskQueueName == "" {
138 return serviceerror.NewInvalidArgument("taskQueue is not set")
139 }
140 > if len(taskQueueName) > maxLength { task_queue_validator.go
141 return serviceerror.NewInvalidArgument("taskQueue length exceeds limit")
142 }
143
144 > if expectRootPartition && strings.HasPrefix(taskQueueName, reservedTaskQueuePrefix) { task_queue_validator.go
145 return serviceerror.NewInvalidArgumentf("task queue name cannot start with reserved prefix %v", reservedTaskQueuePrefix)
146 }
147
148 > return nil task_queue_validator.go
149 }
go.temporal.io/server/service/matching/fair_level.go 23 covered LOC · 8 ranges

Open complete file

22
23 // Returns true if a < b lexicographically.
24 > func (a fairLevel) less(b fairLevel) bool { fair_level.go
25 > return a.pass < b.pass || a.pass == b.pass && a.id < b.id
26 > }
27
28 > func newFairLevelTreeMap() *treemap.Map { fair_level.go
29 > return treemap.NewWith(func(aany, bany any) int {
30 a, b := aany.(fairLevel), bany.(fairLevel) // nolint:revive
31 if a.less(b) {
39
40 // Returns the max of a and b.
41 > func (a fairLevel) max(b fairLevel) fairLevel { fair_level.go
42 > if a.less(b) {
43 > return b
44 > }
45 return a
46 }
47
48 // Returns the next highest fair level.
49 > func (a fairLevel) inc() fairLevel { fair_level.go
50 > return fairLevel{pass: a.pass, id: a.id + 1}
51 > }
52
53 > func fairLevelFromAllocatedTask(t *persistencespb.AllocatedTaskInfo) fairLevel { fair_level.go
54 > return fairLevel{pass: t.TaskPass, id: t.TaskId}
55 > }
56
57 > func fairLevelFromProto(l *taskqueuespb.FairLevel) fairLevel { fair_level.go
58 > if l == nil {
59 > return fairLevel{}
60 > }
61 return fairLevel{pass: l.TaskPass, id: l.TaskId}
62 }
63
64 > func (a fairLevel) toProto() *taskqueuespb.FairLevel { fair_level.go
65 > if (a == fairLevel{}) {
66 > return nil fair_level.go
67 > }
68 return &taskqueuespb.FairLevel{TaskPass: a.pass, TaskId: a.id}
69 }
go.temporal.io/server/temporal/server_option.go 23 covered LOC · 6 ranges

Open complete file

31 )
32
33 > func (f applyFunc) apply(s *serverOptions) { f(s) } server_option.go
34
35 // WithConfig sets a custom configuration
36 > func WithConfig(cfg *config.Config) ServerOption { server_option.go
37 > return applyFunc(func(s *serverOptions) {
38 > s.config = cfg
39 > })
40 }
41
55
56 // ForServices indicates which supplied services (e.g. frontend, history, matching, worker) within the server to start
57 > func ForServices(names []string) ServerOption { server_option.go
58 > return applyFunc(func(s *serverOptions) {
59 > s.serviceNames = make(map[primitives.ServiceName]struct{})
60 > for _, name := range names {
61 > s.serviceNames[primitives.ServiceName(name)] = struct{}{}
62 > }
63 })
64 }
82
83 // WithLogger sets a custom logger
84 > func WithLogger(logger log.Logger) ServerOption { server_option.go
85 > return applyFunc(func(s *serverOptions) {
86 > s.logger = logger
87 > })
88 }
89
138
139 // WithDynamicConfigClient sets custom client for reading dynamic configuration.
140 > func WithDynamicConfigClient(c dynamicconfig.Client) ServerOption { server_option.go
141 > return applyFunc(func(s *serverOptions) {
142 > s.dynamicConfigClient = c
143 > })
144 }
145
195 func WithChainedFrontendGrpcInterceptors(
196 interceptors ...grpc.UnaryServerInterceptor,
197 > ) ServerOption { server_option.go
198 > return applyFunc(func(s *serverOptions) {
199 > s.customFrontendInterceptors = interceptors
200 > })
201 }
202
go.temporal.io/server/common/namespace/nsmanager/attr_validator.go 22 covered LOC · 11 ranges

Open complete file

19 func NewValidator(
20 clusterMetadata cluster.Metadata,
21 > ) *Validator { attr_validator.go
22 > return &Validator{
23 > clusterMetadata: clusterMetadata,
24 > }
25 > }
26
27 > func (d *Validator) ValidateNamespaceConfig(config *persistencespb.NamespaceConfig) error { attr_validator.go
28 > if config.HistoryArchivalState == enumspb.ARCHIVAL_STATE_ENABLED && len(config.HistoryArchivalUri) == 0 {
29 return errInvalidArchivalConfig
30 }
31 > if config.VisibilityArchivalState == enumspb.ARCHIVAL_STATE_ENABLED && len(config.VisibilityArchivalUri) == 0 { attr_validator.go
32 return errInvalidArchivalConfig
33 }
34 > return nil attr_validator.go
35 }
36
37 func (d *Validator) ValidateNamespaceReplicationConfigForLocalNamespace(
38 replicationConfig *persistencespb.NamespaceReplicationConfig,
39 > ) error { attr_validator.go
40 > activeCluster := replicationConfig.ActiveClusterName
41 > clusters := replicationConfig.Clusters
42 >
43 > if err := d.validateClusterName(activeCluster); err != nil {
44 return err
45 }
46 > for _, clusterName := range clusters { attr_validator.go
47 > if err := d.validateClusterName(clusterName); err != nil {
48 return err
49 }
50 }
51
52 > if activeCluster != d.clusterMetadata.GetCurrentClusterName() { attr_validator.go
53 return serviceerror.NewInvalidArgument("Invalid local namespace active cluster")
54 }
55
56 > if len(clusters) != 1 || clusters[0] != activeCluster { attr_validator.go
57 return serviceerror.NewInvalidArgument("Invalid local namespace clusters")
58 }
59
60 > return nil attr_validator.go
61 }
62
86 func (d *Validator) validateClusterName(
87 clusterName string,
88 > ) error { attr_validator.go
89 > if info, ok := d.clusterMetadata.GetAllClusterInfo()[clusterName]; !ok || !info.Enabled {
90 return serviceerror.NewInvalidArgumentf("Invalid cluster name: %v", clusterName)
91 }
92 > return nil attr_validator.go
93 }
go.temporal.io/server/service/history/queues/active_standby_executor.go 22 covered LOC · 6 ranges

Open complete file

26 standbyExecutor Executor,
27 logger log.Logger,
28 > ) Executor { active_standby_executor.go
29 > return &activeStandbyExecutor{
30 > currentClusterName: currentClusterName,
31 > registry: registry,
32 > activeExecutor: activeExecutor,
33 > standbyExecutor: standbyExecutor,
34 > logger: logger,
35 > }
36 > }
37
38 func (e *activeStandbyExecutor) Execute(
39 ctx context.Context,
40 executable Executable,
41 > ) ExecuteResponse { active_standby_executor.go
42 > if e.isActiveTask(executable) {
43 > return e.activeExecutor.Execute(ctx, executable) active_standby_executor.go
44 > }
45
46 // for standby tasks, use preemptable callerType to avoid impacting active traffic
53 func (e *activeStandbyExecutor) isActiveTask(
54 executable Executable,
56 > // Following is the existing task allocator logic for verifying active task
57 >
58 > namespaceID := executable.GetNamespaceID()
59 > entry, err := e.registry.GetNamespaceByID(namespace.ID(namespaceID))
60 > if err != nil {
61 e.logger.Warn("Unable to find namespace, process task as active.", tag.WorkflowNamespaceID(namespaceID), tag.Value(executable.GetTask()))
62 return true
63 }
64
65 > if entry.ActiveClusterName(namespace.RoutingKey{ID: executable.GetWorkflowID()}) != e.currentClusterName { active_standby_executor.go
66 e.logger.Debug("Process task as standby.", tag.WorkflowNamespaceID(namespaceID), tag.Value(executable.GetTask()))
67 return false
68 }
69
70 > e.logger.Debug("Process task as active.", tag.WorkflowNamespaceID(namespaceID), tag.Value(executable.GetTask())) active_standby_executor.go
71 > return true
72 }
go.temporal.io/server/service/history/tasks/task_category_registry.go 22 covered LOC · 5 ranges

Open complete file

26 // each entry point that uses it. Essentially, get it from the dependency graph instead of calling this method, unless
27 // you're in a test.
28 > func NewDefaultTaskCategoryRegistry() *MutableTaskCategoryRegistry { task_category_registry.go
29 > return &MutableTaskCategoryRegistry{
30 > categories: map[int]Category{
31 > CategoryTransfer.ID(): CategoryTransfer,
32 > CategoryTimer.ID(): CategoryTimer,
33 > CategoryVisibility.ID(): CategoryVisibility,
34 > CategoryReplication.ID(): CategoryReplication,
35 > CategoryMemoryTimer.ID(): CategoryMemoryTimer,
36 > CategoryOutbound.ID(): CategoryOutbound,
37 > },
38 > }
39 > }
40
41 // AddCategory register a Category with the registry or panics if a Category with the same ID has already been
42 // registered.
43 > func (r *MutableTaskCategoryRegistry) AddCategory(c Category) { task_category_registry.go
44 > if category, ok := r.categories[c.id]; ok {
45 panic(fmt.Sprintf(
46 "category id: %v has already been defined as type %v and name %v",
51 }
52
53 > r.categories[c.id] = c task_category_registry.go
54 }
55
56 // GetCategoryByID returns a registered Category with the same ID from the registry or false if no such Category exists.
57 > func (r *MutableTaskCategoryRegistry) GetCategoryByID(id int) (Category, bool) { task_category_registry.go
58 > category, ok := r.categories[id]
59 > return category, ok
60 > }
61
62 // GetCategories returns a deep copy of all registered Category objects from the registry.
63 > func (r *MutableTaskCategoryRegistry) GetCategories() map[int]Category { task_category_registry.go
64 > return maps.Clone(r.categories)
65 > }
go.temporal.io/server/service/matching/workers/worker_metrics_emitter.go 22 covered LOC · 6 ranges

Open complete file

24 }
25
26 > func (e *workerMetricsEmitter) emit(nsID namespace.ID, nsName namespace.Name, heartbeats []*workerpb.WorkerHeartbeat) { worker_metrics_emitter.go
27 > // The SDK aggregates all workers on the same Client into one heartbeat RPC, so
28 > // len(heartbeats) approximates workers-per-process. It's per-Client-per-Namespace,
29 > // not strictly per-process, but multiple Clients per process is uncommon in practice.
30 > metrics.WorkerRegistryWorkersPerProcess.With(e.handler).Record(int64(len(heartbeats)))
31 >
32 > enablePluginMetrics := e.config.EnablePluginMetrics != nil && e.config.EnablePluginMetrics()
33 > enablePollerAutoscalingMetrics := e.config.EnablePollerAutoscalingMetrics != nil && e.config.EnablePollerAutoscalingMetrics()
34 > enableStorageDriverMetrics := e.config.ExternalPayloadsEnabled != nil && e.config.ExternalPayloadsEnabled(nsName.String())
35 >
36 > recordedPlugins := make(map[string]bool)
37 > recordedDrivers := make(map[string]bool)
38 >
39 > for _, hb := range heartbeats {
40 > // Activity slots metric (always enabled)
41 > if hb.ActivityTaskSlotsInfo != nil {
42 > metrics.WorkerRegistryActivitySlotsUsed.With(e.handler).Record(int64(hb.ActivityTaskSlotsInfo.CurrentUsedSlots)) worker_metrics_emitter.go
43 > }
44
45 // Plugin metrics (if enabled)
46 > if enablePluginMetrics { worker_metrics_emitter.go
47 for _, pluginInfo := range hb.Plugins {
48 pluginName := pluginInfo.Name
57
58 // Poller autoscaling metrics (if enabled)
59 > if enablePollerAutoscalingMetrics { worker_metrics_emitter.go
60 e.emitPollerAutoscaling(nsID, nsName, hb)
61 }
62
63 // Storage driver metrics (if external payloads enabled)
64 > if enableStorageDriverMetrics { worker_metrics_emitter.go
65 > for _, driver := range hb.GetDrivers() { worker_metrics_emitter.go
66 driverType := driver.GetType()
67 if !recordedDrivers[driverType] {
go.temporal.io/server/chasm/lib/activity/gen/activitypb/v1/tasks.pb.go 21 covered LOC · 2 ranges

Open complete file

495 }
496
497 > func init() { file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_init() } tasks.pb.go
498 > func file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_init() {
499 > if File_temporal_server_chasm_lib_activity_proto_v1_tasks_proto != nil {
500 return
501 }
502 > type x struct{} tasks.pb.go
503 > out := protoimpl.TypeBuilder{
504 > File: protoimpl.DescBuilder{
505 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
506 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_rawDesc), len(file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_rawDesc)),
507 > NumEnums: 2,
508 > NumMessages: 5,
509 > NumExtensions: 0,
510 > NumServices: 0,
511 > },
512 > GoTypes: file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_goTypes,
513 > DependencyIndexes: file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_depIdxs,
514 > EnumInfos: file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_enumTypes,
515 > MessageInfos: file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_msgTypes,
516 > }.Build()
517 > File_temporal_server_chasm_lib_activity_proto_v1_tasks_proto = out.File
518 > file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_goTypes = nil
519 > file_temporal_server_chasm_lib_activity_proto_v1_tasks_proto_depIdxs = nil
520 }
go.temporal.io/server/common/masker/masker.go 21 covered LOC · 6 ranges

Open complete file

16 // MaskYaml replace password values with mask and returns copy of the string.
17 // Does recursive replacement for entire yamlStr.
18 > func MaskYaml(yamlStr string, fieldNamesToMask []string) (string, error) { masker.go
19 > fns := make(map[string]struct{}, len(fieldNamesToMask))
20 > for _, fieldName := range fieldNamesToMask {
21 > fns[fieldName] = struct{}{}
22 > }
23
24 > var parsedYaml map[string]any masker.go
25 > err := yaml.Unmarshal([]byte(yamlStr), &parsedYaml)
26 > if err != nil {
27 return yamlStr, err
28 }
29
30 > maskMap(parsedYaml, fns) masker.go
31 >
32 > strBytes, err := yaml.Marshal(parsedYaml)
33 > if err != nil {
34 return yamlStr, err
35 }
36 > return string(strBytes), nil masker.go
37 }
38
71 }
72
73 > func maskMap(m map[string]any, fns map[string]struct{}) { masker.go
74 > for key, value := range m {
75 > if _, ok := fns[key]; ok {
76 > m[key] = passwordMask
77 > }
78
79 > if valueMap, ok := value.(map[string]any); ok { masker.go
80 > maskMap(valueMap, fns)
81 > }
82 }
83 }
go.temporal.io/server/common/persistence/history_branch_util.go 21 covered LOC · 7 ranges

Open complete file

41 )
42
43 > func NewHistoryBranchUtil(serializer serialization.Serializer) *HistoryBranchUtilImpl { history_branch_util.go
44 > return &HistoryBranchUtilImpl{
45 > serializer: serializer,
46 > }
47 > }
48
49 func (u *HistoryBranchUtilImpl) NewHistoryBranch(
57 _ time.Duration, // executionTimeout
58 _ time.Duration, // retentionDuration
59 > ) ([]byte, error) { history_branch_util.go
60 > var id string
61 > if branchID == nil {
62 > id = primitives.NewUUID().String() history_branch_util.go
63 > } else { history_branch_util.go
64 id = *branchID
65 }
66 > bi := &persistencespb.HistoryBranch{ history_branch_util.go
67 > TreeId: treeID,
68 > BranchId: id,
69 > Ancestors: ancestors,
70 > }
71 > data, err := u.serializer.HistoryBranchToBlob(bi)
72 > if err != nil {
73 return nil, err
74 }
75 > return data.Data, nil history_branch_util.go
76 }
77
78 func (u *HistoryBranchUtilImpl) ParseHistoryBranchInfo(
79 branchToken []byte,
80 > ) (*persistencespb.HistoryBranch, error) { history_branch_util.go
81 > return u.serializer.HistoryBranchFromBlob(branchToken)
82 > }
83
84 func (u *HistoryBranchUtilImpl) UpdateHistoryBranchInfo(
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/task_v1.go 21 covered LOC · 4 ranges

Open complete file

36 ctx context.Context,
37 rows []sqlplugin.TasksRow,
38 > ) (sql.Result, error) { task_v1.go
39 > return mdb.conn.NamedExecContext(ctx,
40 > createTaskQry,
41 > rows,
42 > )
43 > }
44
45 // SelectFromTasks reads one or more rows from tasks table
47 ctx context.Context,
48 filter sqlplugin.TasksFilter,
49 > ) ([]sqlplugin.TasksRow, error) { task_v1.go
50 > var err error
51 > var rows []sqlplugin.TasksRow
52 > switch {
53 > case filter.ExclusiveMaxTaskID != nil:
54 > err = mdb.conn.SelectContext(ctx,
55 > &rows, getTaskMinMaxQry,
56 > filter.RangeHash,
57 > filter.TaskQueueID,
58 > *filter.InclusiveMinTaskID,
59 > *filter.ExclusiveMaxTaskID,
60 > *filter.PageSize,
61 > )
62 default:
63 err = mdb.conn.SelectContext(ctx,
69 )
70 }
71 > if err != nil { task_v1.go
72 return nil, err
73 }
74 > return rows, nil task_v1.go
75 }
76
go.temporal.io/server/common/persistence/sql/store.go 21 covered LOC · 9 ranges

Open complete file

19
20 // RegisterPlugin will register a SQL plugin
21 > func RegisterPlugin(pluginName string, plugin sqlplugin.Plugin) { store.go
22 > if _, ok := supportedPlugins[pluginName]; ok {
23 panic("plugin " + pluginName + " already registered")
24 }
25 > supportedPlugins[pluginName] = plugin store.go
26 }
27
36 logger log.Logger,
37 mh metrics.Handler,
38 > ) (sqlplugin.DB, error) { store.go
39 > return createDB[sqlplugin.DB](dbKind, cfg, r, logger, mh)
40 > }
41
42 // NewSQLAdminDB returns a AdminDB.
47 logger log.Logger,
48 mh metrics.Handler,
49 > ) (sqlplugin.AdminDB, error) { store.go
50 > return createDB[sqlplugin.AdminDB](dbKind, cfg, r, logger, mh)
51 > }
52
53 func createDB[T any](
57 logger log.Logger,
58 mh metrics.Handler,
59 > ) (T, error) { store.go
60 > var res T
61 > plugin, err := getPlugin(cfg.PluginName)
62 > if err != nil {
63 return res, err
64 }
65 > db, err := plugin.CreateDB(dbKind, cfg, r, logger, mh) store.go
66 > if err != nil {
67 return res, err
68 }
69 //revive:disable-next-line:unchecked-type-assertion
70 > res = db.(T) store.go
71 > return res, err
72 }
73
74 > func getPlugin(pluginName string) (sqlplugin.Plugin, error) { store.go
75 > plugin, ok := supportedPlugins[pluginName]
76 > if !ok {
77 keys := expmaps.Keys(supportedPlugins)
78 slices.Sort(keys)
84 )
85 }
86 > return plugin, nil store.go
87 }
88
go.temporal.io/server/common/persistence/sql/version_checker.go 21 covered LOC · 7 ranges

Open complete file

15 r resolver.ServiceResolver,
16 logger log.Logger,
17 > ) error { version_checker.go
18 >
19 > if err := checkMainDatabase(cfg, r, logger); err != nil {
20 return err
21 }
22 > if cfg.VisibilityConfigExist() { version_checker.go
23 > return checkVisibilityDatabase(cfg, r, logger)
24 > }
25 return nil
26 }
30 r resolver.ServiceResolver,
31 logger log.Logger,
32 > ) error { version_checker.go
33 > ds, ok := cfg.DataStores[cfg.DefaultStore]
34 > if ok && ds.SQL != nil {
35 > return checkCompatibleVersion(ds.SQL, r, sqlplugin.DbKindMain, logger)
36 > }
37 return nil
38 }
42 r resolver.ServiceResolver,
43 logger log.Logger,
44 > ) error { version_checker.go
45 > ds, ok := cfg.DataStores[cfg.VisibilityStore]
46 > if ok && ds.SQL != nil {
47 > return checkCompatibleVersion(ds.SQL, r, sqlplugin.DbKindVisibility, logger)
48 > }
49 return nil
50 }
55 dbKind sqlplugin.DbKind,
56 logger log.Logger,
57 > ) error { version_checker.go
58 > db, err := NewSQLAdminDB(dbKind, cfg, r, logger, metrics.NoopMetricsHandler)
59 > if err != nil {
60 return err
61 }
62 > defer func() { _ = db.Close() }() version_checker.go
63
64 > return db.VerifyVersion() version_checker.go
65 }
go.temporal.io/server/common/tasks/group_by_scheduler.go 21 covered LOC · 7 ranges

Open complete file

34
35 // NewGroupByScheduler creates a new [GroupByScheduler] from given options.
36 > func NewGroupByScheduler[K comparable, T Task](options GroupBySchedulerOptions[K, T]) *GroupByScheduler[K, T] { group_by_scheduler.go
37 > return &GroupByScheduler[K, T]{
38 > options: options,
39 > schedulers: make(map[K]RunnableScheduler),
40 > }
41 > }
42
43 > func (*GroupByScheduler[K, T]) Start() { group_by_scheduler.go
44 > // noop
45 > }
46
47 // Stop signals running tasks to stop, aborts any pending tasks and waits up to a minute for all running tasks to
48 // complete.
49 > func (s *GroupByScheduler[K, T]) Stop() { group_by_scheduler.go
50 > if !s.stopped.CompareAndSwap(false, true) {
51 return
52 }
53 > s.mu.Lock() group_by_scheduler.go
54 > for _, lim := range s.schedulers {
55 lim.InitiateShutdown()
56 }
57 > s.mu.Unlock() group_by_scheduler.go
58 >
59 > if success := common.BlockWithTimeout(s.waitShutdown, time.Minute); !success {
60 s.options.Logger.Warn("GroupByScheduler timed out waiting for groups to complete shutdown")
61 > } else { group_by_scheduler.go
62 > s.options.Logger.Debug("GroupByScheduler shutdown complete")
63 > }
64 }
65
66 > func (s *GroupByScheduler[K, T]) waitShutdown() { group_by_scheduler.go
67 > for _, lim := range s.schedulers {
68 lim.WaitShutdown()
69 }
go.temporal.io/server/service/frontend/openapi_http_handler.go 21 covered LOC · 3 ranges

Open complete file

24 rateLimitInterceptor *interceptor.RateLimitInterceptor,
25 logger log.Logger,
26 > ) *OpenAPIHTTPHandler { openapi_http_handler.go
27 > return &OpenAPIHTTPHandler{
28 > logger: logger,
29 > rateLimitInterceptor: rateLimitInterceptor,
30 > }
31 > }
32
33 > func (h *OpenAPIHTTPHandler) RegisterRoutes(r *mux.Router) { openapi_http_handler.go
34 > serve := func(version int, apiName string, contentType string, spec []byte) func(http.ResponseWriter, *http.Request) {
35 > return func(w http.ResponseWriter, r *http.Request) {
36 if err := h.rateLimitInterceptor.Allow(apiName, r.Header); err != nil {
37 w.WriteHeader(http.StatusTooManyRequests)
54 }
55
56 > r.PathPrefix("/swagger.json").Methods("GET").HandlerFunc(serve( openapi_http_handler.go
57 > 2,
58 > configs.OpenAPIV2APIName,
59 > "application/vnd.oai.openapi+json;version=2.0",
60 > openapi.OpenAPIV2JSONSpec,
61 > ))
62 > r.PathPrefix("/openapi.yaml").Methods("GET").HandlerFunc(serve(
63 > 3,
64 > configs.OpenAPIV3APIName,
65 > "application/vnd.oai.openapi;version=3.0",
66 > openapi.OpenAPIV3YAMLSpec,
67 > ))
68 }
go.temporal.io/server/service/history/queues/metrics.go 21 covered LOC · 10 ranges

Open complete file

30 task tasks.Task,
31 chasmRegistry *chasm.Registry,
32 > ) string { metrics.go
33 > prefix := "TransferActive"
34 > switch t := task.(type) {
35 case *tasks.ActivityTask:
36 return metrics.TaskTypeTransferActiveTaskActivity
37 > case *tasks.WorkflowTask: metrics.go
38 > return metrics.TaskTypeTransferActiveTaskWorkflowTask
39 > case *tasks.CloseExecutionTask: metrics.go
40 > return metrics.TaskTypeTransferActiveTaskCloseExecution
41 case *tasks.CancelExecutionTask:
42 return metrics.TaskTypeTransferActiveTaskCancelExecution
156 func GetVisibilityTaskTypeTagValue(
157 task tasks.Task,
158 > ) string { metrics.go
159 > switch task.(type) {
160 > case *tasks.StartExecutionVisibilityTask: metrics.go
161 > return metrics.TaskTypeVisibilityTaskStartExecution
162 case *tasks.UpsertExecutionVisibilityTask:
163 return metrics.TaskTypeVisibilityTaskUpsertExecution
164 > case *tasks.CloseExecutionVisibilityTask: metrics.go
165 > return metrics.TaskTypeVisibilityTaskCloseExecution
166 case *tasks.DeleteExecutionVisibilityTask:
167 return metrics.TaskTypeVisibilityTaskDeleteExecution
223 isActive bool,
224 chasmRegistry *chasm.Registry,
225 > ) string { metrics.go
226 > switch task.GetCategory() {
227 > case tasks.CategoryTransfer: metrics.go
228 > if isActive {
229 > return GetActiveTransferTaskTypeTagValue(task, chasmRegistry) metrics.go
230 > }
231 return GetStandbyTransferTaskTypeTagValue(task, chasmRegistry)
232 case tasks.CategoryTimer:
235 }
236 return GetStandbyTimerTaskTypeTagValue(task, chasmRegistry)
237 > case tasks.CategoryVisibility: metrics.go
238 > return GetVisibilityTaskTypeTagValue(task)
239 case tasks.CategoryArchival:
240 return GetArchivalTaskTypeTagValue(task)
go.temporal.io/server/service/history/queues/priority_assigner.go 21 covered LOC · 8 ranges

Open complete file

23 )
24
25 > func NewPriorityAssigner(nsRegistry namespace.Registry, currentClusterName string) PriorityAssigner { priority_assigner.go
26 > return &priorityAssignerImpl{
27 > nsRegistry: nsRegistry,
28 > currentClusterName: currentClusterName,
29 > }
30 > }
31
32 > func (a *priorityAssignerImpl) Assign(executable Executable) tasks.Priority { priority_assigner.go
33 > ns, err := a.nsRegistry.GetNamespaceByID(namespace.ID(executable.GetNamespaceID()))
34 > if ns != nil && err == nil {
35 > // Use lowest priority level for standby task processing priority_assigner.go
36 > if ns.ActiveClusterName(namespace.RoutingKey{ID: executable.GetWorkflowID()}) != a.currentClusterName {
37 return tasks.PriorityPreemptable
38 }
39 }
40
41 > taskType := executable.GetType() priority_assigner.go
42 > switch taskType {
43 case enumsspb.TASK_TYPE_ACTIVITY_TIMEOUT,
44 enumsspb.TASK_TYPE_WORKFLOW_TASK_TIMEOUT,
57 }
58
59 > if _, ok := enumsspb.TaskType_name[int32(taskType)]; !ok { priority_assigner.go
60 // low priority for unknown task types
61 return tasks.PriorityPreemptable
62 }
63
64 > return tasks.PriorityHigh priority_assigner.go
65 }
66
67 > func NewNoopPriorityAssigner() PriorityAssigner { priority_assigner.go
68 > return NewStaticPriorityAssigner(tasks.PriorityHigh)
69 > }
70
71 > func NewStaticPriorityAssigner(priority tasks.Priority) PriorityAssigner { priority_assigner.go
72 > return staticPriorityAssigner{priority: priority}
73 > }
74
75 func (a staticPriorityAssigner) Assign(_ Executable) tasks.Priority {
go.temporal.io/server/service/history/tasks/close_task.go 21 covered LOC · 7 ranges

Open complete file

22 )
23
24 > func (a *CloseExecutionTask) GetKey() Key { close_task.go
25 > return NewImmediateKey(a.TaskID)
26 > }
27
28 func (a *CloseExecutionTask) GetVersion() int64 {
34 }
35
36 > func (a *CloseExecutionTask) GetTaskID() int64 { close_task.go
37 > return a.TaskID
38 > }
39
40 > func (a *CloseExecutionTask) SetTaskID(id int64) { close_task.go
41 > a.TaskID = id
42 > }
43
44 > func (a *CloseExecutionTask) GetVisibilityTime() time.Time { close_task.go
45 > return a.VisibilityTimestamp
46 > }
47
48 > func (a *CloseExecutionTask) SetVisibilityTime(timestamp time.Time) { close_task.go
49 > a.VisibilityTimestamp = timestamp
50 > }
51
52 > func (a *CloseExecutionTask) GetCategory() Category { close_task.go
53 > return CategoryTransfer
54 > }
55
56 > func (a *CloseExecutionTask) GetType() enumsspb.TaskType { close_task.go
57 > return enumsspb.TASK_TYPE_TRANSFER_CLOSE_EXECUTION
58 > }
59
60 func (a *CloseExecutionTask) String() string {
go.temporal.io/server/service/history/tasks/close_visibility_task.go 21 covered LOC · 7 ranges

Open complete file

19 )
20
21 > func (t *CloseExecutionVisibilityTask) GetKey() Key { close_visibility_task.go
22 > return NewImmediateKey(t.TaskID)
23 > }
24
25 func (t *CloseExecutionVisibilityTask) GetVersion() int64 {
31 }
32
33 > func (t *CloseExecutionVisibilityTask) GetTaskID() int64 { close_visibility_task.go
34 > return t.TaskID
35 > }
36
37 > func (t *CloseExecutionVisibilityTask) SetTaskID(id int64) { close_visibility_task.go
38 > t.TaskID = id
39 > }
40
41 > func (t *CloseExecutionVisibilityTask) GetVisibilityTime() time.Time { close_visibility_task.go
42 > return t.VisibilityTimestamp
43 > }
44
45 > func (t *CloseExecutionVisibilityTask) SetVisibilityTime(timestamp time.Time) { close_visibility_task.go
46 > t.VisibilityTimestamp = timestamp
47 > }
48
49 > func (t *CloseExecutionVisibilityTask) GetCategory() Category { close_visibility_task.go
50 > return CategoryVisibility
51 > }
52
53 > func (t *CloseExecutionVisibilityTask) GetType() enumsspb.TaskType { close_visibility_task.go
54 > return enumsspb.TASK_TYPE_VISIBILITY_CLOSE_EXECUTION
55 > }
go.temporal.io/server/service/history/tasks/start_visibility_task.go 21 covered LOC · 7 ranges

Open complete file

19 )
20
21 > func (t *StartExecutionVisibilityTask) GetKey() Key { start_visibility_task.go
22 > return NewImmediateKey(t.TaskID)
23 > }
24
25 func (t *StartExecutionVisibilityTask) GetVersion() int64 {
31 }
32
33 > func (t *StartExecutionVisibilityTask) GetTaskID() int64 { start_visibility_task.go
34 > return t.TaskID
35 > }
36
37 > func (t *StartExecutionVisibilityTask) SetTaskID(id int64) { start_visibility_task.go
38 > t.TaskID = id
39 > }
40
41 > func (t *StartExecutionVisibilityTask) GetVisibilityTime() time.Time { start_visibility_task.go
42 > return t.VisibilityTimestamp
43 > }
44
45 > func (t *StartExecutionVisibilityTask) SetVisibilityTime(timestamp time.Time) { start_visibility_task.go
46 > t.VisibilityTimestamp = timestamp
47 > }
48
49 > func (t *StartExecutionVisibilityTask) GetCategory() Category { start_visibility_task.go
50 > return CategoryVisibility
51 > }
52
53 > func (t *StartExecutionVisibilityTask) GetType() enumsspb.TaskType { start_visibility_task.go
54 > return enumsspb.TASK_TYPE_VISIBILITY_START_EXECUTION
55 > }
go.temporal.io/server/service/history/tasks/workflow_task.go 21 covered LOC · 7 ranges

Open complete file

23 )
24
25 > func (d *WorkflowTask) GetKey() Key { workflow_task.go
26 > return NewImmediateKey(d.TaskID)
27 > }
28
29 func (d *WorkflowTask) GetVersion() int64 {
35 }
36
37 > func (d *WorkflowTask) GetTaskID() int64 { workflow_task.go
38 > return d.TaskID
39 > }
40
41 > func (d *WorkflowTask) SetTaskID(id int64) { workflow_task.go
42 > d.TaskID = id
43 > }
44
45 > func (d *WorkflowTask) GetVisibilityTime() time.Time { workflow_task.go
46 > return d.VisibilityTimestamp
47 > }
48
49 > func (d *WorkflowTask) SetVisibilityTime(timestamp time.Time) { workflow_task.go
50 > d.VisibilityTimestamp = timestamp
51 > }
52
53 > func (d *WorkflowTask) GetCategory() Category { workflow_task.go
54 > return CategoryTransfer
55 > }
56
57 > func (d *WorkflowTask) GetType() enumsspb.TaskType { workflow_task.go
58 > return enumsspb.TASK_TYPE_TRANSFER_WORKFLOW_TASK
59 > }
60
61 func (d *WorkflowTask) String() string {
go.temporal.io/server/temporal/server_options.go 21 covered LOC · 9 ranges

Open complete file

66 )
67
68 > func newServerOptions(opts []ServerOption) *serverOptions { server_options.go
69 > so := &serverOptions{
70 > // Set defaults here.
71 > persistenceServiceResolver: resolver.NewNoopResolver(),
72 > }
73 > for _, opt := range opts {
74 > opt.apply(so)
75 > }
76
77 > return so server_options.go
78 }
79
80 > func (so *serverOptions) loadAndValidate() error { server_options.go
81 > for serviceName := range so.serviceNames {
82 > if !slices.Contains(Services, string(serviceName)) {
83 return fmt.Errorf("invalid service %q in service list %v", serviceName, so.serviceNames)
84 }
85 }
86
87 > if so.config == nil { server_options.go
88 err := so.loadConfig()
89 if err != nil {
92 }
93
94 > err := so.validateConfig() server_options.go
95 > if err != nil {
96 return fmt.Errorf("config validation error: %w", err)
97 }
98
99 > return nil server_options.go
100 }
101
126 }
127
128 > func (so *serverOptions) validateConfig() error { server_options.go
129 > if err := so.config.Validate(); err != nil {
130 return err
131 }
132
133 > for name := range so.serviceNames { server_options.go
134 > if _, ok := so.config.Services[string(name)]; !ok {
135 return fmt.Errorf("%q service is missing in config", name)
136 }
137 }
138 > return nil server_options.go
139 }
go.temporal.io/server/api/adminservice/v1/service.pb.go 20 covered LOC · 2 ranges

Open complete file

273 }
274
275 > func init() { file_temporal_server_api_adminservice_v1_service_proto_init() } service.pb.go
276 > func file_temporal_server_api_adminservice_v1_service_proto_init() {
277 > if File_temporal_server_api_adminservice_v1_service_proto != nil {
278 return
279 }
280 > file_temporal_server_api_adminservice_v1_request_response_proto_init() service.pb.go
281 > type x struct{}
282 > out := protoimpl.TypeBuilder{
283 > File: protoimpl.DescBuilder{
284 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
285 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_adminservice_v1_service_proto_rawDesc), len(file_temporal_server_api_adminservice_v1_service_proto_rawDesc)),
286 > NumEnums: 0,
287 > NumMessages: 0,
288 > NumExtensions: 0,
289 > NumServices: 1,
290 > },
291 > GoTypes: file_temporal_server_api_adminservice_v1_service_proto_goTypes,
292 > DependencyIndexes: file_temporal_server_api_adminservice_v1_service_proto_depIdxs,
293 > }.Build()
294 > File_temporal_server_api_adminservice_v1_service_proto = out.File
295 > file_temporal_server_api_adminservice_v1_service_proto_goTypes = nil
296 > file_temporal_server_api_adminservice_v1_service_proto_depIdxs = nil
297 }
go.temporal.io/server/api/archiver/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

431 }
432
433 > func init() { file_temporal_server_api_archiver_v1_message_proto_init() } message.pb.go
434 > func file_temporal_server_api_archiver_v1_message_proto_init() {
435 > if File_temporal_server_api_archiver_v1_message_proto != nil {
436 return
437 }
438 > type x struct{} message.pb.go
439 > out := protoimpl.TypeBuilder{
440 > File: protoimpl.DescBuilder{
441 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
442 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_archiver_v1_message_proto_rawDesc), len(file_temporal_server_api_archiver_v1_message_proto_rawDesc)),
443 > NumEnums: 0,
444 > NumMessages: 4,
445 > NumExtensions: 0,
446 > NumServices: 0,
447 > },
448 > GoTypes: file_temporal_server_api_archiver_v1_message_proto_goTypes,
449 > DependencyIndexes: file_temporal_server_api_archiver_v1_message_proto_depIdxs,
450 > MessageInfos: file_temporal_server_api_archiver_v1_message_proto_msgTypes,
451 > }.Build()
452 > File_temporal_server_api_archiver_v1_message_proto = out.File
453 > file_temporal_server_api_archiver_v1_message_proto_goTypes = nil
454 > file_temporal_server_api_archiver_v1_message_proto_depIdxs = nil
455 }
go.temporal.io/server/api/batch/v1/request_response.pb.go 20 covered LOC · 2 ranges

Open complete file

180 }
181
182 > func init() { file_temporal_server_api_batch_v1_request_response_proto_init() } request_response.pb.go
183 > func file_temporal_server_api_batch_v1_request_response_proto_init() {
184 > if File_temporal_server_api_batch_v1_request_response_proto != nil {
185 return
186 }
187 > type x struct{} request_response.pb.go
188 > out := protoimpl.TypeBuilder{
189 > File: protoimpl.DescBuilder{
190 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
191 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_batch_v1_request_response_proto_rawDesc), len(file_temporal_server_api_batch_v1_request_response_proto_rawDesc)),
192 > NumEnums: 0,
193 > NumMessages: 1,
194 > NumExtensions: 0,
195 > NumServices: 0,
196 > },
197 > GoTypes: file_temporal_server_api_batch_v1_request_response_proto_goTypes,
198 > DependencyIndexes: file_temporal_server_api_batch_v1_request_response_proto_depIdxs,
199 > MessageInfos: file_temporal_server_api_batch_v1_request_response_proto_msgTypes,
200 > }.Build()
201 > File_temporal_server_api_batch_v1_request_response_proto = out.File
202 > file_temporal_server_api_batch_v1_request_response_proto_goTypes = nil
203 > file_temporal_server_api_batch_v1_request_response_proto_depIdxs = nil
204 }
go.temporal.io/server/api/chasm/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

206 }
207
208 > func init() { file_temporal_server_api_chasm_v1_message_proto_init() } message.pb.go
209 > func file_temporal_server_api_chasm_v1_message_proto_init() {
210 > if File_temporal_server_api_chasm_v1_message_proto != nil {
211 return
212 }
213 > type x struct{} message.pb.go
214 > out := protoimpl.TypeBuilder{
215 > File: protoimpl.DescBuilder{
216 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
217 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_chasm_v1_message_proto_rawDesc), len(file_temporal_server_api_chasm_v1_message_proto_rawDesc)),
218 > NumEnums: 0,
219 > NumMessages: 1,
220 > NumExtensions: 0,
221 > NumServices: 0,
222 > },
223 > GoTypes: file_temporal_server_api_chasm_v1_message_proto_goTypes,
224 > DependencyIndexes: file_temporal_server_api_chasm_v1_message_proto_depIdxs,
225 > MessageInfos: file_temporal_server_api_chasm_v1_message_proto_msgTypes,
226 > }.Build()
227 > File_temporal_server_api_chasm_v1_message_proto = out.File
228 > file_temporal_server_api_chasm_v1_message_proto_goTypes = nil
229 > file_temporal_server_api_chasm_v1_message_proto_depIdxs = nil
230 }
go.temporal.io/server/api/checksum/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

334 }
335
336 > func init() { file_temporal_server_api_checksum_v1_message_proto_init() } message.pb.go
337 > func file_temporal_server_api_checksum_v1_message_proto_init() {
338 > if File_temporal_server_api_checksum_v1_message_proto != nil {
339 return
340 }
341 > type x struct{} message.pb.go
342 > out := protoimpl.TypeBuilder{
343 > File: protoimpl.DescBuilder{
344 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
345 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_checksum_v1_message_proto_rawDesc), len(file_temporal_server_api_checksum_v1_message_proto_rawDesc)),
346 > NumEnums: 0,
347 > NumMessages: 1,
348 > NumExtensions: 0,
349 > NumServices: 0,
350 > },
351 > GoTypes: file_temporal_server_api_checksum_v1_message_proto_goTypes,
352 > DependencyIndexes: file_temporal_server_api_checksum_v1_message_proto_depIdxs,
353 > MessageInfos: file_temporal_server_api_checksum_v1_message_proto_msgTypes,
354 > }.Build()
355 > File_temporal_server_api_checksum_v1_message_proto = out.File
356 > file_temporal_server_api_checksum_v1_message_proto_goTypes = nil
357 > file_temporal_server_api_checksum_v1_message_proto_depIdxs = nil
358 }
go.temporal.io/server/api/enums/v1/replication.pb.go 20 covered LOC · 2 ranges

Open complete file

314 }
315
316 > func init() { file_temporal_server_api_enums_v1_replication_proto_init() } replication.pb.go
317 > func file_temporal_server_api_enums_v1_replication_proto_init() {
318 > if File_temporal_server_api_enums_v1_replication_proto != nil {
319 return
320 }
321 > type x struct{} replication.pb.go
322 > out := protoimpl.TypeBuilder{
323 > File: protoimpl.DescBuilder{
324 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
325 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_enums_v1_replication_proto_rawDesc), len(file_temporal_server_api_enums_v1_replication_proto_rawDesc)),
326 > NumEnums: 3,
327 > NumMessages: 0,
328 > NumExtensions: 0,
329 > NumServices: 0,
330 > },
331 > GoTypes: file_temporal_server_api_enums_v1_replication_proto_goTypes,
332 > DependencyIndexes: file_temporal_server_api_enums_v1_replication_proto_depIdxs,
333 > EnumInfos: file_temporal_server_api_enums_v1_replication_proto_enumTypes,
334 > }.Build()
335 > File_temporal_server_api_enums_v1_replication_proto = out.File
336 > file_temporal_server_api_enums_v1_replication_proto_goTypes = nil
337 > file_temporal_server_api_enums_v1_replication_proto_depIdxs = nil
338 }
go.temporal.io/server/api/errordetails/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

625 }
626
627 > func init() { file_temporal_server_api_errordetails_v1_message_proto_init() } message.pb.go
628 > func file_temporal_server_api_errordetails_v1_message_proto_init() {
629 > if File_temporal_server_api_errordetails_v1_message_proto != nil {
630 return
631 }
632 > type x struct{} message.pb.go
633 > out := protoimpl.TypeBuilder{
634 > File: protoimpl.DescBuilder{
635 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
636 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_errordetails_v1_message_proto_rawDesc), len(file_temporal_server_api_errordetails_v1_message_proto_rawDesc)),
637 > NumEnums: 0,
638 > NumMessages: 10,
639 > NumExtensions: 0,
640 > NumServices: 0,
641 > },
642 > GoTypes: file_temporal_server_api_errordetails_v1_message_proto_goTypes,
643 > DependencyIndexes: file_temporal_server_api_errordetails_v1_message_proto_depIdxs,
644 > MessageInfos: file_temporal_server_api_errordetails_v1_message_proto_msgTypes,
645 > }.Build()
646 > File_temporal_server_api_errordetails_v1_message_proto = out.File
647 > file_temporal_server_api_errordetails_v1_message_proto_goTypes = nil
648 > file_temporal_server_api_errordetails_v1_message_proto_depIdxs = nil
649 }
go.temporal.io/server/api/historyservice/v1/service.pb.go 20 covered LOC · 2 ranges

Open complete file

428 }
429
430 > func init() { file_temporal_server_api_historyservice_v1_service_proto_init() } service.pb.go
431 > func file_temporal_server_api_historyservice_v1_service_proto_init() {
432 > if File_temporal_server_api_historyservice_v1_service_proto != nil {
433 return
434 }
435 > file_temporal_server_api_historyservice_v1_request_response_proto_init() service.pb.go
436 > type x struct{}
437 > out := protoimpl.TypeBuilder{
438 > File: protoimpl.DescBuilder{
439 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
440 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_historyservice_v1_service_proto_rawDesc), len(file_temporal_server_api_historyservice_v1_service_proto_rawDesc)),
441 > NumEnums: 0,
442 > NumMessages: 0,
443 > NumExtensions: 0,
444 > NumServices: 1,
445 > },
446 > GoTypes: file_temporal_server_api_historyservice_v1_service_proto_goTypes,
447 > DependencyIndexes: file_temporal_server_api_historyservice_v1_service_proto_depIdxs,
448 > }.Build()
449 > File_temporal_server_api_historyservice_v1_service_proto = out.File
450 > file_temporal_server_api_historyservice_v1_service_proto_goTypes = nil
451 > file_temporal_server_api_historyservice_v1_service_proto_depIdxs = nil
452 }
go.temporal.io/server/api/matchingservice/v1/service.pb.go 20 covered LOC · 2 ranges

Open complete file

250 }
251
252 > func init() { file_temporal_server_api_matchingservice_v1_service_proto_init() } service.pb.go
253 > func file_temporal_server_api_matchingservice_v1_service_proto_init() {
254 > if File_temporal_server_api_matchingservice_v1_service_proto != nil {
255 return
256 }
257 > file_temporal_server_api_matchingservice_v1_request_response_proto_init() service.pb.go
258 > type x struct{}
259 > out := protoimpl.TypeBuilder{
260 > File: protoimpl.DescBuilder{
261 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
262 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_matchingservice_v1_service_proto_rawDesc), len(file_temporal_server_api_matchingservice_v1_service_proto_rawDesc)),
263 > NumEnums: 0,
264 > NumMessages: 0,
265 > NumExtensions: 0,
266 > NumServices: 1,
267 > },
268 > GoTypes: file_temporal_server_api_matchingservice_v1_service_proto_goTypes,
269 > DependencyIndexes: file_temporal_server_api_matchingservice_v1_service_proto_depIdxs,
270 > }.Build()
271 > File_temporal_server_api_matchingservice_v1_service_proto = out.File
272 > file_temporal_server_api_matchingservice_v1_service_proto_goTypes = nil
273 > file_temporal_server_api_matchingservice_v1_service_proto_depIdxs = nil
274 }
go.temporal.io/server/api/persistence/v1/chasm_visibility.pb.go 20 covered LOC · 2 ranges

Open complete file

146 }
147
148 > func init() { file_temporal_server_api_persistence_v1_chasm_visibility_proto_init() } chasm_visibility.pb.go
149 > func file_temporal_server_api_persistence_v1_chasm_visibility_proto_init() {
150 > if File_temporal_server_api_persistence_v1_chasm_visibility_proto != nil {
151 return
152 }
153 > type x struct{} chasm_visibility.pb.go
154 > out := protoimpl.TypeBuilder{
155 > File: protoimpl.DescBuilder{
156 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
157 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_persistence_v1_chasm_visibility_proto_rawDesc), len(file_temporal_server_api_persistence_v1_chasm_visibility_proto_rawDesc)),
158 > NumEnums: 0,
159 > NumMessages: 2,
160 > NumExtensions: 0,
161 > NumServices: 0,
162 > },
163 > GoTypes: file_temporal_server_api_persistence_v1_chasm_visibility_proto_goTypes,
164 > DependencyIndexes: file_temporal_server_api_persistence_v1_chasm_visibility_proto_depIdxs,
165 > MessageInfos: file_temporal_server_api_persistence_v1_chasm_visibility_proto_msgTypes,
166 > }.Build()
167 > File_temporal_server_api_persistence_v1_chasm_visibility_proto = out.File
168 > file_temporal_server_api_persistence_v1_chasm_visibility_proto_goTypes = nil
169 > file_temporal_server_api_persistence_v1_chasm_visibility_proto_depIdxs = nil
170 }
go.temporal.io/server/api/visibilityservice/v1/request_response.pb.go 20 covered LOC · 2 ranges

Open complete file

402 }
403
404 > func init() { file_temporal_server_api_visibilityservice_v1_request_response_proto_init() } request_response.pb.go
405 > func file_temporal_server_api_visibilityservice_v1_request_response_proto_init() {
406 > if File_temporal_server_api_visibilityservice_v1_request_response_proto != nil {
407 return
408 }
409 > type x struct{} request_response.pb.go
410 > out := protoimpl.TypeBuilder{
411 > File: protoimpl.DescBuilder{
412 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
413 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_api_visibilityservice_v1_request_response_proto_rawDesc), len(file_temporal_server_api_visibilityservice_v1_request_response_proto_rawDesc)),
414 > NumEnums: 0,
415 > NumMessages: 5,
416 > NumExtensions: 0,
417 > NumServices: 0,
418 > },
419 > GoTypes: file_temporal_server_api_visibilityservice_v1_request_response_proto_goTypes,
420 > DependencyIndexes: file_temporal_server_api_visibilityservice_v1_request_response_proto_depIdxs,
421 > MessageInfos: file_temporal_server_api_visibilityservice_v1_request_response_proto_msgTypes,
422 > }.Build()
423 > File_temporal_server_api_visibilityservice_v1_request_response_proto = out.File
424 > file_temporal_server_api_visibilityservice_v1_request_response_proto_goTypes = nil
425 > file_temporal_server_api_visibilityservice_v1_request_response_proto_depIdxs = nil
426 }
go.temporal.io/server/chasm/lib/activity/gen/activitypb/v1/service.pb.go 20 covered LOC · 2 ranges

Open complete file

91 }
92
93 > func init() { file_temporal_server_chasm_lib_activity_proto_v1_service_proto_init() } service.pb.go
94 > func file_temporal_server_chasm_lib_activity_proto_v1_service_proto_init() {
95 > if File_temporal_server_chasm_lib_activity_proto_v1_service_proto != nil {
96 return
97 }
98 > file_temporal_server_chasm_lib_activity_proto_v1_request_response_proto_init() service.pb.go
99 > type x struct{}
100 > out := protoimpl.TypeBuilder{
101 > File: protoimpl.DescBuilder{
102 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
103 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_activity_proto_v1_service_proto_rawDesc), len(file_temporal_server_chasm_lib_activity_proto_v1_service_proto_rawDesc)),
104 > NumEnums: 0,
105 > NumMessages: 0,
106 > NumExtensions: 0,
107 > NumServices: 1,
108 > },
109 > GoTypes: file_temporal_server_chasm_lib_activity_proto_v1_service_proto_goTypes,
110 > DependencyIndexes: file_temporal_server_chasm_lib_activity_proto_v1_service_proto_depIdxs,
111 > }.Build()
112 > File_temporal_server_chasm_lib_activity_proto_v1_service_proto = out.File
113 > file_temporal_server_chasm_lib_activity_proto_v1_service_proto_goTypes = nil
114 > file_temporal_server_chasm_lib_activity_proto_v1_service_proto_depIdxs = nil
115 }
go.temporal.io/server/chasm/lib/activity/gen/activitypb/v1/service_client.pb.go 20 covered LOC · 4 ranges

Open complete file

37 logger log.Logger,
38 metricsHandler metrics.Handler,
39 > ) (ActivityServiceClient, error) { service_client.pb.go
40 > resolver, err := monitor.GetResolver(primitives.HistoryService)
41 > if err != nil {
42 return nil, err
43 }
44 > connections := history.NewConnectionPool(resolver, rpcFactory, NewActivityServiceClient, logger, dynamicconfig.HistoryConnectionCloseDelay.Get(dc)) service_client.pb.go
45 > var redirector history.Redirector[ActivityServiceClient]
46 > if dynamicconfig.HistoryClientOwnershipCachingEnabled.Get(dc)() {
47 redirector = history.NewCachingRedirector(
48 connections,
51 dynamicconfig.HistoryClientOwnershipCachingStaleTTL.Get(dc),
52 )
53 > } else { service_client.pb.go
54 > redirector = history.NewBasicRedirector(connections, resolver)
55 > }
56 > client := &ActivityServiceLayeredClient{
57 > metricsHandler: metricsHandler,
58 > redirector: redirector,
59 > numShards: config.NumHistoryShards,
60 > retryPolicy: common.CreateHistoryClientRetryPolicy(dynamicconfig.RetryUnboundedOnSystemResourceExhausted.Get(dc)),
61 > }
62 > lc.Append(fx.StopHook(client.Stop))
63 > return client, nil
64 }
65 > func (c *ActivityServiceLayeredClient) Stop() { service_client.pb.go
66 > c.redirector.Close()
67 > }
68 func (c *ActivityServiceLayeredClient) callStartActivityExecutionNoRetry(
69 ctx context.Context,
go.temporal.io/server/chasm/lib/callback/gen/callbackpb/v1/tasks.pb.go 20 covered LOC · 2 ranges

Open complete file

148 }
149
150 > func init() { file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_init() } tasks.pb.go
151 > func file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_init() {
152 > if File_temporal_server_chasm_lib_callback_proto_v1_tasks_proto != nil {
153 return
154 }
155 > type x struct{} tasks.pb.go
156 > out := protoimpl.TypeBuilder{
157 > File: protoimpl.DescBuilder{
158 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
159 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_rawDesc), len(file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_rawDesc)),
160 > NumEnums: 0,
161 > NumMessages: 2,
162 > NumExtensions: 0,
163 > NumServices: 0,
164 > },
165 > GoTypes: file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_goTypes,
166 > DependencyIndexes: file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_depIdxs,
167 > MessageInfos: file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_msgTypes,
168 > }.Build()
169 > File_temporal_server_chasm_lib_callback_proto_v1_tasks_proto = out.File
170 > file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_goTypes = nil
171 > file_temporal_server_chasm_lib_callback_proto_v1_tasks_proto_depIdxs = nil
172 }
go.temporal.io/server/chasm/lib/nexusoperation/gen/nexusoperationpb/v1/service.pb.go 20 covered LOC · 2 ranges

Open complete file

71 }
72
73 > func init() { file_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto_init() } service.pb.go
74 > func file_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto_init() {
75 > if File_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto != nil {
76 return
77 }
78 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_request_response_proto_init() service.pb.go
79 > type x struct{}
80 > out := protoimpl.TypeBuilder{
81 > File: protoimpl.DescBuilder{
82 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
83 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto_rawDesc), len(file_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto_rawDesc)),
84 > NumEnums: 0,
85 > NumMessages: 0,
86 > NumExtensions: 0,
87 > NumServices: 1,
88 > },
89 > GoTypes: file_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto_goTypes,
90 > DependencyIndexes: file_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto_depIdxs,
91 > }.Build()
92 > File_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto = out.File
93 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto_goTypes = nil
94 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_service_proto_depIdxs = nil
95 }
go.temporal.io/server/chasm/lib/nexusoperation/gen/nexusoperationpb/v1/service_client.pb.go 20 covered LOC · 4 ranges

Open complete file

37 logger log.Logger,
38 metricsHandler metrics.Handler,
39 > ) (NexusOperationServiceClient, error) { service_client.pb.go
40 > resolver, err := monitor.GetResolver(primitives.HistoryService)
41 > if err != nil {
42 return nil, err
43 }
44 > connections := history.NewConnectionPool(resolver, rpcFactory, NewNexusOperationServiceClient, logger, dynamicconfig.HistoryConnectionCloseDelay.Get(dc)) service_client.pb.go
45 > var redirector history.Redirector[NexusOperationServiceClient]
46 > if dynamicconfig.HistoryClientOwnershipCachingEnabled.Get(dc)() {
47 redirector = history.NewCachingRedirector(
48 connections,
51 dynamicconfig.HistoryClientOwnershipCachingStaleTTL.Get(dc),
52 )
53 > } else { service_client.pb.go
54 > redirector = history.NewBasicRedirector(connections, resolver)
55 > }
56 > client := &NexusOperationServiceLayeredClient{
57 > metricsHandler: metricsHandler,
58 > redirector: redirector,
59 > numShards: config.NumHistoryShards,
60 > retryPolicy: common.CreateHistoryClientRetryPolicy(dynamicconfig.RetryUnboundedOnSystemResourceExhausted.Get(dc)),
61 > }
62 > lc.Append(fx.StopHook(client.Stop))
63 > return client, nil
64 }
65 > func (c *NexusOperationServiceLayeredClient) Stop() { service_client.pb.go
66 > c.redirector.Close()
67 > }
68 func (c *NexusOperationServiceLayeredClient) callStartNexusOperationNoRetry(
69 ctx context.Context,
go.temporal.io/server/chasm/lib/nexusoperation/gen/nexusoperationpb/v1/tasks.pb.go 20 covered LOC · 2 ranges

Open complete file

354 }
355
356 > func init() { file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_init() } tasks.pb.go
357 > func file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_init() {
358 > if File_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto != nil {
359 return
360 }
361 > type x struct{} tasks.pb.go
362 > out := protoimpl.TypeBuilder{
363 > File: protoimpl.DescBuilder{
364 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
365 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_rawDesc), len(file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_rawDesc)),
366 > NumEnums: 0,
367 > NumMessages: 7,
368 > NumExtensions: 0,
369 > NumServices: 0,
370 > },
371 > GoTypes: file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_goTypes,
372 > DependencyIndexes: file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_depIdxs,
373 > MessageInfos: file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_msgTypes,
374 > }.Build()
375 > File_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto = out.File
376 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_goTypes = nil
377 > file_temporal_server_chasm_lib_nexusoperation_proto_v1_tasks_proto_depIdxs = nil
378 }
go.temporal.io/server/chasm/lib/scheduler/gen/schedulerpb/v1/service.pb.go 20 covered LOC · 2 ranges

Open complete file

86 }
87
88 > func init() { file_temporal_server_chasm_lib_scheduler_proto_v1_service_proto_init() } service.pb.go
89 > func file_temporal_server_chasm_lib_scheduler_proto_v1_service_proto_init() {
90 > if File_temporal_server_chasm_lib_scheduler_proto_v1_service_proto != nil {
91 return
92 }
93 > file_temporal_server_chasm_lib_scheduler_proto_v1_request_response_proto_init() service.pb.go
94 > type x struct{}
95 > out := protoimpl.TypeBuilder{
96 > File: protoimpl.DescBuilder{
97 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
98 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_scheduler_proto_v1_service_proto_rawDesc), len(file_temporal_server_chasm_lib_scheduler_proto_v1_service_proto_rawDesc)),
99 > NumEnums: 0,
100 > NumMessages: 0,
101 > NumExtensions: 0,
102 > NumServices: 1,
103 > },
104 > GoTypes: file_temporal_server_chasm_lib_scheduler_proto_v1_service_proto_goTypes,
105 > DependencyIndexes: file_temporal_server_chasm_lib_scheduler_proto_v1_service_proto_depIdxs,
106 > }.Build()
107 > File_temporal_server_chasm_lib_scheduler_proto_v1_service_proto = out.File
108 > file_temporal_server_chasm_lib_scheduler_proto_v1_service_proto_goTypes = nil
109 > file_temporal_server_chasm_lib_scheduler_proto_v1_service_proto_depIdxs = nil
110 }
go.temporal.io/server/chasm/lib/scheduler/gen/schedulerpb/v1/service_client.pb.go 20 covered LOC · 4 ranges

Open complete file

37 logger log.Logger,
38 metricsHandler metrics.Handler,
39 > ) (SchedulerServiceClient, error) { service_client.pb.go
40 > resolver, err := monitor.GetResolver(primitives.HistoryService)
41 > if err != nil {
42 return nil, err
43 }
44 > connections := history.NewConnectionPool(resolver, rpcFactory, NewSchedulerServiceClient, logger, dynamicconfig.HistoryConnectionCloseDelay.Get(dc)) service_client.pb.go
45 > var redirector history.Redirector[SchedulerServiceClient]
46 > if dynamicconfig.HistoryClientOwnershipCachingEnabled.Get(dc)() {
47 redirector = history.NewCachingRedirector(
48 connections,
51 dynamicconfig.HistoryClientOwnershipCachingStaleTTL.Get(dc),
52 )
53 > } else { service_client.pb.go
54 > redirector = history.NewBasicRedirector(connections, resolver)
55 > }
56 > client := &SchedulerServiceLayeredClient{
57 > metricsHandler: metricsHandler,
58 > redirector: redirector,
59 > numShards: config.NumHistoryShards,
60 > retryPolicy: common.CreateHistoryClientRetryPolicy(dynamicconfig.RetryUnboundedOnSystemResourceExhausted.Get(dc)),
61 > }
62 > lc.Append(fx.StopHook(client.Stop))
63 > return client, nil
64 }
65 > func (c *SchedulerServiceLayeredClient) Stop() { service_client.pb.go
66 > c.redirector.Close()
67 > }
68 func (c *SchedulerServiceLayeredClient) callCreateScheduleNoRetry(
69 ctx context.Context,
go.temporal.io/server/chasm/lib/scheduler/gen/schedulerpb/v1/tasks.pb.go 20 covered LOC · 2 ranges

Open complete file

343 }
344
345 > func init() { file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_init() } tasks.pb.go
346 > func file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_init() {
347 > if File_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto != nil {
348 return
349 }
350 > type x struct{} tasks.pb.go
351 > out := protoimpl.TypeBuilder{
352 > File: protoimpl.DescBuilder{
353 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
354 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_rawDesc), len(file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_rawDesc)),
355 > NumEnums: 0,
356 > NumMessages: 7,
357 > NumExtensions: 0,
358 > NumServices: 0,
359 > },
360 > GoTypes: file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_goTypes,
361 > DependencyIndexes: file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_depIdxs,
362 > MessageInfos: file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_msgTypes,
363 > }.Build()
364 > File_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto = out.File
365 > file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_goTypes = nil
366 > file_temporal_server_chasm_lib_scheduler_proto_v1_tasks_proto_depIdxs = nil
367 }
go.temporal.io/server/chasm/lib/tests/gen/testspb/v1/message.pb.go 20 covered LOC · 2 ranges

Open complete file

242 }
243
244 > func init() { file_temporal_server_chasm_lib_tests_proto_v1_message_proto_init() } message.pb.go
245 > func file_temporal_server_chasm_lib_tests_proto_v1_message_proto_init() {
246 > if File_temporal_server_chasm_lib_tests_proto_v1_message_proto != nil {
247 return
248 }
249 > type x struct{} message.pb.go
250 > out := protoimpl.TypeBuilder{
251 > File: protoimpl.DescBuilder{
252 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
253 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_tests_proto_v1_message_proto_rawDesc), len(file_temporal_server_chasm_lib_tests_proto_v1_message_proto_rawDesc)),
254 > NumEnums: 0,
255 > NumMessages: 4,
256 > NumExtensions: 0,
257 > NumServices: 0,
258 > },
259 > GoTypes: file_temporal_server_chasm_lib_tests_proto_v1_message_proto_goTypes,
260 > DependencyIndexes: file_temporal_server_chasm_lib_tests_proto_v1_message_proto_depIdxs,
261 > MessageInfos: file_temporal_server_chasm_lib_tests_proto_v1_message_proto_msgTypes,
262 > }.Build()
263 > File_temporal_server_chasm_lib_tests_proto_v1_message_proto = out.File
264 > file_temporal_server_chasm_lib_tests_proto_v1_message_proto_goTypes = nil
265 > file_temporal_server_chasm_lib_tests_proto_v1_message_proto_depIdxs = nil
266 }
go.temporal.io/server/chasm/lib/tests/gen/testspb/v1/service.pb.go 20 covered LOC · 2 ranges

Open complete file

46 }
47
48 > func init() { file_temporal_server_chasm_lib_tests_proto_v1_service_proto_init() } service.pb.go
49 > func file_temporal_server_chasm_lib_tests_proto_v1_service_proto_init() {
50 > if File_temporal_server_chasm_lib_tests_proto_v1_service_proto != nil {
51 return
52 }
53 > file_temporal_server_chasm_lib_tests_proto_v1_request_response_proto_init() service.pb.go
54 > type x struct{}
55 > out := protoimpl.TypeBuilder{
56 > File: protoimpl.DescBuilder{
57 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
58 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_tests_proto_v1_service_proto_rawDesc), len(file_temporal_server_chasm_lib_tests_proto_v1_service_proto_rawDesc)),
59 > NumEnums: 0,
60 > NumMessages: 0,
61 > NumExtensions: 0,
62 > NumServices: 1,
63 > },
64 > GoTypes: file_temporal_server_chasm_lib_tests_proto_v1_service_proto_goTypes,
65 > DependencyIndexes: file_temporal_server_chasm_lib_tests_proto_v1_service_proto_depIdxs,
66 > }.Build()
67 > File_temporal_server_chasm_lib_tests_proto_v1_service_proto = out.File
68 > file_temporal_server_chasm_lib_tests_proto_v1_service_proto_goTypes = nil
69 > file_temporal_server_chasm_lib_tests_proto_v1_service_proto_depIdxs = nil
70 }
go.temporal.io/server/chasm/lib/workflow/gen/workflowpb/v1/state.pb.go 20 covered LOC · 2 ranges

Open complete file

211 }
212
213 > func init() { file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_init() } state.pb.go
214 > func file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_init() {
215 > if File_temporal_server_chasm_lib_workflow_proto_v1_state_proto != nil {
216 return
217 }
218 > type x struct{} state.pb.go
219 > out := protoimpl.TypeBuilder{
220 > File: protoimpl.DescBuilder{
221 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
222 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_rawDesc), len(file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_rawDesc)),
223 > NumEnums: 0,
224 > NumMessages: 3,
225 > NumExtensions: 0,
226 > NumServices: 0,
227 > },
228 > GoTypes: file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_goTypes,
229 > DependencyIndexes: file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_depIdxs,
230 > MessageInfos: file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_msgTypes,
231 > }.Build()
232 > File_temporal_server_chasm_lib_workflow_proto_v1_state_proto = out.File
233 > file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_goTypes = nil
234 > file_temporal_server_chasm_lib_workflow_proto_v1_state_proto_depIdxs = nil
235 }
go.temporal.io/server/chasm/lib/workflow/gen/workflowpb/v1/update_state.pb.go 20 covered LOC · 2 ranges

Open complete file

113 }
114
115 > func init() { file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_init() } update_state.pb.go
116 > func file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_init() {
117 > if File_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto != nil {
118 return
119 }
120 > type x struct{} update_state.pb.go
121 > out := protoimpl.TypeBuilder{
122 > File: protoimpl.DescBuilder{
123 > GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
124 > RawDescriptor: unsafe.Slice(unsafe.StringData(file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_rawDesc), len(file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_rawDesc)),
125 > NumEnums: 0,
126 > NumMessages: 1,
127 > NumExtensions: 0,
128 > NumServices: 0,
129 > },
130 > GoTypes: file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_goTypes,
131 > DependencyIndexes: file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_depIdxs,
132 > MessageInfos: file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_msgTypes,
133 > }.Build()
134 > File_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto = out.File
135 > file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_goTypes = nil
136 > file_temporal_server_chasm_lib_workflow_proto_v1_update_state_proto_depIdxs = nil
137 }
go.temporal.io/server/chasm/lib/workflow/nexus_service.go 20 covered LOC · 3 ranges

Open complete file

60 func mustNewWorkflowServiceNexusHandler(
61 handler *workflowServiceNexusHandler,
62 > ) *nexus.Service { nexus_service.go
63 > svc := nexus.NewService(workflowservicenexus.TemporalAPIWorkflowserviceV1WorkflowService.ServiceName)
64 > svc.MustRegister(nexus.NewSyncOperation(
65 > workflowservicenexus.TemporalAPIWorkflowserviceV1WorkflowService.SignalWithStartWorkflowExecution.Name(),
66 > handler.signalWithStartWorkflowExecution,
67 > ))
68 > return svc
69 > }
70
71 > func (h *workflowServiceNexusHandler) setHistoryHandler(handler historyservice.HistoryServiceServer) { nexus_service.go
72 > h.historyHandler = handler
73 > }
74
75 type SignalWithStartOperationProcessor struct {
127 saMapperProvider searchattribute.MapperProvider,
128 saValidator *searchattribute.Validator,
129 > ) *chasm.NexusServiceProcessor { nexus_service.go
130 > sp := chasm.NewNexusServiceProcessor(workflowservicenexus.TemporalAPIWorkflowserviceV1WorkflowService.ServiceName)
131 > op := SignalWithStartOperationProcessor{validator: NewValidator(config, saMapperProvider, saValidator)}
132 > sp.MustRegisterOperation(
133 > workflowservicenexus.TemporalAPIWorkflowserviceV1WorkflowService.SignalWithStartWorkflowExecution.Name(),
134 > chasm.NewRegisterableNexusOperationProcessor(op),
135 > )
136 > return sp
137 > }
go.temporal.io/server/common/channel/shutdown_once.go 20 covered LOC · 4 ranges

Open complete file

26 )
27
28 > func NewShutdownOnce() *ShutdownOnceImpl { shutdown_once.go
29 > return &ShutdownOnceImpl{
30 > status: shutdownOnceStatusOpen,
31 > channel: make(chan struct{}),
32 > }
33 > }
34
35 > func (c *ShutdownOnceImpl) Shutdown() { shutdown_once.go
36 > if atomic.CompareAndSwapInt32(
37 > &c.status,
38 > shutdownOnceStatusOpen,
39 > shutdownOnceStatusClosed,
40 > ) {
41 > close(c.channel)
42 > }
43 }
44
45 > func (c *ShutdownOnceImpl) IsShutdown() bool { shutdown_once.go
46 > return atomic.LoadInt32(&c.status) == shutdownOnceStatusClosed
47 > }
48
49 > func (c *ShutdownOnceImpl) Channel() <-chan struct{} { shutdown_once.go
50 > return c.channel
51 > }
go.temporal.io/server/common/persistence/sql/task_util.go 20 covered LOC · 4 ranges

Open complete file

46 taskType enumspb.TaskQueueType,
47 subqueue int,
48 > ) ([]byte, uint32) { task_util.go
49 > id := taskQueueId(namespaceID, taskQueueName, taskType, subqueue)
50 > return id, farm.Fingerprint32(id)
51 > }
52
53 func taskQueueId(
56 taskType enumspb.TaskQueueType,
57 subqueue int,
58 > ) []byte { task_util.go
59 > idBytes := make([]byte, 0, 16+len(taskQueueName)+1+binary.MaxVarintLen16)
60 > idBytes = append(idBytes, namespaceID...)
61 > idBytes = append(idBytes, []byte(taskQueueName)...)
62 >
63 > // To ensure that different names+types+subqueue ids never collide, we mark types
64 > // containing subqueues with an extra high bit, and then append the subqueue id. There are
65 > // only a few task queue types (currently 3), so the high bits are free. (If we have more
66 > // fields to append, we can use the next lower bit to mark the presence of that one, etc..)
67 > const hasSubqueue = 0x80
68 >
69 > if subqueue > 0 {
70 idBytes = append(idBytes, uint8(taskType)|hasSubqueue)
71 idBytes = binary.AppendUvarint(idBytes, uint64(subqueue))
72 > } else { task_util.go
73 > idBytes = append(idBytes, uint8(taskType))
74 > }
75
76 > return idBytes task_util.go
77 }
go.temporal.io/server/common/util/wildcard.go 20 covered LOC · 7 ranges

Open complete file

18 // WildCardStringToRegexps converts a given slices of string patterns to a slice of regular expressions matching
19 // wildcards (*) with any substring.
20 > func WildCardStringsToRegexp(patterns []string) (*regexp.Regexp, error) { wildcard.go
21 > var result strings.Builder
22 > result.WriteRune('^')
23 > for i, pattern := range patterns {
24 > result.WriteRune('(')
25 > first := true
26 > for literal := range strings.SplitSeq(pattern, "*") {
27 > if !first {
28 // Replace * with .*
29 result.WriteString(".*")
30 }
31 > result.WriteString(regexp.QuoteMeta(literal)) wildcard.go
32 > first = false
33 }
34 > result.WriteRune(')') wildcard.go
35 > if i < len(patterns)-1 {
36 > result.WriteRune('|') wildcard.go
37 > }
38 }
39 > result.WriteRune('$') wildcard.go
40 > return regexp.Compile(result.String())
41 }
42
43 // MustWildCardStringsToRegexp is like WildCardStringsToRegexp but panics on error.
44 > func MustWildCardStringsToRegexp(patterns []string) *regexp.Regexp { wildcard.go
45 > re, err := WildCardStringsToRegexp(patterns)
46 > if err != nil {
47 panic(err) //nolint:forbidigo // Must* functions conventionally panic on error.
48 }
49 > return re wildcard.go
50 }
go.temporal.io/server/service/history/outbound_queue_active_task_executor.go 20 covered LOC · 1 range

Open complete file

41 chasmEngine chasm.Engine,
42 matchingClient resource.MatchingClient,
43 > ) *outboundQueueActiveTaskExecutor { outbound_queue_active_task_executor.go
44 > scopedMetricsHandler := metricsHandler.WithTags(
45 > metrics.OperationTag(metrics.OperationOutboundQueueProcessorScope),
46 > )
47 > return &outboundQueueActiveTaskExecutor{
48 > stateMachineEnvironment: stateMachineEnvironment{
49 > shardContext: shardCtx,
50 > cache: workflowCache,
51 > logger: logger,
52 > metricsHandler: scopedMetricsHandler,
53 > },
54 > chasmEngine: chasmEngine,
55 > workerCommandsDispatcher: workercommands.NewDispatcher(
56 > matchingClient,
57 > shardCtx.GetConfig(),
58 > scopedMetricsHandler,
59 > logger,
60 > ),
61 > }
62 > }
63
64 func (e *outboundQueueActiveTaskExecutor) Execute(
go.temporal.io/server/service/history/queues/tracker.go 20 covered LOC · 5 ranges

Open complete file

18 )
19
20 > func newExecutableTracker(grouper Grouper) *executableTracker { tracker.go
21 > return &executableTracker{
22 > pendingExecutables: make(map[tasks.Key]Executable),
23 > grouper: grouper,
24 > pendingPerKey: make(map[any]int, 0),
25 > }
26 > }
27
28 func (t *executableTracker) split(
57 }
58
59 > func (t *executableTracker) merge(incomingTracker *executableTracker) *executableTracker { tracker.go
60 > thisExecutables, thisPendingTasks := t.pendingExecutables, t.pendingPerKey
61 > thatExecutables, thatPendingTasks := incomingTracker.pendingExecutables, incomingTracker.pendingPerKey
62 > if len(thisExecutables) < len(thatExecutables) {
63 thisExecutables, thatExecutables = thatExecutables, thisExecutables
64 thisPendingTasks = thatPendingTasks
65 }
66
67 > for key, executable := range thatExecutables { tracker.go
68 thisExecutables[key] = executable
69 key := t.grouper.Key(executable)
70 thisPendingTasks[key]++
71 }
72 > t.pendingExecutables = thisExecutables tracker.go
73 > t.pendingPerKey = thisPendingTasks
74 > return t
75 }
76
77 func (t *executableTracker) add(
78 executable Executable,
79 > ) { tracker.go
80 > t.pendingExecutables[executable.GetKey()] = executable
81 > key := t.grouper.Key(executable)
82 > t.pendingPerKey[key]++
83 > }
84
85 func (t *executableTracker) shrink() (tasks.Key, int) {
go.temporal.io/server/service/history/shard/ownership_based_quota_scaler.go 20 covered LOC · 4 ranges

Open complete file

62 totalNumShards int,
63 updateAppliedCallback chan struct{},
64 > ) (*OwnershipBasedQuotaScalerImpl, error) { ownership_based_quota_scaler.go
65 > if totalNumShards <= 0 {
66 return nil, fmt.Errorf("%w: %d", ErrNonPositiveTotalNumShards, totalNumShards)
67 }
68
69 > scaler := &OwnershipBasedQuotaScalerImpl{ ownership_based_quota_scaler.go
70 > shardCounter: shardCounter,
71 > totalNumShards: totalNumShards,
72 > updateAppliedCallback: updateAppliedCallback,
73 > subscription: shardCounter.SubscribeShardCount(),
74 > }
75 >
76 > scaler.shardCount.Store(shardCountNotSet)
77 > scaler.shutdownWG.Go(func() {
78 >
79 > for count := range scaler.subscription.ShardCount() {
80 > scaler.shardCount.Store(int64(count))
81 > if scaler.updateAppliedCallback != nil {
82 scaler.updateAppliedCallback <- struct{}{}
83 }
97 }
98
99 > func (s *OwnershipBasedQuotaScalerImpl) Close() { ownership_based_quota_scaler.go
100 > s.subscription.Unsubscribe()
101 > s.shutdownWG.Wait()
102 > }
103
104 func (s LazyLoadedOwnershipBasedQuotaScaler) ScaleFactor() (float64, bool) {
go.temporal.io/server/chasm/lib/workflow/registry.go 19 covered LOC · 10 ranges

Open complete file

30
31 // NewRegistry creates a new [Registry].
32 > func NewRegistry() *Registry { registry.go
33 > return &Registry{
34 > commandHandlers: make(map[enumspb.CommandType]CommandHandler),
35 > eventDefinitions: make(map[enumspb.EventType]EventDefinition),
36 > eventDefinitionsByGoType: make(map[reflect.Type]EventDefinition),
37 > }
38 > }
39
40 // Register registers all command handlers and event definitions from a [Library].
41 // Returns an [ErrDuplicateRegistration] if a handler or definition is already registered.
42 // All registration is expected to happen in a single thread on process initialization.
43 > func (r *Registry) Register(lib Library) error { registry.go
44 > for t, handler := range lib.CommandHandlers() {
45 > if existing, ok := r.commandHandlers[t]; ok { registry.go
46 return fmt.Errorf("%w: command handler for %v: %v", ErrDuplicateRegistration, t, existing)
47 }
48 > r.commandHandlers[t] = handler registry.go
49 }
50 > for _, def := range lib.EventDefinitions() { registry.go
51 > if existing, ok := r.eventDefinitions[def.Type()]; ok { registry.go
52 return fmt.Errorf("%w: event handler for %v: %v", ErrDuplicateRegistration, def.Type(), existing)
53 }
54 > goType := reflect.TypeOf(def) registry.go
55 > for goType.Kind() == reflect.Pointer {
56 goType = goType.Elem()
57 }
58 > if existing, ok := r.eventDefinitionsByGoType[goType]; ok { registry.go
59 return fmt.Errorf("%w: event definition for Go type %v: %v", ErrDuplicateRegistration, goType, existing)
60 }
61 > r.eventDefinitions[def.Type()] = def registry.go
62 > r.eventDefinitionsByGoType[goType] = def
63 }
64 > return nil registry.go
65 }
66
go.temporal.io/server/common/convert/convert.go 19 covered LOC · 7 ranges

Open complete file

12
13 // Int64Ceil return the int64 ceil of a float64
14 > func Int64Ceil(v float64) int64 { convert.go
15 > return int64(math.Ceil(v))
16 > }
17
18 > func IntToString(v int) string { convert.go
19 > return Int64ToString(int64(v))
20 > }
21
22 func Uint64ToString(v uint64) string {
24 }
25
26 > func Int64ToString(v int64) string { convert.go
27 > return strconv.FormatInt(v, 10)
28 > }
29
30 > func Int32ToString(v int32) string { convert.go
31 > return Int64ToString(int64(v))
32 > }
33
34 > func Uint16ToString(v uint16) string { convert.go
35 > return strconv.FormatUint(uint64(v), 10)
36 > }
37
38 func Int64SetToSlice(
71 func StringSliceToSet(
72 inputs []string,
73 > ) map[string]struct{} { convert.go
74 > outputs := make(map[string]struct{}, len(inputs))
75 > for _, item := range inputs {
76 outputs[item] = struct{}{}
77 }
78 > return outputs convert.go
79 }
go.temporal.io/server/common/definition/workflow_key.go 19 covered LOC · 5 ranges

Open complete file

19 workflowID string,
20 runID string,
21 > ) WorkflowKey { workflow_key.go
22 > return WorkflowKey{
23 > NamespaceID: namespaceID,
24 > WorkflowID: workflowID,
25 > RunID: runID,
26 > }
27 > }
28
29 > func (k *WorkflowKey) GetNamespaceID() string { workflow_key.go
30 > return k.NamespaceID
31 > }
32
33 > func (k *WorkflowKey) GetWorkflowID() string { workflow_key.go
34 > return k.WorkflowID
35 > }
36
37 > func (k *WorkflowKey) GetRunID() string { workflow_key.go
38 > return k.RunID
39 > }
40
41 > func (k *WorkflowKey) String() string { workflow_key.go
42 > return fmt.Sprintf("%v/%v/%v", k.NamespaceID, k.WorkflowID, k.RunID)
43 > }
go.temporal.io/server/common/persistence/namespace_replication_queue.go 19 covered LOC · 4 ranges

Open complete file

28 metricsHandler metrics.Handler,
29 logger log.Logger,
30 > ) (NamespaceReplicationQueue, error) { namespace_replication_queue.go
31 >
32 > blob, err := serializer.QueueMetadataToBlob(
33 > &persistencespb.QueueMetadata{
34 > ClusterAckLevels: make(map[string]int64),
35 > })
36 > if err != nil {
37 return nil, err
38 }
39 > err = queue.Init(context.TODO(), blob) namespace_replication_queue.go
40 > if err != nil {
41 return nil, err
42 }
43
44 > return &namespaceReplicationQueueImpl{ namespace_replication_queue.go
45 > queue: queue,
46 > clusterName: clusterName,
47 > metricsHandler: metricsHandler,
48 > logger: logger,
49 > serializer: serializer,
50 > }, nil
51 }
52
89 )
90
91 > func (q *namespaceReplicationQueueImpl) Close() { namespace_replication_queue.go
92 > q.queue.Close()
93 > }
94
95 func (q *namespaceReplicationQueueImpl) Publish(ctx context.Context, task *replicationspb.ReplicationTask) error {
go.temporal.io/server/common/persistence/visibility/quotas.go 19 covered LOC · 6 ranges

Open complete file

19 maxQPS dynamicconfig.IntPropertyFn,
20 operatorRPSRatio dynamicconfig.FloatPropertyFn,
21 > ) quotas.RequestRateLimiter { quotas.go
22 > rateLimiters := make(map[int]quotas.RequestRateLimiter)
23 > for priority := range PrioritiesOrdered {
24 > if priority == OperatorPriority {
25 > rateLimiters[priority] = quotas.NewRequestRateLimiterAdapter(quotas.NewDefaultOutgoingRateLimiter(operatorRateFn(maxQPS, operatorRPSRatio)))
26 > } else {
27 > rateLimiters[priority] = quotas.NewRequestRateLimiterAdapter(quotas.NewDefaultOutgoingRateLimiter(rateFn(maxQPS)))
28 > }
29 }
30 > return quotas.NewPriorityRateLimiter(func(req quotas.Request) int { quotas.go
31 > if req.CallerType == headers.CallerTypeOperator { quotas.go
32 return OperatorPriority
33 }
34 // default to lowest priority
35 > return PrioritiesOrdered[len(PrioritiesOrdered)-1] quotas.go
36 }, rateLimiters)
37 }
38
39 > func rateFn(maxQPS dynamicconfig.IntPropertyFn) quotas.RateFn { quotas.go
40 > return func() float64 {
41 > return float64(maxQPS())
42 > }
43 }
44
45 > func operatorRateFn(maxQPS dynamicconfig.IntPropertyFn, operatorRPSRatio dynamicconfig.FloatPropertyFn) quotas.RateFn { quotas.go
46 > return func() float64 {
47 > return float64(maxQPS()) * operatorRPSRatio()
48 > }
49 }
go.temporal.io/server/service/history/workflow/task_generator_provider.go 19 covered LOC · 4 ranges

Open complete file

23 )
24
25 > func init() { task_generator_provider.go
26 > var defaultProvider TaskGeneratorProvider = new(taskGeneratorProviderImpl)
27 > populateTaskGeneratorProvider(defaultProvider)
28 > }
29
30 > func populateTaskGeneratorProvider(provider TaskGeneratorProvider) { task_generator_provider.go
31 > _taskGeneratorProvider.Store(&provider)
32 > }
33
34 > func GetTaskGeneratorProvider() TaskGeneratorProvider { task_generator_provider.go
35 > return *_taskGeneratorProvider.Load()
36 > }
37
38 func (p *taskGeneratorProviderImpl) NewTaskGenerator(
39 shard historyi.ShardContext,
40 mutableState historyi.MutableState,
41 > ) TaskGenerator { task_generator_provider.go
42 > return NewTaskGenerator(
43 > shard.GetNamespaceRegistry(),
44 > mutableState,
45 > shard.GetConfig(),
46 > shard.GetArchivalMetadata(),
47 > shard.GetLogger(),
48 > )
49 > }
go.temporal.io/server/chasm/lib/scheduler/invoker_tasks.go 18 covered LOC · 2 ranges

Open complete file

101 )
102
103 > func NewInvokerExecuteTaskHandler(opts InvokerTaskHandlerOptions) *InvokerExecuteTaskHandler { invoker_tasks.go
104 > return &InvokerExecuteTaskHandler{
105 > config: opts.Config,
106 > metricsHandler: opts.MetricsHandler,
107 > baseLogger: opts.BaseLogger,
108 > historyClient: opts.HistoryClient,
109 > frontendClient: opts.FrontendClient,
110 > }
111 > }
112
113 > func NewInvokerProcessBufferTaskHandler(opts InvokerTaskHandlerOptions) *InvokerProcessBufferTaskHandler { invoker_tasks.go
114 > return &InvokerProcessBufferTaskHandler{
115 > config: opts.Config,
116 > metricsHandler: opts.MetricsHandler,
117 > baseLogger: opts.BaseLogger,
118 > historyClient: opts.HistoryClient,
119 > frontendClient: opts.FrontendClient,
120 > }
121 > }
122
123 // recordDuplicateExecuteDrops emits a metric + Debug log for CompletedStarts
go.temporal.io/server/common/aggregate/moving_window_average.go 18 covered LOC · 2 ranges

Open complete file

32 windowSize time.Duration,
33 maxBufferSize int,
34 > ) *MovingWindowAvgImpl { moving_window_average.go
35 > return &MovingWindowAvgImpl{
36 > windowSize: windowSize,
37 > maxBufferSize: maxBufferSize,
38 > buffer: make([]timestampedData, maxBufferSize),
39 > }
40 > }
41
42 > func (a *MovingWindowAvgImpl) Record(val int64) { moving_window_average.go
43 > a.Lock()
44 > defer a.Unlock()
45 >
46 > a.buffer[a.tailIdx] = timestampedData{timestamp: time.Now(), value: val}
47 > a.tailIdx = (a.tailIdx + 1) % a.maxBufferSize
48 >
49 > a.sum += val
50 > a.count++
51 >
52 > if a.tailIdx == a.headIdx {
53 // buffer full, expire oldest element
54 a.sum -= a.buffer[a.headIdx].value
go.temporal.io/server/common/persistence/history_manager_util.go 18 covered LOC · 4 ranges

Open complete file

21 executionMgr ExecutionManager,
22 req *ReadHistoryBranchRequest,
23 > ) ([]*historypb.HistoryEvent, int, []byte, error) { history_manager_util.go
24 > var historyEvents []*historypb.HistoryEvent
25 > size := 0
26 > for {
27 > response, err := executionMgr.ReadHistoryBranch(ctx, req)
28 > if err != nil {
29 return nil, 0, nil, err
30 }
31 > historyEvents = append(historyEvents, response.HistoryEvents...) history_manager_util.go
32 > size += response.Size
33 > if len(historyEvents) >= req.PageSize || len(response.NextPageToken) == 0 {
34 > return historyEvents, size, response.NextPageToken, nil
35 > }
36 req.NextPageToken = response.NextPageToken
37 }
115
116 // GetBeginNodeID gets node id from last ancestor
117 > func GetBeginNodeID(bi *persistencespb.HistoryBranch) int64 { history_manager_util.go
118 > if len(bi.Ancestors) == 0 {
119 > // root branch
120 > return 1
121 > }
122 idx := len(bi.Ancestors) - 1
123 return bi.Ancestors[idx].GetEndNodeId()
124 }
125
126 > func sortAncestors(ans []*persistencespb.HistoryBranchRange) { history_manager_util.go
127 > if len(ans) > 0 {
128 // sort ans based onf EndNodeID so that we can set BeginNodeID
129 sort.Slice(ans, func(i, j int) bool { return (ans)[i].GetEndNodeId() < (ans)[j].GetEndNodeId() })
go.temporal.io/server/common/rpc/multistats.go 18 covered LOC · 4 ranges

Open complete file

10 type MultiStatsHandler []stats.Handler
11
12 > func (m MultiStatsHandler) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context { multistats.go
13 > for _, h := range m {
14 > ctx = h.TagConn(ctx, info)
15 > }
16 > return ctx
17 }
18
19 > func (m MultiStatsHandler) HandleConn(ctx context.Context, cs stats.ConnStats) { multistats.go
20 > for _, h := range m {
21 > h.HandleConn(ctx, cs)
22 > }
23 }
24
25 > func (m MultiStatsHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context { multistats.go
26 > for _, h := range m {
27 > ctx = h.TagRPC(ctx, info)
28 > }
29 > return ctx
30 }
31
32 > func (m MultiStatsHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) { multistats.go
33 > for _, h := range m {
34 > h.HandleRPC(ctx, rs)
35 > }
36 }
go.temporal.io/server/components/nexusoperations/config.go 18 covered LOC · 1 range

Open complete file

185 }
186
187 > func ConfigProvider(dc *dynamicconfig.Collection, cfg *config.Persistence) *Config { config.go
188 > return &Config{
189 > RequestTimeout: RequestTimeout.Get(dc),
190 > MinRequestTimeout: MinRequestTimeout.Get(dc),
191 > MaxConcurrentOperations: MaxConcurrentOperations.Get(dc),
192 > MaxServiceNameLength: MaxServiceNameLength.Get(dc),
193 > MaxOperationNameLength: MaxOperationNameLength.Get(dc),
194 > MaxOperationTokenLength: MaxOperationTokenLength.Get(dc),
195 > MaxOperationHeaderSize: MaxOperationHeaderSize.Get(dc),
196 > DisallowedOperationHeaders: DisallowedOperationHeaders.Get(dc),
197 > MaxOperationScheduleToCloseTimeout: MaxOperationScheduleToCloseTimeout.Get(dc),
198 > PayloadSizeLimit: dynamicconfig.BlobSizeLimitError.Get(dc),
199 > CallbackURLTemplate: CallbackURLTemplate.Get(dc),
200 > UseSystemCallbackURL: UseSystemCallbackURL.Get(dc),
201 > UseNewFailureWireFormat: chasmnexus.UseNewFailureWireFormat.Get(dc),
202 > RecordCancelRequestCompletionEvents: RecordCancelRequestCompletionEvents.Get(dc),
203 > MetricTagConfig: MetricTagConfiguration.Get(dc),
204 > RetryPolicy: func() backoff.RetryPolicy {
205 return backoff.NewExponentialRetryPolicy(
206 RetryPolicyInitialInterval.Get(dc)(),
go.temporal.io/server/service/history/chasm_engine.go 18 covered LOC · 3 ranges

Open complete file

72 fx.Provide(NewChasmNotifier),
73 fx.Provide(newChasmEngine),
74 > fx.Provide(func(impl *ChasmEngine) chasm.Engine { return impl }), chasm_engine.go
75 > fx.Invoke(func(impl *ChasmEngine, shardController shard.Controller) {
76 > impl.SetShardController(shardController)
77 > }),
78 )
79
86 historyServiceResolver membership.ServiceResolver,
87 hostInfoProvider membership.HostInfoProvider,
88 > ) *ChasmEngine { chasm_engine.go
89 > return &ChasmEngine{
90 > executionCache: executionCache,
91 > registry: registry,
92 > config: config,
93 > notifier: notifier,
94 > logger: logger,
95 > historyServiceResolver: historyServiceResolver,
96 > hostInfoProvider: hostInfoProvider,
97 > }
98 > }
99
100 // This is for breaking fx cycle dependency.
102 func (e *ChasmEngine) SetShardController(
103 shardController shard.Controller,
104 > ) { chasm_engine.go
105 > e.shardController = shardController
106 > }
107
108 func (e *ChasmEngine) NotifyExecution(key chasm.ExecutionKey) {
go.temporal.io/server/service/history/tasks/workflow_cleanup_timer.go 18 covered LOC · 6 ranges

Open complete file

25 )
26
27 > func (a *DeleteHistoryEventTask) GetKey() Key { workflow_cleanup_timer.go
28 > return NewKey(a.VisibilityTimestamp, a.TaskID)
29 > }
30
31 func (a *DeleteHistoryEventTask) GetVersion() int64 {
41 }
42
43 > func (a *DeleteHistoryEventTask) SetTaskID(id int64) { workflow_cleanup_timer.go
44 > a.TaskID = id
45 > }
46
47 > func (a *DeleteHistoryEventTask) GetVisibilityTime() time.Time { workflow_cleanup_timer.go
48 > return a.VisibilityTimestamp
49 > }
50
51 > func (a *DeleteHistoryEventTask) SetVisibilityTime(timestamp time.Time) { workflow_cleanup_timer.go
52 > a.VisibilityTimestamp = timestamp
53 > }
54
55 > func (a *DeleteHistoryEventTask) GetCategory() Category { workflow_cleanup_timer.go
56 > return CategoryTimer
57 > }
58
59 > func (a *DeleteHistoryEventTask) GetType() enumsspb.TaskType { workflow_cleanup_timer.go
60 > return enumsspb.TASK_TYPE_DELETE_HISTORY_EVENT
61 > }
62
63 func (a *DeleteHistoryEventTask) GetArchetypeID() uint32 {
go.temporal.io/server/service/history/tasks/workflow_delay_timer.go 18 covered LOC · 6 ranges

Open complete file

23 )
24
25 > func (r *WorkflowBackoffTimerTask) GetKey() Key { workflow_delay_timer.go
26 > return NewKey(r.VisibilityTimestamp, r.TaskID)
27 > }
28
29 func (r *WorkflowBackoffTimerTask) GetVersion() int64 {
39 }
40
41 > func (r *WorkflowBackoffTimerTask) SetTaskID(id int64) { workflow_delay_timer.go
42 > r.TaskID = id
43 > }
44
45 > func (r *WorkflowBackoffTimerTask) GetVisibilityTime() time.Time { workflow_delay_timer.go
46 > return r.VisibilityTimestamp
47 > }
48
49 > func (r *WorkflowBackoffTimerTask) SetVisibilityTime(t time.Time) { workflow_delay_timer.go
50 > r.VisibilityTimestamp = t
51 > }
52
53 > func (r *WorkflowBackoffTimerTask) GetCategory() Category { workflow_delay_timer.go
54 > return CategoryTimer
55 > }
56
57 > func (r *WorkflowBackoffTimerTask) GetType() enumsspb.TaskType { workflow_delay_timer.go
58 > return enumsspb.TASK_TYPE_WORKFLOW_BACKOFF_TIMER
59 > }
60
61 func (r *WorkflowBackoffTimerTask) String() string {
go.temporal.io/server/service/history/tasks/workflow_task_timer.go 18 covered LOC · 7 ranges

Open complete file

40 )
41
42 > func (d *WorkflowTaskTimeoutTask) GetKey() Key { workflow_task_timer.go
43 > return NewKey(d.VisibilityTimestamp, d.TaskID)
44 > }
45
46 func (d *WorkflowTaskTimeoutTask) GetVersion() int64 {
56 }
57
58 > func (d *WorkflowTaskTimeoutTask) SetTaskID(id int64) { workflow_task_timer.go
59 > d.TaskID = id
60 > }
61
62 > func (d *WorkflowTaskTimeoutTask) GetVisibilityTime() time.Time { workflow_task_timer.go
63 > return d.VisibilityTimestamp
64 > }
65
66 > func (d *WorkflowTaskTimeoutTask) SetVisibilityTime(t time.Time) { workflow_task_timer.go
67 > d.VisibilityTimestamp = t
68 > }
69
70 > func (d *WorkflowTaskTimeoutTask) GetCategory() Category { workflow_task_timer.go
71 > if d.InMemory {
72 return CategoryMemoryTimer
73 }
74 > return CategoryTimer workflow_task_timer.go
75 }
76
77 > func (d *WorkflowTaskTimeoutTask) GetType() enumsspb.TaskType { workflow_task_timer.go
78 > return enumsspb.TASK_TYPE_WORKFLOW_TASK_TIMEOUT
79 > }
80
81 // Cancel and State are used by in-memory WorkflowTaskTimeoutTask (for speculative WT) only.
go.temporal.io/server/service/history/vclock/vclock.go 18 covered LOC · 7 ranges

Open complete file

10 shardID int32,
11 clock int64,
12 > ) *clockspb.VectorClock { vclock.go
13 > return &clockspb.VectorClock{
14 > ClusterId: clusterID,
15 > ShardId: shardID,
16 > Clock: clock,
17 > }
18 > }
19
20 func Comparable(
21 clock1 *clockspb.VectorClock,
22 clock2 *clockspb.VectorClock,
23 > ) bool { vclock.go
24 > if clock1 == nil || clock2 == nil {
25 return false
26 }
27 > return clock1.GetClusterId() == clock2.GetClusterId() && vclock.go
28 > clock1.GetShardId() == clock2.GetShardId()
29 }
30
32 clock1 *clockspb.VectorClock,
33 clock2 *clockspb.VectorClock,
34 > ) (int, error) { vclock.go
35 > if !Comparable(clock1, clock2) {
36 return 0, serviceerror.NewInternalf(
37 "Encountered shard ID mismatch: %v:%v vs %v:%v",
43 }
44
45 > vClock1 := clock1.GetClock() vclock.go
46 > vClock2 := clock2.GetClock()
47 > if vClock1 < vClock2 {
48 > return -1, nil vclock.go
49 > } else if vClock1 > vClock2 { vclock.go
50 return 1, nil
51 } else {
go.temporal.io/server/service/matching/liveness.go 18 covered LOC · 5 ranges

Open complete file

25 ttl func() time.Duration,
26 onIdle func(),
27 > ) *liveness { liveness.go
28 > return &liveness{
29 > timeSource: timeSource,
30 > ttl: ttl,
31 > onIdle: onIdle,
32 > }
33 > }
34
35 > func (l *liveness) Start() { liveness.go
36 > l.timer.Store(timerWrapper{l.timeSource.AfterFunc(l.ttl(), l.onIdle)})
37 > }
38
39 > func (l *liveness) Stop() { liveness.go
40 > if t, ok := l.timer.Swap(timerWrapper{}).(timerWrapper); ok && t.Timer != nil {
41 > t.Stop()
42 > }
43 }
44
45 > func (l *liveness) markAlive() { liveness.go
46 > if t, ok := l.timer.Load().(timerWrapper); ok && t.Timer != nil {
47 > t.Reset(l.ttl()) liveness.go
48 > }
49 }
go.temporal.io/server/chasm/context.go 17 covered LOC · 2 ranges

Open complete file

133 ctx context.Context,
134 node *Node,
135 > ) Context { context.go
136 > return newContext(ctx, node)
137 > }
138
139 // newContext creates a new immutableCtx from an existing Context and root Node.
142 ctx context.Context,
143 node *Node,
144 > ) *immutableCtx { context.go
145 > root := node.root()
146 > workflowKey := node.backend.GetWorkflowKey()
147 > return &immutableCtx{
148 > ctx: ctx,
149 > now: root.Now(nil),
150 > root: root,
151 > executionKey: ExecutionKey{
152 > NamespaceID: workflowKey.NamespaceID,
153 > BusinessID: workflowKey.WorkflowID,
154 > RunID: workflowKey.RunID,
155 > },
156 > }
157 > }
158
159 func (c *immutableCtx) Ref(component Component) ([]byte, error) {
go.temporal.io/server/chasm/lib/activity/activity_tasks.go 17 covered LOC · 5 ranges

Open complete file

24 }
25
26 > func newActivityDispatchTaskHandler(opts activityDispatchTaskHandlerOptions) *activityDispatchTaskHandler { activity_tasks.go
27 > return &activityDispatchTaskHandler{
28 > opts: opts,
29 > }
30 > }
31
32 func (h *activityDispatchTaskHandler) Validate(
83 }
84
85 > func newScheduleToStartTimeoutTaskHandler() *scheduleToStartTimeoutTaskHandler { activity_tasks.go
86 > return &scheduleToStartTimeoutTaskHandler{}
87 > }
88
89 func (h *scheduleToStartTimeoutTaskHandler) Validate(
119 type scheduleToCloseTimeoutTaskHandler struct{ chasm.PureTaskHandlerBase }
120
121 > func newScheduleToCloseTimeoutTaskHandler() *scheduleToCloseTimeoutTaskHandler { activity_tasks.go
122 > return &scheduleToCloseTimeoutTaskHandler{}
123 > }
124
125 func (h *scheduleToCloseTimeoutTaskHandler) Validate(
165 type startToCloseTimeoutTaskHandler struct{ chasm.PureTaskHandlerBase }
166
167 > func newStartToCloseTimeoutTaskHandler() *startToCloseTimeoutTaskHandler { activity_tasks.go
168 > return &startToCloseTimeoutTaskHandler{}
169 > }
170
171 func (h *startToCloseTimeoutTaskHandler) Validate(
215 type heartbeatTimeoutTaskHandler struct{ chasm.PureTaskHandlerBase }
216
217 > func newHeartbeatTimeoutTaskHandler() *heartbeatTimeoutTaskHandler { activity_tasks.go
218 > return &heartbeatTimeoutTaskHandler{}
219 > }
220
221 // Validate validates a HeartbeatTimeoutTask.
go.temporal.io/server/common/enums/defaults.go 17 covered LOC · 9 ranges

Open complete file

5 )
6
7 > func SetDefaultWorkflowIdReusePolicy(f *enumspb.WorkflowIdReusePolicy) { defaults.go
8 > if *f == enumspb.WORKFLOW_ID_REUSE_POLICY_UNSPECIFIED {
9 > *f = enumspb.WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE defaults.go
10 > }
11 }
12
16 conflictPolicy *enumspb.WorkflowIdConflictPolicy,
17 defaultConflictPolicy enumspb.WorkflowIdConflictPolicy,
18 > ) { defaults.go
19 > // Set default conflict policy, if unset
20 > if *conflictPolicy == enumspb.WORKFLOW_ID_CONFLICT_POLICY_UNSPECIFIED {
21 > //nolint:staticcheck // SA1019: intentional migration of deprecated policy defaults.go
22 > if *reusePolicy == enumspb.WORKFLOW_ID_REUSE_POLICY_TERMINATE_IF_RUNNING {
23 // Migrate the deprecated TERMINATE_IF_RUNNING.
24 *conflictPolicy = enumspb.WORKFLOW_ID_CONFLICT_POLICY_TERMINATE_EXISTING
25 *reusePolicy = enumspb.WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE
26 > } else { defaults.go
27 > *conflictPolicy = defaultConflictPolicy defaults.go
28 > }
29 }
30
31 // Set default reuse policy, if unset
32 > SetDefaultWorkflowIdReusePolicy(reusePolicy) defaults.go
33 }
34
35 > func SetDefaultHistoryEventFilterType(f *enumspb.HistoryEventFilterType) { defaults.go
36 > if *f == enumspb.HISTORY_EVENT_FILTER_TYPE_UNSPECIFIED {
37 *f = enumspb.HISTORY_EVENT_FILTER_TYPE_ALL_EVENT
38 }
39 }
40
41 > func SetDefaultTaskQueueKind(f *enumspb.TaskQueueKind) { defaults.go
42 > if *f == enumspb.TASK_QUEUE_KIND_UNSPECIFIED {
43 *f = enumspb.TASK_QUEUE_KIND_NORMAL
44 }
go.temporal.io/server/common/log/lazy_logger.go 17 covered LOC · 4 ranges

Open complete file

19 )
20
21 > func NewLazyLogger(logger Logger, tagFn func() []tag.Tag) *lazyLogger { lazy_logger.go
22 > return &lazyLogger{
23 > logger: logger,
24 > tagFn: tagFn,
25 > }
26 > }
27
28 > func (l *lazyLogger) Debug(msg string, tags ...tag.Tag) { lazy_logger.go
29 > l.once.Do(l.tagLogger)
30 > l.logger.Debug(msg, tags...)
31 > }
32
33 func (l *lazyLogger) Info(msg string, tags ...tag.Tag) {
61 }
62
63 > func (l *lazyLogger) With(tags ...tag.Tag) Logger { lazy_logger.go
64 > l.once.Do(l.tagLogger)
65 > return With(l.logger, tags...)
66 > }
67
68 > func (l *lazyLogger) tagLogger() { lazy_logger.go
69 > l.logger = With(l.logger, l.tagFn()...)
70 > }
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/queue.go 17 covered LOC · 4 ranges

Open complete file

107 ctx context.Context,
108 row *sqlplugin.QueueMetadataRow,
109 > ) (sql.Result, error) { queue.go
110 > return mdb.conn.NamedExecContext(ctx,
111 > templateCreateQueueMetadataQuery,
112 > row,
113 > )
114 > }
115
116 func (mdb *db) UpdateQueueMetadata(
127 ctx context.Context,
128 filter sqlplugin.QueueMetadataFilter,
129 > ) (*sqlplugin.QueueMetadataRow, error) { queue.go
130 > var row sqlplugin.QueueMetadataRow
131 > err := mdb.conn.GetContext(ctx,
132 > &row,
133 > templateGetQueueMetadataQuery,
134 > filter.QueueType,
135 > )
136 > if err != nil {
137 > return nil, err queue.go
138 > }
139 > return &row, nil queue.go
140 }
141
go.temporal.io/server/common/persistence/sql/task_store.go 17 covered LOC · 3 ranges

Open complete file

29 enableFairness bool,
30 serializer serialization.Serializer,
31 > ) (persistence.TaskStore, error) { task_store.go
32 > store := SqlStore{
33 > DB: db,
34 > logger: logger,
35 > serializer: serializer,
36 > }
37 > userDataStore := userDataStore{SqlStore: store}
38 > taskQueueStore := taskQueueStore{
39 > SqlStore: store,
40 > version: sqlplugin.MatchingTaskVersion1,
41 > taskScanPartitions: uint32(taskScanPartitions),
42 > }
43 > if enableFairness {
44 > taskQueueStore.version = sqlplugin.MatchingTaskVersion2 task_store.go
45 > return newTaskManagerV2(db, userDataStore, taskQueueStore, logger, serializer)
46 > }
47 > return newTaskManagerV1(db, userDataStore, taskQueueStore, logger, serializer) task_store.go
48 }
go.temporal.io/server/common/testing/await/config.go 17 covered LOC · 3 ranges

Open complete file

17 }
18
19 > func newConfig() config { config.go
20 > return config{
21 > attemptTimeout: envDuration(attemptTimeoutEnvVar, 10*time.Second) * debug.TimeoutMultiplier,
22 > }
23 > }
24
25 > func legacyConfig(timeout, pollInterval time.Duration, timeoutMsg string) config { config.go
26 > cfg := newConfig()
27 > cfg.totalTimeout = timeout
28 > cfg.pollInterval = pollInterval
29 > cfg.timeoutMsg = timeoutMsg
30 > return cfg
31 > }
32
33 > func envDuration(name string, fallback time.Duration) time.Duration { config.go
34 > if s := os.Getenv(name); s != "" {
35 > if d, err := time.ParseDuration(s); err == nil && d > 0 {
36 > return d
37 > }
38 }
39 return fallback
go.temporal.io/server/common/testing/testhooks/test_impl.go 17 covered LOC · 6 ranges

Open complete file

30 }
31
32 > func NewTestHooks() TestHooks { test_impl.go
33 > return TestHooks{data: &sync.Map{}}
34 > }
35
36 // Get gets the value of a test hook from the registry.
37 //
38 // TestHooks should be used sparingly, see comment on TestHooks.
39 > func Get[T any, S any](th TestHooks, key Key[T, S], scope S) (T, bool) { test_impl.go
40 > var zero T
41 > if th.data == nil {
42 // This means TestHooks wasn't created via NewTestHooks. Ignore.
43 return zero, false
44 }
45 > if val, ok := th.data.Load(hookKey{key.id, scope}); ok { test_impl.go
46 return val.(T), true //nolint:revive
47 }
48 > return zero, false test_impl.go
49 }
50
89 var keyCounter atomic.Int64
90
91 > func newKey[T any, S any]() Key[T, S] { test_impl.go
92 > var zero S
93 > var s ScopeType
94 > switch any(zero).(type) {
95 > case namespace.ID, namespace.Name:
96 > s = ScopeNamespace
97 > case global:
98 > s = ScopeGlobal
99 default:
100 panic("testhooks: unknown scope type")
101 }
102 > return Key[T, S]{id: keyCounter.Add(1), scopeType: s} test_impl.go
103 }
go.temporal.io/server/service/history/api/link_util.go 17 covered LOC · 1 range

Open complete file

10 // Use this for backlinks to workflow start: the started event is always EventId=1 (FirstEventID)
11 // and is never buffered, so a concrete EventReference is appropriate.
12 > func GenerateStartedEventRefLink(namespace, workflowID, runID string) *commonpb.Link { link_util.go
13 > return &commonpb.Link{
14 > Variant: &commonpb.Link_WorkflowEvent_{
15 > WorkflowEvent: &commonpb.Link_WorkflowEvent{
16 > Namespace: namespace,
17 > WorkflowId: workflowID,
18 > RunId: runID,
19 > Reference: &commonpb.Link_WorkflowEvent_EventRef{
20 > EventRef: &commonpb.Link_WorkflowEvent_EventReference{
21 > EventId: common.FirstEventID,
22 > EventType: enumspb.EVENT_TYPE_WORKFLOW_EXECUTION_STARTED,
23 > },
24 > },
25 > },
26 > },
27 > }
28 > }
29
30 // GenerateRequestIDRefLink builds a Link with a RequestIdReference.
go.temporal.io/server/service/history/replication/dlq_writer.go 17 covered LOC · 3 ranges

Open complete file

59
60 // NewExecutionManagerDLQWriter creates a new DLQWriter that uses the [ExecutionManager].
61 > func NewExecutionManagerDLQWriter(executionManager ExecutionManager) *executionManagerDLQWriter { dlq_writer.go
62 > return &executionManagerDLQWriter{
63 > executionManager: executionManager,
64 > }
65 > }
66
67 // NewDLQWriterAdapter creates a new DLQWriter from a QueueV2 [queues.DLQWriter].
70 replicationTaskSerializer TaskSerializer,
71 currentClusterName string,
72 > ) *DLQWriterAdapter { dlq_writer.go
73 > return &DLQWriterAdapter{
74 > dlqWriter: dlqWriter,
75 > replicationTaskSerializer: replicationTaskSerializer,
76 > currentClusterName: currentClusterName,
77 > }
78 > }
79
80 // This creates a new [DLQWriter] that can be toggled between the two implementations.
81 func newDLQWriterToggle(
82 params dlqWriterToggleParams,
83 > ) DLQWriter { dlq_writer.go
84 > return &dlqWriterToggle{
85 > dlqWriterToggleParams: &params,
86 > }
87 > }
88
89 // WriteTaskToDLQ implements [DLQWriter.WriteTaskToDLQ] by calling either
go.temporal.io/server/service/history/shard/handover_tracker.go 17 covered LOC · 4 ranges

Open complete file

63
64 // NewDefaultHandoverTrackerFactory returns a factory that creates the default OSS HandoverTracker.
65 > func NewDefaultHandoverTrackerFactory() HandoverTrackerFactory { handover_tracker.go
66 > return func(params HandoverTrackerParams) HandoverTracker {
67 > return &defaultHandoverTracker{ handover_tracker.go
68 > handoverNamespaces: make(map[namespace.Name]*namespaceHandOverInfo),
69 > clusterMetadata: params.ClusterMetadata,
70 > getMaxReplicationTaskID: params.GetMaxReplicationTaskID,
71 > errorByStateFn: params.ErrorByStateFn,
72 > notifyReplicationFn: params.NotifyReplicationFn,
73 > logger: params.Logger,
74 > }
75 > }
76 }
77
113 }
114
115 > func (t *defaultHandoverTracker) IsInHandover(namespaceName namespace.Name, workflowID string) bool { handover_tracker.go
116 > _, ok := t.handoverNamespaces[namespaceName]
117 > return ok
118 > }
119
120 func (t *defaultHandoverTracker) GetHandoverNamespaces() map[string]*historyservice.HandoverNamespaceInfo {
128 }
129
130 > func (t *defaultHandoverTracker) ResolvePendingTaskIDs(maxReplicationTaskID int64) { handover_tracker.go
131 > for _, handoverInfo := range t.handoverNamespaces {
132 if handoverInfo.MaxReplicationTaskID == PendingMaxReplicationTaskID {
133 handoverInfo.MaxReplicationTaskID = maxReplicationTaskID
go.temporal.io/server/service/history/timer_queue_standby_task_executor.go 17 covered LOC · 1 range

Open complete file

54 config *configs.Config,
55 clientBean client.Bean,
56 > ) queues.Executor { timer_queue_standby_task_executor.go
57 > return &timerQueueStandbyTaskExecutor{
58 > timerQueueTaskExecutorBase: newTimerQueueTaskExecutorBase(
59 > shard,
60 > workflowCache,
61 > workflowDeleteManager,
62 > matchingRawClient,
63 > chasmEngine,
64 > logger,
65 > metricProvider,
66 > config,
67 > false,
68 > ),
69 > clusterName: clusterName,
70 > clientBean: clientBean,
71 > }
72 > }
73
74 func (t *timerQueueStandbyTaskExecutor) Execute(
go.temporal.io/server/service/history/timer_queue_task_executor_base.go 17 covered LOC · 1 range

Open complete file

61 config *configs.Config,
62 isActive bool,
63 > ) *timerQueueTaskExecutorBase { timer_queue_task_executor_base.go
64 > return &timerQueueTaskExecutorBase{
65 > stateMachineEnvironment: stateMachineEnvironment{
66 > shardContext: shardContext,
67 > cache: workflowCache,
68 > logger: logger,
69 > metricsHandler: metricsHandler,
70 > },
71 > currentClusterName: shardContext.GetClusterMetadata().GetCurrentClusterName(),
72 > registry: shardContext.GetNamespaceRegistry(),
73 > chasmEngine: chasmEngine,
74 > deleteManager: deleteManager,
75 > matchingRawClient: matchingRawClient,
76 > config: config,
77 > isActive: isActive,
78 > }
79 > }
80
81 func (t *timerQueueTaskExecutorBase) executeDeleteHistoryEventTask(
go.temporal.io/server/service/history/worker_versioning_util.go 17 covered LOC · 2 ranges

Open complete file

126 metricsHandler metrics.Handler,
127 logger log.Logger,
128 > ) (retErr error) { worker_versioning_util.go
129 > if buildId == "" {
130 > // the task is sync-matched, or versioning is not enabled for this Task Queue
131 > return nil
132 > }
133
134 defer func() {
198 }
199
200 > func MakeDirectiveForWorkflowTask(ms historyi.MutableState) *taskqueuespb.TaskVersionDirective { worker_versioning_util.go
201 > return worker_versioning.MakeDirectiveForWorkflowTask(
202 > ms.GetInheritedBuildId(),
203 > ms.GetAssignedBuildId(),
204 > ms.GetMostRecentWorkerVersionStamp(),
205 > ms.HasCompletedAnyWorkflowTask(),
206 > ms.GetEffectiveVersioningBehavior(),
207 > ms.GetEffectiveDeployment(),
208 > ms.GetVersioningRevisionNumber(),
209 > ms.GetShouldUseRampingVersion(),
210 > )
211 > }
212
213 func MakeDirectiveForActivityTask(mutableState historyi.MutableState, activityInfo *persistencespb.ActivityInfo) *taskqueuespb.TaskVersionDirective {
go.temporal.io/server/service/history/workflow/state_transition_history.go 17 covered LOC · 5 ranges

Open complete file

25 history []*persistencespb.VersionedTransition,
26 namespaceFailoverVersion int64,
27 > ) []*persistencespb.VersionedTransition { state_transition_history.go
28 > if len(history) == 0 {
29 > return []*persistencespb.VersionedTransition{ state_transition_history.go
30 > {
31 > NamespaceFailoverVersion: namespaceFailoverVersion,
32 > TransitionCount: 1,
33 > },
34 > }
35 > }
36
37 > lastTransitionCount := history[len(history)-1].TransitionCount state_transition_history.go
38 > if history[len(history)-1].NamespaceFailoverVersion == namespaceFailoverVersion {
39 > history = history[:len(history)-1] state_transition_history.go
40 > }
41 > return append(history, &persistencespb.VersionedTransition{ state_transition_history.go
42 > NamespaceFailoverVersion: namespaceFailoverVersion,
43 > TransitionCount: lastTransitionCount + 1,
44 > })
45 }
go.temporal.io/server/service/worker/deletenamespace/deleteexecutions/activities.go 17 covered LOC · 2 ranges

Open complete file

72 metricsHandler metrics.Handler,
73 logger log.Logger,
74 > ) *Activities { activities.go
75 > return &Activities{
76 > visibilityManager: visibilityManager,
77 > historyClient: historyClient,
78 > deleteActivityRPS: deleteActivityRPS,
79 > useChasmDeleteExecution: useChasmDeleteExecution,
80 > metricsHandler: metricsHandler,
81 > logger: logger,
82 > }
83 > }
84
85 func NewLocalActivities(
87 metricsHandler metrics.Handler,
88 logger log.Logger,
89 > ) *LocalActivities { activities.go
90 > return &LocalActivities{
91 > visibilityManager: visibilityManager,
92 > metricsHandler: metricsHandler,
93 > logger: logger,
94 > }
95 > }
96
97 func (a *LocalActivities) GetNextPageTokenActivity(ctx context.Context, params GetNextPageTokenParams) ([]byte, error) {
go.temporal.io/server/chasm/library_core.go 16 covered LOC · 3 ranges

Open complete file

6 }
7
8 > func (b *CoreLibrary) Name() string { library_core.go
9 > return "core"
10 > }
11
12 > func (b *CoreLibrary) Components() []*RegistrableComponent { library_core.go
13 > return []*RegistrableComponent{
14 > NewRegistrableComponent[*Visibility]("vis", WithDetached()),
15 > }
16 > }
17
18 > func (b *CoreLibrary) Tasks() []*RegistrableTask { library_core.go
19 > return []*RegistrableTask{
20 > NewRegistrableSideEffectTask(
21 > "visTask",
22 > defaultVisibilityTaskHandler,
23 > ),
24 > }
25 > }
go.temporal.io/server/common/api/metadata.go 16 covered LOC · 5 ranges

Open complete file

217 // GetMethodMetadata gets metadata for a given API method in one of the services exported by
218 // frontend (WorkflowService, OperatorService, AdminService).
219 > func GetMethodMetadata(fullApiName string) MethodMetadata { metadata.go
220 > switch {
221 > case strings.HasPrefix(fullApiName, WorkflowServicePrefix):
222 > return workflowServiceMetadata[MethodName(fullApiName)]
223 case strings.HasPrefix(fullApiName, OperatorServicePrefix):
224 return operatorServiceMetadata[MethodName(fullApiName)]
225 case strings.HasPrefix(fullApiName, NexusServicePrefix):
226 return nexusServiceMetadata[MethodName(fullApiName)]
227 > case strings.HasPrefix(fullApiName, AdminServicePrefix): metadata.go
228 > return MethodMetadata{Scope: ScopeCluster, Access: AccessAdmin}
229 default:
230 return MethodMetadata{Scope: ScopeUnknown, Access: AccessUnknown}
233
234 // MethodName returns just the method name from a fully qualified name.
235 > func MethodName(fullApiName string) string { metadata.go
236 > index := strings.LastIndex(fullApiName, "/")
237 > if index > -1 {
238 > return fullApiName[index+1:] metadata.go
239 > }
240 return fullApiName
241 }
242
243 > func ServiceName(fullApiName string) string { metadata.go
244 > index := strings.LastIndex(fullApiName, "/")
245 > if index > -1 {
246 > return fullApiName[:index+1]
247 > }
248 return ""
249 }
go.temporal.io/server/common/clock/time_source.go 16 covered LOC · 5 ranges

Open complete file

31
32 // NewRealTimeSource returns a timeSource that uses the real wall timeSource time.
33 > func NewRealTimeSource() RealTimeSource { time_source.go
34 > return RealTimeSource{}
35 > }
36
37 // Now returns the current time, with the location set to UTC.
38 > func (ts RealTimeSource) Now() time.Time { time_source.go
39 > return time.Now().UTC()
40 > }
41
42 // Since returns the time elapsed since t
43 > func (ts RealTimeSource) Since(t time.Time) time.Duration { time_source.go
44 > return time.Since(t)
45 > }
46
47 // AfterFunc is a pass-through to time.AfterFunc.
48 > func (ts RealTimeSource) AfterFunc(d time.Duration, f func()) Timer { time_source.go
49 > return time.AfterFunc(d, f)
50 > }
51
52 // NewTimer is a pass-through to time.NewTimer.
53 > func (ts RealTimeSource) NewTimer(d time.Duration) (<-chan time.Time, Timer) { time_source.go
54 > t := time.NewTimer(d)
55 > return t.C, t
56 > }
go.temporal.io/server/common/nexus/nexusrpc/server.go 16 covered LOC · 6 ranges

Open complete file

380
381 // NewHTTPHandler constructs an [http.Handler] from given options for handling Nexus service requests.
382 > func NewHTTPHandler(options HandlerOptions) http.Handler { server.go
383 > if options.Logger == nil {
384 options.Logger = slog.Default()
385 }
386 > if options.GetResultTimeout == 0 { server.go
387 options.GetResultTimeout = time.Minute
388 }
389 > if options.Serializer == nil { server.go
390 options.Serializer = nexus.DefaultSerializer()
391 }
392 > if options.FailureConverter == nil { server.go
393 > options.FailureConverter = DefaultFailureConverter() server.go
394 > }
395 > handler := &httpHandler{ server.go
396 > BaseHTTPHandler: BaseHTTPHandler{
397 > Logger: options.Logger,
398 > FailureConverter: options.FailureConverter,
399 > },
400 > options: options,
401 > }
402 >
403 > return http.HandlerFunc(handler.handleRequest)
404 }
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/task_v2.go 16 covered LOC · 4 ranges

Open complete file

44 ctx context.Context,
45 filter sqlplugin.TasksFilterV2,
46 > ) ([]sqlplugin.TasksRowV2, error) { task_v2.go
47 > if filter.InclusiveMinLevel == nil {
48 return nil, serviceerror.NewInternal("missing InclusiveMinLevel")
49 }
50 > var err error task_v2.go
51 > var rows []sqlplugin.TasksRowV2
52 > switch {
53 > case filter.PageSize != nil:
54 > err = mdb.conn.SelectContext(ctx,
55 > &rows, getTaskV2QryWithLimit,
56 > filter.RangeHash,
57 > filter.TaskQueueID,
58 > filter.InclusiveMinLevel.TaskPass,
59 > filter.InclusiveMinLevel.TaskID,
60 > *filter.PageSize,
61 > )
62 default:
63 err = mdb.conn.SelectContext(ctx,
69 )
70 }
71 > if err != nil { task_v2.go
72 return nil, err
73 }
74 > return rows, nil task_v2.go
75 }
76
go.temporal.io/server/common/quotas/multi_reservation_impl.go 16 covered LOC · 6 ranges

Open complete file

17 ok bool,
18 reservations []Reservation,
19 > ) *MultiReservationImpl { multi_reservation_impl.go
20 > if ok && len(reservations) == 0 {
21 panic("expect at least one reservation")
22 }
23 > return &MultiReservationImpl{ multi_reservation_impl.go
24 > ok: ok,
25 > reservations: reservations,
26 > }
27 }
28
29 // OK returns whether the limiter can provide the requested number of tokens
30 > func (r *MultiReservationImpl) OK() bool { multi_reservation_impl.go
31 > return r.ok
32 > }
33
34 // Cancel indicates that the reservation holder will not perform the reserved action
59 // before taking the reserved action. Zero duration means act immediately.
60 // MultiReservation DelayFrom returns the maximum delay of all its sub-reservations.
61 > func (r *MultiReservationImpl) DelayFrom(now time.Time) time.Duration { multi_reservation_impl.go
62 > if !r.ok {
63 return InfDuration
64 }
65
66 > result := r.reservations[0].DelayFrom(now) multi_reservation_impl.go
67 > for _, reservation := range r.reservations {
68 > duration := reservation.DelayFrom(now)
69 > if result < duration {
70 result = duration
71 }
72 }
73 > return result multi_reservation_impl.go
74 }
go.temporal.io/server/common/rpc/encryption/local_store_cert_provider.go 16 covered LOC · 2 ranges

Open complete file

53 type tlsCertFetcher func() (*tls.Certificate, error)
54
55 > func (s *localStoreCertProvider) initialize() { local_store_cert_provider.go
56 >
57 > if s.refreshInterval != 0 {
58 s.stop = make(chan bool)
59 s.ticker = time.NewTicker(s.refreshInterval)
67 legacyWorkerSettings *config.ClientTLS,
68 refreshInterval time.Duration,
69 > logger log.Logger) CertProvider { local_store_cert_provider.go
70 >
71 > provider := &localStoreCertProvider{
72 > tlsSettings: tlsSettings,
73 > workerTLSSettings: workerTlsSettings,
74 > legacyWorkerSettings: legacyWorkerSettings,
75 > isLegacyWorkerConfig: legacyWorkerSettings != nil,
76 > logger: logger,
77 > refreshInterval: refreshInterval,
78 > }
79 > provider.initialize()
80 > return provider
81 > }
82
83 func (s *localStoreCertProvider) Close() {
go.temporal.io/server/common/rpc/interceptor/service_error_interceptor.go 16 covered LOC · 4 ranges

Open complete file

21 func NewServiceErrorInterceptor(
22 maxMessageLength dynamicconfig.IntPropertyFn,
23 > ) *ServiceErrorInterceptor { service_error_interceptor.go
24 > return &ServiceErrorInterceptor{
25 > maxMessageLength: maxMessageLength,
26 > }
27 > }
28
29 func (i *ServiceErrorInterceptor) Intercept(
32 _ *grpc.UnaryServerInfo,
33 handler grpc.UnaryHandler,
34 > ) (any, error) { service_error_interceptor.go
35 > resp, err := handler(ctx, req)
36 >
37 > var deserializationError *serialization.DeserializationError
38 > var serializationError *serialization.SerializationError
39 > // convert serialization errors to be captured as serviceerrors across gRPC calls
40 > if errors.As(err, &deserializationError) || errors.As(err, &serializationError) {
41 err = serviceerror.NewDataLoss(err.Error())
42 }
43
44 // truncate message length if needed
45 > maxLength := i.maxMessageLength() service_error_interceptor.go
46 > st := serviceerror.ToStatus(err)
47 > if len(st.Message()) > maxLength {
48 p := st.Proto()
49 p.Message = util.TruncateUTF8(p.Message, maxLength-len(truncatedSuffix)) + truncatedSuffix
go.temporal.io/server/common/rpc/interceptor/slow_request_logger.go 16 covered LOC · 3 ranges

Open complete file

23 logger log.Logger,
24 slowRequestThreshold dynamicconfig.DurationPropertyFn,
25 > ) *SlowRequestLoggerInterceptor { slow_request_logger.go
26 > return &SlowRequestLoggerInterceptor{
27 > logger: logger,
28 > workflowTags: logtags.NewWorkflowTags(tasktoken.NewSerializer(), logger),
29 > slowRequestThreshold: slowRequestThreshold,
30 > }
31 > }
32
33 func (i *SlowRequestLoggerInterceptor) Intercept(
36 info *grpc.UnaryServerInfo,
37 handler grpc.UnaryHandler,
38 > ) (any, error) { slow_request_logger.go
39 > // Long-polled methods aren't useful logged.
40 > if api.GetMethodMetadata(info.FullMethod).Polling == api.PollingNone {
41 > startTime := time.Now()
42 >
43 > defer func() {
44 > elapsed := time.Since(startTime)
45 > if elapsed > i.slowRequestThreshold() {
46 i.logSlowRequest(request, info, elapsed)
47 }
go.temporal.io/server/common/util/error_type.go 16 covered LOC · 5 ranges

Open complete file

27 // Otherwise, the type name of the first non-wrapper error in the depth-first traversal of err's tree is returned.
28 // We consider errors wrapped via [fmt.Errorf], [errors.Join] and some pkg/errors functions to be wrapper errors.
29 > func ErrorType(err error) string { error_type.go
30 > // If any error in the tree has an explicit type name, use it, preferring the first one in the DFS traversal.
31 > var typedErr typedError
32 > if errors.As(err, &typedErr) {
33 return typedErr.ErrorTypeName()
34 }
35
36 // Special case for context.Cancel error. It is of type errorString, which is not very useful.
37 > if errors.Is(err, context.Canceled) { error_type.go
38 > return "context.Canceled" error_type.go
39 > }
40 // Special case for context.DeadlineExceeded error. It is of unexported type deadlineExceededError.
41 > if errors.Is(err, context.DeadlineExceeded) { error_type.go
42 return "context.DeadlineExceeded"
43 }
44
45 // Otherwise, do a DFS traversal of the error tree, ignoring wrapper errors.
46 > q := []error{err} error_type.go
47 > for len(q) > 0 {
48 > err = q[len(q)-1]
49 > q = q[:len(q)-1]
50 > errType := fmt.Sprintf("%T", err)
51 > if !wrapperErrorTypes[errType] {
52 > return strings.TrimPrefix(errType, "*")
53 > }
54 // The error could implement zero or one of the unary or multi-error wrapper interfaces. It's impossible to
55 // implement both because they have the same method name. As a result, this is still deterministic.
go.temporal.io/server/service/frontend/nexus_endpoint_client.go 16 covered LOC · 2 ranges

Open complete file

53 )
54
55 > func newNexusEndpointClientConfig(dc *dynamicconfig.Collection) *nexusEndpointClientConfig { nexus_endpoint_client.go
56 > maxDescriptionSizeFn := dynamicconfig.NexusEndpointDescriptionMaxSize.Get(dc)
57 >
58 > return &nexusEndpointClientConfig{
59 > maxNameLength: dynamicconfig.NexusEndpointNameMaxLength.Get(dc),
60 > maxTaskQueueLength: dynamicconfig.MaxIDLengthLimit.Get(dc),
61 > maxDescriptionSize: func() int {
62 return maxDescriptionSizeFn("") // Ignore namespace for endpoints since they are global resources.
63 },
74 persistence p.NexusEndpointManager,
75 logger log.Logger,
76 > ) *NexusEndpointClient { nexus_endpoint_client.go
77 > return &NexusEndpointClient{
78 > config: config,
79 > namespaceRegistry: namespaceRegistry,
80 > matchingClient: matchingClient,
81 > persistence: persistence,
82 > logger: logger,
83 > }
84 > }
85
86 func (c *NexusEndpointClient) Create(
go.temporal.io/server/service/history/api/workflow_lease.go 16 covered LOC · 4 ranges

Open complete file

45 releaseFn historyi.ReleaseWorkflowContextFunc,
46 mutableState historyi.MutableState,
47 > ) WorkflowLease { workflow_lease.go
48 > return &workflowLease{
49 > context: wfContext,
50 > releaseFn: releaseFn,
51 > mutableState: mutableState,
52 > }
53 > }
54
55 > func (w *workflowLease) GetContext() historyi.WorkflowContext { workflow_lease.go
56 > return w.context
57 > }
58
59 > func (w *workflowLease) GetMutableState() historyi.MutableState { workflow_lease.go
60 > return w.mutableState
61 > }
62
63 > func (w *workflowLease) GetReleaseFn() historyi.ReleaseWorkflowContextFunc { workflow_lease.go
64 > return w.releaseFn
65 > }
go.temporal.io/server/service/history/outbound_queue_standby_task_executor.go 16 covered LOC · 1 range

Open complete file

41 chasmEngine chasm.Engine,
42 clientBean client.Bean,
43 > ) *outboundQueueStandbyTaskExecutor { outbound_queue_standby_task_executor.go
44 > return &outboundQueueStandbyTaskExecutor{
45 > stateMachineEnvironment: stateMachineEnvironment{
46 > shardContext: shardCtx,
47 > cache: workflowCache,
48 > logger: logger,
49 > metricsHandler: metricsHandler.WithTags(
50 > metrics.OperationTag(metrics.OperationOutboundQueueProcessorScope),
51 > ),
52 > },
53 > config: shardCtx.GetConfig(),
54 > clusterName: clusterName,
55 > chasmEngine: chasmEngine,
56 > clientBean: clientBean,
57 > }
58 > }
59
60 func (e *outboundQueueStandbyTaskExecutor) Execute(
go.temporal.io/server/service/history/transfer_queue_standby_task_executor.go 16 covered LOC · 1 range

Open complete file

58 chasmEngine chasm.Engine,
59 clientBean client.Bean,
60 > ) queues.Executor { transfer_queue_standby_task_executor.go
61 > return &transferQueueStandbyTaskExecutor{
62 > transferQueueTaskExecutorBase: newTransferQueueTaskExecutorBase(
63 > shard,
64 > workflowCache,
65 > logger,
66 > metricProvider,
67 > historyRawClient,
68 > matchingRawClient,
69 > visibilityManager,
70 > chasmEngine,
71 > ),
72 > clusterName: clusterName,
73 > clientBean: clientBean,
74 > }
75 > }
76
77 func (t *transferQueueStandbyTaskExecutor) Execute(
go.temporal.io/server/common/goro/group.go 15 covered LOC · 4 ranges

Open complete file

27 // exit on their own (possibly never).
28 // NOTE: Errors returned by the supplied function are ignored.
29 > func (g *Group) Go(f func(ctx context.Context) error) { group.go
30 > g.initOnce.Do(g.init)
31 > g.wg.Go(func() {
32 > _ = f(g.ctx)
33 > })
34 }
35
36 // Cancel cancels the `context.Context` that was passed to all goroutines
37 // spawned via `Go` on this `Group`.
38 > func (g *Group) Cancel() { group.go
39 > g.initOnce.Do(g.init)
40 > g.cancel()
41 > }
42
43 // Wait blocks waiting for all goroutines spawned via `Go` on this `Group`
44 // instance to complete. If `Go` has not been called then this function returns
45 // immediately.
46 > func (g *Group) Wait() { group.go
47 > g.wg.Wait()
48 > }
49
50 > func (g *Group) init() { group.go
51 > g.ctx, g.cancel = context.WithCancel(context.Background())
52 > }
go.temporal.io/server/common/persistence/sql/sqlplugin/visibility.go 15 covered LOC · 5 ranges

Open complete file

130 }
131
132 > func (vsa VisibilitySearchAttributes) Value() (driver.Value, error) { visibility.go
133 > if vsa == nil {
134 return nil, nil
135 }
136 > bs, err := json.Marshal(vsa) visibility.go
137 > if err != nil {
138 return nil, err
139 }
140 > return string(bs), nil visibility.go
141 }
142
219 }
220
221 > func getDbFields() []string { visibility.go
222 > t := reflect.TypeFor[VisibilityRow]()
223 > dbFields := make([]string, t.NumField())
224 > for i := 0; i < t.NumField(); i++ {
225 > f := t.Field(i)
226 > dbFields[i] = f.Tag.Get("db")
227 > if dbFields[i] == "" {
228 > dbFields[i] = strcase.ToSnake(f.Name)
229 > }
230 }
231 > return dbFields visibility.go
232 }
233
go.temporal.io/server/common/persistence/visibility/store/sql/query_converter_util_legacy.go 15 covered LOC · 3 ranges

Open complete file

68 }
69
70 > func newColName(name string) *colName { query_converter_util_legacy.go
71 > return &colName{Name: name}
72 > }
73
74 func newSAColName(
77 fieldName string,
78 valueType enumspb.IndexedValueType,
79 > ) *saColName { query_converter_util_legacy.go
80 > return &saColName{
81 > dbColName: newColName(dbColName),
82 > alias: alias,
83 > fieldName: fieldName,
84 > valueType: valueType,
85 > }
86 > }
87
88 func newFuncExpr(name string, exprs ...sqlparser.Expr) *sqlparser.FuncExpr {
105 }
106
107 > func getMaxDatetimeValue() time.Time { query_converter_util_legacy.go
108 > t, _ := time.Parse(time.RFC3339, "9999-12-31T23:59:59Z")
109 > return t
110 > }
111
112 // formatComparisonExprStringForError formats comparison expression after
go.temporal.io/server/common/rpc/interceptor/retry.go 15 covered LOC · 3 ranges

Open complete file

20 policy backoff.RetryPolicy,
21 isRetryable backoff.IsRetryable,
22 > ) *RetryableInterceptor { retry.go
23 > return &RetryableInterceptor{
24 > policy: policy,
25 > isRetryable: isRetryable,
26 > }
27 > }
28
29 func (i *RetryableInterceptor) Intercept(
32 info *grpc.UnaryServerInfo,
33 handler grpc.UnaryHandler,
34 > ) (any, error) { retry.go
35 > var response any
36 > op := func(ctx context.Context) error {
37 > var err error
38 > response, err = handler(ctx, req)
39 > return err
40 > }
41
42 > err := backoff.ThrottleRetryContext(ctx, op, i.policy, i.isRetryable) retry.go
43 > return response, err
44 }
go.temporal.io/server/service/history/ndc/state_rebuilder.go 15 covered LOC · 1 range

Open complete file

85 shard historyi.ShardContext,
86 logger log.Logger,
87 > ) *StateRebuilderImpl { state_rebuilder.go
88 >
89 > return &StateRebuilderImpl{
90 > shard: shard,
91 > namespaceRegistry: shard.GetNamespaceRegistry(),
92 > eventsCache: shard.GetEventsCache(),
93 > clusterMetadata: shard.GetClusterMetadata(),
94 > executionMgr: shard.GetExecutionManager(),
95 > taskRefresher: workflow.NewTaskRefresher(shard),
96 > rebuiltHistorySize: 0,
97 > rebuiltExternalPayloadSize: 0,
98 > rebuiltExternalPayloadCount: 0,
99 > logger: logger,
100 > }
101 > }
102
103 func (r *StateRebuilderImpl) Rebuild(
go.temporal.io/server/service/history/tasks/fake_task.go 15 covered LOC · 3 ranges

Open complete file

23 category Category,
24 visibilityTimestamp time.Time,
25 > ) Task { fake_task.go
26 > return &FakeTask{
27 > WorkflowKey: workflowKey,
28 > TaskID: common.EmptyEventTaskID,
29 > Version: common.EmptyVersion,
30 > VisibilityTimestamp: visibilityTimestamp,
31 > Category: category,
32 > }
33 > }
34
35 func (f *FakeTask) GetKey() Key {
52 }
53
54 > func (f *FakeTask) SetTaskID(id int64) { fake_task.go
55 > f.TaskID = id
56 > }
57
58 > func (f *FakeTask) GetVisibilityTime() time.Time { fake_task.go
59 > return f.VisibilityTimestamp
60 > }
61
62 func (f *FakeTask) SetVisibilityTime(t time.Time) {
go.temporal.io/server/service/history/timer_queue_active_task_executor.go 15 covered LOC · 1 range

Open complete file

57 matchingRawClient resource.MatchingRawClient,
58 chasmEngine chasm.Engine,
59 > ) queues.Executor { timer_queue_active_task_executor.go
60 > return &timerQueueActiveTaskExecutor{
61 > timerQueueTaskExecutorBase: newTimerQueueTaskExecutorBase(
62 > shard,
63 > workflowCache,
64 > workflowDeleteManager,
65 > matchingRawClient,
66 > chasmEngine,
67 > logger,
68 > metricProvider,
69 > config,
70 > true,
71 > ),
72 > }
73 > }
74
75 func (t *timerQueueActiveTaskExecutor) Execute(
go.temporal.io/server/service/history/workflow/external_payload_size.go 15 covered LOC · 7 ranges

Open complete file

11
12 // CalculateExternalPayloadSize calculates the total size and count of all external payloads in the given history events.
13 > func CalculateExternalPayloadSize(events []*historypb.HistoryEvent, metricsHandler metrics.Handler) (size int64, count int64, err error) { external_payload_size.go
14 > var totalSize int64
15 > var totalCount int64
16 > visitor := func(vpc *proxy.VisitPayloadsContext, payloads []*commonpb.Payload) ([]*commonpb.Payload, error) {
17 > for _, p := range payloads { external_payload_size.go
18 > totalCount += int64(len(p.ExternalPayloads)) external_payload_size.go
19 > for _, extPayload := range p.ExternalPayloads {
20 totalSize += extPayload.SizeBytes
21 metricsHandler.Histogram(metrics.ExternalPayloadUploadSize.Name(), metrics.Bytes).Record(int64(extPayload.SizeBytes))
22 }
23 }
24 > return payloads, nil external_payload_size.go
25 }
26
27 > for _, event := range events { external_payload_size.go
28 > err := proxy.VisitPayloads(context.Background(), event, proxy.VisitPayloadsOptions{ external_payload_size.go
29 > Visitor: visitor,
30 > SkipSearchAttributes: true,
31 > })
32 > if err != nil {
33 return 0, 0, err
34 }
35 }
36 > return totalSize, totalCount, nil external_payload_size.go
37 }
go.temporal.io/server/service/history/workflow/util.go 15 covered LOC · 6 ranges

Open complete file

130 verifyChecksum func(string) error,
131 autoResetPoints *workflowpb.ResetPoints,
132 > ) (string, *workflowpb.ResetPointInfo) { util.go
133 > if autoResetPoints == nil {
134 > return "", nil util.go
135 > }
136 > now := timeSource.Now() util.go
137 > for _, p := range autoResetPoints.Points {
138 if err := verifyChecksum(p.GetBinaryChecksum()); err != nil && p.GetResettable() {
139 expireTime := timestamp.TimeValue(p.GetExpireTime())
145 }
146 }
147 > return "", nil util.go
148 }
149
178 //
179 //nolint:revive // cognitive complexity to reduce after old code clean up
180 > func GetEffectiveDeployment(versioningInfo *workflowpb.WorkflowExecutionVersioningInfo) *deploymentpb.Deployment { util.go
181 > if versioningInfo == nil {
182 > return nil
183 > } else if transition := versioningInfo.GetVersionTransition(); transition != nil {
184 if v := transition.GetDeploymentVersion(); v != nil { // v0.32
185 return worker_versioning.DeploymentFromExternalDeploymentVersion(v)
214 // 3. Behavior: this is returned when there is no override (most common case). Behavior is
215 // set based on the worker-sent deployment in the latest WFT completion.
216 > func GetEffectiveVersioningBehavior(versioningInfo *workflowpb.WorkflowExecutionVersioningInfo) enumspb.VersioningBehavior { util.go
217 > if versioningInfo == nil {
218 > return enumspb.VERSIONING_BEHAVIOR_UNSPECIFIED
219 > } else if t := versioningInfo.GetVersionTransition(); t != nil {
220 return enumspb.VERSIONING_BEHAVIOR_AUTO_UPGRADE
221 } else if override := versioningInfo.GetVersioningOverride(); override != nil {
go.temporal.io/server/service/matching/simple_partition_scaler.go 15 covered LOC · 4 ranges

Open complete file

24 }
25
26 > func newSimplePartitionScalerFactory(cfg scalerFactoryCfg) *simplePartitionScalerFactory { simple_partition_scaler.go
27 > return &simplePartitionScalerFactory{cfg: cfg}
28 > }
29
30 func (s *simplePartitionScalerFactory) New(
31 nsName namespace.Name, tqName string, tqType enumspb.TaskQueueType,
32 > ) PartitionScaler { simple_partition_scaler.go
33 > cfg := func() dynamicconfig.SimplePartitionScalerSettings { return s.cfg(nsName.String(), tqName, tqType) }
34 > return newSimplePartitionScaler(cfg, clock.NewRealTimeSource())
35 }
36
42 }
43
44 > func newSimplePartitionScaler(cfg scalerCfg, ts clock.TimeSource) *simplePartitionScaler { simple_partition_scaler.go
45 > return &simplePartitionScaler{
46 > cfg: cfg,
47 > ts: ts,
48 > trackers: make(map[time.Duration]*taskTracker),
49 > }
50 > }
51
52 func (s *simplePartitionScaler) getTracker(interval time.Duration) *taskTracker {
116 }
117
118 > func (*simplePartitionScaler) Stop() { simple_partition_scaler.go
119 > }
120
121 func (s *simplePartitionScaler) updateAddTarget(
go.temporal.io/server/service/worker/deletenamespace/reclaimresources/activities.go 15 covered LOC · 2 ranges

Open complete file

36 visibilityManager manager.VisibilityManager,
37 logger log.Logger,
38 > ) *Activities { activities.go
39 > return &Activities{
40 > visibilityManager: visibilityManager,
41 > logger: logger,
42 > }
43 > }
44
45 func NewLocalActivities(
48 namespaceCacheRefreshInterval dynamicconfig.DurationPropertyFn,
49 logger log.Logger,
50 > ) *LocalActivities { activities.go
51 > return &LocalActivities{
52 > visibilityManager: visibilityManager,
53 > metadataManager: metadataManager,
54 > logger: logger,
55 >
56 > namespaceCacheRefreshInterval: namespaceCacheRefreshInterval,
57 > }
58 > }
59
60 func (a *LocalActivities) IsAdvancedVisibilityActivity(_ context.Context, _ namespace.Name) (bool, error) {
go.temporal.io/server/chasm/lib/callback/tasks.go 14 covered LOC · 2 ranges

Open complete file

93 }
94
95 > func newInvocationTaskHandler(opts invocationTaskHandlerOptions) *invocationTaskHandler { tasks.go
96 > return &invocationTaskHandler{
97 > config: opts.Config,
98 > namespaceRegistry: opts.NamespaceRegistry,
99 > metricsHandler: opts.MetricsHandler,
100 > logger: opts.Logger,
101 > httpCallerProvider: opts.HTTPCallerProvider,
102 > httpTraceProvider: opts.HTTPTraceProvider,
103 > historyClient: opts.HistoryClient,
104 > }
105 > }
106
107 func (h *invocationTaskHandler) Validate(ctx chasm.Context, cb *Callback, attrs chasm.TaskInvocation, task *callbackspb.InvocationTask) (bool, error) {
157 }
158
159 > func newBackoffTaskHandler(opts backoffTaskHandlerOptions) *backoffTaskHandler { tasks.go
160 > return &backoffTaskHandler{}
161 > }
162
163 // Execute toggles the callback status from BACKING_OFF to SCHEDULED to trigger a new invocation attempt.
go.temporal.io/server/chasm/lib/scheduler/scheduler_tasks.go 14 covered LOC · 2 ranges

Open complete file

41 }
42
43 > func NewSchedulerIdleTaskHandler(opts SchedulerIdleTaskHandlerOptions) *SchedulerIdleTaskHandler { scheduler_tasks.go
44 > return &SchedulerIdleTaskHandler{
45 > config: opts.Config,
46 > metricsHandler: opts.MetricsHandler,
47 > baseLogger: opts.BaseLogger,
48 > }
49 > }
50
51 func (r *SchedulerIdleTaskHandler) Execute(
134 }
135
136 > func NewSchedulerCallbacksTaskHandler(opts SchedulerCallbacksTaskHandlerOptions) *SchedulerCallbacksTaskHandler { scheduler_tasks.go
137 > return &SchedulerCallbacksTaskHandler{
138 > config: opts.Config,
139 > historyClient: opts.HistoryClient,
140 > frontendClient: opts.FrontendClient,
141 > }
142 > }
143
144 // watchResult holds the outcome of watchRunningStart for a single BufferedStart.
go.temporal.io/server/chasm/library.go 14 covered LOC · 5 ranges

Open complete file

34 }
35
36 > func (UnimplementedLibrary) Tasks() []*RegistrableTask { library.go
37 > return nil
38 > }
39
40 // RegisterServices Registers the gRPC calls to the handlers of the library.
41 > func (UnimplementedLibrary) RegisterServices(_ *grpc.Server) { library.go
42 > }
43
44 > func (UnimplementedLibrary) NexusServices() []*nexus.Service { library.go
45 > return nil
46 > }
47
48 > func (UnimplementedLibrary) NexusServiceProcessors() []*NexusServiceProcessor { library.go
49 > return nil
50 > }
51
52 func (UnimplementedLibrary) mustEmbedUnimplementedLibrary() {}
56 // tasks within the CHASM framework.
57 // The format of the returned FQN is: "libName.name"
58 > func FullyQualifiedName(libName, name string) string { library.go
59 > return libName + "." + name
60 > }
go.temporal.io/server/common/build/build.go 14 covered LOC · 2 ranges

Open complete file

27 )
28
29 > func init() { build.go
30 > buildInfo, ok := debug.ReadBuildInfo()
31 > if !ok {
32 return
33 }
34
35 > InfoData.Available = true build.go
36 > InfoData.GoVersion = buildInfo.GoVersion
37 >
38 > for _, setting := range buildInfo.Settings {
39 > switch setting.Key {
40 > case "GOARCH":
41 > InfoData.GoArch = setting.Value
42 > case "GOOS":
43 > InfoData.GoOs = setting.Value
44 > case "CGO_ENABLED":
45 > InfoData.CgoEnabled = setting.Value == "1"
46 case "vcs.revision":
47 InfoData.GitRevision = setting.Value
go.temporal.io/server/common/config/fx.go 14 covered LOC · 4 ranges

Open complete file

15 )
16
17 > func provideRPCConfig(cfg *Config, svcName primitives.ServiceName) *RPC { fx.go
18 > c := cfg.Services[string(svcName)].RPC
19 >
20 > return &c
21 > }
22
23 > func provideMembershipConfig(cfg *Config) *Membership { fx.go
24 > return &cfg.Global.Membership
25 > }
26
27 > func provideServicePortMap(cfg *Config) ServicePortMap { fx.go
28 > servicePortMap := make(ServicePortMap)
29 > for sn, sc := range cfg.Services {
30 > servicePortMap[primitives.ServiceName(sn)] = sc.RPC.GRPCPort
31 > }
32
33 > return servicePortMap fx.go
34 }
go.temporal.io/server/common/persistence/json_history_token_serializer.go 14 covered LOC · 2 ranges

Open complete file

23
24 // newJSONHistoryTokenSerializer creates a new instance of TaskTokenSerializer
25 > func newJSONHistoryTokenSerializer() *jsonHistoryTokenSerializer { json_history_token_serializer.go
26 > return &jsonHistoryTokenSerializer{}
27 > }
28
29 func (t *historyPagingToken) SetRangeIndexes(
49 defaultLastNodeID int64,
50 defaultLastTransactionID int64,
51 > ) (*historyPagingToken, error) { json_history_token_serializer.go
52 >
53 > if len(data) == 0 {
54 > token := historyPagingToken{
55 > LastEventID: defaultLastEventID,
56 > CurrentRangeIndex: notStartedIndex,
57 > LastNodeID: defaultLastNodeID,
58 > LastTransactionID: defaultLastTransactionID,
59 > }
60 > return &token, nil
61 > }
62
63 token := historyPagingToken{}
go.temporal.io/server/common/rpc/interceptor/routing_key_extractor_gen.go 14 covered LOC · 7 ranges

Open complete file

11 // from a WorkflowService request using field paths declared in the
12 // temporal.api.protometa.v1.request_header proto annotation.
13 > func workflowServiceRequestRoutingKey(req any) namespace.RoutingKey { routing_key_extractor_gen.go
14 > switch r := req.(type) {
15 case *workflowservice.CreateScheduleRequest:
16 return namespace.RoutingKey{ID: r.GetScheduleId()}
43 case *workflowservice.FetchWorkerConfigRequest:
44 return namespace.RoutingKey{ID: routingIDFromResourceID(r.GetResourceId())}
45 > case *workflowservice.GetWorkflowExecutionHistoryRequest: routing_key_extractor_gen.go
46 > return namespace.RoutingKey{ID: r.GetExecution().GetWorkflowId()}
47 case *workflowservice.GetWorkflowExecutionHistoryReverseRequest:
48 return namespace.RoutingKey{ID: r.GetExecution().GetWorkflowId()}
61 case *workflowservice.PollActivityExecutionRequest:
62 return namespace.RoutingKey{ID: r.GetActivityId()}
63 > case *workflowservice.PollActivityTaskQueueRequest: routing_key_extractor_gen.go
64 > return namespace.RoutingKey{ID: r.GetPollerGroupId(), Strategy: namespace.RoutingStrategyPollerGroup}
65 case *workflowservice.PollNexusTaskQueueRequest:
66 return namespace.RoutingKey{ID: r.GetPollerGroupId(), Strategy: namespace.RoutingStrategyPollerGroup}
67 case *workflowservice.PollWorkflowExecutionUpdateRequest:
68 return namespace.RoutingKey{ID: r.GetUpdateRef().GetWorkflowExecution().GetWorkflowId()}
69 > case *workflowservice.PollWorkflowTaskQueueRequest: routing_key_extractor_gen.go
70 > return namespace.RoutingKey{ID: r.GetPollerGroupId(), Strategy: namespace.RoutingStrategyPollerGroup}
71 case *workflowservice.QueryWorkflowRequest:
72 return namespace.RoutingKey{ID: r.GetExecution().GetWorkflowId()}
107 case *workflowservice.RespondQueryTaskCompletedRequest:
108 return namespace.RoutingKey{ID: r.GetPollerGroupId(), Strategy: namespace.RoutingStrategyPollerGroup}
109 > case *workflowservice.RespondWorkflowTaskCompletedRequest: routing_key_extractor_gen.go
110 > return namespace.RoutingKey{ID: routingIDFromResourceID(r.GetResourceId())}
111 case *workflowservice.RespondWorkflowTaskFailedRequest:
112 return namespace.RoutingKey{ID: routingIDFromResourceID(r.GetResourceId())}
125 case *workflowservice.StartBatchOperationRequest:
126 return namespace.RoutingKey{ID: r.GetJobId()}
127 > case *workflowservice.StartWorkflowExecutionRequest: routing_key_extractor_gen.go
128 > return namespace.RoutingKey{ID: r.GetWorkflowId()}
129 case *workflowservice.StopBatchOperationRequest:
130 return namespace.RoutingKey{ID: r.GetJobId()}
157 case *workflowservice.UpdateWorkflowExecutionRequest:
158 return namespace.RoutingKey{ID: r.GetWorkflowExecution().GetWorkflowId()}
160 > return namespace.RoutingKey{}
161 }
162 }
go.temporal.io/server/common/searchattribute/encode.go 14 covered LOC · 6 ranges

Open complete file

57 typeMap *NameTypeMap,
58 allowList bool,
59 > ) (map[string]any, error) { encode.go
60 > if len(searchAttributes.GetIndexedFields()) == 0 {
61 return nil, nil
62 }
63
64 > result := make(map[string]any, len(searchAttributes.GetIndexedFields())) encode.go
65 > var lastErr error
66 > for saName, saPayload := range searchAttributes.GetIndexedFields() {
67 > saType := enumspb.INDEXED_VALUE_TYPE_UNSPECIFIED
68 > if typeMap != nil {
69 > var err error encode.go
70 > saType, err = typeMap.getType(saName, customCategory|predefinedCategory)
71 > if err != nil {
72 if sadefs.IsChasmSearchAttribute(saName) {
73 // Chasm search attributes are not in the standard type map;
89 }
90
91 > searchAttributeValue, err := sadefs.DecodeValue(saPayload, saType, allowList) encode.go
92 > if err != nil {
93 lastErr = err
94 result[saName] = nil
95 continue
96 }
97 > result[saName] = searchAttributeValue encode.go
98 }
99
100 > return result, lastErr encode.go
101 }
go.temporal.io/server/common/taskqueue/stats.go 14 covered LOC · 7 ranges

Open complete file

7
8 // MergeStats merges from into into. Mutates into.
9 > func MergeStats(into, from *taskqueuepb.TaskQueueStats) { stats.go
10 > if from == nil {
11 return
12 }
13 > into.ApproximateBacklogCount += from.ApproximateBacklogCount stats.go
14 > into.ApproximateBacklogAge = oldestBacklogAge(into.ApproximateBacklogAge, from.ApproximateBacklogAge)
15 > into.TasksAddRate += from.TasksAddRate
16 > into.TasksDispatchRate += from.TasksDispatchRate
17 > into.RateLimitingActive = into.RateLimitingActive || from.RateLimitingActive
18 }
19
31 }
32
33 > func oldestBacklogAge(left, right *durationpb.Duration) *durationpb.Duration { stats.go
34 > if left == nil {
35 left = durationpb.New(0)
36 }
37 > if right == nil { stats.go
38 right = durationpb.New(0)
39 }
40 > if left.AsDuration() > right.AsDuration() { stats.go
41 > return left stats.go
42 > }
43 > return right stats.go
44 }
go.temporal.io/server/service/worker/dummy/fx.go 14 covered LOC · 3 ranges

Open complete file

18 var Module = fx.Options(fx.Provide(NewResult))
19
20 > func NewResult() fxResult { fx.go
21 > return fxResult{
22 > Component: &workerComponent{},
23 > }
24 > }
25
26 > func (c *workerComponent) Register(registry sdkworker.Registry, ns *namespace.Namespace, _ workercommon.RegistrationDetails) func() { fx.go
27 > registry.RegisterWorkflowWithOptions(DummyWorkflow, workflow.RegisterOptions{Name: DummyWFTypeName})
28 > return nil
29 > }
30
31 > func (c *workerComponent) DedicatedWorkerOptions(ns *namespace.Namespace) *workercommon.PerNSDedicatedWorkerOptions { fx.go
32 > return &workercommon.PerNSDedicatedWorkerOptions{
33 > Enabled: true,
34 > }
35 > }
go.temporal.io/server/temporal/environment/env.go 14 covered LOC · 5 ranges

Open complete file

39 )
40
41 > func lookupLocalhostIP(domain string) string { env.go
42 > // lookup localhost and favor the first ipv4 address
43 > // unless there are only ipv6 addresses available
44 > ips, err := net.LookupIP(domain)
45 > if err != nil || len(ips) == 0 {
46 // fallback to default instead of error
47 return localhostIPDefault
48 }
49 > for _, ip := range ips { env.go
50 > if ip4 := ip.To4(); ip4 != nil {
51 > return ip4.String() env.go
52 > }
53 }
54 return ips[len(ips)-1].String()
56
57 // GetLocalhostIP returns the ip address of the localhost domain
58 > func GetLocalhostIP() string { env.go
59 > localhostIP := os.Getenv(localhostIPEnv)
60 > ip := net.ParseIP(localhostIP)
61 > if ip != nil {
62 // if localhost is an ip return it
63 return ip.String()
64 }
65 // otherwise, ignore the value and lookup `localhost`
66 > return lookupLocalhostIP("localhost") env.go
67 }
68
go.temporal.io/server/chasm/lib/activity/frontend.go 13 covered LOC · 1 range

Open complete file

65 saMapperProvider searchattribute.MapperProvider,
66 saValidator *searchattribute.Validator,
67 > ) FrontendHandler { frontend.go
68 > return &frontendHandler{
69 > callbackValidator: callbackValidator,
70 > linkValidator: linkValidator,
71 > client: client,
72 > config: config,
73 > logger: logger,
74 > metricsHandler: metricsHandler,
75 > namespaceRegistry: namespaceRegistry,
76 > saMapperProvider: saMapperProvider,
77 > saValidator: saValidator,
78 > }
79 > }
80
81 // IsStandaloneActivityEnabled checks if standalone activities are enabled for the given namespace
go.temporal.io/server/chasm/lib/nexusoperation/task_handler_base.go 13 covered LOC · 1 range

Open complete file

53 }
54
55 > func (o InvocationTaskHandlerOptions) toBase() nexusTaskHandlerBase { task_handler_base.go
56 > return nexusTaskHandlerBase{
57 > config: o.Config,
58 > namespaceRegistry: o.NamespaceRegistry,
59 > metricsHandler: o.MetricsHandler,
60 > logger: o.Logger,
61 > clientProvider: o.ClientProvider,
62 > endpointRegistry: o.EndpointRegistry,
63 > httpTraceProvider: o.HTTPTraceProvider,
64 > historyClient: o.HistoryClient,
65 > chasmRegistry: o.ChasmRegistry,
66 > }
67 > }
68
69 // nexusTaskHandlerBase contains common dependencies shared by the invocation and cancellation task handlers.
go.temporal.io/server/common/archiver/provider/provider.go 13 covered LOC · 1 range

Open complete file

107 logger log.Logger,
108 metricsHandler metrics.Handler,
109 > ) ArchiverProvider { provider.go
110 > return &archiverProvider{
111 > historyArchiverConfigs: historyArchiverConfigs,
112 > visibilityArchiverConfigs: visibilityArchiverConfigs,
113 > executionManager: executionManager,
114 > logger: logger,
115 > metricsHandler: metricsHandler,
116 > customHistoryArchiverFactory: customHistoryArchiverFactory,
117 > customVisibilityArchiverFactory: customVisibilityArchiverFactory,
118 > historyArchivers: make(map[string]archiver.HistoryArchiver),
119 > visibilityArchivers: make(map[string]archiver.VisibilityArchiver),
120 > }
121 > }
122
123 func (p *archiverProvider) GetHistoryArchiver(scheme string) (historyArchiver archiver.HistoryArchiver, err error) {
go.temporal.io/server/common/cluster/frontend_http_client.go 13 covered LOC · 2 ranges

Open complete file

26 metadata Metadata,
27 tlsProvider tlsConfigProvider,
28 > ) *FrontendHTTPClientCache { frontend_http_client.go
29 > cache := &FrontendHTTPClientCache{
30 > metadata: metadata,
31 > tlsProvider: tlsProvider,
32 > }
33 > cache.clients = collection.NewFallibleOnceMap(cache.newClientForCluster)
34 > metadata.RegisterMetadataChangeCallback(cache, cache.evictionCallback)
35 > return cache
36 > }
37
38 // Get returns a cached HttpClient if available, or constructs a new one for the given cluster name.
92 // It invalidates clients which are either no longer present or have had their HTTP address changed.
93 // It is assumed that TLS information has not changed for clusters that are unmodified.
94 > func (c *FrontendHTTPClientCache) evictionCallback(oldClusterMetadata map[string]*ClusterInformation, newClusterMetadata map[string]*ClusterInformation) { frontend_http_client.go
95 > for oldClusterName, oldClusterInfo := range oldClusterMetadata {
96 > if oldClusterName == c.metadata.GetCurrentClusterName() || oldClusterInfo == nil {
97 > continue
98 }
99
go.temporal.io/server/common/membership/ringpop/fx.go 13 covered LOC · 4 ranges

Open complete file

13 )
14
15 > func provideFactory(lc fx.Lifecycle, params factoryParams) (*factory, error) { fx.go
16 > f, err := newFactory(params)
17 > if err != nil {
18 return nil, err
19 }
20 > lc.Append(fx.StopHook(f.closeTChannel)) fx.go
21 > return f, nil
22 }
23
24 > func provideMembership(lc fx.Lifecycle, f *factory) membership.Monitor { fx.go
25 > m := f.getMonitor()
26 > lc.Append(fx.StopHook(m.Stop))
27 > return m
28 > }
29
30 > func provideHostInfoProvider(lc fx.Lifecycle, f *factory) (membership.HostInfoProvider, error) { fx.go
31 > return f.getHostInfoProvider()
32 > }
go.temporal.io/server/common/metrics/defs_base.go 13 covered LOC · 2 ranges

Open complete file

10 }
11
12 > func newMetricDefinition(name string, opts ...Option) metricDefinition { defs_base.go
13 > d := metricDefinition{
14 > name: name,
15 > description: "",
16 > unit: "",
17 > }
18 > for _, opt := range opts {
19 > opt.apply(&d)
20 > }
21 > return d
22 }
23
24 > func (md metricDefinition) Name() string { defs_base.go
25 > return md.name
26 > }
27
28 func (md metricDefinition) Unit() MetricUnit {
go.temporal.io/server/common/namespace/mutate.go 13 covered LOC · 3 ranges

Open complete file

8 type mutationFunc func(*Namespace)
9
10 > func (f mutationFunc) apply(ns *Namespace) { mutate.go
11 > f(ns)
12 > }
13
14 // WithActiveCluster assigns the active cluster to a Namespace during a Clone
43
44 // WithGlobalFlag sets whether or not this Namespace is global.
45 > func WithGlobalFlag(b bool) Mutation { mutate.go
46 > return mutationFunc(
47 > func(ns *Namespace) {
48 > ns.replicationResolver.SetGlobalFlag(b)
49 > })
50 }
51
52 // WithNotificationVersion assigns a notification version to the Namespace.
53 > func WithNotificationVersion(v int64) Mutation { mutate.go
54 > return mutationFunc(
55 > func(ns *Namespace) {
56 > ns.notificationVersion = v
57 > })
58 }
59
go.temporal.io/server/common/nexus/nexusrpc/completion.go 13 covered LOC · 5 ranges

Open complete file

308
309 // NewCompletionHTTPHandler constructs an [http.Handler] from given options for handling operation completion requests.
310 > func NewCompletionHTTPHandler(options CompletionHandlerOptions) http.Handler { completion.go
311 > if options.Logger == nil {
312 options.Logger = slog.Default()
313 }
314 > if options.Serializer == nil { completion.go
315 options.Serializer = nexus.DefaultSerializer()
316 }
317 > if options.FailureConverter == nil { completion.go
318 > options.FailureConverter = DefaultFailureConverter() completion.go
319 > }
320 > return &completionHTTPHandler{ completion.go
321 > options: options,
322 > BaseHTTPHandler: BaseHTTPHandler{
323 > Logger: options.Logger,
324 > FailureConverter: options.FailureConverter,
325 > },
326 > }
327 }
go.temporal.io/server/common/persistence/versionhistory/version_history_item.go 13 covered LOC · 8 ranges

Open complete file

8
9 // NewVersionHistoryItem create a new instance of VersionHistoryItem.
10 > func NewVersionHistoryItem(eventID int64, version int64) *historyspb.VersionHistoryItem { version_history_item.go
11 > if eventID < 0 || version < 0 {
12 panic(fmt.Sprintf("invalid version history item event ID: %v, version: %v", eventID, version))
13 }
14
15 > return &historyspb.VersionHistoryItem{EventId: eventID, Version: version} version_history_item.go
16 }
17
18 // CopyVersionHistoryItem create a new instance of VersionHistoryItem.
19 > func CopyVersionHistoryItem(item *historyspb.VersionHistoryItem) *historyspb.VersionHistoryItem { version_history_item.go
20 > return NewVersionHistoryItem(item.EventId, item.Version)
21 > }
22
23 // IsEqualVersionHistoryItem checks whether version history items are equal
40
41 // CompareVersionHistoryItem compares 2 version history items
42 > func CompareVersionHistoryItem(item1 *historyspb.VersionHistoryItem, item2 *historyspb.VersionHistoryItem) int { version_history_item.go
43 > if item1.Version < item2.Version {
44 return -1
45 }
46 > if item1.Version > item2.Version { version_history_item.go
47 return 1
48 }
49
50 // item1.Version == item2.Version
51 > if item1.EventId < item2.EventId { version_history_item.go
52 return -1
53 }
54 > if item1.EventId > item2.EventId { version_history_item.go
55 > return 1 version_history_item.go
56 > }
57 return 0
58 }
go.temporal.io/server/common/predicates/universal.go 13 covered LOC · 4 ranges

Open complete file

5 )
6
7 > func Universal[T any]() Predicate[T] { universal.go
8 > return &UniversalImpl[T]{}
9 > }
10
11 > func (a *UniversalImpl[T]) Test(t T) bool { universal.go
12 > return true
13 > }
14
15 func (a *UniversalImpl[T]) Equals(
16 predicate Predicate[T],
17 > ) bool { universal.go
18 > _, ok := predicate.(*UniversalImpl[T])
19 > return ok
20 > }
21
22 > func (*UniversalImpl[T]) Size() int { universal.go
23 > return EmptyPredicateProtoSize
24 > }
go.temporal.io/server/common/rpc/interceptor/frontend_service_error.go 13 covered LOC · 4 ranges

Open complete file

26 func NewFrontendServiceErrorInterceptor(
27 logger log.Logger,
28 > ) grpc.UnaryServerInterceptor { frontend_service_error.go
29 > return func(
30 > ctx context.Context,
31 > req any,
32 > info *grpc.UnaryServerInfo,
33 > handler grpc.UnaryHandler,
34 > ) (any, error) {
35 > resp, err := handler(ctx, req)
36 > if err == nil {
37 > return resp, nil frontend_service_error.go
38 > }
39
40 > switch serviceErr := err.(type) { frontend_service_error.go
41 case *serviceerrors.ShardOwnershipLost:
42 err = serviceerror.NewUnavailable("shard unavailable, please backoff and retry")
go.temporal.io/server/common/tasktoken/token.go 13 covered LOC · 1 range

Open complete file

17 clock *clockspb.VectorClock,
18 version int64,
19 > ) *tokenspb.Task { token.go
20 > return &tokenspb.Task{
21 > NamespaceId: namespaceID,
22 > WorkflowId: workflowID,
23 > RunId: runID,
24 > ScheduledEventId: scheduledEventID,
25 > StartedEventId: startedEventId,
26 > StartedTime: startedTime,
27 > Attempt: attempt,
28 > Clock: clock,
29 > Version: version,
30 > }
31 > }
32
33 func NewActivityTaskToken(
go.temporal.io/server/common/telemetry/env.go 13 covered LOC · 5 ranges

Open complete file

29 func SpanExportersFromEnv(
30 envVars envVarLookup,
31 > ) (map[SpanExporterType]otelsdktrace.SpanExporter, error) { env.go
32 > exporters := map[SpanExporterType]otelsdktrace.SpanExporter{}
33 >
34 > exporterTypes, ok := envVars(OtelTracesExporterTypesEnvKey)
35 > if !ok {
36 > return exporters, nil env.go
37 > }
38
39 for exporterType := range strings.SplitSeq(exporterTypes, ",") {
64 rsn primitives.ServiceName,
65 envVars envVarLookup,
66 > ) string { env.go
67 > // map "internal-frontend" to "frontend" for the purpose of tracing
68 > if rsn == primitives.InternalFrontendService {
69 rsn = primitives.FrontendService
70 }
71
72 // allow custom prefix via env vars
73 > serviceNamePrefix := "io.temporal" env.go
74 > if customServicePrefix, found := envVars(OtelServiceNameEnvKey); found {
75 serviceNamePrefix = customServicePrefix
76 }
77
78 > return fmt.Sprintf("%s.%s", serviceNamePrefix, string(rsn)) env.go
79 }
go.temporal.io/server/service/frontend/version_checker.go 13 covered LOC · 3 ranges

Open complete file

36 clusterMetadataManager persistence.ClusterMetadataManager,
37 sdkVersionRecorder *interceptor.SDKVersionInterceptor,
38 > ) *VersionChecker { version_checker.go
39 > return &VersionChecker{
40 > config: config,
41 > shutdownChan: make(chan struct{}),
42 > metricsHandler: metricsHandler.WithTags(metrics.OperationTag(metrics.VersionCheckScope)),
43 > clusterMetadataManager: clusterMetadataManager,
44 > sdkVersionRecorder: sdkVersionRecorder,
45 > }
46 > }
47
48 > func (vc *VersionChecker) Start() { version_checker.go
49 > if vc.config.EnableServerVersionCheck() {
50 vc.startOnce.Do(func() {
51 // TODO: specify a timeout for the context
60 }
61
62 > func (vc *VersionChecker) Stop() { version_checker.go
63 > if vc.config.EnableServerVersionCheck() {
64 vc.stopOnce.Do(func() {
65 close(vc.shutdownChan)
go.temporal.io/server/service/history/replication/eventhandler/resend_handler.go 13 covered LOC · 1 range

Open complete file

63 logger log.Logger,
64 config *configs.Config,
65 > ) ResendHandler { resend_handler.go
66 > return &resendHandlerImpl{
67 > namespaceRegistry: namespaceRegistry,
68 > clientBean: clientBean,
69 > serializer: serializer,
70 > engineProvider: historyEngineProvider,
71 > remoteHistoryFetcher: remoteHistoryFetcher,
72 > eventImporter: importer,
73 > logger: logger,
74 > clusterMetadata: clusterMetadata,
75 > config: config,
76 > }
77 > }
78
79 // ResendHistoryEvents is used to retrieve history events from remote and apply to current(passive) cluster. Mostly handle 3 cases:
go.temporal.io/server/service/history/workflow/mutable_state_state_status.go 13 covered LOC · 6 ranges

Open complete file

18 state enumsspb.WorkflowExecutionState,
19 status enumspb.WorkflowExecutionStatus,
21 > switch e.GetState() {
22 case enumsspb.WORKFLOW_EXECUTION_STATE_VOID:
23 // no validation
24 > case enumsspb.WORKFLOW_EXECUTION_STATE_CREATED: mutable_state_state_status.go
25 > switch state {
26 case enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:
27 if status != enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING {
29 }
30
31 > case enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING: mutable_state_state_status.go
32 > if status != enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING && status != enumspb.WORKFLOW_EXECUTION_STATUS_PAUSED {
33 return invalidStateTransitionErr(e.GetState(), state, status)
34 }
49 return serviceerror.NewInternalf("unknown workflow state: %v", state)
50 }
51 > case enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING: mutable_state_state_status.go
52 > switch state {
53 case enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:
54 return invalidStateTransitionErr(e.GetState(), state, status)
59 }
60
61 > case enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: mutable_state_state_status.go
62 > if status == enumspb.WORKFLOW_EXECUTION_STATUS_RUNNING || status == enumspb.WORKFLOW_EXECUTION_STATUS_PAUSED {
63 return invalidStateTransitionErr(e.GetState(), state, status)
64 }
go.temporal.io/server/service/matching/poller_history.go 13 covered LOC · 2 ranges

Open complete file

28 }
29
30 > func newPollerHistory(pollerHistoryTTL time.Duration) *pollerHistory { poller_history.go
31 > opts := &cache.Options{
32 > TTL: pollerHistoryTTL,
33 > Pin: false,
34 > }
35 >
36 > return &pollerHistory{
37 > history: cache.New(pollerHistoryInitMaxSize, opts),
38 > }
39 > }
40
41 > func (pollers *pollerHistory) updatePollerInfo(id pollerIdentity, pollMetadata *pollMetadata) { poller_history.go
42 > pollers.history.Put(id, &pollerInfo{pollMetadata: *pollMetadata})
43 > }
44
45 func (pollers *pollerHistory) removePoller(id pollerIdentity) {
go.temporal.io/server/service/matching/rate_limit_fraction_provider.go 13 covered LOC · 5 ranges

Open complete file

21 type TaskQueueRateLimitFractionProviderFunc func(nsName namespace.Name, tqName string, tqType enumspb.TaskQueueType) float64
22
23 > func (f TaskQueueRateLimitFractionProviderFunc) GetRateLimitFraction(nsName namespace.Name, tqName string, tqType enumspb.TaskQueueType) float64 { rate_limit_fraction_provider.go
24 > return f(nsName, tqName, tqType)
25 > }
26
27 // NewTaskQueueRateLimitFractionProvider wraps inner and enforces [0.0, 1.0] on every call.
28 > func NewTaskQueueRateLimitFractionProvider(inner TaskQueueRateLimitFractionProvider) TaskQueueRateLimitFractionProvider { rate_limit_fraction_provider.go
29 > return TaskQueueRateLimitFractionProviderFunc(func(nsName namespace.Name, tqName string, tqType enumspb.TaskQueueType) float64 {
30 > return max(min(inner.GetRateLimitFraction(nsName, tqName, tqType), maxRateLimitFraction), minRateLimitFraction) rate_limit_fraction_provider.go
31 > })
32 }
33
34 type unitRateLimitFractionProvider struct{}
35
36 > func (p *unitRateLimitFractionProvider) GetRateLimitFraction(_ namespace.Name, _ string, _ enumspb.TaskQueueType) float64 { rate_limit_fraction_provider.go
37 > return defaultRateLimitFraction
38 > }
39
40 var defaultTaskQueueRateLimitFractionProvider = NewTaskQueueRateLimitFractionProvider(&unitRateLimitFractionProvider{})
41
42 > func taskQueueRateLimitFractionProviderProvider() TaskQueueRateLimitFractionProvider { rate_limit_fraction_provider.go
43 > return defaultTaskQueueRateLimitFractionProvider
44 > }
go.temporal.io/server/chasm/lib/nexusoperation/cancellation_tasks.go 12 covered LOC · 2 ranges

Open complete file

80 }
81
82 > func newCancellationInvocationTaskHandler(opts cancellationInvocationTaskHandlerOptions) *cancellationInvocationTaskHandler { cancellation_tasks.go
83 > return &cancellationInvocationTaskHandler{
84 > nexusTaskHandlerBase: opts.toBase(),
85 > }
86 > }
87
88 func (h *cancellationInvocationTaskHandler) Validate(
205 }
206
207 > func newCancellationBackoffTaskHandler(opts commonTaskHandlerOptions) *cancellationBackoffTaskHandler { cancellation_tasks.go
208 > return &cancellationBackoffTaskHandler{
209 > config: opts.Config,
210 > metricsHandler: opts.MetricsHandler,
211 > logger: opts.Logger,
212 > }
213 > }
214
215 func (h *cancellationBackoffTaskHandler) Validate(
go.temporal.io/server/chasm/lib/scheduler/config.go 12 covered LOC · 4 ranges

Open complete file

48
49 // contextValues builds the CHASM context values exposed to scheduler components.
50 > func (c *Config) contextValues() map[any]any { config.go
51 > var tweakables dynamicconfig.TypedPropertyFnWithNamespaceFilter[Tweakables]
52 > if c != nil {
53 > tweakables = c.Tweakables config.go
54 > }
55 > return map[any]any{tweakablesCtxKey: tweakables} config.go
56 }
57
98 )
99
100 > func ConfigProvider(dc *dynamicconfig.Collection) *Config { config.go
101 > return &Config{
102 > Tweakables: CurrentTweakables.Get(dc),
103 > ServiceCallTimeout: ServiceCallTimeout.Get(dc),
104 > EncodeInternalTokenWithEnvelope: callback.EncodeInternalTokenWithEnvelope.Get(dc),
105 > RetryPolicy: func() backoff.RetryPolicy {
106 return backoff.NewExponentialRetryPolicy(
107 RetryPolicyInitialInterval.Get(dc)(),
go.temporal.io/server/common/backoff/jitter.go 12 covered LOC · 4 ranges

Open complete file

4
5 // FullJitter return random number from 0 to input, inclusive, exclusive
6 > func FullJitter[T ~int64 | ~int | ~int32 | ~float64 | ~float32](input T) T { jitter.go
7 > return T(rand.Float64() * float64(input))
8 > }
9
10 // Jitter return random number from (1-coefficient)*input to (1+coefficient)*input, inclusive, exclusive
11 > func Jitter[T ~int64 | ~int | ~int32 | ~float64 | ~float32](input T, coefficient float64) T { jitter.go
12 > validateCoefficient(coefficient)
13 >
14 > if coefficient == 0 {
15 return input
16 }
17
18 > base := float64(input) * (1 - coefficient) jitter.go
19 > addon := rand.Float64() * 2 * (float64(input) - base)
20 > return T(base + addon)
21 }
22
23 > func validateCoefficient(coefficient float64) { jitter.go
24 > if coefficient < 0 || coefficient > 1 {
25 panic("coefficient cannot be < 0 or > 1")
26 }
go.temporal.io/server/common/cluster/fx.go 12 covered LOC · 3 ranges

Open complete file

12 fx.Invoke(MetadataLifetimeHooks),
13 fx.Provide(fx.Annotate(
14 > func(p Metadata) pingable.Pingable { return p }, fx.go
15 fx.ResultTags(`group:"deadlockDetectorRoots"`),
16 )),
20 lc fx.Lifecycle,
21 clusterMetadata Metadata,
22 > ) { fx.go
23 > lc.Append(
24 > fx.Hook{
25 > OnStart: func(context.Context) error {
26 > clusterMetadata.Start()
27 > return nil
28 > },
29 > OnStop: func(context.Context) error { fx.go
30 > clusterMetadata.Stop()
31 > return nil
32 > },
33 },
34 )
go.temporal.io/server/common/collection/oncemap.go 12 covered LOC · 2 ranges

Open complete file

13 // NewOnceMap creates a [OnceMap] from a given construct function.
14 // construct should be kept light as it is called while holding a lock on the entire map.
15 > func NewOnceMap[K comparable, T any](construct func(K) T) *OnceMap[K, T] { oncemap.go
16 > return &OnceMap[K, T]{
17 > construct: construct,
18 > inner: make(map[K]T, 0),
19 > }
20 > }
21
22 func (m *OnceMap[K, T]) Get(key K) T {
47 // NewFallibleOnceMap creates a [FallibleOnceMap] from a given construct function.
48 // construct should be kept light as it is called while holding a lock on the entire map.
49 > func NewFallibleOnceMap[K comparable, T any](construct func(K) (T, error)) *FallibleOnceMap[K, T] { oncemap.go
50 > return &FallibleOnceMap[K, T]{
51 > construct: construct,
52 > inner: make(map[K]T, 0),
53 > }
54 > }
55
56 func (p *FallibleOnceMap[K, T]) Get(key K) (T, error) {
go.temporal.io/server/common/config/archival.go 12 covered LOC · 4 ranges

Open complete file

15
16 // Validate validates the archival config
17 > func (a *Archival) Validate(namespaceDefaults *ArchivalNamespaceDefaults) error { archival.go
18 > if !isArchivalConfigValid(a.History.State, a.History.EnableRead, namespaceDefaults.History.State, namespaceDefaults.History.URI, a.History.Provider != nil) {
19 return errors.New("invalid history archival config")
20 }
21
22 > if !isArchivalConfigValid(a.Visibility.State, a.Visibility.EnableRead, namespaceDefaults.Visibility.State, namespaceDefaults.Visibility.URI, a.Visibility.Provider != nil) { archival.go
23 return errors.New("invalid visibility archival config")
24 }
25
26 > return nil archival.go
27 }
28
33 domianDefaultURI string,
34 specifiedProvider bool,
35 > ) bool { archival.go
36 > archivalEnabled := clusterStatus == ArchivalEnabled
37 > URISet := len(domianDefaultURI) != 0
38 >
39 > validEnable := archivalEnabled && URISet && specifiedProvider
40 > validDisabled := !archivalEnabled && !enableRead && namespaceDefaultStatus != ArchivalEnabled && !URISet && !specifiedProvider
41 > return validEnable || validDisabled
42 > }
go.temporal.io/server/common/config/validator.go 12 covered LOC · 3 ranges

Open complete file

8 )
9
10 > func newValidator() *validator.Validator { validator.go
11 > validate := validator.NewValidator()
12 > _ = validate.SetValidationFunc("persistence_custom_search_attributes", validatePersistenceCustomSearchAttributes)
13 > return validate
14 > }
15
16 > func validatePersistenceCustomSearchAttributes(v any, param string) error { validator.go
17 > st := reflect.ValueOf(v)
18 > switch st.Kind() {
19 > case reflect.Map:
20 > iter := st.MapRange()
21 > for iter.Next() {
22 // key must be a string and a valid search attribute type
23 key := iter.Key()
46 return validator.ErrUnsupported
47 }
48 > return nil validator.go
49 }
go.temporal.io/server/common/dynamicconfig/registry.go 12 covered LOC · 4 ranges

Open complete file

17 )
18
19 > func register(s GenericSetting) { registry.go
20 > if globalRegistry.queried.Load() {
21 panic("dynamicconfig.New*Setting must only be called from static initializers")
22 }
23 > if globalRegistry.settings == nil { registry.go
24 > globalRegistry.settings = make(map[Key]GenericSetting)
25 > }
26 > if globalRegistry.settings[s.Key()] != nil {
27 // nolint:forbidigo // only called during static initialization
28 panic(fmt.Sprintf("duplicate registration of dynamic config key: %q", s.Key().String()))
29 }
30 > globalRegistry.settings[s.Key()] = s registry.go
31 }
32
33 > func queryRegistry(k Key) GenericSetting { registry.go
34 > if !globalRegistry.queried.Load() {
35 > globalRegistry.queried.Store(true)
36 > }
37 > return globalRegistry.settings[k]
38 }
39
go.temporal.io/server/common/goro/keyed_set.go 12 covered LOC · 3 ranges

Open complete file

15
16 // NewKeyedSet returns a new KeyedSet where all goroutines inherit a context from baseCtx.
17 > func NewKeyedSet[K comparable](baseCtx context.Context) *KeyedSet[K] { keyed_set.go
18 > return &KeyedSet[K]{
19 > baseCtx: baseCtx,
20 > cancels: make(map[K]context.CancelFunc),
21 > }
22 > }
23
24 // Sync cancels/starts goroutines as necessary so that the running set matches the set of keys
32 // returns and is removed, but the caller of f thinks it's now active. In other words, there
33 // should be one source of truth for what should be running.
34 > func (s *KeyedSet[K]) Sync(target map[K]struct{}, f func(context.Context, K)) { keyed_set.go
35 > s.lock.Lock()
36 > defer s.lock.Unlock()
37 >
38 > for key, cancel := range s.cancels {
39 if _, ok := target[key]; !ok {
40 cancel()
43 }
44
45 > for key := range target { keyed_set.go
46 if _, ok := s.cancels[key]; ok {
47 continue
go.temporal.io/server/common/namespace/nsreplication/transmission_task_handler.go 12 covered LOC · 3 ranges

Open complete file

44 namespaceReplicationQueue persistence.NamespaceReplicationQueue,
45 logger log.Logger,
46 > ) Replicator { transmission_task_handler.go
47 > return &replicator{
48 > namespaceReplicationQueue: namespaceReplicationQueue,
49 > logger: logger,
50 > }
51 > }
52
53 // HandleTransmissionTask handle transmission of the namespace replication task
64 failoverHistoy []*persistencespb.FailoverStatus,
65 forceReplicate bool,
67 >
68 > if !forceReplicate {
69 > if !isGlobalNamespace {
71 > }
72 if len(replicationConfig.Clusters) <= 1 && !replicationClusterListUpdated {
73 return nil
go.temporal.io/server/common/persistence/visibility/store/elasticsearch/visibility_store.go 12 covered LOC · 3 ranges

Open complete file

101 }
102
103 > defaultSorter = func() []elastic.Sorter { visibility_store.go
104 > ret := make([]elastic.Sorter, 0, len(defaultSorterFields))
105 > for _, item := range defaultSorterFields {
106 > fs := elastic.NewFieldSort(item.name)
107 > if item.desc {
108 > fs.Desc()
109 > }
110 > if item.missing_first {
111 > fs.Missing("_first")
112 > } else {
113 fs.Missing("_last")
114 }
115 > ret = append(ret, fs) visibility_store.go
116 }
117 > return ret visibility_store.go
118 }()
119
go.temporal.io/server/common/primitives/task_queues.go 12 covered LOC · 5 ranges

Open complete file

39
40 // IsInternalTaskQueue returns true if the task queue name belongs to an internal system task queue.
41 > func IsInternalTaskQueue(taskQueue string) bool { task_queues.go
42 > return strings.HasPrefix(taskQueue, internalTaskQueuePrefix)
43 > }
44
45 // IsInternalPerNsTaskQueue returns true if the task queue name belongs to a per-namespace internal system worker
46 > func IsInternalPerNsTaskQueue(taskQueue string) bool { task_queues.go
47 > // TODO: remove WorkerControllerPerNSWorkerTaskQueue once it has been updated to match the prefix
48 > return strings.HasPrefix(taskQueue, internalTaskQueuePerNSPrefix) || taskQueue == WorkerControllerPerNSWorkerTaskQueue
49 > }
50
51 // CheckInternalPerNsTaskQueueAllowed tries to block the usage of internal per-namespace task queue for illegal cases.
55 //
56 // Returns an error if the usage is illegal, or nil if it's allowed.
57 > func CheckInternalPerNsTaskQueueAllowed(targetTaskQueue, parentTaskQueue string) error { task_queues.go
58 > if targetTaskQueue == "" {
59 return serviceerror.NewInvalidArgument("target task queue is not set")
60 }
61 > if !IsInternalPerNsTaskQueue(targetTaskQueue) { task_queues.go
62 > return nil task_queues.go
63 > }
64 if !IsInternalPerNsTaskQueue(parentTaskQueue) {
65 errMessage := fmt.Sprintf("cannot use internal per-namespace task queue:%s", targetTaskQueue)
go.temporal.io/server/common/quotas/calculator/cluster_aware_quota_calculator.go 12 covered LOC · 6 ranges

Open complete file

32 // limit is used if and only if it is configured to a value greater than zero and the number of instances that
33 // the memberCounter reports is greater than zero. Otherwise, the per-instance limit is used.
34 > func getQuota(memberCounter MemberCounter, instanceLimit, clusterLimit int) float64 { cluster_aware_quota_calculator.go
35 > if clusterLimit > 0 && memberCounter != nil {
36 > if clusterSize := memberCounter.AvailableMemberCount(); clusterSize > 0 { cluster_aware_quota_calculator.go
37 > return float64(clusterLimit) / float64(clusterSize) cluster_aware_quota_calculator.go
38 > }
39 }
40
41 > return float64(instanceLimit) cluster_aware_quota_calculator.go
42 }
43
44 > func (l ClusterAwareQuotaCalculator) GetQuota() float64 { cluster_aware_quota_calculator.go
45 > return getQuota(l.MemberCounter, l.PerInstanceQuota(), l.GlobalQuota())
46 > }
47
48 > func (l ClusterAwareNamespaceQuotaCalculator) GetQuota(namespace string) float64 { cluster_aware_quota_calculator.go
49 > return getQuota(l.MemberCounter, l.PerInstanceQuota(namespace), l.GlobalQuota(namespace))
50 > }
go.temporal.io/server/common/quotas/priority_reservation_impl.go 12 covered LOC · 3 ranges

Open complete file

17 decidingReservation Reservation,
18 otherReservations []Reservation,
19 > ) *PriorityReservationImpl { priority_reservation_impl.go
20 > return &PriorityReservationImpl{
21 > decidingReservation: decidingReservation,
22 > otherReservations: otherReservations,
23 > }
24 > }
25
26 // OK returns whether the limiter can provide the requested number of tokens
27 > func (r *PriorityReservationImpl) OK() bool { priority_reservation_impl.go
28 > return r.decidingReservation.OK()
29 > }
30
31 // Cancel indicates that the reservation holder will not perform the reserved action
52 // DelayFrom returns the duration for which the reservation holder must wait
53 // before taking the reserved action. Zero duration means act immediately.
54 > func (r *PriorityReservationImpl) DelayFrom(now time.Time) time.Duration { priority_reservation_impl.go
55 > return r.decidingReservation.DelayFrom(now)
56 > }
go.temporal.io/server/common/rpc/interceptor/dc_redirection_policy.go 12 covered LOC · 4 ranges

Open complete file

91 namespaceRegistry namespace.Registry,
92 policy config.DCRedirectionPolicy,
93 > ) DCRedirectionPolicy { dc_redirection_policy.go
94 > switch policy.Policy {
95 case DCRedirectionPolicyDefault:
96 // default policy, noop
97 return NewNoopRedirectionPolicy(clusterMetadata.GetCurrentClusterName())
98 > case DCRedirectionPolicyNoop: dc_redirection_policy.go
99 > return NewNoopRedirectionPolicy(clusterMetadata.GetCurrentClusterName())
100 case DCRedirectionPolicySelectedAPIsForwarding:
101 currentClusterName := clusterMetadata.GetCurrentClusterName()
110
111 // NewNoopRedirectionPolicy is DC redirection policy which does nothing
112 > func NewNoopRedirectionPolicy(currentClusterName string) *NoopRedirectionPolicy { dc_redirection_policy.go
113 > return &NoopRedirectionPolicy{
114 > currentClusterName: currentClusterName,
115 > }
116 > }
117
118 // WithNamespaceIDRedirect redirect the API call based on namespace ID
122
123 // WithNamespaceRedirect redirect the API call based on namespace name
124 > func (policy *NoopRedirectionPolicy) WithNamespaceRedirect(_ context.Context, _ namespace.Name, _ string, _ any, call func(string) error) error { dc_redirection_policy.go
125 > return call(policy.currentClusterName)
126 > }
127
128 // NewSelectedAPIsForwardingPolicy creates a forwarding policy for selected APIs based on namespace
go.temporal.io/server/common/rpc/interceptor/health.go 12 covered LOC · 4 ranges

Open complete file

23
24 // NewHealthInterceptor returns a new HealthInterceptor. It starts with state not healthy.
25 > func NewHealthInterceptor() *HealthInterceptor { health.go
26 > return &HealthInterceptor{}
27 > }
28
29 func (i *HealthInterceptor) Intercept(
32 info *grpc.UnaryServerInfo,
33 handler grpc.UnaryHandler,
34 > ) (any, error) { health.go
35 > // only enforce health check on WorkflowService and OperatorService
36 > if strings.HasPrefix(info.FullMethod, api.WorkflowServicePrefix) ||
37 > strings.HasPrefix(info.FullMethod, api.OperatorServicePrefix) {
38 > if !i.healthy.Load() {
39 return nil, notHealthyErr
40 }
41 }
42 > return handler(ctx, req) health.go
43 }
44
45 > func (i *HealthInterceptor) SetHealthy(healthy bool) { health.go
46 > i.healthy.Store(healthy)
47 > }
go.temporal.io/server/common/serviceerror/convert.go 12 covered LOC · 6 ranges

Open complete file

9
10 // FromStatus converts gRPC status to service error.
11 > func FromStatus(st *status.Status) error { convert.go
12 > if st == nil || st.Code() == codes.OK {
13 > return nil convert.go
14 > }
15
16 > errDetails := extractErrorDetails(st) convert.go
17 >
18 > switch st.Code() {
19 case codes.InvalidArgument:
20 switch errDetails := errDetails.(type) {
54 }
55
56 > return serviceerror.FromStatus(st) convert.go
57 }
58
59 > func extractErrorDetails(st *status.Status) any { convert.go
60 > details := st.Details()
61 > if len(details) > 0 {
62 return details[0]
63 }
64
65 > return nil convert.go
66 }
go.temporal.io/server/common/telemetry/grpc.go 12 covered LOC · 5 ranges

Open complete file

44 tmp propagation.TextMapPropagator,
45 logger log.Logger,
46 > ) ServerStatsHandler { grpc.go
47 > if !isEnabled(tp) {
48 > return nil grpc.go
49 > }
50
51 return newCustomServerStatsHandler(
64 tp trace.TracerProvider,
65 tmp propagation.TextMapPropagator,
66 > ) ClientStatsHandler { grpc.go
67 > if !isEnabled(tp) {
68 > return nil grpc.go
69 > }
70
71 return otelgrpc.NewClientHandler(
192 }
193
194 > func isEnabled(tp trace.TracerProvider) bool { grpc.go
195 > _, isNoop := tp.(otelnoop.TracerProvider)
196 > return !isNoop
197 > }
go.temporal.io/server/service/frontend/overrides.go 12 covered LOC · 5 ranges

Open complete file

15 }
16
17 > func NewOverrides() *Overrides { overrides.go
18 > return &Overrides{
19 > minTypeScriptEagerActivitySupportedVersion: semver.MustParse("1.4.4"),
20 > }
21 > }
22
23 > func (o *Overrides) shouldForceDisableEagerDispatch(sdkName, sdkVersion string) bool { overrides.go
24 > if sdkName == headers.ClientNamePythonSDK && (sdkVersion == "0.1a1" || sdkVersion == "0.1a2" || sdkVersion == "0.1b1" || sdkVersion == "0.1b2") {
25 return true
26 > } else if sdkName == headers.ClientNameTypeScriptSDK { overrides.go
27 ver, err := semver.Parse(sdkVersion)
28 // Don't bother with non semver
32 return ver.LT(o.minTypeScriptEagerActivitySupportedVersion)
33 }
34 > return false overrides.go
35 }
36
51 ctx context.Context,
52 request *workflowservice.RespondWorkflowTaskCompletedRequest,
53 > ) { overrides.go
54 > sdkName, sdkVersion := headers.GetClientNameAndVersion(ctx)
55 > if o.shouldForceDisableEagerDispatch(sdkName, sdkVersion) {
56 o.disableEagerDispatch(request)
57 }
go.temporal.io/server/service/history/api/namespace.go 12 covered LOC · 7 ranges

Open complete file

12 namespaceUUID namespace.ID,
13 businessID string,
14 > ) (*namespace.Namespace, error) { namespace.go
15 >
16 > err := ValidateNamespaceUUID(namespaceUUID)
17 > if err != nil {
18 return nil, err
19 }
20
21 > namespaceEntry, err := shard.GetNamespaceRegistry().GetNamespaceByID(namespaceUUID) namespace.go
22 > if err != nil {
23 return nil, err
24 }
25 > if namespaceEntry.ActiveClusterName(namespace.RoutingKey{ID: businessID}) != shard.GetClusterMetadata().GetCurrentClusterName() { namespace.go
26 return nil, serviceerror.NewNamespaceNotActive(
27 namespaceEntry.Name().String(),
29 namespaceEntry.ActiveClusterName(namespace.RoutingKey{ID: businessID}))
30 }
31 > return namespaceEntry, nil namespace.go
32 }
33
52 func ValidateNamespaceUUID(
53 namespaceUUID namespace.ID,
54 > ) error { namespace.go
55 > if namespaceUUID == "" {
56 return serviceerror.NewInvalidArgument("Missing namespace UUID.")
57 > } else if uuid.Validate(namespaceUUID.String()) != nil { namespace.go
58 return serviceerror.NewInvalidArgument("Invalid namespace UUID.")
59 }
60 > return nil namespace.go
61 }
go.temporal.io/server/service/history/deletemanager/delete_manager.go 12 covered LOC · 1 range

Open complete file

64 timeSource clock.TimeSource,
65 visibilityManager manager.VisibilityManager,
66 > ) *DeleteManagerImpl { delete_manager.go
67 > deleteManager := &DeleteManagerImpl{
68 > shardContext: shardContext,
69 > workflowCache: cache,
70 > metricsHandler: shardContext.GetMetricsHandler(),
71 > config: config,
72 > timeSource: timeSource,
73 > visibilityManager: visibilityManager,
74 > }
75 >
76 > return deleteManager
77 > }
78
79 func (m *DeleteManagerImpl) AddDeleteExecutionTask(
go.temporal.io/server/service/history/ndc/workflow_resetter.go 12 covered LOC · 1 range

Open complete file

88 workflowCache wcache.Cache,
89 logger log.Logger,
90 > ) *workflowResetterImpl { workflow_resetter.go
91 > return &workflowResetterImpl{
92 > shardContext: shardContext,
93 > namespaceRegistry: shardContext.GetNamespaceRegistry(),
94 > clusterMetadata: shardContext.GetClusterMetadata(),
95 > executionMgr: shardContext.GetExecutionManager(),
96 > workflowCache: workflowCache,
97 > stateRebuilder: NewStateRebuilder(shardContext, logger),
98 > transaction: workflow.NewTransaction(shardContext),
99 > logger: logger,
100 > }
101 > }
102
103 // ResetWorkflow resets the given base run and creates a new run that would start after baseNextEventID. It additionally does the following
go.temporal.io/server/service/history/queues/mitigator.go 12 covered LOC · 1 range

Open complete file

43 maxReaderCount dynamicconfig.IntPropertyFn,
44 grouper Grouper,
45 > ) *mitigatorImpl { mitigator.go
46 > return &mitigatorImpl{
47 > readerGroup: readerGroup,
48 > monitor: monitor,
49 > logger: logger,
50 > metricsHandler: metricsHandler,
51 > maxReaderCount: maxReaderCount,
52 >
53 > actionRunner: runAction,
54 > grouper: grouper,
55 > }
56 > }
57
58 func (m *mitigatorImpl) Mitigate(alert Alert) {
go.temporal.io/server/chasm/lib/callback/fx.go 11 covered LOC · 4 ranges

Open complete file

19 registry *chasm.Registry,
20 library *Library,
21 > ) error { fx.go
22 > return registry.Register(library)
23 > }
24
25 // httpCallerProviderProvider provides an HTTPCallerProvider for CHASM callbacks.
30 httpClientCache *cluster.FrontendHTTPClientCache,
31 logger log.Logger,
32 > ) (HTTPCallerProvider, error) { fx.go
33 > localClient, err := rpcFactory.CreateLocalFrontendHTTPClient()
34 > if err != nil {
35 return nil, fmt.Errorf("cannot create local frontend HTTP client: %w", err)
36 }
37 > defaultClient := &http.Client{} fx.go
38 > callbackTokenGenerator := commonnexus.NewCallbackTokenGenerator()
39 >
40 > m := collection.NewOnceMap(func(queuescommon.NamespaceIDAndDestination) HTTPCaller {
41 return func(r *http.Request) (*http.Response, error) {
42 return routeRequest(r,
51 }
52 })
53 > return m.Get, nil fx.go
54 }
55
go.temporal.io/server/chasm/lib/nexusoperation/frontend.go 11 covered LOC · 1 range

Open complete file

52 saMapperProvider searchattribute.MapperProvider,
53 saValidator *searchattribute.Validator,
54 > ) FrontendHandler { frontend.go
55 > return &frontendHandler{
56 > client: client,
57 > config: config,
58 > logger: logger,
59 > namespaceRegistry: namespaceRegistry,
60 > endpointRegistry: endpointRegistry,
61 > saMapperProvider: saMapperProvider,
62 > saValidator: saValidator,
63 > }
64 > }
65
66 func (h *frontendHandler) StartNexusOperationExecution(
go.temporal.io/server/common/collection/indexedtakelist.go 11 covered LOC · 4 ranges

Open complete file

21 values []V,
22 indexer func(V) K,
23 > ) *IndexedTakeList[K, V] { indexedtakelist.go
24 > ret := &IndexedTakeList[K, V]{
25 > values: make([]kv[K, V], 0, len(values)),
26 > }
27 > for _, v := range values {
28 ret.values = append(ret.values, kv[K, V]{key: indexer(v), value: v})
29 }
30 > return ret indexedtakelist.go
31 }
32
50
51 // TakeRemaining removes all remaining values from this set and returns them.
52 > func (itl *IndexedTakeList[K, V]) TakeRemaining() []V { indexedtakelist.go
53 > out := make([]V, 0, len(itl.values))
54 > for i := 0; i < len(itl.values); i++ {
55 kv := &itl.values[i]
56 if !kv.removed {
go.temporal.io/server/common/log/slog.go 11 covered LOC · 6 ranges

Open complete file

27
28 // NewSlogLogger creates an slog.Logger from a given logger.
29 > func NewSlogLogger(logger Logger) *slog.Logger { slog.go
30 > // Try extracting and underlying slog logger (e.g. for Temporal CLI).
31 > if sl, ok := logger.(SLogWrapper); ok {
32 return sl.SLog()
33 }
34 > logger = withIncreasedSkip(logger, 3) slog.go
35 > return slog.New(&handler{logger: logger, zapLogger: extractZapLogger(logger), group: "", tags: nil})
36 }
37
94 }
95
96 > func extractZapLogger(logger Logger) *zap.Logger { slog.go
97 > switch l := logger.(type) {
98 case *zapLogger:
99 return l.zl
103 return extractZapLogger(l.logger)
104 }
105 > return nil slog.go
106 }
107
108 // withIncreasedSkip increases the skip level for the given logger if it embeds a zapLogger.
109 > func withIncreasedSkip(logger Logger, skip int) Logger { slog.go
110 > switch l := logger.(type) {
111 case *zapLogger:
112 return l.Skip(skip)
123 }
124 // Default to not increasing the skip, it's better to have a logger than not having one.
125 > return logger slog.go
126 }
127
go.temporal.io/server/common/metrics/fx.go 11 covered LOC · 2 ranges

Open complete file

17 lc fx.Lifecycle,
18 reporter *RuntimeMetricsReporter,
19 > ) { fx.go
20 > lc.Append(
21 > fx.Hook{
22 > OnStart: func(context.Context) error {
23 > reporter.Start()
24 > return nil
25 > },
26 > OnStop: func(context.Context) error { fx.go
27 > reporter.Stop()
28 > return nil
29 > },
30 },
31 )
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/nexus_endpoints.go 11 covered LOC · 3 ranges

Open complete file

32 }
33
34 > func (mdb *db) GetNexusEndpointsTableVersion(ctx context.Context) (int64, error) { nexus_endpoints.go
35 > var version int64
36 > err := mdb.conn.GetContext(ctx, &version, getEndpointsTableVersionQry)
37 > if errors.Is(err, sql.ErrNoRows) {
38 > return 0, nil nexus_endpoints.go
39 > }
40 return version, err
41 }
86 ctx context.Context,
87 request *sqlplugin.ListNexusEndpointsRequest,
88 > ) ([]sqlplugin.NexusEndpointsRow, error) { nexus_endpoints.go
89 > var rows []sqlplugin.NexusEndpointsRow
90 > err := mdb.conn.SelectContext(ctx, &rows, getEndpointsQry, request.LastID, request.Limit)
91 > return rows, err
92 > }
go.temporal.io/server/common/persistence/sql/task_user_data.go 11 covered LOC · 3 ranges

Open complete file

16 }
17
18 > func (uds *userDataStore) GetTaskQueueUserData(ctx context.Context, request *persistence.GetTaskQueueUserDataRequest) (*persistence.InternalGetTaskQueueUserDataResponse, error) { task_user_data.go
19 > namespaceID, err := primitives.ParseUUID(request.NamespaceID)
20 > if err != nil {
21 return nil, serviceerror.NewInternalf("failed to parse namespace ID as UUID: %v", err)
22 }
23 > response, err := uds.DB.GetTaskQueueUserData(ctx, &sqlplugin.GetTaskQueueUserDataRequest{ task_user_data.go
24 > NamespaceID: namespaceID,
25 > TaskQueueName: request.TaskQueue,
26 > })
27 > if err != nil {
28 > if err == sql.ErrNoRows { task_user_data.go
29 > return nil, serviceerror.NewNotFoundf("task queue user data not found for %v.%v", request.NamespaceID, request.TaskQueue)
30 > }
31 return nil, err
32 }
go.temporal.io/server/common/primitives/timestamp/time.go 11 covered LOC · 5 ranges

Open complete file

7 )
8
9 > func TimePtr(t time.Time) *timestamppb.Timestamp { time.go
10 > return timestamppb.New(t)
11 > }
12
13 > func TimeValue(t *timestamppb.Timestamp) time.Time { time.go
14 > if t == nil {
15 > return time.Time{} time.go
16 > }
17 > return t.AsTime() time.go
18 }
19
46 }
47
48 > func TimeNowPtrUtc() *timestamppb.Timestamp { time.go
49 > return TimePtr(time.Now().UTC())
50 > }
go.temporal.io/server/common/quotas/request_rate_limiter_adapter_impl.go 11 covered LOC · 3 ranges

Open complete file

16 func NewRequestRateLimiterAdapter(
17 rateLimiter RateLimiter,
18 > ) RequestRateLimiter { request_rate_limiter_adapter_impl.go
19 > return &RequestRateLimiterAdapterImpl{
20 > rateLimiter: rateLimiter,
21 > }
22 > }
23
24 func (r *RequestRateLimiterAdapterImpl) Allow(
25 now time.Time,
26 request Request,
28 > return r.rateLimiter.AllowN(now, request.Token)
29 > }
30
31 func (r *RequestRateLimiterAdapterImpl) Reserve(
32 now time.Time,
33 request Request,
35 > return r.rateLimiter.ReserveN(now, request.Token)
36 > }
37
38 func (r *RequestRateLimiterAdapterImpl) Wait(
go.temporal.io/server/common/quotas/routing_rate_limiter_impl.go 11 covered LOC · 4 ranges

Open complete file

17 func NewRoutingRateLimiter(
18 apiToRateLimiter map[string]RequestRateLimiter,
19 > ) *RoutingRateLimiterImpl { routing_rate_limiter_impl.go
20 > return &RoutingRateLimiterImpl{
21 > apiToRateLimiter: apiToRateLimiter,
22 > }
23 > }
24
25 // Allow attempts to allow a request to go through. The method returns
go.temporal.io/server/common/rpc/context.go 11 covered LOC · 4 ranges

Open complete file

16 )
17
18 > func (c *valueCopyCtx) Value(key any) any { context.go
19 > if value := c.Context.Value(key); value != nil {
20 > return value context.go
21 > }
22
23 > return c.valueCtx.Value(key) context.go
24 }
25
26 // CopyContextValues copies values in source Context to destination Context.
27 > func CopyContextValues(dst context.Context, src context.Context) context.Context { context.go
28 > return &valueCopyCtx{
29 > Context: dst,
30 > valueCtx: src,
31 > }
32 > }
33
34 // ResetContextTimeout creates new context with specified timeout and copies values from source Context.
go.temporal.io/server/common/rpc/interceptor/logtags/workflow_tags.go 11 covered LOC · 4 ranges

Open complete file

23 serializer *tasktoken.Serializer,
24 logger log.Logger,
25 > ) *WorkflowTags { workflow_tags.go
26 > return &WorkflowTags{
27 > serializer: serializer,
28 > logger: logger,
29 > }
30 > }
31
32 > func (wt *WorkflowTags) Extract(req any, fullMethod string) []tag.Tag { workflow_tags.go
33 > if req == nil {
34 return nil
35 }
36 > switch { workflow_tags.go
37 > case strings.HasPrefix(fullMethod, api.WorkflowServicePrefix): workflow_tags.go
38 > return wt.extractFromWorkflowServiceServerMessage(req)
39 case strings.HasPrefix(fullMethod, api.OperatorServicePrefix):
40 // OperatorService doesn't have a single API with workflow tags.
go.temporal.io/server/common/rpc/interceptor/namespace_logger.go 11 covered LOC · 3 ranges

Open complete file

23 var _ grpc.UnaryServerInterceptor = (*NamespaceLogInterceptor)(nil).Intercept
24
25 > func NewNamespaceLogInterceptor(namespaceRegistry namespace.Registry, logger log.Logger) *NamespaceLogInterceptor { namespace_logger.go
26 >
27 > return &NamespaceLogInterceptor{
28 > namespaceRegistry: namespaceRegistry,
29 > logger: logger,
30 > }
31 > }
32
33 func (nli *NamespaceLogInterceptor) Intercept(
36 info *grpc.UnaryServerInfo,
37 handler grpc.UnaryHandler,
38 > ) (any, error) { namespace_logger.go
39 >
40 > if nli.logger != nil {
41 methodName := api.MethodName(info.FullMethod)
42 namespace := MustGetNamespaceName(nli.namespaceRegistry, req)
58 tag.CertThumbprint(certThumbprint))
59 }
60 > return handler(ctx, req) namespace_logger.go
61 }
go.temporal.io/server/common/tasktoken/serializer.go 11 covered LOC · 4 ranges

Open complete file

9
10 // NewSerializer creates a new instance of Serializer
11 > func NewSerializer() *Serializer { serializer.go
12 > return &Serializer{}
13 > }
14
15 > func (s *Serializer) Serialize(taskToken *tokenspb.Task) ([]byte, error) { serializer.go
16 > if taskToken == nil {
17 return nil, nil
18 }
19 > return taskToken.Marshal() serializer.go
20 }
21
22 > func (s *Serializer) Deserialize(data []byte) (*tokenspb.Task, error) { serializer.go
23 > taskToken := &tokenspb.Task{}
24 > err := taskToken.Unmarshal(data)
25 > return taskToken, err
26 > }
27
28 func (s *Serializer) SerializeQueryTaskToken(taskToken *tokenspb.QueryTask) ([]byte, error) {
go.temporal.io/server/common/telemetry/config.go 11 covered LOC · 4 ranges

Open complete file

157 }
158
159 > func (ec *ExportConfig) SpanExporters() (map[SpanExporterType]otelsdktrace.SpanExporter, error) { config.go
160 > return ec.inner.SpanExporters()
161 > }
162
163 func (ec *ExportConfig) MetricExporters() ([]metric.Exporter, error) {
205 // unmarshalled into this ExportConfig object. The returned SpanExporters have
206 // not been started.
207 > func (ec *exportConfig) SpanExporters() (map[SpanExporterType]otelsdktrace.SpanExporter, error) { config.go
208 > out := make(map[SpanExporterType]otelsdktrace.SpanExporter, len(ec.Exporters))
209 > for _, expcfg := range ec.Exporters {
210 if !strings.HasPrefix(expcfg.Kind.Signal, "trace") {
211 continue
222 }
223 }
224 > return out, nil config.go
225 }
226
417 }
418
419 > func IsEnabled(t trace.Tracer) bool { config.go
420 > _, isNoop := t.(otelnoop.Tracer)
421 > return !isNoop
422 > }
go.temporal.io/server/service/history/replication/eager_namespace_refresher.go 11 covered LOC · 1 range

Open complete file

43 replicationTaskExecutor nsreplication.TaskExecutor,
44 currentCluster string,
45 > metricsHandler metrics.Handler) EagerNamespaceRefresher { eager_namespace_refresher.go
46 > return &eagerNamespaceRefresherImpl{
47 > metadataManager: metadataManager,
48 > namespaceRegistry: namespaceRegistry,
49 > logger: logger,
50 > clientBean: clientBean,
51 > replicationTaskExecutor: replicationTaskExecutor,
52 > currentCluster: currentCluster,
53 > metricsHandler: metricsHandler,
54 > }
55 > }
56
57 func (e *eagerNamespaceRefresherImpl) SyncNamespaceFromSourceCluster(
go.temporal.io/server/service/history/replication/quotas.go 11 covered LOC · 3 ranges

Open complete file

15 )
16
17 > func ClientSchedulerRateLimiterProvider() ClientSchedulerRateLimiter { quotas.go
18 > // Experiment with no op rate limiter
19 > return quotas.NoopRequestRateLimiter
20 > }
21
22 > func ServerSchedulerRateLimiterProvider() ServerSchedulerRateLimiter { quotas.go
23 > // Experiment with no op rate limiter
24 > return quotas.NoopRequestRateLimiter
25 > }
26
27 > func PersistenceRateLimiterProvider() PersistenceRateLimiter { quotas.go
28 > return quotas.NoopRequestRateLimiter
29 > }
go.temporal.io/server/service/worker/deletenamespace/activities.go 11 covered LOC · 1 range

Open complete file

49 allowDeleteNamespaceIfNexusEndpointTarget dynamicconfig.BoolPropertyFn,
50 nexusEndpointListDefaultPageSize dynamicconfig.IntPropertyFn,
51 > ) *localActivities { activities.go
52 > return &localActivities{
53 > metadataManager: metadataManager,
54 > clusterMetadata: clusterMetadata,
55 > nexusEndpointManager: nexusEndpointManager,
56 > logger: logger,
57 > protectedNamespaces: protectedNamespaces,
58 > allowDeleteNamespaceIfNexusEndpointTarget: allowDeleteNamespaceIfNexusEndpointTarget,
59 > nexusEndpointListDefaultPageSize: nexusEndpointListDefaultPageSize,
60 > }
61 > }
62
63 func (a *localActivities) GetNamespaceInfoActivity(ctx context.Context, nsID namespace.ID, nsName namespace.Name) (getNamespaceInfoResult, error) {
go.temporal.io/server/service/worker/scheduler/spec.go 11 covered LOC · 1 range

Open complete file

63 // NewSpecBuilder takes the compute-limit getters directly (rather than a *dynamicconfig.Collection)
64 // so the dynamic-config plumbing stays in the wiring layer, per the common codebase pattern.
65 > func NewSpecBuilder(warnIterations, maxIterations dynamicconfig.IntPropertyFn) *SpecBuilder { spec.go
66 > return &SpecBuilder{
67 > warnIterations: warnIterations,
68 > maxIterations: maxIterations,
69 > locationCache: cache.New(1000,
70 > &cache.Options{
71 > TTL: 24 * time.Hour,
72 > },
73 > ),
74 > }
75 > }
76
77 func (b *SpecBuilder) NewCompiledSpec(spec *schedulepb.ScheduleSpec) (*CompiledSpec, error) {
go.temporal.io/server/chasm/lib/activity/handler.go 10 covered LOC · 1 range

Open complete file

48 logger log.Logger,
49 namespaceRegistry namespace.Registry,
50 > ) *handler { handler.go
51 > return &handler{
52 > config: config,
53 > historyHandler: historyHandler,
54 > linkValidator: linkValidator,
55 > logger: logger,
56 > metricsHandler: metricsHandler,
57 > namespaceRegistry: namespaceRegistry,
58 > }
59 > }
60
61 // StartActivityExecution schedules an activity execution. Note that while external callers refer to
go.temporal.io/server/chasm/lib/scheduler/fx.go 10 covered LOC · 3 ranges

Open complete file

11 registry *chasm.Registry,
12 library *Library,
13 > ) error { fx.go
14 > return registry.Register(library)
15 > }
16
17 var Module = fx.Module(
18 "chasm.lib.scheduler",
19 fx.Provide(ConfigProvider),
20 > fx.Provide(func(dc *dynamicconfig.Collection) *legacyscheduler.SpecBuilder { fx.go
21 > return legacyscheduler.NewSpecBuilder(
22 > dynamicconfig.SchedulerSpecWarnIterations.Get(dc),
23 > dynamicconfig.SchedulerSpecMaxIterations.Get(dc),
24 > )
25 > }),
26 fx.Provide(NewSpecProcessor),
27 > fx.Provide(func(impl *SpecProcessorImpl) SpecProcessor { return impl }), fx.go
28 fx.Provide(newHandler),
29 fx.Provide(NewSchedulerIdleTaskHandler),
go.temporal.io/server/chasm/lib/tests/nexus_service.go 10 covered LOC · 2 ranges

Open complete file

12 })
13
14 > func NewTestServiceNexusService() *nexus.Service { nexus_service.go
15 > service := nexus.NewService("TestService")
16 > service.MustRegister(TestOperation)
17 > return service
18 > }
19
20 type testOperationProcessor struct {
30 }
31
32 > func NewTestServiceNexusServiceProcessor() *chasm.NexusServiceProcessor { nexus_service.go
33 > sp := chasm.NewNexusServiceProcessor("TestService")
34 > sp.MustRegisterOperation("TestOperation", chasm.NewRegisterableNexusOperationProcessor(testOperationProcessor{}))
35 > return sp
36 > }
go.temporal.io/server/common/contextutil/deadline.go 10 covered LOC · 5 ranges

Open complete file

18 timeout time.Duration,
19 buffer time.Duration,
20 > ) (context.Context, context.CancelFunc) { deadline.go
21 > if parent.Err() != nil {
22 return parent, noop
23 }
24
25 > parentDeadline, parentHasDeadline := parent.Deadline() deadline.go
26 >
27 > if !parentHasDeadline {
28 // No parent deadline, so buffer is available to parent after child deadline expiry.
29 return context.WithTimeout(parent, timeout)
32 // If parent deadline itself does not allow buffer then set child timeout to zero. Otherwise
33 // compute child deadline such that at least buffer remains after it and before parent deadline.
34 > remaining := time.Until(parentDeadline) - buffer deadline.go
35 > if remaining < timeout {
36 > timeout = max(0, remaining) deadline.go
37 > }
38 > return context.WithTimeout(parent, timeout) deadline.go
39 }
go.temporal.io/server/common/namespace/nsreplication/replication_task_executor.go 10 covered LOC · 1 range

Open complete file

68 logger log.Logger,
69 testHooks testhooks.TestHooks,
70 > ) TaskExecutor { replication_task_executor.go
71 > return &taskExecutorImpl{
72 > currentCluster: currentCluster,
73 > metadataManager: metadataManagerV2,
74 > dataMerger: dataMerger,
75 > admitter: admitter,
76 > logger: logger,
77 > testHooks: testHooks,
78 > }
79 > }
80
81 // Execute handles receiving of the namespace replication task
go.temporal.io/server/common/persistence/sql/sqlplugin/matching_task_queue.go 10 covered LOC · 6 ranges

Open complete file

62 var switchTaskQueuesTableV1Cache sync.Map
63
64 > func SwitchTaskQueuesTable(baseQuery string, v MatchingTaskVersion) string { matching_task_queue.go
65 > if v == MatchingTaskVersion2 {
66 > return baseQuery matching_task_queue.go
67 > } else if v != MatchingTaskVersion1 { matching_task_queue.go
68 panic("invalid task schema version") // nolint:forbidigo // hardcoded constants
69 }
70 > if v1query, ok := switchTaskQueuesTableV1Cache.Load(baseQuery); ok { matching_task_queue.go
71 > return v1query.(string) // nolint:revive matching_task_queue.go
72 > }
73 > v1query := strings.ReplaceAll(baseQuery, " task_queues_v2 ", " task_queues ") matching_task_queue.go
74 > switchTaskQueuesTableV1Cache.Store(baseQuery, v1query)
75 > return v1query
76 }
go.temporal.io/server/common/persistence/sql/sqlplugin/postgresql/plugin.go 10 covered LOC · 1 range

Open complete file

36 var _ sqlplugin.Plugin = (*plugin)(nil)
37
38 > func init() { plugin.go
39 > sql.RegisterPlugin(PluginName, &plugin{
40 > driver: &driver.PQDriver{},
41 > queryConverter: &queryConverter{},
42 > })
43 > sql.RegisterPlugin(PluginNamePGX, &plugin{
44 > driver: &driver.PGXDriver{},
45 > queryConverter: &queryConverter{},
46 > })
47 > }
48
49 func (p *plugin) GetVisibilityQueryConverter() sqlplugin.VisibilityQueryConverter {
go.temporal.io/server/common/persistence/sql/sqlplugin/postgresql/visibility.go 10 covered LOC · 1 range

Open complete file

40 )
41
42 > func buildOnDuplicateKeyUpdate(fields ...string) string { visibility.go
43 > items := make([]string, len(fields))
44 > for i, field := range fields {
45 > items[i] = fmt.Sprintf("%s = excluded.%s", field, field)
46 > }
47 > return fmt.Sprintf(
48 > // The WHERE clause ensures that no update occurs if the version is behind the saved version.
49 > "ON CONFLICT (namespace_id, run_id) DO UPDATE SET %s WHERE executions_visibility.%s < EXCLUDED.%s",
50 > strings.Join(items, ", "), sqlplugin.VersionColumnName, sqlplugin.VersionColumnName,
51 > )
52 }
53
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/typeconv.go 10 covered LOC · 6 ranges

Open complete file

18
19 // ToSQLiteDateTime converts to time to SQLite datetime
20 > func (c *converter) ToSQLiteDateTime(t time.Time) time.Time { typeconv.go
21 > if t.IsZero() {
22 return minSQLiteDateTime
23 }
24 > return t.UTC().Truncate(time.Microsecond) typeconv.go
25 }
26
27 // FromSQLiteDateTime converts SQLite datetime and returns go time
28 > func (c *converter) FromSQLiteDateTime(t time.Time) time.Time { typeconv.go
29 > if t.Equal(minSQLiteDateTime) {
30 return time.Time{}.UTC()
31 }
32 > return t.UTC() typeconv.go
33 }
34
35 > func getMinSQLiteDateTime() time.Time { typeconv.go
36 > t, err := time.Parse(time.RFC3339, "1000-01-01T00:00:00Z")
37 > if err != nil {
38 return time.Unix(0, 0).UTC()
39 }
40 > return t.UTC() typeconv.go
41 }
go.temporal.io/server/common/persistence/visibility/chasm_visibility_manager.go 10 covered LOC · 2 ranges

Open complete file

24 nsRegistry namespace.Registry,
25 visibilityMgr manager.VisibilityManager,
26 > ) *ChasmVisibilityManager { chasm_visibility_manager.go
27 > return &ChasmVisibilityManager{
28 > registry: registry,
29 > nsRegistry: nsRegistry,
30 > visibilityMgr: visibilityMgr,
31 > }
32 > }
33
34 func ChasmVisibilityManagerProvider(
36 nsRegistry namespace.Registry,
37 visibilityMgr manager.VisibilityManager,
38 > ) chasm.VisibilityManager { chasm_visibility_manager.go
39 > return NewChasmVisibilityManager(registry, nsRegistry, visibilityMgr)
40 > }
41
42 // ListExecutions implements the Engine interface for visibility queries.
go.temporal.io/server/common/persistence/visibility/store/query/util.go 10 covered LOC · 2 ranges

Open complete file

70 }
71
72 > func NewUnsafeSQLString(val string) *UnsafeSQLString { util.go
73 > return &UnsafeSQLString{Val: val}
74 > }
75
76 func NewColName(name string) *ColumnName {
78 }
79
80 > func NewSAColumn(alias string, fieldName string, valueType enumspb.IndexedValueType) *SAColumn { util.go
81 > return &SAColumn{
82 > Alias: alias,
83 > FieldName: fieldName,
84 > ValueType: valueType,
85 > }
86 > }
87
88 func NamespaceDivisionSAColumn() *SAColumn {
go.temporal.io/server/common/quotas/delayed_request_rate_limiter.go 10 covered LOC · 3 ranges

Open complete file

30 delay time.Duration,
31 timeSource clock.TimeSource,
32 > ) (*DelayedRequestRateLimiter, error) { delayed_request_rate_limiter.go
33 > if delay < 0 {
34 return nil, fmt.Errorf("%w: %v", ErrNegativeDelay, delay)
35 }
36
37 > delegator := RequestRateLimiterDelegator{} delayed_request_rate_limiter.go
38 > delegator.SetRateLimiter(NoopRequestRateLimiter)
39 >
40 > timer := timeSource.AfterFunc(delay, func() {
41 delegator.SetRateLimiter(rl)
42 })
43
44 > return &DelayedRequestRateLimiter{ delayed_request_rate_limiter.go
45 > RequestRateLimiter: &delegator,
46 > timer: timer,
47 > }, nil
48 }
49
go.temporal.io/server/common/quotas/request.go 10 covered LOC · 1 range

Open complete file

19 callerSegment int32,
20 initiation string,
21 > ) Request { request.go
22 > return Request{
23 > API: api,
24 > Token: token,
25 > Caller: caller,
26 > CallerType: callerType,
27 > CallerSegment: callerSegment,
28 > Initiation: initiation,
29 > }
30 > }
go.temporal.io/server/components/callbacks/executors.go 10 covered LOC · 2 ranges

Open complete file

25 registry *hsm.Registry,
26 executorOptions TaskExecutorOptions,
27 > ) error { executors.go
28 > exec := taskExecutor{executorOptions}
29 > if err := hsm.RegisterImmediateExecutor(
30 > registry,
31 > exec.executeInvocationTask,
32 > ); err != nil {
33 return err
34 }
35 > return hsm.RegisterTimerExecutor( executors.go
36 > registry,
37 > exec.executeBackoffTask,
38 > )
39 }
40
go.temporal.io/server/components/callbacks/tasks.go 10 covered LOC · 5 ranges

Open complete file

26 }
27
28 > func (InvocationTask) Type() string { tasks.go
29 > return TaskTypeInvocation
30 > }
31
32 func (t InvocationTask) Destination() string {
58 var _ hsm.Task = BackoffTask{}
59
60 > func (BackoffTask) Type() string { tasks.go
61 > return TaskTypeBackoff
62 > }
63
64 func (t BackoffTask) Deadline() time.Time {
84 }
85
86 > func RegisterTaskSerializers(reg *hsm.Registry) error { tasks.go
87 > if err := reg.RegisterTaskSerializer(TaskTypeInvocation, InvocationTaskSerializer{}); err != nil {
88 return err
89 }
90 > if err := reg.RegisterTaskSerializer(TaskTypeBackoff, BackoffTaskSerializer{}); err != nil { // nolint:revive tasks.go
91 return err
92 }
93 > return nil tasks.go
94 }
go.temporal.io/server/schema/sqlite/setup.go 10 covered LOC · 5 ranges

Open complete file

47 //
48 // Note: this function may receive breaking changes or be removed in the future.
49 > func SetupSchemaOnDB(db sqlplugin.AdminDB) error { setup.go
50 > statements, err := p.LoadAndSplitQueryFromReaders([]io.Reader{bytes.NewBuffer(executionSchema)})
51 > if err != nil {
52 return fmt.Errorf("error loading execution schema: %w", err)
53 }
54
55 > for _, stmt := range statements { setup.go
56 > if err = db.Exec(stmt); err != nil {
57 return fmt.Errorf("error executing statement %q: %w", stmt, err)
58 }
59 }
60
61 > statements, err = p.LoadAndSplitQueryFromReaders([]io.Reader{bytes.NewBuffer(visibilitySchema)}) setup.go
62 > if err != nil {
63 return fmt.Errorf("error loading visibility schema: %w", err)
64 }
65
66 > for _, stmt := range statements { setup.go
67 > if err = db.Exec(stmt); err != nil {
68 return fmt.Errorf("error executing statement %q: %w", stmt, err)
69 }
70 }
71
72 > return nil setup.go
73 }
74
go.temporal.io/server/service/frontend/health_check.go 10 covered LOC · 1 range

Open complete file

49 healthCheckFn func(ctx context.Context, hostAddress string) (*historyservice.DeepHealthCheckResponse, error),
50 logger log.Logger,
51 > ) HealthChecker { health_check.go
52 > return &healthCheckerImpl{
53 > serviceName: serviceName,
54 > membershipMonitor: membershipMonitor,
55 > hostFailurePercentage: hostFailurePercentage,
56 > hostDeclinedServingProportion: hostDeclinedServingProportion,
57 > healthCheckFn: healthCheckFn,
58 > logger: logger,
59 > }
60 > }
61
62 func (h *healthCheckerImpl) Check(ctx context.Context) (HealthCheckResult, error) {
go.temporal.io/server/service/history/archival/archiver.go 10 covered LOC · 1 range

Open complete file

94 searchAttributeProvider searchattribute.Provider,
95 visibilityManger manager.VisibilityManager,
96 > ) Archiver { archiver.go
97 > return &archiver{
98 > archiverProvider: archiverProvider,
99 > metricsHandler: metricsHandler.WithTags(metrics.OperationTag(metrics.ArchiverClientScope)),
100 > logger: logger,
101 > rateLimiter: rateLimiter,
102 > searchAttributeProvider: searchAttributeProvider,
103 > visibilityManager: visibilityManger,
104 > }
105 > }
106
107 func (a *archiver) Archive(ctx context.Context, request *Request) (res *Response, err error) {
go.temporal.io/server/service/history/archival_queue_task_executor.go 10 covered LOC · 1 range

Open complete file

36 metricsHandler metrics.Handler,
37 logger log.Logger,
38 > ) queues.Executor { archival_queue_task_executor.go
39 > return &archivalQueueTaskExecutor{
40 > archiver: archiver,
41 > shardContext: shardContext,
42 > workflowCache: workflowCache,
43 > relocatableAttributesFetcher: relocatableAttributesFetcher,
44 > metricsHandler: metricsHandler,
45 > logger: logger,
46 > }
47 > }
48
49 // archivalQueueTaskExecutor is an implementation of queues.Executor for the archival queue.
go.temporal.io/server/service/matching/version_sets.go 10 covered LOC · 2 ranges

Open complete file

387 // - whether the primary set id was guessed (as opposed to found in versioning data)
388 // - error (can only be nil or errEmptyVersioningData)
389 > func lookupVersionSetForAdd(data *persistencespb.VersioningData, buildId string) (string, bool, error) { version_sets.go
390 > var set *persistencespb.CompatibleVersionSet
391 > if buildId == "" {
392 > // If this is a new workflow, assign it to the latest version. version_sets.go
393 > // (If it's an unversioned workflow that has already completed one or more tasks, then
394 > // leave it on the unversioned one. That case is handled already before we get here.)
395 > setLen := len(data.GetVersionSets())
396 > if setLen == 0 || data.VersionSets[setLen-1] == nil {
397 > return "", false, errEmptyVersioningData
398 > }
399 set = data.VersionSets[setLen-1]
400 } else {
go.temporal.io/server/chasm/lib/scheduler/generator_tasks.go 9 covered LOC · 1 range

Open complete file

38 )
39
40 > func NewGeneratorTaskHandler(opts GeneratorTaskHandlerOptions) *GeneratorTaskHandler { generator_tasks.go
41 > return &GeneratorTaskHandler{
42 > config: opts.Config,
43 > metricsHandler: opts.MetricsHandler,
44 > baseLogger: opts.BaseLogger,
45 > SpecProcessor: opts.SpecProcessor,
46 > specBuilder: opts.SpecBuilder,
47 > }
48 > }
49
50 func (g *GeneratorTaskHandler) Execute(
go.temporal.io/server/chasm/lib/scheduler/scheduler_migrate_task.go 9 covered LOC · 1 range

Open complete file

54 func NewSchedulerMigrateToWorkflowTaskHandler(
55 opts SchedulerMigrateToWorkflowTaskHandlerOptions,
56 > ) *SchedulerMigrateToWorkflowTaskHandler { scheduler_migrate_task.go
57 > return &SchedulerMigrateToWorkflowTaskHandler{
58 > config: opts.Config,
59 > metricsHandler: opts.MetricsHandler,
60 > baseLogger: opts.BaseLogger,
61 > historyClient: opts.HistoryClient,
62 > saMapperProvider: opts.SaMapperProvider,
63 > }
64 > }
65
66 func (h *SchedulerMigrateToWorkflowTaskHandler) Validate(
go.temporal.io/server/chasm/lib/workflow/config.go 9 covered LOC · 1 range

Open complete file

14 }
15
16 > func NewConfig(dc *dynamicconfig.Collection) Config { config.go
17 > return Config{
18 > maxIDLengthLimit: dynamicconfig.MaxIDLengthLimit.Get(dc),
19 > defaultWorkflowRetrySettings: dynamicconfig.DefaultWorkflowRetryPolicy.Get(dc),
20 > maxLinksPerRequest: dynamicconfig.FrontendMaxLinksPerRequest.Get(dc),
21 > linkMaxSize: dynamicconfig.FrontendLinkMaxSize.Get(dc),
22 > enableSignalWithStartFromWorkflow: dynamicconfig.EnableSignalWithStartFromWorkflow.Get(dc),
23 > }
24 > }
go.temporal.io/server/chasm/visibility.go 9 covered LOC · 1 range

Open complete file

64
65 // newVisibilitySearchAttributesMapper returns a mapper with all maps initialized.
66 > func newVisibilitySearchAttributesMapper() *VisibilitySearchAttributesMapper { visibility.go
67 > return &VisibilitySearchAttributesMapper{
68 > aliasToField: make(map[string]string),
69 > fieldToAlias: make(map[string]string),
70 > saTypeMap: make(map[string]enumspb.IndexedValueType),
71 > systemAliasToField: make(map[string]string),
72 > overriddenSystemFields: make(map[string]enumspb.IndexedValueType),
73 > }
74 > }
75
76 // Alias returns the alias for a given field.
go.temporal.io/server/common/codec/jsonpb.go 9 covered LOC · 3 ranges

Open complete file

23
24 // NewJSONPBEncoder creates a new JSONPBEncoder.
25 > func NewJSONPBEncoder() JSONPBEncoder { jsonpb.go
26 > return JSONPBEncoder{}
27 > }
28
29 // NewJSONPBIndentEncoder creates a new JSONPBEncoder with indent.
37
38 // Encode protobuf struct to bytes.
39 > func (e JSONPBEncoder) Encode(pb proto.Message) ([]byte, error) { jsonpb.go
40 > return e.marshaler.Marshal(pb)
41 > }
42
43 // Decode bytes to protobuf struct.
44 > func (e JSONPBEncoder) Decode(data []byte, pb proto.Message) error { jsonpb.go
45 > return e.unmarshaler.Unmarshal(data, pb)
46 > }
47
48 // Encode HistoryEvent slice to bytes.
go.temporal.io/server/common/membership/hostinfo.go 9 covered LOC · 3 ranges

Open complete file

12
13 // NewHostInfoFromAddress creates a new HostInfo instance from a socket address.
14 > func NewHostInfoFromAddress(address string) HostInfo { hostinfo.go
15 > return hostAddress(address)
16 > }
17
18 // hostAddress is a HostInfo implementation that uses a string as the address and identity.
20
21 // GetAddress returns the value of the hostAddress.
22 > func (a hostAddress) GetAddress() string { hostinfo.go
23 > return string(a)
24 > }
25
26 // Identity returns the value of the hostAddress.
27 > func (a hostAddress) Identity() string { hostinfo.go
28 > return string(a)
29 > }
go.temporal.io/server/common/metrics/noop_impl.go 9 covered LOC · 5 ranges

Open complete file

15 )
16
17 > func newNoopMetricsHandler() *noopMetricsHandler { return &noopMetricsHandler{} } noop_impl.go
18
19 // WithTags creates a new MetricProvder with provided []Tag
29
30 // Gauge obtains a gauge for the given name.
31 > func (*noopMetricsHandler) Gauge(string) GaugeIface { noop_impl.go
32 > return NoopGaugeMetricFunc
33 > }
34
35 // Timer obtains a timer for the given name.
36 > func (*noopMetricsHandler) Timer(string) TimerIface { noop_impl.go
37 > return NoopTimerMetricFunc
38 > }
39
40 // Histogram obtains a histogram for the given name.
54
55 var NoopCounterMetricFunc = CounterFunc(func(i int64, t ...Tag) {})
56 > var NoopGaugeMetricFunc = GaugeFunc(func(f float64, t ...Tag) {}) noop_impl.go
57 > var NoopTimerMetricFunc = TimerFunc(func(d time.Duration, t ...Tag) {}) noop_impl.go
58 var NoopHistogramMetricFunc = HistogramFunc(func(i int64, t ...Tag) {})
go.temporal.io/server/common/persistence/data_interfaces.go 9 covered LOC · 4 ranges

Open complete file

1408 // UnixMilliseconds returns t as a Unix time, the number of milliseconds elapsed since January 1, 1970 UTC.
1409 // It should be used for all CQL timestamp.
1410 > func UnixMilliseconds(t time.Time) int64 { data_interfaces.go
1411 > // Handling zero time separately because UnixNano is undefined for zero times.
1412 > if t.IsZero() {
1413 return 0
1414 }
1415
1416 > unixNano := t.UnixNano() data_interfaces.go
1417 > if unixNano < 0 {
1418 // Time is before January 1, 1970 UTC
1419 return 0
1420 }
1421 > return unixNano / int64(time.Millisecond) data_interfaces.go
1422 }
1423
1424 // BuildHistoryGarbageCleanupInfo combine the workflow identity information into a string
1425 > func BuildHistoryGarbageCleanupInfo(namespaceID, workflowID, runID string) string { data_interfaces.go
1426 > return fmt.Sprintf("%v:%v:%v", namespaceID, workflowID, runID)
1427 > }
1428
1429 // SplitHistoryGarbageCleanupInfo returns workflow identity information
go.temporal.io/server/common/persistence/sql/sqlplugin/util.go 9 covered LOC · 2 ranges

Open complete file

5 )
6
7 > func appendPrefix(prefix string, fields []string) []string { util.go
8 > out := make([]string, len(fields))
9 > for i, field := range fields {
10 > out[i] = prefix + field
11 > }
12 > return out
13 }
14
15 > func BuildNamedPlaceholder(fields ...string) string { util.go
16 > return strings.Join(appendPrefix(":", fields), ", ")
17 > }
go.temporal.io/server/components/callbacks/statemachine.go 9 covered LOC · 3 ranges

Open complete file

28
29 // MachineCollection creates a new typed [statemachines.Collection] for callbacks.
30 > func MachineCollection(tree *hsm.Node) hsm.Collection[Callback] { statemachine.go
31 > return hsm.NewCollection[Callback](tree, StateMachineType)
32 > }
33
34 // Callback state machine.
130 type stateMachineDefinition struct{}
131
132 > func (stateMachineDefinition) Type() string { statemachine.go
133 > return StateMachineType
134 > }
135
136 func (stateMachineDefinition) Deserialize(d []byte) (any, error) {
179 }
180
181 > func RegisterStateMachine(r *hsm.Registry) error { statemachine.go
182 > return r.RegisterMachine(stateMachineDefinition{})
183 > }
184
185 // EventScheduled is triggered when the callback is meant to be scheduled for the first time - when its Trigger
go.temporal.io/server/components/nexusoperations/statemachine.go 9 covered LOC · 4 ranges

Open complete file

192 type operationMachineDefinition struct{}
193
194 > func (operationMachineDefinition) Type() string { statemachine.go
195 > return OperationMachineType
196 > }
197
198 func (operationMachineDefinition) Deserialize(d []byte) (any, error) {
488 }
489
490 > func (cancelationMachineDefinition) Type() string { statemachine.go
491 > return CancelationMachineType
492 > }
493
494 // CompareState compares the progress of two Cancelation state machines to determine whether to sync machine state while
675 )
676
677 > func RegisterStateMachines(r *hsm.Registry) error { statemachine.go
678 > if err := r.RegisterMachine(operationMachineDefinition{}); err != nil {
679 return err
680 }
681 > return r.RegisterMachine(cancelationMachineDefinition{}) statemachine.go
682 }
go.temporal.io/server/service/history/ndc/events_reapplier.go 9 covered LOC · 1 range

Open complete file

41 metricsHandler metrics.Handler,
42 logger log.Logger,
43 > ) *EventsReapplierImpl { events_reapplier.go
44 >
45 > return &EventsReapplierImpl{
46 > stateMachineRegistry: stateMachineRegistry,
47 > chasmWorkflowRegistry: chasmWorkflowRegistry,
48 > metricsHandler: metricsHandler,
49 > logger: logger,
50 > }
51 > }
52
53 func (r *EventsReapplierImpl) ReapplyEvents(
go.temporal.io/server/service/history/queues/dlq_writer.go 9 covered LOC · 1 range

Open complete file

51 r namespace.Registry,
52 cr *chasm.Registry,
53 > ) *DLQWriter { dlq_writer.go
54 > return &DLQWriter{
55 > dlqWriter: w,
56 > metricsHandler: h,
57 > logger: l,
58 > namespaceRegistry: r,
59 > chasmRegistry: cr,
60 > }
61 > }
62
63 // WriteTaskToDLQ writes a task to the DLQ, creating the underlying queue if it doesn't already exist.
go.temporal.io/server/service/history/replication/progress_cache.go 9 covered LOC · 1 range

Open complete file

53 logger log.Logger,
54 handler metrics.Handler,
55 > ) ProgressCache { progress_cache.go
56 > maxSize := config.ReplicationProgressCacheMaxSize()
57 > opts := &cache.Options{
58 > TTL: config.ReplicationProgressCacheTTL(),
59 > }
60 > return &progressCacheImpl{
61 > cache: cache.NewWithMetrics(maxSize, opts, handler.WithTags(metrics.CacheTypeTag(metrics.ReplicationProgressCacheTypeTagValue))),
62 > }
63 > }
64
65 func (c *progressCacheImpl) Get(
go.temporal.io/server/service/history/replication/sync_state_retriever.go 9 covered LOC · 1 range

Open complete file

88 eventBlobCache persistence.XDCCache,
89 logger log.Logger,
90 > ) *SyncStateRetrieverImpl { sync_state_retriever.go
91 > return &SyncStateRetrieverImpl{
92 > shardContext: shardContext,
93 > workflowCache: workflowCache,
94 > workflowConsistencyChecker: workflowConsistencyChecker,
95 > eventBlobCache: eventBlobCache,
96 > logger: logger,
97 > }
98 > }
99
100 func (s *SyncStateRetrieverImpl) GetSyncWorkflowStateArtifact(
go.temporal.io/server/service/history/tasks/category.go 9 covered LOC · 3 ranges

Open complete file

96 }
97
98 > func (c Category) ID() int { category.go
99 > return c.id
100 > }
101
102 > func (c Category) Name() string { category.go
103 > return c.name
104 > }
105
106 > func (c Category) Type() CategoryType { category.go
107 > return c.cType
108 > }
109
110 func (c Category) MarshalText() (text []byte, err error) {
go.temporal.io/server/service/history/workflow/command_handler.go 9 covered LOC · 3 ranges

Open complete file

31
32 // NewCommandHandlerRegistry creates a new [CommandHandlerRegistry].
33 > func NewCommandHandlerRegistry() *CommandHandlerRegistry { command_handler.go
34 > return &CommandHandlerRegistry{
35 > handlers: make(map[enumspb.CommandType]CommandHandler),
36 > }
37 > }
38
39 // Register registers a [CommandHandler] for a given command type.
40 // Returns an [ErrDuplicateRegistration] if a handler for the given command is already registered.
41 // All registration is expected to happen in a single thread on process initialization.
42 > func (r *CommandHandlerRegistry) Register(t enumspb.CommandType, handler CommandHandler) error { command_handler.go
43 > if existing, ok := r.handlers[t]; ok {
44 return fmt.Errorf("%w: command handler for %v: %v", ErrDuplicateRegistration, t, existing)
45 }
46 > r.handlers[t] = handler command_handler.go
47 > return nil
48 }
49
go.temporal.io/server/service/history/workflow/state_machine_definition.go 9 covered LOC · 3 ranges

Open complete file

25
26 // Serialize is a noop as Deserialize is not supported.
27 > func (stateMachineDefinition) Serialize(any) ([]byte, error) { state_machine_definition.go
28 > return nil, nil
29 > }
30
31 > func (stateMachineDefinition) Type() string { state_machine_definition.go
32 > return StateMachineType
33 > }
34
35 > func RegisterStateMachine(reg *hsm.Registry) error { state_machine_definition.go
36 > return reg.RegisterMachine(stateMachineDefinition{})
37 > }
go.temporal.io/server/service/history/workflow/state_machine_timers.go 9 covered LOC · 3 ranges

Open complete file

16 // AddNextStateMachineTimerTask generates a state machine timer task if the first deadline doesn't have a task scheduled
17 // yet.
18 > func AddNextStateMachineTimerTask(ms historyi.MutableState) { state_machine_timers.go
19 > // filter out empty timer groups
20 > timers := ms.GetExecutionInfo().StateMachineTimers
21 > timers = slices.DeleteFunc(timers, func(timerGroup *persistencespb.StateMachineTimerGroup) bool {
22 return len(timerGroup.Infos) == 0
23 })
24 > ms.GetExecutionInfo().StateMachineTimers = timers state_machine_timers.go
25 >
26 > if len(timers) == 0 {
28 > }
29
30 timerGroup := timers[0]
go.temporal.io/server/chasm/lib/activity/fx.go 8 covered LOC · 2 ranges

Open complete file

21 newLibrary,
22 ),
23 > fx.Invoke(func(l *library, registry *chasm.Registry) error { fx.go
24 > return registry.Register(l)
25 > }),
26 )
27
34 fx.Provide(resource.SearchAttributeValidatorProvider),
35 fx.Provide(newComponentOnlyLibrary),
36 > fx.Invoke(func(l *componentOnlyLibrary, registry *chasm.Registry) error { fx.go
37 > // Frontend needs to register the component in order to serialize ComponentRefs, but doesn't
38 > // need task handlers.
39 > return registry.Register(l)
40 > }),
41 )
go.temporal.io/server/chasm/lib/callback/validator.go 8 covered LOC · 1 range

Open complete file

29 headerMaxSize dynamicconfig.IntPropertyFnWithNamespaceFilter,
30 endpointRules dynamicconfig.TypedPropertyFnWithNamespaceFilter[AddressMatchRules],
31 > ) Validator { validator.go
32 > return &validator{
33 > maxCallbacksPerExecution: maxCallbacksPerExecution,
34 > urlMaxLength: urlMaxLength,
35 > headerMaxSize: headerMaxSize,
36 > endpointRules: endpointRules,
37 > }
38 > }
39
40 // Validate validates completion callbacks: count, URL length, endpoint allowlist, header size, and normalizes header
go.temporal.io/server/chasm/lib/scheduler/backfiller_tasks.go 8 covered LOC · 1 range

Open complete file

36 )
37
38 > func NewBackfillerTaskHandler(opts BackfillerTaskHandlerOptions) *BackfillerTaskHandler { backfiller_tasks.go
39 > return &BackfillerTaskHandler{
40 > config: opts.Config,
41 > metricsHandler: opts.MetricsHandler,
42 > baseLogger: opts.BaseLogger,
43 > specProcessor: opts.SpecProcessor,
44 > }
45 > }
46
47 // BackfillerTask invalidation reasons. Limited cardinality for ReasonTag.
go.temporal.io/server/chasm/lib/scheduler/spec_processor.go 8 covered LOC · 1 range

Open complete file

66 logger log.Logger,
67 specBuilder *legacyscheduler.SpecBuilder,
68 > ) *SpecProcessorImpl { spec_processor.go
69 > return &SpecProcessorImpl{
70 > config: config,
71 > metricsHandler: metricsHandler,
72 > logger: logger,
73 > specBuilder: specBuilder,
74 > }
75 > }
76
77 func (s *SpecProcessorImpl) ProcessTimeRange(
go.temporal.io/server/chasm/lib/workflow/fx.go 8 covered LOC · 3 ranges

Open complete file

17 library *library,
18 config *nexusoperation.Config,
19 > ) error { fx.go
20 > if err := library.registry.Register(
21 > newNexusLibrary(config, chasmRegistry.NexusEndpointProcessor),
22 > ); err != nil {
23 return err
24 }
25 > return chasmRegistry.Register(library) fx.go
26 }),
27 )
30 // history service. Only include this in services that provide
31 // historyservice.HistoryServiceServer (the history service).
32 > var HistoryHandlerModule = fx.Invoke(func(library *library, historyHandler historyservice.HistoryServiceServer) { fx.go
33 > library.workflowServiceNexusHandler.setHistoryHandler(historyHandler)
34 > })
go.temporal.io/server/client/matching/retryable_client.go 8 covered LOC · 1 range

Open complete file

24 pollPolicy backoff.RetryPolicy,
25 isRetryable backoff.IsRetryable,
26 > ) matchingservice.MatchingServiceClient { retryable_client.go
27 > return &retryableClient{
28 > client: client,
29 > policy: policy,
30 > pollPolicy: pollPolicy,
31 > isRetryable: isRetryable,
32 > }
33 > }
34
35 func (c *retryableClient) Route(p tqid.Partition) (string, error) {
go.temporal.io/server/common/membership/hostinfo_provider.go 8 covered LOC · 2 ranges

Open complete file

7 )
8
9 > func NewHostInfoProvider(hostInfo HostInfo) *hostInfoProvider { hostinfo_provider.go
10 > return &hostInfoProvider{
11 > hostInfo: hostInfo,
12 > }
13 > }
14
15 > func (hip *hostInfoProvider) HostInfo() HostInfo { hostinfo_provider.go
16 > return hip.hostInfo
17 > }
go.temporal.io/server/common/persistence/cluster_metadata.go 8 covered LOC · 5 ranges

Open complete file

2
3 // GetOrUseDefaultActiveCluster return the current cluster name or use the input if valid
4 > func GetOrUseDefaultActiveCluster(currentClusterName string, activeClusterName string) string { cluster_metadata.go
5 > if len(activeClusterName) == 0 {
6 return currentClusterName
7 }
8 > return activeClusterName cluster_metadata.go
9 }
10
11 // GetOrUseDefaultClusters return the current cluster or use the input if valid
12 > func GetOrUseDefaultClusters(currentClusterName string, clusters []string) []string { cluster_metadata.go
13 > if len(clusters) == 0 {
14 > return []string{currentClusterName} cluster_metadata.go
15 > }
16 > return clusters cluster_metadata.go
17 }
go.temporal.io/server/common/persistence/history_task_queue_manager.go 8 covered LOC · 2 ranges

Open complete file

50 queue QueueV2,
51 serializer serialization.Serializer,
52 > ) *HistoryTaskQueueManagerImpl { history_task_queue_manager.go
53 > return &HistoryTaskQueueManagerImpl{
54 > queue: queue,
55 > serializer: serializer,
56 > }
57 > }
58
59 func (m *HistoryTaskQueueManagerImpl) EnqueueTask(
224 }
225
226 > func (m HistoryTaskQueueManagerImpl) Close() { history_task_queue_manager.go
227 > }
228
229 // combineUnique combines the given strings into a single string by hashing the length of each string and the string
go.temporal.io/server/common/persistence/sql/sqlplugin/mysql/visibility.go 8 covered LOC · 1 range

Open complete file

73 )
74
75 > func buildOnDuplicateKeyUpdate(fields ...string) string { visibility.go
76 > items := make([]string, len(fields))
77 > for i, field := range fields {
78 > // This line is to ensure that no update occurs (for any column) if the version is behind the saved version.
79 > items[i] = fmt.Sprintf("%v = IF(%v < VALUES(%v), VALUES(%v), %v)",
80 > field, sqlplugin.VersionColumnName, sqlplugin.VersionColumnName, field, field)
81 > }
82 > return fmt.Sprintf("ON DUPLICATE KEY UPDATE %s", strings.Join(items, ", "))
83 }
84
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/admin.go 8 covered LOC · 2 ranges

Open complete file

63
64 // Exec executes a sql statement
65 > func (mdb *db) Exec(stmt string, args ...any) error { admin.go
66 > _, err := mdb.db.Exec(stmt, args...)
67 > return err
68 > }
69
70 // ListTables returns a list of tables in this database
95
96 // CreateDatabase creates a database if it doesn't exist
97 > func (mdb *db) CreateDatabase(name string) error { admin.go
98 > // SQLite does not need to create database
99 > return nil
100 > }
101
102 // DropDatabase drops a database
go.temporal.io/server/common/stats/windowed_tdigest.go 8 covered LOC · 3 ranges

Open complete file

72 // So, if you want 300 seconds of history on an event that records 1k counts/sec, 3 10-second windows
73 // is fine.
74 > func NewWindowedTDigest(cfg WindowConfig) (TimeWindowedStats, error) { windowed_tdigest.go
75 > if cfg.WindowCount <= 0 {
76 return nil, errors.New("windowCount must be non-negative")
77 }
78 > if cfg.WindowSize.Milliseconds() <= 50 { windowed_tdigest.go
79 return nil, errors.New("probable misconfiguration detected: windowSize is too small, consider increasing it to at least 50ms")
80 }
81 > return &timeWindowedTDigest{ windowed_tdigest.go
82 > windows: make([]timedWindow, cfg.WindowCount),
83 > cfg: cfg,
84 > // mu and head both empty
85 > }, nil
86 }
87
go.temporal.io/server/common/tasks/priority.go 8 covered LOC · 2 ranges

Open complete file

59 )
60
61 > func (p Priority) String() string { priority.go
62 > s, ok := PriorityName[p]
63 > if ok {
64 > return s
65 > }
66 return strconv.Itoa(int(p))
67 }
77 func getPriority(
78 class, subClass Priority,
79 > ) Priority { priority.go
80 > return class | subClass
81 > }
go.temporal.io/server/common/workercommands/dispatcher.go 8 covered LOC · 1 range

Open complete file

67 metricsHandler metrics.Handler,
68 logger log.Logger,
69 > ) *Dispatcher { dispatcher.go
70 > return &Dispatcher{
71 > matchingClient: matchingClient,
72 > config: config,
73 > metricsHandler: metricsHandler,
74 > logger: logger,
75 > }
76 > }
77
78 func (d *Dispatcher) Execute(
go.temporal.io/server/components/callbacks/fx.go 8 covered LOC · 3 ranges

Open complete file

30 httpClientCache *cluster.FrontendHTTPClientCache,
31 logger log.Logger,
32 > ) (HTTPCallerProvider, error) { fx.go
33 > localClient, err := rpcFactory.CreateLocalFrontendHTTPClient()
34 > if err != nil {
35 return nil, fmt.Errorf("cannot create local frontend HTTP client: %w", err)
36 }
37 > defaultClient := &http.Client{} fx.go
38 > callbackTokenGenerator := commonnexus.NewCallbackTokenGenerator()
39 >
40 > m := collection.NewOnceMap(func(queuescommon.NamespaceIDAndDestination) HTTPCaller {
41 return func(r *http.Request) (*http.Response, error) {
42 return routeRequest(r,
51 }
52 })
53 > return m.Get, nil fx.go
54 }
go.temporal.io/server/components/nexusoperations/workflow/commands.go 8 covered LOC · 2 ranges

Open complete file

329 endpointRegistry commonnexus.EndpointRegistry,
330 config *nexusoperations.Config,
331 > ) error { commands.go
332 > h := commandHandler{
333 > config: config,
334 > endpointRegistry: endpointRegistry,
335 > nexusProcessor: chasmRegistry.NexusEndpointProcessor,
336 > }
337 > if err := reg.Register(enumspb.COMMAND_TYPE_SCHEDULE_NEXUS_OPERATION, h.HandleScheduleCommand); err != nil {
338 return err
339 }
340 > return reg.Register(enumspb.COMMAND_TYPE_REQUEST_CANCEL_NEXUS_OPERATION, h.HandleCancelCommand) commands.go
341 }
342
go.temporal.io/server/service/history/replication/eventhandler/event_importer.go 8 covered LOC · 1 range

Open complete file

49 serializer serialization.Serializer,
50 logger log.Logger,
51 > ) EventImporter { event_importer.go
52 > return &eventImporterImpl{
53 > historyFetcher: historyFetcher,
54 > engineProvider: engineProvider,
55 > serializer: serializer,
56 > logger: logger,
57 > }
58 > }
59
60 //nolint:revive // cognitive complexity 30 (> max enabled 25)
go.temporal.io/server/service/history/replication/eventhandler/history_events_handler.go 8 covered LOC · 1 range

Open complete file

59 shardController shard.Controller,
60 logger log.Logger,
61 > ) HistoryEventsHandler { history_events_handler.go
62 > return &historyEventsHandlerImpl{
63 > clusterMetadata: clusterMetadata,
64 > eventImporter: eventImporter,
65 > shardController: shardController,
66 > logger: logger,
67 > }
68 > }
69
70 func (h *historyEventsHandlerImpl) HandleHistoryEvents(
go.temporal.io/server/service/history/replication/eventhandler/remote_history_paginated_fetcher.go 8 covered LOC · 1 range

Open complete file

77 serializer serialization.Serializer,
78 logger log.Logger,
79 > ) HistoryPaginatedFetcher { remote_history_paginated_fetcher.go
80 > return &HistoryPaginatedFetcherImpl{
81 > NamespaceRegistry: namespaceRegistry,
82 > ClientBean: clientBean,
83 > Serializer: serializer,
84 > Logger: logger,
85 > }
86 > }
87
88 func (n *HistoryPaginatedFetcherImpl) GetSingleWorkflowHistoryPaginatedIteratorInclusive(
go.temporal.io/server/service/history/workflow/cache/fx.go 8 covered LOC · 2 ranges

Open complete file

12 lc fx.Lifecycle,
13 cache Cache,
14 > ) { fx.go
15 > lc.Append(fx.Hook{
16 > OnStop: func(_ context.Context) error {
17 > ci, ok := cache.(*cacheImpl) fx.go
18 > if ok {
19 > ci.stop()
20 > }
21 > return nil
22 },
23 })
go.temporal.io/server/service/history/workflow_rebuilder.go 8 covered LOC · 1 range

Open complete file

53 workflowCache wcache.Cache,
54 logger log.Logger,
55 > ) *workflowRebuilderImpl { workflow_rebuilder.go
56 > return &workflowRebuilderImpl{
57 > shard: shard,
58 > workflowConsistencyChecker: api.NewWorkflowConsistencyChecker(shard, workflowCache),
59 > transaction: workflow.NewTransaction(shard),
60 > logger: logger,
61 > }
62 > }
63
64 func (r *workflowRebuilderImpl) rebuild(
go.temporal.io/server/service/matching/reachability.go 8 covered LOC · 1 range

Open complete file

304 reachabilityCacheOpenWFExecutionTTL,
305 reachabilityCacheClosedWFExecutionTTL time.Duration,
306 > ) reachabilityCache { reachability.go
307 > return reachabilityCache{
308 > openWFCache: cache.New(reachabilityCacheMaxSize, &cache.Options{TTL: reachabilityCacheOpenWFExecutionTTL}),
309 > closedWFCache: cache.New(reachabilityCacheMaxSize, &cache.Options{TTL: reachabilityCacheClosedWFExecutionTTL}),
310 > metricsHandler: handler,
311 > visibilityMgr: visibilityMgr,
312 > }
313 > }
314
315 // Get retrieves the Workflow Count existence value based on the query-string key.
go.temporal.io/server/service/worker/parentclosepolicy/client.go 8 covered LOC · 1 range

Open complete file

46 sdkClientFactory sdk.ClientFactory,
47 numWorkflows int,
48 > ) Client { client.go
49 > return &clientImpl{
50 > metricsHandler: metricsHandler,
51 > logger: logger,
52 > sdkClientFactory: sdkClientFactory,
53 > numWorkflows: numWorkflows,
54 > }
55 > }
56
57 func (c *clientImpl) SendParentClosePolicyRequest(ctx context.Context, request Request) error {
go.temporal.io/server/chasm/lib/activity/link_validator.go 7 covered LOC · 1 range

Open complete file

21 maxLinksPerComponent dynamicconfig.IntPropertyFnWithNamespaceFilter,
22 linkMaxSize dynamicconfig.IntPropertyFnWithNamespaceFilter,
23 > ) *linkValidator { link_validator.go
24 > return &linkValidator{
25 > maxLinksPerRequest: maxLinksPerRequest,
26 > maxLinksPerComponent: maxLinksPerComponent,
27 > linkMaxSize: linkMaxSize,
28 > }
29 > }
30
31 // ValidateRequest checks count, per-link size, and variant shape for the links
go.temporal.io/server/chasm/statemachine.go 7 covered LOC · 1 range

Open complete file

34 // The apply function is called after verifying the transition is possible but before setting the destination state,
35 // so it can inspect the current (source) state.
36 > func NewTransition[S comparable, SM StateMachine[S], E any](src []S, dst S, apply func(SM, MutableContext, E) error) Transition[S, SM, E] { statemachine.go
37 > return Transition[S, SM, E]{
38 > Sources: src,
39 > Destination: dst,
40 > apply: apply,
41 > }
42 > }
43
44 // Possible returns a boolean indicating whether the transition is possible for the current state.
go.temporal.io/server/client/admin/client.go 7 covered LOC · 1 range

Open complete file

33 largeTimeout time.Duration,
34 client adminservice.AdminServiceClient,
35 > ) adminservice.AdminServiceClient { client.go
36 > return &clientImpl{
37 > timeout: timeout,
38 > largeTimeout: largeTimeout,
39 > client: client,
40 > }
41 > }
42
43 func (c *clientImpl) createContext(parent context.Context) (context.Context, context.CancelFunc) {
go.temporal.io/server/client/admin/metric_client.go 7 covered LOC · 1 range

Open complete file

27 metricsHandler metrics.Handler,
28 throttledLogger log.Logger,
29 > ) adminservice.AdminServiceClient { metric_client.go
30 > return &metricClient{
31 > client: client,
32 > metricsHandler: metricsHandler,
33 > throttledLogger: throttledLogger,
34 > }
35 > }
36
37 func (c *metricClient) startMetricsRecording(
go.temporal.io/server/client/admin/retryable_client.go 7 covered LOC · 1 range

Open complete file

18
19 // NewRetryableClient creates a new instance of adminservice.AdminServiceClient with retry policy
20 > func NewRetryableClient(client adminservice.AdminServiceClient, policy backoff.RetryPolicy, isRetryable backoff.IsRetryable) adminservice.AdminServiceClient { retryable_client.go
21 > return &retryableClient{
22 > client: client,
23 > policy: policy,
24 > isRetryable: isRetryable,
25 > }
26 > }
27
28 func (c *retryableClient) StreamWorkflowReplicationMessages(
go.temporal.io/server/client/frontend/client.go 7 covered LOC · 1 range

Open complete file

32 longPollTimeout time.Duration,
33 client workflowservice.WorkflowServiceClient,
34 > ) workflowservice.WorkflowServiceClient { client.go
35 > return &clientImpl{
36 > timeout: timeout,
37 > longPollTimeout: longPollTimeout,
38 > client: client,
39 > }
40 > }
41
42 func (c *clientImpl) createContext(parent context.Context) (context.Context, context.CancelFunc) {
go.temporal.io/server/client/frontend/metric_client.go 7 covered LOC · 1 range

Open complete file

26 metricsHandler metrics.Handler,
27 throttledLogger log.Logger,
28 > ) workflowservice.WorkflowServiceClient { metric_client.go
29 > return &metricClient{
30 > client: client,
31 > metricsHandler: metricsHandler,
32 > throttledLogger: throttledLogger,
33 > }
34 > }
35
36 func (c *metricClient) startMetricsRecording(
go.temporal.io/server/client/frontend/retryable_client.go 7 covered LOC · 1 range

Open complete file

15
16 // NewRetryableClient creates a new instance of workflowservice.WorkflowServiceClient with retry policy
17 > func NewRetryableClient(client workflowservice.WorkflowServiceClient, policy backoff.RetryPolicy, isRetryable backoff.IsRetryable) workflowservice.WorkflowServiceClient { retryable_client.go
18 > return &retryableClient{
19 > client: client,
20 > policy: policy,
21 > isRetryable: isRetryable,
22 > }
23 > }
go.temporal.io/server/client/history/retryable_client.go 7 covered LOC · 1 range

Open complete file

18
19 // NewRetryableClient creates a new instance of historyservice.HistoryServiceClient with retry policy
20 > func NewRetryableClient(client historyservice.HistoryServiceClient, policy backoff.RetryPolicy, isRetryable backoff.IsRetryable) historyservice.HistoryServiceClient { retryable_client.go
21 > return &retryableClient{
22 > client: client,
23 > policy: policy,
24 > isRetryable: isRetryable,
25 > }
26 > }
27
28 func (c *retryableClient) StreamWorkflowReplicationMessages(
go.temporal.io/server/common/namespace/nsreplication/dlq_message_handler.go 7 covered LOC · 1 range

Open complete file

33 namespaceReplicationQueue persistence.NamespaceReplicationQueue,
34 logger log.Logger,
35 > ) DLQMessageHandler { dlq_message_handler.go
36 > return &dlqMessageHandlerImpl{
37 > replicationHandler: replicationHandler,
38 > namespaceReplicationQueue: namespaceReplicationQueue,
39 > logger: logger,
40 > }
41 > }
42
43 // Read reads namespace replication DLQ messages
go.temporal.io/server/common/persistence/cassandra/version_checker.go 7 covered LOC · 3 ranges

Open complete file

21 r resolver.ServiceResolver,
22 logger log.Logger,
23 > ) error { version_checker.go
24 > return checkMainKeyspace(cfg, r, logger)
25 > }
26
27 func checkMainKeyspace(
29 r resolver.ServiceResolver,
30 logger log.Logger,
31 > ) error { version_checker.go
32 > ds, ok := cfg.DataStores[cfg.DefaultStore]
33 > if ok && ds.Cassandra != nil {
34 return CheckCompatibleVersion(*ds.Cassandra, r, cassandraschema.Version, logger)
35 }
36 > return nil version_checker.go
37 }
38
go.temporal.io/server/common/persistence/data_blob.go 7 covered LOC · 2 ranges

Open complete file

8 // NewDataBlob returns a new DataBlob.
9 // TODO: return an UnknowEncodingType error with the actual type string when encodingTypeStr is invalid
10 > func NewDataBlob(data []byte, encodingTypeStr string) *commonpb.DataBlob { data_blob.go
11 > encodingType, err := enumspb.EncodingTypeFromString(encodingTypeStr)
12 > if err != nil {
13 // encodingTypeStr not valid, an error will be returned on deserialization
14 encodingType = enumspb.ENCODING_TYPE_UNSPECIFIED
15 }
16
17 > return &commonpb.DataBlob{ data_blob.go
18 > Data: data,
19 > EncodingType: encodingType,
20 > }
21 }
go.temporal.io/server/common/worker_versioning/routing_info_cache.go 7 covered LOC · 1 range

Open complete file

63
64 // NewRoutingInfoCache wraps the provided cache with a typed API and metrics.
65 > func NewRoutingInfoCache(c cache.Cache, metricsHandler metrics.Handler) RoutingInfoCache { routing_info_cache.go
66 > h := metricsHandler.WithTags(metrics.CacheTypeTag(metrics.RoutingInfoCacheTypeTagValue))
67 > return &RoutingInfoCacheImpl{
68 > Cache: c,
69 > metricsHandler: h,
70 > }
71 > }
72
73 func (c *RoutingInfoCacheImpl) Get(
go.temporal.io/server/common/worker_versioning/version_membership_cache.go 7 covered LOC · 1 range

Open complete file

63
64 // NewVersionMembershipAndReactivationStatusCache wraps the provided cache with a typed API and metrics.
65 > func NewVersionMembershipAndReactivationStatusCache(c cache.Cache, metricsHandler metrics.Handler) VersionMembershipAndReactivationStatusCache { version_membership_cache.go
66 > h := metricsHandler.WithTags(metrics.CacheTypeTag(metrics.VersionMembershipCacheTypeTagValue))
67 > return &VersionMembershipAndReactivationStatusCacheImpl{
68 > Cache: c,
69 > metricsHandler: h,
70 > }
71 > }
72
73 func (c *VersionMembershipAndReactivationStatusCacheImpl) Get(
go.temporal.io/server/service/history/hsm/sm.go 7 covered LOC · 1 range

Open complete file

41 // NewTransition creates a new [Transition] from the given source states to a destination state for a given event.
42 // The apply function is called after verifying the transition is possible and setting the destination state.
43 > func NewTransition[S comparable, SM StateMachine[S], E any](src []S, dst S, apply func(SM, E) (TransitionOutput, error)) Transition[S, SM, E] { sm.go
44 > return Transition[S, SM, E]{
45 > Sources: src,
46 > Destination: dst,
47 > apply: apply,
48 > }
49 > }
50
51 // Possible returns a boolean indicating whether the transition is possible for the current state.
go.temporal.io/server/tests/testutils/source_root.go 7 covered LOC · 3 ranges

Open complete file

13
14 // GetRepoRootDirectory returns the root directory of the temporal repo.
15 > func GetRepoRootDirectory(opts ...Option) string { source_root.go
16 > p := &osParams{
17 > Getenv: os.Getenv,
18 > }
19 > for _, opt := range opts {
20 opt(p)
21 }
22 > if customRootDirectory := p.Getenv("TEMPORAL_ROOT"); customRootDirectory != "" { source_root.go
23 return customRootDirectory
24 }
25 > return rootDirectory source_root.go
26 }
27
go.temporal.io/server/api/metrics/v1/message.go-helpers.pb.go 6 covered LOC · 2 ranges

Open complete file

7
8 // Marshal an object of type Baggage to the protobuf v3 wire format
9 > func (val *Baggage) Marshal() ([]byte, error) { message.go-helpers.pb.go
10 > return proto.Marshal(val)
11 > }
12
13 // Unmarshal an object of type Baggage from the protobuf v3 wire format
14 > func (val *Baggage) Unmarshal(buf []byte) error { message.go-helpers.pb.go
15 > return proto.Unmarshal(buf, val)
16 > }
17
18 // Size returns the size of the object, in bytes, once serialized
go.temporal.io/server/api/persistence/v1/executions.go-helpers.pb.go 6 covered LOC · 2 ranges

Open complete file

54
55 // Size returns the size of the object, in bytes, once serialized
56 > func (val *WorkflowExecutionInfo) Size() int { executions.go-helpers.pb.go
57 > return proto.Size(val)
58 > }
59
60 // Equal returns whether two WorkflowExecutionInfo values are equivalent by recursively
239
240 // Size returns the size of the object, in bytes, once serialized
241 > func (val *WorkflowExecutionState) Size() int { executions.go-helpers.pb.go
242 > return proto.Size(val)
243 > }
244
245 // Equal returns whether two WorkflowExecutionState values are equivalent by recursively
go.temporal.io/server/api/token/v1/message.go-helpers.pb.go 6 covered LOC · 2 ranges

Open complete file

81
82 // Marshal an object of type Task to the protobuf v3 wire format
83 > func (val *Task) Marshal() ([]byte, error) { message.go-helpers.pb.go
84 > return proto.Marshal(val)
85 > }
86
87 // Unmarshal an object of type Task from the protobuf v3 wire format
88 > func (val *Task) Unmarshal(buf []byte) error { message.go-helpers.pb.go
89 > return proto.Unmarshal(buf, val)
90 > }
91
92 // Size returns the size of the object, in bytes, once serialized
go.temporal.io/server/chasm/lib/nexusoperation/handler.go 6 covered LOC · 1 range

Open complete file

21 }
22
23 > func newHandler(config *Config, logger log.Logger) *handler { handler.go
24 > return &handler{
25 > config: config,
26 > logger: logger,
27 > }
28 > }
29
30 // StartNexusOperation creates a new standalone Nexus operation execution via CHASM.
go.temporal.io/server/chasm/lib/scheduler/handler.go 6 covered LOC · 1 range

Open complete file

22 }
23
24 > func newHandler(logger log.Logger, specBuilder *legacyscheduler.SpecBuilder) *handler { handler.go
25 > return &handler{
26 > logger: logger,
27 > specBuilder: specBuilder,
28 > }
29 > }
30
31 func (h *handler) CreateSchedule(ctx context.Context, req *schedulerpb.CreateScheduleRequest) (resp *schedulerpb.CreateScheduleResponse, err error) {
go.temporal.io/server/common/dynamicconfig/fx.go 6 covered LOC · 2 ranges

Open complete file

8
9 var Module = fx.Options(
10 > fx.Provide(func(client Client, logger log.Logger, lc fx.Lifecycle) *Collection { fx.go
11 > col := NewCollection(client, logger)
12 > lc.Append(fx.StartStopHook(col.Start, col.Stop))
13 > return col
14 > }),
15 fx.Provide(fx.Annotate(
16 > func(c *Collection) pingable.Pingable { return c }, fx.go
17 fx.ResultTags(`group:"deadlockDetectorRoots"`),
18 )),
go.temporal.io/server/common/effect/buffer.go 6 covered LOC · 2 ranges

Open complete file

27 // to this Buffer.
28 // It returns true if any effects were applied.
29 > func (b *Buffer) Apply(ctx context.Context) bool { buffer.go
30 > applied := false
31 > b.cancels = nil
32 > for _, effect := range b.effects {
33 effect(ctx)
34 applied = true
35 }
36 > b.effects = nil buffer.go
37 > return applied
38 }
39
go.temporal.io/server/common/metrics/option.go 6 covered LOC · 2 ranges

Open complete file

10 type WithDescription string
11
12 > func (h WithDescription) apply(m *metricDefinition) { option.go
13 > m.description = string(h)
14 > }
15
16 // WithUnit sets the unit of a metric. See NewBytesHistogramDef for an example.
17 type WithUnit MetricUnit
18
19 > func (h WithUnit) apply(m *metricDefinition) { option.go
20 > m.unit = MetricUnit(h)
21 > }
go.temporal.io/server/common/persistence/nosql/nosqlplugin/cassandra/translator/fixed_address_translator.go 6 covered LOC · 2 ranges

Open complete file

15 )
16
17 > func init() { fixed_address_translator.go
18 > RegisterTranslator(fixedTranslatorName, NewFixedAddressTranslatorPlugin())
19 > }
20
21 type FixedAddressTranslatorPlugin struct {
22 }
23
24 > func NewFixedAddressTranslatorPlugin() TranslatorPlugin { fixed_address_translator.go
25 > return &FixedAddressTranslatorPlugin{}
26 > }
27
28 // GetTranslator What gocql driver does is that it will connect to the first node in the list in configuration
go.temporal.io/server/common/persistence/visibility/defs.go 6 covered LOC · 3 ranges

Open complete file

20 storeNames []string,
21 allowList dynamicconfig.BoolPropertyFnWithNamespaceFilter,
22 > ) dynamicconfig.BoolPropertyFnWithNamespaceFilter { defs.go
23 > if len(storeNames) == 0 {
24 return dynamicconfig.GetBoolPropertyFnFilteredByNamespace(false)
25 }
26
27 > switch storeNames[0] { defs.go
28 > case mysql.PluginName, postgresql.PluginName, postgresql.PluginNamePGX, sqlite.PluginName: defs.go
29 > // Advanced visibility with SQL DB don't support list of values
30 > return dynamicconfig.GetBoolPropertyFnFilteredByNamespace(false)
31 default:
32 // Otherwise (ES), check dynamic config
go.temporal.io/server/common/pprof/fx.go 6 covered LOC · 1 range

Open complete file

16 lc fx.Lifecycle,
17 pprof *PProfInitializerImpl,
18 > ) { fx.go
19 > lc.Append(
20 > fx.Hook{
21 > OnStart: func(context.Context) error {
22 > return pprof.Start()
23 > },
24 // todo: refactor pprof to gracefully shutdown http server
25 // OnStop: func(ctx context.Context) error {
go.temporal.io/server/common/quotas/noop_reservation_impl.go 6 covered LOC · 2 ranges

Open complete file

14
15 // OK returns whether the limiter can provide the requested number of tokens
16 > func (r *NoopReservationImpl) OK() bool { noop_reservation_impl.go
17 > return true
18 > }
19
20 // Cancel indicates that the reservation holder will not perform the reserved action
38 // DelayFrom returns the duration for which the reservation holder must wait
39 // before taking the reserved action. Zero duration means act immediately.
40 > func (r *NoopReservationImpl) DelayFrom(_ time.Time) time.Duration { noop_reservation_impl.go
41 > return time.Duration(0) // no delay
42 > }
go.temporal.io/server/common/rpc/encryption/local_store_per_host_cert_provider_map.go 6 covered LOC · 1 range

Open complete file

22 refreshInterval time.Duration,
23 logger log.Logger,
24 > ) *localStorePerHostCertProviderMap { local_store_per_host_cert_provider_map.go
25 >
26 > providerMap := &localStorePerHostCertProviderMap{}
27 > if overrides == nil {
28 > return providerMap
29 > }
30
31 providerMap.certProviderCache = make(map[string]CertProvider, len(overrides))
go.temporal.io/server/common/rpc/interceptor/logtags/workflow_service_server_gen.go 6 covered LOC · 2 ranges

Open complete file

8 )
9
10 > func (wt *WorkflowTags) extractFromWorkflowServiceServerMessage(message any) []tag.Tag { workflow_service_server_gen.go
11 > switch r := message.(type) {
12 case *workflowservice.CountActivityExecutionsRequest:
13 return nil
528 tag.WorkflowRunID(r.GetRunId()),
529 }
530 > case *workflowservice.StartWorkflowExecutionRequest: workflow_service_server_gen.go
531 > return []tag.Tag{
532 > tag.WorkflowID(r.GetWorkflowId()),
533 > }
534 case *workflowservice.StartWorkflowExecutionResponse:
535 return []tag.Tag{
go.temporal.io/server/common/testing/await/require_true.go 6 covered LOC · 3 ranges

Open complete file

16 // Use [RequireTrue] for simple local predicates only. Do not use assertions or
17 // side effects in the predicate - use [Require] for these.
18 > func RequireTrue(tb testing.TB, condition func() bool, timeout, pollInterval time.Duration) { require_true.go
19 > tb.Helper()
20 > run(testcontext.For(tb), tb, func(t *T) {
21 > if !condition() { require_true.go
22 > t.Fail() require_true.go
23 > }
24 }, legacyConfig(timeout, pollInterval, ""), "RequireTrue", requireTrueMisuseHint, false)
25 }
go.temporal.io/server/common/testing/await/t.go 6 covered LOC · 2 ranges

Open complete file

47
48 // Fail marks the current attempt as failed without stopping it.
49 > func (t *T) Fail() { t.go
50 > t.failed = true
51 > }
52
53 // Error records an error message for reporting on timeout.
83
84 // Failed reports whether this attempt has failed.
85 > func (t *T) Failed() bool { t.go
86 > return t.failed
87 > }
88
89 // Helper marks the calling function as a test helper.
go.temporal.io/server/common/wideevents/events.go 6 covered LOC · 1 range

Open complete file

25 // as an instrumentation-scope attribute (OTEL semconv service.name) so every emitted event carries
26 // it, replacing per-event common-tag plumbing.
27 > func NewLogger(lp log.LoggerProvider, serviceName string) log.Logger { events.go
28 > return lp.Logger(
29 > instrumentationName,
30 > log.WithInstrumentationAttributes(attribute.String("service.name", serviceName)),
31 > )
32 > }
33
34 // NoopLogger returns a logger that discards all events. Safe default for tests and for
go.temporal.io/server/service/frontend/validators.go 6 covered LOC · 5 ranges

Open complete file

13 )
14
15 > func validateExecution(w *commonpb.WorkflowExecution) error { validators.go
16 > if w == nil {
17 return errExecutionNotSet
18 }
19 > if w.GetWorkflowId() == "" { validators.go
20 return errWorkflowIDNotSet
21 }
22 > if w.GetRunId() != "" { validators.go
23 > if err := uuid.Validate(w.GetRunId()); err != nil { validators.go
24 return errInvalidRunID
25 }
26 }
27 > return nil validators.go
28 }
29
go.temporal.io/server/service/history/configs/task.go 6 covered LOC · 1 range

Open complete file

26 func ConvertWeightsToDynamicConfigValue(
27 weights map[tasks.Priority]int,
28 > ) map[string]any { task.go
29 > weightsForDC := make(map[string]any)
30 > for priority, weight := range weights {
31 > weightsForDC[priority.String()] = weight
32 > }
33 > return weightsForDC
34 }
35
go.temporal.io/server/service/history/replication/poller_manager.go 6 covered LOC · 1 range

Open complete file

24 currentShardId int32,
25 clusterMetadata cluster.Metadata,
26 > ) *pollerManagerImpl { poller_manager.go
27 > return &pollerManagerImpl{
28 > currentShardId: currentShardId,
29 > clusterMetadata: clusterMetadata,
30 > }
31 > }
32
33 func (p pollerManagerImpl) getSourceClusterShardIDs(sourceClusterName string) ([]int32, error) {
go.temporal.io/server/service/history/tasks/upsert_visibility_task.go 6 covered LOC · 2 ranges

Open complete file

38 }
39
40 > func (t *UpsertExecutionVisibilityTask) GetCategory() Category { upsert_visibility_task.go
41 > return CategoryVisibility
42 > }
43
44 > func (t *UpsertExecutionVisibilityTask) GetType() enumsspb.TaskType { upsert_visibility_task.go
45 > return enumsspb.TASK_TYPE_VISIBILITY_UPSERT_EXECUTION
46 > }
go.temporal.io/server/service/history/workflow/relocatable_attributes_fetcher.go 6 covered LOC · 1 range

Open complete file

33 config *configs.Config,
34 visibilityManager manager.VisibilityManager,
35 > ) RelocatableAttributesFetcher { relocatable_attributes_fetcher.go
36 > return &relocatableAttributesFetcher{
37 > visibilityManager: visibilityManager,
38 > disableFetchFromVisibility: config.DisableFetchRelocatableAttributesFromVisibility,
39 > }
40 > }
41
42 // RelocatableAttributes contains workflow attributes that can be moved from the mutable state to the persistence
go.temporal.io/server/service/history/workflow/task_refresher.go 6 covered LOC · 1 range

Open complete file

55 func NewTaskRefresher(
56 shard historyi.ShardContext,
57 > ) *TaskRefresherImpl { task_refresher.go
58 > return &TaskRefresherImpl{
59 > shard: shard,
60 > taskGeneratorProvider: GetTaskGeneratorProvider(),
61 > }
62 > }
63
64 func (r *TaskRefresherImpl) Refresh(
go.temporal.io/server/service/matching/backlog_manager.go 6 covered LOC · 1 range

Open complete file

272 }
273
274 > func rangeIDToTaskIDBlock(rangeID int64, rangeSize int64) taskIDBlock { backlog_manager.go
275 > return taskIDBlock{
276 > start: (rangeID-1)*rangeSize + 1,
277 > end: rangeID * rangeSize,
278 > }
279 > }
280
281 // Retry operation on transient error.
go.temporal.io/server/chasm/lib/scheduler/util.go 5 covered LOC · 1 range

Open complete file

26
27 // serializeConflictToken serializes a conflict token as a byte slice.
28 > func serializeConflictToken(conflictToken int64) []byte { util.go
29 > token := make([]byte, 8)
30 > binary.LittleEndian.PutUint64(token, uint64(conflictToken))
31 > return token
32 > }
33
34 // newTaggedLogger returns a logger tagged with the Scheduler's attributes.
go.temporal.io/server/chasm/ms_pointer.go 5 covered LOC · 1 range

Open complete file

18
19 // NewMSPointer creates a new MSPointer instance.
20 > func NewMSPointer(backend NodeBackend) MSPointer { ms_pointer.go
21 > return MSPointer{
22 > backend: backend,
23 > }
24 > }
25
26 // WorkflowRunTimeout returns the workflow run timeout duration. Returns 0 if no timeout is set.
go.temporal.io/server/common/cache/size_getter.go 5 covered LOC · 3 ranges

Open complete file

14 )
15
16 > func getSize(value any) int { size_getter.go
17 > if v, ok := value.(SizeGetter); ok {
18 > return v.CacheSize() size_getter.go
19 > }
20 // if the object does not have a CacheSize() method, assume is count limit cache, which size should be 1
21 > return 1 size_getter.go
22 }
go.temporal.io/server/common/collection/priority_queue.go 5 covered LOC · 1 range

Open complete file

15 func NewPriorityQueue[T any](
16 compareLess func(this T, other T) bool,
17 > ) Queue[T] { priority_queue.go
18 > return &priorityQueueImpl[T]{
19 > compareLess: compareLess,
20 > }
21 > }
22
23 // NewPriorityQueueWithItems creats a new priority queue
go.temporal.io/server/common/dynamicconfig/static_client.go 5 covered LOC · 4 ranges

Open complete file

go.temporal.io/server/common/metrics/registry.go 5 covered LOC · 1 range

Open complete file

43
44 // register adds a metric definition to the list of pending metric definitions. This method is thread-safe.
45 > func (c *registry) register(d metricDefinition) { registry.go
46 > c.Lock()
47 > defer c.Unlock()
48 > c.definitions = append(c.definitions, d)
49 > }
50
51 // buildCatalog builds a catalog from the list of pending metric definitions. It is safe to call this method multiple
go.temporal.io/server/common/nexus/trace.go 5 covered LOC · 1 range

Open complete file

72 }
73
74 > func NewLoggedHTTPClientTraceProvider(dc *dynamicconfig.Collection) HTTPClientTraceProvider { trace.go
75 > return &LoggedHTTPClientTraceProvider{
76 > Config: HTTPTraceConfig.Get(dc),
77 > }
78 > }
79
80 func (p *LoggedHTTPClientTraceProvider) NewTrace(attempt int32, logger log.Logger) *httptrace.ClientTrace {
go.temporal.io/server/common/persistence/sql/queue_v2.go 5 covered LOC · 1 range

Open complete file

37 logger log.Logger,
38 serializer serialization.Serializer,
39 > ) persistence.QueueV2 { queue_v2.go
40 > return &queueV2{
41 > SqlStore: NewSQLStore(db, logger, serializer),
42 > }
43 > }
44
45 func (q *queueV2) EnqueueMessage(
go.temporal.io/server/common/persistence/sql/sqlplugin/mysql/plugin.go 5 covered LOC · 1 range

Open complete file

24 var _ sqlplugin.Plugin = (*plugin)(nil)
25
26 > func init() { plugin.go
27 > sql.RegisterPlugin(PluginName, &plugin{
28 > queryConverter: &queryConverter{},
29 > })
30 > }
31
32 func (p *plugin) GetVisibilityQueryConverter() sqlplugin.VisibilityQueryConverter {
go.temporal.io/server/common/persistence/sql/sqlplugin/sqlite/task_user_data.go 5 covered LOC · 1 range

Open complete file

33 )
34
35 > func (mdb *db) GetTaskQueueUserData(ctx context.Context, request *sqlplugin.GetTaskQueueUserDataRequest) (*sqlplugin.VersionedBlob, error) { task_user_data.go
36 > var row sqlplugin.VersionedBlob
37 > err := mdb.conn.GetContext(ctx, &row, getTaskQueueUserDataQry, request.NamespaceID, request.TaskQueueName)
38 > return &row, err
39 > }
40
41 func (mdb *db) UpdateTaskQueueUserData(ctx context.Context, request *sqlplugin.UpdateTaskQueueDataRequest) error {
go.temporal.io/server/common/retrypolicy/retry_policy.go 5 covered LOC · 2 ranges

Open complete file

57
58 // Validate validates a retry policy
59 > func Validate(policy *commonpb.RetryPolicy) error { retry_policy.go
60 > if policy == nil {
61 > // nil policy is valid which means no retry retry_policy.go
62 > return nil
63 > }
64
65 if policy.GetMaximumAttempts() == 1 {
go.temporal.io/server/common/searchattribute/sadefs/util.go 5 covered LOC · 3 ranges

Open complete file

20 }
21
22 > func SetMetadataType(p *commonpb.Payload, t enumspb.IndexedValueType) { util.go
23 > if t == enumspb.INDEXED_VALUE_TYPE_UNSPECIFIED {
24 return
25 }
26
27 > _, isValidT := enumspb.IndexedValueType_name[int32(t)] util.go
28 > if !isValidT {
29 // nolint: forbidigo
30 panic(fmt.Sprintf("unknown index value type %v", t))
31 }
32 > p.Metadata[MetadataType] = []byte(t.String()) util.go
33 }
go.temporal.io/server/common/testing/await/report.go 5 covered LOC · 2 ranges

Open complete file

28 }
29
30 > func (r *timeoutReport) nextPoll() { report.go
31 > r.attempts++
32 > }
33
34 > func (r *timeoutReport) recordErrors(errors []string) { report.go
35 > if len(errors) > 0 {
36 r.failures = append(r.failures, attemptFailure{attempt: r.attempts, errors: errors})
37 }
go.temporal.io/server/service/history/api/worker_versioning_util.go 5 covered LOC · 1 range

Open complete file

38 shouldSkipReactivation bool,
39 revisionNumber int64,
41 > // Check if signals are enabled globally
42 > if !enabled {
43 > return
44 > }
45
46 // Skip signal if matching confirmed the version is active or still draining.
go.temporal.io/server/service/history/api/workflow_id_dedup.go 5 covered LOC · 1 range

Open complete file

261 wfIDReusePolicy *enumspb.WorkflowIdReusePolicy,
262 wfIDConflictPolicy *enumspb.WorkflowIdConflictPolicy,
264 > // workflow id reuse policy's Terminate-if-Running has been replaced by
265 > // workflow id conflict policy's Terminate-Existing
266 > //nolint:staticcheck // SA1019: intentional migration of deprecated policy
267 > if *wfIDReusePolicy == enumspb.WORKFLOW_ID_REUSE_POLICY_TERMINATE_IF_RUNNING {
268 *wfIDConflictPolicy = enumspb.WORKFLOW_ID_CONFLICT_POLICY_TERMINATE_EXISTING
269
go.temporal.io/server/service/history/chasm_notifier.go 5 covered LOC · 1 range

Open complete file

21
22 // NewChasmNotifier creates a new instance of ChasmNotifier.
23 > func NewChasmNotifier() *ChasmNotifier { chasm_notifier.go
24 > return &ChasmNotifier{
25 > executions: make(map[chasm.ExecutionKey]*subscriptionTracker),
26 > }
27 > }
28
29 // Subscribe returns a channel that will be closed when there is a notification relating to the
go.temporal.io/server/service/history/circuitbreakerpool/circuit_breaker_factory.go 5 covered LOC · 1 range

Open complete file

16 func NewCircuitBreakerPool[K comparable](
17 constructor func(key K) circuitbreaker.TwoStepCircuitBreaker,
18 > ) *CircuitBreakerPool[K] { circuit_breaker_factory.go
19 > return &CircuitBreakerPool[K]{
20 > m: collection.NewOnceMap(constructor),
21 > }
22 > }
go.temporal.io/server/service/history/replication/executable_task_converter.go 5 covered LOC · 1 range

Open complete file

27 func NewExecutableTaskConverter(
28 processToolBox ProcessToolBox,
29 > ) *executableTaskConverterImpl { executable_task_converter.go
30 > return &executableTaskConverterImpl{
31 > processToolBox: processToolBox,
32 > }
33 > }
34
35 func (e *executableTaskConverterImpl) Convert(
go.temporal.io/server/service/matching/bits.go 5 covered LOC · 1 range

Open complete file

7
8 // len returns the index of the highest set bit.
9 > func (bs bitSet) len() int32 { bits.go
10 > i := len(bs) - 1
11 > if i < 0 {
12 > return 0
13 > }
14 return int32(bits.Len64(bs[i]) + i*64)
15 }
go.temporal.io/server/service/matching/version_rule_helpers.go 5 covered LOC · 2 ranges

Open complete file

617 // FindRedirectBuildId follows chain of redirect rules starting from the given sourceBuildId and returns the final
618 // target build ID that should be used for redirect. Returns sourceBuildId if no applicable redirect rules exist.
619 > func FindRedirectBuildId(sourceBuildId string, rules []*persistencespb.RedirectRule) string { version_rule_helpers.go
620 > outer:
621 > for {
622 > for _, r := range rules {
623 if r.GetDeleteTimestamp() != nil {
624 continue
go.temporal.io/server/chasm/lib/callback/config.go 4 covered LOC · 1 range

Open complete file

44 }
45
46 > func configProvider(dc *dynamicconfig.Collection) *Config { config.go
47 > return &Config{
48 > RequestTimeout: RequestTimeout.Get(dc),
49 > RetryPolicy: func() backoff.RetryPolicy {
50 return backoff.NewExponentialRetryPolicy(
51 RetryPolicyInitialInterval.Get(dc)(),
go.temporal.io/server/common/clock/hybrid_logical_clock/hybrid_logical_clock.go 4 covered LOC · 2 ranges

Open complete file

85
86 // UTC returns a Time from a Clock in millisecond resolution. The Time's Location is set to UTC.
87 > func UTC(c *Clock) time.Time { hybrid_logical_clock.go
88 > if c == nil {
89 > return time.Unix(0, 0).UTC() hybrid_logical_clock.go
90 > }
91 return time.Unix(c.WallClock/1000, c.WallClock%1000*1000000).UTC()
92 }
go.temporal.io/server/common/links/validator.go 4 covered LOC · 3 ranges

Open complete file

12 // populated.
13 // nolint:revive // cognitive-complexity is high but justified to keep each case together for readability.
14 > func Validate(links []*commonpb.Link, maxAllowedLinks, maxSize int) error { validator.go
15 > if len(links) > maxAllowedLinks {
16 return serviceerror.NewInvalidArgumentf("cannot attach more than %d links per request, got %d", maxAllowedLinks, len(links))
17 }
18 > for _, l := range links { validator.go
19 if l.Size() > maxSize {
20 return serviceerror.NewInvalidArgumentf("link exceeds allowed size of %d, got %d", maxSize, l.Size())
go.temporal.io/server/common/metrics/metrics.go 4 covered LOC · 4 ranges

Open complete file

80 )
81
82 > func (c CounterFunc) Record(v int64, tags ...Tag) { c(v, tags...) } metrics.go
83 > func (c GaugeFunc) Record(v float64, tags ...Tag) { c(v, tags...) } metrics.go
84 > func (c TimerFunc) Record(v time.Duration, tags ...Tag) { c(v, tags...) } metrics.go
85 > func (c HistogramFunc) Record(v int64, tags ...Tag) { c(v, tags...) } metrics.go
go.temporal.io/server/common/persistence/error_type.go 4 covered LOC · 2 ranges

Open complete file

3 import "go.temporal.io/api/serviceerror"
4
5 > func OperationPossiblySucceeded(err error) bool { error_type.go
6 > switch err.(type) {
7 case *CurrentWorkflowConditionFailedError,
8 *WorkflowConditionFailedError,
17 // Persistence failure that means that write was definitely not committed.
18 return false
19 > default: error_type.go
20 > return true
21 }
22 }
go.temporal.io/server/common/persistence/noop_health_signal_aggregator.go 4 covered LOC · 4 ranges

Open complete file

go.temporal.io/server/common/persistence/sql/sqlplugin/mysql/typeconv.go 4 covered LOC · 2 ranges

Open complete file

33 }
34
35 > func getMinMySQLDateTime() time.Time { typeconv.go
36 > t, err := time.Parse(time.RFC3339, "1000-01-01T00:00:00Z")
37 > if err != nil {
38 return time.Unix(0, 0).UTC()
39 }
40 > return t.UTC() typeconv.go
41 }
go.temporal.io/server/common/persistence/sql/sqlplugin/postgresql/typeconv.go 4 covered LOC · 2 ranges

Open complete file

35 }
36
37 > func getMinPostgreSQLDateTime() time.Time { typeconv.go
38 > t, err := time.Parse(time.RFC3339, "1000-01-01T00:00:00Z")
39 > if err != nil {
40 return time.Unix(0, 0).UTC()
41 }
42 > return t.UTC() typeconv.go
43 }
go.temporal.io/server/common/priorities/priority_util.go 4 covered LOC · 3 ranges

Open complete file

49 }
50
51 > func Validate(p *commonpb.Priority) error { priority_util.go
52 > if p == nil {
53 > return nil priority_util.go
54 > } else if p.PriorityKey < 0 { priority_util.go
55 return ErrInvalidPriority
56 } else if err := ValidateFairnessKey(p.FairnessKey); err != nil {
go.temporal.io/server/components/callbacks/config.go 4 covered LOC · 1 range

Open complete file

38 }
39
40 > func ConfigProvider(dc *dynamicconfig.Collection) *Config { config.go
41 > return &Config{
42 > RequestTimeout: RequestTimeout.Get(dc),
43 > RetryPolicy: func() backoff.RetryPolicy {
44 return backoff.NewExponentialRetryPolicy(
45 RetryPolicyInitialInterval.Get(dc)(),
go.temporal.io/server/service/history/api/token.go 4 covered LOC · 1 range

Open complete file

65
66 // NOTE: DO NOT MODIFY UNLESS ALSO APPLIED TO ./service/frontend/token_deprecated.go
67 > func SerializeHistoryToken(token *tokenspb.HistoryContinuation) ([]byte, error) { token.go
68 > if token == nil {
69 > return nil, nil
70 > }
71 return token.Marshal()
72 }
go.temporal.io/server/service/history/circuitbreakerpool/fx.go 4 covered LOC · 1 range

Open complete file

22 namespaceRegistry namespace.Registry,
23 config *configs.Config,
24 > ) *OutboundQueueCircuitBreakerPool { fx.go
25 > return &OutboundQueueCircuitBreakerPool{
26 > CircuitBreakerPool: NewCircuitBreakerPool(
27 > func(key tasks.TaskGroupNamespaceIDAndDestination) circuitbreaker.TwoStepCircuitBreaker {
28 // This is intentionally not failing the function in case of error. The circuit breaker is
29 // agnostic to Task implementation, and thus the settings function is not expected to return
go.temporal.io/server/service/matching/metrics_util.go 4 covered LOC · 2 ranges

Open complete file

48 // recordDroppedTask records the tasks_dropped counter on the given physical-queue
49 // handler. It is a no-op when reason is dropReasonUnspecified (a non-drop completion).
50 > func recordDroppedTask(handler metrics.Handler, reason dropReason) { metrics_util.go
51 > if reason == dropReasonUnspecified {
52 > return metrics_util.go
53 > }
54 metrics.DroppedTasksCounter.With(handler).Record(1, reason.tag())
55 }
go.temporal.io/server/api/history/v1/message.go-helpers.pb.go 3 covered LOC · 1 range

Open complete file

54
55 // Size returns the size of the object, in bytes, once serialized
56 > func (val *VersionHistoryItem) Size() int { message.go-helpers.pb.go
57 > return proto.Size(val)
58 > }
59
60 // Equal returns whether two VersionHistoryItem values are equivalent by recursively
go.temporal.io/server/api/persistence/v1/predicates.go-helpers.pb.go 3 covered LOC · 1 range

Open complete file

17
18 // Size returns the size of the object, in bytes, once serialized
19 > func (val *Predicate) Size() int { predicates.go-helpers.pb.go
20 > return proto.Size(val)
21 > }
22
23 // Equal returns whether two Predicate values are equivalent by recursively
go.temporal.io/server/api/workflow/v1/message.go-helpers.pb.go 3 covered LOC · 1 range

Open complete file

91
92 // Size returns the size of the object, in bytes, once serialized
93 > func (val *BaseExecutionInfo) Size() int { message.go-helpers.pb.go
94 > return proto.Size(val)
95 > }
96
97 // Equal returns whether two BaseExecutionInfo values are equivalent by recursively
go.temporal.io/server/chasm/component.go 3 covered LOC · 1 range

Open complete file

122 ctx context.Context,
123 intent OperationIntent,
124 > ) context.Context { component.go
125 > return context.WithValue(ctx, operationIntentCtxKey, intent)
126 > }
127
128 func operationIntentFromContext(
go.temporal.io/server/chasm/engine.go 3 covered LOC · 1 range

Open complete file

496 ctx context.Context,
497 engine Engine,
498 > ) context.Context { engine.go
499 > return context.WithValue(ctx, engineCtxKey, engine)
500 > }
501
502 func engineFromContext(
go.temporal.io/server/chasm/fx.go 3 covered LOC · 1 range

Open complete file

6 "chasm",
7 fx.Provide(NewRegistry),
8 > fx.Invoke(func(registry *Registry) error { fx.go
9 > return registry.Register(&CoreLibrary{})
10 > }),
11 )
go.temporal.io/server/chasm/lib/tests/fx.go 3 covered LOC · 1 range

Open complete file

10 var Module = fx.Module(
11 "chasm.lib.tests",
12 > fx.Invoke(func(registry *chasm.Registry) error { fx.go
13 > return registry.Register(Library)
14 > }),
15 )
go.temporal.io/server/chasm/visibility_manager.go 3 covered LOC · 1 range

Open complete file

166 ctx context.Context,
167 engine VisibilityManager,
168 > ) context.Context { visibility_manager.go
169 > return context.WithValue(ctx, visibilityManagerCtxKey, engine)
170 > }
171
172 func visibilityManagerFromContext(
go.temporal.io/server/common/deadlock/fx.go 3 covered LOC · 1 range

Open complete file

7 var Module = fx.Options(
8 fx.Provide(NewDeadlockDetector),
9 > fx.Invoke(func(lc fx.Lifecycle, dd *deadlockDetector) { fx.go
10 > lc.Append(fx.StartStopHook(dd.Start, dd.Stop))
11 > }),
12 )
go.temporal.io/server/common/dynamicconfig/key.go 3 covered LOC · 1 range

Open complete file

13 )
14
15 > func MakeKey(s string) Key { key.go
16 > return Key{handle: unique.Make(strings.ToLower(s))}
17 > }
18
19 func (k Key) String() string {
go.temporal.io/server/common/log/noop_logger.go 3 covered LOC · 1 range

Open complete file

10
11 // NewNoopLogger return a noopLogger
12 > func NewNoopLogger() *noopLogger { noop_logger.go
13 > return &noopLogger{}
14 > }
15
16 func (n *noopLogger) Debug(string, ...tag.Tag) {}
go.temporal.io/server/common/metrics/panic.go 3 covered LOC · 1 range

Open complete file

13 // We have to use pointer is because in golang: "recover return nil if was not called directly by a deferred function."
14 // And we have to set the returned error otherwise our handler will return nil as error which is incorrect
15 > func CapturePanic(logger log.Logger, metricHandler Handler, retError *error) { panic.go
16 > //revive:disable-next-line:defer
17 > if pObj := recover(); pObj != nil {
18 err, ok := pObj.(error)
19 if !ok {
go.temporal.io/server/common/namespace/nsregistry/fx.go 3 covered LOC · 1 range

Open complete file

13 lc fx.Lifecycle,
14 registry namespace.Registry,
15 > ) { fx.go
16 > lc.Append(fx.StartStopHook(registry.Start, registry.Stop))
17 > }
go.temporal.io/server/common/namespace/nsreplication/data_merger.go 3 covered LOC · 1 range

Open complete file

12
13 // NewNoopDataMerger creates a new NoopDataMerger.
14 > func NewNoopDataMerger() NamespaceDataMerger { data_merger.go
15 > return &NoopDataMerger{}
16 > }
17
18 // MergeData returns taskData directly without any merging.
go.temporal.io/server/common/namespace/nsreplication/replication_admitter.go 3 covered LOC · 1 range

Open complete file

19
20 // NewDefaultAdmitter creates the default NamespaceReplicationAdmitter.
21 > func NewDefaultAdmitter() NamespaceReplicationAdmitter { replication_admitter.go
22 > return &DefaultAdmitter{}
23 > }
24
25 // Admit returns true iff currentCluster appears in the task's replication
go.temporal.io/server/common/nexus/callback_token.go 3 covered LOC · 1 range

Open complete file

33 }
34
35 > func NewCallbackTokenGenerator() *CallbackTokenGenerator { callback_token.go
36 > return &CallbackTokenGenerator{}
37 > }
38
39 func (g *CallbackTokenGenerator) Tokenize(completion *tokenspb.NexusOperationCompletion) (string, error) {
go.temporal.io/server/common/nexus/nexusrpc/failure_converter.go 3 covered LOC · 1 range

Open complete file

196 // [Failure] instances are converted to [FailureError] to allow access to the full failure metadata and details if
197 // available.
198 > func DefaultFailureConverter() FailureConverter { failure_converter.go
199 > return defaultFailureConverter
200 > }
201
202 func retryBehaviorAsOptionalBool(e *nexus.HandlerError) *bool {
go.temporal.io/server/common/persistence/nosql/nosqlplugin/cassandra/translator/translator_plugin.go 3 covered LOC · 1 range

Open complete file

22 // RegisterPlugin adds an auth plugin to the plugin registry
23 // it is only safe to use from a package init function
24 > func RegisterTranslator(name string, plugin TranslatorPlugin) { translator_plugin.go
25 > translators[name] = plugin
26 > }
27
28 func LookupTranslator(name string) (TranslatorPlugin, error) {
go.temporal.io/server/common/quotas/noop_request_rate_limiter_impl.go 3 covered LOC · 1 range

Open complete file

go.temporal.io/server/common/quotas/request_rate_limiter_delegator.go 3 covered LOC · 1 range

Open complete file

24
25 // SetRateLimiter sets the rate limiter to delegate to.
26 > func (d *RequestRateLimiterDelegator) SetRateLimiter(rl RequestRateLimiter) { request_rate_limiter_delegator.go
27 > d.delegate.Store(monomorphicRequestRateLimiter{rl})
28 > }
29
30 // loadDelegate returns the rate limiter that this rate limiter delegates to.
go.temporal.io/server/common/resolver/noop_resolver.go 3 covered LOC · 1 range

Open complete file

6 )
7
8 > func NewNoopResolver() *NoopResolver { noop_resolver.go
9 > return &NoopResolver{}
10 > }
11
12 func (c *NoopResolver) Resolve(service string) []string {
go.temporal.io/server/common/serviceerror/stale_partition_counts.go 3 covered LOC · 1 range

Open complete file

16
17 // NewStalePartitionCounts returns new StalePartitionCounts error.
18 > func NewStalePartitionCounts(message string) error { stale_partition_counts.go
19 > return &StalePartitionCounts{Message: message}
20 > }
21
22 // Error returns string message.
go.temporal.io/server/common/softassert/softassert.go 3 covered LOC · 2 ranges

Open complete file

26 // Example:
27 // softassert.That(logger, object.state == "ready", "object is not ready")
28 > func That(logger log.Logger, condition bool, staticMessage string, tags ...tag.Tag) bool { softassert.go
29 > if !condition {
30 // By using the same prefix for all assertions, they can be reliably found in logs.
31 logger.Error("failed assertion: "+staticMessage, append([]tag.Tag{tag.FailedAssertion}, tags...)...)
32 }
33 > return condition softassert.go
34 }
35
go.temporal.io/server/components/nexusoperations/completion.go 3 covered LOC · 1 range

Open complete file

174
175 // NewCompletionHandler returns a CompletionHandler. Wired via fx; see Module.
176 > func NewCompletionHandler(metricsHandler metrics.Handler, config *Config) *CompletionHandler { completion.go
177 > return &CompletionHandler{metricsHandler: metricsHandler, config: config}
178 > }
179
180 // Handle resolves an async Nexus operation completion.
go.temporal.io/server/components/nexusoperations/fx.go 3 covered LOC · 1 range

Open complete file

15 fx.Invoke(RegisterExecutor),
16 // Bridge CHASM ClientProvider to HSM ClientProvider type.
17 > fx.Provide(func(cp chasmnexus.ClientProvider) ClientProvider { fx.go
18 > return ClientProvider(cp)
19 > }),
20 )
21
go.temporal.io/server/service/history/archival/fx.go 3 covered LOC · 1 range

Open complete file

9 var Module = fx.Options(
10 fx.Provide(NewArchiver),
11 > fx.Provide(func(config *configs.Config) quotas.RateLimiter { fx.go
12 > return quotas.NewDefaultOutgoingRateLimiter(quotas.RateFn(config.ArchivalBackendMaxRPS))
13 > }),
14 )
go.temporal.io/server/service/history/events/fx.go 3 covered LOC · 1 range

Open complete file

10
11 var Module = fx.Options(
12 > fx.Provide(func(executionManager persistence.ExecutionManager, config *configs.Config, handler metrics.Handler, logger log.Logger) Cache { fx.go
13 > return NewHostLevelEventsCache(executionManager, config, handler, logger, false)
14 > }),
15 )
go.temporal.io/server/service/history/queues/errors/errors.go 3 covered LOC · 1 range

Open complete file

39
40 // NewUnprocessableTaskError returns a new UnprocessableTaskError from given message.
41 > func NewUnprocessableTaskError(message string) *UnprocessableTaskError { errors.go
42 > return &UnprocessableTaskError{Message: message}
43 > }
44
45 func (e UnprocessableTaskError) Error() string {
go.temporal.io/server/service/history/queues/grouper.go 3 covered LOC · 1 range

Open complete file

17 }
18
19 > func (GrouperNamespaceID) Key(task tasks.Task) (key any) { grouper.go
20 > return task.GetNamespaceID()
21 > }
22
23 func (GrouperNamespaceID) Predicate(keys []any) tasks.Predicate {
go.temporal.io/server/service/matching/loadcause_string_gen.go 3 covered LOC · 2 ranges

Open complete file

25 var _loadCause_index = [...]uint8{0, 11, 15, 20, 28, 36, 45, 49, 58, 68, 73}
26
27 > func (i loadCause) String() string { loadcause_string_gen.go
28 > if i < 0 || i >= loadCause(len(_loadCause_index)-1) {
29 return "loadCause(" + strconv.FormatInt(int64(i), 10) + ")"
30 }
31 > return _loadCause_name[_loadCause_index[i]:_loadCause_index[i+1]] loadcause_string_gen.go
32 }
go.temporal.io/server/service/matching/unloadcause_string_gen.go 3 covered LOC · 2 ranges

Open complete file

24 var _unloadCause_index = [...]uint8{0, 11, 20, 24, 34, 42, 54, 59, 71, 81}
25
26 > func (i unloadCause) String() string { unloadcause_string_gen.go
27 > if i < 0 || i >= unloadCause(len(_unloadCause_index)-1) {
28 return "unloadCause(" + strconv.FormatInt(int64(i), 10) + ")"
29 }
30 > return _unloadCause_name[_unloadCause_index[i]:_unloadCause_index[i+1]] unloadcause_string_gen.go
31 }
go.temporal.io/server/service/worker/common/fx.go 3 covered LOC · 1 range

Open complete file

10 // AnnotateWorkerComponentProvider converts a WorkerComponent factory function into an fx provider which will add the
11 // WorkerComponentTag to the result.
12 > func AnnotateWorkerComponentProvider[T any](f func(t T) WorkerComponent) fx.Option { fx.go
13 > return fx.Provide(fx.Annotate(f, fx.ResultTags(WorkerComponentTag)))
14 > }
go.temporal.io/server/temporal/server.go 3 covered LOC · 1 range

Open complete file

42
43 // NewServer returns a new instance of server that serves one or many services.
44 > func NewServer(opts ...ServerOption) (Server, error) { server.go
45 > return NewServerFx(TopLevelModule, opts...)
46 > }
go.temporal.io/server/common/log/panic.go 2 covered LOC · 1 range

Open complete file

13 // We have to use pointer is because in golang: "recover return nil if was not called directly by a deferred function."
14 // And we have to set the returned error otherwise our handler will return nil as error which is incorrect
15 > func CapturePanic(logger Logger, retError *error) { panic.go
16 > if panicObj := recover(); panicObj != nil {
17 err, ok := panicObj.(error)
18 if !ok {
go.temporal.io/server/common/aggregate/noop_moving_window_average.go 1 covered LOC · 1 range

Open complete file

7 )
8
9 > func newNoopMovingWindowAverage() *noopMovingWindowAverage { return &noopMovingWindowAverage{} } noop_moving_window_average.go
10
11 func (a *noopMovingWindowAverage) Record(_ int64) {}