Skip to content

Commit 9dc533b

Browse files
committed
Fix Cloud Run identity sample for renamed SDK module and trim docs
1 parent fa9d7f0 commit 9dc533b

10 files changed

Lines changed: 43 additions & 169 deletions

File tree

gcp/cloud-run/workerid/Dockerfile

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,7 @@ FROM eclipse-temurin:17-jdk-jammy AS build
33
WORKDIR /workspace
44
COPY . .
55

6-
# TEMPORARY (draft): this sample depends on io.temporal:temporal-gcp-cloud-run-worker-id, which is
7-
# not yet released to Maven Central. Until it ships, the Gradle build resolves it from a local
8-
# Temporal Java SDK checkout through a composite build (see README.md and settings.gradle). For an
9-
# image build the local SDK checkout must be available in the build context (or the module published
10-
# to Maven Local); once the module is released, bump javaSDKVersion in the samples root build.gradle
11-
# and this builds unchanged from Maven Central.
6+
# temporal-gcp-cloud-run-id is unreleased; the composite build resolves it from a local SDK checkout (see README).
127
RUN ./gradlew --no-daemon :gcp:cloud-run:workerid:installDist
138

149
FROM eclipse-temurin:17-jre-jammy

gcp/cloud-run/workerid/README.md

Lines changed: 30 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,150 +1,60 @@
1-
# Temporal Cloud Run worker-identity worker
1+
# Temporal Cloud Run worker-identity sample
22

3-
This sample runs a continuously polling Temporal Java Worker in a Google Cloud Run **worker pool**.
4-
It registers the `WorkerIdPlugin` from the `temporal-gcp-cloud-run-worker-id` module on the Temporal
5-
client so the Worker's Temporal identity is derived from Cloud Run instance metadata as
6-
`{instanceId}@{revision}`. It registers a small greeting Workflow and Activity and runs until Cloud
7-
Run stops the instance. Identity only: the plugin sets the worker identity and nothing else.
3+
A continuously polling Temporal Java worker for a Google Cloud Run **worker pool** that registers
4+
`CloudRunIdPlugin` from `io.temporal:temporal-gcp-cloud-run-id` on the client, so the worker identity
5+
is derived from Cloud Run instance metadata as `{instanceId}@{revision}`. The plugin sets identity
6+
only. A small greeting workflow and activity run until Cloud Run stops the instance.
87

9-
Cloud Run runs a long-lived container rather than a per-request handler, so there is no function to
10-
wrap: registering the plugin on the client fetches the metadata once at startup and applies the
11-
derived identity to the client and the Workers created from it.
12-
13-
> Experimental: Google Cloud Run support is experimental and may change without notice.
8+
> Google Cloud Run support is experimental and may change without notice.
149
1510
## Unreleased SDK dependency
1611

17-
This sample depends on `io.temporal:temporal-gcp-cloud-run-worker-id`, which is **not yet released**
18-
to Maven Central. Until it ships, the samples build wires the module from a local Temporal Java SDK
19-
checkout through a Gradle composite build (`includeBuild`), configured in the samples root
20-
`settings.gradle`.
21-
22-
- It defaults to a sibling `../sdk-java-2` checkout on the `cloud-run-worker-id` branch.
23-
- Override the location with `-PtemporalSdkPath=/path/to/sdk-java`.
24-
- When that checkout is absent, the composite build is skipped and only this module is affected; the
25-
other samples still build.
26-
27-
Once `temporal-gcp-cloud-run-worker-id` is released, remove the composite-build block from
28-
`settings.gradle` and bump `javaSDKVersion` in the samples root `build.gradle` to the released
29-
version; the standard Maven Central build then works without the local checkout. This sample's pull
30-
request stays a draft until then.
31-
32-
## Prerequisites
33-
34-
- Java 17+
35-
- The Temporal CLI (to start Workflows)
36-
- The Google Cloud CLI (`gcloud`) with a project that has Cloud Run enabled
37-
- A Temporal Service reachable from Cloud Run. A plaintext connection is used by default; configure
38-
TLS or an API key in `CloudRunWorker.java` for a secured Service such as Temporal Cloud.
39-
40-
## Files
41-
42-
- `src/main/java/io/temporal/samples/gcp/cloudrun/workerid/CloudRunWorker.java` fetches the Cloud
43-
Run metadata, registers `WorkerIdPlugin` on the client to apply the derived identity, and runs a
44-
long-lived Worker with a bounded shutdown on `SIGTERM`.
45-
- `GreetingWorkflow` / `GreetingWorkflowImpl` and `GreetingActivities` / `GreetingActivitiesImpl` are
46-
the sample Workflow and Activity.
47-
- `Dockerfile` packages the Gradle application as the Worker container.
12+
`temporal-gcp-cloud-run-id` is not yet released. `settings.gradle` resolves it (and the other
13+
`io.temporal:*` modules) from a local SDK checkout via a Gradle composite build, defaulting to
14+
`../sdk-java` and overridable with `-PtemporalSdkPath`. CI has no checkout, so its build stays red
15+
until the module ships; then drop the composite block and bump `javaSDKVersion`.
4816

4917
## How it works
5018

51-
Cloud Run **worker pools** set `CLOUD_RUN_WORKER_POOL` and `CLOUD_RUN_REVISION` on every instance
52-
(Cloud Run **services** set `K_SERVICE` and `K_REVISION`). `GoogleCloudRunMetadata.fetch()` resolves:
19+
Cloud Run worker pools set `CLOUD_RUN_WORKER_POOL` and `CLOUD_RUN_REVISION` (services set `K_SERVICE`
20+
and `K_REVISION`). `CloudRunIdPlugin` reads those plus the instance id from the Cloud Run metadata
21+
server and sets the client identity to `{instanceId}@{revision}` unless one is already set; workers
22+
created from the client inherit it. `GoogleCloudRunMetadata.fetch().identity()` exposes the same
23+
value, which the worker logs at startup.
5324

54-
- **name**: the first non-empty of `CLOUD_RUN_WORKER_POOL` then `K_SERVICE`.
55-
- **revision**: the first non-empty of `CLOUD_RUN_REVISION` then `K_REVISION`.
56-
- **instance id**: a single HTTP `GET` to the Cloud Run metadata server
57-
(`http://metadata.google.internal/computeMetadata/v1/instance/id`, header `Metadata-Flavor:
58-
Google`).
25+
The worker reads `TEMPORAL_ADDRESS` (default `127.0.0.1:7233`), `TEMPORAL_NAMESPACE` (default
26+
`default`), and `TEMPORAL_TASK_QUEUE` (default `cloud-run-worker-id`). A plaintext connection is used;
27+
configure TLS or an API key in `CloudRunWorker.java` for a secured Service such as Temporal Cloud.
5928

60-
`WorkerIdPlugin`, registered on the client with `WorkflowClientOptions.Builder.setPlugins(...)`, then
61-
sets the Worker identity to `{instanceId}@{revision}` (falling back to `{instanceId}@{name}` and then
62-
`{instanceId}`) unless an identity is already set. Workers created from the client inherit that
63-
identity; the plugin sets nothing else on them.
64-
65-
The Worker reads its connection settings from the environment:
66-
67-
```bash
68-
TEMPORAL_ADDRESS # host:port of the Temporal frontend (default 127.0.0.1:7233)
69-
TEMPORAL_NAMESPACE # Temporal Namespace (default "default")
70-
TEMPORAL_TASK_QUEUE # Task Queue to poll (default "cloud-run-worker-id")
71-
```
72-
73-
`CLOUD_RUN_WORKER_POOL` and `CLOUD_RUN_REVISION` are injected by Cloud Run and do not need to be set
74-
manually.
75-
76-
## Build and test locally
77-
78-
The unit test uses `TestWorkflowRule` and needs neither Cloud Run nor a running Temporal Service:
29+
## Build and test
7930

8031
```bash
8132
./gradlew :gcp:cloud-run:workerid:test
82-
```
83-
84-
Build the runnable application (from a local SDK checkout, per the note above):
85-
86-
```bash
8733
./gradlew -PtemporalSdkPath=/path/to/sdk-java :gcp:cloud-run:workerid:installDist
8834
```
8935

90-
## Deploy to a Cloud Run worker pool
36+
## Deploy
9137

92-
Worker pools keep CPU allocated so the Temporal Worker can poll continuously; they are not
93-
request-driven Cloud Run services. Set your connection values and deploy from the sample directory:
38+
Worker pools keep CPU allocated for continuous polling. Until `temporal-gcp-cloud-run-id` is released
39+
a remote `--source` build cannot resolve it, so build the image locally against your SDK checkout and
40+
deploy it by tag:
9441

9542
```bash
9643
export REGION=us-central1
97-
export TEMPORAL_ADDRESS=<your-namespace>.<account>.tmprl.cloud:7233
98-
export TEMPORAL_NAMESPACE=<your-namespace>.<account>
99-
export TEMPORAL_TASK_QUEUE=cloud-run-worker-id
100-
101-
gcloud run worker-pools deploy cloud-run-worker-id \
102-
--source . \
103-
--region "$REGION" \
104-
--set-env-vars "TEMPORAL_ADDRESS=$TEMPORAL_ADDRESS,TEMPORAL_NAMESPACE=$TEMPORAL_NAMESPACE,TEMPORAL_TASK_QUEUE=$TEMPORAL_TASK_QUEUE"
105-
```
106-
107-
`--source .` builds the container from the included `Dockerfile`. Because the image build resolves
108-
the unreleased `temporal-gcp-cloud-run-worker-id` module, a remote source build succeeds only once
109-
that module is released (or published to your Maven Local and made available to the build). Until
110-
then, build the image locally against your SDK checkout and deploy it with `--image` instead:
111-
112-
```bash
11344
gcloud run worker-pools deploy cloud-run-worker-id \
11445
--image "$REGION-docker.pkg.dev/$PROJECT_ID/<repo>/cloud-run-worker-id:latest" \
11546
--region "$REGION" \
116-
--set-env-vars "TEMPORAL_ADDRESS=$TEMPORAL_ADDRESS,TEMPORAL_NAMESPACE=$TEMPORAL_NAMESPACE,TEMPORAL_TASK_QUEUE=$TEMPORAL_TASK_QUEUE"
47+
--set-env-vars "TEMPORAL_ADDRESS=<addr>,TEMPORAL_NAMESPACE=<ns>,TEMPORAL_TASK_QUEUE=cloud-run-worker-id"
11748
```
11849

119-
Each Cloud Run revision starts a fresh instance whose Worker reports a distinct identity, which the
120-
Worker logs at startup.
50+
Each revision starts a fresh instance whose worker reports a distinct identity.
12151

122-
## Start a Workflow
123-
124-
After the Worker is polling, start the sample Workflow on the same Task Queue:
52+
## Start a workflow
12553

12654
```bash
127-
temporal workflow start \
128-
--task-queue cloud-run-worker-id \
129-
--type GreetingWorkflow \
130-
--workflow-id cloud-run-greeting \
131-
--input '"Cloud Run"'
55+
temporal workflow start --type GreetingWorkflow --task-queue cloud-run-worker-id \
56+
--workflow-id cloud-run-greeting --input '"Cloud Run"'
13257
```
13358

134-
The Worker's identity appears on its Task Queue pollers (for example in `temporal task-queue
135-
describe`) and on the events it records.
136-
137-
## Shutdown
138-
139-
Cloud Run sends `SIGTERM` and allows a short grace period before `SIGKILL`. The shutdown hook stops
140-
polling, waits up to six seconds for in-flight tasks to drain, escalates to a forced shutdown if
141-
needed, and then closes the service connection. Long-running Activities should still heartbeat and
142-
handle cancellation so they can stop within the platform's shutdown window.
143-
144-
## Clean up
145-
146-
Delete the worker pool when you are done:
147-
148-
```bash
149-
gcloud run worker-pools delete cloud-run-worker-id --region "$REGION"
150-
```
59+
The identity appears on the task-queue pollers (`temporal task-queue describe`) and recorded events.
60+
Delete the pool with `gcloud run worker-pools delete cloud-run-worker-id --region "$REGION"`.

gcp/cloud-run/workerid/build.gradle

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ apply plugin: 'application'
22

33
dependencies {
44
implementation "io.temporal:temporal-sdk:$javaSDKVersion"
5-
implementation "io.temporal:temporal-gcp-cloud-run-worker-id:$javaSDKVersion"
5+
implementation "io.temporal:temporal-gcp-cloud-run-id:$javaSDKVersion"
66
runtimeOnly group: 'ch.qos.logback', name: 'logback-classic', version: '1.5.6'
77

88
testImplementation "io.temporal:temporal-testing:$javaSDKVersion"
@@ -18,7 +18,6 @@ dependencies {
1818

1919
application {
2020
mainClass = 'io.temporal.samples.gcp.cloudrun.workerid.CloudRunWorker'
21-
// Keep a stable launcher/installDist name independent of the nested Gradle
22-
// project name (:gcp:cloud-run:workerid), which the Dockerfile relies on.
21+
// Stable launcher name the Dockerfile relies on, independent of the Gradle project path.
2322
applicationName = 'cloud-run-worker-id'
2423
}

gcp/cloud-run/workerid/src/main/java/io/temporal/samples/gcp/cloudrun/workerid/CloudRunWorker.java

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
import io.temporal.client.WorkflowClient;
44
import io.temporal.client.WorkflowClientOptions;
5-
import io.temporal.gcp.cloudrun.workerid.GoogleCloudRunMetadata;
6-
import io.temporal.gcp.cloudrun.workerid.WorkerIdPlugin;
5+
import io.temporal.gcp.cloudrun.id.CloudRunIdPlugin;
6+
import io.temporal.gcp.cloudrun.id.GoogleCloudRunMetadata;
77
import io.temporal.serviceclient.WorkflowServiceStubs;
88
import io.temporal.serviceclient.WorkflowServiceStubsOptions;
99
import io.temporal.worker.Worker;
@@ -27,30 +27,22 @@ public final class CloudRunWorker {
2727
private CloudRunWorker() {}
2828

2929
public static void main(String[] args) {
30-
// Read Cloud Run instance metadata once during startup. This performs a single HTTP request to
31-
// the Cloud Run metadata server and throws IllegalStateException when it is unreachable, which
32-
// usually means the process is not running on Google Cloud Run.
33-
GoogleCloudRunMetadata metadata = GoogleCloudRunMetadata.fetch();
34-
3530
String address = envOrDefault(ADDRESS_ENV, DEFAULT_ADDRESS);
3631
String namespace = envOrDefault(NAMESPACE_ENV, DEFAULT_NAMESPACE);
3732
String taskQueue = envOrDefault(TASK_QUEUE_ENV, DEFAULT_TASK_QUEUE);
3833

39-
// Plaintext connection to the Temporal Service. Configure TLS or an API key here for a secured
40-
// Service such as Temporal Cloud.
34+
// Plaintext connection; add TLS or an API key here for Temporal Cloud.
4135
WorkflowServiceStubs service =
4236
WorkflowServiceStubs.newServiceStubs(
4337
WorkflowServiceStubsOptions.newBuilder().setTarget(address).build());
4438

45-
// Register WorkerIdPlugin on the client. It sets the derived worker identity
46-
// ({instanceId}@{revision}) on the client, and workers created from the client inherit it.
47-
// Passing the already-fetched metadata avoids a second call to the Cloud Run metadata server.
39+
// CloudRunIdPlugin sets the client identity to {instanceId}@{revision} from metadata.
4840
WorkflowClient client =
4941
WorkflowClient.newInstance(
5042
service,
5143
WorkflowClientOptions.newBuilder()
5244
.setNamespace(namespace)
53-
.setPlugins(new WorkerIdPlugin(metadata))
45+
.setPlugins(new CloudRunIdPlugin())
5446
.build());
5547

5648
WorkerFactory factory = WorkerFactory.newInstance(client);
@@ -65,16 +57,15 @@ public static void main(String[] args) {
6557
factory.start();
6658
logger.info(
6759
"Temporal worker started (identity={}, taskQueue={})",
68-
metadata.workerIdentity(),
60+
GoogleCloudRunMetadata.fetch().identity(),
6961
taskQueue);
7062

7163
// Cloud Run worker pools are continuous workloads, so keep the process alive until SIGTERM.
7264
factory.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
7365
}
7466

7567
private static void shutdown(WorkerFactory factory, WorkflowServiceStubs service) {
76-
// Cloud Run sends SIGTERM and allows a short grace period before SIGKILL. Stop polling, drain
77-
// in-flight tasks, then close the service connection.
68+
// Cloud Run sends SIGTERM before SIGKILL; stop polling, drain in-flight tasks, then close.
7869
factory.shutdown();
7970
factory.awaitTermination(6, TimeUnit.SECONDS);
8071
if (!factory.isTerminated()) {
Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
package io.temporal.samples.gcp.cloudrun.workerid;
22

33
import io.temporal.activity.ActivityInterface;
4-
import io.temporal.activity.ActivityMethod;
54

6-
/** Activity interface used by {@link GreetingWorkflow}. */
75
@ActivityInterface
86
public interface GreetingActivities {
9-
10-
@ActivityMethod
117
String composeGreeting(String name);
128
}

gcp/cloud-run/workerid/src/main/java/io/temporal/samples/gcp/cloudrun/workerid/GreetingActivitiesImpl.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import org.slf4j.Logger;
44
import org.slf4j.LoggerFactory;
55

6-
/** Activity implementation that returns a simple greeting. */
76
public final class GreetingActivitiesImpl implements GreetingActivities {
87

98
private static final Logger logger = LoggerFactory.getLogger(GreetingActivitiesImpl.class);

gcp/cloud-run/workerid/src/main/java/io/temporal/samples/gcp/cloudrun/workerid/GreetingWorkflow.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33
import io.temporal.workflow.WorkflowInterface;
44
import io.temporal.workflow.WorkflowMethod;
55

6-
/** A small greeting workflow run by the Cloud Run worker. */
76
@WorkflowInterface
87
public interface GreetingWorkflow {
9-
108
@WorkflowMethod
119
String getGreeting(String name);
1210
}

gcp/cloud-run/workerid/src/main/java/io/temporal/samples/gcp/cloudrun/workerid/GreetingWorkflowImpl.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
import io.temporal.workflow.Workflow;
55
import java.time.Duration;
66

7-
/** Greeting workflow implementation. */
87
public final class GreetingWorkflowImpl implements GreetingWorkflow {
9-
108
private final GreetingActivities activities =
119
Workflow.newActivityStub(
1210
GreetingActivities.class,

gcp/cloud-run/workerid/src/test/java/io/temporal/samples/gcp/cloudrun/workerid/GreetingWorkflowTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@
77
import org.junit.Rule;
88
import org.junit.Test;
99

10-
/** Unit test for the sample Workflow and Activity. */
1110
public class GreetingWorkflowTest {
12-
1311
@Rule
1412
public TestWorkflowRule testWorkflowRule =
1513
TestWorkflowRule.newBuilder()

settings.gradle

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,8 @@ include 'lambda-worker:starter'
1111
include 'lambda-worker:worker'
1212
include 'gcp:cloud-run:workerid'
1313

14-
// TEMPORARY (draft): the gcp:cloud-run:workerid sample depends on
15-
// io.temporal:temporal-gcp-cloud-run-worker-id (and the worker-identity APIs it builds on), which
16-
// are not yet released to Maven Central. Until they ship, wire the sample against a local Temporal
17-
// Java SDK checkout with a Gradle composite build so it can compile and run. Defaults to a sibling
18-
// ../sdk-java-2 checkout on the cloud-run-worker-id branch; override the location with
19-
// -PtemporalSdkPath=/path/to/sdk-java. When the checkout is absent (for example on CI building the
20-
// other samples) the composite build is skipped and only the gcp:cloud-run:workerid module is
21-
// affected. Remove this block and bump javaSDKVersion in build.gradle once
22-
// temporal-gcp-cloud-run-worker-id is released.
23-
def temporalSdkPath = gradle.startParameter.projectProperties['temporalSdkPath'] ?: '../sdk-java-2'
24-
def temporalSdkFile = new File(temporalSdkPath)
25-
def temporalSdkDir = temporalSdkFile.isAbsolute() ? temporalSdkFile : new File(settingsDir, temporalSdkPath)
26-
if (temporalSdkDir.isDirectory()) {
14+
// The gcp:cloud-run samples use unreleased temporal-gcp-cloud-run-* modules; resolve them from a local SDK checkout (default ../sdk-java, override with -PtemporalSdkPath) via composite build.
15+
def temporalSdkPath = gradle.startParameter.projectProperties['temporalSdkPath'] ?: '../sdk-java'
16+
if (file(temporalSdkPath).isDirectory()) {
2717
includeBuild temporalSdkPath
2818
}

0 commit comments

Comments
 (0)