Skip to content

Conversation

@cretz
Copy link
Member

@cretz cretz commented Dec 11, 2025

What was changed

Added client.Plugin, worker.Plugin, and temporal.SimplePlugin and everything required to make those work.

Notes:

  • It is recognized that this is missing test suite functionality. I think this may need to be solved as a followup because it involves a discussion around worker options design for test suites.
  • There are some tradeoffs that had to be made compared to the Python and .NET forms of this feature, but all similar functionality should be captured (e.g. ability to register things in plugins, ability to surround workers and replayers with the same context code in simple plugin, etc)

Checklist

  1. Closes Plugin support #2020

@cretz cretz requested a review from a team as a code owner December 11, 2025 20:18
Copy link
Contributor

@yuandrew yuandrew left a comment

Choose a reason for hiding this comment

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

Solid! Mainly questions for my own learning, and a few leftover doc TODOs


// Checks if `line` is a valid definition, and that definition is for `private`
func isValidDefinitionWithMatch(line, private string, inGroup string, insideStruct bool) bool {
// Vars with underscores are often used to assert interface validation and
Copy link
Contributor

Choose a reason for hiding this comment

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

nice

// PluginConfigureWorkerRegistryOptions are the set of callbacks that can
// be adjusted by plugins when configuring workers. If adjusting a callback that
// is already set, implementers may want to take care to invoke the existing
// callback inside their own.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I understand the last sentence or why it needs a special callout, this is only if they want the newly adjusted callback to continue to do the old callback's logic, on top of what's new right? If they want to adjust their plugin callback to do something completely different, then they wouldn't want to do this?

Copy link
Member Author

Choose a reason for hiding this comment

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

Right. But I figured it was important to call out that if they set this, they overwrite what was set by other plugins, because at first glance it could look like each plugin can set this uniquely unrelated to each other.


// RunContextBefore is invoked on worker start or before each workflow
// replay of a replayer. Implementers can use this to register items or
// simply start something needed.
Copy link
Contributor

Choose a reason for hiding this comment

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

register items

refers to registering things onto the Context, right?

simply start something needed

maybe more of a nit: this phrase feels strange to me, maybe because it feels a little vague and I'm not able to imagine what an example is

Copy link
Member Author

Choose a reason for hiding this comment

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

refers to registering things onto the Context, right?

No, the options

type WorkerPluginConfigureWorkflowReplayerOptions struct {
// WorkflowReplayerInstanceKey is the unique, immutable instance key for
// this workflow replayer.
WorkflowReplayerInstanceKey string
Copy link
Contributor

Choose a reason for hiding this comment

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

This is new, I don't think any of the core langs have this. Is there any utility of this I'm not seeing besides giving each replay an ID and allowing tests to verify Plugins are being applied to replay in the correct sequence?

Correct me if I'm wrong, but each time a worker replays a workflow, it'll generate a new WorkflowReplayerInstanceKey. So A single worker, with its own WorkerInstanceKey, can generate many new WorkflowReplayerInstanceKeys

Copy link
Member Author

Choose a reason for hiding this comment

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

The core langs don't have this because they will be getting access to the actual worker/replay instance in their "run worker" or "replay workflow" calls (which has the options and such). This is needed if a user needs to correlate configuration with the instance.

Not specific to this but for all XInstanceKeys in this PR, there needs to be a way for workers to correlate start with stop (and configure, though that's less important) and workflow replayers to correlate successive replay runs together. The worker side is the most important, it's just that I went ahead and added it to replayer for clarity there too.

For instance, say your plugin on worker start registered an activity with a newly opened database connection. When should it close that database connection?

I do expect this to be the same value as the actual instance key we're using for worker heartbeating when we do that at some point, but since this is all experimental (eek, I need to go mark them all as such), we can adjust as needed in the future.

// to invoke the existing callback inside their own.
//
// Exposed as: [go.temporal.io/sdk/worker.PluginConfigureWorkflowReplayerRegistryOptions]
type WorkerPluginConfigureWorkflowReplayerRegistryOptions struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this the longest var name in the SDK? 😂

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.

Plugin support

2 participants