temporalio 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -4,15 +4,17 @@ use crate::{
|
|
4
4
|
build_fake_worker, build_mock_pollers, canned_histories, gen_assert_and_reply,
|
5
5
|
mock_manual_poller, mock_poller, mock_poller_from_resps, mock_worker, poll_and_reply,
|
6
6
|
single_hist_mock_sg, test_worker_cfg, MockPollCfg, MockWorkerInputs, MocksHolder,
|
7
|
-
ResponseType, WorkflowCachingPolicy, TEST_Q,
|
7
|
+
QueueResponse, ResponseType, WorkerExt, WorkflowCachingPolicy, TEST_Q,
|
8
8
|
},
|
9
9
|
worker::client::mocks::{mock_manual_workflow_client, mock_workflow_client},
|
10
10
|
ActivityHeartbeat, Worker, WorkerConfigBuilder,
|
11
11
|
};
|
12
12
|
use futures::FutureExt;
|
13
|
+
use itertools::Itertools;
|
13
14
|
use std::{
|
14
15
|
cell::RefCell,
|
15
16
|
collections::{hash_map::Entry, HashMap, VecDeque},
|
17
|
+
future,
|
16
18
|
rc::Rc,
|
17
19
|
sync::{
|
18
20
|
atomic::{AtomicUsize, Ordering},
|
@@ -22,8 +24,10 @@ use std::{
|
|
22
24
|
};
|
23
25
|
use temporal_client::WorkflowOptions;
|
24
26
|
use temporal_sdk::{ActivityOptions, WfContext};
|
25
|
-
use temporal_sdk_core_api::{
|
26
|
-
|
27
|
+
use temporal_sdk_core_api::{
|
28
|
+
errors::{CompleteActivityError, PollActivityError},
|
29
|
+
Worker as WorkerTrait,
|
30
|
+
};
|
27
31
|
use temporal_sdk_core_protos::{
|
28
32
|
coresdk::{
|
29
33
|
activity_result::{
|
@@ -40,8 +44,11 @@ use temporal_sdk_core_protos::{
|
|
40
44
|
ActivityTaskCompletion,
|
41
45
|
},
|
42
46
|
temporal::api::{
|
43
|
-
command::v1::command::Attributes,
|
47
|
+
command::v1::{command::Attributes, ScheduleActivityTaskCommandAttributes},
|
44
48
|
enums::v1::EventType,
|
49
|
+
history::v1::{
|
50
|
+
history_event::Attributes as EventAttributes, ActivityTaskScheduledEventAttributes,
|
51
|
+
},
|
45
52
|
workflowservice::v1::{
|
46
53
|
PollActivityTaskQueueResponse, RecordActivityTaskHeartbeatResponse,
|
47
54
|
RespondActivityTaskCanceledResponse, RespondActivityTaskCompletedResponse,
|
@@ -52,6 +59,7 @@ use temporal_sdk_core_protos::{
|
|
52
59
|
};
|
53
60
|
use temporal_sdk_core_test_utils::{fanout_tasks, start_timer_cmd, TestWorker};
|
54
61
|
use tokio::{sync::Barrier, time::sleep};
|
62
|
+
use tokio_util::sync::CancellationToken;
|
55
63
|
|
56
64
|
#[tokio::test]
|
57
65
|
async fn max_activities_respected() {
|
@@ -121,7 +129,7 @@ async fn activity_not_found_returns_ok() {
|
|
121
129
|
})
|
122
130
|
.await
|
123
131
|
.unwrap();
|
124
|
-
core.
|
132
|
+
core.drain_activity_poller_and_shutdown().await;
|
125
133
|
}
|
126
134
|
|
127
135
|
#[tokio::test]
|
@@ -217,12 +225,14 @@ async fn heartbeats_report_cancels_only_once() {
|
|
217
225
|
})
|
218
226
|
.await
|
219
227
|
.unwrap();
|
220
|
-
core.
|
228
|
+
core.drain_activity_poller_and_shutdown().await;
|
221
229
|
}
|
222
230
|
|
223
231
|
#[tokio::test]
|
224
232
|
async fn activity_cancel_interrupts_poll() {
|
225
233
|
let mut mock_poller = mock_manual_poller();
|
234
|
+
let shutdown_token = CancellationToken::new();
|
235
|
+
let shutdown_token_clone = shutdown_token.clone();
|
226
236
|
let mut poll_resps = VecDeque::from(vec![
|
227
237
|
async {
|
228
238
|
Some(Ok(PollActivityTaskQueueResponse {
|
@@ -237,10 +247,15 @@ async fn activity_cancel_interrupts_poll() {
|
|
237
247
|
Some(Ok(Default::default()))
|
238
248
|
}
|
239
249
|
.boxed(),
|
250
|
+
async move {
|
251
|
+
shutdown_token.cancelled().await;
|
252
|
+
None
|
253
|
+
}
|
254
|
+
.boxed(),
|
240
255
|
]);
|
241
256
|
mock_poller
|
242
257
|
.expect_poll()
|
243
|
-
.times(
|
258
|
+
.times(3)
|
244
259
|
.returning(move || poll_resps.pop_front().unwrap());
|
245
260
|
|
246
261
|
let mut mock_client = mock_manual_workflow_client();
|
@@ -289,11 +304,12 @@ async fn activity_cancel_interrupts_poll() {
|
|
289
304
|
}
|
290
305
|
).await.unwrap();
|
291
306
|
last_finisher.store(2, Ordering::SeqCst);
|
307
|
+
shutdown_token_clone.cancel();
|
292
308
|
}
|
293
309
|
};
|
294
310
|
// So that we know we blocked
|
295
311
|
assert_eq!(last_finisher.load(Ordering::Acquire), 2);
|
296
|
-
core.
|
312
|
+
core.drain_activity_poller_and_shutdown().await;
|
297
313
|
}
|
298
314
|
|
299
315
|
#[tokio::test]
|
@@ -342,13 +358,10 @@ async fn many_concurrent_heartbeat_cancels() {
|
|
342
358
|
})
|
343
359
|
.collect::<Vec<_>>(),
|
344
360
|
);
|
345
|
-
// Because the mock is so fast, it's possible it can return before the cancel channel in
|
346
|
-
// the activity task poll selector. So, the final poll when there are no more tasks must
|
347
|
-
// take a while.
|
348
361
|
poll_resps.push_back(
|
349
362
|
async {
|
350
|
-
|
351
|
-
unreachable!(
|
363
|
+
future::pending::<()>().await;
|
364
|
+
unreachable!()
|
352
365
|
}
|
353
366
|
.boxed(),
|
354
367
|
);
|
@@ -431,13 +444,13 @@ async fn many_concurrent_heartbeat_cancels() {
|
|
431
444
|
})
|
432
445
|
.await;
|
433
446
|
|
434
|
-
worker.
|
447
|
+
worker.drain_activity_poller_and_shutdown().await;
|
435
448
|
}
|
436
449
|
|
437
450
|
#[tokio::test]
|
438
451
|
async fn activity_timeout_no_double_resolve() {
|
439
452
|
let t = canned_histories::activity_double_resolve_repro();
|
440
|
-
let core = build_fake_worker("fake_wf_id", t,
|
453
|
+
let core = build_fake_worker("fake_wf_id", t, [3]);
|
441
454
|
let activity_id = 1;
|
442
455
|
|
443
456
|
poll_and_reply(
|
@@ -483,7 +496,7 @@ async fn activity_timeout_no_double_resolve() {
|
|
483
496
|
)
|
484
497
|
.await;
|
485
498
|
|
486
|
-
core.
|
499
|
+
core.drain_pollers_and_shutdown().await;
|
487
500
|
}
|
488
501
|
|
489
502
|
#[tokio::test]
|
@@ -529,7 +542,7 @@ async fn can_heartbeat_acts_during_shutdown() {
|
|
529
542
|
})
|
530
543
|
.await
|
531
544
|
.unwrap();
|
532
|
-
|
545
|
+
core.drain_activity_poller_and_shutdown().await;
|
533
546
|
}
|
534
547
|
|
535
548
|
/// Verifies that if a user has tried to record a heartbeat and then immediately after failed the
|
@@ -580,7 +593,7 @@ async fn complete_act_with_fail_flushes_heartbeat() {
|
|
580
593
|
})
|
581
594
|
.await
|
582
595
|
.unwrap();
|
583
|
-
core.
|
596
|
+
core.drain_activity_poller_and_shutdown().await;
|
584
597
|
|
585
598
|
// Verify the last seen call to record a heartbeat had the last detail payload
|
586
599
|
let last_seen_payload = &last_seen_payload.take().unwrap().payloads[0];
|
@@ -613,26 +626,20 @@ async fn max_tq_acts_set_passed_to_poll_properly() {
|
|
613
626
|
worker.poll_activity_task().await.unwrap();
|
614
627
|
}
|
615
628
|
|
616
|
-
/// This test
|
617
|
-
///
|
629
|
+
/// This test doesn't test the real worker config since [mock_worker] bypasses the worker
|
630
|
+
/// constructor, [mock_worker] will not pass an activity poller to the worker when
|
631
|
+
/// `no_remote_activities` is set to `true`.
|
618
632
|
#[tokio::test]
|
619
|
-
async fn
|
633
|
+
async fn no_eager_activities_requested_when_worker_options_disable_remote_activities() {
|
620
634
|
let wfid = "fake_wf_id";
|
621
635
|
let mut t = TestHistoryBuilder::default();
|
622
636
|
t.add_by_type(EventType::WorkflowExecutionStarted);
|
623
637
|
t.add_full_wf_task();
|
624
|
-
let
|
625
|
-
let
|
626
|
-
|
627
|
-
t.add_activity_task_completed(
|
628
|
-
act_same_queue_sched_id,
|
629
|
-
act_same_queue_start_id,
|
630
|
-
b"hi".into(),
|
631
|
-
);
|
638
|
+
let scheduled_event_id = t.add_activity_task_scheduled("act_id");
|
639
|
+
let started_event_id = t.add_activity_task_started(scheduled_event_id);
|
640
|
+
t.add_activity_task_completed(scheduled_event_id, started_event_id, b"hi".into());
|
632
641
|
t.add_full_wf_task();
|
633
|
-
t.add_activity_task_cancel_requested(act_different_queue_sched_id);
|
634
642
|
t.add_workflow_execution_completed();
|
635
|
-
|
636
643
|
let num_eager_requested = Arc::new(AtomicUsize::new(0));
|
637
644
|
// Clone it to move into the callback below
|
638
645
|
let num_eager_requested_clone = num_eager_requested.clone();
|
@@ -658,65 +665,171 @@ async fn activity_tasks_from_completion_are_delivered() {
|
|
658
665
|
num_eager_requested_clone.store(count, Ordering::Relaxed);
|
659
666
|
Ok(RespondWorkflowTaskCompletedResponse {
|
660
667
|
workflow_task: None,
|
661
|
-
activity_tasks: vec![
|
662
|
-
|
663
|
-
activity_id: "act_id_same_queue".to_string(),
|
664
|
-
..Default::default()
|
665
|
-
}],
|
668
|
+
activity_tasks: vec![],
|
669
|
+
reset_history_event_id: 0,
|
666
670
|
})
|
667
671
|
});
|
668
|
-
mock.expect_complete_activity_task()
|
669
|
-
.times(1)
|
670
|
-
.returning(|_, _| Ok(RespondActivityTaskCompletedResponse::default()));
|
671
672
|
let mut mock = single_hist_mock_sg(wfid, t, [1], mock, true);
|
672
673
|
let mut mock_poller = mock_manual_poller();
|
673
674
|
mock_poller
|
674
675
|
.expect_poll()
|
675
676
|
.returning(|| futures::future::pending().boxed());
|
676
677
|
mock.set_act_poller(Box::new(mock_poller));
|
677
|
-
mock.worker_cfg(|wc|
|
678
|
+
mock.worker_cfg(|wc| {
|
679
|
+
wc.max_cached_workflows = 2;
|
680
|
+
wc.no_remote_activities = true;
|
681
|
+
});
|
678
682
|
let core = mock_worker(mock);
|
679
683
|
|
684
|
+
// Test start
|
680
685
|
let wf_task = core.poll_workflow_activation().await.unwrap();
|
686
|
+
let cmds = vec![ScheduleActivity {
|
687
|
+
seq: 1,
|
688
|
+
activity_id: "act_id".to_string(),
|
689
|
+
task_queue: TEST_Q.to_string(),
|
690
|
+
cancellation_type: ActivityCancellationType::TryCancel as i32,
|
691
|
+
..Default::default()
|
692
|
+
}
|
693
|
+
.into()];
|
694
|
+
|
681
695
|
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
682
696
|
wf_task.run_id,
|
683
|
-
|
697
|
+
cmds,
|
698
|
+
))
|
699
|
+
.await
|
700
|
+
.unwrap();
|
701
|
+
|
702
|
+
core.drain_pollers_and_shutdown().await;
|
703
|
+
|
704
|
+
assert_eq!(num_eager_requested.load(Ordering::Relaxed), 0);
|
705
|
+
}
|
706
|
+
|
707
|
+
/// This test verifies that activity tasks which come as replies to completing a WFT are properly
|
708
|
+
/// delivered via polling.
|
709
|
+
#[tokio::test]
|
710
|
+
async fn activity_tasks_from_completion_are_delivered() {
|
711
|
+
// Construct the history - one task with 5 activities, 4 on the same task queue, and 1 on a
|
712
|
+
// different queue, 3 activities will be executed eagerly as specified by the
|
713
|
+
// MAX_EAGER_ACTIVITY_RESERVATIONS_PER_WORKFLOW_TASK constant.
|
714
|
+
let wfid = "fake_wf_id";
|
715
|
+
let mut t = TestHistoryBuilder::default();
|
716
|
+
t.add_by_type(EventType::WorkflowExecutionStarted);
|
717
|
+
t.add_full_wf_task();
|
718
|
+
let act_same_queue_scheduled_ids = (1..4)
|
719
|
+
.map(|i| t.add_activity_task_scheduled(format!("act_id_{i}_same_queue")))
|
720
|
+
.collect_vec();
|
721
|
+
t.add_activity_task_scheduled("act_id_same_queue_not_eager");
|
722
|
+
t.add_activity_task_scheduled("act_id_different_queue");
|
723
|
+
for scheduled_event_id in act_same_queue_scheduled_ids {
|
724
|
+
let started_event_id = t.add_activity_task_started(scheduled_event_id);
|
725
|
+
t.add_activity_task_completed(scheduled_event_id, started_event_id, b"hi".into());
|
726
|
+
}
|
727
|
+
t.add_full_wf_task();
|
728
|
+
t.add_workflow_execution_completed();
|
729
|
+
|
730
|
+
let num_eager_requested = Arc::new(AtomicUsize::new(0));
|
731
|
+
// Clone it to move into the callback below
|
732
|
+
let num_eager_requested_clone = num_eager_requested.clone();
|
733
|
+
|
734
|
+
let mut mock = mock_workflow_client();
|
735
|
+
mock.expect_complete_workflow_task()
|
736
|
+
.times(1)
|
737
|
+
.returning(move |req| {
|
738
|
+
// Store the number of eager activities requested to be checked below
|
739
|
+
let count = req
|
740
|
+
.commands
|
741
|
+
.into_iter()
|
742
|
+
.filter(|c| match c.attributes {
|
743
|
+
Some(Attributes::ScheduleActivityTaskCommandAttributes(
|
744
|
+
ScheduleActivityTaskCommandAttributes {
|
745
|
+
request_eager_execution,
|
746
|
+
..
|
747
|
+
},
|
748
|
+
)) => request_eager_execution,
|
749
|
+
_ => false,
|
750
|
+
})
|
751
|
+
.count();
|
752
|
+
num_eager_requested_clone.store(count, Ordering::Relaxed);
|
753
|
+
Ok(RespondWorkflowTaskCompletedResponse {
|
754
|
+
workflow_task: None,
|
755
|
+
activity_tasks: (1..4)
|
756
|
+
.map(|i| PollActivityTaskQueueResponse {
|
757
|
+
task_token: vec![i],
|
758
|
+
activity_id: format!("act_id_{i}_same_queue"),
|
759
|
+
..Default::default()
|
760
|
+
})
|
761
|
+
.collect_vec(),
|
762
|
+
reset_history_event_id: 0,
|
763
|
+
})
|
764
|
+
});
|
765
|
+
mock.expect_complete_activity_task()
|
766
|
+
.times(3)
|
767
|
+
.returning(|_, _| Ok(RespondActivityTaskCompletedResponse::default()));
|
768
|
+
let mut mock = single_hist_mock_sg(wfid, t, [1], mock, true);
|
769
|
+
let act_tasks: Vec<QueueResponse<PollActivityTaskQueueResponse>> = vec![];
|
770
|
+
mock.set_act_poller(mock_poller_from_resps(act_tasks));
|
771
|
+
mock.worker_cfg(|wc| wc.max_cached_workflows = 2);
|
772
|
+
let core = mock_worker(mock);
|
773
|
+
|
774
|
+
// Test start
|
775
|
+
let wf_task = core.poll_workflow_activation().await.unwrap();
|
776
|
+
let mut cmds = (1..4)
|
777
|
+
.map(|seq| {
|
684
778
|
ScheduleActivity {
|
685
|
-
seq
|
686
|
-
activity_id: "
|
779
|
+
seq,
|
780
|
+
activity_id: format!("act_id_{seq}_same_queue"),
|
687
781
|
task_queue: TEST_Q.to_string(),
|
688
782
|
cancellation_type: ActivityCancellationType::TryCancel as i32,
|
689
783
|
..Default::default()
|
690
784
|
}
|
691
|
-
.into()
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
785
|
+
.into()
|
786
|
+
})
|
787
|
+
.collect_vec();
|
788
|
+
cmds.push(
|
789
|
+
ScheduleActivity {
|
790
|
+
seq: 4,
|
791
|
+
activity_id: "act_id_same_queue_not_eager".to_string(),
|
792
|
+
task_queue: TEST_Q.to_string(),
|
793
|
+
cancellation_type: ActivityCancellationType::TryCancel as i32,
|
794
|
+
..Default::default()
|
795
|
+
}
|
796
|
+
.into(),
|
797
|
+
);
|
798
|
+
cmds.push(
|
799
|
+
ScheduleActivity {
|
800
|
+
seq: 5,
|
801
|
+
activity_id: "act_id_different_queue".to_string(),
|
802
|
+
task_queue: "different_queue".to_string(),
|
803
|
+
cancellation_type: ActivityCancellationType::Abandon as i32,
|
804
|
+
..Default::default()
|
805
|
+
}
|
806
|
+
.into(),
|
807
|
+
);
|
808
|
+
|
809
|
+
core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
|
810
|
+
wf_task.run_id,
|
811
|
+
cmds,
|
701
812
|
))
|
702
813
|
.await
|
703
814
|
.unwrap();
|
704
815
|
|
705
|
-
// We should see the
|
706
|
-
|
707
|
-
|
816
|
+
// We should see the 3 eager activities when we poll now
|
817
|
+
for i in 1..4 {
|
818
|
+
let act_task = core.poll_activity_task().await.unwrap();
|
819
|
+
assert_eq!(act_task.task_token, vec![i]);
|
708
820
|
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
821
|
+
core.complete_activity_task(ActivityTaskCompletion {
|
822
|
+
task_token: act_task.task_token.clone(),
|
823
|
+
result: Some(ActivityExecutionResult::ok("hi".into())),
|
824
|
+
})
|
825
|
+
.await
|
826
|
+
.unwrap();
|
827
|
+
}
|
715
828
|
|
716
|
-
core.
|
829
|
+
core.drain_activity_poller_and_shutdown().await;
|
717
830
|
|
718
831
|
// Verify only a single eager activity was scheduled (the one on our worker's task queue)
|
719
|
-
assert_eq!(num_eager_requested.load(Ordering::Relaxed),
|
832
|
+
assert_eq!(num_eager_requested.load(Ordering::Relaxed), 3);
|
720
833
|
}
|
721
834
|
|
722
835
|
#[tokio::test]
|
@@ -725,11 +838,23 @@ async fn activity_tasks_from_completion_reserve_slots() {
|
|
725
838
|
let mut t = TestHistoryBuilder::default();
|
726
839
|
t.add_by_type(EventType::WorkflowExecutionStarted);
|
727
840
|
t.add_full_wf_task();
|
728
|
-
let schedid = t.
|
841
|
+
let schedid = t.add(EventAttributes::ActivityTaskScheduledEventAttributes(
|
842
|
+
ActivityTaskScheduledEventAttributes {
|
843
|
+
activity_id: "1".to_string(),
|
844
|
+
activity_type: Some("act1".into()),
|
845
|
+
..Default::default()
|
846
|
+
},
|
847
|
+
));
|
729
848
|
let startid = t.add_activity_task_started(schedid);
|
730
849
|
t.add_activity_task_completed(schedid, startid, b"hi".into());
|
731
850
|
t.add_full_wf_task();
|
732
|
-
let schedid = t.
|
851
|
+
let schedid = t.add(EventAttributes::ActivityTaskScheduledEventAttributes(
|
852
|
+
ActivityTaskScheduledEventAttributes {
|
853
|
+
activity_id: "2".to_string(),
|
854
|
+
activity_type: Some("act2".into()),
|
855
|
+
..Default::default()
|
856
|
+
},
|
857
|
+
));
|
733
858
|
let startid = t.add_activity_task_started(schedid);
|
734
859
|
t.add_activity_task_completed(schedid, startid, b"hi".into());
|
735
860
|
t.add_full_wf_task();
|
@@ -799,19 +924,25 @@ async fn activity_tasks_from_completion_reserve_slots() {
|
|
799
924
|
// First poll for activities twice, occupying both slots
|
800
925
|
let at1 = core.poll_activity_task().await.unwrap();
|
801
926
|
let at2 = core.poll_activity_task().await.unwrap();
|
927
|
+
let workflow_complete_token = CancellationToken::new();
|
928
|
+
let workflow_complete_token_clone = workflow_complete_token.clone();
|
802
929
|
|
803
|
-
worker.register_wf(DEFAULT_WORKFLOW_TYPE, move |ctx: WfContext|
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
930
|
+
worker.register_wf(DEFAULT_WORKFLOW_TYPE, move |ctx: WfContext| {
|
931
|
+
let complete_token = workflow_complete_token.clone();
|
932
|
+
async move {
|
933
|
+
ctx.activity(ActivityOptions {
|
934
|
+
activity_type: "act1".to_string(),
|
935
|
+
..Default::default()
|
936
|
+
})
|
937
|
+
.await;
|
938
|
+
ctx.activity(ActivityOptions {
|
939
|
+
activity_type: "act2".to_string(),
|
940
|
+
..Default::default()
|
941
|
+
})
|
942
|
+
.await;
|
943
|
+
complete_token.cancel();
|
944
|
+
Ok(().into())
|
945
|
+
}
|
815
946
|
});
|
816
947
|
|
817
948
|
worker
|
@@ -838,6 +969,13 @@ async fn activity_tasks_from_completion_reserve_slots() {
|
|
838
969
|
.await
|
839
970
|
.unwrap();
|
840
971
|
barr.wait().await;
|
972
|
+
// Wait for workflow to complete in order for all eager activities to be requested before shutting down.
|
973
|
+
// After shutdown, no eager activities slots can be allocated.
|
974
|
+
workflow_complete_token_clone.cancelled().await;
|
975
|
+
core.initiate_shutdown();
|
976
|
+
// Even though this test requests eager activity tasks, none are returned in poll responses.
|
977
|
+
let err = core.poll_activity_task().await.unwrap_err();
|
978
|
+
assert_matches!(err, PollActivityError::ShutDown);
|
841
979
|
};
|
842
980
|
// This wf poll should *not* set the flag that it wants tasks back since both slots are
|
843
981
|
// occupied
|
@@ -871,7 +1009,7 @@ async fn retryable_net_error_exhaustion_is_nonfatal() {
|
|
871
1009
|
})
|
872
1010
|
.await
|
873
1011
|
.unwrap();
|
874
|
-
core.
|
1012
|
+
core.drain_activity_poller_and_shutdown().await;
|
875
1013
|
}
|
876
1014
|
|
877
1015
|
#[tokio::test]
|
@@ -1,4 +1,5 @@
|
|
1
1
|
use crate::{
|
2
|
+
internal_flags::CoreInternalFlags,
|
2
3
|
replay::DEFAULT_WORKFLOW_TYPE,
|
3
4
|
test_help::{canned_histories, mock_sdk, mock_sdk_cfg, MockPollCfg, ResponseType},
|
4
5
|
worker::client::mocks::mock_workflow_client,
|
@@ -8,8 +9,13 @@ use std::{
|
|
8
9
|
time::Duration,
|
9
10
|
};
|
10
11
|
use temporal_client::WorkflowOptions;
|
11
|
-
use temporal_sdk::{
|
12
|
-
|
12
|
+
use temporal_sdk::{
|
13
|
+
ActivityOptions, ChildWorkflowOptions, LocalActivityOptions, WfContext, WorkflowResult,
|
14
|
+
};
|
15
|
+
use temporal_sdk_core_protos::{
|
16
|
+
temporal::api::{enums::v1::WorkflowTaskFailedCause, failure::v1::Failure},
|
17
|
+
DEFAULT_ACTIVITY_TYPE,
|
18
|
+
};
|
13
19
|
|
14
20
|
static DID_FAIL: AtomicBool = AtomicBool::new(false);
|
15
21
|
pub async fn timer_wf_fails_once(ctx: WfContext) -> WorkflowResult<()> {
|
@@ -105,3 +111,160 @@ async fn test_wf_task_rejected_properly_due_to_nondeterminism(#[case] use_cache:
|
|
105
111
|
// timer and proceed without restarting
|
106
112
|
assert_eq!(2, started_count.load(Ordering::Relaxed));
|
107
113
|
}
|
114
|
+
|
115
|
+
#[rstest::rstest]
|
116
|
+
#[tokio::test]
|
117
|
+
async fn activity_id_or_type_change_is_nondeterministic(
|
118
|
+
#[values(true, false)] use_cache: bool,
|
119
|
+
#[values(true, false)] id_change: bool,
|
120
|
+
#[values(true, false)] local_act: bool,
|
121
|
+
) {
|
122
|
+
let wf_id = "fakeid";
|
123
|
+
let wf_type = DEFAULT_WORKFLOW_TYPE;
|
124
|
+
let mut t = if local_act {
|
125
|
+
canned_histories::single_local_activity("1")
|
126
|
+
} else {
|
127
|
+
canned_histories::single_activity("1")
|
128
|
+
};
|
129
|
+
t.set_flags_first_wft(&[CoreInternalFlags::IdAndTypeDeterminismChecks as u32], &[]);
|
130
|
+
let mock = mock_workflow_client();
|
131
|
+
let mut mh = MockPollCfg::from_resp_batches(
|
132
|
+
wf_id,
|
133
|
+
t,
|
134
|
+
// Two polls are needed, since the first will fail
|
135
|
+
[ResponseType::AllHistory, ResponseType::AllHistory],
|
136
|
+
mock,
|
137
|
+
);
|
138
|
+
// We should see one wft failure which has nondeterminism cause
|
139
|
+
mh.num_expected_fails = 1;
|
140
|
+
mh.expect_fail_wft_matcher = Box::new(move |_, cause, f| {
|
141
|
+
let should_contain = if id_change {
|
142
|
+
"does not match activity id"
|
143
|
+
} else {
|
144
|
+
"does not match activity type"
|
145
|
+
};
|
146
|
+
matches!(cause, WorkflowTaskFailedCause::NonDeterministicError)
|
147
|
+
&& matches!(f, Some(Failure {
|
148
|
+
message,
|
149
|
+
..
|
150
|
+
}) if message.contains(should_contain))
|
151
|
+
});
|
152
|
+
let mut worker = mock_sdk_cfg(mh, |cfg| {
|
153
|
+
if use_cache {
|
154
|
+
cfg.max_cached_workflows = 2;
|
155
|
+
}
|
156
|
+
});
|
157
|
+
|
158
|
+
worker.register_wf(wf_type.to_owned(), move |ctx: WfContext| async move {
|
159
|
+
if local_act {
|
160
|
+
ctx.local_activity(if id_change {
|
161
|
+
LocalActivityOptions {
|
162
|
+
activity_id: Some("I'm bad and wrong!".to_string()),
|
163
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
164
|
+
..Default::default()
|
165
|
+
}
|
166
|
+
} else {
|
167
|
+
LocalActivityOptions {
|
168
|
+
activity_type: "not the default act type".to_string(),
|
169
|
+
..Default::default()
|
170
|
+
}
|
171
|
+
})
|
172
|
+
.await;
|
173
|
+
} else {
|
174
|
+
ctx.activity(if id_change {
|
175
|
+
ActivityOptions {
|
176
|
+
activity_id: Some("I'm bad and wrong!".to_string()),
|
177
|
+
activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
178
|
+
..Default::default()
|
179
|
+
}
|
180
|
+
} else {
|
181
|
+
ActivityOptions {
|
182
|
+
activity_type: "not the default act type".to_string(),
|
183
|
+
..Default::default()
|
184
|
+
}
|
185
|
+
})
|
186
|
+
.await;
|
187
|
+
}
|
188
|
+
Ok(().into())
|
189
|
+
});
|
190
|
+
|
191
|
+
worker
|
192
|
+
.submit_wf(
|
193
|
+
wf_id.to_owned(),
|
194
|
+
wf_type.to_owned(),
|
195
|
+
vec![],
|
196
|
+
WorkflowOptions::default(),
|
197
|
+
)
|
198
|
+
.await
|
199
|
+
.unwrap();
|
200
|
+
worker.run_until_done().await.unwrap();
|
201
|
+
}
|
202
|
+
|
203
|
+
#[rstest::rstest]
|
204
|
+
#[tokio::test]
|
205
|
+
async fn child_wf_id_or_type_change_is_nondeterministic(
|
206
|
+
#[values(true, false)] use_cache: bool,
|
207
|
+
#[values(true, false)] id_change: bool,
|
208
|
+
) {
|
209
|
+
let wf_id = "fakeid";
|
210
|
+
let wf_type = DEFAULT_WORKFLOW_TYPE;
|
211
|
+
let mut t = canned_histories::single_child_workflow("1");
|
212
|
+
t.set_flags_first_wft(&[CoreInternalFlags::IdAndTypeDeterminismChecks as u32], &[]);
|
213
|
+
let mock = mock_workflow_client();
|
214
|
+
let mut mh = MockPollCfg::from_resp_batches(
|
215
|
+
wf_id,
|
216
|
+
t,
|
217
|
+
// Two polls are needed, since the first will fail
|
218
|
+
[ResponseType::AllHistory, ResponseType::AllHistory],
|
219
|
+
mock,
|
220
|
+
);
|
221
|
+
// We should see one wft failure which has nondeterminism cause
|
222
|
+
mh.num_expected_fails = 1;
|
223
|
+
mh.expect_fail_wft_matcher = Box::new(move |_, cause, f| {
|
224
|
+
let should_contain = if id_change {
|
225
|
+
"does not match child workflow id"
|
226
|
+
} else {
|
227
|
+
"does not match child workflow type"
|
228
|
+
};
|
229
|
+
matches!(cause, WorkflowTaskFailedCause::NonDeterministicError)
|
230
|
+
&& matches!(f, Some(Failure {
|
231
|
+
message,
|
232
|
+
..
|
233
|
+
}) if message.contains(should_contain))
|
234
|
+
});
|
235
|
+
let mut worker = mock_sdk_cfg(mh, |cfg| {
|
236
|
+
if use_cache {
|
237
|
+
cfg.max_cached_workflows = 2;
|
238
|
+
}
|
239
|
+
});
|
240
|
+
|
241
|
+
worker.register_wf(wf_type.to_owned(), move |ctx: WfContext| async move {
|
242
|
+
ctx.child_workflow(if id_change {
|
243
|
+
ChildWorkflowOptions {
|
244
|
+
workflow_id: "I'm bad and wrong!".to_string(),
|
245
|
+
workflow_type: DEFAULT_ACTIVITY_TYPE.to_string(),
|
246
|
+
..Default::default()
|
247
|
+
}
|
248
|
+
} else {
|
249
|
+
ChildWorkflowOptions {
|
250
|
+
workflow_id: "1".to_string(),
|
251
|
+
workflow_type: "not the child wf type".to_string(),
|
252
|
+
..Default::default()
|
253
|
+
}
|
254
|
+
})
|
255
|
+
.start(&ctx)
|
256
|
+
.await;
|
257
|
+
Ok(().into())
|
258
|
+
});
|
259
|
+
|
260
|
+
worker
|
261
|
+
.submit_wf(
|
262
|
+
wf_id.to_owned(),
|
263
|
+
wf_type.to_owned(),
|
264
|
+
vec![],
|
265
|
+
WorkflowOptions::default(),
|
266
|
+
)
|
267
|
+
.await
|
268
|
+
.unwrap();
|
269
|
+
worker.run_until_done().await.unwrap();
|
270
|
+
}
|