@temporalio/core-bridge 1.10.2 → 1.11.0
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 +563 -676
- package/Cargo.toml +3 -3
- package/lib/index.d.ts +16 -5
- package/lib/index.js.map +1 -1
- package/lib/worker-tuner.d.ts +57 -0
- package/lib/worker-tuner.js +3 -0
- package/lib/worker-tuner.js.map +1 -0
- 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/heavy.yml +6 -11
- package/sdk-core/.github/workflows/per-pr.yml +23 -41
- package/sdk-core/Cargo.toml +5 -5
- package/sdk-core/README.md +2 -0
- package/sdk-core/client/Cargo.toml +4 -2
- package/sdk-core/client/src/lib.rs +60 -17
- package/sdk-core/client/src/metrics.rs +1 -1
- package/sdk-core/client/src/proxy.rs +17 -12
- package/sdk-core/client/src/raw.rs +218 -69
- package/sdk-core/client/src/retry.rs +19 -9
- package/sdk-core/core/Cargo.toml +12 -12
- package/sdk-core/core/src/abstractions.rs +3 -3
- package/sdk-core/core/src/core_tests/activity_tasks.rs +2 -1
- package/sdk-core/core/src/core_tests/determinism.rs +1 -1
- package/sdk-core/core/src/core_tests/local_activities.rs +73 -10
- package/sdk-core/core/src/core_tests/queries.rs +2 -1
- package/sdk-core/core/src/core_tests/updates.rs +162 -4
- package/sdk-core/core/src/core_tests/workers.rs +38 -2
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +158 -27
- package/sdk-core/core/src/internal_flags.rs +17 -7
- package/sdk-core/core/src/lib.rs +9 -3
- package/sdk-core/core/src/pollers/poll_buffer.rs +1 -10
- package/sdk-core/core/src/protosext/mod.rs +0 -1
- package/sdk-core/core/src/protosext/protocol_messages.rs +105 -16
- package/sdk-core/core/src/retry_logic.rs +22 -2
- package/sdk-core/core/src/telemetry/otel.rs +44 -12
- package/sdk-core/core/src/test_help/mod.rs +65 -12
- package/sdk-core/core/src/worker/activities/local_activities.rs +1 -4
- package/sdk-core/core/src/worker/activities.rs +3 -4
- package/sdk-core/core/src/worker/client/mocks.rs +7 -6
- package/sdk-core/core/src/worker/client.rs +11 -2
- package/sdk-core/core/src/worker/mod.rs +49 -24
- package/sdk-core/core/src/worker/tuner/resource_based.rs +48 -48
- package/sdk-core/core/src/worker/tuner.rs +124 -4
- package/sdk-core/core/src/worker/workflow/driven_workflow.rs +1 -1
- package/sdk-core/core/src/worker/workflow/history_update.rs +11 -2
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +18 -3
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +4 -4
- package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +1 -0
- package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +3 -1
- package/sdk-core/core/src/worker/workflow/machines/update_state_machine.rs +38 -28
- package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +4 -2
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +95 -71
- package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +1 -1
- package/sdk-core/core/src/worker/workflow/managed_run.rs +214 -14
- package/sdk-core/core/src/worker/workflow/mod.rs +49 -36
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +1 -2
- package/sdk-core/core-api/src/errors.rs +13 -7
- package/sdk-core/core-api/src/lib.rs +9 -1
- package/sdk-core/sdk/Cargo.toml +1 -1
- package/sdk-core/sdk/src/activity_context.rs +3 -4
- package/sdk-core/sdk/src/lib.rs +96 -49
- package/sdk-core/sdk/src/workflow_context/options.rs +8 -4
- package/sdk-core/sdk/src/workflow_context.rs +53 -49
- package/sdk-core/sdk/src/workflow_future.rs +10 -4
- package/sdk-core/sdk-core-protos/Cargo.toml +4 -3
- package/sdk-core/sdk-core-protos/build.rs +2 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/.github/workflows/build.yaml +18 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/LICENSE +21 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/Makefile +59 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/README.md +25 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/VERSION +1 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/buf.gen.yaml +14 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/buf.lock +8 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/buf.yaml +9 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/request_response.proto +520 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto +263 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/identity/v1/message.proto +173 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/namespace/v1/message.proto +164 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/operation/v1/message.proto +36 -0
- package/sdk-core/sdk-core-protos/protos/api_cloud_upstream/temporal/api/cloud/region/v1/message.proto +22 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/.github/workflows/trigger-api-go-update.yml +50 -8
- package/sdk-core/sdk-core-protos/protos/api_upstream/.gitmodules +3 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv2.json +132 -54
- package/sdk-core/sdk-core-protos/protos/api_upstream/openapi/openapiv3.yaml +177 -81
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/command/v1/message.proto +13 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +2 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +8 -3
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/history/v1/message.proto +10 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/nexus/v1/message.proto +3 -3
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +6 -6
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/enhanced_stack_trace.proto +96 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/user_metadata.proto +49 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/sdk/v1/workflow_metadata.proto +6 -7
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +55 -24
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflow/v1/message.proto +7 -0
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +21 -4
- package/sdk-core/sdk-core-protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +64 -45
- package/sdk-core/sdk-core-protos/src/history_builder.rs +8 -1
- package/sdk-core/sdk-core-protos/src/lib.rs +40 -10
- package/sdk-core/test-utils/src/canned_histories.rs +1 -1
- package/sdk-core/tests/fuzzy_workflow.rs +4 -2
- package/sdk-core/tests/heavy_tests.rs +3 -3
- package/sdk-core/tests/integ_tests/activity_functions.rs +2 -2
- package/sdk-core/tests/integ_tests/client_tests.rs +234 -6
- package/sdk-core/tests/integ_tests/update_tests.rs +180 -47
- package/sdk-core/tests/integ_tests/worker_tests.rs +32 -0
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +47 -3
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +10 -10
- package/sdk-core/tests/main.rs +1 -0
- package/src/conversions.rs +84 -11
- package/src/runtime.rs +5 -17
- package/src/worker.rs +27 -6
- package/ts/index.ts +24 -5
- package/ts/worker-tuner.ts +71 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
use crate::{
|
|
2
2
|
abstractions::dbg_panic,
|
|
3
|
+
internal_flags::CoreInternalFlags,
|
|
3
4
|
protosext::{protocol_messages::IncomingProtocolMessage, WorkflowActivationExt},
|
|
4
5
|
telemetry::metrics,
|
|
5
6
|
worker::{
|
|
@@ -422,20 +423,7 @@ impl ManagedRun {
|
|
|
422
423
|
);
|
|
423
424
|
Ok(None)
|
|
424
425
|
} else {
|
|
425
|
-
|
|
426
|
-
// Would be prettier with `drain_filter`
|
|
427
|
-
let mut query_responses = vec![];
|
|
428
|
-
commands = std::mem::take(&mut commands)
|
|
429
|
-
.into_iter()
|
|
430
|
-
.filter_map(|x| {
|
|
431
|
-
if let WFCommand::QueryResponse(qr) = x {
|
|
432
|
-
query_responses.push(qr);
|
|
433
|
-
None
|
|
434
|
-
} else {
|
|
435
|
-
Some(x)
|
|
436
|
-
}
|
|
437
|
-
})
|
|
438
|
-
.collect();
|
|
426
|
+
let (commands, query_responses) = self.preprocess_command_sequence(commands);
|
|
439
427
|
|
|
440
428
|
if activation_was_only_eviction && !commands.is_empty() {
|
|
441
429
|
dbg_panic!("Reply to an eviction included commands");
|
|
@@ -479,6 +467,38 @@ impl ManagedRun {
|
|
|
479
467
|
}
|
|
480
468
|
}
|
|
481
469
|
|
|
470
|
+
/// Core has received from lang a sequence containing all commands generated
|
|
471
|
+
/// by all workflow coroutines. Return a command sequence containing all
|
|
472
|
+
/// non-terminal (i.e. non-workflow-terminating) commands, followed by the
|
|
473
|
+
/// first terminal command if there are any. Also strip out and return query
|
|
474
|
+
/// results (these don't affect machines and are handled separately
|
|
475
|
+
/// downstream)
|
|
476
|
+
///
|
|
477
|
+
/// The reordering is done in order that all non-terminal commands generated
|
|
478
|
+
/// by workflow coroutines are given a chance for the server to honor them.
|
|
479
|
+
/// For example, in order to deliver an update result to a client as the
|
|
480
|
+
/// workflow completes.
|
|
481
|
+
///
|
|
482
|
+
/// Behavior here has changed backwards-incompatibly, so a flag is set if
|
|
483
|
+
/// the outcome differs from what the outcome would have been previously.
|
|
484
|
+
/// See also CoreInternalFlags::MoveTerminalCommands docstring and
|
|
485
|
+
/// https://github.com/temporalio/features/issues/481.
|
|
486
|
+
fn preprocess_command_sequence(
|
|
487
|
+
&mut self,
|
|
488
|
+
commands: Vec<WFCommand>,
|
|
489
|
+
) -> (Vec<WFCommand>, Vec<QueryResult>) {
|
|
490
|
+
if self.wfm.machines.replaying
|
|
491
|
+
&& !self
|
|
492
|
+
.wfm
|
|
493
|
+
.machines
|
|
494
|
+
.try_use_flag(CoreInternalFlags::MoveTerminalCommands, false)
|
|
495
|
+
{
|
|
496
|
+
preprocess_command_sequence_old_behavior(commands)
|
|
497
|
+
} else {
|
|
498
|
+
preprocess_command_sequence(commands)
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
482
502
|
/// Called after the higher-up machinery has fetched more pages of event history needed to apply
|
|
483
503
|
/// the next workflow task. The history update and paginator used to perform the fetch are
|
|
484
504
|
/// passed in, with the update being used to apply the task, and the paginator stored to be
|
|
@@ -1169,6 +1189,60 @@ impl ManagedRun {
|
|
|
1169
1189
|
}
|
|
1170
1190
|
}
|
|
1171
1191
|
|
|
1192
|
+
// Construct a new command sequence with query responses removed, and any
|
|
1193
|
+
// terminal responses removed, except for the first terminal response, which is
|
|
1194
|
+
// placed at the end. Return new command sequence and query commands. Note that
|
|
1195
|
+
// multiple coroutines may have generated a terminal command, leading to
|
|
1196
|
+
// multiple terminal commands in the input to this function.
|
|
1197
|
+
fn preprocess_command_sequence(commands: Vec<WFCommand>) -> (Vec<WFCommand>, Vec<QueryResult>) {
|
|
1198
|
+
let mut query_results = vec![];
|
|
1199
|
+
let mut terminals = vec![];
|
|
1200
|
+
|
|
1201
|
+
let mut commands: Vec<_> = commands
|
|
1202
|
+
.into_iter()
|
|
1203
|
+
.filter_map(|c| {
|
|
1204
|
+
if let WFCommand::QueryResponse(qr) = c {
|
|
1205
|
+
query_results.push(qr);
|
|
1206
|
+
None
|
|
1207
|
+
} else if c.is_terminal() {
|
|
1208
|
+
terminals.push(c);
|
|
1209
|
+
None
|
|
1210
|
+
} else {
|
|
1211
|
+
Some(c)
|
|
1212
|
+
}
|
|
1213
|
+
})
|
|
1214
|
+
.collect();
|
|
1215
|
+
if let Some(first_terminal) = terminals.into_iter().next() {
|
|
1216
|
+
commands.push(first_terminal);
|
|
1217
|
+
}
|
|
1218
|
+
(commands, query_results)
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
fn preprocess_command_sequence_old_behavior(
|
|
1222
|
+
commands: Vec<WFCommand>,
|
|
1223
|
+
) -> (Vec<WFCommand>, Vec<QueryResult>) {
|
|
1224
|
+
let mut query_results = vec![];
|
|
1225
|
+
let mut seen_terminal = false;
|
|
1226
|
+
|
|
1227
|
+
let commands: Vec<_> = commands
|
|
1228
|
+
.into_iter()
|
|
1229
|
+
.filter_map(|c| {
|
|
1230
|
+
if let WFCommand::QueryResponse(qr) = c {
|
|
1231
|
+
query_results.push(qr);
|
|
1232
|
+
None
|
|
1233
|
+
} else if seen_terminal {
|
|
1234
|
+
None
|
|
1235
|
+
} else {
|
|
1236
|
+
if c.is_terminal() {
|
|
1237
|
+
seen_terminal = true;
|
|
1238
|
+
}
|
|
1239
|
+
Some(c)
|
|
1240
|
+
}
|
|
1241
|
+
})
|
|
1242
|
+
.collect();
|
|
1243
|
+
(commands, query_results)
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1172
1246
|
/// Drains pending queries from the workflow task and appends them to the activation's jobs
|
|
1173
1247
|
fn put_queries_in_act(act: &mut WorkflowActivation, wft: &mut OutstandingTask) {
|
|
1174
1248
|
// Nothing to do if there are no pending queries
|
|
@@ -1397,3 +1471,129 @@ impl From<WFMachinesError> for RunUpdateErr {
|
|
|
1397
1471
|
}
|
|
1398
1472
|
}
|
|
1399
1473
|
}
|
|
1474
|
+
|
|
1475
|
+
#[cfg(test)]
|
|
1476
|
+
mod tests {
|
|
1477
|
+
use crate::worker::workflow::WFCommand;
|
|
1478
|
+
use std::mem::{discriminant, Discriminant};
|
|
1479
|
+
|
|
1480
|
+
use command_utils::*;
|
|
1481
|
+
|
|
1482
|
+
#[rstest::rstest]
|
|
1483
|
+
#[case::empty(
|
|
1484
|
+
vec![],
|
|
1485
|
+
vec![])]
|
|
1486
|
+
#[case::non_terminal_is_retained(
|
|
1487
|
+
vec![update_response()],
|
|
1488
|
+
vec![update_response()])]
|
|
1489
|
+
#[case::terminal_is_retained(
|
|
1490
|
+
vec![complete()],
|
|
1491
|
+
vec![complete()])]
|
|
1492
|
+
#[case::post_terminal_is_retained(
|
|
1493
|
+
vec![complete(), update_response()],
|
|
1494
|
+
vec![update_response(), complete()])]
|
|
1495
|
+
#[case::second_terminal_is_discarded(
|
|
1496
|
+
vec![cancel(), complete()],
|
|
1497
|
+
vec![cancel()])]
|
|
1498
|
+
#[case::move_terminals_to_end_and_retain_first(
|
|
1499
|
+
vec![update_response(), complete(), update_response(), cancel(), update_response()],
|
|
1500
|
+
vec![update_response(), update_response(), update_response(), complete()])]
|
|
1501
|
+
#[test]
|
|
1502
|
+
fn preprocess_command_sequence(
|
|
1503
|
+
#[case] commands_in: Vec<WFCommand>,
|
|
1504
|
+
#[case] expected_commands: Vec<WFCommand>,
|
|
1505
|
+
) {
|
|
1506
|
+
let (commands, _) = super::preprocess_command_sequence(commands_in);
|
|
1507
|
+
assert_eq!(command_types(&commands), command_types(&expected_commands));
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
#[rstest::rstest]
|
|
1511
|
+
#[case::query_responses_extracted(
|
|
1512
|
+
vec![query_response(), update_response(), query_response(), complete(), query_response()],
|
|
1513
|
+
3,
|
|
1514
|
+
)]
|
|
1515
|
+
#[test]
|
|
1516
|
+
fn preprocess_command_sequence_extracts_queries(
|
|
1517
|
+
#[case] commands_in: Vec<WFCommand>,
|
|
1518
|
+
#[case] expected_queries_out: usize,
|
|
1519
|
+
) {
|
|
1520
|
+
let (_, query_responses_out) = super::preprocess_command_sequence(commands_in);
|
|
1521
|
+
assert_eq!(query_responses_out.len(), expected_queries_out);
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
#[rstest::rstest]
|
|
1525
|
+
#[case::empty(
|
|
1526
|
+
vec![],
|
|
1527
|
+
vec![])]
|
|
1528
|
+
#[case::non_terminal_is_retained(
|
|
1529
|
+
vec![update_response()],
|
|
1530
|
+
vec![update_response()])]
|
|
1531
|
+
#[case::terminal_is_retained(
|
|
1532
|
+
vec![complete()],
|
|
1533
|
+
vec![complete()])]
|
|
1534
|
+
#[case::post_terminal_is_discarded(
|
|
1535
|
+
vec![complete(), update_response()],
|
|
1536
|
+
vec![complete()])]
|
|
1537
|
+
#[case::second_terminal_is_discarded(
|
|
1538
|
+
vec![cancel(), complete()],
|
|
1539
|
+
vec![cancel()])]
|
|
1540
|
+
#[case::truncate_at_first_complete(
|
|
1541
|
+
vec![update_response(), complete(), update_response(), cancel()],
|
|
1542
|
+
vec![update_response(), complete()])]
|
|
1543
|
+
#[test]
|
|
1544
|
+
fn preprocess_command_sequence_old_behavior(
|
|
1545
|
+
#[case] commands_in: Vec<WFCommand>,
|
|
1546
|
+
#[case] expected_out: Vec<WFCommand>,
|
|
1547
|
+
) {
|
|
1548
|
+
let (commands_out, _) = super::preprocess_command_sequence_old_behavior(commands_in);
|
|
1549
|
+
assert_eq!(command_types(&commands_out), command_types(&expected_out));
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
#[rstest::rstest]
|
|
1553
|
+
#[case::query_responses_extracted(
|
|
1554
|
+
vec![query_response(), update_response(), query_response(), complete(), query_response()],
|
|
1555
|
+
3,
|
|
1556
|
+
)]
|
|
1557
|
+
#[test]
|
|
1558
|
+
fn preprocess_command_sequence_old_behavior_extracts_queries(
|
|
1559
|
+
#[case] commands_in: Vec<WFCommand>,
|
|
1560
|
+
#[case] expected_queries_out: usize,
|
|
1561
|
+
) {
|
|
1562
|
+
let (_, query_responses_out) = super::preprocess_command_sequence_old_behavior(commands_in);
|
|
1563
|
+
assert_eq!(query_responses_out.len(), expected_queries_out);
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
mod command_utils {
|
|
1567
|
+
use temporal_sdk_core_protos::coresdk::workflow_commands::{
|
|
1568
|
+
CancelWorkflowExecution, CompleteWorkflowExecution, QueryResult, UpdateResponse,
|
|
1569
|
+
};
|
|
1570
|
+
|
|
1571
|
+
use super::*;
|
|
1572
|
+
|
|
1573
|
+
pub(crate) fn complete() -> WFCommand {
|
|
1574
|
+
WFCommand::CompleteWorkflow(CompleteWorkflowExecution { result: None })
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
pub(crate) fn cancel() -> WFCommand {
|
|
1578
|
+
WFCommand::CancelWorkflow(CancelWorkflowExecution {})
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
pub(crate) fn query_response() -> WFCommand {
|
|
1582
|
+
WFCommand::QueryResponse(QueryResult {
|
|
1583
|
+
query_id: "".into(),
|
|
1584
|
+
variant: None,
|
|
1585
|
+
})
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
pub(crate) fn update_response() -> WFCommand {
|
|
1589
|
+
WFCommand::UpdateResponse(UpdateResponse {
|
|
1590
|
+
protocol_instance_id: "".into(),
|
|
1591
|
+
response: None,
|
|
1592
|
+
})
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
pub(crate) fn command_types(commands: &[WFCommand]) -> Vec<Discriminant<WFCommand>> {
|
|
1596
|
+
commands.iter().map(discriminant).collect()
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
@@ -40,6 +40,7 @@ use crate::{
|
|
|
40
40
|
use anyhow::anyhow;
|
|
41
41
|
use futures::{stream::BoxStream, Stream, StreamExt};
|
|
42
42
|
use futures_util::{future::abortable, stream};
|
|
43
|
+
use itertools::Itertools;
|
|
43
44
|
use prost_types::TimestampError;
|
|
44
45
|
use std::{
|
|
45
46
|
cell::RefCell,
|
|
@@ -223,9 +224,11 @@ impl Workflows {
|
|
|
223
224
|
.expect("Activation processor channel not dropped");
|
|
224
225
|
}
|
|
225
226
|
}
|
|
226
|
-
Err(e) =>
|
|
227
|
-
.send(Err(e))
|
|
228
|
-
|
|
227
|
+
Err(e) => {
|
|
228
|
+
let _ = activation_tx.send(Err(e)).inspect_err(|e| {
|
|
229
|
+
error!(activation=?e.0, "Activation processor channel dropped");
|
|
230
|
+
});
|
|
231
|
+
}
|
|
229
232
|
}
|
|
230
233
|
}
|
|
231
234
|
});
|
|
@@ -267,33 +270,41 @@ impl Workflows {
|
|
|
267
270
|
break Ok(act);
|
|
268
271
|
}
|
|
269
272
|
ActivationOrAuto::Autocomplete { run_id } => {
|
|
270
|
-
self
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
273
|
+
if let Err(e) = self
|
|
274
|
+
.activation_completed(
|
|
275
|
+
WorkflowActivationCompletion {
|
|
276
|
+
run_id,
|
|
277
|
+
status: Some(
|
|
278
|
+
workflow_completion::Success::from_variants(vec![]).into(),
|
|
279
|
+
),
|
|
280
|
+
},
|
|
281
|
+
true,
|
|
282
|
+
// We need to say a type, but the type is irrelevant, so imagine some
|
|
283
|
+
// boxed function we'll never call.
|
|
284
|
+
Option::<Box<dyn Fn(PostActivateHookData) + Send>>::None,
|
|
285
|
+
)
|
|
286
|
+
.await
|
|
287
|
+
{
|
|
288
|
+
error!(error=?e, "Error while auto-completing workflow task");
|
|
289
|
+
}
|
|
283
290
|
}
|
|
284
291
|
ActivationOrAuto::AutoFail {
|
|
285
292
|
run_id,
|
|
286
293
|
machines_err,
|
|
287
294
|
} => {
|
|
288
|
-
self
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
295
|
+
if let Err(e) = self
|
|
296
|
+
.activation_completed(
|
|
297
|
+
WorkflowActivationCompletion {
|
|
298
|
+
run_id,
|
|
299
|
+
status: Some(machines_err.as_failure().into()),
|
|
300
|
+
},
|
|
301
|
+
true,
|
|
302
|
+
Option::<Box<dyn Fn(PostActivateHookData) + Send>>::None,
|
|
303
|
+
)
|
|
304
|
+
.await
|
|
305
|
+
{
|
|
306
|
+
error!(error=?e, "Error while auto-failing workflow task");
|
|
307
|
+
}
|
|
297
308
|
}
|
|
298
309
|
}
|
|
299
310
|
}
|
|
@@ -793,6 +804,18 @@ impl PreparedWFT {
|
|
|
793
804
|
let no_new_history = self.update.wft_started_id == 0;
|
|
794
805
|
no_new_history && self.legacy_query.is_some()
|
|
795
806
|
}
|
|
807
|
+
|
|
808
|
+
/// Useful for showing detailed info on incoming WFTs
|
|
809
|
+
#[allow(dead_code)]
|
|
810
|
+
fn print_details(&self) -> String {
|
|
811
|
+
format!(
|
|
812
|
+
"WFT events: [{}], messages: {:?}, legacy_query: {:?}, queries: {:?}",
|
|
813
|
+
self.update.get_events().iter().format(", "),
|
|
814
|
+
&self.messages,
|
|
815
|
+
&self.legacy_query,
|
|
816
|
+
&self.query_requests
|
|
817
|
+
)
|
|
818
|
+
}
|
|
796
819
|
}
|
|
797
820
|
|
|
798
821
|
#[derive(Debug)]
|
|
@@ -1020,7 +1043,7 @@ fn validate_completion(
|
|
|
1020
1043
|
match completion.status {
|
|
1021
1044
|
Some(workflow_activation_completion::Status::Successful(success)) => {
|
|
1022
1045
|
// Convert to wf commands
|
|
1023
|
-
let
|
|
1046
|
+
let commands = success
|
|
1024
1047
|
.commands
|
|
1025
1048
|
.into_iter()
|
|
1026
1049
|
.map(|c| c.try_into())
|
|
@@ -1047,16 +1070,6 @@ fn validate_completion(
|
|
|
1047
1070
|
});
|
|
1048
1071
|
}
|
|
1049
1072
|
|
|
1050
|
-
// Any non-query-response commands after a terminal command should be ignored
|
|
1051
|
-
if let Some(term_cmd_pos) = commands.iter().position(|c| c.is_terminal()) {
|
|
1052
|
-
// Query responses are just fine, so keep them.
|
|
1053
|
-
let queries = commands
|
|
1054
|
-
.split_off(term_cmd_pos + 1)
|
|
1055
|
-
.into_iter()
|
|
1056
|
-
.filter(|c| matches!(c, WFCommand::QueryResponse(_)));
|
|
1057
|
-
commands.extend(queries);
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
1073
|
Ok(ValidatedCompletion::Success {
|
|
1061
1074
|
run_id: completion.run_id,
|
|
1062
1075
|
commands,
|
|
@@ -87,7 +87,7 @@ impl WFStream {
|
|
|
87
87
|
buffered_polls_need_cache_slot: Default::default(),
|
|
88
88
|
runs: RunCache::new(
|
|
89
89
|
basics.worker_config.clone(),
|
|
90
|
-
basics.server_capabilities
|
|
90
|
+
basics.server_capabilities,
|
|
91
91
|
local_activity_request_sink,
|
|
92
92
|
basics.metrics.clone(),
|
|
93
93
|
),
|
|
@@ -165,7 +165,6 @@ impl WFStream {
|
|
|
165
165
|
None
|
|
166
166
|
}
|
|
167
167
|
WFStreamInput::PollerError(e) => {
|
|
168
|
-
warn!("WFT poller errored, shutting down");
|
|
169
168
|
return Err(PollWfError::TonicError(e));
|
|
170
169
|
}
|
|
171
170
|
};
|
|
@@ -2,23 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
use temporal_sdk_core_protos::coresdk::activity_result::ActivityExecutionResult;
|
|
4
4
|
|
|
5
|
+
/// Errors thrown by [crate::Worker::validate]
|
|
6
|
+
#[derive(thiserror::Error, Debug)]
|
|
7
|
+
pub enum WorkerValidationError {
|
|
8
|
+
/// The namespace provided to the worker does not exist on the server.
|
|
9
|
+
#[error("Namespace {namespace} was not found or otherwise could not be described: {source:?}")]
|
|
10
|
+
NamespaceDescribeError {
|
|
11
|
+
source: tonic::Status,
|
|
12
|
+
namespace: String,
|
|
13
|
+
},
|
|
14
|
+
}
|
|
15
|
+
|
|
5
16
|
/// Errors thrown by [crate::Worker::poll_workflow_activation]
|
|
6
17
|
#[derive(thiserror::Error, Debug)]
|
|
7
18
|
pub enum PollWfError {
|
|
8
19
|
/// [crate::Worker::shutdown] was called, and there are no more replay tasks to be handled. Lang
|
|
9
|
-
/// must call [crate::Worker::complete_workflow_activation] for any remaining tasks, and then
|
|
10
|
-
/// exit.
|
|
20
|
+
/// must call [crate::Worker::complete_workflow_activation] for any remaining tasks, and then
|
|
21
|
+
/// may exit.
|
|
11
22
|
#[error("Core is shut down and there are no more workflow replay tasks")]
|
|
12
23
|
ShutDown,
|
|
13
24
|
/// Unhandled error when calling the temporal server. Core will attempt to retry any non-fatal
|
|
14
25
|
/// errors, so lang should consider this fatal.
|
|
15
26
|
#[error("Unhandled grpc error when workflow polling: {0:?}")]
|
|
16
27
|
TonicError(#[from] tonic::Status),
|
|
17
|
-
/// Unhandled error when completing a workflow during a poll -- this can happen when there is no
|
|
18
|
-
/// work for lang to perform, but the server sent us a workflow task (EX: An activity completed
|
|
19
|
-
/// even though we already cancelled it)
|
|
20
|
-
#[error("Unhandled error when auto-completing workflow task: {0:?}")]
|
|
21
|
-
AutocompleteError(#[from] CompleteWfError),
|
|
22
28
|
}
|
|
23
29
|
|
|
24
30
|
/// Errors thrown by [crate::Worker::poll_activity_task]
|
|
@@ -3,7 +3,10 @@ pub mod telemetry;
|
|
|
3
3
|
pub mod worker;
|
|
4
4
|
|
|
5
5
|
use crate::{
|
|
6
|
-
errors::{
|
|
6
|
+
errors::{
|
|
7
|
+
CompleteActivityError, CompleteWfError, PollActivityError, PollWfError,
|
|
8
|
+
WorkerValidationError,
|
|
9
|
+
},
|
|
7
10
|
worker::WorkerConfig,
|
|
8
11
|
};
|
|
9
12
|
use temporal_sdk_core_protos::coresdk::{
|
|
@@ -16,6 +19,11 @@ use temporal_sdk_core_protos::coresdk::{
|
|
|
16
19
|
/// and is bound to a specific task queue.
|
|
17
20
|
#[async_trait::async_trait]
|
|
18
21
|
pub trait Worker: Send + Sync {
|
|
22
|
+
/// Validate that the worker can properly connect to server, plus any other validation that
|
|
23
|
+
/// needs to be done asynchronously. Lang SDKs should call this function once before calling
|
|
24
|
+
/// any others.
|
|
25
|
+
async fn validate(&self) -> Result<(), WorkerValidationError>;
|
|
26
|
+
|
|
19
27
|
/// Ask the worker for some work, returning a [WorkflowActivation]. It is then the language
|
|
20
28
|
/// SDK's responsibility to call the appropriate workflow code with the provided inputs. Blocks
|
|
21
29
|
/// indefinitely until such work is available or [Worker::shutdown] is called.
|
package/sdk-core/sdk/Cargo.toml
CHANGED
|
@@ -18,7 +18,7 @@ crossbeam-channel = "0.5"
|
|
|
18
18
|
derive_more = { workspace = true }
|
|
19
19
|
futures = "0.3"
|
|
20
20
|
parking_lot = { version = "0.12", features = ["send_guard"] }
|
|
21
|
-
prost-types = { version = "0.
|
|
21
|
+
prost-types = { version = "0.6", package = "prost-wkt-types" }
|
|
22
22
|
serde = "1.0"
|
|
23
23
|
tokio = { version = "1.26", features = ["rt", "rt-multi-thread", "parking_lot", "time", "fs"] }
|
|
24
24
|
tokio-util = { version = "0.7" }
|
|
@@ -188,10 +188,9 @@ fn calculate_deadline(
|
|
|
188
188
|
) => {
|
|
189
189
|
let scheduled: SystemTime = maybe_convert_timestamp(scheduled)?;
|
|
190
190
|
let started: SystemTime = maybe_convert_timestamp(started)?;
|
|
191
|
-
let start_to_close_timeout: StdDuration =
|
|
192
|
-
start_to_close_timeout.clone().try_into().ok()?;
|
|
191
|
+
let start_to_close_timeout: StdDuration = (*start_to_close_timeout).try_into().ok()?;
|
|
193
192
|
let schedule_to_close_timeout: StdDuration =
|
|
194
|
-
schedule_to_close_timeout
|
|
193
|
+
(*schedule_to_close_timeout).try_into().ok()?;
|
|
195
194
|
|
|
196
195
|
let start_to_close_deadline: SystemTime =
|
|
197
196
|
started.checked_add(start_to_close_timeout)?;
|
|
@@ -215,7 +214,7 @@ fn calculate_deadline(
|
|
|
215
214
|
/// Helper function lifted from prost_types::Timestamp implementation to prevent double cloning in
|
|
216
215
|
/// error construction
|
|
217
216
|
fn maybe_convert_timestamp(timestamp: &Timestamp) -> Option<SystemTime> {
|
|
218
|
-
let mut timestamp = timestamp
|
|
217
|
+
let mut timestamp = *timestamp;
|
|
219
218
|
timestamp.normalize();
|
|
220
219
|
|
|
221
220
|
let system_time = if timestamp.seconds >= 0 {
|