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,28 @@
|
|
1
|
+
//! Use this binary to fetch histories as proto-encoded binary. The first argument must be a
|
2
|
+
//! workflow ID. A run id may optionally be provided as the second arg. The history is written to
|
3
|
+
//! `{workflow_id}_history.bin`.
|
4
|
+
//!
|
5
|
+
//! We can use `clap` if this needs more arguments / other stuff later on.
|
6
|
+
|
7
|
+
use prost::Message;
|
8
|
+
use temporal_client::WorkflowClientTrait;
|
9
|
+
use temporal_sdk_core_test_utils::get_integ_server_options;
|
10
|
+
|
11
|
+
#[tokio::main]
|
12
|
+
async fn main() -> Result<(), anyhow::Error> {
|
13
|
+
let gw_opts = get_integ_server_options();
|
14
|
+
let client = gw_opts.connect("default", None, None).await?;
|
15
|
+
let wf_id = std::env::args()
|
16
|
+
.nth(1)
|
17
|
+
.expect("must provide workflow id as only argument");
|
18
|
+
let run_id = std::env::args().nth(2);
|
19
|
+
let hist = client
|
20
|
+
.get_workflow_execution_history(wf_id.clone(), run_id, vec![])
|
21
|
+
.await?
|
22
|
+
.history
|
23
|
+
.expect("history field must be populated");
|
24
|
+
// Serialize history to file
|
25
|
+
let byteified = hist.encode_to_vec();
|
26
|
+
tokio::fs::write(format!("{}_history.bin", wf_id), &byteified).await?;
|
27
|
+
Ok(())
|
28
|
+
}
|
@@ -0,0 +1,598 @@
|
|
1
|
+
//! This crate contains testing functionality that can be useful when building SDKs against Core,
|
2
|
+
//! or even when testing workflows written in SDKs that use Core.
|
3
|
+
|
4
|
+
#[macro_use]
|
5
|
+
extern crate tracing;
|
6
|
+
|
7
|
+
pub mod canned_histories;
|
8
|
+
|
9
|
+
use crate::stream::TryStreamExt;
|
10
|
+
use futures::{future, stream, stream::FuturesUnordered, StreamExt};
|
11
|
+
use parking_lot::Mutex;
|
12
|
+
use prost::Message;
|
13
|
+
use rand::{distributions::Standard, Rng};
|
14
|
+
use std::{
|
15
|
+
convert::TryFrom, env, future::Future, net::SocketAddr, path::PathBuf, sync::Arc,
|
16
|
+
time::Duration,
|
17
|
+
};
|
18
|
+
use temporal_client::{
|
19
|
+
Client, RetryClient, WorkflowClientTrait, WorkflowExecutionInfo, WorkflowOptions,
|
20
|
+
};
|
21
|
+
use temporal_sdk::{interceptors::WorkerInterceptor, IntoActivityFunc, Worker, WorkflowFunction};
|
22
|
+
use temporal_sdk_core::{
|
23
|
+
ephemeral_server::{EphemeralExe, EphemeralExeVersion},
|
24
|
+
init_replay_worker, init_worker, telemetry_init, ClientOptions, ClientOptionsBuilder, Logger,
|
25
|
+
MetricsExporter, OtelCollectorOptions, TelemetryOptions, TelemetryOptionsBuilder,
|
26
|
+
TraceExporter, WorkerConfig, WorkerConfigBuilder,
|
27
|
+
};
|
28
|
+
use temporal_sdk_core_api::Worker as CoreWorker;
|
29
|
+
use temporal_sdk_core_protos::{
|
30
|
+
coresdk::{
|
31
|
+
workflow_commands::{
|
32
|
+
workflow_command, ActivityCancellationType, CompleteWorkflowExecution,
|
33
|
+
ScheduleActivity, ScheduleLocalActivity, StartTimer,
|
34
|
+
},
|
35
|
+
workflow_completion::WorkflowActivationCompletion,
|
36
|
+
},
|
37
|
+
temporal::api::{common::v1::Payload, history::v1::History},
|
38
|
+
};
|
39
|
+
use tokio::sync::OnceCell;
|
40
|
+
use url::Url;
|
41
|
+
|
42
|
+
pub const NAMESPACE: &str = "default";
|
43
|
+
pub const TEST_Q: &str = "q";
|
44
|
+
/// The env var used to specify where the integ tests should point
|
45
|
+
pub const INTEG_SERVER_TARGET_ENV_VAR: &str = "TEMPORAL_SERVICE_ADDRESS";
|
46
|
+
/// This env var is set (to any value) if temporalite is in use
|
47
|
+
pub const INTEG_TEMPORALITE_USED_ENV_VAR: &str = "INTEG_TEMPORALITE_ON";
|
48
|
+
/// This env var is set (to any value) if the test server is in use
|
49
|
+
pub const INTEG_TEST_SERVER_USED_ENV_VAR: &str = "INTEG_TEST_SERVER_ON";
|
50
|
+
|
51
|
+
/// If set, turn export traces and metrics to the OTel collector at the given URL
|
52
|
+
const OTEL_URL_ENV_VAR: &str = "TEMPORAL_INTEG_OTEL_URL";
|
53
|
+
/// If set, enable direct scraping of prom metrics on the specified port
|
54
|
+
const PROM_ENABLE_ENV_VAR: &str = "TEMPORAL_INTEG_PROM_PORT";
|
55
|
+
/// Create a worker instance which will use the provided test name to base the task queue and wf id
|
56
|
+
/// upon. Returns the instance and the task queue name (which is also the workflow id).
|
57
|
+
pub async fn init_core_and_create_wf(test_name: &str) -> CoreWfStarter {
|
58
|
+
let mut starter = CoreWfStarter::new(test_name);
|
59
|
+
let _ = starter.get_worker().await;
|
60
|
+
starter.start_wf().await;
|
61
|
+
starter
|
62
|
+
}
|
63
|
+
|
64
|
+
/// Create a worker replay instance preloaded with a provided history. Returns the worker impl
|
65
|
+
/// and the task queue name as in [init_core_and_create_wf].
|
66
|
+
pub fn init_core_replay_preloaded(
|
67
|
+
test_name: &str,
|
68
|
+
history: &History,
|
69
|
+
) -> (Arc<dyn CoreWorker>, String) {
|
70
|
+
telemetry_init(&get_integ_telem_options()).expect("Telemetry inits cleanly");
|
71
|
+
let worker_cfg = WorkerConfigBuilder::default()
|
72
|
+
.namespace(NAMESPACE)
|
73
|
+
.task_queue(test_name)
|
74
|
+
.worker_build_id("test_bin_id")
|
75
|
+
.build()
|
76
|
+
.expect("Configuration options construct properly");
|
77
|
+
let worker = init_replay_worker(worker_cfg, history).expect("Replay worker must init properly");
|
78
|
+
(Arc::new(worker), test_name.to_string())
|
79
|
+
}
|
80
|
+
|
81
|
+
/// Load history from a file containing the protobuf serialization of it
|
82
|
+
pub async fn history_from_proto_binary(path_from_root: &str) -> Result<History, anyhow::Error> {
|
83
|
+
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
84
|
+
path.push("..");
|
85
|
+
path.push(path_from_root);
|
86
|
+
let bytes = tokio::fs::read(path).await?;
|
87
|
+
Ok(History::decode(&*bytes)?)
|
88
|
+
}
|
89
|
+
|
90
|
+
/// Implements a builder pattern to help integ tests initialize core and create workflows
|
91
|
+
pub struct CoreWfStarter {
|
92
|
+
/// Used for both the task queue and workflow id
|
93
|
+
task_queue_name: String,
|
94
|
+
telemetry_options: TelemetryOptions,
|
95
|
+
pub worker_config: WorkerConfig,
|
96
|
+
wft_timeout: Option<Duration>,
|
97
|
+
initted_worker: OnceCell<InitializedWorker>,
|
98
|
+
}
|
99
|
+
struct InitializedWorker {
|
100
|
+
worker: Arc<dyn CoreWorker>,
|
101
|
+
client: Arc<RetryClient<Client>>,
|
102
|
+
}
|
103
|
+
|
104
|
+
impl CoreWfStarter {
|
105
|
+
pub fn new(test_name: &str) -> Self {
|
106
|
+
let rand_bytes: Vec<u8> = rand::thread_rng().sample_iter(&Standard).take(6).collect();
|
107
|
+
let task_q_salt = base64::encode(rand_bytes);
|
108
|
+
let task_queue = format!("{}_{}", test_name, task_q_salt);
|
109
|
+
Self::new_tq_name(&task_queue)
|
110
|
+
}
|
111
|
+
|
112
|
+
pub fn new_tq_name(task_queue: &str) -> Self {
|
113
|
+
Self {
|
114
|
+
task_queue_name: task_queue.to_owned(),
|
115
|
+
telemetry_options: get_integ_telem_options(),
|
116
|
+
worker_config: WorkerConfigBuilder::default()
|
117
|
+
.namespace(NAMESPACE)
|
118
|
+
.task_queue(task_queue)
|
119
|
+
.worker_build_id("test_build_id")
|
120
|
+
.max_cached_workflows(1000_usize)
|
121
|
+
.build()
|
122
|
+
.unwrap(),
|
123
|
+
wft_timeout: None,
|
124
|
+
initted_worker: OnceCell::new(),
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
pub async fn worker(&mut self) -> TestWorker {
|
129
|
+
let mut w = TestWorker::new(
|
130
|
+
self.get_worker().await,
|
131
|
+
self.worker_config.task_queue.clone(),
|
132
|
+
);
|
133
|
+
w.client = Some(self.get_client().await);
|
134
|
+
|
135
|
+
w
|
136
|
+
}
|
137
|
+
|
138
|
+
pub async fn shutdown(&mut self) {
|
139
|
+
self.get_worker().await.shutdown().await;
|
140
|
+
}
|
141
|
+
|
142
|
+
pub async fn get_worker(&mut self) -> Arc<dyn CoreWorker> {
|
143
|
+
self.get_or_init().await.worker.clone()
|
144
|
+
}
|
145
|
+
|
146
|
+
pub async fn get_client(&mut self) -> Arc<RetryClient<Client>> {
|
147
|
+
self.get_or_init().await.client.clone()
|
148
|
+
}
|
149
|
+
|
150
|
+
/// Start the workflow defined by the builder and return run id
|
151
|
+
pub async fn start_wf(&self) -> String {
|
152
|
+
self.start_wf_with_id(self.task_queue_name.clone(), WorkflowOptions::default())
|
153
|
+
.await
|
154
|
+
}
|
155
|
+
|
156
|
+
pub async fn start_wf_with_id(&self, workflow_id: String, mut opts: WorkflowOptions) -> String {
|
157
|
+
opts.task_timeout = opts.task_timeout.or(self.wft_timeout);
|
158
|
+
self.initted_worker
|
159
|
+
.get()
|
160
|
+
.expect(
|
161
|
+
"Worker must be initted before starting a workflow.\
|
162
|
+
Tests must call `get_worker` first.",
|
163
|
+
)
|
164
|
+
.client
|
165
|
+
.start_workflow(
|
166
|
+
vec![],
|
167
|
+
self.worker_config.task_queue.clone(),
|
168
|
+
workflow_id,
|
169
|
+
self.task_queue_name.clone(),
|
170
|
+
None,
|
171
|
+
opts,
|
172
|
+
)
|
173
|
+
.await
|
174
|
+
.unwrap()
|
175
|
+
.run_id
|
176
|
+
}
|
177
|
+
|
178
|
+
/// Fetch the history for the indicated workflow and replay it using the provided worker.
|
179
|
+
/// Can be used after completing workflows normally to ensure replay works as well.
|
180
|
+
pub async fn fetch_history_and_replay(
|
181
|
+
&mut self,
|
182
|
+
wf_id: impl Into<String>,
|
183
|
+
run_id: impl Into<String>,
|
184
|
+
// TODO: Need not be passed in
|
185
|
+
worker: &mut Worker,
|
186
|
+
) -> Result<(), anyhow::Error> {
|
187
|
+
// Fetch history and replay it
|
188
|
+
let history = self
|
189
|
+
.get_client()
|
190
|
+
.await
|
191
|
+
.get_workflow_execution_history(wf_id.into(), Some(run_id.into()), vec![])
|
192
|
+
.await?
|
193
|
+
.history
|
194
|
+
.expect("history field must be populated");
|
195
|
+
let (replay_worker, _) = init_core_replay_preloaded(worker.task_queue(), &history);
|
196
|
+
worker.with_new_core_worker(replay_worker);
|
197
|
+
worker.run().await.unwrap();
|
198
|
+
Ok(())
|
199
|
+
}
|
200
|
+
|
201
|
+
pub fn get_task_queue(&self) -> &str {
|
202
|
+
&self.worker_config.task_queue
|
203
|
+
}
|
204
|
+
|
205
|
+
pub fn get_wf_id(&self) -> &str {
|
206
|
+
&self.task_queue_name
|
207
|
+
}
|
208
|
+
|
209
|
+
pub fn max_cached_workflows(&mut self, num: usize) -> &mut Self {
|
210
|
+
self.worker_config.max_cached_workflows = num;
|
211
|
+
self
|
212
|
+
}
|
213
|
+
|
214
|
+
pub fn max_wft(&mut self, max: usize) -> &mut Self {
|
215
|
+
self.worker_config.max_outstanding_workflow_tasks = max;
|
216
|
+
self
|
217
|
+
}
|
218
|
+
|
219
|
+
pub fn max_at(&mut self, max: usize) -> &mut Self {
|
220
|
+
self.worker_config.max_outstanding_activities = max;
|
221
|
+
self
|
222
|
+
}
|
223
|
+
|
224
|
+
pub fn max_local_at(&mut self, max: usize) -> &mut Self {
|
225
|
+
self.worker_config.max_outstanding_local_activities = max;
|
226
|
+
self
|
227
|
+
}
|
228
|
+
|
229
|
+
pub fn max_at_polls(&mut self, max: usize) -> &mut Self {
|
230
|
+
self.worker_config.max_concurrent_at_polls = max;
|
231
|
+
self
|
232
|
+
}
|
233
|
+
|
234
|
+
pub fn wft_timeout(&mut self, timeout: Duration) -> &mut Self {
|
235
|
+
self.wft_timeout = Some(timeout);
|
236
|
+
self
|
237
|
+
}
|
238
|
+
|
239
|
+
async fn get_or_init(&mut self) -> &InitializedWorker {
|
240
|
+
self.initted_worker
|
241
|
+
.get_or_init(|| async {
|
242
|
+
telemetry_init(&self.telemetry_options).expect("Telemetry inits cleanly");
|
243
|
+
let client = Arc::new(
|
244
|
+
get_integ_server_options()
|
245
|
+
.connect(self.worker_config.namespace.clone(), None, None)
|
246
|
+
.await
|
247
|
+
.expect("Must connect"),
|
248
|
+
);
|
249
|
+
let worker = init_worker(self.worker_config.clone(), client.clone());
|
250
|
+
InitializedWorker {
|
251
|
+
worker: Arc::new(worker),
|
252
|
+
client,
|
253
|
+
}
|
254
|
+
})
|
255
|
+
.await
|
256
|
+
}
|
257
|
+
}
|
258
|
+
|
259
|
+
/// Provides conveniences for running integ tests with the SDK (against real server or mocks)
|
260
|
+
pub struct TestWorker {
|
261
|
+
inner: Worker,
|
262
|
+
pub core_worker: Arc<dyn CoreWorker>,
|
263
|
+
client: Option<Arc<RetryClient<Client>>>,
|
264
|
+
pub started_workflows: Mutex<Vec<WorkflowExecutionInfo>>,
|
265
|
+
/// If set true (default), and a client is available, we will fetch workflow results to
|
266
|
+
/// determine when they have all completed.
|
267
|
+
pub fetch_results: bool,
|
268
|
+
iceptor: Option<TestWorkerCompletionIceptor>,
|
269
|
+
}
|
270
|
+
impl TestWorker {
|
271
|
+
/// Create a new test worker
|
272
|
+
pub fn new(core_worker: Arc<dyn CoreWorker>, task_queue: impl Into<String>) -> Self {
|
273
|
+
let inner = Worker::new_from_core(core_worker.clone(), task_queue);
|
274
|
+
let iceptor = TestWorkerCompletionIceptor::new(
|
275
|
+
TestWorkerShutdownCond::NoAutoShutdown,
|
276
|
+
Arc::new(inner.shutdown_handle()),
|
277
|
+
);
|
278
|
+
Self {
|
279
|
+
inner,
|
280
|
+
core_worker,
|
281
|
+
client: None,
|
282
|
+
started_workflows: Mutex::new(vec![]),
|
283
|
+
fetch_results: true,
|
284
|
+
iceptor: Some(iceptor),
|
285
|
+
}
|
286
|
+
}
|
287
|
+
|
288
|
+
pub fn inner_mut(&mut self) -> &mut Worker {
|
289
|
+
&mut self.inner
|
290
|
+
}
|
291
|
+
|
292
|
+
// TODO: Maybe trait-ify?
|
293
|
+
pub fn register_wf<F: Into<WorkflowFunction>>(
|
294
|
+
&mut self,
|
295
|
+
workflow_type: impl Into<String>,
|
296
|
+
wf_function: F,
|
297
|
+
) {
|
298
|
+
self.inner.register_wf(workflow_type, wf_function)
|
299
|
+
}
|
300
|
+
|
301
|
+
pub fn register_activity<A, R, O>(
|
302
|
+
&mut self,
|
303
|
+
activity_type: impl Into<String>,
|
304
|
+
act_function: impl IntoActivityFunc<A, R, O>,
|
305
|
+
) {
|
306
|
+
self.inner.register_activity(activity_type, act_function)
|
307
|
+
}
|
308
|
+
|
309
|
+
/// Create a workflow, asking the server to start it with the provided workflow ID and using the
|
310
|
+
/// provided workflow function.
|
311
|
+
///
|
312
|
+
/// Increments the expected Workflow run count.
|
313
|
+
///
|
314
|
+
/// Returns the run id of the started workflow
|
315
|
+
pub async fn submit_wf(
|
316
|
+
&self,
|
317
|
+
workflow_id: impl Into<String>,
|
318
|
+
workflow_type: impl Into<String>,
|
319
|
+
input: Vec<Payload>,
|
320
|
+
options: WorkflowOptions,
|
321
|
+
) -> Result<String, anyhow::Error> {
|
322
|
+
if let Some(c) = self.client.as_ref() {
|
323
|
+
let wfid = workflow_id.into();
|
324
|
+
let res = c
|
325
|
+
.start_workflow(
|
326
|
+
input,
|
327
|
+
self.inner.task_queue().to_string(),
|
328
|
+
wfid.clone(),
|
329
|
+
workflow_type.into(),
|
330
|
+
None,
|
331
|
+
options,
|
332
|
+
)
|
333
|
+
.await?;
|
334
|
+
self.started_workflows.lock().push(WorkflowExecutionInfo {
|
335
|
+
namespace: c.namespace().to_string(),
|
336
|
+
workflow_id: wfid,
|
337
|
+
run_id: Some(res.run_id.clone()),
|
338
|
+
});
|
339
|
+
Ok(res.run_id)
|
340
|
+
} else {
|
341
|
+
Ok("fake_run_id".to_string())
|
342
|
+
}
|
343
|
+
}
|
344
|
+
|
345
|
+
/// Runs until all expected workflows have completed
|
346
|
+
pub async fn run_until_done(&mut self) -> Result<(), anyhow::Error> {
|
347
|
+
self.run_until_done_intercepted(Option::<TestWorkerCompletionIceptor>::None)
|
348
|
+
.await
|
349
|
+
}
|
350
|
+
|
351
|
+
/// See [Self::run_until_done], but allows configuration of some low-level interception.
|
352
|
+
pub async fn run_until_done_intercepted(
|
353
|
+
&mut self,
|
354
|
+
interceptor: Option<impl WorkerInterceptor + 'static>,
|
355
|
+
) -> Result<(), anyhow::Error> {
|
356
|
+
let mut iceptor = self.iceptor.take().unwrap();
|
357
|
+
// Automatically use results-based complete detection if we have a client
|
358
|
+
if self.fetch_results {
|
359
|
+
if let Some(c) = self.client.clone() {
|
360
|
+
iceptor.condition = TestWorkerShutdownCond::GetResults(
|
361
|
+
std::mem::take(&mut self.started_workflows.lock()),
|
362
|
+
c,
|
363
|
+
);
|
364
|
+
}
|
365
|
+
}
|
366
|
+
iceptor.next = interceptor.map(|i| Box::new(i) as Box<dyn WorkerInterceptor>);
|
367
|
+
let get_results_waiter = iceptor.wait_all_wfs();
|
368
|
+
self.inner.set_worker_interceptor(Box::new(iceptor));
|
369
|
+
tokio::try_join!(self.inner.run(), get_results_waiter)?;
|
370
|
+
Ok(())
|
371
|
+
}
|
372
|
+
}
|
373
|
+
|
374
|
+
pub type BoxDynActivationHook = Box<dyn Fn(&WorkflowActivationCompletion)>;
|
375
|
+
|
376
|
+
pub enum TestWorkerShutdownCond {
|
377
|
+
GetResults(Vec<WorkflowExecutionInfo>, Arc<RetryClient<Client>>),
|
378
|
+
NoAutoShutdown,
|
379
|
+
}
|
380
|
+
/// Implements calling the shutdown handle when the expected number of test workflows has completed
|
381
|
+
pub struct TestWorkerCompletionIceptor {
|
382
|
+
condition: TestWorkerShutdownCond,
|
383
|
+
shutdown_handle: Arc<dyn Fn()>,
|
384
|
+
every_activation: Option<BoxDynActivationHook>,
|
385
|
+
next: Option<Box<dyn WorkerInterceptor>>,
|
386
|
+
}
|
387
|
+
impl TestWorkerCompletionIceptor {
|
388
|
+
pub fn new(condition: TestWorkerShutdownCond, shutdown_handle: Arc<dyn Fn()>) -> Self {
|
389
|
+
Self {
|
390
|
+
condition,
|
391
|
+
shutdown_handle,
|
392
|
+
every_activation: None,
|
393
|
+
next: None,
|
394
|
+
}
|
395
|
+
}
|
396
|
+
|
397
|
+
fn wait_all_wfs(&mut self) -> impl Future<Output = Result<(), anyhow::Error>> + 'static {
|
398
|
+
if let TestWorkerShutdownCond::GetResults(ref mut wfs, ref client) = self.condition {
|
399
|
+
let wfs = std::mem::take(wfs);
|
400
|
+
let shutdown_h = self.shutdown_handle.clone();
|
401
|
+
let client = (**client).clone();
|
402
|
+
let stream = stream::iter(
|
403
|
+
wfs.into_iter()
|
404
|
+
.map(move |info| info.bind_untyped(client.clone())),
|
405
|
+
)
|
406
|
+
.map(Ok);
|
407
|
+
future::Either::Left(async move {
|
408
|
+
stream
|
409
|
+
.try_for_each_concurrent(None, |wh| async move {
|
410
|
+
wh.get_workflow_result(Default::default()).await?;
|
411
|
+
Ok::<_, anyhow::Error>(())
|
412
|
+
})
|
413
|
+
.await?;
|
414
|
+
shutdown_h();
|
415
|
+
Ok(())
|
416
|
+
})
|
417
|
+
} else {
|
418
|
+
future::Either::Right(future::ready(Ok(())))
|
419
|
+
}
|
420
|
+
}
|
421
|
+
}
|
422
|
+
#[async_trait::async_trait(?Send)]
|
423
|
+
impl WorkerInterceptor for TestWorkerCompletionIceptor {
|
424
|
+
async fn on_workflow_activation_completion(&self, completion: &WorkflowActivationCompletion) {
|
425
|
+
if let Some(func) = self.every_activation.as_ref() {
|
426
|
+
func(completion);
|
427
|
+
}
|
428
|
+
if completion.has_execution_ending() {
|
429
|
+
info!("Workflow {} says it's finishing", &completion.run_id);
|
430
|
+
}
|
431
|
+
if let Some(n) = self.next.as_ref() {
|
432
|
+
n.on_workflow_activation_completion(completion).await;
|
433
|
+
}
|
434
|
+
}
|
435
|
+
|
436
|
+
fn on_shutdown(&self, sdk_worker: &Worker) {
|
437
|
+
if let Some(n) = self.next.as_ref() {
|
438
|
+
n.on_shutdown(sdk_worker);
|
439
|
+
}
|
440
|
+
}
|
441
|
+
}
|
442
|
+
|
443
|
+
/// Returns the client options used to connect to the server used for integration tests.
|
444
|
+
pub fn get_integ_server_options() -> ClientOptions {
|
445
|
+
telemetry_init(&get_integ_telem_options()).expect("Telemetry inits cleanly");
|
446
|
+
let temporal_server_address = match env::var(INTEG_SERVER_TARGET_ENV_VAR) {
|
447
|
+
Ok(addr) => addr,
|
448
|
+
Err(_) => "http://localhost:7233".to_owned(),
|
449
|
+
};
|
450
|
+
let url = Url::try_from(&*temporal_server_address).unwrap();
|
451
|
+
ClientOptionsBuilder::default()
|
452
|
+
.identity("integ_tester".to_string())
|
453
|
+
.target_url(url)
|
454
|
+
.client_name("temporal-core".to_string())
|
455
|
+
.client_version("0.1.0".to_string())
|
456
|
+
.build()
|
457
|
+
.unwrap()
|
458
|
+
}
|
459
|
+
|
460
|
+
pub fn get_integ_telem_options() -> TelemetryOptions {
|
461
|
+
let mut ob = TelemetryOptionsBuilder::default();
|
462
|
+
if let Some(url) = env::var(OTEL_URL_ENV_VAR)
|
463
|
+
.ok()
|
464
|
+
.map(|x| x.parse::<Url>().unwrap())
|
465
|
+
{
|
466
|
+
let opts = OtelCollectorOptions {
|
467
|
+
url,
|
468
|
+
headers: Default::default(),
|
469
|
+
};
|
470
|
+
ob.tracing(TraceExporter::Otel(opts.clone()));
|
471
|
+
ob.metrics(MetricsExporter::Otel(opts));
|
472
|
+
}
|
473
|
+
if let Some(addr) = env::var(PROM_ENABLE_ENV_VAR)
|
474
|
+
.ok()
|
475
|
+
.map(|x| SocketAddr::new([127, 0, 0, 1].into(), x.parse().unwrap()))
|
476
|
+
{
|
477
|
+
ob.metrics(MetricsExporter::Prometheus(addr));
|
478
|
+
}
|
479
|
+
ob.tracing_filter(env::var("RUST_LOG").unwrap_or_else(|_| "temporal_sdk_core=INFO".to_string()))
|
480
|
+
.logging(Logger::Console)
|
481
|
+
.build()
|
482
|
+
.unwrap()
|
483
|
+
}
|
484
|
+
|
485
|
+
pub fn default_cached_download() -> EphemeralExe {
|
486
|
+
EphemeralExe::CachedDownload {
|
487
|
+
version: EphemeralExeVersion::Default {
|
488
|
+
sdk_name: "sdk-rust".to_string(),
|
489
|
+
sdk_version: "0.1.0".to_string(),
|
490
|
+
},
|
491
|
+
dest_dir: None,
|
492
|
+
}
|
493
|
+
}
|
494
|
+
|
495
|
+
pub fn schedule_activity_cmd(
|
496
|
+
seq: u32,
|
497
|
+
task_q: &str,
|
498
|
+
activity_id: &str,
|
499
|
+
cancellation_type: ActivityCancellationType,
|
500
|
+
activity_timeout: Duration,
|
501
|
+
heartbeat_timeout: Duration,
|
502
|
+
) -> workflow_command::Variant {
|
503
|
+
ScheduleActivity {
|
504
|
+
seq,
|
505
|
+
activity_id: activity_id.to_string(),
|
506
|
+
activity_type: "test_activity".to_string(),
|
507
|
+
namespace: NAMESPACE.to_owned(),
|
508
|
+
task_queue: task_q.to_owned(),
|
509
|
+
schedule_to_start_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
510
|
+
start_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
511
|
+
schedule_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
512
|
+
heartbeat_timeout: Some(heartbeat_timeout.try_into().expect("duration fits")),
|
513
|
+
cancellation_type: cancellation_type as i32,
|
514
|
+
..Default::default()
|
515
|
+
}
|
516
|
+
.into()
|
517
|
+
}
|
518
|
+
|
519
|
+
pub fn schedule_local_activity_cmd(
|
520
|
+
seq: u32,
|
521
|
+
activity_id: &str,
|
522
|
+
cancellation_type: ActivityCancellationType,
|
523
|
+
activity_timeout: Duration,
|
524
|
+
) -> workflow_command::Variant {
|
525
|
+
ScheduleLocalActivity {
|
526
|
+
seq,
|
527
|
+
activity_id: activity_id.to_string(),
|
528
|
+
activity_type: "test_activity".to_string(),
|
529
|
+
schedule_to_start_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
530
|
+
start_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
531
|
+
schedule_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
532
|
+
cancellation_type: cancellation_type as i32,
|
533
|
+
..Default::default()
|
534
|
+
}
|
535
|
+
.into()
|
536
|
+
}
|
537
|
+
|
538
|
+
pub fn start_timer_cmd(seq: u32, duration: Duration) -> workflow_command::Variant {
|
539
|
+
StartTimer {
|
540
|
+
seq,
|
541
|
+
start_to_fire_timeout: Some(duration.try_into().expect("duration fits")),
|
542
|
+
}
|
543
|
+
.into()
|
544
|
+
}
|
545
|
+
|
546
|
+
/// Given a desired number of concurrent executions and a provided function that produces a future,
|
547
|
+
/// run that many instances of the future concurrently.
|
548
|
+
///
|
549
|
+
/// Annoyingly, because of a sorta-bug in the way async blocks work, the async block produced by
|
550
|
+
/// the closure must be `async move` if it uses the provided iteration number. On the plus side,
|
551
|
+
/// since you're usually just accessing core in the closure, if core is a reference everything just
|
552
|
+
/// works. See <https://github.com/rust-lang/rust/issues/81653>
|
553
|
+
pub async fn fanout_tasks<FutureMaker, Fut>(num: usize, fm: FutureMaker)
|
554
|
+
where
|
555
|
+
FutureMaker: Fn(usize) -> Fut,
|
556
|
+
Fut: Future,
|
557
|
+
{
|
558
|
+
let mut tasks = FuturesUnordered::new();
|
559
|
+
for i in 0..num {
|
560
|
+
tasks.push(fm(i));
|
561
|
+
}
|
562
|
+
|
563
|
+
while tasks.next().await.is_some() {}
|
564
|
+
}
|
565
|
+
|
566
|
+
#[async_trait::async_trait]
|
567
|
+
pub trait WorkerTestHelpers {
|
568
|
+
async fn complete_execution(&self, run_id: &str);
|
569
|
+
async fn complete_timer(&self, run_id: &str, seq: u32, duration: Duration);
|
570
|
+
}
|
571
|
+
|
572
|
+
#[async_trait::async_trait]
|
573
|
+
impl<T> WorkerTestHelpers for T
|
574
|
+
where
|
575
|
+
T: CoreWorker + ?Sized,
|
576
|
+
{
|
577
|
+
async fn complete_execution(&self, run_id: &str) {
|
578
|
+
self.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
579
|
+
run_id.to_string(),
|
580
|
+
vec![CompleteWorkflowExecution { result: None }.into()],
|
581
|
+
))
|
582
|
+
.await
|
583
|
+
.unwrap();
|
584
|
+
}
|
585
|
+
|
586
|
+
async fn complete_timer(&self, run_id: &str, seq: u32, duration: Duration) {
|
587
|
+
self.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
588
|
+
run_id.to_string(),
|
589
|
+
vec![StartTimer {
|
590
|
+
seq,
|
591
|
+
start_to_fire_timeout: Some(duration.try_into().expect("duration fits")),
|
592
|
+
}
|
593
|
+
.into()],
|
594
|
+
))
|
595
|
+
.await
|
596
|
+
.unwrap();
|
597
|
+
}
|
598
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
use std::time::Duration;
|
2
|
+
use temporal_client::{RetryClient, WorkflowClientTrait, WorkflowService};
|
3
|
+
use temporal_sdk_core_protos::temporal::api::workflowservice::v1::DescribeNamespaceRequest;
|
4
|
+
use temporal_sdk_core_test_utils::{get_integ_server_options, CoreWfStarter, NAMESPACE};
|
5
|
+
|
6
|
+
#[tokio::test]
|
7
|
+
async fn can_use_retry_client() {
|
8
|
+
// Not terribly interesting by itself but can be useful for manually inspecting metrics etc
|
9
|
+
let mut core = CoreWfStarter::new("retry_client");
|
10
|
+
let retry_client = core.get_client().await;
|
11
|
+
for _ in 0..10 {
|
12
|
+
retry_client.list_namespaces().await.unwrap();
|
13
|
+
tokio::time::sleep(Duration::from_millis(10)).await;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
#[tokio::test]
|
18
|
+
async fn can_use_retry_raw_client() {
|
19
|
+
let opts = get_integ_server_options();
|
20
|
+
let raw_client = opts.connect_no_namespace(None, None).await.unwrap();
|
21
|
+
let mut retry_client = RetryClient::new(raw_client, opts.retry_config);
|
22
|
+
retry_client
|
23
|
+
.describe_namespace(DescribeNamespaceRequest {
|
24
|
+
namespace: NAMESPACE.to_string(),
|
25
|
+
..Default::default()
|
26
|
+
})
|
27
|
+
.await
|
28
|
+
.unwrap();
|
29
|
+
}
|
30
|
+
|
31
|
+
#[tokio::test]
|
32
|
+
async fn calls_get_system_info() {
|
33
|
+
let opts = get_integ_server_options();
|
34
|
+
let raw_client = opts.connect_no_namespace(None, None).await.unwrap();
|
35
|
+
assert!(raw_client.get_client().capabilities().is_some());
|
36
|
+
}
|