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
|
@@ -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
|
+
}
|