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,110 @@
|
|
1
|
+
use crate::worker::workflow::{WFCommand, WorkflowStartedInfo};
|
2
|
+
use temporal_sdk_core_protos::{
|
3
|
+
coresdk::workflow_activation::{
|
4
|
+
start_workflow_from_attribs, workflow_activation_job, CancelWorkflow, SignalWorkflow,
|
5
|
+
WorkflowActivationJob,
|
6
|
+
},
|
7
|
+
temporal::api::history::v1::WorkflowExecutionStartedEventAttributes,
|
8
|
+
utilities::TryIntoOrNone,
|
9
|
+
};
|
10
|
+
|
11
|
+
/// Abstracts away the concept of an actual workflow implementation, handling sending it new
|
12
|
+
/// jobs and fetching output from it.
|
13
|
+
pub struct DrivenWorkflow {
|
14
|
+
started_attrs: Option<WorkflowStartedInfo>,
|
15
|
+
fetcher: Box<dyn WorkflowFetcher>,
|
16
|
+
/// Outgoing activation jobs that need to be sent to the lang sdk
|
17
|
+
outgoing_wf_activation_jobs: Vec<workflow_activation_job::Variant>,
|
18
|
+
}
|
19
|
+
|
20
|
+
impl<WF> From<Box<WF>> for DrivenWorkflow
|
21
|
+
where
|
22
|
+
WF: WorkflowFetcher + 'static,
|
23
|
+
{
|
24
|
+
fn from(wf: Box<WF>) -> Self {
|
25
|
+
Self {
|
26
|
+
started_attrs: None,
|
27
|
+
fetcher: wf,
|
28
|
+
outgoing_wf_activation_jobs: Default::default(),
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
impl DrivenWorkflow {
|
34
|
+
/// Start the workflow
|
35
|
+
pub fn start(
|
36
|
+
&mut self,
|
37
|
+
workflow_id: String,
|
38
|
+
randomness_seed: u64,
|
39
|
+
attribs: WorkflowExecutionStartedEventAttributes,
|
40
|
+
) {
|
41
|
+
debug!(run_id = %attribs.original_execution_run_id, "Driven WF start");
|
42
|
+
let started_info = WorkflowStartedInfo {
|
43
|
+
workflow_task_timeout: attribs.workflow_task_timeout.clone().try_into_or_none(),
|
44
|
+
workflow_execution_timeout: attribs
|
45
|
+
.workflow_execution_timeout
|
46
|
+
.clone()
|
47
|
+
.try_into_or_none(),
|
48
|
+
memo: attribs.memo.clone(),
|
49
|
+
search_attrs: attribs.search_attributes.clone(),
|
50
|
+
retry_policy: attribs.retry_policy.clone(),
|
51
|
+
};
|
52
|
+
self.send_job(start_workflow_from_attribs(attribs, workflow_id, randomness_seed).into());
|
53
|
+
self.started_attrs = Some(started_info);
|
54
|
+
}
|
55
|
+
|
56
|
+
/// Return the attributes from the workflow execution started event if this workflow has started
|
57
|
+
pub fn get_started_info(&self) -> Option<&WorkflowStartedInfo> {
|
58
|
+
self.started_attrs.as_ref()
|
59
|
+
}
|
60
|
+
|
61
|
+
/// Enqueue a new job to be sent to the driven workflow
|
62
|
+
pub fn send_job(&mut self, job: workflow_activation_job::Variant) {
|
63
|
+
self.outgoing_wf_activation_jobs.push(job);
|
64
|
+
}
|
65
|
+
|
66
|
+
/// Observe pending jobs
|
67
|
+
pub fn peek_pending_jobs(&self) -> &[workflow_activation_job::Variant] {
|
68
|
+
self.outgoing_wf_activation_jobs.as_slice()
|
69
|
+
}
|
70
|
+
|
71
|
+
/// Drain all pending jobs, so that they may be sent to the driven workflow
|
72
|
+
pub fn drain_jobs(&mut self) -> Vec<WorkflowActivationJob> {
|
73
|
+
self.outgoing_wf_activation_jobs
|
74
|
+
.drain(..)
|
75
|
+
.map(Into::into)
|
76
|
+
.collect()
|
77
|
+
}
|
78
|
+
|
79
|
+
/// Signal the workflow
|
80
|
+
pub fn signal(&mut self, signal: SignalWorkflow) {
|
81
|
+
self.send_job(workflow_activation_job::Variant::SignalWorkflow(signal));
|
82
|
+
}
|
83
|
+
|
84
|
+
/// Cancel the workflow
|
85
|
+
pub fn cancel(&mut self, attribs: CancelWorkflow) {
|
86
|
+
self.send_job(workflow_activation_job::Variant::CancelWorkflow(attribs));
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
#[async_trait::async_trait]
|
91
|
+
impl WorkflowFetcher for DrivenWorkflow {
|
92
|
+
async fn fetch_workflow_iteration_output(&mut self) -> Vec<WFCommand> {
|
93
|
+
self.fetcher.fetch_workflow_iteration_output().await
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
/// Implementors of this trait represent a way to fetch output from executing/iterating some
|
98
|
+
/// workflow code (or a mocked workflow).
|
99
|
+
#[async_trait::async_trait]
|
100
|
+
pub trait WorkflowFetcher: Send {
|
101
|
+
/// Obtain any output from the workflow's recent execution(s). Because the lang sdk is
|
102
|
+
/// responsible for calling workflow code as a result of receiving tasks from
|
103
|
+
/// [crate::Core::poll_task], we cannot directly iterate it here. Thus implementations of this
|
104
|
+
/// trait are expected to either buffer output or otherwise produce it on demand when this
|
105
|
+
/// function is called.
|
106
|
+
///
|
107
|
+
/// In the case of the real [WorkflowBridge] implementation, commands are simply pulled from
|
108
|
+
/// a buffer that the language side sinks into when it calls [crate::Core::complete_task]
|
109
|
+
async fn fetch_workflow_iteration_output(&mut self) -> Vec<WFCommand>;
|
110
|
+
}
|
@@ -0,0 +1,458 @@
|
|
1
|
+
use crate::{
|
2
|
+
replay::{HistoryInfo, TestHistoryBuilder},
|
3
|
+
worker::client::WorkerClient,
|
4
|
+
};
|
5
|
+
use futures::{future::BoxFuture, stream, stream::BoxStream, FutureExt, Stream, StreamExt};
|
6
|
+
use std::{
|
7
|
+
collections::VecDeque,
|
8
|
+
fmt::Debug,
|
9
|
+
future::Future,
|
10
|
+
pin::Pin,
|
11
|
+
sync::Arc,
|
12
|
+
task::{Context, Poll},
|
13
|
+
};
|
14
|
+
use temporal_sdk_core_protos::temporal::api::{
|
15
|
+
enums::v1::EventType,
|
16
|
+
history::v1::{History, HistoryEvent},
|
17
|
+
workflowservice::v1::GetWorkflowExecutionHistoryResponse,
|
18
|
+
};
|
19
|
+
use tracing::Instrument;
|
20
|
+
|
21
|
+
/// A slimmed down version of a poll workflow task response which includes just the info needed
|
22
|
+
/// by [WorkflowManager]. History events are expected to be consumed from it and applied to the
|
23
|
+
/// state machines.
|
24
|
+
pub struct HistoryUpdate {
|
25
|
+
events: BoxStream<'static, Result<HistoryEvent, tonic::Status>>,
|
26
|
+
/// It is useful to be able to look ahead up to one workflow task beyond the currently
|
27
|
+
/// requested one. The initial (possibly only) motivation for this being to be able to
|
28
|
+
/// pre-emptively notify lang about patch markers so that calls to `changed` do not need to
|
29
|
+
/// be async.
|
30
|
+
buffered: VecDeque<HistoryEvent>,
|
31
|
+
pub previous_started_event_id: i64,
|
32
|
+
}
|
33
|
+
impl Debug for HistoryUpdate {
|
34
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
35
|
+
write!(
|
36
|
+
f,
|
37
|
+
"HistoryUpdate(previous_started_event_id: {})",
|
38
|
+
self.previous_started_event_id
|
39
|
+
)
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
pub struct HistoryPaginator {
|
44
|
+
// Potentially this could actually be a ref w/ lifetime here
|
45
|
+
client: Arc<dyn WorkerClient>,
|
46
|
+
event_queue: VecDeque<HistoryEvent>,
|
47
|
+
wf_id: String,
|
48
|
+
run_id: String,
|
49
|
+
next_page_token: NextPageToken,
|
50
|
+
open_history_request:
|
51
|
+
Option<BoxFuture<'static, Result<GetWorkflowExecutionHistoryResponse, tonic::Status>>>,
|
52
|
+
/// These are events that should be returned once pagination has finished. This only happens
|
53
|
+
/// during cache misses, where we got a partial task but need to fetch history from the start.
|
54
|
+
/// We use this to apply any
|
55
|
+
final_events: Vec<HistoryEvent>,
|
56
|
+
}
|
57
|
+
|
58
|
+
#[derive(Clone, Debug)]
|
59
|
+
pub enum NextPageToken {
|
60
|
+
/// There is no page token, we need to fetch history from the beginning
|
61
|
+
FetchFromStart,
|
62
|
+
/// There is a page token
|
63
|
+
Next(Vec<u8>),
|
64
|
+
/// There is no page token, we are done fetching history
|
65
|
+
Done,
|
66
|
+
}
|
67
|
+
|
68
|
+
// If we're converting from a page token from the server, if it's empty, then we're done.
|
69
|
+
impl From<Vec<u8>> for NextPageToken {
|
70
|
+
fn from(page_token: Vec<u8>) -> Self {
|
71
|
+
if page_token.is_empty() {
|
72
|
+
NextPageToken::Done
|
73
|
+
} else {
|
74
|
+
NextPageToken::Next(page_token)
|
75
|
+
}
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
impl HistoryPaginator {
|
80
|
+
pub(crate) fn new(
|
81
|
+
initial_history: History,
|
82
|
+
wf_id: String,
|
83
|
+
run_id: String,
|
84
|
+
next_page_token: impl Into<NextPageToken>,
|
85
|
+
client: Arc<dyn WorkerClient>,
|
86
|
+
) -> Self {
|
87
|
+
let next_page_token = next_page_token.into();
|
88
|
+
let (event_queue, final_events) =
|
89
|
+
if matches!(next_page_token, NextPageToken::FetchFromStart) {
|
90
|
+
(VecDeque::new(), initial_history.events)
|
91
|
+
} else {
|
92
|
+
(initial_history.events.into(), vec![])
|
93
|
+
};
|
94
|
+
Self {
|
95
|
+
client,
|
96
|
+
event_queue,
|
97
|
+
wf_id,
|
98
|
+
run_id,
|
99
|
+
next_page_token,
|
100
|
+
open_history_request: None,
|
101
|
+
final_events,
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
fn extend_queue_with_new_page(&mut self, resp: GetWorkflowExecutionHistoryResponse) {
|
106
|
+
self.next_page_token = resp.next_page_token.into();
|
107
|
+
self.event_queue
|
108
|
+
.extend(resp.history.map(|h| h.events).unwrap_or_default());
|
109
|
+
if matches!(&self.next_page_token, NextPageToken::Done) {
|
110
|
+
// If finished, we need to extend the queue with the final events, skipping any
|
111
|
+
// which are already present.
|
112
|
+
if let Some(last_event_id) = self.event_queue.back().map(|e| e.event_id) {
|
113
|
+
let final_events = std::mem::take(&mut self.final_events);
|
114
|
+
self.event_queue.extend(
|
115
|
+
final_events
|
116
|
+
.into_iter()
|
117
|
+
.skip_while(|e2| e2.event_id <= last_event_id),
|
118
|
+
);
|
119
|
+
}
|
120
|
+
};
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
impl Stream for HistoryPaginator {
|
125
|
+
type Item = Result<HistoryEvent, tonic::Status>;
|
126
|
+
|
127
|
+
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
128
|
+
if let Some(e) = self.event_queue.pop_front() {
|
129
|
+
return Poll::Ready(Some(Ok(e)));
|
130
|
+
}
|
131
|
+
let history_req = if let Some(req) = self.open_history_request.as_mut() {
|
132
|
+
req
|
133
|
+
} else {
|
134
|
+
let npt = match std::mem::replace(&mut self.next_page_token, NextPageToken::Done) {
|
135
|
+
// If there's no open request and the last page token we got was empty, we're done.
|
136
|
+
NextPageToken::Done => return Poll::Ready(None),
|
137
|
+
NextPageToken::FetchFromStart => vec![],
|
138
|
+
NextPageToken::Next(v) => v,
|
139
|
+
};
|
140
|
+
debug!(run_id=%self.run_id, "Fetching new history page");
|
141
|
+
let gw = self.client.clone();
|
142
|
+
let wid = self.wf_id.clone();
|
143
|
+
let rid = self.run_id.clone();
|
144
|
+
let resp_fut = async move {
|
145
|
+
gw.get_workflow_execution_history(wid, Some(rid), npt)
|
146
|
+
.instrument(span!(tracing::Level::TRACE, "fetch_history_in_paginator"))
|
147
|
+
.await
|
148
|
+
};
|
149
|
+
self.open_history_request.insert(resp_fut.boxed())
|
150
|
+
};
|
151
|
+
|
152
|
+
return match Future::poll(history_req.as_mut(), cx) {
|
153
|
+
Poll::Ready(resp) => {
|
154
|
+
self.open_history_request = None;
|
155
|
+
match resp {
|
156
|
+
Err(neterr) => Poll::Ready(Some(Err(neterr))),
|
157
|
+
Ok(resp) => {
|
158
|
+
self.extend_queue_with_new_page(resp);
|
159
|
+
Poll::Ready(self.event_queue.pop_front().map(Ok))
|
160
|
+
}
|
161
|
+
}
|
162
|
+
}
|
163
|
+
Poll::Pending => Poll::Pending,
|
164
|
+
};
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
impl HistoryUpdate {
|
169
|
+
pub fn new(history_iterator: HistoryPaginator, previous_wft_started_id: i64) -> Self {
|
170
|
+
Self {
|
171
|
+
events: history_iterator.fuse().boxed(),
|
172
|
+
buffered: VecDeque::new(),
|
173
|
+
previous_started_event_id: previous_wft_started_id,
|
174
|
+
}
|
175
|
+
}
|
176
|
+
|
177
|
+
/// Create an instance of an update directly from events - should only be used for replaying.
|
178
|
+
pub fn new_from_events<I: IntoIterator<Item = HistoryEvent>>(
|
179
|
+
events: I,
|
180
|
+
previous_wft_started_id: i64,
|
181
|
+
) -> Self
|
182
|
+
where
|
183
|
+
<I as IntoIterator>::IntoIter: Send + 'static,
|
184
|
+
{
|
185
|
+
Self {
|
186
|
+
events: stream::iter(events.into_iter().map(Ok)).boxed(),
|
187
|
+
buffered: VecDeque::new(),
|
188
|
+
previous_started_event_id: previous_wft_started_id,
|
189
|
+
}
|
190
|
+
}
|
191
|
+
|
192
|
+
/// Given a workflow task started id, return all events starting at that number (inclusive) to
|
193
|
+
/// the next WFT started event (inclusive). If there is no subsequent WFT started event,
|
194
|
+
/// remaining history is returned.
|
195
|
+
///
|
196
|
+
/// Events are *consumed* by this process, to keep things efficient in workflow machines, and
|
197
|
+
/// the function may call out to server to fetch more pages if they are known to exist and
|
198
|
+
/// needed to complete the WFT sequence.
|
199
|
+
///
|
200
|
+
/// Always buffers the WFT sequence *after* the returned one as well, if it is available.
|
201
|
+
///
|
202
|
+
/// Can return a tonic error in the event that fetching additional history was needed and failed
|
203
|
+
pub async fn take_next_wft_sequence(
|
204
|
+
&mut self,
|
205
|
+
from_wft_started_id: i64,
|
206
|
+
) -> Result<Vec<HistoryEvent>, tonic::Status> {
|
207
|
+
let (next_wft_events, maybe_bonus_event) = self
|
208
|
+
.take_next_wft_sequence_impl(from_wft_started_id)
|
209
|
+
.await?;
|
210
|
+
if let Some(be) = maybe_bonus_event {
|
211
|
+
self.buffered.push_back(be);
|
212
|
+
}
|
213
|
+
|
214
|
+
if let Some(last_event_id) = next_wft_events.last().map(|he| he.event_id) {
|
215
|
+
// Always attempt to fetch the *next* WFT sequence as well, to buffer it for lookahead
|
216
|
+
let (buffer_these_events, maybe_bonus_event) =
|
217
|
+
self.take_next_wft_sequence_impl(last_event_id).await?;
|
218
|
+
self.buffered.extend(buffer_these_events);
|
219
|
+
if let Some(be) = maybe_bonus_event {
|
220
|
+
self.buffered.push_back(be);
|
221
|
+
}
|
222
|
+
}
|
223
|
+
|
224
|
+
Ok(next_wft_events)
|
225
|
+
}
|
226
|
+
|
227
|
+
/// Lets the caller peek ahead at the next WFT sequence that will be returned by
|
228
|
+
/// [take_next_wft_sequence]. Will always return an empty iterator if that has not been called
|
229
|
+
/// first. May also return an empty iterator or incomplete sequence if we are at the end of
|
230
|
+
/// history.
|
231
|
+
pub fn peek_next_wft_sequence(&self) -> impl Iterator<Item = &HistoryEvent> {
|
232
|
+
self.buffered.iter()
|
233
|
+
}
|
234
|
+
|
235
|
+
async fn take_next_wft_sequence_impl(
|
236
|
+
&mut self,
|
237
|
+
from_event_id: i64,
|
238
|
+
) -> Result<(Vec<HistoryEvent>, Option<HistoryEvent>), tonic::Status> {
|
239
|
+
let mut events_to_next_wft_started: Vec<HistoryEvent> = vec![];
|
240
|
+
|
241
|
+
// This flag tracks if, while determining events to be returned, we have seen the next
|
242
|
+
// logically significant WFT started event which follows the one that was passed in as a
|
243
|
+
// parameter. If a WFT fails or times out, it is not significant. So we will stop returning
|
244
|
+
// events (exclusive) as soon as we see an event following a WFT started that is *not*
|
245
|
+
// failed or timed out.
|
246
|
+
let mut saw_next_wft = false;
|
247
|
+
let mut should_pop = |e: &HistoryEvent| {
|
248
|
+
if e.event_id <= from_event_id {
|
249
|
+
return true;
|
250
|
+
} else if e.event_type == EventType::WorkflowTaskStarted as i32 {
|
251
|
+
saw_next_wft = true;
|
252
|
+
return true;
|
253
|
+
}
|
254
|
+
|
255
|
+
if saw_next_wft {
|
256
|
+
// Must ignore failures and timeouts
|
257
|
+
if e.event_type == EventType::WorkflowTaskFailed as i32
|
258
|
+
|| e.event_type == EventType::WorkflowTaskTimedOut as i32
|
259
|
+
{
|
260
|
+
saw_next_wft = false;
|
261
|
+
return true;
|
262
|
+
}
|
263
|
+
return false;
|
264
|
+
}
|
265
|
+
|
266
|
+
true
|
267
|
+
};
|
268
|
+
|
269
|
+
// Fetch events from the buffer first, then from the network
|
270
|
+
let mut event_q = stream::iter(self.buffered.drain(..).map(Ok)).chain(&mut self.events);
|
271
|
+
|
272
|
+
let mut extra_e = None;
|
273
|
+
let mut last_seen_id = None;
|
274
|
+
while let Some(e) = event_q.next().await {
|
275
|
+
let e = e?;
|
276
|
+
|
277
|
+
// This little block prevents us from infinitely fetching work from the server in the
|
278
|
+
// event that, for whatever reason, it keeps returning stuff we've already seen.
|
279
|
+
if let Some(last_id) = last_seen_id {
|
280
|
+
if e.event_id <= last_id {
|
281
|
+
error!("Server returned history event IDs that went backwards!");
|
282
|
+
break;
|
283
|
+
}
|
284
|
+
}
|
285
|
+
last_seen_id = Some(e.event_id);
|
286
|
+
|
287
|
+
// It's possible to have gotten a new history update without eviction (ex: unhandled
|
288
|
+
// command on completion), where we may need to skip events we already handled.
|
289
|
+
if e.event_id > from_event_id {
|
290
|
+
if !should_pop(&e) {
|
291
|
+
extra_e = Some(e);
|
292
|
+
break;
|
293
|
+
}
|
294
|
+
events_to_next_wft_started.push(e);
|
295
|
+
}
|
296
|
+
}
|
297
|
+
|
298
|
+
Ok((events_to_next_wft_started, extra_e))
|
299
|
+
}
|
300
|
+
}
|
301
|
+
|
302
|
+
impl From<HistoryInfo> for HistoryUpdate {
|
303
|
+
fn from(v: HistoryInfo) -> Self {
|
304
|
+
Self::new_from_events(v.events().to_vec(), v.previous_started_event_id())
|
305
|
+
}
|
306
|
+
}
|
307
|
+
|
308
|
+
pub trait TestHBExt {
|
309
|
+
fn as_history_update(&self) -> HistoryUpdate;
|
310
|
+
}
|
311
|
+
|
312
|
+
impl TestHBExt for TestHistoryBuilder {
|
313
|
+
fn as_history_update(&self) -> HistoryUpdate {
|
314
|
+
self.get_full_history_info().unwrap().into()
|
315
|
+
}
|
316
|
+
}
|
317
|
+
|
318
|
+
#[cfg(test)]
|
319
|
+
pub mod tests {
|
320
|
+
use super::*;
|
321
|
+
use crate::{test_help::canned_histories, worker::client::mocks::mock_workflow_client};
|
322
|
+
|
323
|
+
#[tokio::test]
|
324
|
+
async fn consumes_standard_wft_sequence() {
|
325
|
+
let timer_hist = canned_histories::single_timer("t");
|
326
|
+
let mut update = timer_hist.as_history_update();
|
327
|
+
let seq_1 = update.take_next_wft_sequence(0).await.unwrap();
|
328
|
+
assert_eq!(seq_1.len(), 3);
|
329
|
+
assert_eq!(seq_1.last().unwrap().event_id, 3);
|
330
|
+
let seq_2 = update.take_next_wft_sequence(3).await.unwrap();
|
331
|
+
assert_eq!(seq_2.len(), 5);
|
332
|
+
assert_eq!(seq_2.last().unwrap().event_id, 8);
|
333
|
+
}
|
334
|
+
|
335
|
+
#[tokio::test]
|
336
|
+
async fn skips_wft_failed() {
|
337
|
+
let failed_hist = canned_histories::workflow_fails_with_reset_after_timer("t", "runid");
|
338
|
+
let mut update = failed_hist.as_history_update();
|
339
|
+
let seq_1 = update.take_next_wft_sequence(0).await.unwrap();
|
340
|
+
assert_eq!(seq_1.len(), 3);
|
341
|
+
assert_eq!(seq_1.last().unwrap().event_id, 3);
|
342
|
+
let seq_2 = update.take_next_wft_sequence(3).await.unwrap();
|
343
|
+
assert_eq!(seq_2.len(), 8);
|
344
|
+
assert_eq!(seq_2.last().unwrap().event_id, 11);
|
345
|
+
}
|
346
|
+
|
347
|
+
#[tokio::test]
|
348
|
+
async fn skips_wft_timeout() {
|
349
|
+
let failed_hist = canned_histories::wft_timeout_repro();
|
350
|
+
let mut update = failed_hist.as_history_update();
|
351
|
+
let seq_1 = update.take_next_wft_sequence(0).await.unwrap();
|
352
|
+
assert_eq!(seq_1.len(), 3);
|
353
|
+
assert_eq!(seq_1.last().unwrap().event_id, 3);
|
354
|
+
let seq_2 = update.take_next_wft_sequence(3).await.unwrap();
|
355
|
+
assert_eq!(seq_2.len(), 11);
|
356
|
+
assert_eq!(seq_2.last().unwrap().event_id, 14);
|
357
|
+
}
|
358
|
+
|
359
|
+
#[tokio::test]
|
360
|
+
async fn skips_events_before_desired_wft() {
|
361
|
+
let timer_hist = canned_histories::single_timer("t");
|
362
|
+
let mut update = timer_hist.as_history_update();
|
363
|
+
// We haven't processed the first 3 events, but we should still only get the second sequence
|
364
|
+
let seq_2 = update.take_next_wft_sequence(3).await.unwrap();
|
365
|
+
assert_eq!(seq_2.len(), 5);
|
366
|
+
assert_eq!(seq_2.last().unwrap().event_id, 8);
|
367
|
+
}
|
368
|
+
|
369
|
+
#[tokio::test]
|
370
|
+
async fn paginator_fetches_new_pages() {
|
371
|
+
// Note that this test triggers the "event ids that went backwards" error, acceptably.
|
372
|
+
// Can be fixed by having mock not return earlier events.
|
373
|
+
let wft_count = 500;
|
374
|
+
let long_hist = canned_histories::long_sequential_timers(wft_count);
|
375
|
+
let initial_hist = long_hist.get_history_info(10).unwrap();
|
376
|
+
let prev_started = initial_hist.previous_started_event_id();
|
377
|
+
let mut mock_client = mock_workflow_client();
|
378
|
+
|
379
|
+
let mut npt = 2;
|
380
|
+
mock_client
|
381
|
+
.expect_get_workflow_execution_history()
|
382
|
+
.returning(move |_, _, passed_npt| {
|
383
|
+
assert_eq!(passed_npt, vec![npt]);
|
384
|
+
let history = long_hist.get_history_info(10 * npt as usize).unwrap();
|
385
|
+
npt += 1;
|
386
|
+
Ok(GetWorkflowExecutionHistoryResponse {
|
387
|
+
history: Some(history.into()),
|
388
|
+
raw_history: vec![],
|
389
|
+
next_page_token: vec![npt],
|
390
|
+
archived: false,
|
391
|
+
})
|
392
|
+
});
|
393
|
+
|
394
|
+
let mut update = HistoryUpdate::new(
|
395
|
+
HistoryPaginator::new(
|
396
|
+
initial_hist.into(),
|
397
|
+
"wfid".to_string(),
|
398
|
+
"runid".to_string(),
|
399
|
+
vec![2], // Start at page "2"
|
400
|
+
Arc::new(mock_client),
|
401
|
+
),
|
402
|
+
prev_started,
|
403
|
+
);
|
404
|
+
|
405
|
+
let seq = update.take_next_wft_sequence(0).await.unwrap();
|
406
|
+
assert_eq!(seq.len(), 3);
|
407
|
+
|
408
|
+
let mut last_event_id = 3;
|
409
|
+
let mut last_started_id = 3;
|
410
|
+
for _ in 1..wft_count {
|
411
|
+
let seq = update
|
412
|
+
.take_next_wft_sequence(last_started_id)
|
413
|
+
.await
|
414
|
+
.unwrap();
|
415
|
+
for e in &seq {
|
416
|
+
last_event_id += 1;
|
417
|
+
assert_eq!(e.event_id, last_event_id);
|
418
|
+
}
|
419
|
+
assert_eq!(seq.len(), 5);
|
420
|
+
last_started_id += 5;
|
421
|
+
}
|
422
|
+
}
|
423
|
+
|
424
|
+
#[tokio::test]
|
425
|
+
async fn handles_cache_misses() {
|
426
|
+
let timer_hist = canned_histories::single_timer("t");
|
427
|
+
let partial_task = timer_hist.get_one_wft(2).unwrap();
|
428
|
+
let mut history_from_get: GetWorkflowExecutionHistoryResponse =
|
429
|
+
timer_hist.get_history_info(2).unwrap().into();
|
430
|
+
// Chop off the last event, which is WFT started, which server doesn't return in get
|
431
|
+
// history
|
432
|
+
history_from_get.history.as_mut().map(|h| h.events.pop());
|
433
|
+
let mut mock_client = mock_workflow_client();
|
434
|
+
mock_client
|
435
|
+
.expect_get_workflow_execution_history()
|
436
|
+
.returning(move |_, _, _| Ok(history_from_get.clone()));
|
437
|
+
|
438
|
+
let mut update = HistoryUpdate::new(
|
439
|
+
HistoryPaginator::new(
|
440
|
+
partial_task.into(),
|
441
|
+
"wfid".to_string(),
|
442
|
+
"runid".to_string(),
|
443
|
+
// A cache miss means we'll try to fetch from start
|
444
|
+
NextPageToken::FetchFromStart,
|
445
|
+
Arc::new(mock_client),
|
446
|
+
),
|
447
|
+
1,
|
448
|
+
);
|
449
|
+
// We expect if we try to take the first task sequence that the first event is the first
|
450
|
+
// event in the sequence.
|
451
|
+
let seq = update.take_next_wft_sequence(0).await.unwrap();
|
452
|
+
assert_eq!(seq[0].event_id, 1);
|
453
|
+
let seq = update.take_next_wft_sequence(3).await.unwrap();
|
454
|
+
// Verify anything extra (which should only ever be WFT started) was re-appended to the
|
455
|
+
// end of the event iteration after fetching the old history.
|
456
|
+
assert_eq!(seq.last().unwrap().event_id, 8);
|
457
|
+
}
|
458
|
+
}
|