temporalio 0.0.1 → 0.1.0
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 +4 -4
- data/README.md +180 -7
- data/bridge/Cargo.lock +208 -76
- data/bridge/Cargo.toml +5 -2
- data/bridge/sdk-core/Cargo.toml +1 -1
- data/bridge/sdk-core/README.md +20 -10
- data/bridge/sdk-core/client/Cargo.toml +1 -1
- data/bridge/sdk-core/client/src/lib.rs +227 -59
- data/bridge/sdk-core/client/src/metrics.rs +17 -8
- data/bridge/sdk-core/client/src/raw.rs +13 -12
- data/bridge/sdk-core/client/src/retry.rs +132 -43
- data/bridge/sdk-core/core/Cargo.toml +28 -15
- data/bridge/sdk-core/core/benches/workflow_replay.rs +13 -10
- data/bridge/sdk-core/core/src/abstractions.rs +225 -36
- data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +217 -79
- data/bridge/sdk-core/core/src/core_tests/determinism.rs +165 -2
- data/bridge/sdk-core/core/src/core_tests/local_activities.rs +565 -34
- data/bridge/sdk-core/core/src/core_tests/queries.rs +247 -90
- data/bridge/sdk-core/core/src/core_tests/workers.rs +3 -5
- data/bridge/sdk-core/core/src/core_tests/workflow_cancels.rs +1 -1
- data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +430 -67
- data/bridge/sdk-core/core/src/ephemeral_server/mod.rs +106 -12
- data/bridge/sdk-core/core/src/internal_flags.rs +136 -0
- data/bridge/sdk-core/core/src/lib.rs +148 -34
- data/bridge/sdk-core/core/src/protosext/mod.rs +1 -1
- data/bridge/sdk-core/core/src/replay/mod.rs +185 -41
- data/bridge/sdk-core/core/src/telemetry/log_export.rs +190 -0
- data/bridge/sdk-core/core/src/telemetry/metrics.rs +219 -140
- data/bridge/sdk-core/core/src/telemetry/mod.rs +326 -315
- data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +20 -14
- data/bridge/sdk-core/core/src/test_help/mod.rs +85 -21
- data/bridge/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +112 -156
- data/bridge/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
- data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +364 -128
- data/bridge/sdk-core/core/src/worker/activities.rs +263 -170
- data/bridge/sdk-core/core/src/worker/client/mocks.rs +23 -3
- data/bridge/sdk-core/core/src/worker/client.rs +48 -6
- data/bridge/sdk-core/core/src/worker/mod.rs +186 -75
- data/bridge/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
- data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +13 -24
- data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +879 -226
- data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +101 -48
- data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +8 -12
- data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +6 -9
- data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +90 -32
- data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +6 -9
- data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +7 -10
- data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +6 -9
- data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +160 -83
- data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +36 -54
- data/bridge/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +179 -0
- data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +104 -157
- data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +8 -12
- data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +9 -13
- data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +10 -4
- data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +14 -11
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +6 -17
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +395 -299
- data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +12 -20
- data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +33 -18
- data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +1032 -374
- data/bridge/sdk-core/core/src/worker/workflow/mod.rs +525 -392
- data/bridge/sdk-core/core/src/worker/workflow/run_cache.rs +40 -57
- data/bridge/sdk-core/core/src/worker/workflow/wft_extraction.rs +125 -0
- data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +3 -6
- data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +117 -0
- data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
- data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +456 -681
- data/bridge/sdk-core/core-api/Cargo.toml +6 -4
- data/bridge/sdk-core/core-api/src/errors.rs +1 -34
- data/bridge/sdk-core/core-api/src/lib.rs +7 -45
- data/bridge/sdk-core/core-api/src/telemetry.rs +141 -0
- data/bridge/sdk-core/core-api/src/worker.rs +27 -1
- data/bridge/sdk-core/etc/deps.svg +115 -140
- data/bridge/sdk-core/etc/regen-depgraph.sh +5 -0
- data/bridge/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +18 -15
- data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +1 -1
- data/bridge/sdk-core/fsm/rustfsm_trait/src/lib.rs +8 -3
- data/bridge/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
- data/bridge/sdk-core/histories/evict_while_la_running_no_interference-23_history.bin +0 -0
- data/bridge/sdk-core/histories/evict_while_la_running_no_interference-85_history.bin +0 -0
- data/bridge/sdk-core/protos/api_upstream/buf.yaml +0 -3
- data/bridge/sdk-core/protos/api_upstream/build/go.mod +7 -0
- data/bridge/sdk-core/protos/api_upstream/build/go.sum +5 -0
- data/bridge/sdk-core/protos/api_upstream/{temporal/api/enums/v1/cluster.proto → build/tools.go} +7 -18
- data/bridge/sdk-core/protos/api_upstream/go.mod +6 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +12 -9
- data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +15 -26
- data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +13 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +4 -9
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +3 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +10 -8
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +28 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +24 -19
- data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +62 -26
- data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +4 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +24 -61
- data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +2 -21
- data/bridge/sdk-core/protos/api_upstream/temporal/api/protocol/v1/message.proto +57 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +110 -31
- data/bridge/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
- data/bridge/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +4 -4
- data/bridge/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +71 -6
- data/bridge/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +2 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +3 -2
- data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +111 -36
- data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +19 -5
- data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +1 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +9 -0
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +9 -1
- data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +6 -0
- data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +2 -2
- data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +2 -2
- data/bridge/sdk-core/sdk/Cargo.toml +4 -3
- data/bridge/sdk-core/sdk/src/interceptors.rs +36 -3
- data/bridge/sdk-core/sdk/src/lib.rs +94 -25
- data/bridge/sdk-core/sdk/src/workflow_context.rs +13 -2
- data/bridge/sdk-core/sdk/src/workflow_future.rs +10 -13
- data/bridge/sdk-core/sdk-core-protos/Cargo.toml +5 -2
- data/bridge/sdk-core/sdk-core-protos/build.rs +36 -2
- data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +164 -104
- data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +27 -23
- data/bridge/sdk-core/sdk-core-protos/src/lib.rs +252 -74
- data/bridge/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
- data/bridge/sdk-core/test-utils/Cargo.toml +4 -1
- data/bridge/sdk-core/test-utils/src/canned_histories.rs +106 -296
- data/bridge/sdk-core/test-utils/src/histfetch.rs +1 -1
- data/bridge/sdk-core/test-utils/src/lib.rs +161 -50
- data/bridge/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
- data/bridge/sdk-core/test-utils/src/workflows.rs +29 -0
- data/bridge/sdk-core/tests/fuzzy_workflow.rs +130 -0
- data/bridge/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +125 -51
- data/bridge/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
- data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +10 -5
- data/bridge/sdk-core/tests/integ_tests/metrics_tests.rs +239 -0
- data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +4 -60
- data/bridge/sdk-core/tests/integ_tests/queries_tests.rs +5 -128
- data/bridge/sdk-core/tests/integ_tests/visibility_tests.rs +83 -25
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/activities.rs +93 -69
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +6 -13
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +6 -2
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -10
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +151 -116
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +54 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/patches.rs +7 -28
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +115 -24
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/signals.rs +18 -14
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +6 -20
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -21
- data/bridge/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +6 -4
- data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +27 -18
- data/bridge/sdk-core/tests/main.rs +8 -16
- data/bridge/sdk-core/tests/runner.rs +75 -36
- data/bridge/sdk-core/tests/wf_input_replay.rs +32 -0
- data/bridge/src/connection.rs +117 -82
- data/bridge/src/lib.rs +356 -42
- data/bridge/src/runtime.rs +10 -3
- data/bridge/src/test_server.rs +153 -0
- data/bridge/src/worker.rs +133 -9
- data/lib/gen/temporal/api/batch/v1/message_pb.rb +8 -6
- data/lib/gen/temporal/api/command/v1/message_pb.rb +10 -16
- data/lib/gen/temporal/api/common/v1/message_pb.rb +5 -1
- data/lib/gen/temporal/api/enums/v1/batch_operation_pb.rb +2 -1
- data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +3 -3
- data/lib/gen/temporal/api/enums/v1/common_pb.rb +2 -1
- data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +5 -4
- data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +9 -1
- data/lib/gen/temporal/api/enums/v1/namespace_pb.rb +1 -1
- data/lib/gen/temporal/api/enums/v1/query_pb.rb +1 -1
- data/lib/gen/temporal/api/enums/v1/reset_pb.rb +1 -1
- data/lib/gen/temporal/api/enums/v1/schedule_pb.rb +1 -1
- data/lib/gen/temporal/api/enums/v1/task_queue_pb.rb +1 -1
- data/lib/gen/temporal/api/enums/v1/update_pb.rb +7 -10
- data/lib/gen/temporal/api/enums/v1/workflow_pb.rb +1 -1
- data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +1 -1
- data/lib/gen/temporal/api/failure/v1/message_pb.rb +1 -1
- data/lib/gen/temporal/api/filter/v1/message_pb.rb +1 -1
- data/lib/gen/temporal/api/history/v1/message_pb.rb +34 -25
- data/lib/gen/temporal/api/namespace/v1/message_pb.rb +2 -1
- data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +14 -51
- data/lib/gen/temporal/api/operatorservice/v1/service_pb.rb +1 -1
- data/lib/gen/temporal/api/protocol/v1/message_pb.rb +30 -0
- data/lib/gen/temporal/api/query/v1/message_pb.rb +1 -1
- data/lib/gen/temporal/api/replication/v1/message_pb.rb +1 -1
- data/lib/gen/temporal/api/schedule/v1/message_pb.rb +22 -1
- data/lib/gen/temporal/api/sdk/v1/task_complete_metadata_pb.rb +23 -0
- data/lib/gen/temporal/api/taskqueue/v1/message_pb.rb +2 -2
- data/lib/gen/temporal/api/testservice/v1/request_response_pb.rb +49 -0
- data/lib/gen/temporal/api/testservice/v1/service_pb.rb +21 -0
- data/lib/gen/temporal/api/update/v1/message_pb.rb +49 -3
- data/lib/gen/temporal/api/version/v1/message_pb.rb +1 -1
- data/lib/gen/temporal/api/workflow/v1/message_pb.rb +2 -1
- data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +47 -20
- data/lib/gen/temporal/api/workflowservice/v1/service_pb.rb +1 -1
- data/lib/gen/temporal/sdk/core/activity_result/activity_result_pb.rb +13 -9
- data/lib/gen/temporal/sdk/core/activity_task/activity_task_pb.rb +10 -6
- data/lib/gen/temporal/sdk/core/child_workflow/child_workflow_pb.rb +13 -9
- data/lib/gen/temporal/sdk/core/common/common_pb.rb +7 -3
- data/lib/gen/temporal/sdk/core/core_interface_pb.rb +9 -3
- data/lib/gen/temporal/sdk/core/external_data/external_data_pb.rb +7 -3
- data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +28 -21
- data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +32 -24
- data/lib/gen/temporal/sdk/core/workflow_completion/workflow_completion_pb.rb +12 -5
- data/lib/temporalio/activity/context.rb +102 -0
- data/lib/temporalio/activity/info.rb +67 -0
- data/lib/temporalio/activity.rb +85 -0
- data/lib/temporalio/bridge/connect_options.rb +15 -0
- data/lib/temporalio/bridge/error.rb +8 -0
- data/lib/temporalio/bridge/retry_config.rb +24 -0
- data/lib/temporalio/bridge/tls_options.rb +19 -0
- data/lib/temporalio/bridge.rb +14 -0
- data/lib/{temporal → temporalio}/client/implementation.rb +57 -56
- data/lib/{temporal → temporalio}/client/workflow_handle.rb +35 -35
- data/lib/{temporal → temporalio}/client.rb +19 -32
- data/lib/temporalio/connection/retry_config.rb +44 -0
- data/lib/temporalio/connection/service.rb +20 -0
- data/lib/temporalio/connection/test_service.rb +92 -0
- data/lib/temporalio/connection/tls_options.rb +51 -0
- data/lib/temporalio/connection/workflow_service.rb +731 -0
- data/lib/temporalio/connection.rb +86 -0
- data/lib/{temporal → temporalio}/data_converter.rb +76 -35
- data/lib/{temporal → temporalio}/error/failure.rb +6 -6
- data/lib/{temporal → temporalio}/error/workflow_failure.rb +4 -2
- data/lib/{temporal → temporalio}/errors.rb +19 -1
- data/lib/{temporal → temporalio}/failure_converter/base.rb +5 -5
- data/lib/{temporal → temporalio}/failure_converter/basic.rb +58 -52
- data/lib/temporalio/failure_converter.rb +7 -0
- data/lib/temporalio/interceptor/activity_inbound.rb +22 -0
- data/lib/temporalio/interceptor/activity_outbound.rb +24 -0
- data/lib/{temporal → temporalio}/interceptor/chain.rb +7 -6
- data/lib/{temporal → temporalio}/interceptor/client.rb +27 -2
- data/lib/temporalio/interceptor.rb +22 -0
- data/lib/{temporal → temporalio}/payload_codec/base.rb +5 -5
- data/lib/{temporal → temporalio}/payload_converter/base.rb +3 -3
- data/lib/{temporal → temporalio}/payload_converter/bytes.rb +4 -3
- data/lib/{temporal → temporalio}/payload_converter/composite.rb +7 -5
- data/lib/{temporal → temporalio}/payload_converter/encoding_base.rb +4 -4
- data/lib/{temporal → temporalio}/payload_converter/json.rb +4 -3
- data/lib/{temporal → temporalio}/payload_converter/nil.rb +4 -3
- data/lib/temporalio/payload_converter.rb +14 -0
- data/lib/{temporal → temporalio}/retry_policy.rb +17 -7
- data/lib/{temporal → temporalio}/retry_state.rb +1 -1
- data/lib/temporalio/runtime.rb +25 -0
- data/lib/temporalio/testing/time_skipping_handle.rb +32 -0
- data/lib/temporalio/testing/time_skipping_interceptor.rb +23 -0
- data/lib/temporalio/testing/workflow_environment.rb +112 -0
- data/lib/temporalio/testing.rb +175 -0
- data/lib/{temporal → temporalio}/timeout_type.rb +2 -2
- data/lib/temporalio/version.rb +3 -0
- data/lib/temporalio/worker/activity_runner.rb +114 -0
- data/lib/temporalio/worker/activity_worker.rb +164 -0
- data/lib/temporalio/worker/reactor.rb +46 -0
- data/lib/temporalio/worker/runner.rb +63 -0
- data/lib/temporalio/worker/sync_worker.rb +124 -0
- data/lib/temporalio/worker/thread_pool_executor.rb +51 -0
- data/lib/temporalio/worker.rb +204 -0
- data/lib/temporalio/workflow/async.rb +46 -0
- data/lib/{temporal → temporalio}/workflow/execution_info.rb +4 -4
- data/lib/{temporal → temporalio}/workflow/execution_status.rb +1 -1
- data/lib/temporalio/workflow/future.rb +138 -0
- data/lib/{temporal → temporalio}/workflow/id_reuse_policy.rb +6 -6
- data/lib/temporalio/workflow/info.rb +76 -0
- data/lib/{temporal → temporalio}/workflow/query_reject_condition.rb +5 -5
- data/lib/temporalio.rb +12 -3
- data/temporalio.gemspec +11 -6
- metadata +137 -64
- data/bridge/sdk-core/Cargo.lock +0 -2606
- data/bridge/sdk-core/bridge-ffi/Cargo.toml +0 -24
- data/bridge/sdk-core/bridge-ffi/LICENSE.txt +0 -23
- data/bridge/sdk-core/bridge-ffi/build.rs +0 -25
- data/bridge/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -249
- data/bridge/sdk-core/bridge-ffi/src/lib.rs +0 -825
- data/bridge/sdk-core/bridge-ffi/src/wrappers.rs +0 -211
- data/bridge/sdk-core/core/src/log_export.rs +0 -62
- data/bridge/sdk-core/core/src/worker/workflow/machines/mutable_side_effect_state_machine.rs +0 -127
- data/bridge/sdk-core/core/src/worker/workflow/machines/side_effect_state_machine.rs +0 -71
- data/bridge/sdk-core/protos/api_upstream/temporal/api/cluster/v1/message.proto +0 -83
- data/bridge/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -210
- data/bridge/sdk-core/sdk/src/conversions.rs +0 -8
- data/lib/bridge.so +0 -0
- data/lib/gen/temporal/api/cluster/v1/message_pb.rb +0 -67
- data/lib/gen/temporal/api/enums/v1/cluster_pb.rb +0 -26
- data/lib/gen/temporal/sdk/core/bridge/bridge_pb.rb +0 -222
- data/lib/temporal/bridge.rb +0 -14
- data/lib/temporal/connection.rb +0 -736
- data/lib/temporal/failure_converter.rb +0 -8
- data/lib/temporal/payload_converter.rb +0 -14
- data/lib/temporal/runtime.rb +0 -22
- data/lib/temporal/version.rb +0 -3
- data/lib/temporal.rb +0 -8
|
@@ -23,6 +23,6 @@ async fn main() -> Result<(), anyhow::Error> {
|
|
|
23
23
|
.expect("history field must be populated");
|
|
24
24
|
// Serialize history to file
|
|
25
25
|
let byteified = hist.encode_to_vec();
|
|
26
|
-
tokio::fs::write(format!("{}_history.bin"
|
|
26
|
+
tokio::fs::write(format!("{wf_id}_history.bin"), &byteified).await?;
|
|
27
27
|
Ok(())
|
|
28
28
|
}
|
|
@@ -5,8 +5,14 @@
|
|
|
5
5
|
extern crate tracing;
|
|
6
6
|
|
|
7
7
|
pub mod canned_histories;
|
|
8
|
+
pub mod wf_input_saver;
|
|
9
|
+
pub mod workflows;
|
|
8
10
|
|
|
9
|
-
use crate::
|
|
11
|
+
use crate::{
|
|
12
|
+
stream::{Stream, TryStreamExt},
|
|
13
|
+
wf_input_saver::stream_to_file,
|
|
14
|
+
};
|
|
15
|
+
use base64::{prelude::BASE64_STANDARD, Engine};
|
|
10
16
|
use futures::{future, stream, stream::FuturesUnordered, StreamExt};
|
|
11
17
|
use parking_lot::Mutex;
|
|
12
18
|
use prost::Message;
|
|
@@ -18,14 +24,24 @@ use std::{
|
|
|
18
24
|
use temporal_client::{
|
|
19
25
|
Client, RetryClient, WorkflowClientTrait, WorkflowExecutionInfo, WorkflowOptions,
|
|
20
26
|
};
|
|
21
|
-
use temporal_sdk::{
|
|
27
|
+
use temporal_sdk::{
|
|
28
|
+
interceptors::{FailOnNondeterminismInterceptor, WorkerInterceptor},
|
|
29
|
+
IntoActivityFunc, Worker, WorkflowFunction,
|
|
30
|
+
};
|
|
22
31
|
use temporal_sdk_core::{
|
|
23
32
|
ephemeral_server::{EphemeralExe, EphemeralExeVersion},
|
|
24
|
-
init_replay_worker, init_worker,
|
|
25
|
-
|
|
26
|
-
|
|
33
|
+
init_replay_worker, init_worker,
|
|
34
|
+
replay::HistoryForReplay,
|
|
35
|
+
ClientOptions, ClientOptionsBuilder, CoreRuntime, WorkerConfig, WorkerConfigBuilder,
|
|
36
|
+
};
|
|
37
|
+
use temporal_sdk_core_api::errors::{PollActivityError, PollWfError};
|
|
38
|
+
use temporal_sdk_core_api::{
|
|
39
|
+
telemetry::{
|
|
40
|
+
Logger, MetricsExporter, OtelCollectorOptions, TelemetryOptions, TelemetryOptionsBuilder,
|
|
41
|
+
TraceExportConfig, TraceExporter,
|
|
42
|
+
},
|
|
43
|
+
Worker as CoreWorker,
|
|
27
44
|
};
|
|
28
|
-
use temporal_sdk_core_api::Worker as CoreWorker;
|
|
29
45
|
use temporal_sdk_core_protos::{
|
|
30
46
|
coresdk::{
|
|
31
47
|
workflow_commands::{
|
|
@@ -35,16 +51,17 @@ use temporal_sdk_core_protos::{
|
|
|
35
51
|
workflow_completion::WorkflowActivationCompletion,
|
|
36
52
|
},
|
|
37
53
|
temporal::api::{common::v1::Payload, history::v1::History},
|
|
54
|
+
DEFAULT_ACTIVITY_TYPE,
|
|
38
55
|
};
|
|
39
|
-
use tokio::sync::OnceCell;
|
|
56
|
+
use tokio::sync::{mpsc::unbounded_channel, OnceCell};
|
|
40
57
|
use url::Url;
|
|
41
58
|
|
|
42
59
|
pub const NAMESPACE: &str = "default";
|
|
43
60
|
pub const TEST_Q: &str = "q";
|
|
44
61
|
/// The env var used to specify where the integ tests should point
|
|
45
62
|
pub const INTEG_SERVER_TARGET_ENV_VAR: &str = "TEMPORAL_SERVICE_ADDRESS";
|
|
46
|
-
/// This env var is set (to any value) if
|
|
47
|
-
pub const
|
|
63
|
+
/// This env var is set (to any value) if temporal CLI dev server is in use
|
|
64
|
+
pub const INTEG_TEMPORAL_DEV_SERVER_USED_ENV_VAR: &str = "INTEG_TEMPORAL_DEV_SERVER_ON";
|
|
48
65
|
/// This env var is set (to any value) if the test server is in use
|
|
49
66
|
pub const INTEG_TEST_SERVER_USED_ENV_VAR: &str = "INTEG_TEST_SERVER_ON";
|
|
50
67
|
|
|
@@ -52,6 +69,15 @@ pub const INTEG_TEST_SERVER_USED_ENV_VAR: &str = "INTEG_TEST_SERVER_ON";
|
|
|
52
69
|
const OTEL_URL_ENV_VAR: &str = "TEMPORAL_INTEG_OTEL_URL";
|
|
53
70
|
/// If set, enable direct scraping of prom metrics on the specified port
|
|
54
71
|
const PROM_ENABLE_ENV_VAR: &str = "TEMPORAL_INTEG_PROM_PORT";
|
|
72
|
+
#[macro_export]
|
|
73
|
+
macro_rules! prost_dur {
|
|
74
|
+
($dur_call:ident $args:tt) => {
|
|
75
|
+
std::time::Duration::$dur_call$args
|
|
76
|
+
.try_into()
|
|
77
|
+
.expect("test duration fits")
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
55
81
|
/// Create a worker instance which will use the provided test name to base the task queue and wf id
|
|
56
82
|
/// upon. Returns the instance and the task queue name (which is also the workflow id).
|
|
57
83
|
pub async fn init_core_and_create_wf(test_name: &str) -> CoreWfStarter {
|
|
@@ -61,21 +87,44 @@ pub async fn init_core_and_create_wf(test_name: &str) -> CoreWfStarter {
|
|
|
61
87
|
starter
|
|
62
88
|
}
|
|
63
89
|
|
|
64
|
-
/// Create a worker replay instance preloaded with
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
90
|
+
/// Create a worker replay instance preloaded with provided histories. Returns the worker impl.
|
|
91
|
+
pub fn init_core_replay_preloaded<I>(test_name: &str, histories: I) -> Arc<dyn CoreWorker>
|
|
92
|
+
where
|
|
93
|
+
I: IntoIterator<Item = HistoryForReplay> + 'static,
|
|
94
|
+
<I as IntoIterator>::IntoIter: Send,
|
|
95
|
+
{
|
|
96
|
+
init_core_replay_stream(test_name, stream::iter(histories))
|
|
97
|
+
}
|
|
98
|
+
pub fn init_core_replay_stream<I>(test_name: &str, histories: I) -> Arc<dyn CoreWorker>
|
|
99
|
+
where
|
|
100
|
+
I: Stream<Item = HistoryForReplay> + Send + 'static,
|
|
101
|
+
{
|
|
102
|
+
init_integ_telem();
|
|
71
103
|
let worker_cfg = WorkerConfigBuilder::default()
|
|
72
104
|
.namespace(NAMESPACE)
|
|
73
105
|
.task_queue(test_name)
|
|
74
106
|
.worker_build_id("test_bin_id")
|
|
75
107
|
.build()
|
|
76
108
|
.expect("Configuration options construct properly");
|
|
77
|
-
let worker =
|
|
78
|
-
|
|
109
|
+
let worker =
|
|
110
|
+
init_replay_worker(worker_cfg, histories).expect("Replay worker must init properly");
|
|
111
|
+
Arc::new(worker)
|
|
112
|
+
}
|
|
113
|
+
pub fn replay_sdk_worker<I>(histories: I) -> Worker
|
|
114
|
+
where
|
|
115
|
+
I: IntoIterator<Item = HistoryForReplay> + 'static,
|
|
116
|
+
<I as IntoIterator>::IntoIter: Send,
|
|
117
|
+
{
|
|
118
|
+
replay_sdk_worker_stream(stream::iter(histories))
|
|
119
|
+
}
|
|
120
|
+
pub fn replay_sdk_worker_stream<I>(histories: I) -> Worker
|
|
121
|
+
where
|
|
122
|
+
I: Stream<Item = HistoryForReplay> + Send + 'static,
|
|
123
|
+
{
|
|
124
|
+
let core = init_core_replay_stream("replay_worker_test", histories);
|
|
125
|
+
let mut worker = Worker::new_from_core(core, "replay_q".to_string());
|
|
126
|
+
worker.set_worker_interceptor(Box::new(FailOnNondeterminismInterceptor {}));
|
|
127
|
+
worker
|
|
79
128
|
}
|
|
80
129
|
|
|
81
130
|
/// Load history from a file containing the protobuf serialization of it
|
|
@@ -87,13 +136,24 @@ pub async fn history_from_proto_binary(path_from_root: &str) -> Result<History,
|
|
|
87
136
|
Ok(History::decode(&*bytes)?)
|
|
88
137
|
}
|
|
89
138
|
|
|
139
|
+
static INTEG_TESTS_RT: once_cell::sync::OnceCell<CoreRuntime> = once_cell::sync::OnceCell::new();
|
|
140
|
+
pub fn init_integ_telem() {
|
|
141
|
+
INTEG_TESTS_RT.get_or_init(|| {
|
|
142
|
+
let telemetry_options = get_integ_telem_options();
|
|
143
|
+
let rt =
|
|
144
|
+
CoreRuntime::new_assume_tokio(telemetry_options).expect("Core runtime inits cleanly");
|
|
145
|
+
let _ = tracing::subscriber::set_global_default(rt.trace_subscriber());
|
|
146
|
+
rt
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
90
150
|
/// Implements a builder pattern to help integ tests initialize core and create workflows
|
|
91
151
|
pub struct CoreWfStarter {
|
|
92
152
|
/// Used for both the task queue and workflow id
|
|
93
153
|
task_queue_name: String,
|
|
94
|
-
telemetry_options: TelemetryOptions,
|
|
95
154
|
pub worker_config: WorkerConfig,
|
|
96
|
-
|
|
155
|
+
/// Options to use when starting workflow(s)
|
|
156
|
+
pub workflow_options: WorkflowOptions,
|
|
97
157
|
initted_worker: OnceCell<InitializedWorker>,
|
|
98
158
|
}
|
|
99
159
|
struct InitializedWorker {
|
|
@@ -103,16 +163,12 @@ struct InitializedWorker {
|
|
|
103
163
|
|
|
104
164
|
impl CoreWfStarter {
|
|
105
165
|
pub fn new(test_name: &str) -> Self {
|
|
166
|
+
init_integ_telem();
|
|
106
167
|
let rand_bytes: Vec<u8> = rand::thread_rng().sample_iter(&Standard).take(6).collect();
|
|
107
|
-
let task_q_salt =
|
|
108
|
-
let task_queue = format!("{}_{}"
|
|
109
|
-
Self::new_tq_name(&task_queue)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
pub fn new_tq_name(task_queue: &str) -> Self {
|
|
168
|
+
let task_q_salt = BASE64_STANDARD.encode(rand_bytes);
|
|
169
|
+
let task_queue = format!("{test_name}_{task_q_salt}");
|
|
113
170
|
Self {
|
|
114
171
|
task_queue_name: task_queue.to_owned(),
|
|
115
|
-
telemetry_options: get_integ_telem_options(),
|
|
116
172
|
worker_config: WorkerConfigBuilder::default()
|
|
117
173
|
.namespace(NAMESPACE)
|
|
118
174
|
.task_queue(task_queue)
|
|
@@ -120,8 +176,8 @@ impl CoreWfStarter {
|
|
|
120
176
|
.max_cached_workflows(1000_usize)
|
|
121
177
|
.build()
|
|
122
178
|
.unwrap(),
|
|
123
|
-
wft_timeout: None,
|
|
124
179
|
initted_worker: OnceCell::new(),
|
|
180
|
+
workflow_options: Default::default(),
|
|
125
181
|
}
|
|
126
182
|
}
|
|
127
183
|
|
|
@@ -148,13 +204,27 @@ impl CoreWfStarter {
|
|
|
148
204
|
}
|
|
149
205
|
|
|
150
206
|
/// 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()
|
|
207
|
+
pub async fn start_wf(&mut self) -> String {
|
|
208
|
+
self.start_wf_with_id(self.task_queue_name.clone()).await
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
pub async fn start_with_worker(
|
|
212
|
+
&self,
|
|
213
|
+
wf_name: impl Into<String>,
|
|
214
|
+
worker: &mut TestWorker,
|
|
215
|
+
) -> String {
|
|
216
|
+
worker
|
|
217
|
+
.submit_wf(
|
|
218
|
+
self.task_queue_name.clone(),
|
|
219
|
+
wf_name.into(),
|
|
220
|
+
vec![],
|
|
221
|
+
self.workflow_options.clone(),
|
|
222
|
+
)
|
|
153
223
|
.await
|
|
224
|
+
.unwrap()
|
|
154
225
|
}
|
|
155
226
|
|
|
156
|
-
pub async fn start_wf_with_id(&self, workflow_id: String
|
|
157
|
-
opts.task_timeout = opts.task_timeout.or(self.wft_timeout);
|
|
227
|
+
pub async fn start_wf_with_id(&self, workflow_id: String) -> String {
|
|
158
228
|
self.initted_worker
|
|
159
229
|
.get()
|
|
160
230
|
.expect(
|
|
@@ -168,7 +238,7 @@ impl CoreWfStarter {
|
|
|
168
238
|
workflow_id,
|
|
169
239
|
self.task_queue_name.clone(),
|
|
170
240
|
None,
|
|
171
|
-
|
|
241
|
+
self.workflow_options.clone(),
|
|
172
242
|
)
|
|
173
243
|
.await
|
|
174
244
|
.unwrap()
|
|
@@ -181,19 +251,21 @@ impl CoreWfStarter {
|
|
|
181
251
|
&mut self,
|
|
182
252
|
wf_id: impl Into<String>,
|
|
183
253
|
run_id: impl Into<String>,
|
|
184
|
-
// TODO: Need not be passed in
|
|
185
254
|
worker: &mut Worker,
|
|
186
255
|
) -> Result<(), anyhow::Error> {
|
|
256
|
+
let wf_id = wf_id.into();
|
|
187
257
|
// Fetch history and replay it
|
|
188
258
|
let history = self
|
|
189
259
|
.get_client()
|
|
190
260
|
.await
|
|
191
|
-
.get_workflow_execution_history(wf_id.
|
|
261
|
+
.get_workflow_execution_history(wf_id.clone(), Some(run_id.into()), vec![])
|
|
192
262
|
.await?
|
|
193
263
|
.history
|
|
194
264
|
.expect("history field must be populated");
|
|
195
|
-
let
|
|
265
|
+
let with_id = HistoryForReplay::new(history, wf_id);
|
|
266
|
+
let replay_worker = init_core_replay_preloaded(worker.task_queue(), [with_id]);
|
|
196
267
|
worker.with_new_core_worker(replay_worker);
|
|
268
|
+
worker.set_worker_interceptor(Box::new(FailOnNondeterminismInterceptor {}));
|
|
197
269
|
worker.run().await.unwrap();
|
|
198
270
|
Ok(())
|
|
199
271
|
}
|
|
@@ -231,22 +303,36 @@ impl CoreWfStarter {
|
|
|
231
303
|
self
|
|
232
304
|
}
|
|
233
305
|
|
|
234
|
-
pub fn
|
|
235
|
-
self.
|
|
306
|
+
pub fn no_remote_activities(&mut self) -> &mut Self {
|
|
307
|
+
self.worker_config.no_remote_activities = true;
|
|
308
|
+
self
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
pub fn enable_wf_state_input_recording(&mut self) -> &mut Self {
|
|
312
|
+
let (ser_tx, ser_rx) = unbounded_channel();
|
|
313
|
+
let worker_cfg_clone = self.worker_config.clone();
|
|
314
|
+
tokio::spawn(async move {
|
|
315
|
+
stream_to_file(&worker_cfg_clone, ser_rx).await.unwrap();
|
|
316
|
+
});
|
|
317
|
+
self.worker_config.wf_state_inputs = Some(ser_tx);
|
|
236
318
|
self
|
|
237
319
|
}
|
|
238
320
|
|
|
239
321
|
async fn get_or_init(&mut self) -> &InitializedWorker {
|
|
240
322
|
self.initted_worker
|
|
241
323
|
.get_or_init(|| async {
|
|
242
|
-
telemetry_init(&self.telemetry_options).expect("Telemetry inits cleanly");
|
|
243
324
|
let client = Arc::new(
|
|
244
325
|
get_integ_server_options()
|
|
245
326
|
.connect(self.worker_config.namespace.clone(), None, None)
|
|
246
327
|
.await
|
|
247
328
|
.expect("Must connect"),
|
|
248
329
|
);
|
|
249
|
-
let worker = init_worker(
|
|
330
|
+
let worker = init_worker(
|
|
331
|
+
INTEG_TESTS_RT.get().unwrap(),
|
|
332
|
+
self.worker_config.clone(),
|
|
333
|
+
client.clone(),
|
|
334
|
+
)
|
|
335
|
+
.expect("Worker inits cleanly");
|
|
250
336
|
InitializedWorker {
|
|
251
337
|
worker: Arc::new(worker),
|
|
252
338
|
client,
|
|
@@ -442,7 +528,6 @@ impl WorkerInterceptor for TestWorkerCompletionIceptor {
|
|
|
442
528
|
|
|
443
529
|
/// Returns the client options used to connect to the server used for integration tests.
|
|
444
530
|
pub fn get_integ_server_options() -> ClientOptions {
|
|
445
|
-
telemetry_init(&get_integ_telem_options()).expect("Telemetry inits cleanly");
|
|
446
531
|
let temporal_server_address = match env::var(INTEG_SERVER_TARGET_ENV_VAR) {
|
|
447
532
|
Ok(addr) => addr,
|
|
448
533
|
Err(_) => "http://localhost:7233".to_owned(),
|
|
@@ -459,6 +544,8 @@ pub fn get_integ_server_options() -> ClientOptions {
|
|
|
459
544
|
|
|
460
545
|
pub fn get_integ_telem_options() -> TelemetryOptions {
|
|
461
546
|
let mut ob = TelemetryOptionsBuilder::default();
|
|
547
|
+
let filter_string =
|
|
548
|
+
env::var("RUST_LOG").unwrap_or_else(|_| "temporal_sdk_core=INFO".to_string());
|
|
462
549
|
if let Some(url) = env::var(OTEL_URL_ENV_VAR)
|
|
463
550
|
.ok()
|
|
464
551
|
.map(|x| x.parse::<Url>().unwrap())
|
|
@@ -466,8 +553,12 @@ pub fn get_integ_telem_options() -> TelemetryOptions {
|
|
|
466
553
|
let opts = OtelCollectorOptions {
|
|
467
554
|
url,
|
|
468
555
|
headers: Default::default(),
|
|
556
|
+
metric_periodicity: None,
|
|
469
557
|
};
|
|
470
|
-
ob.tracing(
|
|
558
|
+
ob.tracing(TraceExportConfig {
|
|
559
|
+
filter: filter_string.clone(),
|
|
560
|
+
exporter: TraceExporter::Otel(opts.clone()),
|
|
561
|
+
});
|
|
471
562
|
ob.metrics(MetricsExporter::Otel(opts));
|
|
472
563
|
}
|
|
473
564
|
if let Some(addr) = env::var(PROM_ENABLE_ENV_VAR)
|
|
@@ -476,15 +567,16 @@ pub fn get_integ_telem_options() -> TelemetryOptions {
|
|
|
476
567
|
{
|
|
477
568
|
ob.metrics(MetricsExporter::Prometheus(addr));
|
|
478
569
|
}
|
|
479
|
-
ob.
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
570
|
+
ob.logging(Logger::Console {
|
|
571
|
+
filter: filter_string,
|
|
572
|
+
})
|
|
573
|
+
.build()
|
|
574
|
+
.unwrap()
|
|
483
575
|
}
|
|
484
576
|
|
|
485
577
|
pub fn default_cached_download() -> EphemeralExe {
|
|
486
578
|
EphemeralExe::CachedDownload {
|
|
487
|
-
version: EphemeralExeVersion::
|
|
579
|
+
version: EphemeralExeVersion::SDKDefault {
|
|
488
580
|
sdk_name: "sdk-rust".to_string(),
|
|
489
581
|
sdk_version: "0.1.0".to_string(),
|
|
490
582
|
},
|
|
@@ -503,8 +595,7 @@ pub fn schedule_activity_cmd(
|
|
|
503
595
|
ScheduleActivity {
|
|
504
596
|
seq,
|
|
505
597
|
activity_id: activity_id.to_string(),
|
|
506
|
-
activity_type:
|
|
507
|
-
namespace: NAMESPACE.to_owned(),
|
|
598
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
508
599
|
task_queue: task_q.to_owned(),
|
|
509
600
|
schedule_to_start_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
510
601
|
start_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
@@ -525,7 +616,7 @@ pub fn schedule_local_activity_cmd(
|
|
|
525
616
|
ScheduleLocalActivity {
|
|
526
617
|
seq,
|
|
527
618
|
activity_id: activity_id.to_string(),
|
|
528
|
-
activity_type:
|
|
619
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
|
529
620
|
schedule_to_start_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
530
621
|
start_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
531
622
|
schedule_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
|
|
@@ -596,3 +687,23 @@ where
|
|
|
596
687
|
.unwrap();
|
|
597
688
|
}
|
|
598
689
|
}
|
|
690
|
+
|
|
691
|
+
/// Initiate shutdown, drain the pollers, and wait for shutdown to complete.
|
|
692
|
+
pub async fn drain_pollers_and_shutdown(worker: &Arc<dyn CoreWorker>) {
|
|
693
|
+
worker.initiate_shutdown();
|
|
694
|
+
tokio::join!(
|
|
695
|
+
async {
|
|
696
|
+
assert!(matches!(
|
|
697
|
+
worker.poll_activity_task().await.unwrap_err(),
|
|
698
|
+
PollActivityError::ShutDown
|
|
699
|
+
));
|
|
700
|
+
},
|
|
701
|
+
async {
|
|
702
|
+
assert!(matches!(
|
|
703
|
+
worker.poll_workflow_activation().await.unwrap_err(),
|
|
704
|
+
PollWfError::ShutDown,
|
|
705
|
+
));
|
|
706
|
+
}
|
|
707
|
+
);
|
|
708
|
+
worker.shutdown().await;
|
|
709
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
use anyhow::anyhow;
|
|
2
|
+
use bytes::BytesMut;
|
|
3
|
+
use futures::{stream::BoxStream, SinkExt, StreamExt};
|
|
4
|
+
use prost::bytes::Bytes;
|
|
5
|
+
use std::path::Path;
|
|
6
|
+
use temporal_sdk_core_api::worker::WorkerConfig;
|
|
7
|
+
use tokio::{fs::File, sync::mpsc::UnboundedReceiver};
|
|
8
|
+
use tokio_util::codec::{FramedRead, FramedWrite, LengthDelimitedCodec};
|
|
9
|
+
|
|
10
|
+
pub struct WFStateReplayData {
|
|
11
|
+
pub config: WorkerConfig,
|
|
12
|
+
pub inputs: BoxStream<'static, Result<BytesMut, std::io::Error>>,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
pub async fn stream_to_file(
|
|
16
|
+
config: &WorkerConfig,
|
|
17
|
+
mut rcv: UnboundedReceiver<Vec<u8>>,
|
|
18
|
+
) -> Result<(), anyhow::Error> {
|
|
19
|
+
let file = File::create("wf_inputs").await?;
|
|
20
|
+
let mut transport = FramedWrite::new(file, ldc());
|
|
21
|
+
// First write the worker config, since things like cache size affect how many evictions there
|
|
22
|
+
// will be, etc.
|
|
23
|
+
transport.send(rmp_serde::to_vec(config)?.into()).await?;
|
|
24
|
+
while let Some(v) = rcv.recv().await {
|
|
25
|
+
transport.send(Bytes::from(v)).await?;
|
|
26
|
+
}
|
|
27
|
+
Ok(())
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
pub async fn read_from_file(path: impl AsRef<Path>) -> Result<WFStateReplayData, anyhow::Error> {
|
|
31
|
+
let file = File::open(path).await?;
|
|
32
|
+
let mut framed_read = FramedRead::new(file, ldc());
|
|
33
|
+
// Deserialize the worker config first
|
|
34
|
+
let config = framed_read
|
|
35
|
+
.next()
|
|
36
|
+
.await
|
|
37
|
+
.ok_or_else(|| anyhow!("Replay data file is empty"))??;
|
|
38
|
+
let config = rmp_serde::from_slice(config.as_ref())?;
|
|
39
|
+
|
|
40
|
+
Ok(WFStateReplayData {
|
|
41
|
+
config,
|
|
42
|
+
inputs: framed_read.boxed(),
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
fn ldc() -> LengthDelimitedCodec {
|
|
47
|
+
LengthDelimitedCodec::builder()
|
|
48
|
+
.length_field_type::<u16>()
|
|
49
|
+
.new_codec()
|
|
50
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
use crate::prost_dur;
|
|
2
|
+
use std::time::Duration;
|
|
3
|
+
use temporal_sdk::{ActivityOptions, LocalActivityOptions, WfContext, WorkflowResult};
|
|
4
|
+
use temporal_sdk_core_protos::{coresdk::AsJsonPayloadExt, temporal::api::common::v1::RetryPolicy};
|
|
5
|
+
|
|
6
|
+
pub async fn la_problem_workflow(ctx: WfContext) -> WorkflowResult<()> {
|
|
7
|
+
ctx.local_activity(LocalActivityOptions {
|
|
8
|
+
activity_type: "delay".to_string(),
|
|
9
|
+
input: "hi".as_json_payload().expect("serializes fine"),
|
|
10
|
+
retry_policy: RetryPolicy {
|
|
11
|
+
initial_interval: Some(prost_dur!(from_micros(15))),
|
|
12
|
+
backoff_coefficient: 1_000.,
|
|
13
|
+
maximum_interval: Some(prost_dur!(from_millis(1500))),
|
|
14
|
+
maximum_attempts: 4,
|
|
15
|
+
non_retryable_error_types: vec![],
|
|
16
|
+
},
|
|
17
|
+
timer_backoff_threshold: Some(Duration::from_secs(1)),
|
|
18
|
+
..Default::default()
|
|
19
|
+
})
|
|
20
|
+
.await;
|
|
21
|
+
ctx.activity(ActivityOptions {
|
|
22
|
+
activity_type: "delay".to_string(),
|
|
23
|
+
start_to_close_timeout: Some(Duration::from_secs(20)),
|
|
24
|
+
input: "hi!".as_json_payload().expect("serializes fine"),
|
|
25
|
+
..Default::default()
|
|
26
|
+
})
|
|
27
|
+
.await;
|
|
28
|
+
Ok(().into())
|
|
29
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
use futures_util::{sink, stream::FuturesUnordered, FutureExt, StreamExt};
|
|
2
|
+
use rand::{prelude::Distribution, rngs::SmallRng, Rng, SeedableRng};
|
|
3
|
+
use std::{future, time::Duration};
|
|
4
|
+
use temporal_client::{WfClientExt, WorkflowClientTrait, WorkflowOptions};
|
|
5
|
+
use temporal_sdk::{ActContext, ActivityOptions, LocalActivityOptions, WfContext, WorkflowResult};
|
|
6
|
+
use temporal_sdk_core_protos::coresdk::{AsJsonPayloadExt, FromJsonPayloadExt, IntoPayloadsExt};
|
|
7
|
+
use temporal_sdk_core_test_utils::CoreWfStarter;
|
|
8
|
+
use tokio_util::sync::CancellationToken;
|
|
9
|
+
|
|
10
|
+
const FUZZY_SIG: &str = "fuzzy_sig";
|
|
11
|
+
|
|
12
|
+
#[derive(serde::Serialize, serde::Deserialize, Copy, Clone)]
|
|
13
|
+
enum FuzzyWfAction {
|
|
14
|
+
Shutdown,
|
|
15
|
+
DoAct,
|
|
16
|
+
DoLocalAct,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
struct FuzzyWfActionSampler;
|
|
20
|
+
impl Distribution<FuzzyWfAction> for FuzzyWfActionSampler {
|
|
21
|
+
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> FuzzyWfAction {
|
|
22
|
+
let v: u8 = rng.gen_range(1..=2);
|
|
23
|
+
match v {
|
|
24
|
+
1 => FuzzyWfAction::DoAct,
|
|
25
|
+
2 => FuzzyWfAction::DoLocalAct,
|
|
26
|
+
_ => unreachable!(),
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async fn echo(_ctx: ActContext, echo_me: String) -> Result<String, anyhow::Error> {
|
|
32
|
+
Ok(echo_me)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async fn fuzzy_wf_def(ctx: WfContext) -> WorkflowResult<()> {
|
|
36
|
+
let sigchan = ctx
|
|
37
|
+
.make_signal_channel(FUZZY_SIG)
|
|
38
|
+
.map(|sd| FuzzyWfAction::from_json_payload(&sd.input[0]).expect("Can deserialize signal"));
|
|
39
|
+
let done = CancellationToken::new();
|
|
40
|
+
let done_setter = done.clone();
|
|
41
|
+
|
|
42
|
+
sigchan
|
|
43
|
+
.take_until(done.cancelled())
|
|
44
|
+
.for_each_concurrent(None, |action| {
|
|
45
|
+
let fut = match action {
|
|
46
|
+
FuzzyWfAction::DoAct => ctx
|
|
47
|
+
.activity(ActivityOptions {
|
|
48
|
+
activity_type: "echo_activity".to_string(),
|
|
49
|
+
start_to_close_timeout: Some(Duration::from_secs(5)),
|
|
50
|
+
input: "hi!".as_json_payload().expect("serializes fine"),
|
|
51
|
+
..Default::default()
|
|
52
|
+
})
|
|
53
|
+
.map(|_| ())
|
|
54
|
+
.boxed(),
|
|
55
|
+
FuzzyWfAction::DoLocalAct => ctx
|
|
56
|
+
.local_activity(LocalActivityOptions {
|
|
57
|
+
activity_type: "echo_activity".to_string(),
|
|
58
|
+
start_to_close_timeout: Some(Duration::from_secs(5)),
|
|
59
|
+
input: "hi!".as_json_payload().expect("serializes fine"),
|
|
60
|
+
..Default::default()
|
|
61
|
+
})
|
|
62
|
+
.map(|_| ())
|
|
63
|
+
.boxed(),
|
|
64
|
+
FuzzyWfAction::Shutdown => {
|
|
65
|
+
done_setter.cancel();
|
|
66
|
+
future::ready(()).boxed()
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
fut
|
|
70
|
+
})
|
|
71
|
+
.await;
|
|
72
|
+
|
|
73
|
+
Ok(().into())
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
|
|
77
|
+
async fn fuzzy_workflow() {
|
|
78
|
+
let num_workflows = 200;
|
|
79
|
+
let wf_name = "fuzzy_wf";
|
|
80
|
+
let mut starter = CoreWfStarter::new("fuzzy_workflow");
|
|
81
|
+
starter.max_wft(25).max_cached_workflows(25).max_at(25);
|
|
82
|
+
// .enable_wf_state_input_recording();
|
|
83
|
+
let mut worker = starter.worker().await;
|
|
84
|
+
worker.register_wf(wf_name.to_owned(), fuzzy_wf_def);
|
|
85
|
+
worker.register_activity("echo_activity", echo);
|
|
86
|
+
let client = starter.get_client().await;
|
|
87
|
+
|
|
88
|
+
let mut workflow_handles = vec![];
|
|
89
|
+
for i in 0..num_workflows {
|
|
90
|
+
let wfid = format!("{wf_name}_{i}");
|
|
91
|
+
let rid = worker
|
|
92
|
+
.submit_wf(
|
|
93
|
+
wfid.clone(),
|
|
94
|
+
wf_name.to_owned(),
|
|
95
|
+
vec![],
|
|
96
|
+
WorkflowOptions::default(),
|
|
97
|
+
)
|
|
98
|
+
.await
|
|
99
|
+
.unwrap();
|
|
100
|
+
workflow_handles.push(client.get_untyped_workflow_handle(wfid, rid));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
let rng = SmallRng::seed_from_u64(523189);
|
|
104
|
+
let mut actions: Vec<FuzzyWfAction> = rng.sample_iter(FuzzyWfActionSampler).take(15).collect();
|
|
105
|
+
actions.push(FuzzyWfAction::Shutdown);
|
|
106
|
+
|
|
107
|
+
let sig_sender = async {
|
|
108
|
+
for action in actions {
|
|
109
|
+
let sends: FuturesUnordered<_> = (0..num_workflows)
|
|
110
|
+
.map(|i| {
|
|
111
|
+
client.signal_workflow_execution(
|
|
112
|
+
format!("{wf_name}_{i}"),
|
|
113
|
+
"".to_string(),
|
|
114
|
+
FUZZY_SIG.to_string(),
|
|
115
|
+
[action.as_json_payload().expect("Serializes ok")].into_payloads(),
|
|
116
|
+
None,
|
|
117
|
+
)
|
|
118
|
+
})
|
|
119
|
+
.collect();
|
|
120
|
+
sends
|
|
121
|
+
.map(|_| Ok(()))
|
|
122
|
+
.forward(sink::drain())
|
|
123
|
+
.await
|
|
124
|
+
.expect("Sending signals works");
|
|
125
|
+
tokio::time::sleep(Duration::from_secs(1)).await;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
let (r1, _) = tokio::join!(worker.run_until_done(), sig_sender);
|
|
129
|
+
r1.unwrap();
|
|
130
|
+
}
|