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,683 @@
|
|
1
|
+
mod options;
|
2
|
+
|
3
|
+
pub use options::{
|
4
|
+
ActivityOptions, ChildWorkflowOptions, LocalActivityOptions, Signal, SignalData,
|
5
|
+
SignalWorkflowOptions,
|
6
|
+
};
|
7
|
+
|
8
|
+
use crate::{
|
9
|
+
workflow_context::options::IntoWorkflowCommand, CancelExternalWfResult, CancellableID,
|
10
|
+
CommandCreateRequest, CommandSubscribeChildWorkflowCompletion, RustWfCmd,
|
11
|
+
SignalExternalWfResult, TimerResult, UnblockEvent, Unblockable,
|
12
|
+
};
|
13
|
+
use crossbeam::channel::{Receiver, Sender};
|
14
|
+
use futures::{task::Context, FutureExt, Stream};
|
15
|
+
use parking_lot::RwLock;
|
16
|
+
use std::{
|
17
|
+
collections::HashMap,
|
18
|
+
future::Future,
|
19
|
+
marker::PhantomData,
|
20
|
+
pin::Pin,
|
21
|
+
sync::{
|
22
|
+
atomic::{AtomicBool, Ordering},
|
23
|
+
Arc,
|
24
|
+
},
|
25
|
+
task::Poll,
|
26
|
+
time::{Duration, SystemTime},
|
27
|
+
};
|
28
|
+
use temporal_sdk_core_protos::{
|
29
|
+
coresdk::{
|
30
|
+
activity_result::{activity_resolution, ActivityResolution},
|
31
|
+
child_workflow::ChildWorkflowResult,
|
32
|
+
common::NamespacedWorkflowExecution,
|
33
|
+
workflow_activation::resolve_child_workflow_execution_start::Status as ChildWorkflowStartStatus,
|
34
|
+
workflow_commands::{
|
35
|
+
request_cancel_external_workflow_execution as cancel_we,
|
36
|
+
signal_external_workflow_execution as sig_we, workflow_command,
|
37
|
+
RequestCancelExternalWorkflowExecution, SetPatchMarker,
|
38
|
+
SignalExternalWorkflowExecution, StartTimer, UpsertWorkflowSearchAttributes,
|
39
|
+
},
|
40
|
+
},
|
41
|
+
temporal::api::common::v1::Payload,
|
42
|
+
};
|
43
|
+
use tokio::sync::{mpsc, oneshot, watch};
|
44
|
+
use tokio_stream::wrappers::UnboundedReceiverStream;
|
45
|
+
|
46
|
+
/// Used within workflows to issue commands, get info, etc.
|
47
|
+
pub struct WfContext {
|
48
|
+
namespace: String,
|
49
|
+
task_queue: String,
|
50
|
+
args: Vec<Payload>,
|
51
|
+
|
52
|
+
chan: Sender<RustWfCmd>,
|
53
|
+
am_cancelled: watch::Receiver<bool>,
|
54
|
+
shared: Arc<RwLock<WfContextSharedData>>,
|
55
|
+
|
56
|
+
seq_nums: RwLock<WfCtxProtectedDat>,
|
57
|
+
}
|
58
|
+
|
59
|
+
struct WfCtxProtectedDat {
|
60
|
+
next_timer_sequence_number: u32,
|
61
|
+
next_activity_sequence_number: u32,
|
62
|
+
next_child_workflow_sequence_number: u32,
|
63
|
+
next_cancel_external_wf_sequence_number: u32,
|
64
|
+
next_signal_external_wf_sequence_number: u32,
|
65
|
+
}
|
66
|
+
|
67
|
+
impl WfCtxProtectedDat {
|
68
|
+
fn next_timer_seq(&mut self) -> u32 {
|
69
|
+
let seq = self.next_timer_sequence_number;
|
70
|
+
self.next_timer_sequence_number += 1;
|
71
|
+
seq
|
72
|
+
}
|
73
|
+
fn next_activity_seq(&mut self) -> u32 {
|
74
|
+
let seq = self.next_activity_sequence_number;
|
75
|
+
self.next_activity_sequence_number += 1;
|
76
|
+
seq
|
77
|
+
}
|
78
|
+
fn next_child_workflow_seq(&mut self) -> u32 {
|
79
|
+
let seq = self.next_child_workflow_sequence_number;
|
80
|
+
self.next_child_workflow_sequence_number += 1;
|
81
|
+
seq
|
82
|
+
}
|
83
|
+
fn next_cancel_external_wf_seq(&mut self) -> u32 {
|
84
|
+
let seq = self.next_cancel_external_wf_sequence_number;
|
85
|
+
self.next_cancel_external_wf_sequence_number += 1;
|
86
|
+
seq
|
87
|
+
}
|
88
|
+
fn next_signal_external_wf_seq(&mut self) -> u32 {
|
89
|
+
let seq = self.next_signal_external_wf_sequence_number;
|
90
|
+
self.next_signal_external_wf_sequence_number += 1;
|
91
|
+
seq
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
#[derive(Clone, Debug, Default)]
|
96
|
+
pub struct WfContextSharedData {
|
97
|
+
/// Maps change ids -> resolved status
|
98
|
+
pub changes: HashMap<String, bool>,
|
99
|
+
pub is_replaying: bool,
|
100
|
+
pub wf_time: Option<SystemTime>,
|
101
|
+
}
|
102
|
+
|
103
|
+
// TODO: Dataconverter type interface to replace Payloads here. Possibly just use serde
|
104
|
+
// traits.
|
105
|
+
impl WfContext {
|
106
|
+
/// Create a new wf context, returning the context itself and a receiver which outputs commands
|
107
|
+
/// sent from the workflow.
|
108
|
+
pub(super) fn new(
|
109
|
+
namespace: String,
|
110
|
+
task_queue: String,
|
111
|
+
args: Vec<Payload>,
|
112
|
+
am_cancelled: watch::Receiver<bool>,
|
113
|
+
) -> (Self, Receiver<RustWfCmd>) {
|
114
|
+
// We need to use a normal std channel since our receiving side is non-async
|
115
|
+
let (chan, rx) = crossbeam::channel::unbounded();
|
116
|
+
(
|
117
|
+
Self {
|
118
|
+
namespace,
|
119
|
+
task_queue,
|
120
|
+
args,
|
121
|
+
chan,
|
122
|
+
am_cancelled,
|
123
|
+
shared: Arc::new(RwLock::new(Default::default())),
|
124
|
+
seq_nums: RwLock::new(WfCtxProtectedDat {
|
125
|
+
next_timer_sequence_number: 1,
|
126
|
+
next_activity_sequence_number: 1,
|
127
|
+
next_child_workflow_sequence_number: 1,
|
128
|
+
next_cancel_external_wf_sequence_number: 1,
|
129
|
+
next_signal_external_wf_sequence_number: 1,
|
130
|
+
}),
|
131
|
+
},
|
132
|
+
rx,
|
133
|
+
)
|
134
|
+
}
|
135
|
+
|
136
|
+
/// Return the namespace the workflow is executing in
|
137
|
+
pub fn namespace(&self) -> &str {
|
138
|
+
&self.namespace
|
139
|
+
}
|
140
|
+
|
141
|
+
/// Get the arguments provided to the workflow upon execution start
|
142
|
+
pub fn get_args(&self) -> &[Payload] {
|
143
|
+
self.args.as_slice()
|
144
|
+
}
|
145
|
+
|
146
|
+
/// Return the current time according to the workflow (which is not wall-clock time).
|
147
|
+
pub fn workflow_time(&self) -> Option<SystemTime> {
|
148
|
+
self.shared.read().wf_time
|
149
|
+
}
|
150
|
+
|
151
|
+
pub(crate) fn get_shared_data(&self) -> Arc<RwLock<WfContextSharedData>> {
|
152
|
+
self.shared.clone()
|
153
|
+
}
|
154
|
+
|
155
|
+
/// A future that resolves if/when the workflow is cancelled
|
156
|
+
pub async fn cancelled(&mut self) {
|
157
|
+
if *self.am_cancelled.borrow() {
|
158
|
+
return;
|
159
|
+
}
|
160
|
+
self.am_cancelled
|
161
|
+
.changed()
|
162
|
+
.await
|
163
|
+
.expect("Cancelled send half not dropped");
|
164
|
+
}
|
165
|
+
|
166
|
+
/// Request to create a timer
|
167
|
+
pub fn timer(&self, duration: Duration) -> impl CancellableFuture<TimerResult> {
|
168
|
+
let seq = self.seq_nums.write().next_timer_seq();
|
169
|
+
let (cmd, unblocker) = CancellableWFCommandFut::new(CancellableID::Timer(seq));
|
170
|
+
self.send(
|
171
|
+
CommandCreateRequest {
|
172
|
+
cmd: StartTimer {
|
173
|
+
seq,
|
174
|
+
start_to_fire_timeout: Some(
|
175
|
+
duration
|
176
|
+
.try_into()
|
177
|
+
.expect("Durations must fit into 64 bits"),
|
178
|
+
),
|
179
|
+
}
|
180
|
+
.into(),
|
181
|
+
unblocker,
|
182
|
+
}
|
183
|
+
.into(),
|
184
|
+
);
|
185
|
+
cmd
|
186
|
+
}
|
187
|
+
|
188
|
+
/// Request to run an activity
|
189
|
+
pub fn activity(
|
190
|
+
&self,
|
191
|
+
mut opts: ActivityOptions,
|
192
|
+
) -> impl CancellableFuture<ActivityResolution> {
|
193
|
+
if opts.task_queue.is_empty() {
|
194
|
+
opts.task_queue = self.task_queue.clone()
|
195
|
+
}
|
196
|
+
let seq = self.seq_nums.write().next_activity_seq();
|
197
|
+
let (cmd, unblocker) = CancellableWFCommandFut::new(CancellableID::Activity(seq));
|
198
|
+
self.send(
|
199
|
+
CommandCreateRequest {
|
200
|
+
cmd: opts.into_command(seq).into(),
|
201
|
+
unblocker,
|
202
|
+
}
|
203
|
+
.into(),
|
204
|
+
);
|
205
|
+
cmd
|
206
|
+
}
|
207
|
+
|
208
|
+
/// Request to run a local activity
|
209
|
+
pub fn local_activity(
|
210
|
+
&self,
|
211
|
+
opts: LocalActivityOptions,
|
212
|
+
) -> impl CancellableFuture<ActivityResolution> + '_ {
|
213
|
+
LATimerBackoffFut::new(opts, self)
|
214
|
+
}
|
215
|
+
|
216
|
+
/// Request to run a local activity with no implementation of timer-backoff based retrying.
|
217
|
+
fn local_activity_no_timer_retry(
|
218
|
+
&self,
|
219
|
+
opts: LocalActivityOptions,
|
220
|
+
) -> impl CancellableFuture<ActivityResolution> {
|
221
|
+
let seq = self.seq_nums.write().next_activity_seq();
|
222
|
+
let (cmd, unblocker) = CancellableWFCommandFut::new(CancellableID::LocalActivity(seq));
|
223
|
+
self.send(
|
224
|
+
CommandCreateRequest {
|
225
|
+
cmd: opts.into_command(seq).into(),
|
226
|
+
unblocker,
|
227
|
+
}
|
228
|
+
.into(),
|
229
|
+
);
|
230
|
+
cmd
|
231
|
+
}
|
232
|
+
|
233
|
+
/// Creates a child workflow stub with the provided options
|
234
|
+
pub fn child_workflow(&self, opts: ChildWorkflowOptions) -> ChildWorkflow {
|
235
|
+
ChildWorkflow { opts }
|
236
|
+
}
|
237
|
+
|
238
|
+
/// Check (or record) that this workflow history was created with the provided patch
|
239
|
+
pub fn patched(&self, patch_id: &str) -> bool {
|
240
|
+
self.patch_impl(patch_id, false)
|
241
|
+
}
|
242
|
+
|
243
|
+
/// Record that this workflow history was created with the provided patch, and it is being
|
244
|
+
/// phased out.
|
245
|
+
pub fn deprecate_patch(&self, patch_id: &str) {
|
246
|
+
self.patch_impl(patch_id, true);
|
247
|
+
}
|
248
|
+
|
249
|
+
fn patch_impl(&self, patch_id: &str, deprecated: bool) -> bool {
|
250
|
+
self.send(
|
251
|
+
workflow_command::Variant::SetPatchMarker(SetPatchMarker {
|
252
|
+
patch_id: patch_id.to_string(),
|
253
|
+
deprecated,
|
254
|
+
})
|
255
|
+
.into(),
|
256
|
+
);
|
257
|
+
// See if we already know about the status of this change
|
258
|
+
if let Some(present) = self.shared.read().changes.get(patch_id) {
|
259
|
+
return *present;
|
260
|
+
}
|
261
|
+
|
262
|
+
// If we don't already know about the change, that means there is no marker in history,
|
263
|
+
// and we should return false if we are replaying
|
264
|
+
let res = !self.shared.read().is_replaying;
|
265
|
+
|
266
|
+
self.shared
|
267
|
+
.write()
|
268
|
+
.changes
|
269
|
+
.insert(patch_id.to_string(), res);
|
270
|
+
|
271
|
+
res
|
272
|
+
}
|
273
|
+
|
274
|
+
/// Send a signal to an external workflow. May resolve as a failure if the signal didn't work
|
275
|
+
/// or was cancelled.
|
276
|
+
pub fn signal_workflow(
|
277
|
+
&self,
|
278
|
+
opts: impl Into<SignalWorkflowOptions>,
|
279
|
+
) -> impl CancellableFuture<SignalExternalWfResult> {
|
280
|
+
let options: SignalWorkflowOptions = opts.into();
|
281
|
+
let target = sig_we::Target::WorkflowExecution(NamespacedWorkflowExecution {
|
282
|
+
namespace: self.namespace.clone(),
|
283
|
+
workflow_id: options.workflow_id,
|
284
|
+
run_id: options.run_id.unwrap_or_default(),
|
285
|
+
});
|
286
|
+
self.send_signal_wf(target, options.signal)
|
287
|
+
}
|
288
|
+
|
289
|
+
/// Add or create a set of search attributes
|
290
|
+
pub fn upsert_search_attributes(&self, attr_iter: impl IntoIterator<Item = (String, Payload)>) {
|
291
|
+
self.send(RustWfCmd::NewNonblockingCmd(
|
292
|
+
workflow_command::Variant::UpsertWorkflowSearchAttributes(
|
293
|
+
UpsertWorkflowSearchAttributes {
|
294
|
+
search_attributes: HashMap::from_iter(attr_iter.into_iter()),
|
295
|
+
},
|
296
|
+
),
|
297
|
+
))
|
298
|
+
}
|
299
|
+
|
300
|
+
/// Return a stream that produces values when the named signal is sent to this workflow
|
301
|
+
pub fn make_signal_channel(&self, signal_name: impl Into<String>) -> DrainableSignalStream {
|
302
|
+
let (tx, rx) = mpsc::unbounded_channel();
|
303
|
+
self.send(RustWfCmd::SubscribeSignal(signal_name.into(), tx));
|
304
|
+
DrainableSignalStream(UnboundedReceiverStream::new(rx))
|
305
|
+
}
|
306
|
+
|
307
|
+
/// Force a workflow task failure (EX: in order to retry on non-sticky queue)
|
308
|
+
pub fn force_task_fail(&self, with: anyhow::Error) {
|
309
|
+
self.send(with.into());
|
310
|
+
}
|
311
|
+
|
312
|
+
/// Request the cancellation of an external workflow. May resolve as a failure if the workflow
|
313
|
+
/// was not found or the cancel was otherwise unsendable.
|
314
|
+
pub fn cancel_external(
|
315
|
+
&self,
|
316
|
+
target: NamespacedWorkflowExecution,
|
317
|
+
) -> impl Future<Output = CancelExternalWfResult> {
|
318
|
+
let target = cancel_we::Target::WorkflowExecution(target);
|
319
|
+
let seq = self.seq_nums.write().next_cancel_external_wf_seq();
|
320
|
+
let (cmd, unblocker) = WFCommandFut::new();
|
321
|
+
self.send(
|
322
|
+
CommandCreateRequest {
|
323
|
+
cmd: RequestCancelExternalWorkflowExecution {
|
324
|
+
seq,
|
325
|
+
target: Some(target),
|
326
|
+
}
|
327
|
+
.into(),
|
328
|
+
unblocker,
|
329
|
+
}
|
330
|
+
.into(),
|
331
|
+
);
|
332
|
+
cmd
|
333
|
+
}
|
334
|
+
|
335
|
+
fn send_signal_wf(
|
336
|
+
&self,
|
337
|
+
target: sig_we::Target,
|
338
|
+
signal: Signal,
|
339
|
+
) -> impl CancellableFuture<SignalExternalWfResult> {
|
340
|
+
let seq = self.seq_nums.write().next_signal_external_wf_seq();
|
341
|
+
let (cmd, unblocker) =
|
342
|
+
CancellableWFCommandFut::new(CancellableID::SignalExternalWorkflow(seq));
|
343
|
+
self.send(
|
344
|
+
CommandCreateRequest {
|
345
|
+
cmd: SignalExternalWorkflowExecution {
|
346
|
+
seq,
|
347
|
+
signal_name: signal.signal_name,
|
348
|
+
args: signal.data.input,
|
349
|
+
target: Some(target),
|
350
|
+
headers: signal.data.headers,
|
351
|
+
}
|
352
|
+
.into(),
|
353
|
+
unblocker,
|
354
|
+
}
|
355
|
+
.into(),
|
356
|
+
);
|
357
|
+
cmd
|
358
|
+
}
|
359
|
+
|
360
|
+
/// Cancel any cancellable operation by ID
|
361
|
+
fn cancel(&self, cancellable_id: CancellableID) {
|
362
|
+
self.send(RustWfCmd::Cancel(cancellable_id));
|
363
|
+
}
|
364
|
+
|
365
|
+
fn send(&self, c: RustWfCmd) {
|
366
|
+
self.chan.send(c).unwrap();
|
367
|
+
}
|
368
|
+
}
|
369
|
+
|
370
|
+
/// Helper Wrapper that can drain the channel into a Vec<SignalData> in a blocking way. Useful
|
371
|
+
/// for making sure channels are empty before ContinueAsNew-ing a workflow
|
372
|
+
pub struct DrainableSignalStream(UnboundedReceiverStream<SignalData>);
|
373
|
+
|
374
|
+
impl DrainableSignalStream {
|
375
|
+
pub fn drain_all(self) -> Vec<SignalData> {
|
376
|
+
let mut receiver = self.0.into_inner();
|
377
|
+
let mut signals = vec![];
|
378
|
+
while let Ok(s) = receiver.try_recv() {
|
379
|
+
signals.push(s);
|
380
|
+
}
|
381
|
+
signals
|
382
|
+
}
|
383
|
+
}
|
384
|
+
|
385
|
+
impl Stream for DrainableSignalStream {
|
386
|
+
type Item = SignalData;
|
387
|
+
|
388
|
+
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
389
|
+
Pin::new(&mut self.0).poll_next(cx)
|
390
|
+
}
|
391
|
+
}
|
392
|
+
|
393
|
+
/// A Future that can be cancelled.
|
394
|
+
/// Used in the prototype SDK for cancelling operations like timers and activities.
|
395
|
+
pub trait CancellableFuture<T>: Future<Output = T> {
|
396
|
+
/// Cancel this Future
|
397
|
+
fn cancel(&self, cx: &WfContext);
|
398
|
+
}
|
399
|
+
|
400
|
+
struct WFCommandFut<T, D> {
|
401
|
+
_unused: PhantomData<T>,
|
402
|
+
result_rx: oneshot::Receiver<UnblockEvent>,
|
403
|
+
other_dat: Option<D>,
|
404
|
+
}
|
405
|
+
impl<T> WFCommandFut<T, ()> {
|
406
|
+
fn new() -> (Self, oneshot::Sender<UnblockEvent>) {
|
407
|
+
Self::new_with_dat(())
|
408
|
+
}
|
409
|
+
}
|
410
|
+
|
411
|
+
impl<T, D> WFCommandFut<T, D> {
|
412
|
+
fn new_with_dat(other_dat: D) -> (Self, oneshot::Sender<UnblockEvent>) {
|
413
|
+
let (tx, rx) = oneshot::channel();
|
414
|
+
(
|
415
|
+
Self {
|
416
|
+
_unused: PhantomData,
|
417
|
+
result_rx: rx,
|
418
|
+
other_dat: Some(other_dat),
|
419
|
+
},
|
420
|
+
tx,
|
421
|
+
)
|
422
|
+
}
|
423
|
+
}
|
424
|
+
|
425
|
+
impl<T, D> Unpin for WFCommandFut<T, D> where T: Unblockable<OtherDat = D> {}
|
426
|
+
impl<T, D> Future for WFCommandFut<T, D>
|
427
|
+
where
|
428
|
+
T: Unblockable<OtherDat = D>,
|
429
|
+
{
|
430
|
+
type Output = T;
|
431
|
+
|
432
|
+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
433
|
+
self.result_rx.poll_unpin(cx).map(|x| {
|
434
|
+
// SAFETY: Because we can only enter this section once the future has resolved, we
|
435
|
+
// know it will never be polled again, therefore consuming the option is OK.
|
436
|
+
let od = self
|
437
|
+
.other_dat
|
438
|
+
.take()
|
439
|
+
.expect("Other data must exist when resolving command future");
|
440
|
+
Unblockable::unblock(x.unwrap(), od)
|
441
|
+
})
|
442
|
+
}
|
443
|
+
}
|
444
|
+
|
445
|
+
struct CancellableWFCommandFut<T, D> {
|
446
|
+
cmd_fut: WFCommandFut<T, D>,
|
447
|
+
cancellable_id: CancellableID,
|
448
|
+
}
|
449
|
+
impl<T> CancellableWFCommandFut<T, ()> {
|
450
|
+
fn new(cancellable_id: CancellableID) -> (Self, oneshot::Sender<UnblockEvent>) {
|
451
|
+
Self::new_with_dat(cancellable_id, ())
|
452
|
+
}
|
453
|
+
}
|
454
|
+
impl<T, D> CancellableWFCommandFut<T, D> {
|
455
|
+
fn new_with_dat(
|
456
|
+
cancellable_id: CancellableID,
|
457
|
+
other_dat: D,
|
458
|
+
) -> (Self, oneshot::Sender<UnblockEvent>) {
|
459
|
+
let (cmd_fut, sender) = WFCommandFut::new_with_dat(other_dat);
|
460
|
+
(
|
461
|
+
Self {
|
462
|
+
cmd_fut,
|
463
|
+
cancellable_id,
|
464
|
+
},
|
465
|
+
sender,
|
466
|
+
)
|
467
|
+
}
|
468
|
+
}
|
469
|
+
impl<T, D> Unpin for CancellableWFCommandFut<T, D> where T: Unblockable<OtherDat = D> {}
|
470
|
+
impl<T, D> Future for CancellableWFCommandFut<T, D>
|
471
|
+
where
|
472
|
+
T: Unblockable<OtherDat = D>,
|
473
|
+
{
|
474
|
+
type Output = T;
|
475
|
+
|
476
|
+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
477
|
+
self.cmd_fut.poll_unpin(cx)
|
478
|
+
}
|
479
|
+
}
|
480
|
+
|
481
|
+
impl<T, D> CancellableFuture<T> for CancellableWFCommandFut<T, D>
|
482
|
+
where
|
483
|
+
T: Unblockable<OtherDat = D>,
|
484
|
+
{
|
485
|
+
fn cancel(&self, cx: &WfContext) {
|
486
|
+
cx.cancel(self.cancellable_id.clone());
|
487
|
+
}
|
488
|
+
}
|
489
|
+
|
490
|
+
struct LATimerBackoffFut<'a> {
|
491
|
+
la_opts: LocalActivityOptions,
|
492
|
+
current_fut: Pin<Box<dyn CancellableFuture<ActivityResolution> + Send + Unpin + 'a>>,
|
493
|
+
timer_fut: Option<Pin<Box<dyn CancellableFuture<TimerResult> + Send + Unpin + 'a>>>,
|
494
|
+
ctx: &'a WfContext,
|
495
|
+
next_attempt: u32,
|
496
|
+
next_sched_time: Option<prost_types::Timestamp>,
|
497
|
+
did_cancel: AtomicBool,
|
498
|
+
}
|
499
|
+
impl<'a> LATimerBackoffFut<'a> {
|
500
|
+
pub(crate) fn new(opts: LocalActivityOptions, ctx: &'a WfContext) -> Self {
|
501
|
+
Self {
|
502
|
+
la_opts: opts.clone(),
|
503
|
+
current_fut: Box::pin(ctx.local_activity_no_timer_retry(opts)),
|
504
|
+
timer_fut: None,
|
505
|
+
ctx,
|
506
|
+
next_attempt: 1,
|
507
|
+
next_sched_time: None,
|
508
|
+
did_cancel: AtomicBool::new(false),
|
509
|
+
}
|
510
|
+
}
|
511
|
+
}
|
512
|
+
impl<'a> Unpin for LATimerBackoffFut<'a> {}
|
513
|
+
impl<'a> Future for LATimerBackoffFut<'a> {
|
514
|
+
type Output = ActivityResolution;
|
515
|
+
|
516
|
+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
517
|
+
// If the timer exists, wait for it first
|
518
|
+
if let Some(tf) = self.timer_fut.as_mut() {
|
519
|
+
return match tf.poll_unpin(cx) {
|
520
|
+
Poll::Ready(tr) => {
|
521
|
+
self.timer_fut = None;
|
522
|
+
// Schedule next LA if this timer wasn't cancelled
|
523
|
+
if let TimerResult::Fired = tr {
|
524
|
+
let mut opts = self.la_opts.clone();
|
525
|
+
opts.attempt = Some(self.next_attempt);
|
526
|
+
opts.original_schedule_time = self.next_sched_time.clone();
|
527
|
+
self.current_fut = Box::pin(self.ctx.local_activity_no_timer_retry(opts));
|
528
|
+
Poll::Pending
|
529
|
+
} else {
|
530
|
+
Poll::Ready(ActivityResolution {
|
531
|
+
status: Some(
|
532
|
+
activity_resolution::Status::Cancelled(Default::default()),
|
533
|
+
),
|
534
|
+
})
|
535
|
+
}
|
536
|
+
}
|
537
|
+
Poll::Pending => Poll::Pending,
|
538
|
+
};
|
539
|
+
}
|
540
|
+
let poll_res = self.current_fut.poll_unpin(cx);
|
541
|
+
if let Poll::Ready(ref r) = poll_res {
|
542
|
+
// If we've already said we want to cancel, don't schedule the backoff timer. Just
|
543
|
+
// return cancel status. This can happen if cancel comes after the LA says it wants to
|
544
|
+
// back off but before we have scheduled the timer.
|
545
|
+
if self.did_cancel.load(Ordering::Acquire) {
|
546
|
+
return Poll::Ready(ActivityResolution {
|
547
|
+
status: Some(activity_resolution::Status::Cancelled(Default::default())),
|
548
|
+
});
|
549
|
+
}
|
550
|
+
|
551
|
+
if let Some(activity_resolution::Status::Backoff(b)) = r.status.as_ref() {
|
552
|
+
let timer_f = self.ctx.timer(
|
553
|
+
b.backoff_duration
|
554
|
+
.clone()
|
555
|
+
.expect("Duration is set")
|
556
|
+
.try_into()
|
557
|
+
.expect("duration converts ok"),
|
558
|
+
);
|
559
|
+
self.timer_fut = Some(Box::pin(timer_f));
|
560
|
+
self.next_attempt = b.attempt;
|
561
|
+
self.next_sched_time = b.original_schedule_time.clone();
|
562
|
+
return Poll::Pending;
|
563
|
+
}
|
564
|
+
}
|
565
|
+
poll_res
|
566
|
+
}
|
567
|
+
}
|
568
|
+
impl<'a> CancellableFuture<ActivityResolution> for LATimerBackoffFut<'a> {
|
569
|
+
fn cancel(&self, ctx: &WfContext) {
|
570
|
+
self.did_cancel.store(true, Ordering::Release);
|
571
|
+
if let Some(tf) = self.timer_fut.as_ref() {
|
572
|
+
tf.cancel(ctx);
|
573
|
+
}
|
574
|
+
self.current_fut.cancel(ctx);
|
575
|
+
}
|
576
|
+
}
|
577
|
+
|
578
|
+
/// A stub representing an unstarted child workflow.
|
579
|
+
#[derive(Default, Debug, Clone)]
|
580
|
+
pub struct ChildWorkflow {
|
581
|
+
opts: ChildWorkflowOptions,
|
582
|
+
}
|
583
|
+
|
584
|
+
pub struct ChildWfCommon {
|
585
|
+
workflow_id: String,
|
586
|
+
result_future: CancellableWFCommandFut<ChildWorkflowResult, ()>,
|
587
|
+
}
|
588
|
+
|
589
|
+
pub struct PendingChildWorkflow {
|
590
|
+
pub status: ChildWorkflowStartStatus,
|
591
|
+
pub common: ChildWfCommon,
|
592
|
+
}
|
593
|
+
|
594
|
+
impl PendingChildWorkflow {
|
595
|
+
/// Returns `None` if the child did not start successfully. The returned [StartedChildWorkflow]
|
596
|
+
/// can be used to wait on, signal, or cancel the child workflow.
|
597
|
+
pub fn into_started(self) -> Option<StartedChildWorkflow> {
|
598
|
+
match self.status {
|
599
|
+
ChildWorkflowStartStatus::Succeeded(s) => Some(StartedChildWorkflow {
|
600
|
+
run_id: s.run_id,
|
601
|
+
common: self.common,
|
602
|
+
}),
|
603
|
+
_ => None,
|
604
|
+
}
|
605
|
+
}
|
606
|
+
}
|
607
|
+
|
608
|
+
pub struct StartedChildWorkflow {
|
609
|
+
pub run_id: String,
|
610
|
+
common: ChildWfCommon,
|
611
|
+
}
|
612
|
+
|
613
|
+
impl ChildWorkflow {
|
614
|
+
/// Start the child workflow, the returned Future is cancellable.
|
615
|
+
pub fn start(self, cx: &WfContext) -> impl CancellableFuture<PendingChildWorkflow> {
|
616
|
+
let child_seq = cx.seq_nums.write().next_child_workflow_seq();
|
617
|
+
// Immediately create the command/future for the result, otherwise if the user does
|
618
|
+
// not await the result until *after* we receive an activation for it, there will be nothing
|
619
|
+
// to match when unblocking.
|
620
|
+
let cancel_seq = cx.seq_nums.write().next_cancel_external_wf_seq();
|
621
|
+
let (result_cmd, unblocker) =
|
622
|
+
CancellableWFCommandFut::new(CancellableID::ExternalWorkflow {
|
623
|
+
seqnum: cancel_seq,
|
624
|
+
execution: NamespacedWorkflowExecution {
|
625
|
+
workflow_id: self.opts.workflow_id.clone(),
|
626
|
+
..Default::default()
|
627
|
+
},
|
628
|
+
only_child: true,
|
629
|
+
});
|
630
|
+
cx.send(
|
631
|
+
CommandSubscribeChildWorkflowCompletion {
|
632
|
+
seq: child_seq,
|
633
|
+
unblocker,
|
634
|
+
}
|
635
|
+
.into(),
|
636
|
+
);
|
637
|
+
|
638
|
+
let common = ChildWfCommon {
|
639
|
+
workflow_id: self.opts.workflow_id.clone(),
|
640
|
+
result_future: result_cmd,
|
641
|
+
};
|
642
|
+
|
643
|
+
let (cmd, unblocker) =
|
644
|
+
CancellableWFCommandFut::new_with_dat(CancellableID::ChildWorkflow(child_seq), common);
|
645
|
+
cx.send(
|
646
|
+
CommandCreateRequest {
|
647
|
+
cmd: self.opts.into_command(child_seq).into(),
|
648
|
+
unblocker,
|
649
|
+
}
|
650
|
+
.into(),
|
651
|
+
);
|
652
|
+
|
653
|
+
cmd
|
654
|
+
}
|
655
|
+
}
|
656
|
+
|
657
|
+
impl StartedChildWorkflow {
|
658
|
+
/// Consumes self and returns a future that will wait until completion of this child workflow
|
659
|
+
/// execution
|
660
|
+
pub fn result(self) -> impl CancellableFuture<ChildWorkflowResult> {
|
661
|
+
self.common.result_future
|
662
|
+
}
|
663
|
+
|
664
|
+
/// Cancel the child workflow
|
665
|
+
pub fn cancel(&self, cx: &WfContext) -> impl Future<Output = CancelExternalWfResult> {
|
666
|
+
let target = NamespacedWorkflowExecution {
|
667
|
+
namespace: cx.namespace().to_string(),
|
668
|
+
workflow_id: self.common.workflow_id.clone(),
|
669
|
+
..Default::default()
|
670
|
+
};
|
671
|
+
cx.cancel_external(target)
|
672
|
+
}
|
673
|
+
|
674
|
+
/// Signal the child workflow
|
675
|
+
pub fn signal(
|
676
|
+
&self,
|
677
|
+
cx: &WfContext,
|
678
|
+
data: impl Into<Signal>,
|
679
|
+
) -> impl CancellableFuture<SignalExternalWfResult> {
|
680
|
+
let target = sig_we::Target::ChildWorkflowId(self.common.workflow_id.clone());
|
681
|
+
cx.send_signal_wf(target, data.into())
|
682
|
+
}
|
683
|
+
}
|