temporalio 0.0.2 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (320) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +25 -23
  3. data/bridge/Cargo.lock +185 -76
  4. data/bridge/Cargo.toml +6 -4
  5. data/bridge/sdk-core/README.md +19 -6
  6. data/bridge/sdk-core/client/src/lib.rs +215 -39
  7. data/bridge/sdk-core/client/src/metrics.rs +17 -8
  8. data/bridge/sdk-core/client/src/raw.rs +4 -4
  9. data/bridge/sdk-core/client/src/retry.rs +32 -20
  10. data/bridge/sdk-core/core/Cargo.toml +22 -9
  11. data/bridge/sdk-core/core/src/abstractions.rs +203 -14
  12. data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +76 -41
  13. data/bridge/sdk-core/core/src/core_tests/determinism.rs +165 -2
  14. data/bridge/sdk-core/core/src/core_tests/local_activities.rs +204 -83
  15. data/bridge/sdk-core/core/src/core_tests/queries.rs +3 -4
  16. data/bridge/sdk-core/core/src/core_tests/workers.rs +1 -3
  17. data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +397 -54
  18. data/bridge/sdk-core/core/src/ephemeral_server/mod.rs +106 -12
  19. data/bridge/sdk-core/core/src/internal_flags.rs +136 -0
  20. data/bridge/sdk-core/core/src/lib.rs +16 -9
  21. data/bridge/sdk-core/core/src/telemetry/log_export.rs +1 -1
  22. data/bridge/sdk-core/core/src/telemetry/metrics.rs +69 -35
  23. data/bridge/sdk-core/core/src/telemetry/mod.rs +29 -13
  24. data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +17 -12
  25. data/bridge/sdk-core/core/src/test_help/mod.rs +62 -12
  26. data/bridge/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +112 -156
  27. data/bridge/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
  28. data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +352 -122
  29. data/bridge/sdk-core/core/src/worker/activities.rs +233 -157
  30. data/bridge/sdk-core/core/src/worker/client/mocks.rs +22 -2
  31. data/bridge/sdk-core/core/src/worker/client.rs +18 -2
  32. data/bridge/sdk-core/core/src/worker/mod.rs +165 -58
  33. data/bridge/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
  34. data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -5
  35. data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +856 -277
  36. data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +100 -43
  37. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +7 -7
  38. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +5 -4
  39. data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +87 -27
  40. data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +5 -4
  41. data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +5 -4
  42. data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +5 -4
  43. data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +137 -62
  44. data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +25 -17
  45. data/bridge/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +7 -6
  46. data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +103 -152
  47. data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +7 -7
  48. data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +9 -9
  49. data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
  50. data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +14 -7
  51. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +5 -16
  52. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +201 -121
  53. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +11 -14
  54. data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +30 -15
  55. data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +1026 -376
  56. data/bridge/sdk-core/core/src/worker/workflow/mod.rs +460 -384
  57. data/bridge/sdk-core/core/src/worker/workflow/run_cache.rs +40 -57
  58. data/bridge/sdk-core/core/src/worker/workflow/wft_extraction.rs +125 -0
  59. data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +1 -4
  60. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +117 -0
  61. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
  62. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +448 -718
  63. data/bridge/sdk-core/core-api/Cargo.toml +2 -1
  64. data/bridge/sdk-core/core-api/src/errors.rs +1 -34
  65. data/bridge/sdk-core/core-api/src/lib.rs +6 -2
  66. data/bridge/sdk-core/core-api/src/telemetry.rs +0 -6
  67. data/bridge/sdk-core/core-api/src/worker.rs +14 -1
  68. data/bridge/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +18 -15
  69. data/bridge/sdk-core/fsm/rustfsm_trait/src/lib.rs +8 -3
  70. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
  71. data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +5 -17
  72. data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +11 -0
  73. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +1 -6
  74. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +6 -6
  75. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +5 -0
  76. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +22 -6
  77. data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +48 -19
  78. data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +2 -0
  79. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +3 -0
  80. data/bridge/sdk-core/protos/api_upstream/temporal/api/{enums/v1/interaction_type.proto → protocol/v1/message.proto} +29 -11
  81. data/bridge/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
  82. data/bridge/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +111 -0
  83. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +59 -28
  84. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +2 -2
  85. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +1 -0
  86. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +1 -0
  87. data/bridge/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +1 -0
  88. data/bridge/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
  89. data/bridge/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
  90. data/bridge/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +1 -0
  91. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +7 -0
  92. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +1 -0
  93. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +6 -0
  94. data/bridge/sdk-core/sdk/Cargo.toml +3 -2
  95. data/bridge/sdk-core/sdk/src/lib.rs +87 -20
  96. data/bridge/sdk-core/sdk/src/workflow_future.rs +9 -8
  97. data/bridge/sdk-core/sdk-core-protos/Cargo.toml +5 -2
  98. data/bridge/sdk-core/sdk-core-protos/build.rs +36 -1
  99. data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +100 -87
  100. data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +5 -1
  101. data/bridge/sdk-core/sdk-core-protos/src/lib.rs +175 -57
  102. data/bridge/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
  103. data/bridge/sdk-core/test-utils/Cargo.toml +3 -1
  104. data/bridge/sdk-core/test-utils/src/canned_histories.rs +106 -296
  105. data/bridge/sdk-core/test-utils/src/histfetch.rs +1 -1
  106. data/bridge/sdk-core/test-utils/src/lib.rs +82 -23
  107. data/bridge/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
  108. data/bridge/sdk-core/test-utils/src/workflows.rs +29 -0
  109. data/bridge/sdk-core/tests/fuzzy_workflow.rs +130 -0
  110. data/bridge/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +125 -51
  111. data/bridge/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
  112. data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +5 -3
  113. data/bridge/sdk-core/tests/integ_tests/metrics_tests.rs +218 -16
  114. data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +4 -47
  115. data/bridge/sdk-core/tests/integ_tests/queries_tests.rs +5 -128
  116. data/bridge/sdk-core/tests/integ_tests/visibility_tests.rs +83 -25
  117. data/bridge/sdk-core/tests/integ_tests/workflow_tests/activities.rs +93 -69
  118. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
  119. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +6 -13
  120. data/bridge/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +1 -0
  121. data/bridge/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +6 -2
  122. data/bridge/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -10
  123. data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +72 -191
  124. data/bridge/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +1 -0
  125. data/bridge/sdk-core/tests/integ_tests/workflow_tests/patches.rs +7 -28
  126. data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +12 -7
  127. data/bridge/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
  128. data/bridge/sdk-core/tests/integ_tests/workflow_tests/signals.rs +18 -14
  129. data/bridge/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +6 -20
  130. data/bridge/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -21
  131. data/bridge/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +6 -4
  132. data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +10 -11
  133. data/bridge/sdk-core/tests/main.rs +3 -13
  134. data/bridge/sdk-core/tests/runner.rs +75 -36
  135. data/bridge/sdk-core/tests/wf_input_replay.rs +32 -0
  136. data/bridge/src/connection.rs +41 -25
  137. data/bridge/src/lib.rs +269 -14
  138. data/bridge/src/runtime.rs +1 -1
  139. data/bridge/src/test_server.rs +153 -0
  140. data/bridge/src/worker.rs +89 -16
  141. data/lib/gen/temporal/api/command/v1/message_pb.rb +4 -18
  142. data/lib/gen/temporal/api/common/v1/message_pb.rb +4 -0
  143. data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +1 -3
  144. data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +3 -3
  145. data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +2 -0
  146. data/lib/gen/temporal/api/enums/v1/update_pb.rb +6 -4
  147. data/lib/gen/temporal/api/history/v1/message_pb.rb +27 -19
  148. data/lib/gen/temporal/api/namespace/v1/message_pb.rb +1 -0
  149. data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +3 -0
  150. data/lib/gen/temporal/api/protocol/v1/message_pb.rb +30 -0
  151. data/lib/gen/temporal/api/sdk/v1/task_complete_metadata_pb.rb +23 -0
  152. data/lib/gen/temporal/api/testservice/v1/request_response_pb.rb +49 -0
  153. data/lib/gen/temporal/api/testservice/v1/service_pb.rb +21 -0
  154. data/lib/gen/temporal/api/update/v1/message_pb.rb +72 -0
  155. data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +26 -16
  156. data/lib/gen/temporal/sdk/core/activity_result/activity_result_pb.rb +13 -9
  157. data/lib/gen/temporal/sdk/core/activity_task/activity_task_pb.rb +10 -6
  158. data/lib/gen/temporal/sdk/core/child_workflow/child_workflow_pb.rb +13 -9
  159. data/lib/gen/temporal/sdk/core/common/common_pb.rb +7 -3
  160. data/lib/gen/temporal/sdk/core/core_interface_pb.rb +9 -3
  161. data/lib/gen/temporal/sdk/core/external_data/external_data_pb.rb +7 -3
  162. data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +27 -21
  163. data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +28 -24
  164. data/lib/gen/temporal/sdk/core/workflow_completion/workflow_completion_pb.rb +12 -5
  165. data/lib/temporalio/activity/context.rb +13 -8
  166. data/lib/temporalio/activity/info.rb +1 -1
  167. data/lib/temporalio/bridge/connect_options.rb +15 -0
  168. data/lib/temporalio/bridge/retry_config.rb +24 -0
  169. data/lib/temporalio/bridge/tls_options.rb +19 -0
  170. data/lib/temporalio/bridge.rb +1 -1
  171. data/lib/temporalio/client/implementation.rb +8 -8
  172. data/lib/temporalio/connection/retry_config.rb +44 -0
  173. data/lib/temporalio/connection/service.rb +20 -0
  174. data/lib/temporalio/connection/test_service.rb +92 -0
  175. data/lib/temporalio/connection/tls_options.rb +51 -0
  176. data/lib/temporalio/connection/workflow_service.rb +731 -0
  177. data/lib/temporalio/connection.rb +55 -720
  178. data/lib/temporalio/interceptor/activity_inbound.rb +22 -0
  179. data/lib/temporalio/interceptor/activity_outbound.rb +24 -0
  180. data/lib/temporalio/interceptor/chain.rb +5 -5
  181. data/lib/temporalio/interceptor/client.rb +8 -4
  182. data/lib/temporalio/interceptor.rb +22 -0
  183. data/lib/temporalio/retry_policy.rb +13 -3
  184. data/lib/temporalio/testing/time_skipping_handle.rb +32 -0
  185. data/lib/temporalio/testing/time_skipping_interceptor.rb +23 -0
  186. data/lib/temporalio/testing/workflow_environment.rb +112 -0
  187. data/lib/temporalio/testing.rb +175 -0
  188. data/lib/temporalio/version.rb +1 -1
  189. data/lib/temporalio/worker/activity_runner.rb +26 -4
  190. data/lib/temporalio/worker/activity_worker.rb +44 -18
  191. data/lib/temporalio/worker/sync_worker.rb +47 -11
  192. data/lib/temporalio/worker.rb +27 -21
  193. data/lib/temporalio/workflow/async.rb +46 -0
  194. data/lib/temporalio/workflow/future.rb +138 -0
  195. data/lib/temporalio/workflow/info.rb +76 -0
  196. data/lib/thermite_patch.rb +10 -0
  197. data/sig/async.rbs +17 -0
  198. data/sig/protobuf.rbs +16 -0
  199. data/sig/protos/dependencies/gogoproto/gogo.rbs +914 -0
  200. data/sig/protos/google/protobuf/any.rbs +157 -0
  201. data/sig/protos/google/protobuf/descriptor.rbs +2825 -0
  202. data/sig/protos/google/protobuf/duration.rbs +114 -0
  203. data/sig/protos/google/protobuf/empty.rbs +36 -0
  204. data/sig/protos/google/protobuf/timestamp.rbs +145 -0
  205. data/sig/protos/google/protobuf/wrappers.rbs +358 -0
  206. data/sig/protos/temporal/api/batch/v1/message.rbs +300 -0
  207. data/sig/protos/temporal/api/command/v1/message.rbs +1399 -0
  208. data/sig/protos/temporal/api/common/v1/message.rbs +528 -0
  209. data/sig/protos/temporal/api/enums/v1/batch_operation.rbs +79 -0
  210. data/sig/protos/temporal/api/enums/v1/command_type.rbs +68 -0
  211. data/sig/protos/temporal/api/enums/v1/common.rbs +118 -0
  212. data/sig/protos/temporal/api/enums/v1/event_type.rbs +264 -0
  213. data/sig/protos/temporal/api/enums/v1/failed_cause.rbs +277 -0
  214. data/sig/protos/temporal/api/enums/v1/namespace.rbs +108 -0
  215. data/sig/protos/temporal/api/enums/v1/query.rbs +81 -0
  216. data/sig/protos/temporal/api/enums/v1/reset.rbs +44 -0
  217. data/sig/protos/temporal/api/enums/v1/schedule.rbs +72 -0
  218. data/sig/protos/temporal/api/enums/v1/task_queue.rbs +92 -0
  219. data/sig/protos/temporal/api/enums/v1/update.rbs +64 -0
  220. data/sig/protos/temporal/api/enums/v1/workflow.rbs +371 -0
  221. data/sig/protos/temporal/api/errordetails/v1/message.rbs +551 -0
  222. data/sig/protos/temporal/api/failure/v1/message.rbs +581 -0
  223. data/sig/protos/temporal/api/filter/v1/message.rbs +171 -0
  224. data/sig/protos/temporal/api/history/v1/message.rbs +4609 -0
  225. data/sig/protos/temporal/api/namespace/v1/message.rbs +410 -0
  226. data/sig/protos/temporal/api/operatorservice/v1/request_response.rbs +643 -0
  227. data/sig/protos/temporal/api/operatorservice/v1/service.rbs +17 -0
  228. data/sig/protos/temporal/api/protocol/v1/message.rbs +84 -0
  229. data/sig/protos/temporal/api/query/v1/message.rbs +182 -0
  230. data/sig/protos/temporal/api/replication/v1/message.rbs +148 -0
  231. data/sig/protos/temporal/api/schedule/v1/message.rbs +1488 -0
  232. data/sig/protos/temporal/api/sdk/v1/task_complete_metadata.rbs +110 -0
  233. data/sig/protos/temporal/api/taskqueue/v1/message.rbs +486 -0
  234. data/sig/protos/temporal/api/testservice/v1/request_response.rbs +249 -0
  235. data/sig/protos/temporal/api/testservice/v1/service.rbs +15 -0
  236. data/sig/protos/temporal/api/update/v1/message.rbs +489 -0
  237. data/sig/protos/temporal/api/version/v1/message.rbs +184 -0
  238. data/sig/protos/temporal/api/workflow/v1/message.rbs +824 -0
  239. data/sig/protos/temporal/api/workflowservice/v1/request_response.rbs +7250 -0
  240. data/sig/protos/temporal/api/workflowservice/v1/service.rbs +22 -0
  241. data/sig/protos/temporal/sdk/core/activity_result/activity_result.rbs +380 -0
  242. data/sig/protos/temporal/sdk/core/activity_task/activity_task.rbs +386 -0
  243. data/sig/protos/temporal/sdk/core/child_workflow/child_workflow.rbs +323 -0
  244. data/sig/protos/temporal/sdk/core/common/common.rbs +62 -0
  245. data/sig/protos/temporal/sdk/core/core_interface.rbs +101 -0
  246. data/sig/protos/temporal/sdk/core/external_data/external_data.rbs +119 -0
  247. data/sig/protos/temporal/sdk/core/workflow_activation/workflow_activation.rbs +1473 -0
  248. data/sig/protos/temporal/sdk/core/workflow_commands/workflow_commands.rbs +1784 -0
  249. data/sig/protos/temporal/sdk/core/workflow_completion/workflow_completion.rbs +180 -0
  250. data/sig/ruby.rbs +12 -0
  251. data/sig/temporalio/activity/context.rbs +29 -0
  252. data/sig/temporalio/activity/info.rbs +43 -0
  253. data/sig/temporalio/activity.rbs +19 -0
  254. data/sig/temporalio/bridge/connect_options.rbs +19 -0
  255. data/sig/temporalio/bridge/error.rbs +8 -0
  256. data/sig/temporalio/bridge/retry_config.rbs +21 -0
  257. data/sig/temporalio/bridge/tls_options.rbs +17 -0
  258. data/sig/temporalio/bridge.rbs +71 -0
  259. data/sig/temporalio/client/implementation.rbs +38 -0
  260. data/sig/temporalio/client/workflow_handle.rbs +41 -0
  261. data/sig/temporalio/client.rbs +35 -0
  262. data/sig/temporalio/connection/retry_config.rbs +37 -0
  263. data/sig/temporalio/connection/service.rbs +14 -0
  264. data/sig/temporalio/connection/test_service.rbs +13 -0
  265. data/sig/temporalio/connection/tls_options.rbs +43 -0
  266. data/sig/temporalio/connection/workflow_service.rbs +48 -0
  267. data/sig/temporalio/connection.rbs +30 -0
  268. data/sig/temporalio/data_converter.rbs +35 -0
  269. data/sig/temporalio/error/failure.rbs +121 -0
  270. data/sig/temporalio/error/workflow_failure.rbs +9 -0
  271. data/sig/temporalio/errors.rbs +36 -0
  272. data/sig/temporalio/failure_converter/base.rbs +12 -0
  273. data/sig/temporalio/failure_converter/basic.rbs +86 -0
  274. data/sig/temporalio/failure_converter.rbs +5 -0
  275. data/sig/temporalio/interceptor/activity_inbound.rbs +21 -0
  276. data/sig/temporalio/interceptor/activity_outbound.rbs +10 -0
  277. data/sig/temporalio/interceptor/chain.rbs +24 -0
  278. data/sig/temporalio/interceptor/client.rbs +148 -0
  279. data/sig/temporalio/interceptor.rbs +6 -0
  280. data/sig/temporalio/payload_codec/base.rbs +12 -0
  281. data/sig/temporalio/payload_converter/base.rbs +12 -0
  282. data/sig/temporalio/payload_converter/bytes.rbs +9 -0
  283. data/sig/temporalio/payload_converter/composite.rbs +19 -0
  284. data/sig/temporalio/payload_converter/encoding_base.rbs +14 -0
  285. data/sig/temporalio/payload_converter/json.rbs +9 -0
  286. data/sig/temporalio/payload_converter/nil.rbs +9 -0
  287. data/sig/temporalio/payload_converter.rbs +5 -0
  288. data/sig/temporalio/retry_policy.rbs +25 -0
  289. data/sig/temporalio/retry_state.rbs +20 -0
  290. data/sig/temporalio/runtime.rbs +12 -0
  291. data/sig/temporalio/testing/time_skipping_handle.rbs +15 -0
  292. data/sig/temporalio/testing/time_skipping_interceptor.rbs +13 -0
  293. data/sig/temporalio/testing/workflow_environment.rbs +22 -0
  294. data/sig/temporalio/testing.rbs +35 -0
  295. data/sig/temporalio/timeout_type.rbs +15 -0
  296. data/sig/temporalio/version.rbs +3 -0
  297. data/sig/temporalio/worker/activity_runner.rbs +35 -0
  298. data/sig/temporalio/worker/activity_worker.rbs +44 -0
  299. data/sig/temporalio/worker/reactor.rbs +22 -0
  300. data/sig/temporalio/worker/runner.rbs +21 -0
  301. data/sig/temporalio/worker/sync_worker.rbs +23 -0
  302. data/sig/temporalio/worker/thread_pool_executor.rbs +23 -0
  303. data/sig/temporalio/worker.rbs +46 -0
  304. data/sig/temporalio/workflow/async.rbs +9 -0
  305. data/sig/temporalio/workflow/execution_info.rbs +55 -0
  306. data/sig/temporalio/workflow/execution_status.rbs +21 -0
  307. data/sig/temporalio/workflow/future.rbs +40 -0
  308. data/sig/temporalio/workflow/id_reuse_policy.rbs +15 -0
  309. data/sig/temporalio/workflow/info.rbs +55 -0
  310. data/sig/temporalio/workflow/query_reject_condition.rbs +14 -0
  311. data/sig/temporalio.rbs +2 -0
  312. data/sig/thermite_patch.rbs +15 -0
  313. data/temporalio.gemspec +6 -4
  314. metadata +183 -17
  315. data/bridge/sdk-core/Cargo.lock +0 -2606
  316. data/bridge/sdk-core/protos/api_upstream/temporal/api/interaction/v1/message.proto +0 -87
  317. data/lib/bridge.so +0 -0
  318. data/lib/gen/temporal/api/enums/v1/interaction_type_pb.rb +0 -25
  319. data/lib/gen/temporal/api/interaction/v1/message_pb.rb +0 -49
  320. data/lib/gen/temporal/sdk/core/bridge/bridge_pb.rb +0 -222
@@ -23,6 +23,6 @@ async fn main() -> Result<(), anyhow::Error> {
23
23
  .expect("history field must be populated");
24
24
  // Serialize history to file
25
25
  let byteified = hist.encode_to_vec();
26
- tokio::fs::write(format!("{}_history.bin", wf_id), &byteified).await?;
26
+ tokio::fs::write(format!("{wf_id}_history.bin"), &byteified).await?;
27
27
  Ok(())
28
28
  }
@@ -5,8 +5,14 @@
5
5
  extern crate tracing;
6
6
 
7
7
  pub mod canned_histories;
8
+ pub mod wf_input_saver;
9
+ pub mod workflows;
8
10
 
9
- use crate::stream::{Stream, TryStreamExt};
11
+ use crate::{
12
+ stream::{Stream, TryStreamExt},
13
+ wf_input_saver::stream_to_file,
14
+ };
15
+ use base64::{prelude::BASE64_STANDARD, Engine};
10
16
  use futures::{future, stream, stream::FuturesUnordered, StreamExt};
11
17
  use parking_lot::Mutex;
12
18
  use prost::Message;
@@ -28,6 +34,7 @@ use temporal_sdk_core::{
28
34
  replay::HistoryForReplay,
29
35
  ClientOptions, ClientOptionsBuilder, CoreRuntime, WorkerConfig, WorkerConfigBuilder,
30
36
  };
37
+ use temporal_sdk_core_api::errors::{PollActivityError, PollWfError};
31
38
  use temporal_sdk_core_api::{
32
39
  telemetry::{
33
40
  Logger, MetricsExporter, OtelCollectorOptions, TelemetryOptions, TelemetryOptionsBuilder,
@@ -44,16 +51,17 @@ use temporal_sdk_core_protos::{
44
51
  workflow_completion::WorkflowActivationCompletion,
45
52
  },
46
53
  temporal::api::{common::v1::Payload, history::v1::History},
54
+ DEFAULT_ACTIVITY_TYPE,
47
55
  };
48
- use tokio::sync::OnceCell;
56
+ use tokio::sync::{mpsc::unbounded_channel, OnceCell};
49
57
  use url::Url;
50
58
 
51
59
  pub const NAMESPACE: &str = "default";
52
60
  pub const TEST_Q: &str = "q";
53
61
  /// The env var used to specify where the integ tests should point
54
62
  pub const INTEG_SERVER_TARGET_ENV_VAR: &str = "TEMPORAL_SERVICE_ADDRESS";
55
- /// This env var is set (to any value) if temporalite is in use
56
- pub const INTEG_TEMPORALITE_USED_ENV_VAR: &str = "INTEG_TEMPORALITE_ON";
63
+ /// This env var is set (to any value) if temporal CLI dev server is in use
64
+ pub const INTEG_TEMPORAL_DEV_SERVER_USED_ENV_VAR: &str = "INTEG_TEMPORAL_DEV_SERVER_ON";
57
65
  /// This env var is set (to any value) if the test server is in use
58
66
  pub const INTEG_TEST_SERVER_USED_ENV_VAR: &str = "INTEG_TEST_SERVER_ON";
59
67
 
@@ -61,6 +69,15 @@ pub const INTEG_TEST_SERVER_USED_ENV_VAR: &str = "INTEG_TEST_SERVER_ON";
61
69
  const OTEL_URL_ENV_VAR: &str = "TEMPORAL_INTEG_OTEL_URL";
62
70
  /// If set, enable direct scraping of prom metrics on the specified port
63
71
  const PROM_ENABLE_ENV_VAR: &str = "TEMPORAL_INTEG_PROM_PORT";
72
+ #[macro_export]
73
+ macro_rules! prost_dur {
74
+ ($dur_call:ident $args:tt) => {
75
+ std::time::Duration::$dur_call$args
76
+ .try_into()
77
+ .expect("test duration fits")
78
+ };
79
+ }
80
+
64
81
  /// Create a worker instance which will use the provided test name to base the task queue and wf id
65
82
  /// upon. Returns the instance and the task queue name (which is also the workflow id).
66
83
  pub async fn init_core_and_create_wf(test_name: &str) -> CoreWfStarter {
@@ -82,6 +99,7 @@ pub fn init_core_replay_stream<I>(test_name: &str, histories: I) -> Arc<dyn Core
82
99
  where
83
100
  I: Stream<Item = HistoryForReplay> + Send + 'static,
84
101
  {
102
+ init_integ_telem();
85
103
  let worker_cfg = WorkerConfigBuilder::default()
86
104
  .namespace(NAMESPACE)
87
105
  .task_queue(test_name)
@@ -134,7 +152,8 @@ pub struct CoreWfStarter {
134
152
  /// Used for both the task queue and workflow id
135
153
  task_queue_name: String,
136
154
  pub worker_config: WorkerConfig,
137
- wft_timeout: Option<Duration>,
155
+ /// Options to use when starting workflow(s)
156
+ pub workflow_options: WorkflowOptions,
138
157
  initted_worker: OnceCell<InitializedWorker>,
139
158
  }
140
159
  struct InitializedWorker {
@@ -144,14 +163,10 @@ struct InitializedWorker {
144
163
 
145
164
  impl CoreWfStarter {
146
165
  pub fn new(test_name: &str) -> Self {
147
- let rand_bytes: Vec<u8> = rand::thread_rng().sample_iter(&Standard).take(6).collect();
148
- let task_q_salt = base64::encode(rand_bytes);
149
- let task_queue = format!("{}_{}", test_name, task_q_salt);
150
- Self::new_tq_name(&task_queue)
151
- }
152
-
153
- pub fn new_tq_name(task_queue: &str) -> Self {
154
166
  init_integ_telem();
167
+ let rand_bytes: Vec<u8> = rand::thread_rng().sample_iter(&Standard).take(6).collect();
168
+ let task_q_salt = BASE64_STANDARD.encode(rand_bytes);
169
+ let task_queue = format!("{test_name}_{task_q_salt}");
155
170
  Self {
156
171
  task_queue_name: task_queue.to_owned(),
157
172
  worker_config: WorkerConfigBuilder::default()
@@ -161,8 +176,8 @@ impl CoreWfStarter {
161
176
  .max_cached_workflows(1000_usize)
162
177
  .build()
163
178
  .unwrap(),
164
- wft_timeout: None,
165
179
  initted_worker: OnceCell::new(),
180
+ workflow_options: Default::default(),
166
181
  }
167
182
  }
168
183
 
@@ -189,13 +204,27 @@ impl CoreWfStarter {
189
204
  }
190
205
 
191
206
  /// Start the workflow defined by the builder and return run id
192
- pub async fn start_wf(&self) -> String {
193
- self.start_wf_with_id(self.task_queue_name.clone(), WorkflowOptions::default())
207
+ pub async fn start_wf(&mut self) -> String {
208
+ self.start_wf_with_id(self.task_queue_name.clone()).await
209
+ }
210
+
211
+ pub async fn start_with_worker(
212
+ &self,
213
+ wf_name: impl Into<String>,
214
+ worker: &mut TestWorker,
215
+ ) -> String {
216
+ worker
217
+ .submit_wf(
218
+ self.task_queue_name.clone(),
219
+ wf_name.into(),
220
+ vec![],
221
+ self.workflow_options.clone(),
222
+ )
194
223
  .await
224
+ .unwrap()
195
225
  }
196
226
 
197
- pub async fn start_wf_with_id(&self, workflow_id: String, mut opts: WorkflowOptions) -> String {
198
- opts.task_timeout = opts.task_timeout.or(self.wft_timeout);
227
+ pub async fn start_wf_with_id(&self, workflow_id: String) -> String {
199
228
  self.initted_worker
200
229
  .get()
201
230
  .expect(
@@ -209,7 +238,7 @@ impl CoreWfStarter {
209
238
  workflow_id,
210
239
  self.task_queue_name.clone(),
211
240
  None,
212
- opts,
241
+ self.workflow_options.clone(),
213
242
  )
214
243
  .await
215
244
  .unwrap()
@@ -274,8 +303,18 @@ impl CoreWfStarter {
274
303
  self
275
304
  }
276
305
 
277
- pub fn wft_timeout(&mut self, timeout: Duration) -> &mut Self {
278
- self.wft_timeout = Some(timeout);
306
+ pub fn no_remote_activities(&mut self) -> &mut Self {
307
+ self.worker_config.no_remote_activities = true;
308
+ self
309
+ }
310
+
311
+ pub fn enable_wf_state_input_recording(&mut self) -> &mut Self {
312
+ let (ser_tx, ser_rx) = unbounded_channel();
313
+ let worker_cfg_clone = self.worker_config.clone();
314
+ tokio::spawn(async move {
315
+ stream_to_file(&worker_cfg_clone, ser_rx).await.unwrap();
316
+ });
317
+ self.worker_config.wf_state_inputs = Some(ser_tx);
279
318
  self
280
319
  }
281
320
 
@@ -537,7 +576,7 @@ pub fn get_integ_telem_options() -> TelemetryOptions {
537
576
 
538
577
  pub fn default_cached_download() -> EphemeralExe {
539
578
  EphemeralExe::CachedDownload {
540
- version: EphemeralExeVersion::Default {
579
+ version: EphemeralExeVersion::SDKDefault {
541
580
  sdk_name: "sdk-rust".to_string(),
542
581
  sdk_version: "0.1.0".to_string(),
543
582
  },
@@ -556,7 +595,7 @@ pub fn schedule_activity_cmd(
556
595
  ScheduleActivity {
557
596
  seq,
558
597
  activity_id: activity_id.to_string(),
559
- activity_type: "test_activity".to_string(),
598
+ activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
560
599
  task_queue: task_q.to_owned(),
561
600
  schedule_to_start_timeout: Some(activity_timeout.try_into().expect("duration fits")),
562
601
  start_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
@@ -577,7 +616,7 @@ pub fn schedule_local_activity_cmd(
577
616
  ScheduleLocalActivity {
578
617
  seq,
579
618
  activity_id: activity_id.to_string(),
580
- activity_type: "test_activity".to_string(),
619
+ activity_type: DEFAULT_ACTIVITY_TYPE.to_string(),
581
620
  schedule_to_start_timeout: Some(activity_timeout.try_into().expect("duration fits")),
582
621
  start_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
583
622
  schedule_to_close_timeout: Some(activity_timeout.try_into().expect("duration fits")),
@@ -648,3 +687,23 @@ where
648
687
  .unwrap();
649
688
  }
650
689
  }
690
+
691
+ /// Initiate shutdown, drain the pollers, and wait for shutdown to complete.
692
+ pub async fn drain_pollers_and_shutdown(worker: &Arc<dyn CoreWorker>) {
693
+ worker.initiate_shutdown();
694
+ tokio::join!(
695
+ async {
696
+ assert!(matches!(
697
+ worker.poll_activity_task().await.unwrap_err(),
698
+ PollActivityError::ShutDown
699
+ ));
700
+ },
701
+ async {
702
+ assert!(matches!(
703
+ worker.poll_workflow_activation().await.unwrap_err(),
704
+ PollWfError::ShutDown,
705
+ ));
706
+ }
707
+ );
708
+ worker.shutdown().await;
709
+ }
@@ -0,0 +1,50 @@
1
+ use anyhow::anyhow;
2
+ use bytes::BytesMut;
3
+ use futures::{stream::BoxStream, SinkExt, StreamExt};
4
+ use prost::bytes::Bytes;
5
+ use std::path::Path;
6
+ use temporal_sdk_core_api::worker::WorkerConfig;
7
+ use tokio::{fs::File, sync::mpsc::UnboundedReceiver};
8
+ use tokio_util::codec::{FramedRead, FramedWrite, LengthDelimitedCodec};
9
+
10
+ pub struct WFStateReplayData {
11
+ pub config: WorkerConfig,
12
+ pub inputs: BoxStream<'static, Result<BytesMut, std::io::Error>>,
13
+ }
14
+
15
+ pub async fn stream_to_file(
16
+ config: &WorkerConfig,
17
+ mut rcv: UnboundedReceiver<Vec<u8>>,
18
+ ) -> Result<(), anyhow::Error> {
19
+ let file = File::create("wf_inputs").await?;
20
+ let mut transport = FramedWrite::new(file, ldc());
21
+ // First write the worker config, since things like cache size affect how many evictions there
22
+ // will be, etc.
23
+ transport.send(rmp_serde::to_vec(config)?.into()).await?;
24
+ while let Some(v) = rcv.recv().await {
25
+ transport.send(Bytes::from(v)).await?;
26
+ }
27
+ Ok(())
28
+ }
29
+
30
+ pub async fn read_from_file(path: impl AsRef<Path>) -> Result<WFStateReplayData, anyhow::Error> {
31
+ let file = File::open(path).await?;
32
+ let mut framed_read = FramedRead::new(file, ldc());
33
+ // Deserialize the worker config first
34
+ let config = framed_read
35
+ .next()
36
+ .await
37
+ .ok_or_else(|| anyhow!("Replay data file is empty"))??;
38
+ let config = rmp_serde::from_slice(config.as_ref())?;
39
+
40
+ Ok(WFStateReplayData {
41
+ config,
42
+ inputs: framed_read.boxed(),
43
+ })
44
+ }
45
+
46
+ fn ldc() -> LengthDelimitedCodec {
47
+ LengthDelimitedCodec::builder()
48
+ .length_field_type::<u16>()
49
+ .new_codec()
50
+ }
@@ -0,0 +1,29 @@
1
+ use crate::prost_dur;
2
+ use std::time::Duration;
3
+ use temporal_sdk::{ActivityOptions, LocalActivityOptions, WfContext, WorkflowResult};
4
+ use temporal_sdk_core_protos::{coresdk::AsJsonPayloadExt, temporal::api::common::v1::RetryPolicy};
5
+
6
+ pub async fn la_problem_workflow(ctx: WfContext) -> WorkflowResult<()> {
7
+ ctx.local_activity(LocalActivityOptions {
8
+ activity_type: "delay".to_string(),
9
+ input: "hi".as_json_payload().expect("serializes fine"),
10
+ retry_policy: RetryPolicy {
11
+ initial_interval: Some(prost_dur!(from_micros(15))),
12
+ backoff_coefficient: 1_000.,
13
+ maximum_interval: Some(prost_dur!(from_millis(1500))),
14
+ maximum_attempts: 4,
15
+ non_retryable_error_types: vec![],
16
+ },
17
+ timer_backoff_threshold: Some(Duration::from_secs(1)),
18
+ ..Default::default()
19
+ })
20
+ .await;
21
+ ctx.activity(ActivityOptions {
22
+ activity_type: "delay".to_string(),
23
+ start_to_close_timeout: Some(Duration::from_secs(20)),
24
+ input: "hi!".as_json_payload().expect("serializes fine"),
25
+ ..Default::default()
26
+ })
27
+ .await;
28
+ Ok(().into())
29
+ }
@@ -0,0 +1,130 @@
1
+ use futures_util::{sink, stream::FuturesUnordered, FutureExt, StreamExt};
2
+ use rand::{prelude::Distribution, rngs::SmallRng, Rng, SeedableRng};
3
+ use std::{future, time::Duration};
4
+ use temporal_client::{WfClientExt, WorkflowClientTrait, WorkflowOptions};
5
+ use temporal_sdk::{ActContext, ActivityOptions, LocalActivityOptions, WfContext, WorkflowResult};
6
+ use temporal_sdk_core_protos::coresdk::{AsJsonPayloadExt, FromJsonPayloadExt, IntoPayloadsExt};
7
+ use temporal_sdk_core_test_utils::CoreWfStarter;
8
+ use tokio_util::sync::CancellationToken;
9
+
10
+ const FUZZY_SIG: &str = "fuzzy_sig";
11
+
12
+ #[derive(serde::Serialize, serde::Deserialize, Copy, Clone)]
13
+ enum FuzzyWfAction {
14
+ Shutdown,
15
+ DoAct,
16
+ DoLocalAct,
17
+ }
18
+
19
+ struct FuzzyWfActionSampler;
20
+ impl Distribution<FuzzyWfAction> for FuzzyWfActionSampler {
21
+ fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> FuzzyWfAction {
22
+ let v: u8 = rng.gen_range(1..=2);
23
+ match v {
24
+ 1 => FuzzyWfAction::DoAct,
25
+ 2 => FuzzyWfAction::DoLocalAct,
26
+ _ => unreachable!(),
27
+ }
28
+ }
29
+ }
30
+
31
+ async fn echo(_ctx: ActContext, echo_me: String) -> Result<String, anyhow::Error> {
32
+ Ok(echo_me)
33
+ }
34
+
35
+ async fn fuzzy_wf_def(ctx: WfContext) -> WorkflowResult<()> {
36
+ let sigchan = ctx
37
+ .make_signal_channel(FUZZY_SIG)
38
+ .map(|sd| FuzzyWfAction::from_json_payload(&sd.input[0]).expect("Can deserialize signal"));
39
+ let done = CancellationToken::new();
40
+ let done_setter = done.clone();
41
+
42
+ sigchan
43
+ .take_until(done.cancelled())
44
+ .for_each_concurrent(None, |action| {
45
+ let fut = match action {
46
+ FuzzyWfAction::DoAct => ctx
47
+ .activity(ActivityOptions {
48
+ activity_type: "echo_activity".to_string(),
49
+ start_to_close_timeout: Some(Duration::from_secs(5)),
50
+ input: "hi!".as_json_payload().expect("serializes fine"),
51
+ ..Default::default()
52
+ })
53
+ .map(|_| ())
54
+ .boxed(),
55
+ FuzzyWfAction::DoLocalAct => ctx
56
+ .local_activity(LocalActivityOptions {
57
+ activity_type: "echo_activity".to_string(),
58
+ start_to_close_timeout: Some(Duration::from_secs(5)),
59
+ input: "hi!".as_json_payload().expect("serializes fine"),
60
+ ..Default::default()
61
+ })
62
+ .map(|_| ())
63
+ .boxed(),
64
+ FuzzyWfAction::Shutdown => {
65
+ done_setter.cancel();
66
+ future::ready(()).boxed()
67
+ }
68
+ };
69
+ fut
70
+ })
71
+ .await;
72
+
73
+ Ok(().into())
74
+ }
75
+
76
+ #[tokio::test(flavor = "multi_thread", worker_threads = 4)]
77
+ async fn fuzzy_workflow() {
78
+ let num_workflows = 200;
79
+ let wf_name = "fuzzy_wf";
80
+ let mut starter = CoreWfStarter::new("fuzzy_workflow");
81
+ starter.max_wft(25).max_cached_workflows(25).max_at(25);
82
+ // .enable_wf_state_input_recording();
83
+ let mut worker = starter.worker().await;
84
+ worker.register_wf(wf_name.to_owned(), fuzzy_wf_def);
85
+ worker.register_activity("echo_activity", echo);
86
+ let client = starter.get_client().await;
87
+
88
+ let mut workflow_handles = vec![];
89
+ for i in 0..num_workflows {
90
+ let wfid = format!("{wf_name}_{i}");
91
+ let rid = worker
92
+ .submit_wf(
93
+ wfid.clone(),
94
+ wf_name.to_owned(),
95
+ vec![],
96
+ WorkflowOptions::default(),
97
+ )
98
+ .await
99
+ .unwrap();
100
+ workflow_handles.push(client.get_untyped_workflow_handle(wfid, rid));
101
+ }
102
+
103
+ let rng = SmallRng::seed_from_u64(523189);
104
+ let mut actions: Vec<FuzzyWfAction> = rng.sample_iter(FuzzyWfActionSampler).take(15).collect();
105
+ actions.push(FuzzyWfAction::Shutdown);
106
+
107
+ let sig_sender = async {
108
+ for action in actions {
109
+ let sends: FuturesUnordered<_> = (0..num_workflows)
110
+ .map(|i| {
111
+ client.signal_workflow_execution(
112
+ format!("{wf_name}_{i}"),
113
+ "".to_string(),
114
+ FUZZY_SIG.to_string(),
115
+ [action.as_json_payload().expect("Serializes ok")].into_payloads(),
116
+ None,
117
+ )
118
+ })
119
+ .collect();
120
+ sends
121
+ .map(|_| Ok(()))
122
+ .forward(sink::drain())
123
+ .await
124
+ .expect("Sending signals works");
125
+ tokio::time::sleep(Duration::from_secs(1)).await;
126
+ }
127
+ };
128
+ let (r1, _) = tokio::join!(worker.run_until_done(), sig_sender);
129
+ r1.unwrap();
130
+ }
@@ -1,17 +1,17 @@
1
- use assert_matches::assert_matches;
2
1
  use futures::{future::join_all, sink, stream::FuturesUnordered, StreamExt};
3
2
  use std::time::{Duration, Instant};
4
3
  use temporal_client::{WfClientExt, WorkflowClientTrait, WorkflowOptions};
5
- use temporal_sdk::{ActContext, ActivityOptions, WfContext};
4
+ use temporal_sdk::{ActContext, ActivityOptions, WfContext, WorkflowResult};
6
5
  use temporal_sdk_core_protos::coresdk::{
7
- activity_result::ActivityExecutionResult, activity_task::activity_task as act_task,
8
- workflow_commands::ActivityCancellationType, ActivityTaskCompletion, AsJsonPayloadExt,
6
+ workflow_commands::ActivityCancellationType, AsJsonPayloadExt,
9
7
  };
10
- use temporal_sdk_core_test_utils::CoreWfStarter;
8
+ use temporal_sdk_core_test_utils::{workflows::la_problem_workflow, CoreWfStarter};
9
+
10
+ mod fuzzy_workflow;
11
11
 
12
12
  #[tokio::test]
13
13
  async fn activity_load() {
14
- const CONCURRENCY: usize = 1000;
14
+ const CONCURRENCY: usize = 512;
15
15
 
16
16
  let mut starter = CoreWfStarter::new("activity_load");
17
17
  starter
@@ -23,18 +23,16 @@ async fn activity_load() {
23
23
 
24
24
  let activity_id = "act-1";
25
25
  let activity_timeout = Duration::from_secs(8);
26
- let payload_dat = b"hello".to_vec();
27
26
  let task_queue = starter.get_task_queue().to_owned();
28
27
 
29
- let pd = payload_dat.clone();
30
28
  let wf_fn = move |ctx: WfContext| {
31
29
  let task_queue = task_queue.clone();
32
- let payload_dat = pd.clone();
33
-
30
+ let payload = "yo".as_json_payload().unwrap();
34
31
  async move {
35
32
  let activity = ActivityOptions {
36
33
  activity_id: Some(activity_id.to_string()),
37
34
  activity_type: "test_activity".to_string(),
35
+ input: payload.clone(),
38
36
  task_queue,
39
37
  schedule_to_start_timeout: Some(activity_timeout),
40
38
  start_to_close_timeout: Some(activity_timeout),
@@ -44,7 +42,7 @@ async fn activity_load() {
44
42
  ..Default::default()
45
43
  };
46
44
  let res = ctx.activity(activity).await.unwrap_ok_payload();
47
- assert_eq!(res.data, payload_dat);
45
+ assert_eq!(res.data, payload.data);
48
46
  Ok(().into())
49
47
  }
50
48
  };
@@ -52,9 +50,13 @@ async fn activity_load() {
52
50
  let starting = Instant::now();
53
51
  let wf_type = "activity_load";
54
52
  worker.register_wf(wf_type.to_owned(), wf_fn);
53
+ worker.register_activity(
54
+ "test_activity",
55
+ |_ctx: ActContext, echo: String| async move { Ok(echo) },
56
+ );
55
57
  join_all((0..CONCURRENCY).map(|i| {
56
58
  let worker = &worker;
57
- let wf_id = format!("activity_load_{}", i);
59
+ let wf_id = format!("activity_load_{i}");
58
60
  async move {
59
61
  worker
60
62
  .submit_wf(
@@ -71,42 +73,8 @@ async fn activity_load() {
71
73
  dbg!(starting.elapsed());
72
74
 
73
75
  let running = Instant::now();
74
- let core = starter.get_worker().await;
75
-
76
- // Poll for and complete all activities
77
- let c2 = core.clone();
78
- let all_acts = async move {
79
- let mut act_complete_futs = vec![];
80
- for _ in 0..CONCURRENCY {
81
- let task = c2.poll_activity_task().await.unwrap();
82
- assert_matches!(
83
- task.variant,
84
- Some(act_task::Variant::Start(ref start_activity)) => {
85
- assert_eq!(start_activity.activity_type, "test_activity")
86
- }
87
- );
88
- let pd = payload_dat.clone();
89
- let core = c2.clone();
90
- act_complete_futs.push(tokio::spawn(async move {
91
- core.complete_activity_task(ActivityTaskCompletion {
92
- task_token: task.task_token,
93
- result: Some(ActivityExecutionResult::ok(pd.into())),
94
- })
95
- .await
96
- .unwrap()
97
- }));
98
- }
99
- join_all(act_complete_futs)
100
- .await
101
- .into_iter()
102
- .for_each(|h| h.unwrap());
103
- };
104
- tokio::join! {
105
- async {
106
- worker.run_until_done().await.unwrap();
107
- },
108
- all_acts
109
- };
76
+
77
+ worker.run_until_done().await.unwrap();
110
78
  dbg!(running.elapsed());
111
79
  }
112
80
 
@@ -153,7 +121,7 @@ async fn workflow_load() {
153
121
 
154
122
  let mut workflow_handles = vec![];
155
123
  for i in 0..num_workflows {
156
- let wfid = format!("{}_{}", wf_name, i);
124
+ let wfid = format!("{wf_name}_{i}");
157
125
  let rid = worker
158
126
  .submit_wf(
159
127
  wfid.clone(),
@@ -171,7 +139,7 @@ async fn workflow_load() {
171
139
  let sends: FuturesUnordered<_> = (0..num_workflows)
172
140
  .map(|i| {
173
141
  client.signal_workflow_execution(
174
- format!("{}_{}", wf_name, i),
142
+ format!("{wf_name}_{i}"),
175
143
  "".to_string(),
176
144
  SIGNAME.to_string(),
177
145
  None,
@@ -187,5 +155,111 @@ async fn workflow_load() {
187
155
  tokio::time::sleep(Duration::from_secs(2)).await;
188
156
  }
189
157
  };
190
- tokio::select! { r1 = worker.run_until_done() => {r1.unwrap()}, _ = sig_sender => {}};
158
+ tokio::select! { r1 = worker.run_until_done() => {r1.unwrap()}, _ = sig_sender => {}}
159
+ }
160
+
161
+ #[tokio::test(flavor = "multi_thread", worker_threads = 4)]
162
+ async fn evict_while_la_running_no_interference() {
163
+ let wf_name = "evict_while_la_running_no_interference";
164
+ let mut starter = CoreWfStarter::new(wf_name);
165
+ starter.max_local_at(20);
166
+ starter.max_cached_workflows(20);
167
+ // Though it doesn't make sense to set wft higher than cached workflows, leaving this commented
168
+ // introduces more instability that can be useful in the test.
169
+ // starter.max_wft(20);
170
+ let mut worker = starter.worker().await;
171
+
172
+ worker.register_wf(wf_name.to_owned(), la_problem_workflow);
173
+ worker.register_activity("delay", |_: ActContext, _: String| async {
174
+ tokio::time::sleep(Duration::from_secs(15)).await;
175
+ Ok(())
176
+ });
177
+
178
+ let client = starter.get_client().await;
179
+ let subfs = FuturesUnordered::new();
180
+ for i in 1..100 {
181
+ let wf_id = format!("{wf_name}-{i}");
182
+ let run_id = worker
183
+ .submit_wf(
184
+ &wf_id,
185
+ wf_name.to_owned(),
186
+ vec![],
187
+ WorkflowOptions::default(),
188
+ )
189
+ .await
190
+ .unwrap();
191
+ let cw = worker.core_worker.clone();
192
+ let client = client.clone();
193
+ subfs.push(async move {
194
+ // Evict the workflow
195
+ tokio::time::sleep(Duration::from_secs(1)).await;
196
+ cw.request_workflow_eviction(&run_id);
197
+ // Wake up workflow by sending signal
198
+ client
199
+ .signal_workflow_execution(
200
+ wf_id,
201
+ run_id.clone(),
202
+ "whaatever".to_string(),
203
+ None,
204
+ None,
205
+ )
206
+ .await
207
+ .unwrap();
208
+ });
209
+ }
210
+ let runf = async {
211
+ worker.run_until_done().await.unwrap();
212
+ };
213
+ tokio::join!(subfs.collect::<Vec<_>>(), runf);
214
+ }
215
+
216
+ pub async fn many_parallel_timers_longhist(ctx: WfContext) -> WorkflowResult<()> {
217
+ for _ in 0..120 {
218
+ let mut futs = vec![];
219
+ for _ in 0..100 {
220
+ futs.push(ctx.timer(Duration::from_millis(100)));
221
+ }
222
+ join_all(futs).await;
223
+ }
224
+ Ok(().into())
225
+ }
226
+
227
+ #[tokio::test]
228
+ async fn can_paginate_long_history() {
229
+ let wf_name = "can_paginate_long_history";
230
+ let mut starter = CoreWfStarter::new(wf_name);
231
+ starter.no_remote_activities();
232
+ // Do not use sticky queues so we are forced to paginate once history gets long
233
+ starter.max_cached_workflows(0);
234
+
235
+ let mut worker = starter.worker().await;
236
+ worker.register_wf(wf_name.to_owned(), many_parallel_timers_longhist);
237
+ let run_id = worker
238
+ .submit_wf(
239
+ wf_name.to_owned(),
240
+ wf_name.to_owned(),
241
+ vec![],
242
+ WorkflowOptions::default(),
243
+ )
244
+ .await
245
+ .unwrap();
246
+ let client = starter.get_client().await;
247
+ tokio::spawn(async move {
248
+ loop {
249
+ for _ in 0..10 {
250
+ client
251
+ .signal_workflow_execution(
252
+ wf_name.to_owned(),
253
+ run_id.clone(),
254
+ "sig".to_string(),
255
+ None,
256
+ None,
257
+ )
258
+ .await
259
+ .unwrap();
260
+ }
261
+ tokio::time::sleep(Duration::from_secs(3)).await;
262
+ }
263
+ });
264
+ worker.run_until_done().await.unwrap();
191
265
  }