@temporalio/core-bridge 0.19.2 → 0.20.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +90 -157
- package/Cargo.toml +1 -0
- package/index.d.ts +11 -27
- package/package.json +3 -3
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/releases/x86_64-apple-darwin/index.node +0 -0
- package/releases/x86_64-pc-windows-msvc/index.node +0 -0
- package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
- package/sdk-core/.buildkite/docker/Dockerfile +1 -1
- package/sdk-core/.buildkite/docker/docker-compose.yaml +1 -1
- package/sdk-core/.cargo/config.toml +1 -0
- package/sdk-core/CODEOWNERS +1 -1
- package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +119 -86
- package/sdk-core/bridge-ffi/src/lib.rs +311 -315
- package/sdk-core/bridge-ffi/src/wrappers.rs +108 -113
- package/sdk-core/client/Cargo.toml +13 -9
- package/sdk-core/client/LICENSE.txt +23 -0
- package/sdk-core/client/src/lib.rs +286 -174
- package/sdk-core/client/src/metrics.rs +86 -12
- package/sdk-core/client/src/raw.rs +566 -0
- package/sdk-core/client/src/retry.rs +137 -99
- package/sdk-core/core/Cargo.toml +15 -10
- package/sdk-core/core/LICENSE.txt +23 -0
- package/sdk-core/core/benches/workflow_replay.rs +79 -0
- package/sdk-core/core/src/abstractions.rs +38 -0
- package/sdk-core/core/src/core_tests/activity_tasks.rs +108 -182
- package/sdk-core/core/src/core_tests/child_workflows.rs +16 -11
- package/sdk-core/core/src/core_tests/determinism.rs +24 -12
- package/sdk-core/core/src/core_tests/local_activities.rs +53 -27
- package/sdk-core/core/src/core_tests/mod.rs +30 -43
- package/sdk-core/core/src/core_tests/queries.rs +82 -81
- package/sdk-core/core/src/core_tests/workers.rs +111 -296
- package/sdk-core/core/src/core_tests/workflow_cancels.rs +4 -4
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +257 -242
- package/sdk-core/core/src/lib.rs +73 -318
- package/sdk-core/core/src/pollers/mod.rs +4 -6
- package/sdk-core/core/src/pollers/poll_buffer.rs +20 -14
- package/sdk-core/core/src/protosext/mod.rs +7 -10
- package/sdk-core/core/src/replay/mod.rs +11 -150
- package/sdk-core/core/src/telemetry/metrics.rs +35 -2
- package/sdk-core/core/src/telemetry/mod.rs +49 -16
- package/sdk-core/core/src/telemetry/prometheus_server.rs +14 -35
- package/sdk-core/core/src/test_help/mod.rs +104 -170
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +57 -34
- package/sdk-core/core/src/worker/activities/local_activities.rs +95 -23
- package/sdk-core/core/src/worker/activities.rs +23 -16
- package/sdk-core/core/src/worker/client/mocks.rs +86 -0
- package/sdk-core/core/src/worker/client.rs +209 -0
- package/sdk-core/core/src/worker/mod.rs +207 -108
- package/sdk-core/core/src/workflow/driven_workflow.rs +21 -6
- package/sdk-core/core/src/workflow/history_update.rs +107 -24
- package/sdk-core/core/src/workflow/machines/activity_state_machine.rs +2 -3
- package/sdk-core/core/src/workflow/machines/child_workflow_state_machine.rs +2 -3
- package/sdk-core/core/src/workflow/machines/mod.rs +20 -17
- package/sdk-core/core/src/workflow/machines/signal_external_state_machine.rs +56 -19
- package/sdk-core/core/src/workflow/machines/transition_coverage.rs +5 -0
- package/sdk-core/core/src/workflow/machines/upsert_search_attributes_state_machine.rs +230 -22
- package/sdk-core/core/src/workflow/machines/workflow_machines.rs +81 -115
- package/sdk-core/core/src/workflow/machines/workflow_task_state_machine.rs +4 -4
- package/sdk-core/core/src/workflow/mod.rs +13 -1
- package/sdk-core/core/src/workflow/workflow_tasks/concurrency_manager.rs +70 -11
- package/sdk-core/core/src/workflow/workflow_tasks/mod.rs +65 -41
- package/sdk-core/core-api/Cargo.toml +9 -1
- package/sdk-core/core-api/LICENSE.txt +23 -0
- package/sdk-core/core-api/src/errors.rs +7 -38
- package/sdk-core/core-api/src/lib.rs +44 -52
- package/sdk-core/core-api/src/worker.rs +10 -2
- package/sdk-core/etc/deps.svg +127 -96
- package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +11 -7
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +10 -0
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +6 -1
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +6 -0
- package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +6 -0
- package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +2 -1
- package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +3 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +12 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +25 -0
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +4 -0
- package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +19 -35
- package/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +2 -6
- package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +53 -11
- package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +14 -7
- package/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +3 -5
- package/sdk-core/sdk/Cargo.toml +16 -2
- package/sdk-core/sdk/LICENSE.txt +23 -0
- package/sdk-core/sdk/src/interceptors.rs +11 -0
- package/sdk-core/sdk/src/lib.rs +139 -151
- package/sdk-core/sdk/src/workflow_context/options.rs +86 -1
- package/sdk-core/sdk/src/workflow_context.rs +36 -17
- package/sdk-core/sdk/src/workflow_future.rs +19 -25
- package/sdk-core/sdk-core-protos/Cargo.toml +1 -1
- package/sdk-core/sdk-core-protos/build.rs +1 -0
- package/sdk-core/sdk-core-protos/src/history_info.rs +17 -4
- package/sdk-core/sdk-core-protos/src/lib.rs +251 -47
- package/sdk-core/test-utils/Cargo.toml +3 -1
- package/sdk-core/test-utils/src/canned_histories.rs +27 -0
- package/sdk-core/test-utils/src/histfetch.rs +3 -3
- package/sdk-core/test-utils/src/lib.rs +223 -68
- package/sdk-core/tests/integ_tests/client_tests.rs +27 -4
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +93 -14
- package/sdk-core/tests/integ_tests/polling_tests.rs +18 -12
- package/sdk-core/tests/integ_tests/queries_tests.rs +50 -53
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +117 -103
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +8 -1
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +10 -5
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +7 -1
- package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +32 -9
- package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +7 -1
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +76 -15
- package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +19 -3
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +39 -42
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +84 -0
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +30 -8
- package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +21 -6
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +26 -16
- package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +66 -0
- package/sdk-core/tests/integ_tests/workflow_tests.rs +78 -74
- package/sdk-core/tests/load_tests.rs +9 -6
- package/sdk-core/tests/main.rs +43 -10
- package/src/conversions.rs +7 -12
- package/src/lib.rs +322 -357
- package/sdk-core/client/src/mocks.rs +0 -167
- package/sdk-core/core/src/worker/dispatcher.rs +0 -171
- package/sdk-core/protos/local/temporal/sdk/core/bridge/service.proto +0 -61
|
@@ -1,15 +1,22 @@
|
|
|
1
|
+
use crate::{AttachMetricLabels, LONG_POLL_METHOD_NAMES};
|
|
2
|
+
use futures::{future::BoxFuture, FutureExt};
|
|
1
3
|
use opentelemetry::{
|
|
2
4
|
metrics::{Counter, Meter, ValueRecorder},
|
|
3
5
|
KeyValue,
|
|
4
6
|
};
|
|
5
|
-
use std::{
|
|
7
|
+
use std::{
|
|
8
|
+
sync::Arc,
|
|
9
|
+
task::{Context, Poll},
|
|
10
|
+
time::{Duration, Instant},
|
|
11
|
+
};
|
|
12
|
+
use tonic::{body::BoxBody, transport::Channel};
|
|
13
|
+
use tower::Service;
|
|
6
14
|
|
|
7
15
|
/// Used to track context associated with metrics, and record/update them
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/// appropriate k/vs have already been set.
|
|
16
|
+
// Possible improvement: make generic over some type tag so that methods are only exposed if the
|
|
17
|
+
// appropriate k/vs have already been set.
|
|
11
18
|
#[derive(Clone, Debug)]
|
|
12
|
-
pub
|
|
19
|
+
pub struct MetricsContext {
|
|
13
20
|
kvs: Arc<Vec<KeyValue>>,
|
|
14
21
|
poll_is_long: bool,
|
|
15
22
|
|
|
@@ -23,7 +30,7 @@ pub(crate) struct MetricsContext {
|
|
|
23
30
|
}
|
|
24
31
|
|
|
25
32
|
impl MetricsContext {
|
|
26
|
-
fn new(kvs: Vec<KeyValue>, meter: &Meter) -> Self {
|
|
33
|
+
pub(crate) fn new(kvs: Vec<KeyValue>, meter: &Meter) -> Self {
|
|
27
34
|
Self {
|
|
28
35
|
kvs: Arc::new(kvs),
|
|
29
36
|
poll_is_long: false,
|
|
@@ -36,17 +43,18 @@ impl MetricsContext {
|
|
|
36
43
|
}
|
|
37
44
|
}
|
|
38
45
|
|
|
39
|
-
|
|
40
|
-
Self::new(vec![KeyValue::new(KEY_NAMESPACE, namespace)], meter)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/// Extend an existing metrics context with new attributes
|
|
46
|
+
/// Extend an existing metrics context with new attributes, returning a new one
|
|
44
47
|
pub(crate) fn with_new_attrs(&self, new_kvs: impl IntoIterator<Item = KeyValue>) -> Self {
|
|
45
48
|
let mut r = self.clone();
|
|
46
|
-
|
|
49
|
+
r.add_new_attrs(new_kvs);
|
|
47
50
|
r
|
|
48
51
|
}
|
|
49
52
|
|
|
53
|
+
/// Add new attributes to the context, mutating it
|
|
54
|
+
pub(crate) fn add_new_attrs(&mut self, new_kvs: impl IntoIterator<Item = KeyValue>) {
|
|
55
|
+
Arc::make_mut(&mut self.kvs).extend(new_kvs);
|
|
56
|
+
}
|
|
57
|
+
|
|
50
58
|
pub(crate) fn set_is_long_poll(&mut self) {
|
|
51
59
|
self.poll_is_long = true;
|
|
52
60
|
}
|
|
@@ -83,7 +91,73 @@ impl MetricsContext {
|
|
|
83
91
|
|
|
84
92
|
const KEY_NAMESPACE: &str = "namespace";
|
|
85
93
|
const KEY_SVC_METHOD: &str = "operation";
|
|
94
|
+
const KEY_TASK_QUEUE: &str = "task_queue";
|
|
95
|
+
|
|
96
|
+
pub(crate) fn namespace_kv(ns: String) -> KeyValue {
|
|
97
|
+
KeyValue::new(KEY_NAMESPACE, ns)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
pub(crate) fn task_queue_kv(tq: String) -> KeyValue {
|
|
101
|
+
KeyValue::new(KEY_TASK_QUEUE, tq)
|
|
102
|
+
}
|
|
86
103
|
|
|
87
104
|
pub(crate) fn svc_operation(op: String) -> KeyValue {
|
|
88
105
|
KeyValue::new(KEY_SVC_METHOD, op)
|
|
89
106
|
}
|
|
107
|
+
|
|
108
|
+
/// Implements metrics functionality for gRPC (really, any http) calls
|
|
109
|
+
#[derive(Debug, Clone)]
|
|
110
|
+
pub struct GrpcMetricSvc {
|
|
111
|
+
pub(crate) inner: Channel,
|
|
112
|
+
// If set to none, metrics are a no-op
|
|
113
|
+
pub(crate) metrics: Option<MetricsContext>,
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
impl Service<http::Request<BoxBody>> for GrpcMetricSvc {
|
|
117
|
+
type Response = http::Response<tonic::transport::Body>;
|
|
118
|
+
type Error = tonic::transport::Error;
|
|
119
|
+
type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
|
|
120
|
+
|
|
121
|
+
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
|
122
|
+
self.inner.poll_ready(cx).map_err(Into::into)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
fn call(&mut self, mut req: http::Request<BoxBody>) -> Self::Future {
|
|
126
|
+
let metrics = self
|
|
127
|
+
.metrics
|
|
128
|
+
.clone()
|
|
129
|
+
.map(|m| {
|
|
130
|
+
// Attach labels from client wrapper
|
|
131
|
+
if let Some(other_labels) = req.extensions_mut().remove::<AttachMetricLabels>() {
|
|
132
|
+
m.with_new_attrs(other_labels.labels)
|
|
133
|
+
} else {
|
|
134
|
+
m
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
.and_then(|mut metrics| {
|
|
138
|
+
// Attach method name label if possible
|
|
139
|
+
req.uri().to_string().rsplit_once('/').map(|split_tup| {
|
|
140
|
+
let method_name = split_tup.1;
|
|
141
|
+
metrics.add_new_attrs([svc_operation(method_name.to_string())]);
|
|
142
|
+
if LONG_POLL_METHOD_NAMES.contains(&method_name) {
|
|
143
|
+
metrics.set_is_long_poll();
|
|
144
|
+
}
|
|
145
|
+
metrics.svc_request();
|
|
146
|
+
metrics
|
|
147
|
+
})
|
|
148
|
+
});
|
|
149
|
+
let callfut = self.inner.call(req);
|
|
150
|
+
async move {
|
|
151
|
+
let started = Instant::now();
|
|
152
|
+
let res = callfut.await;
|
|
153
|
+
if let Some(metrics) = metrics {
|
|
154
|
+
metrics.record_svc_req_latency(started.elapsed());
|
|
155
|
+
if res.is_err() {
|
|
156
|
+
metrics.svc_request_failed();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
res
|
|
160
|
+
}
|
|
161
|
+
.boxed()
|
|
162
|
+
}
|
|
163
|
+
}
|
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
//! We need a way to trait-ify the raw grpc client because there is no other way to get the
|
|
2
|
+
//! information we need via interceptors. This module contains the necessary stuff to make that
|
|
3
|
+
//! happen.
|
|
4
|
+
|
|
5
|
+
use crate::{
|
|
6
|
+
metrics::{namespace_kv, task_queue_kv},
|
|
7
|
+
raw::sealed::RawClientLike,
|
|
8
|
+
LONG_POLL_TIMEOUT,
|
|
9
|
+
};
|
|
10
|
+
use futures::{future::BoxFuture, FutureExt};
|
|
11
|
+
use temporal_sdk_core_protos::temporal::api::{
|
|
12
|
+
taskqueue::v1::TaskQueue, workflowservice::v1::workflow_service_client::WorkflowServiceClient,
|
|
13
|
+
};
|
|
14
|
+
use tonic::{body::BoxBody, client::GrpcService, metadata::KeyAndValueRef};
|
|
15
|
+
|
|
16
|
+
pub(super) mod sealed {
|
|
17
|
+
use super::*;
|
|
18
|
+
use crate::{ConfiguredClient, RetryClient};
|
|
19
|
+
use futures::TryFutureExt;
|
|
20
|
+
use tonic::{Request, Response, Status};
|
|
21
|
+
|
|
22
|
+
/// Something that has a workflow service client
|
|
23
|
+
#[async_trait::async_trait]
|
|
24
|
+
pub trait RawClientLike: Send {
|
|
25
|
+
type SvcType: Send + Sync + Clone + 'static;
|
|
26
|
+
|
|
27
|
+
/// Return the actual client instance
|
|
28
|
+
fn client(&mut self) -> &mut WorkflowServiceClient<Self::SvcType>;
|
|
29
|
+
|
|
30
|
+
async fn do_call<F, Req, Resp>(
|
|
31
|
+
&mut self,
|
|
32
|
+
_call_name: &'static str,
|
|
33
|
+
mut callfn: F,
|
|
34
|
+
req: Request<Req>,
|
|
35
|
+
) -> Result<Response<Resp>, Status>
|
|
36
|
+
where
|
|
37
|
+
Req: Clone + Unpin + Send + Sync + 'static,
|
|
38
|
+
F: FnMut(
|
|
39
|
+
&mut WorkflowServiceClient<Self::SvcType>,
|
|
40
|
+
Request<Req>,
|
|
41
|
+
) -> BoxFuture<'static, Result<Response<Resp>, Status>>,
|
|
42
|
+
F: Send + Sync + Unpin + 'static,
|
|
43
|
+
{
|
|
44
|
+
callfn(self.client(), req).await
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Here we implement retry on anything that is already RawClientLike
|
|
49
|
+
#[async_trait::async_trait]
|
|
50
|
+
impl<RC, T> RawClientLike for RetryClient<RC>
|
|
51
|
+
where
|
|
52
|
+
RC: RawClientLike<SvcType = T> + 'static,
|
|
53
|
+
T: Send + Sync + Clone + 'static,
|
|
54
|
+
{
|
|
55
|
+
type SvcType = T;
|
|
56
|
+
|
|
57
|
+
fn client(&mut self) -> &mut WorkflowServiceClient<Self::SvcType> {
|
|
58
|
+
self.get_client_mut().client()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async fn do_call<F, Req, Resp>(
|
|
62
|
+
&mut self,
|
|
63
|
+
call_name: &'static str,
|
|
64
|
+
mut callfn: F,
|
|
65
|
+
req: Request<Req>,
|
|
66
|
+
) -> Result<Response<Resp>, Status>
|
|
67
|
+
where
|
|
68
|
+
Req: Clone + Unpin + Send + Sync + 'static,
|
|
69
|
+
F: FnMut(
|
|
70
|
+
&mut WorkflowServiceClient<Self::SvcType>,
|
|
71
|
+
Request<Req>,
|
|
72
|
+
) -> BoxFuture<'static, Result<Response<Resp>, Status>>,
|
|
73
|
+
F: Send + Sync + Unpin + 'static,
|
|
74
|
+
{
|
|
75
|
+
let rtc = self.get_retry_config(call_name);
|
|
76
|
+
let req = req_cloner(&req);
|
|
77
|
+
let fact = || {
|
|
78
|
+
let req_clone = req_cloner(&req);
|
|
79
|
+
callfn(self.client(), req_clone)
|
|
80
|
+
};
|
|
81
|
+
let res = Self::make_future_retry(rtc, fact, call_name);
|
|
82
|
+
res.map_err(|(e, _attempt)| e).map_ok(|x| x.0).await
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
impl<T> RawClientLike for WorkflowServiceClient<T>
|
|
87
|
+
where
|
|
88
|
+
T: Send + Sync + Clone + 'static,
|
|
89
|
+
{
|
|
90
|
+
type SvcType = T;
|
|
91
|
+
|
|
92
|
+
fn client(&mut self) -> &mut WorkflowServiceClient<Self::SvcType> {
|
|
93
|
+
self
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
impl<T> RawClientLike for ConfiguredClient<WorkflowServiceClient<T>>
|
|
98
|
+
where
|
|
99
|
+
T: Send + Sync + Clone + 'static,
|
|
100
|
+
{
|
|
101
|
+
type SvcType = T;
|
|
102
|
+
|
|
103
|
+
fn client(&mut self) -> &mut WorkflowServiceClient<Self::SvcType> {
|
|
104
|
+
&mut self.client
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/// Helper for cloning a tonic request as long as the inner message may be cloned.
|
|
110
|
+
/// We drop extensions, so, lang bridges can't pass those in :shrug:
|
|
111
|
+
fn req_cloner<T: Clone>(cloneme: &tonic::Request<T>) -> tonic::Request<T> {
|
|
112
|
+
let msg = cloneme.get_ref().clone();
|
|
113
|
+
let mut new_req = tonic::Request::new(msg);
|
|
114
|
+
let new_met = new_req.metadata_mut();
|
|
115
|
+
for kv in cloneme.metadata().iter() {
|
|
116
|
+
match kv {
|
|
117
|
+
KeyAndValueRef::Ascii(k, v) => {
|
|
118
|
+
new_met.insert(k, v.clone());
|
|
119
|
+
}
|
|
120
|
+
KeyAndValueRef::Binary(k, v) => {
|
|
121
|
+
new_met.insert_bin(k, v.clone());
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
new_req
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
#[derive(Debug)]
|
|
129
|
+
pub(super) struct AttachMetricLabels {
|
|
130
|
+
pub(super) labels: Vec<opentelemetry::KeyValue>,
|
|
131
|
+
}
|
|
132
|
+
impl AttachMetricLabels {
|
|
133
|
+
pub fn new(kvs: impl Into<Vec<opentelemetry::KeyValue>>) -> Self {
|
|
134
|
+
Self { labels: kvs.into() }
|
|
135
|
+
}
|
|
136
|
+
pub fn namespace(ns: impl Into<String>) -> Self {
|
|
137
|
+
AttachMetricLabels::new(vec![namespace_kv(ns.into())])
|
|
138
|
+
}
|
|
139
|
+
pub fn task_q(&mut self, tq: Option<TaskQueue>) -> &mut Self {
|
|
140
|
+
if let Some(tq) = tq {
|
|
141
|
+
self.labels.push(task_queue_kv(tq.name));
|
|
142
|
+
}
|
|
143
|
+
self
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Blanket impl the trait for all raw-client-like things. Since the trait default-implements
|
|
148
|
+
// everything, there's nothing to actually implement.
|
|
149
|
+
impl<RC, T> WorkflowService for RC
|
|
150
|
+
where
|
|
151
|
+
RC: RawClientLike<SvcType = T>,
|
|
152
|
+
T: tonic::client::GrpcService<tonic::body::BoxBody> + Send + Clone + 'static,
|
|
153
|
+
T::ResponseBody: tonic::codegen::Body + Send + 'static,
|
|
154
|
+
T::Error: Into<tonic::codegen::StdError>,
|
|
155
|
+
T::Future: Send,
|
|
156
|
+
<T::ResponseBody as tonic::codegen::Body>::Error: Into<tonic::codegen::StdError> + Send,
|
|
157
|
+
{
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/// Helps re-declare gRPC client methods
|
|
161
|
+
macro_rules! proxy {
|
|
162
|
+
($method:ident, $req:ident, $resp:ident $(, $closure:expr)?) => {
|
|
163
|
+
#[doc = concat!("See [WorkflowServiceClient::", stringify!($method), "]")]
|
|
164
|
+
fn $method(
|
|
165
|
+
&mut self,
|
|
166
|
+
request: impl tonic::IntoRequest<super::$req>,
|
|
167
|
+
) -> BoxFuture<Result<tonic::Response<super::$resp>, tonic::Status>> {
|
|
168
|
+
#[allow(unused_mut)]
|
|
169
|
+
let fact = |c: &mut WorkflowServiceClient<Self::SvcType>, mut req: tonic::Request<super::$req>| {
|
|
170
|
+
$( type_closure_arg(&mut req, $closure); )*
|
|
171
|
+
let mut c = c.clone();
|
|
172
|
+
async move { c.$method(req).await }.boxed()
|
|
173
|
+
};
|
|
174
|
+
self.do_call(stringify!($method), fact, request.into_request())
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
// Nice little trick to avoid the callsite asking to type the closure parameter
|
|
179
|
+
fn type_closure_arg<T, R>(arg: T, f: impl FnOnce(T) -> R) -> R {
|
|
180
|
+
f(arg)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/// Trait version of the generated workflow service client with modifications to attach appropriate
|
|
184
|
+
/// metric labels or whatever else to requests
|
|
185
|
+
pub trait WorkflowService: RawClientLike
|
|
186
|
+
where
|
|
187
|
+
// Yo this is wild
|
|
188
|
+
<Self as RawClientLike>::SvcType: GrpcService<BoxBody> + Send + Clone + 'static,
|
|
189
|
+
<<Self as RawClientLike>::SvcType as GrpcService<BoxBody>>::ResponseBody:
|
|
190
|
+
tonic::codegen::Body + Send + 'static,
|
|
191
|
+
<<Self as RawClientLike>::SvcType as GrpcService<BoxBody>>::Error:
|
|
192
|
+
Into<tonic::codegen::StdError>,
|
|
193
|
+
<<Self as RawClientLike>::SvcType as GrpcService<BoxBody>>::Future: Send,
|
|
194
|
+
<<<Self as RawClientLike>::SvcType as GrpcService<BoxBody>>::ResponseBody as tonic::codegen::Body>::Error:
|
|
195
|
+
Into<tonic::codegen::StdError> + Send,
|
|
196
|
+
{
|
|
197
|
+
proxy!(
|
|
198
|
+
register_namespace,
|
|
199
|
+
RegisterNamespaceRequest,
|
|
200
|
+
RegisterNamespaceResponse,
|
|
201
|
+
|r| {
|
|
202
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
203
|
+
r.extensions_mut().insert(labels);
|
|
204
|
+
}
|
|
205
|
+
);
|
|
206
|
+
proxy!(
|
|
207
|
+
describe_namespace,
|
|
208
|
+
DescribeNamespaceRequest,
|
|
209
|
+
DescribeNamespaceResponse,
|
|
210
|
+
|r| {
|
|
211
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
212
|
+
r.extensions_mut().insert(labels);
|
|
213
|
+
}
|
|
214
|
+
);
|
|
215
|
+
proxy!(
|
|
216
|
+
list_namespaces,
|
|
217
|
+
ListNamespacesRequest,
|
|
218
|
+
ListNamespacesResponse
|
|
219
|
+
);
|
|
220
|
+
proxy!(
|
|
221
|
+
update_namespace,
|
|
222
|
+
UpdateNamespaceRequest,
|
|
223
|
+
UpdateNamespaceResponse,
|
|
224
|
+
|r| {
|
|
225
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
226
|
+
r.extensions_mut().insert(labels);
|
|
227
|
+
}
|
|
228
|
+
);
|
|
229
|
+
proxy!(
|
|
230
|
+
deprecate_namespace,
|
|
231
|
+
DeprecateNamespaceRequest,
|
|
232
|
+
DeprecateNamespaceResponse,
|
|
233
|
+
|r| {
|
|
234
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
235
|
+
r.extensions_mut().insert(labels);
|
|
236
|
+
}
|
|
237
|
+
);
|
|
238
|
+
proxy!(
|
|
239
|
+
start_workflow_execution,
|
|
240
|
+
StartWorkflowExecutionRequest,
|
|
241
|
+
StartWorkflowExecutionResponse,
|
|
242
|
+
|r| {
|
|
243
|
+
let mut labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
244
|
+
labels.task_q(r.get_ref().task_queue.clone());
|
|
245
|
+
r.extensions_mut().insert(labels);
|
|
246
|
+
}
|
|
247
|
+
);
|
|
248
|
+
proxy!(
|
|
249
|
+
get_workflow_execution_history,
|
|
250
|
+
GetWorkflowExecutionHistoryRequest,
|
|
251
|
+
GetWorkflowExecutionHistoryResponse,
|
|
252
|
+
|r| {
|
|
253
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
254
|
+
r.extensions_mut().insert(labels);
|
|
255
|
+
}
|
|
256
|
+
);
|
|
257
|
+
proxy!(
|
|
258
|
+
poll_workflow_task_queue,
|
|
259
|
+
PollWorkflowTaskQueueRequest,
|
|
260
|
+
PollWorkflowTaskQueueResponse,
|
|
261
|
+
|r| {
|
|
262
|
+
let mut labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
263
|
+
labels.task_q(r.get_ref().task_queue.clone());
|
|
264
|
+
r.extensions_mut().insert(labels);
|
|
265
|
+
r.set_timeout(LONG_POLL_TIMEOUT);
|
|
266
|
+
}
|
|
267
|
+
);
|
|
268
|
+
proxy!(
|
|
269
|
+
respond_workflow_task_completed,
|
|
270
|
+
RespondWorkflowTaskCompletedRequest,
|
|
271
|
+
RespondWorkflowTaskCompletedResponse,
|
|
272
|
+
|r| {
|
|
273
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
274
|
+
r.extensions_mut().insert(labels);
|
|
275
|
+
}
|
|
276
|
+
);
|
|
277
|
+
proxy!(
|
|
278
|
+
respond_workflow_task_failed,
|
|
279
|
+
RespondWorkflowTaskFailedRequest,
|
|
280
|
+
RespondWorkflowTaskFailedResponse,
|
|
281
|
+
|r| {
|
|
282
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
283
|
+
r.extensions_mut().insert(labels);
|
|
284
|
+
}
|
|
285
|
+
);
|
|
286
|
+
proxy!(
|
|
287
|
+
poll_activity_task_queue,
|
|
288
|
+
PollActivityTaskQueueRequest,
|
|
289
|
+
PollActivityTaskQueueResponse,
|
|
290
|
+
|r| {
|
|
291
|
+
let mut labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
292
|
+
labels.task_q(r.get_ref().task_queue.clone());
|
|
293
|
+
r.extensions_mut().insert(labels);
|
|
294
|
+
r.set_timeout(LONG_POLL_TIMEOUT);
|
|
295
|
+
}
|
|
296
|
+
);
|
|
297
|
+
proxy!(
|
|
298
|
+
record_activity_task_heartbeat,
|
|
299
|
+
RecordActivityTaskHeartbeatRequest,
|
|
300
|
+
RecordActivityTaskHeartbeatResponse,
|
|
301
|
+
|r| {
|
|
302
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
303
|
+
r.extensions_mut().insert(labels);
|
|
304
|
+
}
|
|
305
|
+
);
|
|
306
|
+
proxy!(
|
|
307
|
+
record_activity_task_heartbeat_by_id,
|
|
308
|
+
RecordActivityTaskHeartbeatByIdRequest,
|
|
309
|
+
RecordActivityTaskHeartbeatByIdResponse,
|
|
310
|
+
|r| {
|
|
311
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
312
|
+
r.extensions_mut().insert(labels);
|
|
313
|
+
}
|
|
314
|
+
);
|
|
315
|
+
proxy!(
|
|
316
|
+
respond_activity_task_completed,
|
|
317
|
+
RespondActivityTaskCompletedRequest,
|
|
318
|
+
RespondActivityTaskCompletedResponse,
|
|
319
|
+
|r| {
|
|
320
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
321
|
+
r.extensions_mut().insert(labels);
|
|
322
|
+
}
|
|
323
|
+
);
|
|
324
|
+
proxy!(
|
|
325
|
+
respond_activity_task_completed_by_id,
|
|
326
|
+
RespondActivityTaskCompletedByIdRequest,
|
|
327
|
+
RespondActivityTaskCompletedByIdResponse,
|
|
328
|
+
|r| {
|
|
329
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
330
|
+
r.extensions_mut().insert(labels);
|
|
331
|
+
}
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
proxy!(
|
|
335
|
+
respond_activity_task_failed,
|
|
336
|
+
RespondActivityTaskFailedRequest,
|
|
337
|
+
RespondActivityTaskFailedResponse,
|
|
338
|
+
|r| {
|
|
339
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
340
|
+
r.extensions_mut().insert(labels);
|
|
341
|
+
}
|
|
342
|
+
);
|
|
343
|
+
proxy!(
|
|
344
|
+
respond_activity_task_failed_by_id,
|
|
345
|
+
RespondActivityTaskFailedByIdRequest,
|
|
346
|
+
RespondActivityTaskFailedByIdResponse,
|
|
347
|
+
|r| {
|
|
348
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
349
|
+
r.extensions_mut().insert(labels);
|
|
350
|
+
}
|
|
351
|
+
);
|
|
352
|
+
proxy!(
|
|
353
|
+
respond_activity_task_canceled,
|
|
354
|
+
RespondActivityTaskCanceledRequest,
|
|
355
|
+
RespondActivityTaskCanceledResponse,
|
|
356
|
+
|r| {
|
|
357
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
358
|
+
r.extensions_mut().insert(labels);
|
|
359
|
+
}
|
|
360
|
+
);
|
|
361
|
+
proxy!(
|
|
362
|
+
respond_activity_task_canceled_by_id,
|
|
363
|
+
RespondActivityTaskCanceledByIdRequest,
|
|
364
|
+
RespondActivityTaskCanceledByIdResponse,
|
|
365
|
+
|r| {
|
|
366
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
367
|
+
r.extensions_mut().insert(labels);
|
|
368
|
+
}
|
|
369
|
+
);
|
|
370
|
+
proxy!(
|
|
371
|
+
request_cancel_workflow_execution,
|
|
372
|
+
RequestCancelWorkflowExecutionRequest,
|
|
373
|
+
RequestCancelWorkflowExecutionResponse,
|
|
374
|
+
|r| {
|
|
375
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
376
|
+
r.extensions_mut().insert(labels);
|
|
377
|
+
}
|
|
378
|
+
);
|
|
379
|
+
proxy!(
|
|
380
|
+
signal_workflow_execution,
|
|
381
|
+
SignalWorkflowExecutionRequest,
|
|
382
|
+
SignalWorkflowExecutionResponse,
|
|
383
|
+
|r| {
|
|
384
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
385
|
+
r.extensions_mut().insert(labels);
|
|
386
|
+
}
|
|
387
|
+
);
|
|
388
|
+
proxy!(
|
|
389
|
+
signal_with_start_workflow_execution,
|
|
390
|
+
SignalWithStartWorkflowExecutionRequest,
|
|
391
|
+
SignalWithStartWorkflowExecutionResponse,
|
|
392
|
+
|r| {
|
|
393
|
+
let mut labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
394
|
+
labels.task_q(r.get_ref().task_queue.clone());
|
|
395
|
+
r.extensions_mut().insert(labels);
|
|
396
|
+
}
|
|
397
|
+
);
|
|
398
|
+
proxy!(
|
|
399
|
+
reset_workflow_execution,
|
|
400
|
+
ResetWorkflowExecutionRequest,
|
|
401
|
+
ResetWorkflowExecutionResponse,
|
|
402
|
+
|r| {
|
|
403
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
404
|
+
r.extensions_mut().insert(labels);
|
|
405
|
+
}
|
|
406
|
+
);
|
|
407
|
+
proxy!(
|
|
408
|
+
terminate_workflow_execution,
|
|
409
|
+
TerminateWorkflowExecutionRequest,
|
|
410
|
+
TerminateWorkflowExecutionResponse,
|
|
411
|
+
|r| {
|
|
412
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
413
|
+
r.extensions_mut().insert(labels);
|
|
414
|
+
}
|
|
415
|
+
);
|
|
416
|
+
proxy!(
|
|
417
|
+
list_open_workflow_executions,
|
|
418
|
+
ListOpenWorkflowExecutionsRequest,
|
|
419
|
+
ListOpenWorkflowExecutionsResponse,
|
|
420
|
+
|r| {
|
|
421
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
422
|
+
r.extensions_mut().insert(labels);
|
|
423
|
+
}
|
|
424
|
+
);
|
|
425
|
+
proxy!(
|
|
426
|
+
list_closed_workflow_executions,
|
|
427
|
+
ListClosedWorkflowExecutionsRequest,
|
|
428
|
+
ListClosedWorkflowExecutionsResponse,
|
|
429
|
+
|r| {
|
|
430
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
431
|
+
r.extensions_mut().insert(labels);
|
|
432
|
+
}
|
|
433
|
+
);
|
|
434
|
+
proxy!(
|
|
435
|
+
list_workflow_executions,
|
|
436
|
+
ListWorkflowExecutionsRequest,
|
|
437
|
+
ListWorkflowExecutionsResponse,
|
|
438
|
+
|r| {
|
|
439
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
440
|
+
r.extensions_mut().insert(labels);
|
|
441
|
+
}
|
|
442
|
+
);
|
|
443
|
+
proxy!(
|
|
444
|
+
list_archived_workflow_executions,
|
|
445
|
+
ListArchivedWorkflowExecutionsRequest,
|
|
446
|
+
ListArchivedWorkflowExecutionsResponse,
|
|
447
|
+
|r| {
|
|
448
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
449
|
+
r.extensions_mut().insert(labels);
|
|
450
|
+
}
|
|
451
|
+
);
|
|
452
|
+
proxy!(
|
|
453
|
+
scan_workflow_executions,
|
|
454
|
+
ScanWorkflowExecutionsRequest,
|
|
455
|
+
ScanWorkflowExecutionsResponse,
|
|
456
|
+
|r| {
|
|
457
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
458
|
+
r.extensions_mut().insert(labels);
|
|
459
|
+
}
|
|
460
|
+
);
|
|
461
|
+
proxy!(
|
|
462
|
+
count_workflow_executions,
|
|
463
|
+
CountWorkflowExecutionsRequest,
|
|
464
|
+
CountWorkflowExecutionsResponse,
|
|
465
|
+
|r| {
|
|
466
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
467
|
+
r.extensions_mut().insert(labels);
|
|
468
|
+
}
|
|
469
|
+
);
|
|
470
|
+
proxy!(
|
|
471
|
+
get_search_attributes,
|
|
472
|
+
GetSearchAttributesRequest,
|
|
473
|
+
GetSearchAttributesResponse
|
|
474
|
+
);
|
|
475
|
+
proxy!(
|
|
476
|
+
respond_query_task_completed,
|
|
477
|
+
RespondQueryTaskCompletedRequest,
|
|
478
|
+
RespondQueryTaskCompletedResponse,
|
|
479
|
+
|r| {
|
|
480
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
481
|
+
r.extensions_mut().insert(labels);
|
|
482
|
+
}
|
|
483
|
+
);
|
|
484
|
+
proxy!(
|
|
485
|
+
reset_sticky_task_queue,
|
|
486
|
+
ResetStickyTaskQueueRequest,
|
|
487
|
+
ResetStickyTaskQueueResponse,
|
|
488
|
+
|r| {
|
|
489
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
490
|
+
r.extensions_mut().insert(labels);
|
|
491
|
+
}
|
|
492
|
+
);
|
|
493
|
+
proxy!(
|
|
494
|
+
query_workflow,
|
|
495
|
+
QueryWorkflowRequest,
|
|
496
|
+
QueryWorkflowResponse,
|
|
497
|
+
|r| {
|
|
498
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
499
|
+
r.extensions_mut().insert(labels);
|
|
500
|
+
}
|
|
501
|
+
);
|
|
502
|
+
proxy!(
|
|
503
|
+
describe_workflow_execution,
|
|
504
|
+
DescribeWorkflowExecutionRequest,
|
|
505
|
+
DescribeWorkflowExecutionResponse,
|
|
506
|
+
|r| {
|
|
507
|
+
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
508
|
+
r.extensions_mut().insert(labels);
|
|
509
|
+
}
|
|
510
|
+
);
|
|
511
|
+
proxy!(
|
|
512
|
+
describe_task_queue,
|
|
513
|
+
DescribeTaskQueueRequest,
|
|
514
|
+
DescribeTaskQueueResponse,
|
|
515
|
+
|r| {
|
|
516
|
+
let mut labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
517
|
+
labels.task_q(r.get_ref().task_queue.clone());
|
|
518
|
+
r.extensions_mut().insert(labels);
|
|
519
|
+
}
|
|
520
|
+
);
|
|
521
|
+
proxy!(
|
|
522
|
+
get_cluster_info,
|
|
523
|
+
GetClusterInfoRequest,
|
|
524
|
+
GetClusterInfoResponse
|
|
525
|
+
);
|
|
526
|
+
proxy!(
|
|
527
|
+
get_system_info,
|
|
528
|
+
GetSystemInfoRequest,
|
|
529
|
+
GetSystemInfoResponse
|
|
530
|
+
);
|
|
531
|
+
proxy!(
|
|
532
|
+
list_task_queue_partitions,
|
|
533
|
+
ListTaskQueuePartitionsRequest,
|
|
534
|
+
ListTaskQueuePartitionsResponse,
|
|
535
|
+
|r| {
|
|
536
|
+
let mut labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
537
|
+
labels.task_q(r.get_ref().task_queue.clone());
|
|
538
|
+
r.extensions_mut().insert(labels);
|
|
539
|
+
}
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
#[cfg(test)]
|
|
544
|
+
mod tests {
|
|
545
|
+
use super::*;
|
|
546
|
+
use crate::{ClientOptionsBuilder, RetryClient, WorkflowServiceClientWithMetrics};
|
|
547
|
+
use temporal_sdk_core_protos::temporal::api::workflowservice::v1::ListNamespacesRequest;
|
|
548
|
+
|
|
549
|
+
// Just to help make sure some stuff compiles. Not run.
|
|
550
|
+
#[allow(dead_code)]
|
|
551
|
+
async fn raw_client_retry_compiles() {
|
|
552
|
+
let opts = ClientOptionsBuilder::default().build().unwrap();
|
|
553
|
+
let raw_client = opts.connect_no_namespace(None).await.unwrap();
|
|
554
|
+
let mut retry_client = RetryClient::new(raw_client, opts.retry_config);
|
|
555
|
+
|
|
556
|
+
let the_request = ListNamespacesRequest::default();
|
|
557
|
+
let fact = |c: &mut WorkflowServiceClientWithMetrics, req| {
|
|
558
|
+
let mut c = c.clone();
|
|
559
|
+
async move { c.list_namespaces(req).await }.boxed()
|
|
560
|
+
};
|
|
561
|
+
retry_client
|
|
562
|
+
.do_call("whatever", fact, tonic::Request::new(the_request))
|
|
563
|
+
.await
|
|
564
|
+
.unwrap();
|
|
565
|
+
}
|
|
566
|
+
}
|