mirror of
https://github.com/hanzoai/tasks.git
synced 2026-10-04 02:04:03 +00:00
## What changed? Cherry-pick versioning PRs - #9168 - Cache for system protection - #9262 - Cache for system protection - #9239 - Critical PR to enable sending `TargetVersionChanged` flag for Upgrade-on-CaN feature - #9147 - Tracks version drainage properly when version receives workflows via `VersioningOverride`. Needed for automated worker controllers to correctly scale versioned workers that received workflows via `VersioningOverride`. - #9300 - Needed for `approximate_backlog_count` metric to track Current and Ramping version tasks correctly - #9316 - Needed for `approximate_backlog_count` metric to track Current and Ramping version tasks correctly - #8957 - Contains minor metric improvement. Included because it adds a test harness that is used in the two metrics PRs above - #9250 - Bug fix of task rescheduling edge case during AutoUpgrade Transition ## Why? For OSS v1.30.2 ## How did you test it? - [x] built - [ ] run locally and tested manually - [x] covered by existing tests - [ ] added new unit test(s) - [ ] added new functional test(s) --- > [!NOTE] > **Medium Risk** > Touches history/matching worker-versioning paths, adding new caches and changing workflow task/start handling and backlog metric emission; incorrect caching or signaling could affect dispatch/upgrade behavior and observability. > > **Overview** > Adds new worker-versioning protections and upgrade signaling: workflow task started events now persist a `workflow_task_target_worker_deployment_version_changed` flag (and emit a new `workflow_target_version_changed_count` metric) under a new `EnableSendTargetVersionChanged` dynamic config. > > Introduces two new caches with metrics and dynamic config knobs: a `RoutingInfoCache` to avoid repeated `GetTaskQueueUserData` lookups during activity start/transition logic, and a `ReactivationSignalCache` plus `EnableVersionReactivationSignals` to dedupe and asynchronously send “reactivation” signals when workflows are pinned (via start/signal-with-start/reset/update-options) to potentially drained/inactive worker versions. > > Extends matching backlog metrics to support version-attributed reporting by adding `BacklogMetricsEmitInterval` and switching queue DB emission to *physical* backlog gauges (`physical_approximate_backlog_*`) when attribution is enabled, while keeping legacy gauges when disabled. > > Adds frontend scaffolding for a new visibility RPC `CountSchedules` (client plumbing, interception/metadata/quota wiring) but leaves the frontend handler unimplemented, and bumps `go.temporal.io/api` to `v1.62.2`. > > <sup>Written by [Cursor Bugbot]() for commit cb8ae14c86666654c51dd66ae91cb225722e1ba7. This will update automatically on new commits. Configure [here]().</sup> --------- Co-authored-by: Shahab Tajik <[email protected]> Co-authored-by: Shivam <[email protected]>
200 lines
5.9 KiB
Go
200 lines
5.9 KiB
Go
package history
|
|
|
|
import (
|
|
"go.temporal.io/server/client"
|
|
"go.temporal.io/server/common/log"
|
|
"go.temporal.io/server/common/log/tag"
|
|
"go.temporal.io/server/common/metrics"
|
|
"go.temporal.io/server/common/persistence/visibility/manager"
|
|
"go.temporal.io/server/common/resource"
|
|
"go.temporal.io/server/common/sdk"
|
|
"go.temporal.io/server/common/telemetry"
|
|
"go.temporal.io/server/common/worker_versioning"
|
|
historyi "go.temporal.io/server/service/history/interfaces"
|
|
"go.temporal.io/server/service/history/queues"
|
|
"go.temporal.io/server/service/history/tasks"
|
|
"go.uber.org/fx"
|
|
)
|
|
|
|
const (
|
|
transferQueuePersistenceMaxRPSRatio = 0.3
|
|
)
|
|
|
|
type (
|
|
transferQueueFactoryParams struct {
|
|
fx.In
|
|
|
|
QueueFactoryBaseParams
|
|
|
|
ClientBean client.Bean
|
|
SdkClientFactory sdk.ClientFactory
|
|
HistoryRawClient resource.HistoryRawClient
|
|
MatchingRawClient resource.MatchingRawClient
|
|
VisibilityManager manager.VisibilityManager
|
|
VersionMembershipCache worker_versioning.VersionMembershipCache
|
|
}
|
|
|
|
transferQueueFactory struct {
|
|
transferQueueFactoryParams
|
|
QueueFactoryBase
|
|
}
|
|
)
|
|
|
|
func NewTransferQueueFactory(
|
|
params transferQueueFactoryParams,
|
|
) QueueFactory {
|
|
return &transferQueueFactory{
|
|
transferQueueFactoryParams: params,
|
|
QueueFactoryBase: QueueFactoryBase{
|
|
HostScheduler: queues.NewScheduler(
|
|
params.ClusterMetadata.GetCurrentClusterName(),
|
|
queues.SchedulerOptions{
|
|
WorkerCount: params.Config.TransferProcessorSchedulerWorkerCount,
|
|
ActiveNamespaceWeights: params.Config.TransferProcessorSchedulerActiveRoundRobinWeights,
|
|
StandbyNamespaceWeights: params.Config.TransferProcessorSchedulerStandbyRoundRobinWeights,
|
|
InactiveNamespaceDeletionDelay: params.Config.TaskSchedulerInactiveChannelDeletionDelay,
|
|
},
|
|
params.NamespaceRegistry,
|
|
params.Logger,
|
|
),
|
|
HostPriorityAssigner: queues.NewPriorityAssigner(
|
|
params.NamespaceRegistry,
|
|
params.ClusterMetadata.GetCurrentClusterName(),
|
|
),
|
|
HostReaderRateLimiter: queues.NewReaderPriorityRateLimiter(
|
|
NewHostRateLimiterRateFn(
|
|
params.Config.TransferProcessorMaxPollHostRPS,
|
|
params.Config.PersistenceMaxQPS,
|
|
transferQueuePersistenceMaxRPSRatio,
|
|
),
|
|
int64(params.Config.TransferQueueMaxReaderCount()),
|
|
),
|
|
Tracer: params.TracerProvider.Tracer(telemetry.ComponentQueueTransfer),
|
|
},
|
|
}
|
|
}
|
|
|
|
func (f *transferQueueFactory) CreateQueue(
|
|
shardContext historyi.ShardContext,
|
|
) queues.Queue {
|
|
logger := log.With(shardContext.GetLogger(), tag.ComponentTransferQueue)
|
|
metricsHandler := f.MetricsHandler.WithTags(metrics.OperationTag(metrics.OperationTransferQueueProcessorScope))
|
|
|
|
currentClusterName := f.ClusterMetadata.GetCurrentClusterName()
|
|
|
|
var shardScheduler = f.HostScheduler
|
|
if f.Config.TaskSchedulerEnableRateLimiter() {
|
|
shardScheduler = queues.NewRateLimitedScheduler(
|
|
f.HostScheduler,
|
|
queues.RateLimitedSchedulerOptions{
|
|
EnableShadowMode: f.Config.TaskSchedulerEnableRateLimiterShadowMode,
|
|
StartupDelay: f.Config.TaskSchedulerRateLimiterStartupDelay,
|
|
},
|
|
currentClusterName,
|
|
f.NamespaceRegistry,
|
|
f.SchedulerRateLimiter,
|
|
f.TimeSource,
|
|
f.ChasmRegistry,
|
|
logger,
|
|
metricsHandler,
|
|
)
|
|
}
|
|
|
|
rescheduler := queues.NewRescheduler(
|
|
shardScheduler,
|
|
shardContext.GetTimeSource(),
|
|
logger,
|
|
metricsHandler,
|
|
)
|
|
|
|
activeExecutor := newTransferQueueActiveTaskExecutor(
|
|
shardContext,
|
|
f.WorkflowCache,
|
|
f.SdkClientFactory,
|
|
logger,
|
|
f.MetricsHandler,
|
|
f.Config,
|
|
f.HistoryRawClient,
|
|
f.MatchingRawClient,
|
|
f.VisibilityManager,
|
|
f.ChasmEngine,
|
|
f.VersionMembershipCache,
|
|
)
|
|
|
|
standbyExecutor := newTransferQueueStandbyTaskExecutor(
|
|
shardContext,
|
|
f.WorkflowCache,
|
|
logger,
|
|
f.MetricsHandler,
|
|
currentClusterName,
|
|
f.HistoryRawClient,
|
|
f.MatchingRawClient,
|
|
f.VisibilityManager,
|
|
f.ChasmEngine,
|
|
f.ClientBean,
|
|
)
|
|
|
|
executor := queues.NewActiveStandbyExecutor(
|
|
currentClusterName,
|
|
f.NamespaceRegistry,
|
|
activeExecutor,
|
|
standbyExecutor,
|
|
logger,
|
|
)
|
|
if f.ExecutorWrapper != nil {
|
|
executor = f.ExecutorWrapper.Wrap(executor)
|
|
}
|
|
|
|
factory := queues.NewExecutableFactory(
|
|
executor,
|
|
shardScheduler,
|
|
rescheduler,
|
|
f.HostPriorityAssigner,
|
|
shardContext.GetTimeSource(),
|
|
shardContext.GetNamespaceRegistry(),
|
|
shardContext.GetClusterMetadata(),
|
|
f.ChasmRegistry,
|
|
queues.GetTaskTypeTagValue,
|
|
logger,
|
|
metricsHandler,
|
|
f.Tracer,
|
|
f.DLQWriter,
|
|
f.Config.TaskDLQEnabled,
|
|
f.Config.TaskDLQUnexpectedErrorAttempts,
|
|
f.Config.TaskDLQInternalErrors,
|
|
f.Config.TaskDLQErrorPattern,
|
|
)
|
|
return queues.NewImmediateQueue(
|
|
shardContext,
|
|
tasks.CategoryTransfer,
|
|
shardScheduler,
|
|
rescheduler,
|
|
&queues.Options{
|
|
ReaderOptions: queues.ReaderOptions{
|
|
BatchSize: f.Config.TransferTaskBatchSize,
|
|
MaxPendingTasksCount: f.Config.QueuePendingTaskMaxCount,
|
|
PollBackoffInterval: f.Config.TransferProcessorPollBackoffInterval,
|
|
MaxPredicateSize: f.Config.QueueMaxPredicateSize,
|
|
},
|
|
MonitorOptions: queues.MonitorOptions{
|
|
PendingTasksCriticalCount: f.Config.QueuePendingTaskCriticalCount,
|
|
ReaderStuckCriticalAttempts: f.Config.QueueReaderStuckCriticalAttempts,
|
|
SliceCountCriticalThreshold: f.Config.QueueCriticalSlicesCount,
|
|
},
|
|
MaxPollRPS: f.Config.TransferProcessorMaxPollRPS,
|
|
MaxPollInterval: f.Config.TransferProcessorMaxPollInterval,
|
|
MaxPollIntervalJitterCoefficient: f.Config.TransferProcessorMaxPollIntervalJitterCoefficient,
|
|
CheckpointInterval: f.Config.TransferProcessorUpdateAckInterval,
|
|
CheckpointIntervalJitterCoefficient: f.Config.TransferProcessorUpdateAckIntervalJitterCoefficient,
|
|
MaxReaderCount: f.Config.TransferQueueMaxReaderCount,
|
|
MoveGroupTaskCountBase: f.Config.QueueMoveGroupTaskCountBase,
|
|
MoveGroupTaskCountMultiplier: f.Config.QueueMoveGroupTaskCountMultiplier,
|
|
},
|
|
f.HostReaderRateLimiter,
|
|
queues.GrouperNamespaceID{},
|
|
logger,
|
|
metricsHandler,
|
|
factory,
|
|
)
|
|
}
|