From 930e9d9598d301f4206f3bae74fba889ee0941dd Mon Sep 17 00:00:00 2001 From: Kannan Rajah Date: Thu, 30 Apr 2026 17:13:12 -0700 Subject: [PATCH 1/5] Use task queue kind instead of name prefix for nexus metrics is_internal tag Replace string prefix check on task queue name with TASK_QUEUE_KIND_WORKER_COMMANDS enum check, now that the kind exists. Co-Authored-By: Claude Opus 4.6 --- service/matching/handler.go | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/service/matching/handler.go b/service/matching/handler.go index 8359f88baad..66e8be9849c 100644 --- a/service/matching/handler.go +++ b/service/matching/handler.go @@ -2,7 +2,6 @@ package matching import ( "context" - "strings" "sync" "time" @@ -156,18 +155,12 @@ func (h *Handler) opMetricsHandler( ) } -// internalTaskQueuePrefix identifies server-internal task queues -// (e.g. /temporal-sys/worker-commands/{namespace}/{worker_grouping_key}). -// Note: BreakdownMetricsByTaskQueue should NOT be enabled for these queues as -// they are per-worker and will cause cardinality explosion. -const internalTaskQueuePrefix = "/temporal-sys/" - // recordNexusTaskRequest emits the nexus_task_requests metric with namespace, // operation, client_name, and is_internal tags. -func (h *Handler) recordNexusTaskRequest(ctx context.Context, namespaceID string, taskQueueName string, operation string) { +func (h *Handler) recordNexusTaskRequest(ctx context.Context, namespaceID string, taskQueueKind enumspb.TaskQueueKind, operation string) { nsName := h.namespaceName(namespace.ID(namespaceID)) clientName, _ := headers.GetClientNameAndVersion(ctx) - isInternal := strings.HasPrefix(taskQueueName, internalTaskQueuePrefix) + isInternal := taskQueueKind == enumspb.TASK_QUEUE_KIND_WORKER_COMMANDS metrics.NexusTaskRequests.With(h.metricsHandler).Record(1, metrics.NamespaceTag(nsName.String()), metrics.OperationTag(operation), @@ -531,7 +524,7 @@ func (h *Handler) PollNexusTaskQueue(ctx context.Context, request *matchingservi // Only record on the initial handler call (ForwardedSource == ""), not on // the forwarded call to the root partition, to avoid double-counting. if request.GetForwardedSource() == "" { - h.recordNexusTaskRequest(ctx, request.GetNamespaceId(), request.GetRequest().GetTaskQueue().GetName(), "PollNexusTaskQueue") + h.recordNexusTaskRequest(ctx, request.GetNamespaceId(), request.GetRequest().GetTaskQueue().GetKind(), "PollNexusTaskQueue") } if request.GetForwardedSource() != "" { @@ -556,7 +549,7 @@ func (h *Handler) RespondNexusTaskCompleted(ctx context.Context, request *matchi enumspb.TASK_QUEUE_TYPE_NEXUS, metrics.MatchingRespondNexusTaskCompletedScope, ) - h.recordNexusTaskRequest(ctx, request.GetNamespaceId(), request.GetTaskQueue().GetName(), "RespondNexusTaskCompleted") + h.recordNexusTaskRequest(ctx, request.GetNamespaceId(), request.GetTaskQueue().GetKind(), "RespondNexusTaskCompleted") return h.engine.RespondNexusTaskCompleted(ctx, request, opMetrics) } @@ -569,7 +562,7 @@ func (h *Handler) RespondNexusTaskFailed(ctx context.Context, request *matchings enumspb.TASK_QUEUE_TYPE_NEXUS, metrics.MatchingRespondNexusTaskFailedScope, ) - h.recordNexusTaskRequest(ctx, request.GetNamespaceId(), request.GetTaskQueue().GetName(), "RespondNexusTaskFailed") + h.recordNexusTaskRequest(ctx, request.GetNamespaceId(), request.GetTaskQueue().GetKind(), "RespondNexusTaskFailed") return h.engine.RespondNexusTaskFailed(ctx, request, opMetrics) } From 73333a3e2b087bf8fd4ca06d8625a2743dce04fc Mon Sep 17 00:00:00 2001 From: Kannan Rajah Date: Thu, 30 Apr 2026 18:24:23 -0700 Subject: [PATCH 2/5] Add IsInternalTaskQueueKind to primitives and update test Centralize the internal task queue kind check in common/primitives alongside the existing internal task queue helpers. Update the handler test to use TASK_QUEUE_KIND_WORKER_COMMANDS instead of relying on the name prefix. Co-Authored-By: Claude Opus 4.6 --- common/primitives/task_queues.go | 7 +++++++ service/matching/handler.go | 3 ++- service/matching/handler_test.go | 6 +++--- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/common/primitives/task_queues.go b/common/primitives/task_queues.go index 2a8433ff706..50324386b11 100644 --- a/common/primitives/task_queues.go +++ b/common/primitives/task_queues.go @@ -3,6 +3,7 @@ package primitives import ( "fmt" + enumspb "go.temporal.io/api/enums/v1" "go.temporal.io/api/serviceerror" ) @@ -17,6 +18,12 @@ const ( DLQActivityTQ = "temporal-sys-dlq-activity-tq" ) +// IsInternalTaskQueueKind returns true if the task queue kind identifies a +// server-internal task queue (e.g. worker commands queues). +func IsInternalTaskQueueKind(kind enumspb.TaskQueueKind) bool { + return kind == enumspb.TASK_QUEUE_KIND_WORKER_COMMANDS +} + func IsInternalPerNsTaskQueue(taskQueue string) bool { return taskQueue == PerNSWorkerTaskQueue } diff --git a/service/matching/handler.go b/service/matching/handler.go index 66e8be9849c..cfb754d5742 100644 --- a/service/matching/handler.go +++ b/service/matching/handler.go @@ -17,6 +17,7 @@ import ( "go.temporal.io/server/common/membership" "go.temporal.io/server/common/metrics" "go.temporal.io/server/common/namespace" + "go.temporal.io/server/common/primitives" "go.temporal.io/server/common/persistence" "go.temporal.io/server/common/persistence/serialization" "go.temporal.io/server/common/persistence/visibility/manager" @@ -160,7 +161,7 @@ func (h *Handler) opMetricsHandler( func (h *Handler) recordNexusTaskRequest(ctx context.Context, namespaceID string, taskQueueKind enumspb.TaskQueueKind, operation string) { nsName := h.namespaceName(namespace.ID(namespaceID)) clientName, _ := headers.GetClientNameAndVersion(ctx) - isInternal := taskQueueKind == enumspb.TASK_QUEUE_KIND_WORKER_COMMANDS + isInternal := primitives.IsInternalTaskQueueKind(taskQueueKind) metrics.NexusTaskRequests.With(h.metricsHandler).Record(1, metrics.NamespaceTag(nsName.String()), metrics.OperationTag(operation), diff --git a/service/matching/handler_test.go b/service/matching/handler_test.go index bbe64cc0591..f102c07d231 100644 --- a/service/matching/handler_test.go +++ b/service/matching/handler_test.go @@ -178,7 +178,7 @@ func TestNexusHandlersEmitClientNameMetric(t *testing.T) { "should not have client_name tag when header is absent, got: %v", snap) }) - t.Run("is_internal for /temporal-sys/ task queue", func(t *testing.T) { + t.Run("is_internal for worker commands task queue kind", func(t *testing.T) { captureHandler := metricstest.NewCaptureHandler() capture := captureHandler.StartCapture() defer captureHandler.StopCapture(capture) @@ -187,7 +187,7 @@ func TestNexusHandlersEmitClientNameMetric(t *testing.T) { ctx := ctxWithClientName(t, expectedClientName) internalTQ := &taskqueuepb.TaskQueue{ Name: "/temporal-sys/worker-commands/ns/grouping-key", - Kind: enumspb.TASK_QUEUE_KIND_NORMAL, + Kind: enumspb.TASK_QUEUE_KIND_WORKER_COMMANDS, } _, err := h.PollNexusTaskQueue(ctx, &matchingservice.PollNexusTaskQueueRequest{ @@ -201,7 +201,7 @@ func TestNexusHandlersEmitClientNameMetric(t *testing.T) { snap := capture.Snapshot() require.NotEmpty(t, snap[nexusTaskRequestsMetric]) require.True(t, findMetricWithTag(snap, nexusTaskRequestsMetric, "is_internal", "true"), - "should have is_internal=true for /temporal-sys/ task queue, got: %v", snap) + "should have is_internal=true for worker commands task queue kind, got: %v", snap) }) } From 6cee9a599c6d61e85bc2b50066dcc9607706a05a Mon Sep 17 00:00:00 2001 From: Kannan Rajah Date: Thu, 30 Apr 2026 18:31:40 -0700 Subject: [PATCH 3/5] Use exhaustive switch in IsInternalTaskQueueKind, remove name dependency in test Enumerate all TaskQueueKind values explicitly so adding a new kind forces a decision about whether it's internal. Use a plain task queue name in the test to prove is_internal depends only on the kind. Co-Authored-By: Claude Opus 4.6 --- common/primitives/task_queues.go | 12 +++++++++++- service/matching/handler_test.go | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/common/primitives/task_queues.go b/common/primitives/task_queues.go index 50324386b11..70f26a30c6c 100644 --- a/common/primitives/task_queues.go +++ b/common/primitives/task_queues.go @@ -20,8 +20,18 @@ const ( // IsInternalTaskQueueKind returns true if the task queue kind identifies a // server-internal task queue (e.g. worker commands queues). +// All kinds are listed explicitly so that adding a new kind produces a compile error. func IsInternalTaskQueueKind(kind enumspb.TaskQueueKind) bool { - return kind == enumspb.TASK_QUEUE_KIND_WORKER_COMMANDS + switch kind { + case enumspb.TASK_QUEUE_KIND_WORKER_COMMANDS: + return true + case enumspb.TASK_QUEUE_KIND_UNSPECIFIED, + enumspb.TASK_QUEUE_KIND_NORMAL, + enumspb.TASK_QUEUE_KIND_STICKY: + return false + default: + return false + } } func IsInternalPerNsTaskQueue(taskQueue string) bool { diff --git a/service/matching/handler_test.go b/service/matching/handler_test.go index f102c07d231..aee197be787 100644 --- a/service/matching/handler_test.go +++ b/service/matching/handler_test.go @@ -186,7 +186,7 @@ func TestNexusHandlersEmitClientNameMetric(t *testing.T) { h, _ := newTestHandler(t, captureHandler) ctx := ctxWithClientName(t, expectedClientName) internalTQ := &taskqueuepb.TaskQueue{ - Name: "/temporal-sys/worker-commands/ns/grouping-key", + Name: "some-task-queue", Kind: enumspb.TASK_QUEUE_KIND_WORKER_COMMANDS, } From 56ce4e7cf4e848326219c2de975a1dd4704f0cd1 Mon Sep 17 00:00:00 2001 From: Kannan Rajah Date: Thu, 30 Apr 2026 18:34:40 -0700 Subject: [PATCH 4/5] Remove default case to enable exhaustive lint check Without the default case, the exhaustive linter will flag this switch when a new TaskQueueKind is added, forcing the developer to decide whether the new kind is internal. Co-Authored-By: Claude Opus 4.6 --- common/primitives/task_queues.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common/primitives/task_queues.go b/common/primitives/task_queues.go index 70f26a30c6c..4a2910d4dcb 100644 --- a/common/primitives/task_queues.go +++ b/common/primitives/task_queues.go @@ -29,9 +29,8 @@ func IsInternalTaskQueueKind(kind enumspb.TaskQueueKind) bool { enumspb.TASK_QUEUE_KIND_NORMAL, enumspb.TASK_QUEUE_KIND_STICKY: return false - default: - return false } + return false } func IsInternalPerNsTaskQueue(taskQueue string) bool { From 535ef71a8ceaf235fe6c3fd584f4f3de3230b864 Mon Sep 17 00:00:00 2001 From: Kannan Rajah Date: Fri, 1 May 2026 12:41:30 -0700 Subject: [PATCH 5/5] Fix import ordering in handler.go Co-Authored-By: Claude Opus 4.6 --- service/matching/handler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/matching/handler.go b/service/matching/handler.go index cfb754d5742..53575447db2 100644 --- a/service/matching/handler.go +++ b/service/matching/handler.go @@ -17,10 +17,10 @@ import ( "go.temporal.io/server/common/membership" "go.temporal.io/server/common/metrics" "go.temporal.io/server/common/namespace" - "go.temporal.io/server/common/primitives" "go.temporal.io/server/common/persistence" "go.temporal.io/server/common/persistence/serialization" "go.temporal.io/server/common/persistence/visibility/manager" + "go.temporal.io/server/common/primitives" "go.temporal.io/server/common/resource" "go.temporal.io/server/common/searchattribute" "go.temporal.io/server/common/testing/testhooks"