This module derives a Temporal worker identity for Google Cloud Run from instance metadata, for both Cloud Run worker pools and Cloud Run services.
The primary API is CloudRunIdPlugin. Register it once on your workflow client and it sets the client identity automatically; every worker created from that client inherits it. This mirrors the CloudRunOpenTelemetryPlugin in the companion temporal-gcp-cloud-run-opentelemetry module.
Experimental: Google Cloud Run support is experimental and may change without notice.
Add temporal-gcp-cloud-run-id next to your Temporal SDK dependency, then register the plugin on the workflow client options:
import io.temporal.client.WorkflowClient;
import io.temporal.client.WorkflowClientOptions;
import io.temporal.gcp.cloudrun.id.CloudRunIdPlugin;
import io.temporal.serviceclient.WorkflowServiceStubs;
import io.temporal.serviceclient.WorkflowServiceStubsOptions;
import io.temporal.worker.Worker;
import io.temporal.worker.WorkerFactory;
public final class Main {
public static void main(String[] args) {
WorkflowServiceStubs service =
WorkflowServiceStubs.newServiceStubs(
WorkflowServiceStubsOptions.newBuilder()
.setTarget("my-namespace.tmprl.cloud:7233")
.build());
// Registering the plugin on the client:
// - reads Cloud Run instance metadata once while the client is configured, and
// - sets the client identity to the derived worker identity (unless you set one yourself).
WorkflowClient client =
WorkflowClient.newInstance(
service,
WorkflowClientOptions.newBuilder()
.setNamespace("my-namespace")
.setPlugins(new CloudRunIdPlugin())
.build());
WorkerFactory factory = WorkerFactory.newInstance(client);
// Workers created from this client inherit the identity the plugin set on the client. No
// per-worker wiring needed.
Worker worker = factory.newWorker("orders");
worker.registerWorkflowImplementationTypes(OrderWorkflowImpl.class);
worker.registerActivitiesImplementations(new OrderActivitiesImpl());
factory.start();
}
}You can also register the plugin on WorkflowServiceStubsOptions.Builder.setPlugins(...); from there it propagates to the client and workers as well.
CloudRunIdPlugin reads Cloud Run instance metadata through GoogleCloudRunMetadata, which resolves three values:
- name: the Cloud Run worker pool name — the first non-empty of
CLOUD_RUN_WORKER_POOL(set on Cloud Run worker pools) thenK_SERVICE(set on Cloud Run services). - revision: the first non-empty of
CLOUD_RUN_REVISION(worker pools) thenK_REVISION(services). - instanceId: read from the Cloud Run metadata server with a single HTTP
GETtohttp://metadata.google.internal/computeMetadata/v1/instance/idwith the requiredMetadata-Flavor: Googleheader. The metadata server is available on both worker pools and services.
Worker pools receive CLOUD_RUN_WORKER_POOL and CLOUD_RUN_REVISION and no K_* variables, while services receive K_SERVICE and K_REVISION, so resolving each value from the worker-pool variable first and the service variable second supports both.
The plugin then applies the metadata through the SDK's client plugin hook:
- Client (
configureWorkflowClient): sets the client identity to<instanceId>@<revision>(falling back to<instanceId>@<name>and then the bare<instanceId>), but only when you have not already set an identity, so a user-provided identity always wins. The metadata is fetched here, once, and cached. Workers created from the client inherit this identity; the plugin sets nothing else on them.
The metadata server is only reachable from a Cloud Run instance, so the fetch in configureWorkflowClient throws IllegalStateException when it cannot be reached (usually because the process is not running on Google Cloud Run).
If you prefer to read the values yourself, use GoogleCloudRunMetadata directly:
GoogleCloudRunMetadata metadata = GoogleCloudRunMetadata.fetch();
String identity = metadata.identity();GoogleCloudRunMetadata.fetch(String metadataUrl, Duration timeout) overrides the metadata URL or the request timeout.
This module depends only on the Temporal SDK at compile time and uses the JDK's HttpURLConnection for the metadata request, so it adds no additional runtime dependencies.
