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,185 @@
|
|
1
|
+
use crate::{InterceptedMetricsSvc, RawClientLike};
|
2
|
+
use anyhow::{anyhow, bail};
|
3
|
+
use std::marker::PhantomData;
|
4
|
+
use temporal_sdk_core_protos::{
|
5
|
+
coresdk::FromPayloadsExt,
|
6
|
+
temporal::api::{
|
7
|
+
common::v1::{Payload, WorkflowExecution},
|
8
|
+
enums::v1::HistoryEventFilterType,
|
9
|
+
failure::v1::Failure,
|
10
|
+
history::v1::history_event::Attributes,
|
11
|
+
workflowservice::v1::GetWorkflowExecutionHistoryRequest,
|
12
|
+
},
|
13
|
+
};
|
14
|
+
|
15
|
+
/// Enumerates terminal states for a particular workflow execution
|
16
|
+
// TODO: Add non-proto failure types, flesh out details, etc.
|
17
|
+
#[derive(Debug)]
|
18
|
+
#[allow(clippy::large_enum_variant)]
|
19
|
+
pub enum WorkflowExecutionResult<T> {
|
20
|
+
/// The workflow finished successfully
|
21
|
+
Succeeded(T),
|
22
|
+
/// The workflow finished in failure
|
23
|
+
Failed(Failure),
|
24
|
+
/// The workflow was cancelled
|
25
|
+
Cancelled(Vec<Payload>),
|
26
|
+
/// The workflow was terminated
|
27
|
+
Terminated(Vec<Payload>),
|
28
|
+
/// The workflow timed out
|
29
|
+
TimedOut,
|
30
|
+
/// The workflow continued as new
|
31
|
+
ContinuedAsNew,
|
32
|
+
}
|
33
|
+
|
34
|
+
/// Options for fetching workflow results
|
35
|
+
#[derive(Debug, Clone, Copy)]
|
36
|
+
pub struct GetWorkflowResultOpts {
|
37
|
+
/// If true (the default), follows to the next workflow run in the execution chain while
|
38
|
+
/// retrieving results.
|
39
|
+
pub follow_runs: bool,
|
40
|
+
}
|
41
|
+
impl Default for GetWorkflowResultOpts {
|
42
|
+
fn default() -> Self {
|
43
|
+
Self { follow_runs: true }
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
/// A workflow handle which can refer to a specific workflow run, or a chain of workflow runs with
|
48
|
+
/// the same workflow id.
|
49
|
+
pub struct WorkflowHandle<ClientT, ResultT> {
|
50
|
+
client: ClientT,
|
51
|
+
info: WorkflowExecutionInfo,
|
52
|
+
|
53
|
+
_res_type: PhantomData<ResultT>,
|
54
|
+
}
|
55
|
+
|
56
|
+
/// Holds needed information to refer to a specific workflow run, or workflow execution chain
|
57
|
+
pub struct WorkflowExecutionInfo {
|
58
|
+
/// Namespace the workflow lives in
|
59
|
+
pub namespace: String,
|
60
|
+
/// The workflow's id
|
61
|
+
pub workflow_id: String,
|
62
|
+
/// If set, target this specific run of the workflow
|
63
|
+
pub run_id: Option<String>,
|
64
|
+
}
|
65
|
+
|
66
|
+
impl WorkflowExecutionInfo {
|
67
|
+
/// Bind the workflow info to a specific client, turning it into a workflow handle
|
68
|
+
pub fn bind_untyped<CT>(self, client: CT) -> UntypedWorkflowHandle<CT>
|
69
|
+
where
|
70
|
+
CT: RawClientLike<SvcType = InterceptedMetricsSvc> + Clone,
|
71
|
+
{
|
72
|
+
UntypedWorkflowHandle::new(client, self)
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
/// A workflow handle to a workflow with unknown types. Uses raw payloads.
|
77
|
+
pub type UntypedWorkflowHandle<CT> = WorkflowHandle<CT, Vec<Payload>>;
|
78
|
+
|
79
|
+
impl<CT, RT> WorkflowHandle<CT, RT>
|
80
|
+
where
|
81
|
+
CT: RawClientLike<SvcType = InterceptedMetricsSvc> + Clone,
|
82
|
+
// TODO: Make more generic, capable of (de)serialization w/ serde
|
83
|
+
RT: FromPayloadsExt,
|
84
|
+
{
|
85
|
+
pub(crate) fn new(client: CT, info: WorkflowExecutionInfo) -> Self {
|
86
|
+
Self {
|
87
|
+
client,
|
88
|
+
info,
|
89
|
+
_res_type: PhantomData::<RT>,
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
pub async fn get_workflow_result(
|
94
|
+
&self,
|
95
|
+
opts: GetWorkflowResultOpts,
|
96
|
+
) -> Result<WorkflowExecutionResult<RT>, anyhow::Error> {
|
97
|
+
let mut next_page_tok = vec![];
|
98
|
+
let mut run_id = self.info.run_id.clone().unwrap_or_default();
|
99
|
+
loop {
|
100
|
+
let server_res = self
|
101
|
+
.client
|
102
|
+
.clone()
|
103
|
+
.workflow_client()
|
104
|
+
.get_workflow_execution_history(GetWorkflowExecutionHistoryRequest {
|
105
|
+
namespace: self.info.namespace.to_string(),
|
106
|
+
execution: Some(WorkflowExecution {
|
107
|
+
workflow_id: self.info.workflow_id.clone(),
|
108
|
+
run_id: run_id.clone(),
|
109
|
+
}),
|
110
|
+
skip_archival: true,
|
111
|
+
wait_new_event: true,
|
112
|
+
history_event_filter_type: HistoryEventFilterType::CloseEvent as i32,
|
113
|
+
next_page_token: next_page_tok.clone(),
|
114
|
+
..Default::default()
|
115
|
+
})
|
116
|
+
.await?
|
117
|
+
.into_inner();
|
118
|
+
|
119
|
+
let mut history = server_res
|
120
|
+
.history
|
121
|
+
.ok_or_else(|| anyhow!("Server returned an empty history!"))?;
|
122
|
+
|
123
|
+
if history.events.is_empty() {
|
124
|
+
next_page_tok = server_res.next_page_token;
|
125
|
+
continue;
|
126
|
+
}
|
127
|
+
// If page token was previously set, clear it.
|
128
|
+
next_page_tok = vec![];
|
129
|
+
|
130
|
+
let event_attrs = history.events.pop().and_then(|ev| ev.attributes);
|
131
|
+
|
132
|
+
macro_rules! follow {
|
133
|
+
($attrs:ident) => {
|
134
|
+
if opts.follow_runs && $attrs.new_execution_run_id != "" {
|
135
|
+
run_id = $attrs.new_execution_run_id;
|
136
|
+
continue;
|
137
|
+
}
|
138
|
+
};
|
139
|
+
}
|
140
|
+
|
141
|
+
break match event_attrs {
|
142
|
+
Some(Attributes::WorkflowExecutionCompletedEventAttributes(attrs)) => {
|
143
|
+
follow!(attrs);
|
144
|
+
Ok(WorkflowExecutionResult::Succeeded(RT::from_payloads(
|
145
|
+
attrs.result,
|
146
|
+
)))
|
147
|
+
}
|
148
|
+
Some(Attributes::WorkflowExecutionFailedEventAttributes(attrs)) => {
|
149
|
+
follow!(attrs);
|
150
|
+
Ok(WorkflowExecutionResult::Failed(
|
151
|
+
attrs.failure.unwrap_or_default(),
|
152
|
+
))
|
153
|
+
}
|
154
|
+
Some(Attributes::WorkflowExecutionCanceledEventAttributes(attrs)) => Ok(
|
155
|
+
WorkflowExecutionResult::Cancelled(Vec::from_payloads(attrs.details)),
|
156
|
+
),
|
157
|
+
Some(Attributes::WorkflowExecutionTimedOutEventAttributes(attrs)) => {
|
158
|
+
follow!(attrs);
|
159
|
+
Ok(WorkflowExecutionResult::TimedOut)
|
160
|
+
}
|
161
|
+
Some(Attributes::WorkflowExecutionTerminatedEventAttributes(attrs)) => Ok(
|
162
|
+
WorkflowExecutionResult::Terminated(Vec::from_payloads(attrs.details)),
|
163
|
+
),
|
164
|
+
Some(Attributes::WorkflowExecutionContinuedAsNewEventAttributes(attrs)) => {
|
165
|
+
if opts.follow_runs {
|
166
|
+
if !attrs.new_execution_run_id.is_empty() {
|
167
|
+
run_id = attrs.new_execution_run_id;
|
168
|
+
continue;
|
169
|
+
} else {
|
170
|
+
bail!("New execution run id was empty in continue as new event!");
|
171
|
+
}
|
172
|
+
} else {
|
173
|
+
Ok(WorkflowExecutionResult::ContinuedAsNew)
|
174
|
+
}
|
175
|
+
}
|
176
|
+
o => Err(anyhow!(
|
177
|
+
"Server returned an event that didn't match the CloseEvent filter. \
|
178
|
+
This is either a server bug or a new event the SDK does not understand. \
|
179
|
+
Event details: {:?}",
|
180
|
+
o
|
181
|
+
)),
|
182
|
+
};
|
183
|
+
}
|
184
|
+
}
|
185
|
+
}
|
@@ -0,0 +1,116 @@
|
|
1
|
+
[package]
|
2
|
+
name = "temporal-sdk-core"
|
3
|
+
version = "0.1.0"
|
4
|
+
authors = ["Spencer Judge <spencer@temporal.io>", "Vitaly Arbuzov <vitaly@temporal.io>"]
|
5
|
+
edition = "2021"
|
6
|
+
license-file = "LICENSE.txt"
|
7
|
+
description = "Library for building new Temporal SDKs"
|
8
|
+
homepage = "https://temporal.io/"
|
9
|
+
repository = "https://github.com/temporalio/sdk-core"
|
10
|
+
keywords = ["temporal", "workflow"]
|
11
|
+
categories = ["development-tools"]
|
12
|
+
|
13
|
+
[lib]
|
14
|
+
|
15
|
+
[dependencies]
|
16
|
+
anyhow = "1.0"
|
17
|
+
arc-swap = "1.3"
|
18
|
+
async-channel = "1.6"
|
19
|
+
async-trait = "0.1"
|
20
|
+
base64 = "0.13"
|
21
|
+
crossbeam = "0.8"
|
22
|
+
dashmap = "5.0"
|
23
|
+
derive_builder = "0.11"
|
24
|
+
derive_more = "0.99"
|
25
|
+
enum_dispatch = "0.3"
|
26
|
+
flate2 = "1.0"
|
27
|
+
futures = "0.3"
|
28
|
+
futures-util = "0.3"
|
29
|
+
governor = "0.5"
|
30
|
+
http = "0.2"
|
31
|
+
hyper = "0.14"
|
32
|
+
itertools = "0.10"
|
33
|
+
lazy_static = "1.4"
|
34
|
+
log = "0.4"
|
35
|
+
lru = "0.8"
|
36
|
+
mockall = "0.11"
|
37
|
+
nix = "0.25"
|
38
|
+
once_cell = "1.5"
|
39
|
+
opentelemetry = { version = "0.18", features = ["rt-tokio"] }
|
40
|
+
opentelemetry-otlp = { version = "0.11", features = ["tokio", "metrics"] }
|
41
|
+
opentelemetry-prometheus = "0.11"
|
42
|
+
parking_lot = { version = "0.12", features = ["send_guard"] }
|
43
|
+
prometheus = "0.13"
|
44
|
+
prost = "0.11"
|
45
|
+
prost-types = "0.11"
|
46
|
+
rand = "0.8.3"
|
47
|
+
reqwest = { version = "0.11", features = ["json", "stream", "rustls-tls", "tokio-rustls"], default-features = false }
|
48
|
+
ringbuf = "0.2"
|
49
|
+
serde = "1.0"
|
50
|
+
serde_json = "1.0"
|
51
|
+
siphasher = "0.3"
|
52
|
+
slotmap = "1.0"
|
53
|
+
tar = "0.4"
|
54
|
+
thiserror = "1.0"
|
55
|
+
tokio = { version = "1.1", features = ["rt", "rt-multi-thread", "parking_lot", "time", "fs", "process"] }
|
56
|
+
tokio-util = { version = "0.7", features = ["io", "io-util"] }
|
57
|
+
tokio-stream = "0.1"
|
58
|
+
tonic = { version = "0.8", features = ["tls", "tls-roots"] }
|
59
|
+
tracing = { version = "0.1", features = ["log-always"] }
|
60
|
+
tracing-futures = "0.2"
|
61
|
+
tracing-opentelemetry = "0.18"
|
62
|
+
tracing-subscriber = { version = "0.3", features = ["parking_lot", "env-filter"] }
|
63
|
+
url = "2.2"
|
64
|
+
uuid = { version = "1.1", features = ["v4"] }
|
65
|
+
zip = "0.6"
|
66
|
+
|
67
|
+
# 1st party local deps
|
68
|
+
[dependencies.temporal-sdk-core-api]
|
69
|
+
path = "../core-api"
|
70
|
+
version = "0.1"
|
71
|
+
|
72
|
+
[dependencies.temporal-sdk-core-protos]
|
73
|
+
path = "../sdk-core-protos"
|
74
|
+
version = "0.1"
|
75
|
+
features = ["history_builders"]
|
76
|
+
|
77
|
+
[dependencies.temporal-client]
|
78
|
+
path = "../client"
|
79
|
+
version = "0.1"
|
80
|
+
|
81
|
+
[dependencies.rustfsm]
|
82
|
+
path = "../fsm"
|
83
|
+
version = "0.1"
|
84
|
+
|
85
|
+
[dev-dependencies]
|
86
|
+
assert_matches = "1.4"
|
87
|
+
bimap = "0.6.1"
|
88
|
+
criterion = "0.4"
|
89
|
+
rstest = "0.15"
|
90
|
+
temporal-sdk-core-test-utils = { path = "../test-utils" }
|
91
|
+
temporal-sdk = { path = "../sdk" }
|
92
|
+
|
93
|
+
[build-dependencies]
|
94
|
+
tonic-build = "0.8"
|
95
|
+
|
96
|
+
[[test]]
|
97
|
+
name = "integ_tests"
|
98
|
+
path = "../tests/main.rs"
|
99
|
+
# Prevents autodiscovery, and hence these getting run with `cargo test`. Run with
|
100
|
+
# `cargo test --test integ_tests`
|
101
|
+
test = false
|
102
|
+
|
103
|
+
[[test]]
|
104
|
+
name = "load_tests"
|
105
|
+
path = "../tests/load_tests.rs"
|
106
|
+
test = false
|
107
|
+
|
108
|
+
[[bench]]
|
109
|
+
name = "workflow_replay"
|
110
|
+
harness = false
|
111
|
+
|
112
|
+
# This is maybe a bit hacky, but we call the runner an "example" because that gets it compiling with
|
113
|
+
# the dev-dependencies, which we want.
|
114
|
+
[[example]]
|
115
|
+
name = "integ_runner"
|
116
|
+
path = "../tests/runner.rs"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Temporal Core SDK
|
2
|
+
|
3
|
+
The MIT License
|
4
|
+
|
5
|
+
Copyright (c) 2021 Temporal Technologies, Inc. All Rights Reserved
|
6
|
+
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
9
|
+
in the Software without restriction, including without limitation the rights
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
12
|
+
furnished to do so, subject to the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
15
|
+
copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
SOFTWARE.
|
@@ -0,0 +1,73 @@
|
|
1
|
+
use criterion::{criterion_group, criterion_main, Criterion};
|
2
|
+
use futures::StreamExt;
|
3
|
+
use std::time::Duration;
|
4
|
+
use temporal_sdk::{WfContext, Worker, WorkflowFunction};
|
5
|
+
use temporal_sdk_core::{telemetry_init, TelemetryOptionsBuilder};
|
6
|
+
use temporal_sdk_core_protos::DEFAULT_WORKFLOW_TYPE;
|
7
|
+
use temporal_sdk_core_test_utils::{canned_histories, init_core_replay_preloaded};
|
8
|
+
|
9
|
+
pub fn criterion_benchmark(c: &mut Criterion) {
|
10
|
+
let tokio_runtime = tokio::runtime::Builder::new_current_thread()
|
11
|
+
.enable_time()
|
12
|
+
.build()
|
13
|
+
.unwrap();
|
14
|
+
telemetry_init(&TelemetryOptionsBuilder::default().build().unwrap()).unwrap();
|
15
|
+
let _g = tokio_runtime.enter();
|
16
|
+
|
17
|
+
let num_timers = 10;
|
18
|
+
let t = canned_histories::long_sequential_timers(num_timers as usize);
|
19
|
+
let hist = t.get_full_history_info().unwrap().into();
|
20
|
+
|
21
|
+
c.bench_function("Small history replay", |b| {
|
22
|
+
b.iter(|| {
|
23
|
+
tokio_runtime.block_on(async {
|
24
|
+
let func = timers_wf(num_timers);
|
25
|
+
let (worker, _) = init_core_replay_preloaded("replay_bench", &hist);
|
26
|
+
let mut worker = Worker::new_from_core(worker, "replay_bench".to_string());
|
27
|
+
worker.register_wf(DEFAULT_WORKFLOW_TYPE, func);
|
28
|
+
worker.run().await.unwrap();
|
29
|
+
})
|
30
|
+
})
|
31
|
+
});
|
32
|
+
|
33
|
+
let num_tasks = 50;
|
34
|
+
let t = canned_histories::lots_of_big_signals(num_tasks);
|
35
|
+
let hist = t.get_full_history_info().unwrap().into();
|
36
|
+
|
37
|
+
c.bench_function("Large payloads history replay", |b| {
|
38
|
+
b.iter(|| {
|
39
|
+
tokio_runtime.block_on(async {
|
40
|
+
let func = big_signals_wf(num_tasks);
|
41
|
+
let (worker, _) = init_core_replay_preloaded("large_hist_bench", &hist);
|
42
|
+
let mut worker = Worker::new_from_core(worker, "large_hist_bench".to_string());
|
43
|
+
worker.register_wf(DEFAULT_WORKFLOW_TYPE, func);
|
44
|
+
worker.run().await.unwrap();
|
45
|
+
})
|
46
|
+
})
|
47
|
+
});
|
48
|
+
}
|
49
|
+
|
50
|
+
criterion_group!(benches, criterion_benchmark);
|
51
|
+
criterion_main!(benches);
|
52
|
+
|
53
|
+
fn timers_wf(num_timers: u32) -> WorkflowFunction {
|
54
|
+
WorkflowFunction::new(move |ctx: WfContext| async move {
|
55
|
+
for _ in 1..=num_timers {
|
56
|
+
ctx.timer(Duration::from_secs(1)).await;
|
57
|
+
}
|
58
|
+
Ok(().into())
|
59
|
+
})
|
60
|
+
}
|
61
|
+
|
62
|
+
fn big_signals_wf(num_tasks: usize) -> WorkflowFunction {
|
63
|
+
WorkflowFunction::new(move |ctx: WfContext| async move {
|
64
|
+
let mut sigs = ctx.make_signal_channel("bigsig");
|
65
|
+
for _ in 1..=num_tasks {
|
66
|
+
for _ in 1..=5 {
|
67
|
+
let _ = sigs.next().await.unwrap();
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
Ok(().into())
|
72
|
+
})
|
73
|
+
}
|
@@ -0,0 +1,166 @@
|
|
1
|
+
//! This module contains very generic helpers that can be used codebase-wide
|
2
|
+
|
3
|
+
use crate::MetricsContext;
|
4
|
+
use futures::{stream, Stream, StreamExt};
|
5
|
+
use std::{
|
6
|
+
fmt::{Debug, Formatter},
|
7
|
+
future::Future,
|
8
|
+
sync::Arc,
|
9
|
+
};
|
10
|
+
use tokio::sync::{AcquireError, Notify, OwnedSemaphorePermit, Semaphore, TryAcquireError};
|
11
|
+
|
12
|
+
/// Wraps a [Semaphore] with a function call that is fed the available permits any time a permit is
|
13
|
+
/// acquired or restored through the provided methods
|
14
|
+
#[derive(Clone)]
|
15
|
+
pub(crate) struct MeteredSemaphore {
|
16
|
+
sem: Arc<Semaphore>,
|
17
|
+
metrics_ctx: MetricsContext,
|
18
|
+
record_fn: fn(&MetricsContext, usize),
|
19
|
+
}
|
20
|
+
|
21
|
+
impl MeteredSemaphore {
|
22
|
+
pub fn new(
|
23
|
+
inital_permits: usize,
|
24
|
+
metrics_ctx: MetricsContext,
|
25
|
+
record_fn: fn(&MetricsContext, usize),
|
26
|
+
) -> Self {
|
27
|
+
Self {
|
28
|
+
sem: Arc::new(Semaphore::new(inital_permits)),
|
29
|
+
metrics_ctx,
|
30
|
+
record_fn,
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
pub fn available_permits(&self) -> usize {
|
35
|
+
self.sem.available_permits()
|
36
|
+
}
|
37
|
+
|
38
|
+
pub async fn acquire_owned(&self) -> Result<OwnedMeteredSemPermit, AcquireError> {
|
39
|
+
let res = self.sem.clone().acquire_owned().await?;
|
40
|
+
self.record();
|
41
|
+
Ok(OwnedMeteredSemPermit {
|
42
|
+
inner: res,
|
43
|
+
record_fn: self.record_drop_owned(),
|
44
|
+
})
|
45
|
+
}
|
46
|
+
|
47
|
+
pub fn try_acquire_owned(&self) -> Result<OwnedMeteredSemPermit, TryAcquireError> {
|
48
|
+
let res = self.sem.clone().try_acquire_owned()?;
|
49
|
+
self.record();
|
50
|
+
Ok(OwnedMeteredSemPermit {
|
51
|
+
inner: res,
|
52
|
+
record_fn: self.record_drop_owned(),
|
53
|
+
})
|
54
|
+
}
|
55
|
+
|
56
|
+
fn record(&self) {
|
57
|
+
(self.record_fn)(&self.metrics_ctx, self.sem.available_permits());
|
58
|
+
}
|
59
|
+
|
60
|
+
fn record_drop_owned(&self) -> Box<dyn Fn() + Send + Sync> {
|
61
|
+
let rcf = self.record_fn;
|
62
|
+
let mets = self.metrics_ctx.clone();
|
63
|
+
let sem = self.sem.clone();
|
64
|
+
Box::new(move || rcf(&mets, sem.available_permits() + 1))
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
/// Wraps an [OwnedSemaphorePermit] to update metrics when it's dropped
|
69
|
+
pub(crate) struct OwnedMeteredSemPermit {
|
70
|
+
inner: OwnedSemaphorePermit,
|
71
|
+
record_fn: Box<dyn Fn() + Send + Sync>,
|
72
|
+
}
|
73
|
+
impl Drop for OwnedMeteredSemPermit {
|
74
|
+
fn drop(&mut self) {
|
75
|
+
(self.record_fn)()
|
76
|
+
}
|
77
|
+
}
|
78
|
+
impl Debug for OwnedMeteredSemPermit {
|
79
|
+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
80
|
+
self.inner.fmt(f)
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
/// From the input stream, create a new stream which only pulls from the input stream when allowed.
|
85
|
+
/// When allowed is determined by the passed in `proceeder` which must return a future every time
|
86
|
+
/// it's called. The input stream is only pulled from when that future resolves.
|
87
|
+
pub(crate) fn stream_when_allowed<S, F, FF>(
|
88
|
+
input: S,
|
89
|
+
proceeder: FF,
|
90
|
+
) -> impl Stream<Item = (S::Item, F::Output)>
|
91
|
+
where
|
92
|
+
S: Stream + Send + 'static,
|
93
|
+
F: Future,
|
94
|
+
FF: FnMut() -> F,
|
95
|
+
{
|
96
|
+
let acceptable_notify = Arc::new(Notify::new());
|
97
|
+
acceptable_notify.notify_one();
|
98
|
+
let stream = stream::unfold(
|
99
|
+
(proceeder, input.boxed()),
|
100
|
+
|(mut proceeder, mut input)| async {
|
101
|
+
let v = proceeder().await;
|
102
|
+
input.next().await.map(|i| ((i, v), (proceeder, input)))
|
103
|
+
},
|
104
|
+
);
|
105
|
+
stream
|
106
|
+
}
|
107
|
+
|
108
|
+
macro_rules! dbg_panic {
|
109
|
+
($($arg:tt)*) => {
|
110
|
+
error!($($arg)*);
|
111
|
+
debug_assert!(true, $($arg)*);
|
112
|
+
};
|
113
|
+
}
|
114
|
+
pub(crate) use dbg_panic;
|
115
|
+
|
116
|
+
#[cfg(test)]
|
117
|
+
mod tests {
|
118
|
+
use super::*;
|
119
|
+
use futures::pin_mut;
|
120
|
+
use std::{cell::RefCell, task::Poll};
|
121
|
+
use tokio::sync::mpsc::unbounded_channel;
|
122
|
+
|
123
|
+
// This is fine. Test only / guaranteed to happen serially.
|
124
|
+
#[allow(clippy::await_holding_refcell_ref)]
|
125
|
+
#[test]
|
126
|
+
fn stream_when_allowed_works() {
|
127
|
+
let inputs = stream::iter([1, 2, 3]);
|
128
|
+
let (allow_tx, allow_rx) = unbounded_channel();
|
129
|
+
let allow_rx = RefCell::new(allow_rx);
|
130
|
+
let when_allowed = stream_when_allowed(inputs, || async {
|
131
|
+
allow_rx.borrow_mut().recv().await.unwrap()
|
132
|
+
});
|
133
|
+
|
134
|
+
let waker = futures::task::noop_waker_ref();
|
135
|
+
let mut cx = std::task::Context::from_waker(waker);
|
136
|
+
pin_mut!(when_allowed);
|
137
|
+
|
138
|
+
allow_tx.send(()).unwrap();
|
139
|
+
assert_eq!(
|
140
|
+
when_allowed.poll_next_unpin(&mut cx),
|
141
|
+
Poll::Ready(Some((1, ())))
|
142
|
+
);
|
143
|
+
// Now, it won't be ready
|
144
|
+
for _ in 1..10 {
|
145
|
+
assert_eq!(when_allowed.poll_next_unpin(&mut cx), Poll::Pending);
|
146
|
+
}
|
147
|
+
allow_tx.send(()).unwrap();
|
148
|
+
assert_eq!(
|
149
|
+
when_allowed.poll_next_unpin(&mut cx),
|
150
|
+
Poll::Ready(Some((2, ())))
|
151
|
+
);
|
152
|
+
for _ in 1..10 {
|
153
|
+
assert_eq!(when_allowed.poll_next_unpin(&mut cx), Poll::Pending);
|
154
|
+
}
|
155
|
+
allow_tx.send(()).unwrap();
|
156
|
+
assert_eq!(
|
157
|
+
when_allowed.poll_next_unpin(&mut cx),
|
158
|
+
Poll::Ready(Some((3, ())))
|
159
|
+
);
|
160
|
+
for _ in 1..10 {
|
161
|
+
assert_eq!(when_allowed.poll_next_unpin(&mut cx), Poll::Pending);
|
162
|
+
}
|
163
|
+
allow_tx.send(()).unwrap();
|
164
|
+
assert_eq!(when_allowed.poll_next_unpin(&mut cx), Poll::Ready(None));
|
165
|
+
}
|
166
|
+
}
|