temporalio 0.0.1 → 0.1.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.
- checksums.yaml +4 -4
- data/README.md +180 -7
- data/bridge/Cargo.lock +208 -76
- data/bridge/Cargo.toml +5 -2
- data/bridge/sdk-core/Cargo.toml +1 -1
- data/bridge/sdk-core/README.md +20 -10
- data/bridge/sdk-core/client/Cargo.toml +1 -1
- data/bridge/sdk-core/client/src/lib.rs +227 -59
- data/bridge/sdk-core/client/src/metrics.rs +17 -8
- data/bridge/sdk-core/client/src/raw.rs +13 -12
- data/bridge/sdk-core/client/src/retry.rs +132 -43
- data/bridge/sdk-core/core/Cargo.toml +28 -15
- data/bridge/sdk-core/core/benches/workflow_replay.rs +13 -10
- data/bridge/sdk-core/core/src/abstractions.rs +225 -36
- data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +217 -79
- data/bridge/sdk-core/core/src/core_tests/determinism.rs +165 -2
- data/bridge/sdk-core/core/src/core_tests/local_activities.rs +565 -34
- data/bridge/sdk-core/core/src/core_tests/queries.rs +247 -90
- data/bridge/sdk-core/core/src/core_tests/workers.rs +3 -5
- data/bridge/sdk-core/core/src/core_tests/workflow_cancels.rs +1 -1
- data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +430 -67
- data/bridge/sdk-core/core/src/ephemeral_server/mod.rs +106 -12
- data/bridge/sdk-core/core/src/internal_flags.rs +136 -0
- data/bridge/sdk-core/core/src/lib.rs +148 -34
- data/bridge/sdk-core/core/src/protosext/mod.rs +1 -1
- data/bridge/sdk-core/core/src/replay/mod.rs +185 -41
- data/bridge/sdk-core/core/src/telemetry/log_export.rs +190 -0
- data/bridge/sdk-core/core/src/telemetry/metrics.rs +219 -140
- data/bridge/sdk-core/core/src/telemetry/mod.rs +326 -315
- data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +20 -14
- data/bridge/sdk-core/core/src/test_help/mod.rs +85 -21
- data/bridge/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +112 -156
- data/bridge/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
- data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +364 -128
- data/bridge/sdk-core/core/src/worker/activities.rs +263 -170
- data/bridge/sdk-core/core/src/worker/client/mocks.rs +23 -3
- data/bridge/sdk-core/core/src/worker/client.rs +48 -6
- data/bridge/sdk-core/core/src/worker/mod.rs +186 -75
- data/bridge/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
- data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +13 -24
- data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +879 -226
- data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +101 -48
- data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +8 -12
- data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +6 -9
- data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +90 -32
- data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +6 -9
- data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +7 -10
- data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +6 -9
- data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +160 -83
- data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +36 -54
- data/bridge/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +179 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +104 -157
- data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +8 -12
- data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +9 -13
- data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +10 -4
- data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +14 -11
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +6 -17
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +395 -299
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +12 -20
- data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +33 -18
- data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +1032 -374
- data/bridge/sdk-core/core/src/worker/workflow/mod.rs +525 -392
- data/bridge/sdk-core/core/src/worker/workflow/run_cache.rs +40 -57
- data/bridge/sdk-core/core/src/worker/workflow/wft_extraction.rs +125 -0
- data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +3 -6
- data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +117 -0
- data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
- data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +456 -681
- data/bridge/sdk-core/core-api/Cargo.toml +6 -4
- data/bridge/sdk-core/core-api/src/errors.rs +1 -34
- data/bridge/sdk-core/core-api/src/lib.rs +7 -45
- data/bridge/sdk-core/core-api/src/telemetry.rs +141 -0
- data/bridge/sdk-core/core-api/src/worker.rs +27 -1
- data/bridge/sdk-core/etc/deps.svg +115 -140
- data/bridge/sdk-core/etc/regen-depgraph.sh +5 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +18 -15
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +1 -1
- data/bridge/sdk-core/fsm/rustfsm_trait/src/lib.rs +8 -3
- data/bridge/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
- data/bridge/sdk-core/histories/evict_while_la_running_no_interference-23_history.bin +0 -0
- data/bridge/sdk-core/histories/evict_while_la_running_no_interference-85_history.bin +0 -0
- data/bridge/sdk-core/protos/api_upstream/buf.yaml +0 -3
- data/bridge/sdk-core/protos/api_upstream/build/go.mod +7 -0
- data/bridge/sdk-core/protos/api_upstream/build/go.sum +5 -0
- data/bridge/sdk-core/protos/api_upstream/{temporal/api/enums/v1/cluster.proto → build/tools.go} +7 -18
- data/bridge/sdk-core/protos/api_upstream/go.mod +6 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +12 -9
- data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +15 -26
- data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +13 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +4 -9
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +3 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +10 -8
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +28 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +24 -19
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +62 -26
- data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +4 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +24 -61
- data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +2 -21
- data/bridge/sdk-core/protos/api_upstream/temporal/api/protocol/v1/message.proto +57 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +110 -31
- data/bridge/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +4 -4
- data/bridge/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +71 -6
- data/bridge/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +3 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +111 -36
- data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +19 -5
- data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +9 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +9 -1
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +6 -0
- data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +2 -2
- data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +2 -2
- data/bridge/sdk-core/sdk/Cargo.toml +4 -3
- data/bridge/sdk-core/sdk/src/interceptors.rs +36 -3
- data/bridge/sdk-core/sdk/src/lib.rs +94 -25
- data/bridge/sdk-core/sdk/src/workflow_context.rs +13 -2
- data/bridge/sdk-core/sdk/src/workflow_future.rs +10 -13
- data/bridge/sdk-core/sdk-core-protos/Cargo.toml +5 -2
- data/bridge/sdk-core/sdk-core-protos/build.rs +36 -2
- data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +164 -104
- data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +27 -23
- data/bridge/sdk-core/sdk-core-protos/src/lib.rs +252 -74
- data/bridge/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
- data/bridge/sdk-core/test-utils/Cargo.toml +4 -1
- data/bridge/sdk-core/test-utils/src/canned_histories.rs +106 -296
- data/bridge/sdk-core/test-utils/src/histfetch.rs +1 -1
- data/bridge/sdk-core/test-utils/src/lib.rs +161 -50
- data/bridge/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
- data/bridge/sdk-core/test-utils/src/workflows.rs +29 -0
- data/bridge/sdk-core/tests/fuzzy_workflow.rs +130 -0
- data/bridge/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +125 -51
- data/bridge/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
- data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +10 -5
- data/bridge/sdk-core/tests/integ_tests/metrics_tests.rs +239 -0
- data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +4 -60
- data/bridge/sdk-core/tests/integ_tests/queries_tests.rs +5 -128
- data/bridge/sdk-core/tests/integ_tests/visibility_tests.rs +83 -25
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/activities.rs +93 -69
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +6 -13
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +6 -2
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -10
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +151 -116
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +54 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/patches.rs +7 -28
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +115 -24
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/signals.rs +18 -14
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +6 -20
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -21
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +6 -4
- data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +27 -18
- data/bridge/sdk-core/tests/main.rs +8 -16
- data/bridge/sdk-core/tests/runner.rs +75 -36
- data/bridge/sdk-core/tests/wf_input_replay.rs +32 -0
- data/bridge/src/connection.rs +117 -82
- data/bridge/src/lib.rs +356 -42
- data/bridge/src/runtime.rs +10 -3
- data/bridge/src/test_server.rs +153 -0
- data/bridge/src/worker.rs +133 -9
- data/lib/gen/temporal/api/batch/v1/message_pb.rb +8 -6
- data/lib/gen/temporal/api/command/v1/message_pb.rb +10 -16
- data/lib/gen/temporal/api/common/v1/message_pb.rb +5 -1
- data/lib/gen/temporal/api/enums/v1/batch_operation_pb.rb +2 -1
- data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +3 -3
- data/lib/gen/temporal/api/enums/v1/common_pb.rb +2 -1
- data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +5 -4
- data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +9 -1
- data/lib/gen/temporal/api/enums/v1/namespace_pb.rb +1 -1
- data/lib/gen/temporal/api/enums/v1/query_pb.rb +1 -1
- data/lib/gen/temporal/api/enums/v1/reset_pb.rb +1 -1
- data/lib/gen/temporal/api/enums/v1/schedule_pb.rb +1 -1
- data/lib/gen/temporal/api/enums/v1/task_queue_pb.rb +1 -1
- data/lib/gen/temporal/api/enums/v1/update_pb.rb +7 -10
- data/lib/gen/temporal/api/enums/v1/workflow_pb.rb +1 -1
- data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +1 -1
- data/lib/gen/temporal/api/failure/v1/message_pb.rb +1 -1
- data/lib/gen/temporal/api/filter/v1/message_pb.rb +1 -1
- data/lib/gen/temporal/api/history/v1/message_pb.rb +34 -25
- data/lib/gen/temporal/api/namespace/v1/message_pb.rb +2 -1
- data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +14 -51
- data/lib/gen/temporal/api/operatorservice/v1/service_pb.rb +1 -1
- data/lib/gen/temporal/api/protocol/v1/message_pb.rb +30 -0
- data/lib/gen/temporal/api/query/v1/message_pb.rb +1 -1
- data/lib/gen/temporal/api/replication/v1/message_pb.rb +1 -1
- data/lib/gen/temporal/api/schedule/v1/message_pb.rb +22 -1
- data/lib/gen/temporal/api/sdk/v1/task_complete_metadata_pb.rb +23 -0
- data/lib/gen/temporal/api/taskqueue/v1/message_pb.rb +2 -2
- data/lib/gen/temporal/api/testservice/v1/request_response_pb.rb +49 -0
- data/lib/gen/temporal/api/testservice/v1/service_pb.rb +21 -0
- data/lib/gen/temporal/api/update/v1/message_pb.rb +49 -3
- data/lib/gen/temporal/api/version/v1/message_pb.rb +1 -1
- data/lib/gen/temporal/api/workflow/v1/message_pb.rb +2 -1
- data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +47 -20
- data/lib/gen/temporal/api/workflowservice/v1/service_pb.rb +1 -1
- data/lib/gen/temporal/sdk/core/activity_result/activity_result_pb.rb +13 -9
- data/lib/gen/temporal/sdk/core/activity_task/activity_task_pb.rb +10 -6
- data/lib/gen/temporal/sdk/core/child_workflow/child_workflow_pb.rb +13 -9
- data/lib/gen/temporal/sdk/core/common/common_pb.rb +7 -3
- data/lib/gen/temporal/sdk/core/core_interface_pb.rb +9 -3
- data/lib/gen/temporal/sdk/core/external_data/external_data_pb.rb +7 -3
- data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +28 -21
- data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +32 -24
- data/lib/gen/temporal/sdk/core/workflow_completion/workflow_completion_pb.rb +12 -5
- data/lib/temporalio/activity/context.rb +102 -0
- data/lib/temporalio/activity/info.rb +67 -0
- data/lib/temporalio/activity.rb +85 -0
- data/lib/temporalio/bridge/connect_options.rb +15 -0
- data/lib/temporalio/bridge/error.rb +8 -0
- data/lib/temporalio/bridge/retry_config.rb +24 -0
- data/lib/temporalio/bridge/tls_options.rb +19 -0
- data/lib/temporalio/bridge.rb +14 -0
- data/lib/{temporal → temporalio}/client/implementation.rb +57 -56
- data/lib/{temporal → temporalio}/client/workflow_handle.rb +35 -35
- data/lib/{temporal → temporalio}/client.rb +19 -32
- data/lib/temporalio/connection/retry_config.rb +44 -0
- data/lib/temporalio/connection/service.rb +20 -0
- data/lib/temporalio/connection/test_service.rb +92 -0
- data/lib/temporalio/connection/tls_options.rb +51 -0
- data/lib/temporalio/connection/workflow_service.rb +731 -0
- data/lib/temporalio/connection.rb +86 -0
- data/lib/{temporal → temporalio}/data_converter.rb +76 -35
- data/lib/{temporal → temporalio}/error/failure.rb +6 -6
- data/lib/{temporal → temporalio}/error/workflow_failure.rb +4 -2
- data/lib/{temporal → temporalio}/errors.rb +19 -1
- data/lib/{temporal → temporalio}/failure_converter/base.rb +5 -5
- data/lib/{temporal → temporalio}/failure_converter/basic.rb +58 -52
- data/lib/temporalio/failure_converter.rb +7 -0
- data/lib/temporalio/interceptor/activity_inbound.rb +22 -0
- data/lib/temporalio/interceptor/activity_outbound.rb +24 -0
- data/lib/{temporal → temporalio}/interceptor/chain.rb +7 -6
- data/lib/{temporal → temporalio}/interceptor/client.rb +27 -2
- data/lib/temporalio/interceptor.rb +22 -0
- data/lib/{temporal → temporalio}/payload_codec/base.rb +5 -5
- data/lib/{temporal → temporalio}/payload_converter/base.rb +3 -3
- data/lib/{temporal → temporalio}/payload_converter/bytes.rb +4 -3
- data/lib/{temporal → temporalio}/payload_converter/composite.rb +7 -5
- data/lib/{temporal → temporalio}/payload_converter/encoding_base.rb +4 -4
- data/lib/{temporal → temporalio}/payload_converter/json.rb +4 -3
- data/lib/{temporal → temporalio}/payload_converter/nil.rb +4 -3
- data/lib/temporalio/payload_converter.rb +14 -0
- data/lib/{temporal → temporalio}/retry_policy.rb +17 -7
- data/lib/{temporal → temporalio}/retry_state.rb +1 -1
- data/lib/temporalio/runtime.rb +25 -0
- data/lib/temporalio/testing/time_skipping_handle.rb +32 -0
- data/lib/temporalio/testing/time_skipping_interceptor.rb +23 -0
- data/lib/temporalio/testing/workflow_environment.rb +112 -0
- data/lib/temporalio/testing.rb +175 -0
- data/lib/{temporal → temporalio}/timeout_type.rb +2 -2
- data/lib/temporalio/version.rb +3 -0
- data/lib/temporalio/worker/activity_runner.rb +114 -0
- data/lib/temporalio/worker/activity_worker.rb +164 -0
- data/lib/temporalio/worker/reactor.rb +46 -0
- data/lib/temporalio/worker/runner.rb +63 -0
- data/lib/temporalio/worker/sync_worker.rb +124 -0
- data/lib/temporalio/worker/thread_pool_executor.rb +51 -0
- data/lib/temporalio/worker.rb +204 -0
- data/lib/temporalio/workflow/async.rb +46 -0
- data/lib/{temporal → temporalio}/workflow/execution_info.rb +4 -4
- data/lib/{temporal → temporalio}/workflow/execution_status.rb +1 -1
- data/lib/temporalio/workflow/future.rb +138 -0
- data/lib/{temporal → temporalio}/workflow/id_reuse_policy.rb +6 -6
- data/lib/temporalio/workflow/info.rb +76 -0
- data/lib/{temporal → temporalio}/workflow/query_reject_condition.rb +5 -5
- data/lib/temporalio.rb +12 -3
- data/temporalio.gemspec +11 -6
- metadata +137 -64
- data/bridge/sdk-core/Cargo.lock +0 -2606
- data/bridge/sdk-core/bridge-ffi/Cargo.toml +0 -24
- data/bridge/sdk-core/bridge-ffi/LICENSE.txt +0 -23
- data/bridge/sdk-core/bridge-ffi/build.rs +0 -25
- data/bridge/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -249
- data/bridge/sdk-core/bridge-ffi/src/lib.rs +0 -825
- data/bridge/sdk-core/bridge-ffi/src/wrappers.rs +0 -211
- data/bridge/sdk-core/core/src/log_export.rs +0 -62
- data/bridge/sdk-core/core/src/worker/workflow/machines/mutable_side_effect_state_machine.rs +0 -127
- data/bridge/sdk-core/core/src/worker/workflow/machines/side_effect_state_machine.rs +0 -71
- data/bridge/sdk-core/protos/api_upstream/temporal/api/cluster/v1/message.proto +0 -83
- data/bridge/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -210
- data/bridge/sdk-core/sdk/src/conversions.rs +0 -8
- data/lib/bridge.so +0 -0
- data/lib/gen/temporal/api/cluster/v1/message_pb.rb +0 -67
- data/lib/gen/temporal/api/enums/v1/cluster_pb.rb +0 -26
- data/lib/gen/temporal/sdk/core/bridge/bridge_pb.rb +0 -222
- data/lib/temporal/bridge.rb +0 -14
- data/lib/temporal/connection.rb +0 -736
- data/lib/temporal/failure_converter.rb +0 -8
- data/lib/temporal/payload_converter.rb +0 -14
- data/lib/temporal/runtime.rb +0 -22
- data/lib/temporal/version.rb +0 -3
- data/lib/temporal.rb +0 -8
|
@@ -3,22 +3,26 @@ 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,
|
|
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
|
+
use crossbeam::queue::SegQueue;
|
|
11
12
|
use futures::{future::join_all, FutureExt};
|
|
12
13
|
use std::{
|
|
13
14
|
collections::HashMap,
|
|
15
|
+
ops::Sub,
|
|
14
16
|
sync::{
|
|
15
17
|
atomic::{AtomicUsize, Ordering},
|
|
16
18
|
Arc,
|
|
17
19
|
},
|
|
18
|
-
time::Duration,
|
|
20
|
+
time::{Duration, SystemTime},
|
|
19
21
|
};
|
|
20
22
|
use temporal_client::WorkflowOptions;
|
|
21
|
-
use temporal_sdk::{
|
|
23
|
+
use temporal_sdk::{
|
|
24
|
+
ActContext, ActivityCancelledError, LocalActivityOptions, WfContext, WorkflowResult,
|
|
25
|
+
};
|
|
22
26
|
use temporal_sdk_core_api::Worker;
|
|
23
27
|
use temporal_sdk_core_protos::{
|
|
24
28
|
coresdk::{
|
|
@@ -29,11 +33,16 @@ use temporal_sdk_core_protos::{
|
|
|
29
33
|
ActivityTaskCompletion, AsJsonPayloadExt,
|
|
30
34
|
},
|
|
31
35
|
temporal::api::{
|
|
32
|
-
common::v1::RetryPolicy,
|
|
36
|
+
common::v1::RetryPolicy,
|
|
37
|
+
enums::v1::{EventType, TimeoutType, WorkflowTaskFailedCause},
|
|
38
|
+
failure::v1::Failure,
|
|
33
39
|
query::v1::WorkflowQuery,
|
|
34
40
|
},
|
|
41
|
+
DEFAULT_ACTIVITY_TYPE,
|
|
42
|
+
};
|
|
43
|
+
use temporal_sdk_core_test_utils::{
|
|
44
|
+
schedule_local_activity_cmd, start_timer_cmd, WorkerTestHelpers,
|
|
35
45
|
};
|
|
36
|
-
use temporal_sdk_core_test_utils::{schedule_local_activity_cmd, WorkerTestHelpers};
|
|
37
46
|
use tokio::sync::Barrier;
|
|
38
47
|
|
|
39
48
|
async fn echo(_ctx: ActContext, e: String) -> anyhow::Result<String> {
|
|
@@ -52,7 +61,7 @@ async fn local_act_two_wfts_before_marker(#[case] replay: bool, #[case] cached:
|
|
|
52
61
|
let mut t = TestHistoryBuilder::default();
|
|
53
62
|
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
54
63
|
t.add_full_wf_task();
|
|
55
|
-
let timer_started_event_id = t.
|
|
64
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
56
65
|
t.add_full_wf_task();
|
|
57
66
|
t.add_local_activity_result_marker(1, "1", b"echo".into());
|
|
58
67
|
t.add_timer_fired(timer_started_event_id, "1".to_string());
|
|
@@ -77,7 +86,7 @@ async fn local_act_two_wfts_before_marker(#[case] replay: bool, #[case] cached:
|
|
|
77
86
|
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
78
87
|
|ctx: WfContext| async move {
|
|
79
88
|
let la = ctx.local_activity(LocalActivityOptions {
|
|
80
|
-
activity_type:
|
|
89
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
81
90
|
input: "hi".as_json_payload().expect("serializes fine"),
|
|
82
91
|
..Default::default()
|
|
83
92
|
});
|
|
@@ -86,7 +95,7 @@ async fn local_act_two_wfts_before_marker(#[case] replay: bool, #[case] cached:
|
|
|
86
95
|
Ok(().into())
|
|
87
96
|
},
|
|
88
97
|
);
|
|
89
|
-
worker.register_activity(
|
|
98
|
+
worker.register_activity(DEFAULT_ACTIVITY_TYPE, echo);
|
|
90
99
|
worker
|
|
91
100
|
.submit_wf(
|
|
92
101
|
wf_id.to_owned(),
|
|
@@ -104,7 +113,7 @@ pub async fn local_act_fanout_wf(ctx: WfContext) -> WorkflowResult<()> {
|
|
|
104
113
|
.map(|i| {
|
|
105
114
|
ctx.local_activity(LocalActivityOptions {
|
|
106
115
|
activity_type: "echo".to_string(),
|
|
107
|
-
input: format!("Hi {}"
|
|
116
|
+
input: format!("Hi {i}")
|
|
108
117
|
.as_json_payload()
|
|
109
118
|
.expect("serializes fine"),
|
|
110
119
|
..Default::default()
|
|
@@ -121,7 +130,7 @@ async fn local_act_many_concurrent() {
|
|
|
121
130
|
let mut t = TestHistoryBuilder::default();
|
|
122
131
|
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
123
132
|
t.add_full_wf_task();
|
|
124
|
-
let timer_started_event_id = t.
|
|
133
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
125
134
|
t.add_full_wf_task();
|
|
126
135
|
for i in 1..=50 {
|
|
127
136
|
t.add_local_activity_result_marker(i, &i.to_string(), b"echo".into());
|
|
@@ -162,12 +171,7 @@ async fn local_act_many_concurrent() {
|
|
|
162
171
|
async fn local_act_heartbeat(#[case] shutdown_middle: bool) {
|
|
163
172
|
let mut t = TestHistoryBuilder::default();
|
|
164
173
|
let wft_timeout = Duration::from_millis(200);
|
|
165
|
-
|
|
166
|
-
wes_short_wft_timeout.workflow_task_timeout = Some(wft_timeout.try_into().unwrap());
|
|
167
|
-
t.add(
|
|
168
|
-
EventType::WorkflowExecutionStarted,
|
|
169
|
-
wes_short_wft_timeout.into(),
|
|
170
|
-
);
|
|
174
|
+
t.add_wfe_started_with_wft_timeout(wft_timeout);
|
|
171
175
|
t.add_full_wf_task();
|
|
172
176
|
// Task created by WFT heartbeat
|
|
173
177
|
t.add_full_wf_task();
|
|
@@ -298,7 +302,7 @@ async fn local_act_retry_long_backoff_uses_timer() {
|
|
|
298
302
|
"1",
|
|
299
303
|
Failure::application_failure("la failed".to_string(), false),
|
|
300
304
|
);
|
|
301
|
-
let timer_started_event_id = t.
|
|
305
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
302
306
|
t.add_timer_fired(timer_started_event_id, "1".to_string());
|
|
303
307
|
t.add_full_wf_task();
|
|
304
308
|
t.add_local_activity_fail_marker(
|
|
@@ -306,7 +310,7 @@ async fn local_act_retry_long_backoff_uses_timer() {
|
|
|
306
310
|
"2",
|
|
307
311
|
Failure::application_failure("la failed".to_string(), false),
|
|
308
312
|
);
|
|
309
|
-
let timer_started_event_id = t.
|
|
313
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
310
314
|
t.add_timer_fired(timer_started_event_id, "2".to_string());
|
|
311
315
|
t.add_full_wf_task();
|
|
312
316
|
t.add_workflow_execution_completed();
|
|
@@ -326,7 +330,7 @@ async fn local_act_retry_long_backoff_uses_timer() {
|
|
|
326
330
|
|ctx: WfContext| async move {
|
|
327
331
|
let la_res = ctx
|
|
328
332
|
.local_activity(LocalActivityOptions {
|
|
329
|
-
activity_type:
|
|
333
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
330
334
|
input: "hi".as_json_payload().expect("serializes fine"),
|
|
331
335
|
retry_policy: RetryPolicy {
|
|
332
336
|
initial_interval: Some(prost_dur!(from_millis(65))),
|
|
@@ -345,9 +349,12 @@ async fn local_act_retry_long_backoff_uses_timer() {
|
|
|
345
349
|
Ok(().into())
|
|
346
350
|
},
|
|
347
351
|
);
|
|
348
|
-
worker.register_activity(
|
|
349
|
-
|
|
350
|
-
|
|
352
|
+
worker.register_activity(
|
|
353
|
+
DEFAULT_ACTIVITY_TYPE,
|
|
354
|
+
move |_ctx: ActContext, _: String| async move {
|
|
355
|
+
Result::<(), _>::Err(anyhow!("Oh no I failed!"))
|
|
356
|
+
},
|
|
357
|
+
);
|
|
351
358
|
worker
|
|
352
359
|
.submit_wf(
|
|
353
360
|
wf_id.to_owned(),
|
|
@@ -365,7 +372,7 @@ async fn local_act_null_result() {
|
|
|
365
372
|
let mut t = TestHistoryBuilder::default();
|
|
366
373
|
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
367
374
|
t.add_full_wf_task();
|
|
368
|
-
t.add_local_activity_marker(1, "1", None, None,
|
|
375
|
+
t.add_local_activity_marker(1, "1", None, None, |_| {});
|
|
369
376
|
t.add_workflow_execution_completed();
|
|
370
377
|
|
|
371
378
|
let wf_id = "fakeid";
|
|
@@ -398,24 +405,63 @@ async fn local_act_null_result() {
|
|
|
398
405
|
worker.run_until_done().await.unwrap();
|
|
399
406
|
}
|
|
400
407
|
|
|
408
|
+
#[tokio::test]
|
|
409
|
+
async fn local_act_command_immediately_follows_la_marker() {
|
|
410
|
+
// This repro only works both when cache is off, and there is at least one heartbeat wft
|
|
411
|
+
// before the marker & next command are recorded.
|
|
412
|
+
let mut t = TestHistoryBuilder::default();
|
|
413
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
414
|
+
t.add_full_wf_task();
|
|
415
|
+
t.add_full_wf_task();
|
|
416
|
+
t.add_local_activity_result_marker(1, "1", "done".into());
|
|
417
|
+
t.add_by_type(EventType::TimerStarted);
|
|
418
|
+
t.add_full_wf_task();
|
|
419
|
+
|
|
420
|
+
let wf_id = "fakeid";
|
|
421
|
+
let mock = mock_workflow_client();
|
|
422
|
+
// Bug only repros when seeing history up to third wft
|
|
423
|
+
let mh = MockPollCfg::from_resp_batches(wf_id, t, [3], mock);
|
|
424
|
+
let mut worker = mock_sdk_cfg(mh, |w| w.max_cached_workflows = 0);
|
|
425
|
+
|
|
426
|
+
worker.register_wf(
|
|
427
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
428
|
+
|ctx: WfContext| async move {
|
|
429
|
+
ctx.local_activity(LocalActivityOptions {
|
|
430
|
+
activity_type: "nullres".to_string(),
|
|
431
|
+
input: "hi".as_json_payload().expect("serializes fine"),
|
|
432
|
+
..Default::default()
|
|
433
|
+
})
|
|
434
|
+
.await;
|
|
435
|
+
ctx.timer(Duration::from_secs(1)).await;
|
|
436
|
+
Ok(().into())
|
|
437
|
+
},
|
|
438
|
+
);
|
|
439
|
+
worker.register_activity("nullres", |_ctx: ActContext, _: String| async { Ok(()) });
|
|
440
|
+
worker
|
|
441
|
+
.submit_wf(
|
|
442
|
+
wf_id.to_owned(),
|
|
443
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
444
|
+
vec![],
|
|
445
|
+
WorkflowOptions::default(),
|
|
446
|
+
)
|
|
447
|
+
.await
|
|
448
|
+
.unwrap();
|
|
449
|
+
worker.run_until_done().await.unwrap();
|
|
450
|
+
}
|
|
451
|
+
|
|
401
452
|
#[tokio::test]
|
|
402
453
|
async fn query_during_wft_heartbeat_doesnt_accidentally_fail_to_continue_heartbeat() {
|
|
403
454
|
let wfid = "fake_wf_id";
|
|
404
455
|
let mut t = TestHistoryBuilder::default();
|
|
405
|
-
|
|
406
|
-
wes_short_wft_timeout.workflow_task_timeout = Some(prost_dur!(from_millis(200)));
|
|
407
|
-
t.add(
|
|
408
|
-
EventType::WorkflowExecutionStarted,
|
|
409
|
-
wes_short_wft_timeout.into(),
|
|
410
|
-
);
|
|
456
|
+
t.add_wfe_started_with_wft_timeout(Duration::from_millis(200));
|
|
411
457
|
t.add_full_wf_task();
|
|
412
458
|
// get query here
|
|
413
459
|
t.add_full_wf_task();
|
|
414
|
-
t.
|
|
460
|
+
t.add_local_activity_result_marker(1, "1", "done".into());
|
|
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)
|
|
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();
|
|
@@ -457,7 +502,7 @@ async fn query_during_wft_heartbeat_doesnt_accidentally_fail_to_continue_heartbe
|
|
|
457
502
|
task.run_id,
|
|
458
503
|
schedule_local_activity_cmd(
|
|
459
504
|
1,
|
|
460
|
-
"
|
|
505
|
+
"1",
|
|
461
506
|
ActivityCancellationType::TryCancel,
|
|
462
507
|
Duration::from_secs(60),
|
|
463
508
|
),
|
|
@@ -513,3 +558,489 @@ 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
|
+
t.add(default_wes_attribs());
|
|
572
|
+
// Since we don't send queries with start workflow, need one workflow task of something else
|
|
573
|
+
// b/c we want to get an activation with a job and a nonlegacy query
|
|
574
|
+
t.add_full_wf_task();
|
|
575
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
576
|
+
t.add_timer_fired(timer_started_event_id, "1".to_string());
|
|
577
|
+
|
|
578
|
+
// nonlegacy query got here & LA started here
|
|
579
|
+
t.add_full_wf_task();
|
|
580
|
+
// legacy query got here, at the same time that the LA is resolved
|
|
581
|
+
t.add_local_activity_result_marker(1, "1", "whatever".into());
|
|
582
|
+
t.add_workflow_execution_completed();
|
|
583
|
+
|
|
584
|
+
let barr = Arc::new(Barrier::new(2));
|
|
585
|
+
let barr_c = barr.clone();
|
|
586
|
+
|
|
587
|
+
let tasks = [
|
|
588
|
+
hist_to_poll_resp(&t, wfid.to_owned(), ResponseType::ToTaskNum(1)),
|
|
589
|
+
{
|
|
590
|
+
let mut pr = hist_to_poll_resp(&t, wfid.to_owned(), ResponseType::OneTask(2));
|
|
591
|
+
pr.queries = HashMap::new();
|
|
592
|
+
pr.queries.insert(
|
|
593
|
+
"q1".to_string(),
|
|
594
|
+
WorkflowQuery {
|
|
595
|
+
query_type: "query-type".to_string(),
|
|
596
|
+
query_args: Some(b"hi".into()),
|
|
597
|
+
header: None,
|
|
598
|
+
},
|
|
599
|
+
);
|
|
600
|
+
pr
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
let mut pr = hist_to_poll_resp(
|
|
604
|
+
&t,
|
|
605
|
+
wfid.to_owned(),
|
|
606
|
+
ResponseType::UntilResolved(
|
|
607
|
+
async move {
|
|
608
|
+
barr_c.wait().await;
|
|
609
|
+
// This sleep is the only not-incredibly-invasive way to ensure the LA
|
|
610
|
+
// resolves & updates machines before we process this task
|
|
611
|
+
tokio::time::sleep(Duration::from_secs(1)).await;
|
|
612
|
+
}
|
|
613
|
+
.boxed(),
|
|
614
|
+
2,
|
|
615
|
+
),
|
|
616
|
+
);
|
|
617
|
+
// Strip beginning of history so the only events are WFT sched/started, we need to look
|
|
618
|
+
// like we hit the cache
|
|
619
|
+
{
|
|
620
|
+
let h = pr.history.as_mut().unwrap();
|
|
621
|
+
h.events = h.events.split_off(6);
|
|
622
|
+
}
|
|
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
|
+
}
|
|
738
|
+
|
|
739
|
+
#[tokio::test]
|
|
740
|
+
async fn test_schedule_to_start_timeout() {
|
|
741
|
+
let mut t = TestHistoryBuilder::default();
|
|
742
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
743
|
+
t.add_full_wf_task();
|
|
744
|
+
|
|
745
|
+
let wf_id = "fakeid";
|
|
746
|
+
let mock = mock_workflow_client();
|
|
747
|
+
let mh = MockPollCfg::from_resp_batches(wf_id, t, [ResponseType::ToTaskNum(1)], mock);
|
|
748
|
+
let mut worker = mock_sdk_cfg(mh, |w| w.max_cached_workflows = 1);
|
|
749
|
+
|
|
750
|
+
worker.register_wf(
|
|
751
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
752
|
+
|ctx: WfContext| async move {
|
|
753
|
+
let la_res = ctx
|
|
754
|
+
.local_activity(LocalActivityOptions {
|
|
755
|
+
activity_type: "echo".to_string(),
|
|
756
|
+
input: "hi".as_json_payload().expect("serializes fine"),
|
|
757
|
+
// Impossibly small timeout so we timeout in the queue
|
|
758
|
+
schedule_to_start_timeout: prost_dur!(from_nanos(1)),
|
|
759
|
+
..Default::default()
|
|
760
|
+
})
|
|
761
|
+
.await;
|
|
762
|
+
assert_eq!(la_res.timed_out(), Some(TimeoutType::ScheduleToStart));
|
|
763
|
+
Ok(().into())
|
|
764
|
+
},
|
|
765
|
+
);
|
|
766
|
+
worker.register_activity(
|
|
767
|
+
"echo",
|
|
768
|
+
move |_ctx: ActContext, _: String| async move { Ok(()) },
|
|
769
|
+
);
|
|
770
|
+
worker
|
|
771
|
+
.submit_wf(
|
|
772
|
+
wf_id.to_owned(),
|
|
773
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
774
|
+
vec![],
|
|
775
|
+
WorkflowOptions::default(),
|
|
776
|
+
)
|
|
777
|
+
.await
|
|
778
|
+
.unwrap();
|
|
779
|
+
worker.run_until_done().await.unwrap();
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
#[rstest::rstest]
|
|
783
|
+
#[case::sched_to_start(true)]
|
|
784
|
+
#[case::sched_to_close(false)]
|
|
785
|
+
#[tokio::test]
|
|
786
|
+
async fn test_schedule_to_start_timeout_not_based_on_original_time(
|
|
787
|
+
#[case] is_sched_to_start: bool,
|
|
788
|
+
) {
|
|
789
|
+
// We used to carry over the schedule time of LAs from the "original" schedule time if these LAs
|
|
790
|
+
// created newly after backing off across a timer. That was a mistake, since schedule-to-start
|
|
791
|
+
// timeouts should apply to when the new attempt was scheduled. This test verifies:
|
|
792
|
+
// * we don't time out on s-t-s timeouts because of that, when the param is true.
|
|
793
|
+
// * we do properly time out on s-t-c timeouts when the param is false
|
|
794
|
+
|
|
795
|
+
let mut t = TestHistoryBuilder::default();
|
|
796
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
797
|
+
t.add_full_wf_task();
|
|
798
|
+
let orig_sched = SystemTime::now().sub(Duration::from_secs(60 * 20));
|
|
799
|
+
t.add_local_activity_marker(
|
|
800
|
+
1,
|
|
801
|
+
"1",
|
|
802
|
+
None,
|
|
803
|
+
Some(Failure::application_failure("la failed".to_string(), false)),
|
|
804
|
+
|deets| {
|
|
805
|
+
// Really old schedule time, which should _not_ count against schedule_to_start
|
|
806
|
+
deets.original_schedule_time = Some(orig_sched.into());
|
|
807
|
+
// Backoff value must be present since we're simulating timer backoff
|
|
808
|
+
deets.backoff = Some(prost_dur!(from_secs(100)));
|
|
809
|
+
},
|
|
810
|
+
);
|
|
811
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
812
|
+
t.add_timer_fired(timer_started_event_id, "1".to_string());
|
|
813
|
+
t.add_workflow_task_scheduled_and_started();
|
|
814
|
+
|
|
815
|
+
let wf_id = "fakeid";
|
|
816
|
+
let mock = mock_workflow_client();
|
|
817
|
+
let mh = MockPollCfg::from_resp_batches(wf_id, t, [ResponseType::AllHistory], mock);
|
|
818
|
+
let mut worker = mock_sdk_cfg(mh, |w| w.max_cached_workflows = 1);
|
|
819
|
+
|
|
820
|
+
let schedule_to_close_timeout = Some(if is_sched_to_start {
|
|
821
|
+
// This 60 minute timeout will not have elapsed according to the original
|
|
822
|
+
// schedule time in the history.
|
|
823
|
+
Duration::from_secs(60 * 60)
|
|
824
|
+
} else {
|
|
825
|
+
// This 10 minute timeout will have already elapsed
|
|
826
|
+
Duration::from_secs(10 * 60)
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
worker.register_wf(
|
|
830
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
831
|
+
move |ctx: WfContext| async move {
|
|
832
|
+
let la_res = ctx
|
|
833
|
+
.local_activity(LocalActivityOptions {
|
|
834
|
+
activity_type: "echo".to_string(),
|
|
835
|
+
input: "hi".as_json_payload().expect("serializes fine"),
|
|
836
|
+
retry_policy: RetryPolicy {
|
|
837
|
+
initial_interval: Some(prost_dur!(from_millis(50))),
|
|
838
|
+
backoff_coefficient: 1.2,
|
|
839
|
+
maximum_interval: None,
|
|
840
|
+
maximum_attempts: 5,
|
|
841
|
+
non_retryable_error_types: vec![],
|
|
842
|
+
},
|
|
843
|
+
schedule_to_start_timeout: Some(Duration::from_secs(60)),
|
|
844
|
+
schedule_to_close_timeout,
|
|
845
|
+
..Default::default()
|
|
846
|
+
})
|
|
847
|
+
.await;
|
|
848
|
+
if is_sched_to_start {
|
|
849
|
+
assert!(la_res.completed_ok());
|
|
850
|
+
} else {
|
|
851
|
+
assert_eq!(la_res.timed_out(), Some(TimeoutType::ScheduleToClose));
|
|
852
|
+
}
|
|
853
|
+
Ok(().into())
|
|
854
|
+
},
|
|
855
|
+
);
|
|
856
|
+
worker.register_activity(
|
|
857
|
+
"echo",
|
|
858
|
+
move |_ctx: ActContext, _: String| async move { Ok(()) },
|
|
859
|
+
);
|
|
860
|
+
worker
|
|
861
|
+
.submit_wf(
|
|
862
|
+
wf_id.to_owned(),
|
|
863
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
864
|
+
vec![],
|
|
865
|
+
WorkflowOptions::default(),
|
|
866
|
+
)
|
|
867
|
+
.await
|
|
868
|
+
.unwrap();
|
|
869
|
+
worker.run_until_done().await.unwrap();
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
#[tokio::test]
|
|
873
|
+
async fn wft_failure_cancels_running_las() {
|
|
874
|
+
let mut t = TestHistoryBuilder::default();
|
|
875
|
+
t.add_wfe_started_with_wft_timeout(Duration::from_millis(200));
|
|
876
|
+
t.add_full_wf_task();
|
|
877
|
+
let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
|
|
878
|
+
t.add_timer_fired(timer_started_event_id, "1".to_string());
|
|
879
|
+
t.add_workflow_task_scheduled_and_started();
|
|
880
|
+
|
|
881
|
+
let wf_id = "fakeid";
|
|
882
|
+
let mock = mock_workflow_client();
|
|
883
|
+
let mut mh = MockPollCfg::from_resp_batches(wf_id, t, [1, 2], mock);
|
|
884
|
+
mh.num_expected_fails = 1;
|
|
885
|
+
let mut worker = mock_sdk_cfg(mh, |w| w.max_cached_workflows = 1);
|
|
886
|
+
|
|
887
|
+
worker.register_wf(
|
|
888
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
889
|
+
|ctx: WfContext| async move {
|
|
890
|
+
let la_handle = ctx.local_activity(LocalActivityOptions {
|
|
891
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
892
|
+
input: "hi".as_json_payload().expect("serializes fine"),
|
|
893
|
+
..Default::default()
|
|
894
|
+
});
|
|
895
|
+
tokio::join!(
|
|
896
|
+
async {
|
|
897
|
+
ctx.timer(Duration::from_secs(1)).await;
|
|
898
|
+
panic!("ahhh I'm failing wft")
|
|
899
|
+
},
|
|
900
|
+
la_handle
|
|
901
|
+
);
|
|
902
|
+
Ok(().into())
|
|
903
|
+
},
|
|
904
|
+
);
|
|
905
|
+
worker.register_activity(
|
|
906
|
+
DEFAULT_ACTIVITY_TYPE,
|
|
907
|
+
move |ctx: ActContext, _: String| async move {
|
|
908
|
+
let res = tokio::time::timeout(Duration::from_millis(500), ctx.cancelled()).await;
|
|
909
|
+
if res.is_err() {
|
|
910
|
+
panic!("Activity must be cancelled!!!!");
|
|
911
|
+
}
|
|
912
|
+
Result::<(), _>::Err(ActivityCancelledError::default().into())
|
|
913
|
+
},
|
|
914
|
+
);
|
|
915
|
+
worker
|
|
916
|
+
.submit_wf(
|
|
917
|
+
wf_id.to_owned(),
|
|
918
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
919
|
+
vec![],
|
|
920
|
+
WorkflowOptions::default(),
|
|
921
|
+
)
|
|
922
|
+
.await
|
|
923
|
+
.unwrap();
|
|
924
|
+
worker.run_until_done().await.unwrap();
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
#[tokio::test]
|
|
928
|
+
async fn resolved_las_not_recorded_if_wft_fails_many_times() {
|
|
929
|
+
// We shouldn't record any LA results if the workflow activation is repeatedly failing. There
|
|
930
|
+
// was an issue that, because we stop reporting WFT failures after 2 tries, this meant the WFT
|
|
931
|
+
// was not marked as "completed" and the WFT could accidentally be replied to with LA results.
|
|
932
|
+
let mut t = TestHistoryBuilder::default();
|
|
933
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
|
934
|
+
t.add_workflow_task_scheduled_and_started();
|
|
935
|
+
t.add_workflow_task_failed_with_failure(
|
|
936
|
+
WorkflowTaskFailedCause::Unspecified,
|
|
937
|
+
Default::default(),
|
|
938
|
+
);
|
|
939
|
+
t.add_workflow_task_scheduled_and_started();
|
|
940
|
+
|
|
941
|
+
let wf_id = "fakeid";
|
|
942
|
+
let mock = mock_workflow_client();
|
|
943
|
+
let mut mh = MockPollCfg::from_resp_batches(
|
|
944
|
+
wf_id,
|
|
945
|
+
t,
|
|
946
|
+
[1.into(), ResponseType::AllHistory, ResponseType::AllHistory],
|
|
947
|
+
mock,
|
|
948
|
+
);
|
|
949
|
+
mh.num_expected_fails = 2;
|
|
950
|
+
mh.num_expected_completions = Some(0.into());
|
|
951
|
+
let mut worker = mock_sdk_cfg(mh, |w| w.max_cached_workflows = 1);
|
|
952
|
+
|
|
953
|
+
worker.register_wf(
|
|
954
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
955
|
+
|ctx: WfContext| async move {
|
|
956
|
+
ctx.local_activity(LocalActivityOptions {
|
|
957
|
+
activity_type: "echo".to_string(),
|
|
958
|
+
input: "hi".as_json_payload().expect("serializes fine"),
|
|
959
|
+
..Default::default()
|
|
960
|
+
})
|
|
961
|
+
.await;
|
|
962
|
+
panic!("Oh nooooo")
|
|
963
|
+
},
|
|
964
|
+
);
|
|
965
|
+
worker.register_activity(
|
|
966
|
+
"echo",
|
|
967
|
+
move |_: ActContext, _: String| async move { Ok(()) },
|
|
968
|
+
);
|
|
969
|
+
worker
|
|
970
|
+
.submit_wf(
|
|
971
|
+
wf_id.to_owned(),
|
|
972
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
973
|
+
vec![],
|
|
974
|
+
WorkflowOptions::default(),
|
|
975
|
+
)
|
|
976
|
+
.await
|
|
977
|
+
.unwrap();
|
|
978
|
+
worker.run_until_done().await.unwrap();
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
#[tokio::test]
|
|
982
|
+
async fn local_act_records_nonfirst_attempts_ok() {
|
|
983
|
+
let mut t = TestHistoryBuilder::default();
|
|
984
|
+
let wft_timeout = Duration::from_millis(200);
|
|
985
|
+
t.add_wfe_started_with_wft_timeout(wft_timeout);
|
|
986
|
+
t.add_full_wf_task();
|
|
987
|
+
t.add_full_wf_task();
|
|
988
|
+
t.add_full_wf_task();
|
|
989
|
+
t.add_workflow_task_scheduled_and_started();
|
|
990
|
+
|
|
991
|
+
let wf_id = "fakeid";
|
|
992
|
+
let mock = mock_workflow_client();
|
|
993
|
+
let mut mh = MockPollCfg::from_resp_batches(wf_id, t, [1, 2, 3], mock);
|
|
994
|
+
let nonfirst_counts = Arc::new(SegQueue::new());
|
|
995
|
+
let nfc_c = nonfirst_counts.clone();
|
|
996
|
+
mh.completion_asserts = Some(Box::new(move |c| {
|
|
997
|
+
nfc_c.push(
|
|
998
|
+
c.metering_metadata
|
|
999
|
+
.nonfirst_local_activity_execution_attempts,
|
|
1000
|
+
);
|
|
1001
|
+
}));
|
|
1002
|
+
let mut worker = mock_sdk_cfg(mh, |wc| {
|
|
1003
|
+
wc.max_cached_workflows = 1;
|
|
1004
|
+
wc.max_outstanding_workflow_tasks = 1;
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
worker.register_wf(
|
|
1008
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
1009
|
+
|ctx: WfContext| async move {
|
|
1010
|
+
ctx.local_activity(LocalActivityOptions {
|
|
1011
|
+
activity_type: "echo".to_string(),
|
|
1012
|
+
input: "hi".as_json_payload().expect("serializes fine"),
|
|
1013
|
+
retry_policy: RetryPolicy {
|
|
1014
|
+
initial_interval: Some(prost_dur!(from_millis(10))),
|
|
1015
|
+
backoff_coefficient: 1.0,
|
|
1016
|
+
maximum_interval: None,
|
|
1017
|
+
maximum_attempts: 0,
|
|
1018
|
+
non_retryable_error_types: vec![],
|
|
1019
|
+
},
|
|
1020
|
+
..Default::default()
|
|
1021
|
+
})
|
|
1022
|
+
.await;
|
|
1023
|
+
Ok(().into())
|
|
1024
|
+
},
|
|
1025
|
+
);
|
|
1026
|
+
worker.register_activity("echo", move |_ctx: ActContext, _: String| async move {
|
|
1027
|
+
Result::<(), _>::Err(anyhow!("I fail"))
|
|
1028
|
+
});
|
|
1029
|
+
worker
|
|
1030
|
+
.submit_wf(
|
|
1031
|
+
wf_id.to_owned(),
|
|
1032
|
+
DEFAULT_WORKFLOW_TYPE.to_owned(),
|
|
1033
|
+
vec![],
|
|
1034
|
+
WorkflowOptions::default(),
|
|
1035
|
+
)
|
|
1036
|
+
.await
|
|
1037
|
+
.unwrap();
|
|
1038
|
+
worker.run_until_done().await.unwrap();
|
|
1039
|
+
// 3 workflow tasks
|
|
1040
|
+
assert_eq!(nonfirst_counts.len(), 3);
|
|
1041
|
+
// First task's non-first count should, of course, be 0
|
|
1042
|
+
assert_eq!(nonfirst_counts.pop().unwrap(), 0);
|
|
1043
|
+
// Next two, some nonzero amount which could vary based on test load
|
|
1044
|
+
assert!(nonfirst_counts.pop().unwrap() > 0);
|
|
1045
|
+
assert!(nonfirst_counts.pop().unwrap() > 0);
|
|
1046
|
+
}
|