temporalio 0.0.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.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +130 -0
- data/bridge/Cargo.lock +2865 -0
- data/bridge/Cargo.toml +26 -0
- data/bridge/sdk-core/ARCHITECTURE.md +76 -0
- data/bridge/sdk-core/Cargo.lock +2606 -0
- data/bridge/sdk-core/Cargo.toml +2 -0
- data/bridge/sdk-core/LICENSE.txt +23 -0
- data/bridge/sdk-core/README.md +107 -0
- data/bridge/sdk-core/arch_docs/diagrams/README.md +10 -0
- data/bridge/sdk-core/arch_docs/diagrams/sticky_queues.puml +40 -0
- data/bridge/sdk-core/arch_docs/diagrams/workflow_internals.svg +1 -0
- data/bridge/sdk-core/arch_docs/sticky_queues.md +51 -0
- data/bridge/sdk-core/bridge-ffi/Cargo.toml +24 -0
- data/bridge/sdk-core/bridge-ffi/LICENSE.txt +23 -0
- data/bridge/sdk-core/bridge-ffi/build.rs +25 -0
- data/bridge/sdk-core/bridge-ffi/include/sdk-core-bridge.h +249 -0
- data/bridge/sdk-core/bridge-ffi/src/lib.rs +825 -0
- data/bridge/sdk-core/bridge-ffi/src/wrappers.rs +211 -0
- data/bridge/sdk-core/client/Cargo.toml +40 -0
- data/bridge/sdk-core/client/LICENSE.txt +23 -0
- data/bridge/sdk-core/client/src/lib.rs +1294 -0
- data/bridge/sdk-core/client/src/metrics.rs +165 -0
- data/bridge/sdk-core/client/src/raw.rs +931 -0
- data/bridge/sdk-core/client/src/retry.rs +674 -0
- data/bridge/sdk-core/client/src/workflow_handle/mod.rs +185 -0
- data/bridge/sdk-core/core/Cargo.toml +116 -0
- data/bridge/sdk-core/core/LICENSE.txt +23 -0
- data/bridge/sdk-core/core/benches/workflow_replay.rs +73 -0
- data/bridge/sdk-core/core/src/abstractions.rs +166 -0
- data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +911 -0
- data/bridge/sdk-core/core/src/core_tests/child_workflows.rs +221 -0
- data/bridge/sdk-core/core/src/core_tests/determinism.rs +107 -0
- data/bridge/sdk-core/core/src/core_tests/local_activities.rs +515 -0
- data/bridge/sdk-core/core/src/core_tests/mod.rs +100 -0
- data/bridge/sdk-core/core/src/core_tests/queries.rs +736 -0
- data/bridge/sdk-core/core/src/core_tests/replay_flag.rs +65 -0
- data/bridge/sdk-core/core/src/core_tests/workers.rs +259 -0
- data/bridge/sdk-core/core/src/core_tests/workflow_cancels.rs +124 -0
- data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +2070 -0
- data/bridge/sdk-core/core/src/ephemeral_server/mod.rs +515 -0
- data/bridge/sdk-core/core/src/lib.rs +175 -0
- data/bridge/sdk-core/core/src/log_export.rs +62 -0
- data/bridge/sdk-core/core/src/pollers/mod.rs +54 -0
- data/bridge/sdk-core/core/src/pollers/poll_buffer.rs +297 -0
- data/bridge/sdk-core/core/src/protosext/mod.rs +428 -0
- data/bridge/sdk-core/core/src/replay/mod.rs +71 -0
- data/bridge/sdk-core/core/src/retry_logic.rs +202 -0
- data/bridge/sdk-core/core/src/telemetry/metrics.rs +383 -0
- data/bridge/sdk-core/core/src/telemetry/mod.rs +412 -0
- data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +77 -0
- data/bridge/sdk-core/core/src/test_help/mod.rs +875 -0
- data/bridge/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +580 -0
- data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +1042 -0
- data/bridge/sdk-core/core/src/worker/activities.rs +464 -0
- data/bridge/sdk-core/core/src/worker/client/mocks.rs +87 -0
- data/bridge/sdk-core/core/src/worker/client.rs +347 -0
- data/bridge/sdk-core/core/src/worker/mod.rs +566 -0
- data/bridge/sdk-core/core/src/worker/workflow/bridge.rs +37 -0
- data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +110 -0
- data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +458 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +911 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +298 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +171 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +860 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +140 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +161 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +133 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +1448 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +342 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/mutable_side_effect_state_machine.rs +127 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +712 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/side_effect_state_machine.rs +71 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +443 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +439 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +169 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +246 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +96 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +1184 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +277 -0
- data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +198 -0
- data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +647 -0
- data/bridge/sdk-core/core/src/worker/workflow/mod.rs +1143 -0
- data/bridge/sdk-core/core/src/worker/workflow/run_cache.rs +145 -0
- data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +88 -0
- data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +940 -0
- data/bridge/sdk-core/core-api/Cargo.toml +31 -0
- data/bridge/sdk-core/core-api/LICENSE.txt +23 -0
- data/bridge/sdk-core/core-api/src/errors.rs +95 -0
- data/bridge/sdk-core/core-api/src/lib.rs +151 -0
- data/bridge/sdk-core/core-api/src/worker.rs +135 -0
- data/bridge/sdk-core/etc/deps.svg +187 -0
- data/bridge/sdk-core/etc/dynamic-config.yaml +2 -0
- data/bridge/sdk-core/etc/otel-collector-config.yaml +36 -0
- data/bridge/sdk-core/etc/prometheus.yaml +6 -0
- data/bridge/sdk-core/fsm/Cargo.toml +18 -0
- data/bridge/sdk-core/fsm/LICENSE.txt +23 -0
- data/bridge/sdk-core/fsm/README.md +3 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/Cargo.toml +27 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/LICENSE.txt +23 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +647 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/progress.rs +8 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.rs +18 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dupe_transitions_fail.stderr +12 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/dynamic_dest_pass.rs +41 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/forgot_name_fail.rs +14 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/forgot_name_fail.stderr +11 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/handler_arg_pass.rs +32 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/handler_pass.rs +31 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/medium_complex_pass.rs +46 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.rs +29 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +12 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/simple_pass.rs +32 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.rs +18 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/struct_event_variant_fail.stderr +5 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.rs +11 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_more_item_event_variant_fail.stderr +5 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.rs +11 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/tuple_zero_item_event_variant_fail.stderr +5 -0
- data/bridge/sdk-core/fsm/rustfsm_trait/Cargo.toml +14 -0
- data/bridge/sdk-core/fsm/rustfsm_trait/LICENSE.txt +23 -0
- data/bridge/sdk-core/fsm/rustfsm_trait/src/lib.rs +249 -0
- data/bridge/sdk-core/fsm/src/lib.rs +2 -0
- data/bridge/sdk-core/histories/fail_wf_task.bin +0 -0
- data/bridge/sdk-core/histories/timer_workflow_history.bin +0 -0
- data/bridge/sdk-core/integ-with-otel.sh +7 -0
- data/bridge/sdk-core/protos/api_upstream/README.md +9 -0
- data/bridge/sdk-core/protos/api_upstream/api-linter.yaml +40 -0
- data/bridge/sdk-core/protos/api_upstream/buf.yaml +12 -0
- data/bridge/sdk-core/protos/api_upstream/dependencies/gogoproto/gogo.proto +141 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +86 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/cluster/v1/message.proto +83 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +259 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +112 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +46 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/cluster.proto +40 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +57 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +55 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +168 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +97 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +51 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +50 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +41 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +60 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +59 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +51 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +122 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +108 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +114 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +56 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +751 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +97 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +161 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +99 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +61 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +55 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +300 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +108 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +46 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +59 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +145 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +1124 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +401 -0
- data/bridge/sdk-core/protos/grpc/health/v1/health.proto +63 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +78 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +79 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +210 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +77 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/common/common.proto +15 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +30 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +30 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +261 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +297 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +29 -0
- data/bridge/sdk-core/protos/testsrv_upstream/api-linter.yaml +38 -0
- data/bridge/sdk-core/protos/testsrv_upstream/buf.yaml +13 -0
- data/bridge/sdk-core/protos/testsrv_upstream/dependencies/gogoproto/gogo.proto +141 -0
- data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +63 -0
- data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +90 -0
- data/bridge/sdk-core/rustfmt.toml +1 -0
- data/bridge/sdk-core/sdk/Cargo.toml +47 -0
- data/bridge/sdk-core/sdk/LICENSE.txt +23 -0
- data/bridge/sdk-core/sdk/src/activity_context.rs +230 -0
- data/bridge/sdk-core/sdk/src/app_data.rs +37 -0
- data/bridge/sdk-core/sdk/src/conversions.rs +8 -0
- data/bridge/sdk-core/sdk/src/interceptors.rs +17 -0
- data/bridge/sdk-core/sdk/src/lib.rs +792 -0
- data/bridge/sdk-core/sdk/src/payload_converter.rs +11 -0
- data/bridge/sdk-core/sdk/src/workflow_context/options.rs +295 -0
- data/bridge/sdk-core/sdk/src/workflow_context.rs +683 -0
- data/bridge/sdk-core/sdk/src/workflow_future.rs +503 -0
- data/bridge/sdk-core/sdk-core-protos/Cargo.toml +30 -0
- data/bridge/sdk-core/sdk-core-protos/LICENSE.txt +23 -0
- data/bridge/sdk-core/sdk-core-protos/build.rs +108 -0
- data/bridge/sdk-core/sdk-core-protos/src/constants.rs +7 -0
- data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +497 -0
- data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +230 -0
- data/bridge/sdk-core/sdk-core-protos/src/lib.rs +1910 -0
- data/bridge/sdk-core/sdk-core-protos/src/task_token.rs +38 -0
- data/bridge/sdk-core/sdk-core-protos/src/utilities.rs +14 -0
- data/bridge/sdk-core/test-utils/Cargo.toml +35 -0
- data/bridge/sdk-core/test-utils/src/canned_histories.rs +1579 -0
- data/bridge/sdk-core/test-utils/src/histfetch.rs +28 -0
- data/bridge/sdk-core/test-utils/src/lib.rs +598 -0
- data/bridge/sdk-core/tests/integ_tests/client_tests.rs +36 -0
- data/bridge/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +128 -0
- data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +218 -0
- data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +146 -0
- data/bridge/sdk-core/tests/integ_tests/queries_tests.rs +437 -0
- data/bridge/sdk-core/tests/integ_tests/visibility_tests.rs +93 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/activities.rs +878 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/appdata_propagation.rs +61 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +59 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +58 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +50 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +60 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +54 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +634 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/patches.rs +113 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +137 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/resets.rs +93 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/signals.rs +167 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +99 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/timers.rs +131 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +75 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +587 -0
- data/bridge/sdk-core/tests/load_tests.rs +191 -0
- data/bridge/sdk-core/tests/main.rs +111 -0
- data/bridge/sdk-core/tests/runner.rs +93 -0
- data/bridge/src/connection.rs +167 -0
- data/bridge/src/lib.rs +180 -0
- data/bridge/src/runtime.rs +47 -0
- data/bridge/src/worker.rs +73 -0
- data/ext/Rakefile +9 -0
- data/lib/bridge.so +0 -0
- data/lib/gen/dependencies/gogoproto/gogo_pb.rb +14 -0
- data/lib/gen/temporal/api/batch/v1/message_pb.rb +48 -0
- data/lib/gen/temporal/api/cluster/v1/message_pb.rb +67 -0
- data/lib/gen/temporal/api/command/v1/message_pb.rb +166 -0
- data/lib/gen/temporal/api/common/v1/message_pb.rb +69 -0
- data/lib/gen/temporal/api/enums/v1/batch_operation_pb.rb +32 -0
- data/lib/gen/temporal/api/enums/v1/cluster_pb.rb +26 -0
- data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +37 -0
- data/lib/gen/temporal/api/enums/v1/common_pb.rb +41 -0
- data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +67 -0
- data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +71 -0
- data/lib/gen/temporal/api/enums/v1/namespace_pb.rb +37 -0
- data/lib/gen/temporal/api/enums/v1/query_pb.rb +31 -0
- data/lib/gen/temporal/api/enums/v1/reset_pb.rb +24 -0
- data/lib/gen/temporal/api/enums/v1/schedule_pb.rb +28 -0
- data/lib/gen/temporal/api/enums/v1/task_queue_pb.rb +30 -0
- data/lib/gen/temporal/api/enums/v1/update_pb.rb +28 -0
- data/lib/gen/temporal/api/enums/v1/workflow_pb.rb +89 -0
- data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +84 -0
- data/lib/gen/temporal/api/failure/v1/message_pb.rb +83 -0
- data/lib/gen/temporal/api/filter/v1/message_pb.rb +40 -0
- data/lib/gen/temporal/api/history/v1/message_pb.rb +489 -0
- data/lib/gen/temporal/api/namespace/v1/message_pb.rb +63 -0
- data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +125 -0
- data/lib/gen/temporal/api/operatorservice/v1/service_pb.rb +20 -0
- data/lib/gen/temporal/api/query/v1/message_pb.rb +38 -0
- data/lib/gen/temporal/api/replication/v1/message_pb.rb +37 -0
- data/lib/gen/temporal/api/schedule/v1/message_pb.rb +128 -0
- data/lib/gen/temporal/api/taskqueue/v1/message_pb.rb +73 -0
- data/lib/gen/temporal/api/update/v1/message_pb.rb +26 -0
- data/lib/gen/temporal/api/version/v1/message_pb.rb +41 -0
- data/lib/gen/temporal/api/workflow/v1/message_pb.rb +110 -0
- data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +771 -0
- data/lib/gen/temporal/api/workflowservice/v1/service_pb.rb +20 -0
- data/lib/gen/temporal/sdk/core/activity_result/activity_result_pb.rb +58 -0
- data/lib/gen/temporal/sdk/core/activity_task/activity_task_pb.rb +57 -0
- data/lib/gen/temporal/sdk/core/bridge/bridge_pb.rb +222 -0
- data/lib/gen/temporal/sdk/core/child_workflow/child_workflow_pb.rb +57 -0
- data/lib/gen/temporal/sdk/core/common/common_pb.rb +22 -0
- data/lib/gen/temporal/sdk/core/core_interface_pb.rb +34 -0
- data/lib/gen/temporal/sdk/core/external_data/external_data_pb.rb +27 -0
- data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +164 -0
- data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +192 -0
- data/lib/gen/temporal/sdk/core/workflow_completion/workflow_completion_pb.rb +34 -0
- data/lib/temporal/bridge.rb +14 -0
- data/lib/temporal/client/implementation.rb +339 -0
- data/lib/temporal/client/workflow_handle.rb +243 -0
- data/lib/temporal/client.rb +144 -0
- data/lib/temporal/connection.rb +736 -0
- data/lib/temporal/data_converter.rb +150 -0
- data/lib/temporal/error/failure.rb +194 -0
- data/lib/temporal/error/workflow_failure.rb +17 -0
- data/lib/temporal/errors.rb +22 -0
- data/lib/temporal/failure_converter/base.rb +26 -0
- data/lib/temporal/failure_converter/basic.rb +313 -0
- data/lib/temporal/failure_converter.rb +8 -0
- data/lib/temporal/interceptor/chain.rb +27 -0
- data/lib/temporal/interceptor/client.rb +102 -0
- data/lib/temporal/payload_codec/base.rb +32 -0
- data/lib/temporal/payload_converter/base.rb +24 -0
- data/lib/temporal/payload_converter/bytes.rb +26 -0
- data/lib/temporal/payload_converter/composite.rb +47 -0
- data/lib/temporal/payload_converter/encoding_base.rb +35 -0
- data/lib/temporal/payload_converter/json.rb +25 -0
- data/lib/temporal/payload_converter/nil.rb +25 -0
- data/lib/temporal/payload_converter.rb +14 -0
- data/lib/temporal/retry_policy.rb +82 -0
- data/lib/temporal/retry_state.rb +35 -0
- data/lib/temporal/runtime.rb +22 -0
- data/lib/temporal/timeout_type.rb +29 -0
- data/lib/temporal/version.rb +3 -0
- data/lib/temporal/workflow/execution_info.rb +54 -0
- data/lib/temporal/workflow/execution_status.rb +36 -0
- data/lib/temporal/workflow/id_reuse_policy.rb +36 -0
- data/lib/temporal/workflow/query_reject_condition.rb +33 -0
- data/lib/temporal.rb +8 -0
- data/lib/temporalio.rb +3 -0
- data/lib/thermite_patch.rb +23 -0
- data/temporalio.gemspec +41 -0
- metadata +583 -0
@@ -0,0 +1,587 @@
|
|
1
|
+
mod activities;
|
2
|
+
mod appdata_propagation;
|
3
|
+
mod cancel_external;
|
4
|
+
mod cancel_wf;
|
5
|
+
mod child_workflows;
|
6
|
+
mod continue_as_new;
|
7
|
+
mod determinism;
|
8
|
+
mod local_activities;
|
9
|
+
mod patches;
|
10
|
+
mod replay;
|
11
|
+
mod resets;
|
12
|
+
mod signals;
|
13
|
+
mod stickyness;
|
14
|
+
mod timers;
|
15
|
+
mod upsert_search_attrs;
|
16
|
+
|
17
|
+
use assert_matches::assert_matches;
|
18
|
+
use futures::{channel::mpsc::UnboundedReceiver, future, SinkExt, StreamExt};
|
19
|
+
use std::{
|
20
|
+
collections::HashMap,
|
21
|
+
sync::{
|
22
|
+
atomic::{AtomicUsize, Ordering},
|
23
|
+
Arc,
|
24
|
+
},
|
25
|
+
time::Duration,
|
26
|
+
};
|
27
|
+
use temporal_client::{WorkflowClientTrait, WorkflowOptions};
|
28
|
+
use temporal_sdk::{
|
29
|
+
interceptors::WorkerInterceptor, ActContext, ActivityOptions, WfContext, WorkflowResult,
|
30
|
+
};
|
31
|
+
use temporal_sdk_core_api::{errors::PollWfError, Worker};
|
32
|
+
use temporal_sdk_core_protos::{
|
33
|
+
coresdk::{
|
34
|
+
activity_result::ActivityExecutionResult,
|
35
|
+
workflow_activation::{workflow_activation_job, WorkflowActivation, WorkflowActivationJob},
|
36
|
+
workflow_commands::{ActivityCancellationType, FailWorkflowExecution, StartTimer},
|
37
|
+
workflow_completion::WorkflowActivationCompletion,
|
38
|
+
ActivityTaskCompletion, AsJsonPayloadExt, IntoCompletion,
|
39
|
+
},
|
40
|
+
temporal::api::failure::v1::Failure,
|
41
|
+
};
|
42
|
+
use temporal_sdk_core_test_utils::{
|
43
|
+
history_from_proto_binary, init_core_and_create_wf, init_core_replay_preloaded,
|
44
|
+
schedule_activity_cmd, CoreWfStarter, WorkerTestHelpers,
|
45
|
+
};
|
46
|
+
use tokio::time::sleep;
|
47
|
+
use uuid::Uuid;
|
48
|
+
|
49
|
+
// TODO: We should get expected histories for these tests and confirm that the history at the end
|
50
|
+
// matches.
|
51
|
+
|
52
|
+
#[tokio::test]
|
53
|
+
async fn parallel_workflows_same_queue() {
|
54
|
+
let mut starter = CoreWfStarter::new("parallel_workflows_same_queue");
|
55
|
+
let core = starter.get_worker().await;
|
56
|
+
let num_workflows = 25usize;
|
57
|
+
|
58
|
+
let run_ids: Vec<_> = future::join_all(
|
59
|
+
(0..num_workflows)
|
60
|
+
.map(|i| starter.start_wf_with_id(format!("wf-id-{}", i), WorkflowOptions::default())),
|
61
|
+
)
|
62
|
+
.await;
|
63
|
+
|
64
|
+
let mut send_chans = HashMap::new();
|
65
|
+
async fn wf_task(
|
66
|
+
worker: Arc<dyn Worker>,
|
67
|
+
mut task_chan: UnboundedReceiver<WorkflowActivation>,
|
68
|
+
) {
|
69
|
+
let task = task_chan.next().await.unwrap();
|
70
|
+
assert_matches!(
|
71
|
+
task.jobs.as_slice(),
|
72
|
+
[WorkflowActivationJob {
|
73
|
+
variant: Some(workflow_activation_job::Variant::StartWorkflow(_)),
|
74
|
+
}]
|
75
|
+
);
|
76
|
+
worker
|
77
|
+
.complete_timer(&task.run_id, 1, Duration::from_secs(1))
|
78
|
+
.await;
|
79
|
+
let task = task_chan.next().await.unwrap();
|
80
|
+
worker.complete_execution(&task.run_id).await;
|
81
|
+
}
|
82
|
+
|
83
|
+
let handles: Vec<_> = run_ids
|
84
|
+
.iter()
|
85
|
+
.map(|run_id| {
|
86
|
+
let (tx, rx) = futures::channel::mpsc::unbounded();
|
87
|
+
send_chans.insert(run_id.clone(), tx);
|
88
|
+
tokio::spawn(wf_task(core.clone(), rx))
|
89
|
+
})
|
90
|
+
.collect();
|
91
|
+
|
92
|
+
for _ in 0..num_workflows * 2 {
|
93
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
94
|
+
send_chans
|
95
|
+
.get(&task.run_id)
|
96
|
+
.unwrap()
|
97
|
+
.send(task)
|
98
|
+
.await
|
99
|
+
.unwrap();
|
100
|
+
}
|
101
|
+
|
102
|
+
for handle in handles {
|
103
|
+
handle.await.unwrap()
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
static RUN_CT: AtomicUsize = AtomicUsize::new(0);
|
108
|
+
pub async fn cache_evictions_wf(command_sink: WfContext) -> WorkflowResult<()> {
|
109
|
+
RUN_CT.fetch_add(1, Ordering::SeqCst);
|
110
|
+
command_sink.timer(Duration::from_secs(1)).await;
|
111
|
+
Ok(().into())
|
112
|
+
}
|
113
|
+
|
114
|
+
#[tokio::test]
|
115
|
+
async fn workflow_lru_cache_evictions() {
|
116
|
+
let wf_type = "workflow_lru_cache_evictions";
|
117
|
+
let mut starter = CoreWfStarter::new(wf_type);
|
118
|
+
starter.max_cached_workflows(1);
|
119
|
+
let mut worker = starter.worker().await;
|
120
|
+
worker.register_wf(wf_type.to_string(), cache_evictions_wf);
|
121
|
+
|
122
|
+
let n_workflows = 3;
|
123
|
+
for _ in 0..n_workflows {
|
124
|
+
worker
|
125
|
+
.submit_wf(
|
126
|
+
format!("wce-{}", Uuid::new_v4()),
|
127
|
+
wf_type.to_string(),
|
128
|
+
vec![],
|
129
|
+
WorkflowOptions::default(),
|
130
|
+
)
|
131
|
+
.await
|
132
|
+
.unwrap();
|
133
|
+
}
|
134
|
+
struct CacheAsserter;
|
135
|
+
#[async_trait::async_trait(?Send)]
|
136
|
+
impl WorkerInterceptor for CacheAsserter {
|
137
|
+
async fn on_workflow_activation_completion(&self, _: &WorkflowActivationCompletion) {}
|
138
|
+
fn on_shutdown(&self, sdk_worker: &temporal_sdk::Worker) {
|
139
|
+
// 0 since the sdk worker force-evicts and drains everything on shutdown.
|
140
|
+
assert_eq!(sdk_worker.cached_workflows(), 0);
|
141
|
+
}
|
142
|
+
}
|
143
|
+
worker
|
144
|
+
.run_until_done_intercepted(Some(CacheAsserter))
|
145
|
+
.await
|
146
|
+
.unwrap();
|
147
|
+
// The wf must have started more than # workflows times, since all but one must experience
|
148
|
+
// an eviction
|
149
|
+
assert!(RUN_CT.load(Ordering::SeqCst) > n_workflows);
|
150
|
+
}
|
151
|
+
|
152
|
+
// Ideally this would be a unit test, but returning a pending future with mockall bloats the mock
|
153
|
+
// code a bunch and just isn't worth it. Do it when https://github.com/asomers/mockall/issues/189 is
|
154
|
+
// fixed.
|
155
|
+
#[tokio::test]
|
156
|
+
async fn shutdown_aborts_actively_blocked_poll() {
|
157
|
+
let mut starter = CoreWfStarter::new("shutdown_aborts_actively_blocked_poll");
|
158
|
+
let core = starter.get_worker().await;
|
159
|
+
// Begin the poll, and request shutdown from another thread after a small period of time.
|
160
|
+
let tcore = core.clone();
|
161
|
+
let handle = tokio::spawn(async move {
|
162
|
+
std::thread::sleep(Duration::from_millis(100));
|
163
|
+
tcore.shutdown().await;
|
164
|
+
});
|
165
|
+
assert_matches!(
|
166
|
+
core.poll_workflow_activation().await.unwrap_err(),
|
167
|
+
PollWfError::ShutDown
|
168
|
+
);
|
169
|
+
handle.await.unwrap();
|
170
|
+
// Ensure double-shutdown doesn't explode
|
171
|
+
core.shutdown().await;
|
172
|
+
assert_matches!(
|
173
|
+
core.poll_workflow_activation().await.unwrap_err(),
|
174
|
+
PollWfError::ShutDown
|
175
|
+
);
|
176
|
+
}
|
177
|
+
|
178
|
+
#[rstest::rstest]
|
179
|
+
#[tokio::test]
|
180
|
+
async fn fail_wf_task(#[values(true, false)] replay: bool) {
|
181
|
+
let core = if replay {
|
182
|
+
let (core, _) = init_core_replay_preloaded(
|
183
|
+
"fail_wf_task",
|
184
|
+
&history_from_proto_binary("histories/fail_wf_task.bin")
|
185
|
+
.await
|
186
|
+
.unwrap(),
|
187
|
+
);
|
188
|
+
core
|
189
|
+
} else {
|
190
|
+
let mut starter = init_core_and_create_wf("fail_wf_task").await;
|
191
|
+
starter.get_worker().await
|
192
|
+
};
|
193
|
+
// Start with a timer
|
194
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
195
|
+
core.complete_timer(&task.run_id, 0, Duration::from_millis(200))
|
196
|
+
.await;
|
197
|
+
|
198
|
+
// Then break for whatever reason
|
199
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
200
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::fail(
|
201
|
+
task.run_id,
|
202
|
+
Failure::application_failure("I did an oopsie".to_string(), false),
|
203
|
+
))
|
204
|
+
.await
|
205
|
+
.unwrap();
|
206
|
+
|
207
|
+
// The server will want to retry the task. This time we finish the workflow -- but we need
|
208
|
+
// to poll a couple of times as there will be more than one required workflow activation.
|
209
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
210
|
+
// The first poll response will tell us to evict
|
211
|
+
assert_matches!(
|
212
|
+
task.jobs.as_slice(),
|
213
|
+
[WorkflowActivationJob {
|
214
|
+
variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
|
215
|
+
}]
|
216
|
+
);
|
217
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(task.run_id))
|
218
|
+
.await
|
219
|
+
.unwrap();
|
220
|
+
|
221
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
222
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
223
|
+
task.run_id,
|
224
|
+
vec![StartTimer {
|
225
|
+
seq: 0,
|
226
|
+
start_to_fire_timeout: Some(prost_dur!(from_millis(200))),
|
227
|
+
}
|
228
|
+
.into()],
|
229
|
+
))
|
230
|
+
.await
|
231
|
+
.unwrap();
|
232
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
233
|
+
core.complete_execution(&task.run_id).await;
|
234
|
+
}
|
235
|
+
|
236
|
+
#[tokio::test]
|
237
|
+
async fn fail_workflow_execution() {
|
238
|
+
let core = init_core_and_create_wf("fail_workflow_execution")
|
239
|
+
.await
|
240
|
+
.get_worker()
|
241
|
+
.await;
|
242
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
243
|
+
core.complete_timer(&task.run_id, 0, Duration::from_secs(1))
|
244
|
+
.await;
|
245
|
+
let task = core.poll_workflow_activation().await.unwrap();
|
246
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
247
|
+
task.run_id,
|
248
|
+
vec![FailWorkflowExecution {
|
249
|
+
failure: Some(Failure::application_failure("I'm ded".to_string(), false)),
|
250
|
+
}
|
251
|
+
.into()],
|
252
|
+
))
|
253
|
+
.await
|
254
|
+
.unwrap();
|
255
|
+
}
|
256
|
+
|
257
|
+
#[tokio::test]
|
258
|
+
async fn signal_workflow() {
|
259
|
+
let mut starter = init_core_and_create_wf("signal_workflow").await;
|
260
|
+
let core = starter.get_worker().await;
|
261
|
+
let client = starter.get_client().await;
|
262
|
+
let workflow_id = starter.get_task_queue().to_string();
|
263
|
+
|
264
|
+
let signal_id_1 = "signal1";
|
265
|
+
let signal_id_2 = "signal2";
|
266
|
+
let res = core.poll_workflow_activation().await.unwrap();
|
267
|
+
// Task is completed with no commands
|
268
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
269
|
+
res.run_id.clone(),
|
270
|
+
vec![],
|
271
|
+
))
|
272
|
+
.await
|
273
|
+
.unwrap();
|
274
|
+
|
275
|
+
// Send the signals to the server
|
276
|
+
client
|
277
|
+
.signal_workflow_execution(
|
278
|
+
workflow_id.to_string(),
|
279
|
+
res.run_id.to_string(),
|
280
|
+
signal_id_1.to_string(),
|
281
|
+
None,
|
282
|
+
None,
|
283
|
+
)
|
284
|
+
.await
|
285
|
+
.unwrap();
|
286
|
+
client
|
287
|
+
.signal_workflow_execution(
|
288
|
+
workflow_id.to_string(),
|
289
|
+
res.run_id.to_string(),
|
290
|
+
signal_id_2.to_string(),
|
291
|
+
None,
|
292
|
+
None,
|
293
|
+
)
|
294
|
+
.await
|
295
|
+
.unwrap();
|
296
|
+
|
297
|
+
let mut res = core.poll_workflow_activation().await.unwrap();
|
298
|
+
// Sometimes both signals are complete at once, sometimes only one, depending on server
|
299
|
+
// Converting test to wf function type would make this shorter
|
300
|
+
if res.jobs.len() == 2 {
|
301
|
+
assert_matches!(
|
302
|
+
res.jobs.as_slice(),
|
303
|
+
[
|
304
|
+
WorkflowActivationJob {
|
305
|
+
variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
|
306
|
+
},
|
307
|
+
WorkflowActivationJob {
|
308
|
+
variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
|
309
|
+
}
|
310
|
+
]
|
311
|
+
);
|
312
|
+
} else if res.jobs.len() == 1 {
|
313
|
+
assert_matches!(
|
314
|
+
res.jobs.as_slice(),
|
315
|
+
[WorkflowActivationJob {
|
316
|
+
variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
|
317
|
+
},]
|
318
|
+
);
|
319
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
320
|
+
res.run_id,
|
321
|
+
vec![],
|
322
|
+
))
|
323
|
+
.await
|
324
|
+
.unwrap();
|
325
|
+
res = core.poll_workflow_activation().await.unwrap();
|
326
|
+
assert_matches!(
|
327
|
+
res.jobs.as_slice(),
|
328
|
+
[WorkflowActivationJob {
|
329
|
+
variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
|
330
|
+
},]
|
331
|
+
);
|
332
|
+
}
|
333
|
+
core.complete_execution(&res.run_id).await;
|
334
|
+
}
|
335
|
+
|
336
|
+
#[tokio::test]
|
337
|
+
async fn signal_workflow_signal_not_handled_on_workflow_completion() {
|
338
|
+
let mut starter =
|
339
|
+
init_core_and_create_wf("signal_workflow_signal_not_handled_on_workflow_completion").await;
|
340
|
+
let core = starter.get_worker().await;
|
341
|
+
let workflow_id = starter.get_task_queue().to_string();
|
342
|
+
let signal_id_1 = "signal1";
|
343
|
+
for i in 1..=2 {
|
344
|
+
let res = core.poll_workflow_activation().await.unwrap();
|
345
|
+
// Task is completed with a timer
|
346
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
347
|
+
res.run_id,
|
348
|
+
vec![StartTimer {
|
349
|
+
seq: 0,
|
350
|
+
start_to_fire_timeout: Some(prost_dur!(from_millis(10))),
|
351
|
+
}
|
352
|
+
.into()],
|
353
|
+
))
|
354
|
+
.await
|
355
|
+
.unwrap();
|
356
|
+
|
357
|
+
let res = core.poll_workflow_activation().await.unwrap();
|
358
|
+
|
359
|
+
if i == 1 {
|
360
|
+
// First attempt we should only see the timer being fired
|
361
|
+
assert_matches!(
|
362
|
+
res.jobs.as_slice(),
|
363
|
+
[WorkflowActivationJob {
|
364
|
+
variant: Some(workflow_activation_job::Variant::FireTimer(_)),
|
365
|
+
}]
|
366
|
+
);
|
367
|
+
|
368
|
+
let run_id = res.run_id.clone();
|
369
|
+
|
370
|
+
// Send the signal to the server
|
371
|
+
starter
|
372
|
+
.get_client()
|
373
|
+
.await
|
374
|
+
.signal_workflow_execution(
|
375
|
+
workflow_id.clone(),
|
376
|
+
res.run_id.to_string(),
|
377
|
+
signal_id_1.to_string(),
|
378
|
+
None,
|
379
|
+
None,
|
380
|
+
)
|
381
|
+
.await
|
382
|
+
.unwrap();
|
383
|
+
|
384
|
+
// Send completion - not having seen a poll response with a signal in it yet (unhandled
|
385
|
+
// command error will be logged as a warning and an eviction will be issued)
|
386
|
+
core.complete_execution(&run_id).await;
|
387
|
+
|
388
|
+
// We should be told to evict
|
389
|
+
let res = core.poll_workflow_activation().await.unwrap();
|
390
|
+
assert_matches!(
|
391
|
+
res.jobs.as_slice(),
|
392
|
+
[WorkflowActivationJob {
|
393
|
+
variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
|
394
|
+
}]
|
395
|
+
);
|
396
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(res.run_id))
|
397
|
+
.await
|
398
|
+
.unwrap();
|
399
|
+
// Loop to the top to handle wf from the beginning
|
400
|
+
continue;
|
401
|
+
}
|
402
|
+
|
403
|
+
// On the second attempt, we will see the signal we failed to handle as well as the timer
|
404
|
+
assert_matches!(
|
405
|
+
res.jobs.as_slice(),
|
406
|
+
[
|
407
|
+
WorkflowActivationJob {
|
408
|
+
variant: Some(workflow_activation_job::Variant::FireTimer(_)),
|
409
|
+
},
|
410
|
+
WorkflowActivationJob {
|
411
|
+
variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
|
412
|
+
}
|
413
|
+
]
|
414
|
+
);
|
415
|
+
core.complete_execution(&res.run_id).await;
|
416
|
+
}
|
417
|
+
}
|
418
|
+
|
419
|
+
#[tokio::test]
|
420
|
+
async fn wft_timeout_doesnt_create_unsolvable_autocomplete() {
|
421
|
+
let activity_id = "act-1";
|
422
|
+
let signal_at_start = "at-start";
|
423
|
+
let signal_at_complete = "at-complete";
|
424
|
+
let mut wf_starter = CoreWfStarter::new("wft_timeout_doesnt_create_unsolvable_autocomplete");
|
425
|
+
wf_starter
|
426
|
+
// Test needs eviction on and a short timeout
|
427
|
+
.max_cached_workflows(0)
|
428
|
+
.max_wft(1)
|
429
|
+
.wft_timeout(Duration::from_secs(1));
|
430
|
+
let core = wf_starter.get_worker().await;
|
431
|
+
let client = wf_starter.get_client().await;
|
432
|
+
let task_q = wf_starter.get_task_queue();
|
433
|
+
let wf_id = &wf_starter.get_wf_id().to_owned();
|
434
|
+
|
435
|
+
// Set up some helpers for polling and completing
|
436
|
+
let poll_sched_act = || async {
|
437
|
+
let wf_task = core.poll_workflow_activation().await.unwrap();
|
438
|
+
core.complete_workflow_activation(
|
439
|
+
schedule_activity_cmd(
|
440
|
+
0,
|
441
|
+
task_q,
|
442
|
+
activity_id,
|
443
|
+
ActivityCancellationType::TryCancel,
|
444
|
+
Duration::from_secs(60),
|
445
|
+
Duration::from_secs(60),
|
446
|
+
)
|
447
|
+
.into_completion(wf_task.run_id.clone()),
|
448
|
+
)
|
449
|
+
.await
|
450
|
+
.unwrap();
|
451
|
+
wf_task
|
452
|
+
};
|
453
|
+
wf_starter.start_wf().await;
|
454
|
+
|
455
|
+
// Poll and schedule the activity
|
456
|
+
let wf_task = poll_sched_act().await;
|
457
|
+
// Before polling for a task again, we start and complete the activity and send the
|
458
|
+
// corresponding signals.
|
459
|
+
let ac_task = core.poll_activity_task().await.unwrap();
|
460
|
+
let rid = wf_task.run_id.clone();
|
461
|
+
// Send the signals to the server & resolve activity -- sometimes this happens too fast
|
462
|
+
sleep(Duration::from_millis(200)).await;
|
463
|
+
client
|
464
|
+
.signal_workflow_execution(
|
465
|
+
wf_id.to_string(),
|
466
|
+
rid,
|
467
|
+
signal_at_start.to_string(),
|
468
|
+
None,
|
469
|
+
None,
|
470
|
+
)
|
471
|
+
.await
|
472
|
+
.unwrap();
|
473
|
+
// Complete activity successfully.
|
474
|
+
core.complete_activity_task(ActivityTaskCompletion {
|
475
|
+
task_token: ac_task.task_token,
|
476
|
+
result: Some(ActivityExecutionResult::ok(Default::default())),
|
477
|
+
})
|
478
|
+
.await
|
479
|
+
.unwrap();
|
480
|
+
let rid = wf_task.run_id.clone();
|
481
|
+
client
|
482
|
+
.signal_workflow_execution(
|
483
|
+
wf_id.to_string(),
|
484
|
+
rid,
|
485
|
+
signal_at_complete.to_string(),
|
486
|
+
None,
|
487
|
+
None,
|
488
|
+
)
|
489
|
+
.await
|
490
|
+
.unwrap();
|
491
|
+
// Now poll again, it will be an eviction b/c non-sticky mode.
|
492
|
+
let wf_task = core.poll_workflow_activation().await.unwrap();
|
493
|
+
assert_matches!(
|
494
|
+
wf_task.jobs.as_slice(),
|
495
|
+
[WorkflowActivationJob {
|
496
|
+
variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
|
497
|
+
}]
|
498
|
+
);
|
499
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
|
500
|
+
.await
|
501
|
+
.unwrap();
|
502
|
+
// Start from the beginning
|
503
|
+
poll_sched_act().await;
|
504
|
+
let wf_task = core.poll_workflow_activation().await.unwrap();
|
505
|
+
// Time out this time
|
506
|
+
sleep(Duration::from_secs(2)).await;
|
507
|
+
// Poll again, which should not have any work to do and spin, until the complete goes through.
|
508
|
+
// Which will be rejected with not found, producing an eviction.
|
509
|
+
let (wf_task, _) = tokio::join!(
|
510
|
+
async { core.poll_workflow_activation().await.unwrap() },
|
511
|
+
async {
|
512
|
+
sleep(Duration::from_millis(500)).await;
|
513
|
+
// Reply to the first one, finally
|
514
|
+
core.complete_execution(&wf_task.run_id).await;
|
515
|
+
}
|
516
|
+
);
|
517
|
+
assert_matches!(
|
518
|
+
wf_task.jobs.as_slice(),
|
519
|
+
[WorkflowActivationJob {
|
520
|
+
variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
|
521
|
+
}]
|
522
|
+
);
|
523
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
|
524
|
+
.await
|
525
|
+
.unwrap();
|
526
|
+
// Do it all over again, without timing out this time
|
527
|
+
poll_sched_act().await;
|
528
|
+
let wf_task = core.poll_workflow_activation().await.unwrap();
|
529
|
+
// Server can sometimes arbitrarily re-order the activity complete to be after the second signal
|
530
|
+
// Seeing 3 jobs is enough info.
|
531
|
+
assert_eq!(wf_task.jobs.len(), 3);
|
532
|
+
core.complete_execution(&wf_task.run_id).await;
|
533
|
+
}
|
534
|
+
|
535
|
+
/// We had a bug related to polling being faster than completion causing issues with cache
|
536
|
+
/// overflow. This test intentionally makes completes slower than polls to evaluate that.
|
537
|
+
///
|
538
|
+
/// It's expected that this test may generate some task timeouts.
|
539
|
+
#[tokio::test]
|
540
|
+
async fn slow_completes_with_small_cache() {
|
541
|
+
let wf_name = "slow_completes_with_small_cache";
|
542
|
+
let mut starter = CoreWfStarter::new(wf_name);
|
543
|
+
starter.max_wft(5).max_cached_workflows(5);
|
544
|
+
let mut worker = starter.worker().await;
|
545
|
+
worker.register_wf(wf_name.to_owned(), |ctx: WfContext| async move {
|
546
|
+
for _ in 0..3 {
|
547
|
+
ctx.activity(ActivityOptions {
|
548
|
+
activity_type: "echo_activity".to_string(),
|
549
|
+
start_to_close_timeout: Some(Duration::from_secs(5)),
|
550
|
+
input: "hi!".as_json_payload().expect("serializes fine"),
|
551
|
+
..Default::default()
|
552
|
+
})
|
553
|
+
.await;
|
554
|
+
ctx.timer(Duration::from_secs(1)).await;
|
555
|
+
}
|
556
|
+
Ok(().into())
|
557
|
+
});
|
558
|
+
worker.register_activity(
|
559
|
+
"echo_activity",
|
560
|
+
|_ctx: ActContext, echo_me: String| async move { Ok(echo_me) },
|
561
|
+
);
|
562
|
+
for i in 0..20 {
|
563
|
+
worker
|
564
|
+
.submit_wf(
|
565
|
+
format!("{}_{}", wf_name, i),
|
566
|
+
wf_name.to_owned(),
|
567
|
+
vec![],
|
568
|
+
WorkflowOptions::default(),
|
569
|
+
)
|
570
|
+
.await
|
571
|
+
.unwrap();
|
572
|
+
}
|
573
|
+
|
574
|
+
struct SlowCompleter {}
|
575
|
+
#[async_trait::async_trait(?Send)]
|
576
|
+
impl WorkerInterceptor for SlowCompleter {
|
577
|
+
async fn on_workflow_activation_completion(&self, _: &WorkflowActivationCompletion) {
|
578
|
+
// They don't need to be much slower
|
579
|
+
tokio::time::sleep(Duration::from_millis(100)).await;
|
580
|
+
}
|
581
|
+
fn on_shutdown(&self, _: &temporal_sdk::Worker) {}
|
582
|
+
}
|
583
|
+
worker
|
584
|
+
.run_until_done_intercepted(Some(SlowCompleter {}))
|
585
|
+
.await
|
586
|
+
.unwrap();
|
587
|
+
}
|