Skip to content

Conversation

@yuandrew
Copy link
Contributor

@yuandrew yuandrew commented Oct 14, 2025

What was changed

Send plugin names over to core for worker heartbeating.

Updated Core to latest main, 9e9a461.

Updated test to validate replacing clients with a client from a different runtime is invalid.

Why?

Worker heartbeating

Checklist

  1. Closes

  2. How was this tested:

Added tests for plugin name propogation, and runtime options configuration

  1. Any docs updates needed?

Note

Forward worker plugin names to Core and add runtime options (incl. worker heartbeat); upgrade Rust deps; expose client.plugins; enforce client-runtime match; CI lint step tweaks.

  • Worker/Core integration:
    • Forward worker plugin names to Core via plugins in WorkerConfig (Rust PluginInfo), with optional skip_client_worker_set_check.
    • replace_client now reports errors; Python worker enforces new client uses same runtime.
  • Runtime/API:
    • Replace init_runtime(telemetry) with init_runtime(options); add RuntimeOptions (telemetry + worker_heartbeat_interval_millis).
    • Python Runtime accepts worker_heartbeat_interval; validates and forwards millis.
  • Client API:
    • Expose Client.plugins property.
  • Deps/SDK-Core:
    • Update submodule to 9e9a461; bump Rust crates (prost 0.14, tonic 0.14, opentelemetry 0.31, prost-wkt 0.7, etc.) and add new deps (tonic-prost, pulldown-cmark*, dyn-clone).
    • Adjust bridge client to use TemporalServiceClient and reworked tonic import.
  • CI:
    • Ensure poe lint runs (reordered/duplicated) in build and latest-deps jobs.
  • Tests:
    • New tests for plugin name propagation, runtime options/heartbeat, client runtime mismatch; set skip_client_worker_set_check by default for tests; minor assertions updates.

Written by Cursor Bugbot for commit c276572. This will update automatically on new commits. Configure here.

@yuandrew yuandrew marked this pull request as ready for review October 21, 2025 01:04
@yuandrew yuandrew requested a review from a team as a code owner October 21, 2025 01:04
activity_task_poller_behavior: PollerBehavior
nexus_task_poller_behavior: PollerBehavior
plugins: Sequence[Plugin]
skip_client_worker_set_check: bool
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't love the addition of this to the very public worker config. This was due to validation issues in the tests, correct? How much work do we think it would be to actually just fix those issues? Is there any place where it is really meaningful?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we want to set skip_client_worker_set_check to false for tests. I didn't check how python does things, but in Core, since tests run in parallel and use the same namespace, we were hitting errors from that. No reason to have this check for tests, unless we're explicitly trying to test for it, which we already do in Core.

I can try to remove from here

Copy link
Contributor

Choose a reason for hiding this comment

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

Makes sense in Core, but exposing it in the public API wouldn't be fun. Let's see if we can find another way around it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Struggling to think of a way around this, our tests pass in WorkerConfig as a typed dict, and Worker::init also uses the WorkerConfig typed dict.

I feel like it should be fine to expose this publically, for users writing their own tests, if they run their tests in parallel on the same namespace/task queue, they would also want to disable this check

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I think it's reasonable to expose this publicly

)
.nexus_task_poller_behavior(conf.nexus_task_poller_behavior)
.plugins(
conf.plugins
Copy link
Contributor

Choose a reason for hiding this comment

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

So, something that will need some discussion here. This PR reports worker plugins. We should discuss whether that is really what we intend. Plugins which exist only in the client and not the worker will be completely invisible. That could potentially be changed here at least for plugins in clients used by workers, though not generally for any client. I think that was something we didn't really think through when we decided to go with heartbeat as a carrier for this information, but maybe we conclude that is fine.

Typescript will be a bit more complicated as well with its additional plugin types.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Discussed offline, we will for now have both worker and client plugins and dedup names

"""Python representation of the Rust struct for runtime options."""

telemetry: TelemetryConfig
worker_heartbeat_interval_millis: Optional[int] = 30_000 # 30s
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we want the defaults defined by each language, or does this make more sense to take optionally into core and default there? Since this is optional but with a default number, does that mean overriding with None disables heartbeating?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah specifying None here disables heartbeating. so I think we need the default to be passed down to lang as well

Copy link
Contributor

Choose a reason for hiding this comment

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

The alternative would be a nested optional or some form of enum, but I accept this is the easiest route.

Copy link
Member

Choose a reason for hiding this comment

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

Wait why is this 30? Isn't our default 60?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

🤦 it is.. thanks for catching

Copy link
Member

@Sushisource Sushisource left a comment

Choose a reason for hiding this comment

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

This is looking good to me, only thing is the default interval

Copy link
Member

@Sushisource Sushisource left a comment

Choose a reason for hiding this comment

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

Nice!

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.

4 participants