Skip to content

Add a hook point to the Matching service once a task has been matched or not#9311

Merged
02strich merged 1 commit intoserverlessfrom
stefan/matching-service
Feb 20, 2026
Merged

Add a hook point to the Matching service once a task has been matched or not#9311
02strich merged 1 commit intoserverlessfrom
stefan/matching-service

Conversation

@02strich
Copy link
Copy Markdown
Contributor

What changed?

This adds a hook point to the matching service once it has matched a task or decided to spool it.

Why?

This can be leveraged to react to task sync or no-sync match events, while keeping matching service decoupled from the event handling logic.

How did you test it?

  • built
  • run locally and tested manually
  • covered by existing tests
  • added new unit test(s)
  • added new functional test(s)

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Feb 13, 2026

CLA assistant check
All committers have signed the CLA.

@02strich 02strich force-pushed the stefan/matching-service branch 8 times, most recently from cb2a1fa to 30a201a Compare February 13, 2026 04:36
Copy link
Copy Markdown
Contributor

@rkannan82 rkannan82 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. Lets add David/Shahab to this.

Comment thread service/matching/task_queue_partition_manager.go Outdated
Comment thread service/matching/task_queue_partition_manager.go Outdated
@02strich 02strich force-pushed the stefan/matching-service branch from 30a201a to fa521df Compare February 17, 2026 22:16
@02strich 02strich marked this pull request as ready for review February 17, 2026 22:17
@02strich 02strich requested review from a team as code owners February 17, 2026 22:17
Comment thread service/matching/task_queue_partition_manager.go Outdated
Comment thread service/matching/task_queue_partition_manager.go Outdated
Comment thread service/matching/task_queue_partition_manager.go Outdated
@02strich 02strich force-pushed the stefan/matching-service branch from fa521df to 1849a89 Compare February 18, 2026 18:08
Comment thread service/matching/task_queue_partition_manager.go Outdated
@02strich 02strich force-pushed the stefan/matching-service branch 3 times, most recently from fee0744 to 0091e88 Compare February 18, 2026 19:28
Comment thread service/matching/hooks/task_lifecycle_hooks.go Outdated
@02strich 02strich force-pushed the stefan/matching-service branch 2 times, most recently from 9fdf08f to 280df75 Compare February 18, 2026 19:56
Comment thread service/matching/hooks/task_lifecycle_hooks.go
@02strich 02strich force-pushed the stefan/matching-service branch 3 times, most recently from 50abbf7 to ef7ec27 Compare February 18, 2026 21:40
Comment thread service/matching/hooks/task_lifecycle_hooks.go Outdated
@02strich 02strich force-pushed the stefan/matching-service branch from ef7ec27 to a40f820 Compare February 18, 2026 22:07
@@ -0,0 +1,36 @@
package hooks
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this really need to be a new package? if it is a new package, let's remove "TaskHook" as a prefix from all these names to reduce stuttering.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it can't be in matching as that causes a dependency loop. I would love if there was a different existing place instead of creating a new one

Comment thread service/matching/hooks/task_lifecycle_hooks.go Outdated
Comment thread service/matching/hooks/task_lifecycle_hooks.go Outdated
Comment thread service/matching/hooks/task_lifecycle_hooks.go Outdated
Comment thread service/matching/hooks/task_lifecycle_hooks.go Outdated
Comment thread service/matching/task_queue_partition_manager.go Outdated
tqConfig,
partition.TaskQueue().TaskType())
var taskHooks []hooks.TaskHook
for _, hookProducer := range taskHookFactories {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have a case for more than one of these? can we simplify it to one optional hook factory/hook?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a use case for one today, but I don't believe it is wise to limit today given all the difference is having this as a loop

Comment thread service/matching/task_queue_partition_manager.go
assignedBuildId = spoolQueue.QueueKey().Version().BuildId()
}

pm.processTaskAddHooks(ctx, targetVersion, false, dbq)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about errors? do we care if we call this and then SpoolTask fails?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this some more. Originally, I didn't really care about errors as slight over-signaling isn't harmful for the specific use case. That said, It is likely to be confusing when debugging, and similarly under-signaling also cannot be a critical issue. So in the name of less confusion, changing it to only trigger the hooks on successful spool

Comment thread service/matching/task_queue_partition_manager.go Outdated
@02strich 02strich force-pushed the stefan/matching-service branch from a40f820 to d7e9c5a Compare February 19, 2026 19:45
@02strich 02strich changed the base branch from main to serverless February 19, 2026 19:46
@02strich 02strich force-pushed the stefan/matching-service branch 3 times, most recently from c41f922 to a86c2ca Compare February 19, 2026 20:09
Copy link
Copy Markdown
Contributor

@jaypipes jaypipes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obviously I need to read more about how the matching service works, but I would have thought that there would be an event sink that we could set up to receive an event/signal that a particular task queue + type tuple had no active pollers. Is there no such mechanism we can "hook into"?

Comment on lines +234 to +236
for _, hook := range pm.taskHooks {
hook.Start()
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and below, do we need to have a deterministic order to the firing of task hook Start() and (reverse-orderered) Stop() calls?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no promise on ordering of different hooks, so they need to be independent in general - which should extend to start and stop

@02strich
Copy link
Copy Markdown
Contributor Author

Obviously I need to read more about how the matching service works, but I would have thought that there would be an event sink that we could set up to receive an event/signal that a particular task queue + type tuple had no active pollers. Is there no such mechanism we can "hook into"?

@jaypipes this PR adds that hook point. Though we don't care about whether there are no active pollers in general, but just when a task needs to be matched so this is in the task dispatching path.

Comment on lines +15 to +17
TaskQueueName string
TaskQueueType enumspb.TaskQueueType
TaskQueueKind enumspb.TaskQueueKind
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be tqid.Partition to match the granularity in which we create the hook instances.

The Partition has all the info needed by the hook. I understand that the hook's usage of the data may be oblivious of the fact that it is partition level, but still the interface should be clear that instantiation is per partition.

I also have a problem with bringing TaskQueueKind to the interface, as the enum belongs to the outdated representation of sticky task queues. For context, sticky task queues are now considered a partition of the user-level task queue, and not as much of a separate task queue.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline, and added a stripped down interface to reduce the amount of exposed details

@02strich 02strich force-pushed the stefan/matching-service branch from a86c2ca to b327a9d Compare February 19, 2026 21:32
… (or not)

This adds a hook point to the matching service once it has matched a task or decided to spool it. This can be leveraged to react to task sync or no-sync match events, while keeping matching service decoupled from the event handling logic.
@02strich 02strich force-pushed the stefan/matching-service branch from b327a9d to aef287a Compare February 19, 2026 21:45
// TaskQueuePartition is a simplified version of tqid.Partition that removes details
// the hooks should not concern themselves with
TaskQueuePartition interface {
NamespaceId() string
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could probably drop this since we have Namespace in the TaskHookFactoryCreateDetails?

Comment thread service/matching/task_queue_partition_manager.go
Comment on lines +1580 to +1587
s.Require().Eventually(func() bool {
select {
case <-pollStarted:
return true
default:
return false
}
}, 2*time.Second, 1*time.Millisecond)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: it might be nice to move https://github.com/temporalio/temporal/blob/main/tests/testcore/functional_test_base.go#L660
to a common test utils so we could use it in unit tests. doesn't have to be now of course

@02strich 02strich merged commit 2418246 into serverless Feb 20, 2026
43 of 45 checks passed
@02strich 02strich deleted the stefan/matching-service branch February 20, 2026 21:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants