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.
Files changed (310) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +180 -7
  3. data/bridge/Cargo.lock +208 -76
  4. data/bridge/Cargo.toml +5 -2
  5. data/bridge/sdk-core/Cargo.toml +1 -1
  6. data/bridge/sdk-core/README.md +20 -10
  7. data/bridge/sdk-core/client/Cargo.toml +1 -1
  8. data/bridge/sdk-core/client/src/lib.rs +227 -59
  9. data/bridge/sdk-core/client/src/metrics.rs +17 -8
  10. data/bridge/sdk-core/client/src/raw.rs +13 -12
  11. data/bridge/sdk-core/client/src/retry.rs +132 -43
  12. data/bridge/sdk-core/core/Cargo.toml +28 -15
  13. data/bridge/sdk-core/core/benches/workflow_replay.rs +13 -10
  14. data/bridge/sdk-core/core/src/abstractions.rs +225 -36
  15. data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +217 -79
  16. data/bridge/sdk-core/core/src/core_tests/determinism.rs +165 -2
  17. data/bridge/sdk-core/core/src/core_tests/local_activities.rs +565 -34
  18. data/bridge/sdk-core/core/src/core_tests/queries.rs +247 -90
  19. data/bridge/sdk-core/core/src/core_tests/workers.rs +3 -5
  20. data/bridge/sdk-core/core/src/core_tests/workflow_cancels.rs +1 -1
  21. data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +430 -67
  22. data/bridge/sdk-core/core/src/ephemeral_server/mod.rs +106 -12
  23. data/bridge/sdk-core/core/src/internal_flags.rs +136 -0
  24. data/bridge/sdk-core/core/src/lib.rs +148 -34
  25. data/bridge/sdk-core/core/src/protosext/mod.rs +1 -1
  26. data/bridge/sdk-core/core/src/replay/mod.rs +185 -41
  27. data/bridge/sdk-core/core/src/telemetry/log_export.rs +190 -0
  28. data/bridge/sdk-core/core/src/telemetry/metrics.rs +219 -140
  29. data/bridge/sdk-core/core/src/telemetry/mod.rs +326 -315
  30. data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +20 -14
  31. data/bridge/sdk-core/core/src/test_help/mod.rs +85 -21
  32. data/bridge/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +112 -156
  33. data/bridge/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
  34. data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +364 -128
  35. data/bridge/sdk-core/core/src/worker/activities.rs +263 -170
  36. data/bridge/sdk-core/core/src/worker/client/mocks.rs +23 -3
  37. data/bridge/sdk-core/core/src/worker/client.rs +48 -6
  38. data/bridge/sdk-core/core/src/worker/mod.rs +186 -75
  39. data/bridge/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
  40. data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +13 -24
  41. data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +879 -226
  42. data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +101 -48
  43. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +8 -12
  44. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +6 -9
  45. data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +90 -32
  46. data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +6 -9
  47. data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +7 -10
  48. data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +6 -9
  49. data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +160 -83
  50. data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +36 -54
  51. data/bridge/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +179 -0
  52. data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +104 -157
  53. data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +8 -12
  54. data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +9 -13
  55. data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +10 -4
  56. data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +14 -11
  57. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +6 -17
  58. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +395 -299
  59. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +12 -20
  60. data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +33 -18
  61. data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +1032 -374
  62. data/bridge/sdk-core/core/src/worker/workflow/mod.rs +525 -392
  63. data/bridge/sdk-core/core/src/worker/workflow/run_cache.rs +40 -57
  64. data/bridge/sdk-core/core/src/worker/workflow/wft_extraction.rs +125 -0
  65. data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +3 -6
  66. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +117 -0
  67. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
  68. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +456 -681
  69. data/bridge/sdk-core/core-api/Cargo.toml +6 -4
  70. data/bridge/sdk-core/core-api/src/errors.rs +1 -34
  71. data/bridge/sdk-core/core-api/src/lib.rs +7 -45
  72. data/bridge/sdk-core/core-api/src/telemetry.rs +141 -0
  73. data/bridge/sdk-core/core-api/src/worker.rs +27 -1
  74. data/bridge/sdk-core/etc/deps.svg +115 -140
  75. data/bridge/sdk-core/etc/regen-depgraph.sh +5 -0
  76. data/bridge/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +18 -15
  77. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +1 -1
  78. data/bridge/sdk-core/fsm/rustfsm_trait/src/lib.rs +8 -3
  79. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
  80. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-23_history.bin +0 -0
  81. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-85_history.bin +0 -0
  82. data/bridge/sdk-core/protos/api_upstream/buf.yaml +0 -3
  83. data/bridge/sdk-core/protos/api_upstream/build/go.mod +7 -0
  84. data/bridge/sdk-core/protos/api_upstream/build/go.sum +5 -0
  85. data/bridge/sdk-core/protos/api_upstream/{temporal/api/enums/v1/cluster.proto → build/tools.go} +7 -18
  86. data/bridge/sdk-core/protos/api_upstream/go.mod +6 -0
  87. data/bridge/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +12 -9
  88. data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +15 -26
  89. data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +13 -2
  90. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -2
  91. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +4 -9
  92. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +3 -2
  93. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +10 -8
  94. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +28 -2
  95. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +2 -2
  96. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +2 -2
  97. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -2
  98. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +2 -2
  99. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +2 -2
  100. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +24 -19
  101. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +2 -2
  102. data/bridge/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +2 -2
  103. data/bridge/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -2
  104. data/bridge/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +2 -2
  105. data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +62 -26
  106. data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +4 -2
  107. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +24 -61
  108. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +2 -21
  109. data/bridge/sdk-core/protos/api_upstream/temporal/api/protocol/v1/message.proto +57 -0
  110. data/bridge/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +2 -2
  111. data/bridge/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +2 -2
  112. data/bridge/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +110 -31
  113. data/bridge/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
  114. data/bridge/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +4 -4
  115. data/bridge/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +71 -6
  116. data/bridge/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +2 -2
  117. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +3 -2
  118. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +111 -36
  119. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +19 -5
  120. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +1 -0
  121. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +1 -0
  122. data/bridge/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +1 -0
  123. data/bridge/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
  124. data/bridge/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
  125. data/bridge/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +1 -0
  126. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +9 -0
  127. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +9 -1
  128. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +6 -0
  129. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +2 -2
  130. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +2 -2
  131. data/bridge/sdk-core/sdk/Cargo.toml +4 -3
  132. data/bridge/sdk-core/sdk/src/interceptors.rs +36 -3
  133. data/bridge/sdk-core/sdk/src/lib.rs +94 -25
  134. data/bridge/sdk-core/sdk/src/workflow_context.rs +13 -2
  135. data/bridge/sdk-core/sdk/src/workflow_future.rs +10 -13
  136. data/bridge/sdk-core/sdk-core-protos/Cargo.toml +5 -2
  137. data/bridge/sdk-core/sdk-core-protos/build.rs +36 -2
  138. data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +164 -104
  139. data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +27 -23
  140. data/bridge/sdk-core/sdk-core-protos/src/lib.rs +252 -74
  141. data/bridge/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
  142. data/bridge/sdk-core/test-utils/Cargo.toml +4 -1
  143. data/bridge/sdk-core/test-utils/src/canned_histories.rs +106 -296
  144. data/bridge/sdk-core/test-utils/src/histfetch.rs +1 -1
  145. data/bridge/sdk-core/test-utils/src/lib.rs +161 -50
  146. data/bridge/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
  147. data/bridge/sdk-core/test-utils/src/workflows.rs +29 -0
  148. data/bridge/sdk-core/tests/fuzzy_workflow.rs +130 -0
  149. data/bridge/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +125 -51
  150. data/bridge/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
  151. data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +10 -5
  152. data/bridge/sdk-core/tests/integ_tests/metrics_tests.rs +239 -0
  153. data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +4 -60
  154. data/bridge/sdk-core/tests/integ_tests/queries_tests.rs +5 -128
  155. data/bridge/sdk-core/tests/integ_tests/visibility_tests.rs +83 -25
  156. data/bridge/sdk-core/tests/integ_tests/workflow_tests/activities.rs +93 -69
  157. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
  158. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +6 -13
  159. data/bridge/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +1 -0
  160. data/bridge/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +6 -2
  161. data/bridge/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -10
  162. data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +151 -116
  163. data/bridge/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +54 -0
  164. data/bridge/sdk-core/tests/integ_tests/workflow_tests/patches.rs +7 -28
  165. data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +115 -24
  166. data/bridge/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
  167. data/bridge/sdk-core/tests/integ_tests/workflow_tests/signals.rs +18 -14
  168. data/bridge/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +6 -20
  169. data/bridge/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -21
  170. data/bridge/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +6 -4
  171. data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +27 -18
  172. data/bridge/sdk-core/tests/main.rs +8 -16
  173. data/bridge/sdk-core/tests/runner.rs +75 -36
  174. data/bridge/sdk-core/tests/wf_input_replay.rs +32 -0
  175. data/bridge/src/connection.rs +117 -82
  176. data/bridge/src/lib.rs +356 -42
  177. data/bridge/src/runtime.rs +10 -3
  178. data/bridge/src/test_server.rs +153 -0
  179. data/bridge/src/worker.rs +133 -9
  180. data/lib/gen/temporal/api/batch/v1/message_pb.rb +8 -6
  181. data/lib/gen/temporal/api/command/v1/message_pb.rb +10 -16
  182. data/lib/gen/temporal/api/common/v1/message_pb.rb +5 -1
  183. data/lib/gen/temporal/api/enums/v1/batch_operation_pb.rb +2 -1
  184. data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +3 -3
  185. data/lib/gen/temporal/api/enums/v1/common_pb.rb +2 -1
  186. data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +5 -4
  187. data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +9 -1
  188. data/lib/gen/temporal/api/enums/v1/namespace_pb.rb +1 -1
  189. data/lib/gen/temporal/api/enums/v1/query_pb.rb +1 -1
  190. data/lib/gen/temporal/api/enums/v1/reset_pb.rb +1 -1
  191. data/lib/gen/temporal/api/enums/v1/schedule_pb.rb +1 -1
  192. data/lib/gen/temporal/api/enums/v1/task_queue_pb.rb +1 -1
  193. data/lib/gen/temporal/api/enums/v1/update_pb.rb +7 -10
  194. data/lib/gen/temporal/api/enums/v1/workflow_pb.rb +1 -1
  195. data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +1 -1
  196. data/lib/gen/temporal/api/failure/v1/message_pb.rb +1 -1
  197. data/lib/gen/temporal/api/filter/v1/message_pb.rb +1 -1
  198. data/lib/gen/temporal/api/history/v1/message_pb.rb +34 -25
  199. data/lib/gen/temporal/api/namespace/v1/message_pb.rb +2 -1
  200. data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +14 -51
  201. data/lib/gen/temporal/api/operatorservice/v1/service_pb.rb +1 -1
  202. data/lib/gen/temporal/api/protocol/v1/message_pb.rb +30 -0
  203. data/lib/gen/temporal/api/query/v1/message_pb.rb +1 -1
  204. data/lib/gen/temporal/api/replication/v1/message_pb.rb +1 -1
  205. data/lib/gen/temporal/api/schedule/v1/message_pb.rb +22 -1
  206. data/lib/gen/temporal/api/sdk/v1/task_complete_metadata_pb.rb +23 -0
  207. data/lib/gen/temporal/api/taskqueue/v1/message_pb.rb +2 -2
  208. data/lib/gen/temporal/api/testservice/v1/request_response_pb.rb +49 -0
  209. data/lib/gen/temporal/api/testservice/v1/service_pb.rb +21 -0
  210. data/lib/gen/temporal/api/update/v1/message_pb.rb +49 -3
  211. data/lib/gen/temporal/api/version/v1/message_pb.rb +1 -1
  212. data/lib/gen/temporal/api/workflow/v1/message_pb.rb +2 -1
  213. data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +47 -20
  214. data/lib/gen/temporal/api/workflowservice/v1/service_pb.rb +1 -1
  215. data/lib/gen/temporal/sdk/core/activity_result/activity_result_pb.rb +13 -9
  216. data/lib/gen/temporal/sdk/core/activity_task/activity_task_pb.rb +10 -6
  217. data/lib/gen/temporal/sdk/core/child_workflow/child_workflow_pb.rb +13 -9
  218. data/lib/gen/temporal/sdk/core/common/common_pb.rb +7 -3
  219. data/lib/gen/temporal/sdk/core/core_interface_pb.rb +9 -3
  220. data/lib/gen/temporal/sdk/core/external_data/external_data_pb.rb +7 -3
  221. data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +28 -21
  222. data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +32 -24
  223. data/lib/gen/temporal/sdk/core/workflow_completion/workflow_completion_pb.rb +12 -5
  224. data/lib/temporalio/activity/context.rb +102 -0
  225. data/lib/temporalio/activity/info.rb +67 -0
  226. data/lib/temporalio/activity.rb +85 -0
  227. data/lib/temporalio/bridge/connect_options.rb +15 -0
  228. data/lib/temporalio/bridge/error.rb +8 -0
  229. data/lib/temporalio/bridge/retry_config.rb +24 -0
  230. data/lib/temporalio/bridge/tls_options.rb +19 -0
  231. data/lib/temporalio/bridge.rb +14 -0
  232. data/lib/{temporal → temporalio}/client/implementation.rb +57 -56
  233. data/lib/{temporal → temporalio}/client/workflow_handle.rb +35 -35
  234. data/lib/{temporal → temporalio}/client.rb +19 -32
  235. data/lib/temporalio/connection/retry_config.rb +44 -0
  236. data/lib/temporalio/connection/service.rb +20 -0
  237. data/lib/temporalio/connection/test_service.rb +92 -0
  238. data/lib/temporalio/connection/tls_options.rb +51 -0
  239. data/lib/temporalio/connection/workflow_service.rb +731 -0
  240. data/lib/temporalio/connection.rb +86 -0
  241. data/lib/{temporal → temporalio}/data_converter.rb +76 -35
  242. data/lib/{temporal → temporalio}/error/failure.rb +6 -6
  243. data/lib/{temporal → temporalio}/error/workflow_failure.rb +4 -2
  244. data/lib/{temporal → temporalio}/errors.rb +19 -1
  245. data/lib/{temporal → temporalio}/failure_converter/base.rb +5 -5
  246. data/lib/{temporal → temporalio}/failure_converter/basic.rb +58 -52
  247. data/lib/temporalio/failure_converter.rb +7 -0
  248. data/lib/temporalio/interceptor/activity_inbound.rb +22 -0
  249. data/lib/temporalio/interceptor/activity_outbound.rb +24 -0
  250. data/lib/{temporal → temporalio}/interceptor/chain.rb +7 -6
  251. data/lib/{temporal → temporalio}/interceptor/client.rb +27 -2
  252. data/lib/temporalio/interceptor.rb +22 -0
  253. data/lib/{temporal → temporalio}/payload_codec/base.rb +5 -5
  254. data/lib/{temporal → temporalio}/payload_converter/base.rb +3 -3
  255. data/lib/{temporal → temporalio}/payload_converter/bytes.rb +4 -3
  256. data/lib/{temporal → temporalio}/payload_converter/composite.rb +7 -5
  257. data/lib/{temporal → temporalio}/payload_converter/encoding_base.rb +4 -4
  258. data/lib/{temporal → temporalio}/payload_converter/json.rb +4 -3
  259. data/lib/{temporal → temporalio}/payload_converter/nil.rb +4 -3
  260. data/lib/temporalio/payload_converter.rb +14 -0
  261. data/lib/{temporal → temporalio}/retry_policy.rb +17 -7
  262. data/lib/{temporal → temporalio}/retry_state.rb +1 -1
  263. data/lib/temporalio/runtime.rb +25 -0
  264. data/lib/temporalio/testing/time_skipping_handle.rb +32 -0
  265. data/lib/temporalio/testing/time_skipping_interceptor.rb +23 -0
  266. data/lib/temporalio/testing/workflow_environment.rb +112 -0
  267. data/lib/temporalio/testing.rb +175 -0
  268. data/lib/{temporal → temporalio}/timeout_type.rb +2 -2
  269. data/lib/temporalio/version.rb +3 -0
  270. data/lib/temporalio/worker/activity_runner.rb +114 -0
  271. data/lib/temporalio/worker/activity_worker.rb +164 -0
  272. data/lib/temporalio/worker/reactor.rb +46 -0
  273. data/lib/temporalio/worker/runner.rb +63 -0
  274. data/lib/temporalio/worker/sync_worker.rb +124 -0
  275. data/lib/temporalio/worker/thread_pool_executor.rb +51 -0
  276. data/lib/temporalio/worker.rb +204 -0
  277. data/lib/temporalio/workflow/async.rb +46 -0
  278. data/lib/{temporal → temporalio}/workflow/execution_info.rb +4 -4
  279. data/lib/{temporal → temporalio}/workflow/execution_status.rb +1 -1
  280. data/lib/temporalio/workflow/future.rb +138 -0
  281. data/lib/{temporal → temporalio}/workflow/id_reuse_policy.rb +6 -6
  282. data/lib/temporalio/workflow/info.rb +76 -0
  283. data/lib/{temporal → temporalio}/workflow/query_reject_condition.rb +5 -5
  284. data/lib/temporalio.rb +12 -3
  285. data/temporalio.gemspec +11 -6
  286. metadata +137 -64
  287. data/bridge/sdk-core/Cargo.lock +0 -2606
  288. data/bridge/sdk-core/bridge-ffi/Cargo.toml +0 -24
  289. data/bridge/sdk-core/bridge-ffi/LICENSE.txt +0 -23
  290. data/bridge/sdk-core/bridge-ffi/build.rs +0 -25
  291. data/bridge/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -249
  292. data/bridge/sdk-core/bridge-ffi/src/lib.rs +0 -825
  293. data/bridge/sdk-core/bridge-ffi/src/wrappers.rs +0 -211
  294. data/bridge/sdk-core/core/src/log_export.rs +0 -62
  295. data/bridge/sdk-core/core/src/worker/workflow/machines/mutable_side_effect_state_machine.rs +0 -127
  296. data/bridge/sdk-core/core/src/worker/workflow/machines/side_effect_state_machine.rs +0 -71
  297. data/bridge/sdk-core/protos/api_upstream/temporal/api/cluster/v1/message.proto +0 -83
  298. data/bridge/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -210
  299. data/bridge/sdk-core/sdk/src/conversions.rs +0 -8
  300. data/lib/bridge.so +0 -0
  301. data/lib/gen/temporal/api/cluster/v1/message_pb.rb +0 -67
  302. data/lib/gen/temporal/api/enums/v1/cluster_pb.rb +0 -26
  303. data/lib/gen/temporal/sdk/core/bridge/bridge_pb.rb +0 -222
  304. data/lib/temporal/bridge.rb +0 -14
  305. data/lib/temporal/connection.rb +0 -736
  306. data/lib/temporal/failure_converter.rb +0 -8
  307. data/lib/temporal/payload_converter.rb +0 -14
  308. data/lib/temporal/runtime.rb +0 -22
  309. data/lib/temporal/version.rb +0 -3
  310. data/lib/temporal.rb +0 -8
@@ -7,7 +7,6 @@ use crate::{
7
7
  mock_worker, poll_and_reply, poll_and_reply_clears_outstanding_evicts, single_hist_mock_sg,
8
8
  test_worker_cfg, FakeWfResponses, MockPollCfg, MocksHolder, ResponseType,
9
9
  WorkflowCachingPolicy::{self, AfterEveryReply, NonSticky},
10
- TEST_Q,
11
10
  },
12
11
  worker::client::mocks::{mock_manual_workflow_client, mock_workflow_client},
13
12
  Worker,
@@ -17,7 +16,7 @@ use rstest::{fixture, rstest};
17
16
  use std::{
18
17
  collections::{HashMap, VecDeque},
19
18
  sync::{
20
- atomic::{AtomicU64, Ordering},
19
+ atomic::{AtomicBool, AtomicU64, Ordering},
21
20
  Arc,
22
21
  },
23
22
  time::Duration,
@@ -38,20 +37,25 @@ use temporal_sdk_core_protos::{
38
37
  },
39
38
  workflow_completion::WorkflowActivationCompletion,
40
39
  },
41
- default_wes_attribs,
40
+ default_act_sched, default_wes_attribs,
42
41
  temporal::api::{
43
42
  command::v1::command::Attributes,
44
43
  common::v1::{Payload, RetryPolicy},
45
44
  enums::v1::{EventType, WorkflowTaskFailedCause},
46
45
  failure::v1::Failure,
47
- history::v1::{history_event, TimerFiredEventAttributes},
46
+ history::v1::{
47
+ history_event, TimerFiredEventAttributes,
48
+ WorkflowPropertiesModifiedExternallyEventAttributes,
49
+ },
48
50
  workflowservice::v1::{
49
51
  GetWorkflowExecutionHistoryResponse, RespondWorkflowTaskCompletedResponse,
50
52
  },
51
53
  },
52
- DEFAULT_WORKFLOW_TYPE,
54
+ DEFAULT_ACTIVITY_TYPE, DEFAULT_WORKFLOW_TYPE,
55
+ };
56
+ use temporal_sdk_core_test_utils::{
57
+ fanout_tasks, schedule_activity_cmd, start_timer_cmd, WorkerTestHelpers,
53
58
  };
54
- use temporal_sdk_core_test_utils::{fanout_tasks, start_timer_cmd};
55
59
  use tokio::{
56
60
  join,
57
61
  sync::{Barrier, Semaphore},
@@ -121,7 +125,7 @@ async fn single_activity_completion(worker: Worker) {
121
125
  &job_assert!(workflow_activation_job::Variant::StartWorkflow(_)),
122
126
  vec![ScheduleActivity {
123
127
  activity_id: "fake_activity".to_string(),
124
- ..Default::default()
128
+ ..default_act_sched()
125
129
  }
126
130
  .into()],
127
131
  ),
@@ -246,7 +250,7 @@ async fn scheduled_activity_cancellation_try_cancel(hist_batches: &'static [usiz
246
250
  seq: activity_seq,
247
251
  activity_id: activity_id.to_string(),
248
252
  cancellation_type: ActivityCancellationType::TryCancel as i32,
249
- ..Default::default()
253
+ ..default_act_sched()
250
254
  }
251
255
  .into()],
252
256
  ),
@@ -282,7 +286,7 @@ async fn scheduled_activity_timeout(hist_batches: &'static [usize]) {
282
286
  vec![ScheduleActivity {
283
287
  seq: activity_seq,
284
288
  activity_id: activity_id.to_string(),
285
- ..Default::default()
289
+ ..default_act_sched()
286
290
  }
287
291
  .into()],
288
292
  ),
@@ -335,7 +339,7 @@ async fn started_activity_timeout(hist_batches: &'static [usize]) {
335
339
  vec![ScheduleActivity {
336
340
  seq: activity_seq,
337
341
  activity_id: activity_seq.to_string(),
338
- ..Default::default()
342
+ ..default_act_sched()
339
343
  }
340
344
  .into()],
341
345
  ),
@@ -390,7 +394,7 @@ async fn cancelled_activity_timeout(hist_batches: &'static [usize]) {
390
394
  vec![ScheduleActivity {
391
395
  seq: activity_seq,
392
396
  activity_id: activity_id.to_string(),
393
- ..Default::default()
397
+ ..default_act_sched()
394
398
  }
395
399
  .into()],
396
400
  ),
@@ -458,10 +462,10 @@ async fn abandoned_activities_ignore_start_and_complete(hist_batches: &'static [
458
462
  t.add_by_type(EventType::WorkflowExecutionStarted);
459
463
  t.add_full_wf_task();
460
464
  let act_scheduled_event_id = t.add_activity_task_scheduled(activity_id);
461
- let timer_started_event_id = t.add_get_event_id(EventType::TimerStarted, None);
465
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
462
466
  t.add_timer_fired(timer_started_event_id, "1".to_string());
463
467
  t.add_full_wf_task();
464
- let timer_started_event_id = t.add_get_event_id(EventType::TimerStarted, None);
468
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
465
469
  let act_started_event_id = t.add_activity_task_started(act_scheduled_event_id);
466
470
  t.add_activity_task_completed(
467
471
  act_scheduled_event_id,
@@ -477,7 +481,7 @@ async fn abandoned_activities_ignore_start_and_complete(hist_batches: &'static [
477
481
 
478
482
  worker.register_wf(wf_type.to_owned(), |ctx: WfContext| async move {
479
483
  let act_fut = ctx.activity(ActivityOptions {
480
- activity_type: "echo_activity".to_string(),
484
+ activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
481
485
  start_to_close_timeout: Some(Duration::from_secs(5)),
482
486
  cancellation_type: ActivityCancellationType::Abandon,
483
487
  ..Default::default()
@@ -543,7 +547,7 @@ async fn verify_activity_cancellation(
543
547
  seq: activity_seq,
544
548
  activity_id: activity_seq.to_string(),
545
549
  cancellation_type: cancel_type as i32,
546
- ..Default::default()
550
+ ..default_act_sched()
547
551
  }
548
552
  .into()],
549
553
  ),
@@ -611,7 +615,7 @@ async fn verify_activity_cancellation_wait_for_cancellation(activity_id: u32, wo
611
615
  seq: activity_id,
612
616
  activity_id: activity_id.to_string(),
613
617
  cancellation_type: ActivityCancellationType::WaitCancellationCompleted as i32,
614
- ..Default::default()
618
+ ..default_act_sched()
615
619
  }
616
620
  .into()],
617
621
  ),
@@ -652,7 +656,7 @@ async fn workflow_update_random_seed_on_workflow_reset() {
652
656
  timer_1_id.to_string().as_str(),
653
657
  new_run_id,
654
658
  );
655
- let core = build_fake_worker(wfid, t, &[2]);
659
+ let core = build_fake_worker(wfid, t, [2]);
656
660
 
657
661
  poll_and_reply(
658
662
  &core,
@@ -706,7 +710,7 @@ async fn cancel_timer_before_sent_wf_bridge() {
706
710
  t.add_full_wf_task();
707
711
  t.add_workflow_execution_completed();
708
712
 
709
- let core = build_fake_worker(wfid, t, &[1]);
713
+ let core = build_fake_worker(wfid, t, [1]);
710
714
 
711
715
  poll_and_reply(
712
716
  &core,
@@ -893,7 +897,7 @@ async fn max_wft_respected() {
893
897
  let total_wfs = 100;
894
898
  let wf_ids: Vec<_> = (0..total_wfs)
895
899
  .into_iter()
896
- .map(|i| format!("fake-wf-{}", i))
900
+ .map(|i| format!("fake-wf-{i}"))
897
901
  .collect();
898
902
  let hists = wf_ids.iter().map(|wf_id| {
899
903
  let hist = canned_histories::single_timer("1");
@@ -948,7 +952,7 @@ async fn activity_not_canceled_on_replay_repro(hist_batches: &'static [usize]) {
948
952
  seq: activity_id,
949
953
  activity_id: activity_id.to_string(),
950
954
  cancellation_type: ActivityCancellationType::TryCancel as i32,
951
- ..Default::default()
955
+ ..default_act_sched()
952
956
  }
953
957
  .into(),
954
958
  start_timer_cmd(1, Duration::from_secs(1)),
@@ -990,9 +994,9 @@ async fn activity_not_canceled_when_also_completed_repro(hist_batches: &'static
990
994
  &job_assert!(workflow_activation_job::Variant::StartWorkflow(_)),
991
995
  vec![ScheduleActivity {
992
996
  seq: activity_id,
993
- activity_id: activity_id.to_string(),
997
+ activity_id: "act-1".to_string(),
994
998
  cancellation_type: ActivityCancellationType::TryCancel as i32,
995
- ..Default::default()
999
+ ..default_act_sched()
996
1000
  }
997
1001
  .into()],
998
1002
  ),
@@ -1023,7 +1027,7 @@ async fn activity_not_canceled_when_also_completed_repro(hist_batches: &'static
1023
1027
  async fn lots_of_workflows() {
1024
1028
  let total_wfs = 500;
1025
1029
  let hists = (0..total_wfs).into_iter().map(|i| {
1026
- let wf_id = format!("fake-wf-{}", i);
1030
+ let wf_id = format!("fake-wf-{i}");
1027
1031
  let hist = canned_histories::single_timer("1");
1028
1032
  FakeWfResponses {
1029
1033
  wf_id,
@@ -1037,7 +1041,6 @@ async fn lots_of_workflows() {
1037
1041
  let completed_count = Arc::new(Semaphore::new(0));
1038
1042
  let killer = async {
1039
1043
  let _ = completed_count.acquire_many(total_wfs).await.unwrap();
1040
- dbg!("Shutdown initted");
1041
1044
  worker.initiate_shutdown();
1042
1045
  };
1043
1046
  let poller = fanout_tasks(5, |_| {
@@ -1094,7 +1097,7 @@ async fn wft_timeout_repro(hist_batches: &'static [usize]) {
1094
1097
  seq: activity_id,
1095
1098
  activity_id: activity_id.to_string(),
1096
1099
  cancellation_type: ActivityCancellationType::TryCancel as i32,
1097
- ..Default::default()
1100
+ ..default_act_sched()
1098
1101
  }
1099
1102
  .into()],
1100
1103
  ),
@@ -1122,7 +1125,7 @@ async fn complete_after_eviction() {
1122
1125
  let t = canned_histories::single_timer("1");
1123
1126
  let mut mock = mock_workflow_client();
1124
1127
  mock.expect_complete_workflow_task().times(0);
1125
- let mock = single_hist_mock_sg(wfid, t, &[2], mock, true);
1128
+ let mock = single_hist_mock_sg(wfid, t, [2], mock, true);
1126
1129
  let core = mock_worker(mock);
1127
1130
 
1128
1131
  let activation = core.poll_workflow_activation().await.unwrap();
@@ -1164,7 +1167,7 @@ async fn sends_appropriate_sticky_task_queue_responses() {
1164
1167
  .times(1)
1165
1168
  .returning(|_| Ok(Default::default()));
1166
1169
  mock.expect_complete_workflow_task().times(0);
1167
- let mut mock = single_hist_mock_sg(wfid, t, &[1], mock, false);
1170
+ let mut mock = single_hist_mock_sg(wfid, t, [1], mock, false);
1168
1171
  mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
1169
1172
  let core = mock_worker(mock);
1170
1173
 
@@ -1182,7 +1185,7 @@ async fn sends_appropriate_sticky_task_queue_responses() {
1182
1185
  async fn new_server_work_while_eviction_outstanding_doesnt_overwrite_activation() {
1183
1186
  let wfid = "fake_wf_id";
1184
1187
  let t = canned_histories::single_timer("1");
1185
- let mock = single_hist_mock_sg(wfid, t, &[1, 2], mock_workflow_client(), false);
1188
+ let mock = single_hist_mock_sg(wfid, t, [1, 2], mock_workflow_client(), false);
1186
1189
  let taskmap = mock.outstanding_task_map.clone().unwrap();
1187
1190
  let core = mock_worker(mock);
1188
1191
 
@@ -1224,17 +1227,16 @@ async fn buffered_work_drained_on_shutdown() {
1224
1227
  t.add_workflow_task_scheduled_and_started();
1225
1228
  // Need to build the first response before adding the timeout events b/c otherwise the history
1226
1229
  // builder will include them in the first task
1227
- let resp_1 = hist_to_poll_resp(&t, wfid.to_owned(), 1.into(), TEST_Q.to_string()).resp;
1230
+ let resp_1 = hist_to_poll_resp(&t, wfid.to_owned(), 1.into()).resp;
1228
1231
  t.add_workflow_task_timed_out();
1229
1232
  t.add_full_wf_task();
1230
- let timer_started_event_id = t.add_get_event_id(EventType::TimerStarted, None);
1231
- t.add(
1232
- EventType::TimerFired,
1233
- history_event::Attributes::TimerFiredEventAttributes(TimerFiredEventAttributes {
1233
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
1234
+ t.add(history_event::Attributes::TimerFiredEventAttributes(
1235
+ TimerFiredEventAttributes {
1234
1236
  started_event_id: timer_started_event_id,
1235
1237
  timer_id: "1".to_string(),
1236
- }),
1237
- );
1238
+ },
1239
+ ));
1238
1240
  t.add_full_wf_task();
1239
1241
  t.add_workflow_execution_completed();
1240
1242
 
@@ -1242,10 +1244,7 @@ async fn buffered_work_drained_on_shutdown() {
1242
1244
  // Extend the task list with the now timeout-included version of the task. We add a bunch of
1243
1245
  // them because the poll loop will spin while new tasks are available and it is buffering them
1244
1246
  tasks.extend(
1245
- std::iter::repeat_with(|| {
1246
- hist_to_poll_resp(&t, wfid.to_owned(), 2.into(), TEST_Q.to_string()).resp
1247
- })
1248
- .take(50),
1247
+ std::iter::repeat_with(|| hist_to_poll_resp(&t, wfid.to_owned(), 2.into()).resp).take(50),
1249
1248
  );
1250
1249
  let mut mock = mock_workflow_client();
1251
1250
  mock.expect_complete_workflow_task()
@@ -1269,6 +1268,8 @@ async fn buffered_work_drained_on_shutdown() {
1269
1268
  .unwrap();
1270
1269
  };
1271
1270
  let complete_first = async move {
1271
+ // If the first complete is sent too fast, we may not have had a chance to buffer work.
1272
+ tokio::time::sleep(Duration::from_millis(50)).await;
1272
1273
  core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
1273
1274
  act1.run_id,
1274
1275
  start_timer_cmd(1, Duration::from_secs(1)),
@@ -1277,8 +1278,6 @@ async fn buffered_work_drained_on_shutdown() {
1277
1278
  .unwrap();
1278
1279
  };
1279
1280
  join!(poll_fut, complete_first, async {
1280
- // If the shutdown is sent too too fast, we might not have got a chance to even buffer work
1281
- tokio::time::sleep(Duration::from_millis(5)).await;
1282
1281
  core.shutdown().await;
1283
1282
  });
1284
1283
  }
@@ -1308,7 +1307,7 @@ async fn fail_wft_then_recover() {
1308
1307
  act.run_id.clone(),
1309
1308
  vec![ScheduleActivity {
1310
1309
  activity_id: "fake_activity".to_string(),
1311
- ..Default::default()
1310
+ ..default_act_sched()
1312
1311
  }
1313
1312
  .into()],
1314
1313
  ))
@@ -1360,12 +1359,17 @@ async fn poll_response_triggers_wf_error() {
1360
1359
  t.add_full_wf_task();
1361
1360
  t.add_workflow_execution_completed();
1362
1361
 
1363
- let mh = MockPollCfg::from_resp_batches(
1362
+ let mut mh = MockPollCfg::from_resp_batches(
1364
1363
  "fake_wf_id",
1365
1364
  t,
1366
1365
  [ResponseType::AllHistory],
1367
1366
  mock_workflow_client(),
1368
1367
  );
1368
+ // Fail wft will be called when auto-failing.
1369
+ mh.num_expected_fails = 1;
1370
+ mh.expect_fail_wft_matcher = Box::new(move |_, cause, _| {
1371
+ matches!(cause, WorkflowTaskFailedCause::NonDeterministicError)
1372
+ });
1369
1373
  let mock = build_mock_pollers(mh);
1370
1374
  let core = mock_worker(mock);
1371
1375
  // Poll for first WFT, which is immediately an eviction
@@ -1448,7 +1452,7 @@ async fn tries_cancel_of_completed_activity() {
1448
1452
  t.add_workflow_task_scheduled_and_started();
1449
1453
 
1450
1454
  let mock = mock_workflow_client();
1451
- let mut mock = single_hist_mock_sg("fake_wf_id", t, &[1, 2], mock, true);
1455
+ let mut mock = single_hist_mock_sg("fake_wf_id", t, [1, 2], mock, true);
1452
1456
  mock.worker_cfg(|cfg| cfg.max_cached_workflows = 1);
1453
1457
  let core = mock_worker(mock);
1454
1458
 
@@ -1458,7 +1462,7 @@ async fn tries_cancel_of_completed_activity() {
1458
1462
  ScheduleActivity {
1459
1463
  seq: 1,
1460
1464
  activity_id: "1".to_string(),
1461
- ..Default::default()
1465
+ ..default_act_sched()
1462
1466
  }
1463
1467
  .into(),
1464
1468
  ))
@@ -1551,9 +1555,8 @@ async fn failing_wft_doesnt_eat_permit_forever() {
1551
1555
  ))
1552
1556
  .await
1553
1557
  .unwrap();
1554
- assert_eq!(worker.available_wft_permits().await, 2);
1555
-
1556
1558
  worker.shutdown().await;
1559
+ assert_eq!(worker.available_wft_permits().await, 2);
1557
1560
  }
1558
1561
 
1559
1562
  #[tokio::test]
@@ -1579,6 +1582,8 @@ async fn cache_miss_will_fetch_history() {
1579
1582
  let mut mock = build_mock_pollers(mh);
1580
1583
  mock.worker_cfg(|cfg| {
1581
1584
  cfg.max_cached_workflows = 1;
1585
+ // Also verifies tying the WFT permit to the fetch request doesn't get us stuck
1586
+ cfg.max_outstanding_workflow_tasks = 1;
1582
1587
  });
1583
1588
  let worker = mock_worker(mock);
1584
1589
 
@@ -1658,10 +1663,9 @@ async fn tasks_from_completion_are_delivered() {
1658
1663
 
1659
1664
  let mut mock = mock_workflow_client();
1660
1665
  let complete_resp = RespondWorkflowTaskCompletedResponse {
1661
- workflow_task: Some(
1662
- hist_to_poll_resp(&t, wfid.to_owned(), 2.into(), TEST_Q.to_string()).resp,
1663
- ),
1666
+ workflow_task: Some(hist_to_poll_resp(&t, wfid.to_owned(), 2.into()).resp),
1664
1667
  activity_tasks: vec![],
1668
+ reset_history_event_id: 0,
1665
1669
  };
1666
1670
  mock.expect_complete_workflow_task()
1667
1671
  .times(1)
@@ -1693,12 +1697,63 @@ async fn tasks_from_completion_are_delivered() {
1693
1697
  core.shutdown().await;
1694
1698
  }
1695
1699
 
1700
+ #[tokio::test]
1701
+ async fn pagination_works_with_tasks_from_completion() {
1702
+ let wfid = "fake_wf_id";
1703
+ let mut t = TestHistoryBuilder::default();
1704
+ t.add_by_type(EventType::WorkflowExecutionStarted);
1705
+ t.add_full_wf_task();
1706
+ t.add_we_signaled("sig", vec![]);
1707
+ t.add_full_wf_task();
1708
+ t.add_workflow_execution_completed();
1709
+ let get_exec_resp: GetWorkflowExecutionHistoryResponse = t.get_history_info(2).unwrap().into();
1710
+
1711
+ let mut mock = mock_workflow_client();
1712
+ let mut needs_pag_resp = hist_to_poll_resp(&t, wfid.to_owned(), ResponseType::OneTask(2)).resp;
1713
+ needs_pag_resp.next_page_token = vec![1];
1714
+ let complete_resp = RespondWorkflowTaskCompletedResponse {
1715
+ workflow_task: Some(needs_pag_resp),
1716
+ ..Default::default()
1717
+ };
1718
+ mock.expect_complete_workflow_task()
1719
+ .times(1)
1720
+ .returning(move |_| Ok(complete_resp.clone()));
1721
+ mock.expect_complete_workflow_task()
1722
+ .times(1)
1723
+ .returning(|_| Ok(Default::default()));
1724
+ mock.expect_get_workflow_execution_history()
1725
+ .returning(move |_, _, _| Ok(get_exec_resp.clone()))
1726
+ .times(1);
1727
+ let mut mock = single_hist_mock_sg(wfid, t, [1], mock, true);
1728
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 2);
1729
+ let core = mock_worker(mock);
1730
+
1731
+ let wf_task = core.poll_workflow_activation().await.unwrap();
1732
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
1733
+ .await
1734
+ .unwrap();
1735
+ let wf_task = core.poll_workflow_activation().await.unwrap();
1736
+ assert_matches!(
1737
+ wf_task.jobs.as_slice(),
1738
+ [WorkflowActivationJob {
1739
+ variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
1740
+ },]
1741
+ );
1742
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmds(
1743
+ wf_task.run_id,
1744
+ vec![CompleteWorkflowExecution { result: None }.into()],
1745
+ ))
1746
+ .await
1747
+ .unwrap();
1748
+ core.shutdown().await;
1749
+ }
1750
+
1696
1751
  #[tokio::test]
1697
1752
  async fn poll_faster_than_complete_wont_overflow_cache() {
1698
1753
  // Make workflow tasks for 5 different runs
1699
1754
  let tasks: Vec<_> = (1..=5)
1700
1755
  .map(|i| FakeWfResponses {
1701
- wf_id: format!("wf-{}", i),
1756
+ wf_id: format!("wf-{i}"),
1702
1757
  hist: canned_histories::single_timer("1"),
1703
1758
  response_batches: vec![ResponseType::ToTaskNum(1)],
1704
1759
  })
@@ -1829,7 +1884,7 @@ async fn eviction_waits_until_replay_finished() {
1829
1884
  let wfid = "fake_wf_id";
1830
1885
  let t = canned_histories::long_sequential_timers(3);
1831
1886
  let mock = mock_workflow_client();
1832
- let mock = single_hist_mock_sg(wfid, t, &[3], mock, true);
1887
+ let mock = single_hist_mock_sg(wfid, t, [3], mock, true);
1833
1888
  let core = mock_worker(mock);
1834
1889
 
1835
1890
  let activation = core.poll_workflow_activation().await.unwrap();
@@ -1890,7 +1945,7 @@ async fn autocompletes_wft_no_work() {
1890
1945
  t.add_activity_task_completed(scheduled_event_id, started_event_id, Default::default());
1891
1946
  t.add_full_wf_task();
1892
1947
  let mock = mock_workflow_client();
1893
- let mut mock = single_hist_mock_sg(wfid, t, &[1, 2, 3, 4], mock, true);
1948
+ let mut mock = single_hist_mock_sg(wfid, t, [1, 2, 3, 4], mock, true);
1894
1949
  mock.worker_cfg(|w| w.max_cached_workflows = 1);
1895
1950
  let core = mock_worker(mock);
1896
1951
 
@@ -1907,7 +1962,7 @@ async fn autocompletes_wft_no_work() {
1907
1962
  seq: 1,
1908
1963
  activity_id: activity_id.to_string(),
1909
1964
  cancellation_type: ActivityCancellationType::Abandon as i32,
1910
- ..Default::default()
1965
+ ..default_act_sched()
1911
1966
  }
1912
1967
  .into(),
1913
1968
  ))
@@ -1951,8 +2006,7 @@ async fn no_race_acquiring_permits() {
1951
2006
  .expect_poll_workflow_task()
1952
2007
  .returning(move |_, _| {
1953
2008
  let t = canned_histories::single_timer("1");
1954
- let poll_resp =
1955
- hist_to_poll_resp(&t, wfid.to_owned(), 2.into(), TEST_Q.to_string()).resp;
2009
+ let poll_resp = hist_to_poll_resp(&t, wfid.to_owned(), 2.into()).resp;
1956
2010
  async move {
1957
2011
  task_barr.wait().await;
1958
2012
  Ok(poll_resp.clone())
@@ -2021,23 +2075,14 @@ async fn continue_as_new_preserves_some_values() {
2021
2075
  let mut mock_client = mock_workflow_client();
2022
2076
  let hist = {
2023
2077
  let mut t = TestHistoryBuilder::default();
2024
- t.add(
2025
- EventType::WorkflowExecutionStarted,
2026
- wes_attrs.clone().into(),
2027
- );
2078
+ t.add(wes_attrs.clone());
2028
2079
  t.add_full_wf_task();
2029
2080
  t
2030
2081
  };
2031
2082
  mock_client
2032
2083
  .expect_poll_workflow_task()
2033
2084
  .returning(move |_, _| {
2034
- Ok(hist_to_poll_resp(
2035
- &hist,
2036
- wfid.to_owned(),
2037
- ResponseType::AllHistory,
2038
- TEST_Q.to_string(),
2039
- )
2040
- .resp)
2085
+ Ok(hist_to_poll_resp(&hist, wfid.to_owned(), ResponseType::AllHistory).resp)
2041
2086
  });
2042
2087
  mock_client
2043
2088
  .expect_complete_workflow_task()
@@ -2068,3 +2113,321 @@ async fn continue_as_new_preserves_some_values() {
2068
2113
  .await
2069
2114
  .unwrap();
2070
2115
  }
2116
+
2117
+ #[rstest]
2118
+ #[tokio::test]
2119
+ async fn ignorable_events_are_ok(#[values(true, false)] attribs_unset: bool) {
2120
+ let mut t = TestHistoryBuilder::default();
2121
+ t.add_by_type(EventType::WorkflowExecutionStarted);
2122
+ let id = t.add(WorkflowPropertiesModifiedExternallyEventAttributes::default());
2123
+ t.modify_event(id, |e| {
2124
+ e.worker_may_ignore = true;
2125
+ // Ignorable events are ignored if we can't interpret the proto of either the event attribs
2126
+ // or proto - otherwise (this is the _may_ part of may ignore), we'll still try to process
2127
+ // it. That processing may ultimately still choose to do nothing, if we want to _explicitly_
2128
+ // ignore it.
2129
+ if attribs_unset {
2130
+ e.attributes = None;
2131
+ } else {
2132
+ e.event_type = EventType::Unspecified as i32;
2133
+ }
2134
+ });
2135
+ t.add_workflow_task_scheduled_and_started();
2136
+
2137
+ let mock = mock_workflow_client();
2138
+ let mock = single_hist_mock_sg("wheee", t, [ResponseType::AllHistory], mock, true);
2139
+ let core = mock_worker(mock);
2140
+
2141
+ let act = core.poll_workflow_activation().await.unwrap();
2142
+ assert_matches!(
2143
+ act.jobs[0].variant,
2144
+ Some(workflow_activation_job::Variant::StartWorkflow(_))
2145
+ );
2146
+ }
2147
+
2148
+ #[tokio::test]
2149
+ async fn fetching_to_continue_replay_works() {
2150
+ let mut mock_client = mock_workflow_client();
2151
+ let mut t = TestHistoryBuilder::default();
2152
+ t.add_by_type(EventType::WorkflowExecutionStarted);
2153
+ t.add_full_wf_task();
2154
+ t.add_full_wf_task(); // ends 7
2155
+ let mut need_fetch_resp =
2156
+ hist_to_poll_resp(&t, "wfid".to_owned(), ResponseType::AllHistory).resp;
2157
+ need_fetch_resp.next_page_token = vec![1];
2158
+
2159
+ t.add_full_wf_task();
2160
+ t.add_we_signaled("hi", vec![]); // Need to make there be two complete WFTs
2161
+ t.add_full_wf_task(); // end 14
2162
+ let mut fetch_resp: GetWorkflowExecutionHistoryResponse =
2163
+ t.get_full_history_info().unwrap().into();
2164
+ // Should only contain events after 7
2165
+ if let Some(ref mut h) = fetch_resp.history {
2166
+ h.events.retain(|e| e.event_id >= 8);
2167
+ }
2168
+ // And indicate that even *more* needs to be fetched after this, so we see a request for the
2169
+ // next page happen.
2170
+ fetch_resp.next_page_token = vec![2];
2171
+
2172
+ let timer_started_event_id = t.add_by_type(EventType::TimerStarted);
2173
+ t.add_timer_fired(timer_started_event_id, "1".to_string());
2174
+ t.add_full_wf_task();
2175
+ let mut final_fetch_resp: GetWorkflowExecutionHistoryResponse =
2176
+ t.get_full_history_info().unwrap().into();
2177
+ // Should have only the final event
2178
+ if let Some(ref mut h) = final_fetch_resp.history {
2179
+ h.events.retain(|e| e.event_id >= 15);
2180
+ }
2181
+
2182
+ let tasks = vec![
2183
+ ResponseType::ToTaskNum(1),
2184
+ ResponseType::Raw(need_fetch_resp),
2185
+ ];
2186
+ mock_client
2187
+ .expect_get_workflow_execution_history()
2188
+ .returning(move |_, _, _| Ok(fetch_resp.clone()))
2189
+ .times(1);
2190
+ mock_client
2191
+ .expect_get_workflow_execution_history()
2192
+ .returning(move |_, _, _| Ok(final_fetch_resp.clone()))
2193
+ .times(1);
2194
+ let mut mock = single_hist_mock_sg("wfid", t, tasks, mock_client, true);
2195
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
2196
+ let core = mock_worker(mock);
2197
+ let act = core.poll_workflow_activation().await.unwrap();
2198
+ assert_matches!(
2199
+ act.jobs[0].variant,
2200
+ Some(workflow_activation_job::Variant::StartWorkflow(_))
2201
+ );
2202
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(act.run_id))
2203
+ .await
2204
+ .unwrap();
2205
+ let act = core.poll_workflow_activation().await.unwrap();
2206
+ assert_matches!(
2207
+ act.jobs.as_slice(),
2208
+ [WorkflowActivationJob {
2209
+ variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
2210
+ }]
2211
+ );
2212
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
2213
+ act.run_id,
2214
+ start_timer_cmd(1, Duration::from_secs(1)),
2215
+ ))
2216
+ .await
2217
+ .unwrap();
2218
+ let act = core.poll_workflow_activation().await.unwrap();
2219
+ assert_matches!(
2220
+ act.jobs.as_slice(),
2221
+ [WorkflowActivationJob {
2222
+ variant: Some(workflow_activation_job::Variant::FireTimer(_)),
2223
+ }]
2224
+ );
2225
+ }
2226
+
2227
+ #[tokio::test]
2228
+ async fn fetching_error_evicts_wf() {
2229
+ let mut mock_client = mock_workflow_client();
2230
+ let mut t = TestHistoryBuilder::default();
2231
+ t.add_by_type(EventType::WorkflowExecutionStarted);
2232
+ t.add_workflow_task_scheduled_and_started();
2233
+ t.add_workflow_task_completed();
2234
+ let mut need_fetch_resp =
2235
+ hist_to_poll_resp(&t, "wfid".to_owned(), ResponseType::AllHistory).resp;
2236
+ need_fetch_resp.next_page_token = vec![1];
2237
+ let tasks = vec![
2238
+ ResponseType::ToTaskNum(1),
2239
+ ResponseType::Raw(need_fetch_resp),
2240
+ ];
2241
+ mock_client
2242
+ .expect_get_workflow_execution_history()
2243
+ .returning(move |_, _, _| Err(tonic::Status::not_found("Ahh broken")))
2244
+ .times(1);
2245
+ let mut mock = single_hist_mock_sg("wfid", t, tasks, mock_client, true);
2246
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 10);
2247
+ let core = mock_worker(mock);
2248
+ let act = core.poll_workflow_activation().await.unwrap();
2249
+ assert_matches!(
2250
+ act.jobs[0].variant,
2251
+ Some(workflow_activation_job::Variant::StartWorkflow(_))
2252
+ );
2253
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(act.run_id))
2254
+ .await
2255
+ .unwrap();
2256
+ let evict_act = core.poll_workflow_activation().await.unwrap();
2257
+ assert_matches!(
2258
+ evict_act.jobs.as_slice(),
2259
+ [WorkflowActivationJob {
2260
+ variant: Some(workflow_activation_job::Variant::RemoveFromCache(r)),
2261
+ }] => r.message.contains("Fetching history failed")
2262
+ );
2263
+ }
2264
+
2265
+ /// This test verifies that if we fail to fetch a page during a completion, that we don't get stuck
2266
+ /// in the complete waiting for the completion to finish.
2267
+ #[tokio::test]
2268
+ async fn ensure_fetching_fail_during_complete_sends_task_failure() {
2269
+ let wfid = "fake_wf_id";
2270
+ let mut t = TestHistoryBuilder::default();
2271
+ t.add_by_type(EventType::WorkflowExecutionStarted);
2272
+ t.add_full_wf_task(); // started 3
2273
+ t.add_we_signaled("sig1", vec![]);
2274
+ t.add_full_wf_task(); // started 7
2275
+ t.add_we_signaled("sig2", vec![]);
2276
+ t.add_full_wf_task(); // started 11
2277
+ t.add_workflow_execution_completed();
2278
+
2279
+ let mut first_poll = hist_to_poll_resp(&t, wfid, ResponseType::ToTaskNum(1)).resp;
2280
+ first_poll.next_page_token = vec![1];
2281
+ first_poll.previous_started_event_id = 3;
2282
+
2283
+ let mut next_page: GetWorkflowExecutionHistoryResponse = t.get_history_info(2).unwrap().into();
2284
+ next_page.next_page_token = vec![2];
2285
+
2286
+ let mut mock = mock_workflow_client();
2287
+ mock.expect_get_workflow_execution_history()
2288
+ .returning(move |_, _, _| {
2289
+ error!("Called fetch!");
2290
+ Ok(next_page.clone())
2291
+ })
2292
+ .times(1);
2293
+ let mut really_empty_fetch_resp: GetWorkflowExecutionHistoryResponse =
2294
+ t.get_history_info(1).unwrap().into();
2295
+ really_empty_fetch_resp.history = Some(Default::default());
2296
+ mock.expect_get_workflow_execution_history()
2297
+ .returning(move |_, _, _| {
2298
+ error!("Called fetch second time!");
2299
+ Ok(really_empty_fetch_resp.clone())
2300
+ })
2301
+ .times(1);
2302
+ mock.expect_fail_workflow_task()
2303
+ .returning(|_, _, _| Ok(Default::default()))
2304
+ .times(1);
2305
+
2306
+ let mut mock = single_hist_mock_sg(wfid, t, [ResponseType::Raw(first_poll)], mock, true);
2307
+ mock.make_wft_stream_interminable();
2308
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 2);
2309
+ let core = mock_worker(mock);
2310
+
2311
+ let wf_task = core.poll_workflow_activation().await.unwrap();
2312
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
2313
+ .await
2314
+ .unwrap();
2315
+
2316
+ let wf_task = core.poll_workflow_activation().await.unwrap();
2317
+ assert_matches!(
2318
+ wf_task.jobs.as_slice(),
2319
+ [WorkflowActivationJob {
2320
+ variant: Some(workflow_activation_job::Variant::SignalWorkflow(_)),
2321
+ },]
2322
+ );
2323
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(wf_task.run_id))
2324
+ .await
2325
+ .unwrap();
2326
+
2327
+ // Expect to see eviction b/c of history fetching error here.
2328
+ let wf_task = core.poll_workflow_activation().await.unwrap();
2329
+ assert_matches!(
2330
+ wf_task.jobs.as_slice(),
2331
+ [WorkflowActivationJob {
2332
+ variant: Some(workflow_activation_job::Variant::RemoveFromCache(_)),
2333
+ },]
2334
+ );
2335
+
2336
+ core.shutdown().await;
2337
+ }
2338
+
2339
+ #[tokio::test]
2340
+ async fn lang_internal_flags() {
2341
+ let mut t = TestHistoryBuilder::default();
2342
+ t.add_by_type(EventType::WorkflowExecutionStarted);
2343
+ t.add_full_wf_task();
2344
+ t.set_flags_first_wft(&[], &[1]);
2345
+ t.add_we_signaled("sig1", vec![]);
2346
+ t.add_full_wf_task();
2347
+ t.set_flags_last_wft(&[], &[2]);
2348
+ t.add_we_signaled("sig2", vec![]);
2349
+ t.add_full_wf_task();
2350
+ t.add_workflow_execution_completed();
2351
+
2352
+ let mut mh = MockPollCfg::from_resp_batches(
2353
+ "fake_wf_id",
2354
+ t,
2355
+ [ResponseType::ToTaskNum(2), ResponseType::AllHistory],
2356
+ mock_workflow_client(),
2357
+ );
2358
+ mh.completion_asserts = Some(Box::new(|c| {
2359
+ assert_matches!(c.sdk_metadata.lang_used_flags.as_slice(), &[2]);
2360
+ }));
2361
+ let mut mock = build_mock_pollers(mh);
2362
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 1);
2363
+ let core = mock_worker(mock);
2364
+
2365
+ let act = core.poll_workflow_activation().await.unwrap();
2366
+ assert_matches!(act.available_internal_flags.as_slice(), [1]);
2367
+ core.complete_workflow_activation(WorkflowActivationCompletion::empty(act.run_id))
2368
+ .await
2369
+ .unwrap();
2370
+
2371
+ let act = core.poll_workflow_activation().await.unwrap();
2372
+ let mut completion = WorkflowActivationCompletion::empty(act.run_id);
2373
+ completion.add_internal_flags(2);
2374
+ core.complete_workflow_activation(completion).await.unwrap();
2375
+
2376
+ let act = core.poll_workflow_activation().await.unwrap();
2377
+ assert_matches!(act.available_internal_flags.as_slice(), [1, 2]);
2378
+ core.complete_execution(&act.run_id).await;
2379
+ core.shutdown().await;
2380
+ }
2381
+
2382
+ // Verify we send flags to server when they're used
2383
+ #[tokio::test]
2384
+ async fn core_internal_flags() {
2385
+ let mut t = TestHistoryBuilder::default();
2386
+ t.add_by_type(EventType::WorkflowExecutionStarted);
2387
+ t.add_full_wf_task();
2388
+ let act_scheduled_event_id = t.add_activity_task_scheduled("act-id");
2389
+ let act_started_event_id = t.add_activity_task_started(act_scheduled_event_id);
2390
+ t.add_activity_task_completed(
2391
+ act_scheduled_event_id,
2392
+ act_started_event_id,
2393
+ Default::default(),
2394
+ );
2395
+ t.add_full_wf_task();
2396
+ t.add_workflow_execution_completed();
2397
+
2398
+ let mut mh = MockPollCfg::from_resp_batches(
2399
+ "fake_wf_id",
2400
+ t,
2401
+ [ResponseType::ToTaskNum(1), ResponseType::ToTaskNum(2)],
2402
+ mock_workflow_client(),
2403
+ );
2404
+ let first_poll = AtomicBool::new(true);
2405
+ mh.completion_asserts = Some(Box::new(move |c| {
2406
+ if !first_poll.load(Ordering::Acquire) {
2407
+ assert_matches!(c.sdk_metadata.core_used_flags.as_slice(), &[1]);
2408
+ }
2409
+ first_poll.store(false, Ordering::Release);
2410
+ }));
2411
+ let mut mock = build_mock_pollers(mh);
2412
+ mock.worker_cfg(|wc| wc.max_cached_workflows = 1);
2413
+ let core = mock_worker(mock);
2414
+
2415
+ let act = core.poll_workflow_activation().await.unwrap();
2416
+ core.complete_workflow_activation(WorkflowActivationCompletion::from_cmd(
2417
+ act.run_id,
2418
+ schedule_activity_cmd(
2419
+ 1,
2420
+ "whatever",
2421
+ "act-id",
2422
+ ActivityCancellationType::TryCancel,
2423
+ Duration::from_secs(60),
2424
+ Duration::from_secs(60),
2425
+ ),
2426
+ ))
2427
+ .await
2428
+ .unwrap();
2429
+
2430
+ let act = core.poll_workflow_activation().await.unwrap();
2431
+ core.complete_execution(&act.run_id).await;
2432
+ core.shutdown().await;
2433
+ }