|
1 | | -# Temporal Cloud Run worker-identity worker |
| 1 | +# Temporal Cloud Run worker-identity sample |
2 | 2 |
|
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. |
8 | 7 |
|
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. |
14 | 9 |
|
15 | 10 | ## Unreleased SDK dependency |
16 | 11 |
|
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`. |
48 | 16 |
|
49 | 17 | ## How it works |
50 | 18 |
|
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. |
53 | 24 |
|
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. |
59 | 28 |
|
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 |
79 | 30 |
|
80 | 31 | ```bash |
81 | 32 | ./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 |
87 | 33 | ./gradlew -PtemporalSdkPath=/path/to/sdk-java :gcp:cloud-run:workerid:installDist |
88 | 34 | ``` |
89 | 35 |
|
90 | | -## Deploy to a Cloud Run worker pool |
| 36 | +## Deploy |
91 | 37 |
|
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: |
94 | 41 |
|
95 | 42 | ```bash |
96 | 43 | 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 |
113 | 44 | gcloud run worker-pools deploy cloud-run-worker-id \ |
114 | 45 | --image "$REGION-docker.pkg.dev/$PROJECT_ID/<repo>/cloud-run-worker-id:latest" \ |
115 | 46 | --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" |
117 | 48 | ``` |
118 | 49 |
|
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. |
121 | 51 |
|
122 | | -## Start a Workflow |
123 | | - |
124 | | -After the Worker is polling, start the sample Workflow on the same Task Queue: |
| 52 | +## Start a workflow |
125 | 53 |
|
126 | 54 | ```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"' |
132 | 57 | ``` |
133 | 58 |
|
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"`. |
0 commit comments