@temporalio/core-bridge 1.11.1 → 1.11.3
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 +86 -88
- package/lib/errors.d.ts +2 -0
- package/lib/errors.js +5 -1
- package/lib/errors.js.map +1 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.js.map +1 -1
- 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/.github/workflows/per-pr.yml +7 -1
- package/sdk-core/Cargo.toml +1 -1
- package/sdk-core/client/Cargo.toml +3 -3
- package/sdk-core/client/src/lib.rs +1 -1
- package/sdk-core/client/src/metrics.rs +2 -2
- package/sdk-core/client/src/raw.rs +39 -13
- package/sdk-core/client/src/retry.rs +108 -62
- package/sdk-core/client/src/workflow_handle/mod.rs +1 -2
- package/sdk-core/core/Cargo.toml +4 -5
- package/sdk-core/core/src/abstractions.rs +2 -3
- package/sdk-core/core/src/core_tests/activity_tasks.rs +1 -1
- package/sdk-core/core/src/core_tests/local_activities.rs +2 -2
- package/sdk-core/core/src/core_tests/queries.rs +8 -4
- package/sdk-core/core/src/core_tests/updates.rs +2 -2
- package/sdk-core/core/src/core_tests/workflow_cancels.rs +3 -3
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +55 -54
- package/sdk-core/core/src/ephemeral_server/mod.rs +5 -3
- package/sdk-core/core/src/protosext/mod.rs +3 -0
- package/sdk-core/core/src/telemetry/mod.rs +0 -8
- package/sdk-core/core/src/telemetry/otel.rs +7 -3
- package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +11 -0
- package/sdk-core/core/src/worker/activities.rs +1 -1
- package/sdk-core/core/src/worker/mod.rs +6 -6
- package/sdk-core/core/src/worker/slot_provider.rs +4 -3
- package/sdk-core/core/src/worker/tuner/resource_based.rs +1 -1
- package/sdk-core/core/src/worker/workflow/driven_workflow.rs +28 -2
- package/sdk-core/core/src/worker/workflow/history_update.rs +2 -2
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +8 -5
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +1 -1
- package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +1 -1
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +7 -7
- package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +10 -15
- package/sdk-core/core/src/worker/workflow/machines/mod.rs +1 -1
- package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +3 -2
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +1 -1
- package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +4 -4
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +30 -20
- package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +2 -2
- package/sdk-core/core/src/worker/workflow/managed_run.rs +20 -4
- package/sdk-core/core/src/worker/workflow/mod.rs +33 -29
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +2 -2
- package/sdk-core/core-api/src/telemetry.rs +1 -0
- package/sdk-core/docker/docker-compose-telem.yaml +4 -4
- package/sdk-core/etc/otel-collector-config.yaml +12 -9
- package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +2 -2
- package/sdk-core/sdk/src/lib.rs +30 -3
- package/sdk-core/sdk/src/workflow_context.rs +15 -2
- package/sdk-core/sdk/src/workflow_future.rs +28 -8
- package/sdk-core/sdk-core-protos/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +31 -12
- package/sdk-core/sdk-core-protos/src/lib.rs +104 -63
- package/sdk-core/test-utils/src/lib.rs +4 -3
- package/sdk-core/tests/integ_tests/client_tests.rs +36 -7
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +1 -1
- package/sdk-core/tests/integ_tests/metrics_tests.rs +50 -4
- package/sdk-core/tests/integ_tests/queries_tests.rs +95 -62
- package/sdk-core/tests/integ_tests/update_tests.rs +16 -9
- package/sdk-core/tests/integ_tests/visibility_tests.rs +1 -1
- package/sdk-core/tests/integ_tests/worker_tests.rs +82 -1
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +46 -8
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +81 -2
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +139 -4
- package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +43 -28
- package/sdk-core/tests/integ_tests/workflow_tests.rs +2 -1
- package/sdk-core/tests/main.rs +28 -19
- package/sdk-core/tests/runner.rs +7 -2
- package/ts/errors.ts +9 -2
- package/ts/index.ts +3 -0
|
@@ -90,13 +90,13 @@ fsm! {
|
|
|
90
90
|
|
|
91
91
|
#[derive(Debug, derive_more::Display)]
|
|
92
92
|
pub(super) enum ActivityMachineCommand {
|
|
93
|
-
#[display(
|
|
93
|
+
#[display("Complete")]
|
|
94
94
|
Complete(Option<Payloads>),
|
|
95
|
-
#[display(
|
|
95
|
+
#[display("Fail")]
|
|
96
96
|
Fail(Failure),
|
|
97
|
-
#[display(
|
|
97
|
+
#[display("Cancel")]
|
|
98
98
|
Cancel(Option<ActivityTaskCanceledEventAttributes>),
|
|
99
|
-
#[display(
|
|
99
|
+
#[display("RequestCancellation")]
|
|
100
100
|
RequestCancellation(Command),
|
|
101
101
|
}
|
|
102
102
|
|
|
@@ -166,6 +166,7 @@ impl ActivityMachine {
|
|
|
166
166
|
failure: Some(new_cancel_failure(&self.shared_state, attrs)),
|
|
167
167
|
})),
|
|
168
168
|
}),
|
|
169
|
+
is_local: false,
|
|
169
170
|
}
|
|
170
171
|
}
|
|
171
172
|
}
|
|
@@ -265,6 +266,7 @@ impl WFMachinesAdapter for ActivityMachine {
|
|
|
265
266
|
result: convert_payloads(event_info, result)?,
|
|
266
267
|
})),
|
|
267
268
|
}),
|
|
269
|
+
is_local: false,
|
|
268
270
|
}
|
|
269
271
|
.into()]
|
|
270
272
|
}
|
|
@@ -276,6 +278,7 @@ impl WFMachinesAdapter for ActivityMachine {
|
|
|
276
278
|
failure: Some(failure),
|
|
277
279
|
})),
|
|
278
280
|
}),
|
|
281
|
+
is_local: false,
|
|
279
282
|
}
|
|
280
283
|
.into()]
|
|
281
284
|
}
|
|
@@ -838,7 +841,7 @@ mod test {
|
|
|
838
841
|
assert_matches!(
|
|
839
842
|
a.jobs.as_slice(),
|
|
840
843
|
[WorkflowActivationJob {
|
|
841
|
-
variant: Some(workflow_activation_job::Variant::
|
|
844
|
+
variant: Some(workflow_activation_job::Variant::InitializeWorkflow(_)),
|
|
842
845
|
}]
|
|
843
846
|
)
|
|
844
847
|
});
|
|
@@ -51,7 +51,7 @@ pub(super) struct SharedState {
|
|
|
51
51
|
pub(super) enum CancelExternalCommand {
|
|
52
52
|
/// The target workflow has been notified of the cancel
|
|
53
53
|
Requested,
|
|
54
|
-
#[display(
|
|
54
|
+
#[display("Failed")]
|
|
55
55
|
Failed(CancelExternalWorkflowExecutionFailedCause),
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -133,7 +133,7 @@ mod tests {
|
|
|
133
133
|
assert_matches!(
|
|
134
134
|
a.jobs.as_slice(),
|
|
135
135
|
[WorkflowActivationJob {
|
|
136
|
-
variant: Some(workflow_activation_job::Variant::
|
|
136
|
+
variant: Some(workflow_activation_job::Variant::InitializeWorkflow(_)),
|
|
137
137
|
}]
|
|
138
138
|
)
|
|
139
139
|
});
|
|
@@ -105,19 +105,19 @@ pub(super) struct ChildWorkflowExecutionStartedEvent {
|
|
|
105
105
|
|
|
106
106
|
#[derive(Debug, derive_more::Display)]
|
|
107
107
|
pub(super) enum ChildWorkflowCommand {
|
|
108
|
-
#[display(
|
|
108
|
+
#[display("Start")]
|
|
109
109
|
Start(WorkflowExecution),
|
|
110
|
-
#[display(
|
|
110
|
+
#[display("Complete")]
|
|
111
111
|
Complete(Option<Payloads>),
|
|
112
|
-
#[display(
|
|
112
|
+
#[display("Fail")]
|
|
113
113
|
Fail(Failure),
|
|
114
|
-
#[display(
|
|
114
|
+
#[display("Cancel")]
|
|
115
115
|
Cancel,
|
|
116
|
-
#[display(
|
|
116
|
+
#[display("StartFail")]
|
|
117
117
|
StartFail(StartChildWorkflowExecutionFailedCause),
|
|
118
|
-
#[display(
|
|
118
|
+
#[display("StartCancel")]
|
|
119
119
|
StartCancel(Failure),
|
|
120
|
-
#[display(
|
|
120
|
+
#[display("CancelAfterStarted")]
|
|
121
121
|
IssueCancelAfterStarted { reason: String },
|
|
122
122
|
}
|
|
123
123
|
|
|
@@ -8,7 +8,7 @@ use crate::{
|
|
|
8
8
|
worker::{
|
|
9
9
|
workflow::{
|
|
10
10
|
machines::{activity_state_machine::activity_fail_info, HistEventData},
|
|
11
|
-
InternalFlagsRef,
|
|
11
|
+
InternalFlagsRef,
|
|
12
12
|
},
|
|
13
13
|
LocalActivityExecutionResult,
|
|
14
14
|
},
|
|
@@ -342,17 +342,17 @@ impl SharedState {
|
|
|
342
342
|
#[derive(Debug, derive_more::Display)]
|
|
343
343
|
pub(super) enum LocalActivityCommand {
|
|
344
344
|
RequestActivityExecution(ValidScheduleLA),
|
|
345
|
-
#[display(
|
|
345
|
+
#[display("Resolved")]
|
|
346
346
|
Resolved(ResolveDat),
|
|
347
347
|
/// The fake marker is used to avoid special casing marker recorded event handling.
|
|
348
348
|
/// If we didn't have the fake marker, there would be no "outgoing command" to match
|
|
349
349
|
/// against the event. This way there is, but the command never will be issued to
|
|
350
350
|
/// server because it is understood to be meaningless.
|
|
351
|
-
#[display(
|
|
351
|
+
#[display("FakeMarker")]
|
|
352
352
|
FakeMarker,
|
|
353
353
|
/// Indicate we want to cancel an LA that is currently executing, or look up if we have
|
|
354
354
|
/// processed a marker with resolution data since the machine was constructed.
|
|
355
|
-
#[display(
|
|
355
|
+
#[display("Cancel")]
|
|
356
356
|
RequestCancel,
|
|
357
357
|
}
|
|
358
358
|
|
|
@@ -631,9 +631,6 @@ impl Cancellable for LocalActivityMachine {
|
|
|
631
631
|
}
|
|
632
632
|
}
|
|
633
633
|
|
|
634
|
-
#[derive(Default, Clone)]
|
|
635
|
-
pub(super) struct Abandoned {}
|
|
636
|
-
|
|
637
634
|
impl WFMachinesAdapter for LocalActivityMachine {
|
|
638
635
|
fn adapt_response(
|
|
639
636
|
&self,
|
|
@@ -737,14 +734,12 @@ impl WFMachinesAdapter for LocalActivityMachine {
|
|
|
737
734
|
};
|
|
738
735
|
|
|
739
736
|
let mut responses = vec![
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
is_la_resolution: true,
|
|
747
|
-
}),
|
|
737
|
+
ResolveActivity {
|
|
738
|
+
seq: self.shared_state.attrs.seq,
|
|
739
|
+
result: Some(resolution),
|
|
740
|
+
is_local: true,
|
|
741
|
+
}
|
|
742
|
+
.into(),
|
|
748
743
|
MachineResponse::UpdateWFTime(complete_time),
|
|
749
744
|
];
|
|
750
745
|
|
|
@@ -236,7 +236,7 @@ trait WFMachinesAdapter: StateMachine {
|
|
|
236
236
|
/// Wraps a history event with extra relevant data that a machine might care about while the event
|
|
237
237
|
/// is being applied to it.
|
|
238
238
|
#[derive(Debug, derive_more::Display)]
|
|
239
|
-
#[display(
|
|
239
|
+
#[display("{event}")]
|
|
240
240
|
struct HistEventData {
|
|
241
241
|
event: HistoryEvent,
|
|
242
242
|
/// Is the current workflow task under replay or not during application of this event?
|
|
@@ -551,10 +551,11 @@ mod tests {
|
|
|
551
551
|
|
|
552
552
|
let mut aai = ActivationAssertionsInterceptor::default();
|
|
553
553
|
aai.then(move |act| {
|
|
554
|
-
// replaying cases should immediately get a resolve change activation when marker is
|
|
554
|
+
// replaying cases should immediately get a resolve change activation when marker is
|
|
555
|
+
// present
|
|
555
556
|
if replaying && marker_type != MarkerType::NoMarker {
|
|
556
557
|
assert_matches!(
|
|
557
|
-
&act.jobs[
|
|
558
|
+
&act.jobs[1],
|
|
558
559
|
WorkflowActivationJob {
|
|
559
560
|
variant: Some(workflow_activation_job::Variant::NotifyHasPatch(
|
|
560
561
|
NotifyHasPatch {
|
|
@@ -59,13 +59,13 @@ fsm! {
|
|
|
59
59
|
|
|
60
60
|
#[derive(Debug, derive_more::Display)]
|
|
61
61
|
pub(super) enum UpdateMachineCommand {
|
|
62
|
-
#[display(
|
|
62
|
+
#[display("Accept")]
|
|
63
63
|
Accept(update::v1::Request),
|
|
64
|
-
#[display(
|
|
64
|
+
#[display("Reject")]
|
|
65
65
|
Reject(update::v1::Request, Failure),
|
|
66
|
-
#[display(
|
|
66
|
+
#[display("Complete")]
|
|
67
67
|
Complete(Payload),
|
|
68
|
-
#[display(
|
|
68
|
+
#[display("Fail")]
|
|
69
69
|
Fail(Failure),
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -163,7 +163,7 @@ pub(crate) struct WorkflowMachines {
|
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
#[derive(Debug, derive_more::Display)]
|
|
166
|
-
#[display(
|
|
166
|
+
#[display("Cmd&Machine({command})")]
|
|
167
167
|
struct CommandAndMachine {
|
|
168
168
|
command: MachineAssociatedCommand,
|
|
169
169
|
machine: MachineKey,
|
|
@@ -172,7 +172,7 @@ struct CommandAndMachine {
|
|
|
172
172
|
#[derive(Debug, derive_more::Display)]
|
|
173
173
|
enum MachineAssociatedCommand {
|
|
174
174
|
Real(Box<ProtoCommand>),
|
|
175
|
-
#[display(
|
|
175
|
+
#[display("FakeLocalActivityMarker({_0})")]
|
|
176
176
|
FakeLocalActivityMarker(u32),
|
|
177
177
|
}
|
|
178
178
|
|
|
@@ -186,7 +186,7 @@ struct ChangeInfo {
|
|
|
186
186
|
#[must_use]
|
|
187
187
|
#[allow(clippy::large_enum_variant)]
|
|
188
188
|
pub(super) enum MachineResponse {
|
|
189
|
-
#[display(
|
|
189
|
+
#[display("PushWFJob({_0})")]
|
|
190
190
|
PushWFJob(OutgoingJob),
|
|
191
191
|
|
|
192
192
|
/// Pushes a new command into the list that will be sent to server once we respond with the
|
|
@@ -198,31 +198,31 @@ pub(super) enum MachineResponse {
|
|
|
198
198
|
/// The machine requests the creation of another *different* machine. This acts as if lang
|
|
199
199
|
/// had replied to the activation with a command, but we use a special set of IDs to avoid
|
|
200
200
|
/// collisions.
|
|
201
|
-
#[display(
|
|
201
|
+
#[display("NewCoreOriginatedCommand({_0:?})")]
|
|
202
202
|
NewCoreOriginatedCommand(ProtoCmdAttrs),
|
|
203
|
-
#[display(
|
|
203
|
+
#[display("IssueFakeLocalActivityMarker({_0})")]
|
|
204
204
|
IssueFakeLocalActivityMarker(u32),
|
|
205
|
-
#[display(
|
|
205
|
+
#[display("TriggerWFTaskStarted")]
|
|
206
206
|
TriggerWFTaskStarted {
|
|
207
207
|
task_started_event_id: i64,
|
|
208
208
|
time: SystemTime,
|
|
209
209
|
},
|
|
210
|
-
#[display(
|
|
210
|
+
#[display("UpdateRunIdOnWorkflowReset({run_id})")]
|
|
211
211
|
UpdateRunIdOnWorkflowReset { run_id: String },
|
|
212
212
|
|
|
213
213
|
/// Queue a local activity to be processed by the worker
|
|
214
|
-
#[display(
|
|
214
|
+
#[display("QueueLocalActivity")]
|
|
215
215
|
QueueLocalActivity(ValidScheduleLA),
|
|
216
216
|
/// Request cancellation of an executing local activity
|
|
217
|
-
#[display(
|
|
217
|
+
#[display("RequestCancelLocalActivity({_0})")]
|
|
218
218
|
RequestCancelLocalActivity(u32),
|
|
219
219
|
/// Indicates we are abandoning the indicated LA, so we can remove it from "outstanding" LAs
|
|
220
220
|
/// and we will not try to WFT heartbeat because of it.
|
|
221
|
-
#[display(
|
|
221
|
+
#[display("AbandonLocalActivity({_0:?})")]
|
|
222
222
|
AbandonLocalActivity(u32),
|
|
223
223
|
|
|
224
224
|
/// Set the workflow time to the provided time
|
|
225
|
-
#[display(
|
|
225
|
+
#[display("UpdateWFTime({_0:?})")]
|
|
226
226
|
UpdateWFTime(Option<SystemTime>),
|
|
227
227
|
}
|
|
228
228
|
|
|
@@ -449,7 +449,7 @@ impl WorkflowMachines {
|
|
|
449
449
|
self.drive_me
|
|
450
450
|
.peek_pending_jobs()
|
|
451
451
|
.iter()
|
|
452
|
-
.any(|v| v.
|
|
452
|
+
.any(|v| v.variant.is_local_activity_resolution())
|
|
453
453
|
}
|
|
454
454
|
|
|
455
455
|
pub(crate) fn get_metadata_for_wft_complete(&mut self) -> WorkflowTaskCompletedMetadata {
|
|
@@ -701,7 +701,16 @@ impl WorkflowMachines {
|
|
|
701
701
|
}
|
|
702
702
|
let mut delayed_actions = vec![];
|
|
703
703
|
// Scan through to the next WFT, searching for any patch / la markers, so that we can
|
|
704
|
-
// pre-resolve them.
|
|
704
|
+
// pre-resolve them. This lookahead is necessary because we need these things to be already
|
|
705
|
+
// resolved in the same activations they would have been resolved in during initial
|
|
706
|
+
// execution. For example: If a workflow asks to run an LA and then waits on it, we will
|
|
707
|
+
// write the completion marker at the end of that WFT (as a command). So, upon replay,
|
|
708
|
+
// we need to lookahead and see that that LA is in fact resolved, so that we don't decide
|
|
709
|
+
// to execute it anew when lang says it wants to run it.
|
|
710
|
+
//
|
|
711
|
+
// Alternatively, lookahead can seemingly be avoided if we were to consider the commands
|
|
712
|
+
// that follow a WFT to be _part of_ that wft rather than the next one. That change might
|
|
713
|
+
// make sense to do, and maybe simplifies things slightly, but is a substantial alteration.
|
|
705
714
|
for e in self
|
|
706
715
|
.last_history_from_server
|
|
707
716
|
.peek_next_wft_sequence(last_handled_wft_started_id)
|
|
@@ -1152,6 +1161,9 @@ impl WorkflowMachines {
|
|
|
1152
1161
|
);
|
|
1153
1162
|
}
|
|
1154
1163
|
ProtoCmdAttrs::UpsertWorkflowSearchAttributesCommandAttributes(attrs) => {
|
|
1164
|
+
// We explicitly do not update the workflows current SAs here since
|
|
1165
|
+
// core-generated upserts aren't meant to be modified or used within
|
|
1166
|
+
// workflows by users (but rather, just for them to search with).
|
|
1155
1167
|
self.add_cmd_to_wf_task(
|
|
1156
1168
|
upsert_search_attrs_internal(attrs),
|
|
1157
1169
|
CommandIdKind::NeverResolves,
|
|
@@ -1262,6 +1274,8 @@ impl WorkflowMachines {
|
|
|
1262
1274
|
self.add_cmd_to_wf_task(new_timer(attrs), CommandID::Timer(seq).into());
|
|
1263
1275
|
}
|
|
1264
1276
|
WFCommand::UpsertSearchAttributes(attrs) => {
|
|
1277
|
+
self.drive_me
|
|
1278
|
+
.search_attributes_update(attrs.search_attributes.clone());
|
|
1265
1279
|
self.add_cmd_to_wf_task(
|
|
1266
1280
|
upsert_search_attrs(
|
|
1267
1281
|
attrs,
|
|
@@ -1538,17 +1552,13 @@ impl WorkflowMachines {
|
|
|
1538
1552
|
.map(Into::into)
|
|
1539
1553
|
.unwrap_or_default();
|
|
1540
1554
|
}
|
|
1541
|
-
if attrs.search_attributes.is_empty() {
|
|
1542
|
-
attrs.search_attributes = started_info
|
|
1543
|
-
.search_attrs
|
|
1544
|
-
.clone()
|
|
1545
|
-
.map(Into::into)
|
|
1546
|
-
.unwrap_or_default();
|
|
1547
|
-
}
|
|
1548
1555
|
if attrs.retry_policy.is_none() {
|
|
1549
1556
|
attrs.retry_policy.clone_from(&started_info.retry_policy);
|
|
1550
1557
|
}
|
|
1551
1558
|
}
|
|
1559
|
+
if attrs.search_attributes.is_empty() {
|
|
1560
|
+
attrs.search_attributes = self.drive_me.get_current_search_attributes();
|
|
1561
|
+
}
|
|
1552
1562
|
attrs
|
|
1553
1563
|
}
|
|
1554
1564
|
|
|
@@ -44,12 +44,12 @@ impl WorkflowTaskMachine {
|
|
|
44
44
|
#[derive(Debug, derive_more::Display)]
|
|
45
45
|
pub(super) enum WFTaskMachineCommand {
|
|
46
46
|
/// Issued to (possibly) trigger the event loop
|
|
47
|
-
#[display(
|
|
47
|
+
#[display("WFTaskStartedTrigger")]
|
|
48
48
|
WFTaskStartedTrigger {
|
|
49
49
|
task_started_event_id: i64,
|
|
50
50
|
time: SystemTime,
|
|
51
51
|
},
|
|
52
|
-
#[display(
|
|
52
|
+
#[display("RunIdOnWorkflowResetUpdate({run_id})")]
|
|
53
53
|
RunIdOnWorkflowResetUpdate { run_id: String },
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -52,9 +52,9 @@ pub(super) type RunUpdateAct = Option<ActivationOrAuto>;
|
|
|
52
52
|
|
|
53
53
|
/// Manages access to a specific workflow run. Everything inside is entirely synchronous and should
|
|
54
54
|
/// remain that way.
|
|
55
|
-
#[derive(derive_more::
|
|
55
|
+
#[derive(derive_more::Debug)]
|
|
56
56
|
#[debug(
|
|
57
|
-
|
|
57
|
+
"ManagedRun {{ wft: {:?}, activation: {:?}, task_buffer: {:?} \
|
|
58
58
|
trying_to_evict: {} }}",
|
|
59
59
|
wft,
|
|
60
60
|
activation,
|
|
@@ -562,6 +562,7 @@ impl ManagedRun {
|
|
|
562
562
|
reason,
|
|
563
563
|
EvictionReason::Unspecified | EvictionReason::PaginationOrHistoryFetch
|
|
564
564
|
);
|
|
565
|
+
|
|
565
566
|
let (should_report, rur) = if is_no_report_query_fail {
|
|
566
567
|
(false, None)
|
|
567
568
|
} else {
|
|
@@ -580,6 +581,7 @@ impl ManagedRun {
|
|
|
580
581
|
let rur = evict_req_outcome.into_run_update_resp();
|
|
581
582
|
(should_report, rur)
|
|
582
583
|
};
|
|
584
|
+
|
|
583
585
|
let outcome = if self.pending_work_is_legacy_query() {
|
|
584
586
|
if is_no_report_query_fail {
|
|
585
587
|
ActivationCompleteOutcome::WFTFailedDontReport
|
|
@@ -617,6 +619,7 @@ impl ManagedRun {
|
|
|
617
619
|
} else {
|
|
618
620
|
ActivationCompleteOutcome::WFTFailedDontReport
|
|
619
621
|
};
|
|
622
|
+
|
|
620
623
|
self.metrics
|
|
621
624
|
.with_new_attrs([metrics::failure_reason(cause.into())])
|
|
622
625
|
.wf_task_failed();
|
|
@@ -870,6 +873,19 @@ impl ManagedRun {
|
|
|
870
873
|
|
|
871
874
|
if !self.activation_is_eviction() && self.trying_to_evict.is_none() {
|
|
872
875
|
debug!(run_id=%info.run_id, reason=%info.message, "Eviction requested");
|
|
876
|
+
// If we've requested an eviction because of failure related reasons then we want to
|
|
877
|
+
// delete any pending queries, since handling them no longer makes sense. Evictions
|
|
878
|
+
// because the cache is full should get a chance to finish processing properly.
|
|
879
|
+
if !matches!(info.reason, EvictionReason::CacheFull)
|
|
880
|
+
// If the wft was just a legacy query, still reply, otherwise we might try to
|
|
881
|
+
// reply to the task as if it were a task rather than a query.
|
|
882
|
+
&& !self.pending_work_is_legacy_query()
|
|
883
|
+
{
|
|
884
|
+
if let Some(wft) = self.wft.as_mut() {
|
|
885
|
+
wft.pending_queries.clear();
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
|
|
873
889
|
self.trying_to_evict = Some(info);
|
|
874
890
|
EvictionRequestResult::EvictionRequested(attempts, self.check_more_activations())
|
|
875
891
|
} else {
|
|
@@ -1456,8 +1472,8 @@ enum ActOrFulfill {
|
|
|
1456
1472
|
FulfillableComplete(Option<FulfillableActivationComplete>),
|
|
1457
1473
|
}
|
|
1458
1474
|
|
|
1459
|
-
#[derive(derive_more::
|
|
1460
|
-
#[debug(
|
|
1475
|
+
#[derive(derive_more::Debug)]
|
|
1476
|
+
#[debug("RunUpdateErr({source:?})")]
|
|
1461
1477
|
struct RunUpdateErr {
|
|
1462
1478
|
source: WFMachinesError,
|
|
1463
1479
|
complete_resp_chan: Option<oneshot::Sender<ActivationCompleteResult>>,
|
|
@@ -44,12 +44,10 @@ use itertools::Itertools;
|
|
|
44
44
|
use prost_types::TimestampError;
|
|
45
45
|
use std::{
|
|
46
46
|
cell::RefCell,
|
|
47
|
-
cmp::Ordering,
|
|
48
47
|
collections::VecDeque,
|
|
49
48
|
fmt::Debug,
|
|
50
49
|
future::Future,
|
|
51
50
|
mem,
|
|
52
|
-
mem::discriminant,
|
|
53
51
|
ops::DerefMut,
|
|
54
52
|
rc::Rc,
|
|
55
53
|
result,
|
|
@@ -722,10 +720,7 @@ impl Workflows {
|
|
|
722
720
|
/// Returned when a cache miss happens and we need to fetch history from the beginning to
|
|
723
721
|
/// replay a run
|
|
724
722
|
#[derive(Debug, derive_more::Display)]
|
|
725
|
-
#[display(
|
|
726
|
-
fmt = "CacheMissFetchReq(run_id: {})",
|
|
727
|
-
"original_wft.work.execution.run_id"
|
|
728
|
-
)]
|
|
723
|
+
#[display("CacheMissFetchReq(run_id: {})", "original_wft.work.execution.run_id")]
|
|
729
724
|
#[must_use]
|
|
730
725
|
struct CacheMissFetchReq {
|
|
731
726
|
original_wft: PermittedWFT,
|
|
@@ -751,11 +746,11 @@ enum ActivationOrAuto {
|
|
|
751
746
|
/// This type should only be filled with an empty activation which is ready to have queries
|
|
752
747
|
/// inserted into the joblist
|
|
753
748
|
ReadyForQueries(WorkflowActivation),
|
|
754
|
-
#[display(
|
|
749
|
+
#[display("Autocomplete(run_id={run_id})")]
|
|
755
750
|
Autocomplete {
|
|
756
751
|
run_id: String,
|
|
757
752
|
},
|
|
758
|
-
#[display(
|
|
753
|
+
#[display("AutoFail(run_id={run_id})")]
|
|
759
754
|
AutoFail {
|
|
760
755
|
run_id: String,
|
|
761
756
|
machines_err: WFMachinesError,
|
|
@@ -764,8 +759,8 @@ enum ActivationOrAuto {
|
|
|
764
759
|
|
|
765
760
|
/// A WFT which is considered to be using a slot for metrics purposes and being or about to be
|
|
766
761
|
/// applied to workflow state.
|
|
767
|
-
#[derive(derive_more::
|
|
768
|
-
#[debug(
|
|
762
|
+
#[derive(derive_more::Debug)]
|
|
763
|
+
#[debug("PermittedWft({work:?})")]
|
|
769
764
|
pub(crate) struct PermittedWFT {
|
|
770
765
|
work: PreparedWFT,
|
|
771
766
|
permit: UsedMeteredSemPermit<WorkflowSlotKind>,
|
|
@@ -1247,19 +1242,13 @@ struct WorkflowStartedInfo {
|
|
|
1247
1242
|
|
|
1248
1243
|
/// Wraps outgoing activation job protos with some internal details core might care about
|
|
1249
1244
|
#[derive(Debug, derive_more::Display)]
|
|
1250
|
-
#[display(
|
|
1245
|
+
#[display("{variant}")]
|
|
1251
1246
|
struct OutgoingJob {
|
|
1252
1247
|
variant: workflow_activation_job::Variant,
|
|
1253
|
-
/// Since LA resolutions are not distinguished from non-LA resolutions as far as lang is
|
|
1254
|
-
/// concerned, but core cares about that sometimes, attach that info here.
|
|
1255
|
-
is_la_resolution: bool,
|
|
1256
1248
|
}
|
|
1257
1249
|
impl<WA: Into<workflow_activation_job::Variant>> From<WA> for OutgoingJob {
|
|
1258
1250
|
fn from(wa: WA) -> Self {
|
|
1259
|
-
Self {
|
|
1260
|
-
variant: wa.into(),
|
|
1261
|
-
is_la_resolution: false,
|
|
1262
|
-
}
|
|
1251
|
+
Self { variant: wa.into() }
|
|
1263
1252
|
}
|
|
1264
1253
|
}
|
|
1265
1254
|
impl From<OutgoingJob> for WorkflowActivationJob {
|
|
@@ -1333,8 +1322,17 @@ impl LocalActivityRequestSink for LAReqSink {
|
|
|
1333
1322
|
/// Sorts jobs in an activation to be in the order lang expects, and confirms any invariants
|
|
1334
1323
|
/// activations must uphold.
|
|
1335
1324
|
///
|
|
1336
|
-
/// ## Ordering
|
|
1337
|
-
///
|
|
1325
|
+
/// ## Job Ordering
|
|
1326
|
+
/// 1. init workflow
|
|
1327
|
+
/// 2. patches
|
|
1328
|
+
/// 3. random-seed-updates
|
|
1329
|
+
/// 4. signals/updates
|
|
1330
|
+
/// 5. all others
|
|
1331
|
+
/// 6. local activity resolutions
|
|
1332
|
+
/// 7. queries
|
|
1333
|
+
/// 8. evictions
|
|
1334
|
+
///
|
|
1335
|
+
/// See the [WorkflowActivation] docstring for more detail
|
|
1338
1336
|
///
|
|
1339
1337
|
/// ## Invariants:
|
|
1340
1338
|
/// * Queries always go in their own activation
|
|
@@ -1361,26 +1359,26 @@ fn prepare_to_ship_activation(wfa: &mut WorkflowActivation) {
|
|
|
1361
1359
|
// Unwrapping is fine here since we'll never issue empty variants
|
|
1362
1360
|
let j1v = j1.variant.as_ref().unwrap();
|
|
1363
1361
|
let j2v = j2.variant.as_ref().unwrap();
|
|
1364
|
-
if discriminant(j1v) == discriminant(j2v) {
|
|
1365
|
-
return Ordering::Equal;
|
|
1366
|
-
}
|
|
1367
1362
|
fn variant_ordinal(v: &workflow_activation_job::Variant) -> u8 {
|
|
1368
1363
|
match v {
|
|
1364
|
+
workflow_activation_job::Variant::InitializeWorkflow(_) => 0,
|
|
1369
1365
|
workflow_activation_job::Variant::NotifyHasPatch(_) => 1,
|
|
1370
|
-
workflow_activation_job::Variant::
|
|
1371
|
-
workflow_activation_job::Variant::
|
|
1366
|
+
workflow_activation_job::Variant::UpdateRandomSeed(_) => 2,
|
|
1367
|
+
workflow_activation_job::Variant::SignalWorkflow(_) => 3,
|
|
1368
|
+
workflow_activation_job::Variant::DoUpdate(_) => 3,
|
|
1369
|
+
workflow_activation_job::Variant::ResolveActivity(ra) if ra.is_local => 5,
|
|
1372
1370
|
// In principle we should never actually need to sort these with the others, since
|
|
1373
1371
|
// queries always get their own activation, but, maintaining the semantic is
|
|
1374
1372
|
// reasonable.
|
|
1375
|
-
workflow_activation_job::Variant::QueryWorkflow(_) =>
|
|
1373
|
+
workflow_activation_job::Variant::QueryWorkflow(_) => 6,
|
|
1376
1374
|
// Also shouldn't ever end up anywhere but the end by construction, but no harm in
|
|
1377
1375
|
// double-checking.
|
|
1378
|
-
workflow_activation_job::Variant::RemoveFromCache(_) =>
|
|
1379
|
-
_ =>
|
|
1376
|
+
workflow_activation_job::Variant::RemoveFromCache(_) => 7,
|
|
1377
|
+
_ => 4,
|
|
1380
1378
|
}
|
|
1381
1379
|
}
|
|
1382
1380
|
variant_ordinal(j1v).cmp(&variant_ordinal(j2v))
|
|
1383
|
-
})
|
|
1381
|
+
});
|
|
1384
1382
|
}
|
|
1385
1383
|
|
|
1386
1384
|
#[cfg(test)]
|
|
@@ -1421,6 +1419,11 @@ mod tests {
|
|
|
1421
1419
|
Default::default(),
|
|
1422
1420
|
)),
|
|
1423
1421
|
},
|
|
1422
|
+
WorkflowActivationJob {
|
|
1423
|
+
variant: Some(workflow_activation_job::Variant::UpdateRandomSeed(
|
|
1424
|
+
Default::default(),
|
|
1425
|
+
)),
|
|
1426
|
+
},
|
|
1424
1427
|
WorkflowActivationJob {
|
|
1425
1428
|
variant: Some(workflow_activation_job::Variant::SignalWorkflow(
|
|
1426
1429
|
SignalWorkflow {
|
|
@@ -1442,6 +1445,7 @@ mod tests {
|
|
|
1442
1445
|
variants.as_slice(),
|
|
1443
1446
|
&[
|
|
1444
1447
|
workflow_activation_job::Variant::NotifyHasPatch(_),
|
|
1448
|
+
workflow_activation_job::Variant::UpdateRandomSeed(_),
|
|
1445
1449
|
workflow_activation_job::Variant::SignalWorkflow(ref s1),
|
|
1446
1450
|
workflow_activation_job::Variant::DoUpdate(_),
|
|
1447
1451
|
workflow_activation_job::Variant::SignalWorkflow(ref s2),
|
|
@@ -571,8 +571,8 @@ enum WFStreamInput {
|
|
|
571
571
|
}
|
|
572
572
|
|
|
573
573
|
/// A non-poller-received input to the [WFStream]
|
|
574
|
-
#[derive(derive_more::
|
|
575
|
-
#[debug(
|
|
574
|
+
#[derive(derive_more::Debug)]
|
|
575
|
+
#[debug("LocalInput {{ {input:?} }}")]
|
|
576
576
|
pub(super) struct LocalInput {
|
|
577
577
|
pub(super) input: LocalInputs,
|
|
578
578
|
pub(super) span: Span,
|
|
@@ -54,6 +54,7 @@ pub struct OtelCollectorOptions {
|
|
|
54
54
|
/// export to this same collector.
|
|
55
55
|
pub url: Url,
|
|
56
56
|
/// Optional set of HTTP headers to send to the Collector, e.g for authentication.
|
|
57
|
+
#[builder(default = "HashMap::new()")]
|
|
57
58
|
pub headers: HashMap<String, String>,
|
|
58
59
|
/// Optionally specify how frequently metrics should be exported. Defaults to 1 second.
|
|
59
60
|
#[builder(default = "Duration::from_secs(1)")]
|
|
@@ -10,9 +10,9 @@ services:
|
|
|
10
10
|
|
|
11
11
|
otel-collector:
|
|
12
12
|
image: otel/opentelemetry-collector:latest
|
|
13
|
-
command: ['--config=/etc/otel-collector-config.yaml']
|
|
13
|
+
command: [ '--config=/etc/otel-collector-config.yaml' ]
|
|
14
14
|
volumes:
|
|
15
|
-
-
|
|
15
|
+
- ../etc/otel-collector-config.yaml:/etc/otel-collector-config.yaml
|
|
16
16
|
ports:
|
|
17
17
|
# - "1888:1888" # pprof extension
|
|
18
18
|
# It's useful to be able to manually inspect metrics during dev
|
|
@@ -20,7 +20,7 @@ services:
|
|
|
20
20
|
- '8889:8889' # Prometheus exporter metrics
|
|
21
21
|
# - "13133:13133" # health_check extension
|
|
22
22
|
- '4317:4317' # OTLP gRPC receiver
|
|
23
|
-
# - "
|
|
23
|
+
# - "55679:55679" # zpages extension
|
|
24
24
|
depends_on:
|
|
25
25
|
- jaeger
|
|
26
26
|
|
|
@@ -28,6 +28,6 @@ services:
|
|
|
28
28
|
container_name: prometheus
|
|
29
29
|
image: prom/prometheus:latest
|
|
30
30
|
volumes:
|
|
31
|
-
-
|
|
31
|
+
- ../etc/prometheus.yaml:/etc/prometheus/prometheus.yml
|
|
32
32
|
ports:
|
|
33
33
|
- '9090:9090'
|
|
@@ -2,16 +2,19 @@ receivers:
|
|
|
2
2
|
otlp:
|
|
3
3
|
protocols:
|
|
4
4
|
grpc:
|
|
5
|
+
endpoint: 0.0.0.0:4317
|
|
6
|
+
http:
|
|
7
|
+
endpoint: 0.0.0.0:4318
|
|
5
8
|
|
|
6
9
|
exporters:
|
|
7
10
|
prometheus:
|
|
8
11
|
endpoint: '0.0.0.0:8889'
|
|
9
12
|
namespace: temporal_sdk
|
|
13
|
+
|
|
10
14
|
logging:
|
|
11
15
|
|
|
12
|
-
jaeger:
|
|
16
|
+
otlp/jaeger:
|
|
13
17
|
endpoint: jaeger:14250
|
|
14
|
-
insecure: true
|
|
15
18
|
|
|
16
19
|
processors:
|
|
17
20
|
batch:
|
|
@@ -24,13 +27,13 @@ extensions:
|
|
|
24
27
|
endpoint: :55679
|
|
25
28
|
|
|
26
29
|
service:
|
|
27
|
-
extensions: [pprof, zpages, health_check]
|
|
30
|
+
extensions: [ pprof, zpages, health_check ]
|
|
28
31
|
pipelines:
|
|
29
32
|
traces:
|
|
30
|
-
receivers: [otlp]
|
|
31
|
-
processors: [batch]
|
|
32
|
-
exporters: [logging, jaeger]
|
|
33
|
+
receivers: [ otlp ]
|
|
34
|
+
processors: [ batch ]
|
|
35
|
+
exporters: [ logging, otlp/jaeger ]
|
|
33
36
|
metrics:
|
|
34
|
-
receivers: [otlp]
|
|
35
|
-
processors: [batch]
|
|
36
|
-
exporters: [logging, prometheus]
|
|
37
|
+
receivers: [ otlp ]
|
|
38
|
+
processors: [ batch ]
|
|
39
|
+
exporters: [ logging, prometheus ]
|