@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
|
@@ -3,9 +3,10 @@ pub(crate) use temporal_sdk_core_test_utils::canned_histories;
|
|
|
3
3
|
use crate::{
|
|
4
4
|
pollers::{BoxedActPoller, BoxedPoller, BoxedWFPoller, MockManualPoller, MockPoller},
|
|
5
5
|
replay::TestHistoryBuilder,
|
|
6
|
+
sticky_q_name_for_worker,
|
|
7
|
+
worker::client::{mocks::mock_workflow_client, MockWorkerClient, WorkerClient},
|
|
6
8
|
workflow::WorkflowCachingPolicy,
|
|
7
|
-
|
|
8
|
-
WorkerConfigBuilder,
|
|
9
|
+
TaskToken, Worker, WorkerClientBag, WorkerConfig, WorkerConfigBuilder,
|
|
9
10
|
};
|
|
10
11
|
use bimap::BiMap;
|
|
11
12
|
use futures::FutureExt;
|
|
@@ -16,10 +17,7 @@ use std::{
|
|
|
16
17
|
ops::RangeFull,
|
|
17
18
|
sync::Arc,
|
|
18
19
|
};
|
|
19
|
-
use
|
|
20
|
-
mocks::{fake_sg_opts, mock_gateway},
|
|
21
|
-
MockServerGatewayApis,
|
|
22
|
-
};
|
|
20
|
+
use temporal_sdk_core_api::Worker as WorkerTrait;
|
|
23
21
|
use temporal_sdk_core_protos::{
|
|
24
22
|
coresdk::{
|
|
25
23
|
workflow_activation::WorkflowActivation,
|
|
@@ -40,6 +38,12 @@ use temporal_sdk_core_protos::{
|
|
|
40
38
|
pub const TEST_Q: &str = "q";
|
|
41
39
|
pub static NO_MORE_WORK_ERROR_MSG: &str = "No more work to do";
|
|
42
40
|
|
|
41
|
+
pub fn test_worker_cfg() -> WorkerConfigBuilder {
|
|
42
|
+
let mut wcb = WorkerConfigBuilder::default();
|
|
43
|
+
wcb.namespace("default").task_queue(TEST_Q);
|
|
44
|
+
wcb
|
|
45
|
+
}
|
|
46
|
+
|
|
43
47
|
/// When constructing responses for mocks, indicates how a given response should be built
|
|
44
48
|
#[derive(derive_more::From, Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
|
45
49
|
pub enum ResponseType {
|
|
@@ -64,92 +68,58 @@ impl From<&Self> for ResponseType {
|
|
|
64
68
|
}
|
|
65
69
|
|
|
66
70
|
/// Given identifiers for a workflow/run, and a test history builder, construct an instance of
|
|
67
|
-
/// the
|
|
71
|
+
/// the a worker with a mock server client that will produce the responses as appropriate.
|
|
68
72
|
///
|
|
69
73
|
/// `response_batches` is used to control the fake [PollWorkflowTaskQueueResponse]s returned. For
|
|
70
74
|
/// each number in the input list, a fake response will be prepared which includes history up to the
|
|
71
75
|
/// workflow task with that number, as in [TestHistoryBuilder::get_history_info].
|
|
72
|
-
pub(crate) fn
|
|
76
|
+
pub(crate) fn build_fake_worker(
|
|
73
77
|
wf_id: &str,
|
|
74
78
|
t: TestHistoryBuilder,
|
|
75
79
|
response_batches: impl IntoIterator<Item = impl Into<ResponseType>>,
|
|
76
|
-
) ->
|
|
80
|
+
) -> Worker {
|
|
77
81
|
let response_batches = response_batches.into_iter().map(Into::into).collect();
|
|
78
|
-
let
|
|
82
|
+
let mock_holder = build_multihist_mock_sg(
|
|
79
83
|
vec![FakeWfResponses {
|
|
80
84
|
wf_id: wf_id.to_owned(),
|
|
81
85
|
hist: t,
|
|
82
86
|
response_batches,
|
|
83
|
-
task_q: TEST_Q.to_owned(),
|
|
84
87
|
}],
|
|
85
88
|
true,
|
|
86
89
|
None,
|
|
87
90
|
);
|
|
88
|
-
|
|
91
|
+
mock_worker(mock_holder)
|
|
89
92
|
}
|
|
90
93
|
|
|
91
|
-
pub(crate) fn
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
) -> CoreSDK
|
|
102
|
-
where
|
|
103
|
-
SG: ServerGatewayApis + Send + Sync + 'static,
|
|
104
|
-
{
|
|
105
|
-
let mut core = mock_core_with_opts_no_workers(mocks.sg, opts);
|
|
106
|
-
register_mock_workers(&mut core, mocks.mock_pollers.into_values());
|
|
107
|
-
core
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
pub(crate) fn register_mock_workers(
|
|
111
|
-
core: &mut CoreSDK,
|
|
112
|
-
mocks: impl IntoIterator<Item = MockWorker>,
|
|
113
|
-
) {
|
|
114
|
-
for worker in mocks {
|
|
115
|
-
core.reg_worker_sync(worker);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
pub(crate) fn mock_core_with_opts_no_workers<SG>(
|
|
120
|
-
sg: SG,
|
|
121
|
-
mut opts: CoreInitOptionsBuilder,
|
|
122
|
-
) -> CoreSDK
|
|
123
|
-
where
|
|
124
|
-
SG: ServerGatewayApis + Send + Sync + 'static,
|
|
125
|
-
{
|
|
126
|
-
CoreSDK::new(sg, opts.gateway_opts(fake_sg_opts()).build().unwrap())
|
|
94
|
+
pub(crate) fn mock_worker(mocks: MocksHolder) -> Worker {
|
|
95
|
+
let sticky_q = sticky_q_name_for_worker("unit-test", &mocks.mock_worker.config);
|
|
96
|
+
Worker::new_with_pollers(
|
|
97
|
+
mocks.mock_worker.config,
|
|
98
|
+
sticky_q,
|
|
99
|
+
Arc::new(mocks.client_bag),
|
|
100
|
+
mocks.mock_worker.wf_poller,
|
|
101
|
+
mocks.mock_worker.act_poller,
|
|
102
|
+
Default::default(),
|
|
103
|
+
)
|
|
127
104
|
}
|
|
128
105
|
|
|
129
106
|
pub struct FakeWfResponses {
|
|
130
107
|
pub wf_id: String,
|
|
131
108
|
pub hist: TestHistoryBuilder,
|
|
132
109
|
pub response_batches: Vec<ResponseType>,
|
|
133
|
-
pub task_q: String,
|
|
134
110
|
}
|
|
135
111
|
|
|
136
|
-
// TODO:
|
|
137
|
-
pub struct MocksHolder
|
|
138
|
-
|
|
139
|
-
|
|
112
|
+
// TODO: Rename to mock TQ or something?
|
|
113
|
+
pub struct MocksHolder {
|
|
114
|
+
client_bag: WorkerClientBag,
|
|
115
|
+
mock_worker: MockWorker,
|
|
140
116
|
// bidirectional mapping of run id / task token
|
|
141
117
|
pub outstanding_task_map: Option<Arc<RwLock<BiMap<String, TaskToken>>>>,
|
|
142
118
|
}
|
|
143
119
|
|
|
144
|
-
impl
|
|
145
|
-
pub fn worker_cfg(&mut self,
|
|
146
|
-
|
|
147
|
-
mutator(&mut w.config);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
pub fn take_pollers(self) -> HashMap<String, MockWorker> {
|
|
152
|
-
self.mock_pollers
|
|
120
|
+
impl MocksHolder {
|
|
121
|
+
pub fn worker_cfg(&mut self, mutator: impl FnOnce(&mut WorkerConfig)) {
|
|
122
|
+
mutator(&mut self.mock_worker.config);
|
|
153
123
|
}
|
|
154
124
|
}
|
|
155
125
|
|
|
@@ -161,74 +131,57 @@ pub struct MockWorker {
|
|
|
161
131
|
|
|
162
132
|
impl Default for MockWorker {
|
|
163
133
|
fn default() -> Self {
|
|
164
|
-
Self::
|
|
134
|
+
Self::new(Box::from(mock_poller()))
|
|
165
135
|
}
|
|
166
136
|
}
|
|
167
137
|
|
|
168
138
|
impl MockWorker {
|
|
169
|
-
pub fn new(
|
|
139
|
+
pub fn new(wf_poller: BoxedWFPoller) -> Self {
|
|
170
140
|
Self {
|
|
171
141
|
wf_poller,
|
|
172
142
|
act_poller: None,
|
|
173
|
-
config:
|
|
174
|
-
.task_queue(q)
|
|
175
|
-
.build()
|
|
176
|
-
.unwrap(),
|
|
143
|
+
config: test_worker_cfg().build().unwrap(),
|
|
177
144
|
}
|
|
178
145
|
}
|
|
179
|
-
|
|
180
|
-
pub fn for_queue(q: &str) -> Self {
|
|
181
|
-
Self::new(q, Box::from(mock_poller()))
|
|
182
|
-
}
|
|
183
146
|
}
|
|
184
147
|
|
|
185
|
-
impl
|
|
186
|
-
|
|
187
|
-
SG: ServerGatewayApis + Send + Sync + 'static,
|
|
188
|
-
{
|
|
189
|
-
pub fn from_mock_workers(sg: SG, mock_workers: impl IntoIterator<Item = MockWorker>) -> Self {
|
|
190
|
-
let mock_pollers = mock_workers
|
|
191
|
-
.into_iter()
|
|
192
|
-
.map(|w| (w.config.task_queue.clone(), w))
|
|
193
|
-
.collect();
|
|
148
|
+
impl MocksHolder {
|
|
149
|
+
pub(crate) fn from_mock_worker(client_bag: WorkerClientBag, mock_worker: MockWorker) -> Self {
|
|
194
150
|
Self {
|
|
195
|
-
|
|
196
|
-
|
|
151
|
+
client_bag,
|
|
152
|
+
mock_worker,
|
|
197
153
|
outstanding_task_map: None,
|
|
198
154
|
}
|
|
199
155
|
}
|
|
200
156
|
|
|
201
157
|
/// Uses the provided list of tasks to create a mock poller for the `TEST_Q`
|
|
202
|
-
pub fn
|
|
158
|
+
pub(crate) fn from_client_with_responses<WFT, ACT>(
|
|
159
|
+
client: impl WorkerClient + 'static,
|
|
160
|
+
wf_tasks: WFT,
|
|
161
|
+
act_tasks: ACT,
|
|
162
|
+
) -> Self
|
|
203
163
|
where
|
|
204
164
|
WFT: IntoIterator<Item = PollWorkflowTaskQueueResponse>,
|
|
205
165
|
ACT: IntoIterator<Item = PollActivityTaskQueueResponse>,
|
|
206
166
|
<WFT as IntoIterator>::IntoIter: Send + 'static,
|
|
207
167
|
<ACT as IntoIterator>::IntoIter: Send + 'static,
|
|
208
168
|
{
|
|
209
|
-
let mut mock_pollers = HashMap::new();
|
|
210
169
|
let mock_poller = mock_poller_from_resps(wf_tasks);
|
|
211
170
|
let mock_act_poller = mock_poller_from_resps(act_tasks);
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
config: WorkerConfigBuilder::default()
|
|
218
|
-
.task_queue(TEST_Q)
|
|
219
|
-
.build()
|
|
220
|
-
.unwrap(),
|
|
221
|
-
},
|
|
222
|
-
);
|
|
171
|
+
let mock_worker = MockWorker {
|
|
172
|
+
wf_poller: mock_poller,
|
|
173
|
+
act_poller: Some(mock_act_poller),
|
|
174
|
+
config: test_worker_cfg().build().unwrap(),
|
|
175
|
+
};
|
|
223
176
|
Self {
|
|
224
|
-
|
|
225
|
-
|
|
177
|
+
client_bag: client.into(),
|
|
178
|
+
mock_worker,
|
|
226
179
|
outstanding_task_map: None,
|
|
227
180
|
}
|
|
228
181
|
}
|
|
229
182
|
}
|
|
230
183
|
|
|
231
|
-
pub fn mock_poller_from_resps<T, I>(tasks: I) -> BoxedPoller<T>
|
|
184
|
+
pub(crate) fn mock_poller_from_resps<T, I>(tasks: I) -> BoxedPoller<T>
|
|
232
185
|
where
|
|
233
186
|
T: Send + Sync + 'static,
|
|
234
187
|
I: IntoIterator<Item = T>,
|
|
@@ -268,7 +221,7 @@ where
|
|
|
268
221
|
mock_poller
|
|
269
222
|
}
|
|
270
223
|
|
|
271
|
-
/// Build a mock server
|
|
224
|
+
/// Build a mock server client capable of returning multiple different histories for different
|
|
272
225
|
/// workflows. It does so by tracking outstanding workflow tasks like is also happening in core
|
|
273
226
|
/// (which is unfortunately a bit redundant, we could provide hooks in core but that feels a little
|
|
274
227
|
/// nasty). If there is an outstanding task for a given workflow, new chunks of its history are not
|
|
@@ -277,11 +230,11 @@ where
|
|
|
277
230
|
///
|
|
278
231
|
/// `num_expected_fails` can be provided to set a specific number of expected failed workflow tasks
|
|
279
232
|
/// sent to the server.
|
|
280
|
-
pub fn build_multihist_mock_sg(
|
|
233
|
+
pub(crate) fn build_multihist_mock_sg(
|
|
281
234
|
hists: impl IntoIterator<Item = FakeWfResponses>,
|
|
282
235
|
enforce_correct_number_of_polls: bool,
|
|
283
236
|
num_expected_fails: Option<usize>,
|
|
284
|
-
) -> MocksHolder
|
|
237
|
+
) -> MocksHolder {
|
|
285
238
|
let mh = MockPollCfg::new(
|
|
286
239
|
hists.into_iter().collect(),
|
|
287
240
|
enforce_correct_number_of_polls,
|
|
@@ -291,23 +244,23 @@ pub fn build_multihist_mock_sg(
|
|
|
291
244
|
}
|
|
292
245
|
|
|
293
246
|
/// See [build_multihist_mock_sg] -- one history convenience version
|
|
294
|
-
pub fn single_hist_mock_sg(
|
|
247
|
+
pub(crate) fn single_hist_mock_sg(
|
|
295
248
|
wf_id: &str,
|
|
296
249
|
t: TestHistoryBuilder,
|
|
297
250
|
response_batches: impl IntoIterator<Item = impl Into<ResponseType>>,
|
|
298
|
-
|
|
251
|
+
mock_client: MockWorkerClient,
|
|
299
252
|
enforce_num_polls: bool,
|
|
300
|
-
) -> MocksHolder
|
|
301
|
-
let mut mh = MockPollCfg::from_resp_batches(wf_id, t, response_batches,
|
|
253
|
+
) -> MocksHolder {
|
|
254
|
+
let mut mh = MockPollCfg::from_resp_batches(wf_id, t, response_batches, mock_client);
|
|
302
255
|
mh.enforce_correct_number_of_polls = enforce_num_polls;
|
|
303
256
|
build_mock_pollers(mh)
|
|
304
257
|
}
|
|
305
258
|
|
|
306
|
-
pub struct MockPollCfg {
|
|
259
|
+
pub(crate) struct MockPollCfg {
|
|
307
260
|
pub hists: Vec<FakeWfResponses>,
|
|
308
261
|
pub enforce_correct_number_of_polls: bool,
|
|
309
262
|
pub num_expected_fails: Option<usize>,
|
|
310
|
-
pub
|
|
263
|
+
pub mock_client: MockWorkerClient,
|
|
311
264
|
/// All calls to fail WFTs must match this predicate
|
|
312
265
|
pub expect_fail_wft_matcher:
|
|
313
266
|
Box<dyn Fn(&TaskToken, &WorkflowTaskFailedCause, &Option<Failure>) -> bool + Send>,
|
|
@@ -323,7 +276,7 @@ impl MockPollCfg {
|
|
|
323
276
|
hists,
|
|
324
277
|
enforce_correct_number_of_polls,
|
|
325
278
|
num_expected_fails,
|
|
326
|
-
|
|
279
|
+
mock_client: mock_workflow_client(),
|
|
327
280
|
expect_fail_wft_matcher: Box::new(|_, _, _| true),
|
|
328
281
|
}
|
|
329
282
|
}
|
|
@@ -331,27 +284,25 @@ impl MockPollCfg {
|
|
|
331
284
|
wf_id: &str,
|
|
332
285
|
t: TestHistoryBuilder,
|
|
333
286
|
resps: impl IntoIterator<Item = impl Into<ResponseType>>,
|
|
334
|
-
|
|
287
|
+
mock_client: MockWorkerClient,
|
|
335
288
|
) -> Self {
|
|
336
289
|
Self {
|
|
337
290
|
hists: vec![FakeWfResponses {
|
|
338
291
|
wf_id: wf_id.to_owned(),
|
|
339
292
|
hist: t,
|
|
340
293
|
response_batches: resps.into_iter().map(Into::into).collect(),
|
|
341
|
-
task_q: TEST_Q.to_owned(),
|
|
342
294
|
}],
|
|
343
295
|
enforce_correct_number_of_polls: true,
|
|
344
296
|
num_expected_fails: None,
|
|
345
|
-
|
|
297
|
+
mock_client,
|
|
346
298
|
expect_fail_wft_matcher: Box::new(|_, _, _| true),
|
|
347
299
|
}
|
|
348
300
|
}
|
|
349
301
|
}
|
|
350
302
|
|
|
351
303
|
/// Given an iterable of fake responses, return the mocks & associated data to work with them
|
|
352
|
-
pub fn build_mock_pollers(mut cfg: MockPollCfg) -> MocksHolder
|
|
353
|
-
|
|
354
|
-
let mut task_queues_to_resps: HashMap<String, BTreeMap<String, VecDeque<_>>> = HashMap::new();
|
|
304
|
+
pub(crate) fn build_mock_pollers(mut cfg: MockPollCfg) -> MocksHolder {
|
|
305
|
+
let mut task_q_resps: BTreeMap<String, VecDeque<_>> = BTreeMap::new();
|
|
355
306
|
let outstanding_wf_task_tokens = Arc::new(RwLock::new(BiMap::new()));
|
|
356
307
|
let mut correct_num_polls = None;
|
|
357
308
|
|
|
@@ -384,12 +335,7 @@ pub fn build_mock_pollers(mut cfg: MockPollCfg) -> MocksHolder<MockServerGateway
|
|
|
384
335
|
.iter()
|
|
385
336
|
.map(|to_task_num| {
|
|
386
337
|
let cur_attempt = attempts_at_task_num.entry(to_task_num).or_insert(1);
|
|
387
|
-
let mut r = hist_to_poll_resp(
|
|
388
|
-
&hist.hist,
|
|
389
|
-
hist.wf_id.clone(),
|
|
390
|
-
*to_task_num,
|
|
391
|
-
hist.task_q.clone(),
|
|
392
|
-
);
|
|
338
|
+
let mut r = hist_to_poll_resp(&hist.hist, hist.wf_id.clone(), *to_task_num, TEST_Q);
|
|
393
339
|
r.attempt = *cur_attempt;
|
|
394
340
|
*cur_attempt += 1;
|
|
395
341
|
r
|
|
@@ -397,52 +343,44 @@ pub fn build_mock_pollers(mut cfg: MockPollCfg) -> MocksHolder<MockServerGateway
|
|
|
397
343
|
.collect();
|
|
398
344
|
|
|
399
345
|
let tasks = VecDeque::from(responses);
|
|
400
|
-
|
|
401
|
-
.entry(hist.task_q)
|
|
402
|
-
.or_default()
|
|
403
|
-
.insert(hist.wf_id, tasks);
|
|
346
|
+
task_q_resps.insert(hist.wf_id, tasks);
|
|
404
347
|
}
|
|
405
348
|
|
|
406
|
-
let mut
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
.
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
.write()
|
|
426
|
-
.insert(rid, TaskToken(t.task_token.clone()));
|
|
427
|
-
return Some(Ok(t));
|
|
428
|
-
}
|
|
349
|
+
let mut mock_poller = mock_poller();
|
|
350
|
+
// The poller will return history from any workflow runs that do not have currently
|
|
351
|
+
// outstanding tasks.
|
|
352
|
+
let outstanding = outstanding_wf_task_tokens.clone();
|
|
353
|
+
mock_poller
|
|
354
|
+
.expect_poll()
|
|
355
|
+
.times(correct_num_polls.map_or_else(|| RangeFull.into(), Into::<TimesRange>::into))
|
|
356
|
+
.returning(move || {
|
|
357
|
+
for (_, tasks) in task_q_resps.iter_mut() {
|
|
358
|
+
// Must extract run id from a workflow task associated with this workflow
|
|
359
|
+
// TODO: Case where run id changes for same workflow id is not handled here
|
|
360
|
+
if let Some(t) = tasks.get(0) {
|
|
361
|
+
let rid = t.workflow_execution.as_ref().unwrap().run_id.clone();
|
|
362
|
+
if !outstanding.read().contains_left(&rid) {
|
|
363
|
+
let t = tasks.pop_front().unwrap();
|
|
364
|
+
outstanding
|
|
365
|
+
.write()
|
|
366
|
+
.insert(rid, TaskToken(t.task_token.clone()));
|
|
367
|
+
return Some(Ok(t));
|
|
429
368
|
}
|
|
430
369
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
}
|
|
370
|
+
}
|
|
371
|
+
Some(Err(tonic::Status::cancelled(NO_MORE_WORK_ERROR_MSG)))
|
|
372
|
+
});
|
|
373
|
+
let mock_worker = MockWorker::new(Box::from(mock_poller));
|
|
436
374
|
|
|
437
375
|
let outstanding = outstanding_wf_task_tokens.clone();
|
|
438
|
-
cfg.
|
|
376
|
+
cfg.mock_client
|
|
439
377
|
.expect_complete_workflow_task()
|
|
440
378
|
.returning(move |comp| {
|
|
441
379
|
outstanding.write().remove_by_right(&comp.task_token);
|
|
442
380
|
Ok(RespondWorkflowTaskCompletedResponse::default())
|
|
443
381
|
});
|
|
444
382
|
let outstanding = outstanding_wf_task_tokens.clone();
|
|
445
|
-
cfg.
|
|
383
|
+
cfg.mock_client
|
|
446
384
|
.expect_fail_workflow_task()
|
|
447
385
|
.withf(cfg.expect_fail_wft_matcher)
|
|
448
386
|
.times(
|
|
@@ -453,13 +391,10 @@ pub fn build_mock_pollers(mut cfg: MockPollCfg) -> MocksHolder<MockServerGateway
|
|
|
453
391
|
outstanding.write().remove_by_right(&tt);
|
|
454
392
|
Ok(Default::default())
|
|
455
393
|
});
|
|
456
|
-
cfg.mock_gateway
|
|
457
|
-
.expect_start_workflow()
|
|
458
|
-
.returning(|_, _, _, _, _| Ok(Default::default()));
|
|
459
394
|
|
|
460
395
|
MocksHolder {
|
|
461
|
-
|
|
462
|
-
|
|
396
|
+
client_bag: cfg.mock_client.into(),
|
|
397
|
+
mock_worker,
|
|
463
398
|
outstanding_task_map: Some(outstanding_wf_task_tokens),
|
|
464
399
|
}
|
|
465
400
|
}
|
|
@@ -468,7 +403,7 @@ pub fn hist_to_poll_resp(
|
|
|
468
403
|
t: &TestHistoryBuilder,
|
|
469
404
|
wf_id: String,
|
|
470
405
|
response_type: ResponseType,
|
|
471
|
-
task_queue: String
|
|
406
|
+
task_queue: impl Into<String>,
|
|
472
407
|
) -> PollWorkflowTaskQueueResponse {
|
|
473
408
|
let run_id = t.get_orig_run_id();
|
|
474
409
|
let wf = WorkflowExecution {
|
|
@@ -498,15 +433,15 @@ type AsserterWithReply<'a> = (
|
|
|
498
433
|
/// since they clearly can't be returned every time we replay the workflow, or it could never
|
|
499
434
|
/// proceed
|
|
500
435
|
pub(crate) async fn poll_and_reply<'a>(
|
|
501
|
-
|
|
436
|
+
worker: &'a Worker,
|
|
502
437
|
eviction_mode: WorkflowCachingPolicy,
|
|
503
438
|
expect_and_reply: &'a [AsserterWithReply<'a>],
|
|
504
439
|
) {
|
|
505
|
-
poll_and_reply_clears_outstanding_evicts(
|
|
440
|
+
poll_and_reply_clears_outstanding_evicts(worker, None, eviction_mode, expect_and_reply).await;
|
|
506
441
|
}
|
|
507
442
|
|
|
508
443
|
pub(crate) async fn poll_and_reply_clears_outstanding_evicts<'a>(
|
|
509
|
-
|
|
444
|
+
worker: &'a Worker,
|
|
510
445
|
outstanding_map: Option<Arc<RwLock<BiMap<String, TaskToken>>>>,
|
|
511
446
|
eviction_mode: WorkflowCachingPolicy,
|
|
512
447
|
expect_and_reply: &'a [AsserterWithReply<'a>],
|
|
@@ -530,7 +465,7 @@ pub(crate) async fn poll_and_reply_clears_outstanding_evicts<'a>(
|
|
|
530
465
|
continue;
|
|
531
466
|
}
|
|
532
467
|
|
|
533
|
-
let mut res =
|
|
468
|
+
let mut res = worker.poll_workflow_activation().await.unwrap();
|
|
534
469
|
let contains_eviction = res.eviction_index();
|
|
535
470
|
|
|
536
471
|
if let Some(eviction_job_ix) = contains_eviction {
|
|
@@ -554,17 +489,16 @@ pub(crate) async fn poll_and_reply_clears_outstanding_evicts<'a>(
|
|
|
554
489
|
|
|
555
490
|
let reply = if res.jobs.is_empty() {
|
|
556
491
|
// Just an eviction
|
|
557
|
-
WorkflowActivationCompletion::empty(
|
|
492
|
+
WorkflowActivationCompletion::empty(res.run_id.clone())
|
|
558
493
|
} else {
|
|
559
494
|
// Eviction plus some work, we still want to issue the reply
|
|
560
495
|
WorkflowActivationCompletion {
|
|
561
|
-
task_queue: TEST_Q.to_string(),
|
|
562
496
|
run_id: res.run_id.clone(),
|
|
563
497
|
status: Some(reply.clone()),
|
|
564
498
|
}
|
|
565
499
|
};
|
|
566
500
|
|
|
567
|
-
|
|
501
|
+
worker.complete_workflow_activation(reply).await.unwrap();
|
|
568
502
|
|
|
569
503
|
// Restart assertions from the beginning if it was an eviction
|
|
570
504
|
if contains_eviction.is_some() {
|
|
@@ -580,7 +514,7 @@ pub(crate) async fn poll_and_reply_clears_outstanding_evicts<'a>(
|
|
|
580
514
|
WorkflowCachingPolicy::NonSticky => (),
|
|
581
515
|
WorkflowCachingPolicy::AfterEveryReply => {
|
|
582
516
|
if evictions < expected_evictions {
|
|
583
|
-
|
|
517
|
+
worker.request_workflow_eviction(&res.run_id);
|
|
584
518
|
evictions += 1;
|
|
585
519
|
}
|
|
586
520
|
}
|
|
@@ -591,7 +525,7 @@ pub(crate) async fn poll_and_reply_clears_outstanding_evicts<'a>(
|
|
|
591
525
|
}
|
|
592
526
|
|
|
593
527
|
assert_eq!(expected_fail_count, executed_failures.len());
|
|
594
|
-
assert_eq!(
|
|
528
|
+
assert_eq!(worker.outstanding_workflow_tasks(), 0);
|
|
595
529
|
}
|
|
596
530
|
|
|
597
531
|
pub(crate) fn gen_assert_and_reply(
|