@temporalio/core-bridge 1.4.4 → 1.5.1

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.
Files changed (123) hide show
  1. package/Cargo.lock +327 -419
  2. package/Cargo.toml +1 -1
  3. package/index.js +25 -2
  4. package/lib/errors.d.ts +22 -0
  5. package/lib/errors.js +65 -0
  6. package/lib/errors.js.map +1 -0
  7. package/lib/index.d.ts +440 -0
  8. package/lib/index.js +8 -0
  9. package/lib/index.js.map +1 -0
  10. package/package.json +11 -5
  11. package/releases/aarch64-apple-darwin/index.node +0 -0
  12. package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
  13. package/releases/x86_64-apple-darwin/index.node +0 -0
  14. package/releases/x86_64-pc-windows-msvc/index.node +0 -0
  15. package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
  16. package/sdk-core/.buildkite/docker/Dockerfile +1 -1
  17. package/sdk-core/.buildkite/docker/docker-compose.yaml +2 -2
  18. package/sdk-core/bridge-ffi/Cargo.toml +1 -1
  19. package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -25
  20. package/sdk-core/bridge-ffi/src/lib.rs +29 -108
  21. package/sdk-core/bridge-ffi/src/wrappers.rs +35 -25
  22. package/sdk-core/client/Cargo.toml +1 -1
  23. package/sdk-core/client/src/lib.rs +12 -20
  24. package/sdk-core/client/src/raw.rs +9 -8
  25. package/sdk-core/client/src/retry.rs +100 -23
  26. package/sdk-core/core/Cargo.toml +5 -5
  27. package/sdk-core/core/benches/workflow_replay.rs +13 -10
  28. package/sdk-core/core/src/abstractions.rs +22 -22
  29. package/sdk-core/core/src/core_tests/activity_tasks.rs +1 -1
  30. package/sdk-core/core/src/core_tests/local_activities.rs +228 -6
  31. package/sdk-core/core/src/core_tests/queries.rs +247 -89
  32. package/sdk-core/core/src/core_tests/workers.rs +2 -2
  33. package/sdk-core/core/src/core_tests/workflow_cancels.rs +1 -1
  34. package/sdk-core/core/src/core_tests/workflow_tasks.rs +46 -27
  35. package/sdk-core/core/src/lib.rs +139 -32
  36. package/sdk-core/core/src/replay/mod.rs +185 -41
  37. package/sdk-core/core/src/telemetry/log_export.rs +190 -0
  38. package/sdk-core/core/src/telemetry/metrics.rs +184 -139
  39. package/sdk-core/core/src/telemetry/mod.rs +296 -318
  40. package/sdk-core/core/src/telemetry/prometheus_server.rs +4 -3
  41. package/sdk-core/core/src/test_help/mod.rs +9 -7
  42. package/sdk-core/core/src/worker/activities/local_activities.rs +2 -1
  43. package/sdk-core/core/src/worker/activities.rs +40 -23
  44. package/sdk-core/core/src/worker/client/mocks.rs +1 -1
  45. package/sdk-core/core/src/worker/client.rs +30 -4
  46. package/sdk-core/core/src/worker/mod.rs +22 -18
  47. package/sdk-core/core/src/worker/workflow/driven_workflow.rs +10 -19
  48. package/sdk-core/core/src/worker/workflow/history_update.rs +99 -25
  49. package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +1 -5
  50. package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +1 -5
  51. package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +1 -5
  52. package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +1 -5
  53. package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +1 -5
  54. package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +2 -6
  55. package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +1 -5
  56. package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +18 -21
  57. package/sdk-core/core/src/worker/workflow/machines/mod.rs +12 -38
  58. package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +178 -0
  59. package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +1 -5
  60. package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +1 -5
  61. package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +1 -5
  62. package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +8 -2
  63. package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +1 -5
  64. package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +232 -216
  65. package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +1 -6
  66. package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +4 -4
  67. package/sdk-core/core/src/worker/workflow/managed_run.rs +13 -5
  68. package/sdk-core/core/src/worker/workflow/mod.rs +61 -9
  69. package/sdk-core/core/src/worker/workflow/wft_poller.rs +2 -2
  70. package/sdk-core/core/src/worker/workflow/workflow_stream.rs +56 -11
  71. package/sdk-core/core-api/Cargo.toml +4 -3
  72. package/sdk-core/core-api/src/lib.rs +1 -43
  73. package/sdk-core/core-api/src/telemetry.rs +147 -0
  74. package/sdk-core/core-api/src/worker.rs +13 -0
  75. package/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +1 -1
  76. package/sdk-core/histories/evict_while_la_running_no_interference-23_history.bin +0 -0
  77. package/sdk-core/histories/evict_while_la_running_no_interference-85_history.bin +0 -0
  78. package/sdk-core/protos/api_upstream/.github/CODEOWNERS +1 -1
  79. package/sdk-core/protos/api_upstream/buf.yaml +0 -3
  80. package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +3 -7
  81. package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +8 -0
  82. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +1 -2
  83. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +2 -0
  84. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +3 -0
  85. package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +13 -0
  86. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +19 -59
  87. package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +0 -19
  88. package/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +108 -29
  89. package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -2
  90. package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +1 -0
  91. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +47 -8
  92. package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +15 -1
  93. package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
  94. package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +8 -1
  95. package/sdk-core/sdk/src/interceptors.rs +36 -3
  96. package/sdk-core/sdk/src/lib.rs +7 -4
  97. package/sdk-core/sdk/src/workflow_context.rs +13 -2
  98. package/sdk-core/sdk-core-protos/src/history_builder.rs +47 -1
  99. package/sdk-core/sdk-core-protos/src/history_info.rs +22 -22
  100. package/sdk-core/sdk-core-protos/src/lib.rs +49 -27
  101. package/sdk-core/test-utils/Cargo.toml +1 -0
  102. package/sdk-core/test-utils/src/lib.rs +81 -29
  103. package/sdk-core/tests/integ_tests/metrics_tests.rs +37 -0
  104. package/sdk-core/tests/integ_tests/polling_tests.rs +0 -13
  105. package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +145 -4
  106. package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +53 -0
  107. package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +106 -20
  108. package/sdk-core/tests/integ_tests/workflow_tests.rs +18 -8
  109. package/sdk-core/tests/main.rs +6 -4
  110. package/src/conversions.rs +52 -47
  111. package/src/errors.rs +28 -86
  112. package/src/helpers.rs +3 -4
  113. package/src/lib.rs +2 -2
  114. package/src/runtime.rs +132 -61
  115. package/src/testing.rs +7 -4
  116. package/src/worker.rs +67 -50
  117. package/ts/errors.ts +55 -0
  118. package/{index.d.ts → ts/index.ts} +121 -15
  119. package/sdk-core/core/src/log_export.rs +0 -62
  120. package/sdk-core/core/src/worker/workflow/machines/mutable_side_effect_state_machine.rs +0 -127
  121. package/sdk-core/core/src/worker/workflow/machines/side_effect_state_machine.rs +0 -71
  122. package/sdk-core/protos/api_upstream/temporal/api/cluster/v1/message.proto +0 -83
  123. package/sdk-core/protos/api_upstream/temporal/api/enums/v1/cluster.proto +0 -40
@@ -3,9 +3,9 @@ use crate::{
3
3
  replay::{default_wes_attribs, TestHistoryBuilder, DEFAULT_WORKFLOW_TYPE},
4
4
  test_help::{
5
5
  hist_to_poll_resp, mock_sdk, mock_sdk_cfg, mock_worker, single_hist_mock_sg, MockPollCfg,
6
- ResponseType, TEST_Q,
6
+ ResponseType,
7
7
  },
8
- worker::client::mocks::mock_workflow_client,
8
+ worker::{client::mocks::mock_workflow_client, LEGACY_QUERY_ID},
9
9
  };
10
10
  use anyhow::anyhow;
11
11
  use futures::{future::join_all, FutureExt};
@@ -29,11 +29,13 @@ use temporal_sdk_core_protos::{
29
29
  ActivityTaskCompletion, AsJsonPayloadExt,
30
30
  },
31
31
  temporal::api::{
32
- common::v1::RetryPolicy, enums::v1::EventType, failure::v1::Failure,
32
+ common::v1::RetryPolicy, enums::v1::EventType, failure::v1::Failure, history::v1::History,
33
33
  query::v1::WorkflowQuery,
34
34
  },
35
35
  };
36
- use temporal_sdk_core_test_utils::{schedule_local_activity_cmd, WorkerTestHelpers};
36
+ use temporal_sdk_core_test_utils::{
37
+ schedule_local_activity_cmd, start_timer_cmd, WorkerTestHelpers,
38
+ };
37
39
  use tokio::sync::Barrier;
38
40
 
39
41
  async fn echo(_ctx: ActContext, e: String) -> anyhow::Result<String> {
@@ -398,6 +400,50 @@ async fn local_act_null_result() {
398
400
  worker.run_until_done().await.unwrap();
399
401
  }
400
402
 
403
+ #[tokio::test]
404
+ async fn local_act_command_immediately_follows_la_marker() {
405
+ // This repro only works both when cache is off, and there is at least one heartbeat wft
406
+ // before the marker & next command are recorded.
407
+ let mut t = TestHistoryBuilder::default();
408
+ t.add_by_type(EventType::WorkflowExecutionStarted);
409
+ t.add_full_wf_task();
410
+ t.add_full_wf_task();
411
+ t.add_local_activity_marker(1, "1", None, None, None);
412
+ t.add_get_event_id(EventType::TimerStarted, None);
413
+ t.add_full_wf_task();
414
+
415
+ let wf_id = "fakeid";
416
+ let mock = mock_workflow_client();
417
+ // Bug only repros when seeing history up to third wft
418
+ let mh = MockPollCfg::from_resp_batches(wf_id, t, [3], mock);
419
+ let mut worker = mock_sdk_cfg(mh, |w| w.max_cached_workflows = 0);
420
+
421
+ worker.register_wf(
422
+ DEFAULT_WORKFLOW_TYPE.to_owned(),
423
+ |ctx: WfContext| async move {
424
+ ctx.local_activity(LocalActivityOptions {
425
+ activity_type: "nullres".to_string(),
426
+ input: "hi".as_json_payload().expect("serializes fine"),
427
+ ..Default::default()
428
+ })
429
+ .await;
430
+ ctx.timer(Duration::from_secs(1)).await;
431
+ Ok(().into())
432
+ },
433
+ );
434
+ worker.register_activity("nullres", |_ctx: ActContext, _: String| async { Ok(()) });
435
+ worker
436
+ .submit_wf(
437
+ wf_id.to_owned(),
438
+ DEFAULT_WORKFLOW_TYPE.to_owned(),
439
+ vec![],
440
+ WorkflowOptions::default(),
441
+ )
442
+ .await
443
+ .unwrap();
444
+ worker.run_until_done().await.unwrap();
445
+ }
446
+
401
447
  #[tokio::test]
402
448
  async fn query_during_wft_heartbeat_doesnt_accidentally_fail_to_continue_heartbeat() {
403
449
  let wfid = "fake_wf_id";
@@ -415,7 +461,7 @@ async fn query_during_wft_heartbeat_doesnt_accidentally_fail_to_continue_heartbe
415
461
  t.add_workflow_execution_completed();
416
462
 
417
463
  let query_with_hist_task = {
418
- let mut pr = hist_to_poll_resp(&t, wfid, ResponseType::ToTaskNum(1), TEST_Q);
464
+ let mut pr = hist_to_poll_resp(&t, wfid, ResponseType::ToTaskNum(1));
419
465
  pr.queries = HashMap::new();
420
466
  pr.queries.insert(
421
467
  "the-query".to_string(),
@@ -441,7 +487,6 @@ async fn query_during_wft_heartbeat_doesnt_accidentally_fail_to_continue_heartbe
441
487
  .boxed(),
442
488
  3,
443
489
  ),
444
- TEST_Q,
445
490
  ),
446
491
  ];
447
492
  let mock = mock_workflow_client();
@@ -513,3 +558,180 @@ async fn query_during_wft_heartbeat_doesnt_accidentally_fail_to_continue_heartbe
513
558
 
514
559
  tokio::join!(wf_fut, act_fut);
515
560
  }
561
+
562
+ #[rstest::rstest]
563
+ #[case::impossible_query_in_task(true)]
564
+ #[case::real_history(false)]
565
+ #[tokio::test]
566
+ async fn la_resolve_during_legacy_query_does_not_combine(#[case] impossible_query_in_task: bool) {
567
+ // Ensures we do not send an activation with a legacy query and any other work, which should
568
+ // never happen, but there was an issue where an LA resolving could trigger that.
569
+ let wfid = "fake_wf_id";
570
+ let mut t = TestHistoryBuilder::default();
571
+ let wes_short_wft_timeout = default_wes_attribs();
572
+ t.add(
573
+ EventType::WorkflowExecutionStarted,
574
+ wes_short_wft_timeout.into(),
575
+ );
576
+ // Since we don't send queries with start workflow, need one workflow task of something else
577
+ // b/c we want to get an activation with a job and a nonlegacy query
578
+ t.add_full_wf_task();
579
+ let timer_started_event_id = t.add_get_event_id(EventType::TimerStarted, None);
580
+ t.add_timer_fired(timer_started_event_id, "1".to_string());
581
+
582
+ // nonlegacy query got here & LA started here
583
+ t.add_full_wf_task();
584
+ // legacy query got here, at the same time that the LA is resolved
585
+ t.add_local_activity_marker(1, "1", None, None, None);
586
+ t.add_workflow_execution_completed();
587
+
588
+ let barr = Arc::new(Barrier::new(2));
589
+ let barr_c = barr.clone();
590
+
591
+ let tasks = [
592
+ hist_to_poll_resp(&t, wfid.to_owned(), ResponseType::ToTaskNum(1)),
593
+ {
594
+ let mut pr = hist_to_poll_resp(&t, wfid.to_owned(), ResponseType::OneTask(2));
595
+ pr.queries = HashMap::new();
596
+ pr.queries.insert(
597
+ "q1".to_string(),
598
+ WorkflowQuery {
599
+ query_type: "query-type".to_string(),
600
+ query_args: Some(b"hi".into()),
601
+ header: None,
602
+ },
603
+ );
604
+ pr
605
+ },
606
+ {
607
+ let mut pr = hist_to_poll_resp(
608
+ &t,
609
+ wfid.to_owned(),
610
+ ResponseType::UntilResolved(
611
+ async move {
612
+ barr_c.wait().await;
613
+ // This sleep is the only not-incredibly-invasive way to ensure the LA
614
+ // resolves & updates machines before we process this task
615
+ tokio::time::sleep(Duration::from_secs(1)).await;
616
+ }
617
+ .boxed(),
618
+ 2,
619
+ ),
620
+ );
621
+ // Strip history, we need to look like we hit the cache
622
+ pr.history = Some(History { events: vec![] });
623
+ // In the nonsense server response case, we attach a legacy query, otherwise this
624
+ // response looks like a normal response to a forced WFT heartbeat.
625
+ if impossible_query_in_task {
626
+ pr.query = Some(WorkflowQuery {
627
+ query_type: "query-type".to_string(),
628
+ query_args: Some(b"hi".into()),
629
+ header: None,
630
+ });
631
+ }
632
+ pr
633
+ },
634
+ ];
635
+ let mut mock = mock_workflow_client();
636
+ if impossible_query_in_task {
637
+ mock.expect_respond_legacy_query()
638
+ .times(1)
639
+ .returning(move |_, _| Ok(Default::default()));
640
+ }
641
+ let mut mock = single_hist_mock_sg(wfid, t, tasks, mock, true);
642
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 1);
643
+ let core = mock_worker(mock);
644
+
645
+ let wf_fut = async {
646
+ let task = core.poll_workflow_activation().await.unwrap();
647
+ assert_matches!(
648
+ task.jobs.as_slice(),
649
+ &[WorkflowActivationJob {
650
+ variant: Some(workflow_activation_job::Variant::StartWorkflow(_)),
651
+ },]
652
+ );
653
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
654
+ task.run_id,
655
+ start_timer_cmd(1, Duration::from_secs(1)),
656
+ ))
657
+ .await
658
+ .unwrap();
659
+ let task = core.poll_workflow_activation().await.unwrap();
660
+ assert_matches!(
661
+ task.jobs.as_slice(),
662
+ &[
663
+ WorkflowActivationJob {
664
+ variant: Some(workflow_activation_job::Variant::FireTimer(_)),
665
+ },
666
+ WorkflowActivationJob {
667
+ variant: Some(workflow_activation_job::Variant::QueryWorkflow(_)),
668
+ }
669
+ ]
670
+ );
671
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
672
+ task.run_id,
673
+ vec![
674
+ schedule_local_activity_cmd(
675
+ 1,
676
+ "act-id",
677
+ ActivityCancellationType::TryCancel,
678
+ Duration::from_secs(60),
679
+ ),
680
+ QueryResult {
681
+ query_id: "q1".to_string(),
682
+ variant: Some(
683
+ QuerySuccess {
684
+ response: Some("whatev".into()),
685
+ }
686
+ .into(),
687
+ ),
688
+ }
689
+ .into(),
690
+ ],
691
+ ))
692
+ .await
693
+ .unwrap();
694
+ barr.wait().await;
695
+ let task = core.poll_workflow_activation().await.unwrap();
696
+ // The next task needs to be resolve, since the LA is completed immediately
697
+ assert_matches!(
698
+ task.jobs.as_slice(),
699
+ [WorkflowActivationJob {
700
+ variant: Some(workflow_activation_job::Variant::ResolveActivity(_)),
701
+ }]
702
+ );
703
+ // Complete workflow
704
+ core.complete_execution(&task.run_id).await;
705
+ if impossible_query_in_task {
706
+ // finish last query
707
+ let task = core.poll_workflow_activation().await.unwrap();
708
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
709
+ task.run_id,
710
+ vec![QueryResult {
711
+ query_id: LEGACY_QUERY_ID.to_string(),
712
+ variant: Some(
713
+ QuerySuccess {
714
+ response: Some("whatev".into()),
715
+ }
716
+ .into(),
717
+ ),
718
+ }
719
+ .into()],
720
+ ))
721
+ .await
722
+ .unwrap();
723
+ }
724
+ };
725
+ let act_fut = async {
726
+ let act_task = core.poll_activity_task().await.unwrap();
727
+ core.complete_activity_task(ActivityTaskCompletion {
728
+ task_token: act_task.task_token,
729
+ result: Some(ActivityExecutionResult::ok(vec![1].into())),
730
+ })
731
+ .await
732
+ .unwrap();
733
+ };
734
+
735
+ tokio::join!(wf_fut, act_fut);
736
+ core.shutdown().await;
737
+ }