temporalio 0.0.2 → 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 (202) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +25 -23
  3. data/bridge/Cargo.lock +168 -59
  4. data/bridge/Cargo.toml +4 -2
  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/client/implementation.rb +8 -8
  171. data/lib/temporalio/connection/retry_config.rb +44 -0
  172. data/lib/temporalio/connection/service.rb +20 -0
  173. data/lib/temporalio/connection/test_service.rb +92 -0
  174. data/lib/temporalio/connection/tls_options.rb +51 -0
  175. data/lib/temporalio/connection/workflow_service.rb +731 -0
  176. data/lib/temporalio/connection.rb +55 -720
  177. data/lib/temporalio/interceptor/activity_inbound.rb +22 -0
  178. data/lib/temporalio/interceptor/activity_outbound.rb +24 -0
  179. data/lib/temporalio/interceptor/chain.rb +5 -5
  180. data/lib/temporalio/interceptor/client.rb +8 -4
  181. data/lib/temporalio/interceptor.rb +22 -0
  182. data/lib/temporalio/retry_policy.rb +13 -3
  183. data/lib/temporalio/testing/time_skipping_handle.rb +32 -0
  184. data/lib/temporalio/testing/time_skipping_interceptor.rb +23 -0
  185. data/lib/temporalio/testing/workflow_environment.rb +112 -0
  186. data/lib/temporalio/testing.rb +175 -0
  187. data/lib/temporalio/version.rb +1 -1
  188. data/lib/temporalio/worker/activity_runner.rb +26 -4
  189. data/lib/temporalio/worker/activity_worker.rb +44 -18
  190. data/lib/temporalio/worker/sync_worker.rb +47 -11
  191. data/lib/temporalio/worker.rb +27 -21
  192. data/lib/temporalio/workflow/async.rb +46 -0
  193. data/lib/temporalio/workflow/future.rb +138 -0
  194. data/lib/temporalio/workflow/info.rb +76 -0
  195. data/temporalio.gemspec +4 -3
  196. metadata +67 -17
  197. data/bridge/sdk-core/Cargo.lock +0 -2606
  198. data/bridge/sdk-core/protos/api_upstream/temporal/api/interaction/v1/message.proto +0 -87
  199. data/lib/bridge.so +0 -0
  200. data/lib/gen/temporal/api/enums/v1/interaction_type_pb.rb +0 -25
  201. data/lib/gen/temporal/api/interaction/v1/message_pb.rb +0 -49
  202. data/lib/gen/temporal/sdk/core/bridge/bridge_pb.rb +0 -222
@@ -1,17 +1,32 @@
1
1
  require 'temporalio/error/failure'
2
2
  require 'temporalio/errors'
3
+ require 'temporalio/interceptor'
4
+ require 'temporalio/interceptor/chain'
3
5
  require 'temporalio/worker/activity_runner'
4
- require 'temporalio/worker/sync_worker'
5
6
 
6
7
  module Temporalio
7
8
  class Worker
8
9
  # @api private
9
10
  class ActivityWorker
10
- def initialize(task_queue, core_worker, activities, converter, executor, graceful_timeout)
11
+ def initialize(
12
+ task_queue,
13
+ worker,
14
+ activities,
15
+ converter,
16
+ interceptors,
17
+ executor,
18
+ graceful_timeout
19
+ )
11
20
  @task_queue = task_queue
12
- @worker = SyncWorker.new(core_worker)
21
+ @worker = worker
13
22
  @activities = prepare_activities(activities)
14
23
  @converter = converter
24
+ @inbound_interceptors = Temporalio::Interceptor::Chain.new(
25
+ Temporalio::Interceptor.filter(interceptors, :activity_inbound),
26
+ )
27
+ @outbound_interceptors = Temporalio::Interceptor::Chain.new(
28
+ Temporalio::Interceptor.filter(interceptors, :activity_outbound),
29
+ )
15
30
  @executor = executor
16
31
  @graceful_timeout = graceful_timeout
17
32
  @running_activities = {}
@@ -38,20 +53,21 @@ module Temporalio
38
53
  rescue Temporalio::Bridge::Error::WorkerShutdown
39
54
  # No need to re-raise this error, it's a part of a normal shutdown
40
55
  ensure
41
- reactor.async do |async_task|
42
- cancelation_task =
43
- if graceful_timeout
44
- async_task.async do
45
- sleep graceful_timeout
46
- running_activities.each_value do |activity_runner|
47
- activity_runner.cancel('Worker is shutting down', by_request: false)
48
- end
56
+ outstanding_tasks.each(&:wait)
57
+ @cancelation_task&.wait
58
+ drain_queue.close
59
+ end
60
+
61
+ def setup_graceful_shutdown_timer(reactor)
62
+ if graceful_timeout
63
+ reactor.async do |async_task|
64
+ @cancelation_task = async_task.async do
65
+ sleep graceful_timeout
66
+ @running_activities.each_value do |activity_runner|
67
+ activity_runner.cancel('Worker is shutting down', by_request: false)
49
68
  end
50
69
  end
51
-
52
- outstanding_tasks.each(&:wait)
53
- cancelation_task&.stop # all tasks completed, stop cancellations
54
- drain_queue.close
70
+ end
55
71
  end
56
72
  end
57
73
 
@@ -61,8 +77,9 @@ module Temporalio
61
77
 
62
78
  private
63
79
 
64
- attr_reader :task_queue, :worker, :activities, :converter, :executor, :graceful_timeout,
65
- :running_activities, :cancellations, :drain_queue
80
+ attr_reader :task_queue, :worker, :activities, :converter, :inbound_interceptors,
81
+ :outbound_interceptors, :executor, :graceful_timeout, :running_activities,
82
+ :cancellations, :drain_queue
66
83
 
67
84
  def prepare_activities(activities)
68
85
  activities.each_with_object({}) do |activity, result|
@@ -91,7 +108,16 @@ module Temporalio
91
108
 
92
109
  def run_activity(token, start)
93
110
  activity_class = lookup_activity(start.activity_type)
94
- runner = ActivityRunner.new(activity_class, start, task_queue, token, worker, converter)
111
+ runner = ActivityRunner.new(
112
+ activity_class,
113
+ start,
114
+ task_queue,
115
+ token,
116
+ worker,
117
+ converter,
118
+ inbound_interceptors,
119
+ outbound_interceptors,
120
+ )
95
121
  running_activities[token] = runner
96
122
  queue = Queue.new
97
123
 
@@ -1,5 +1,7 @@
1
1
  require 'temporal/sdk/core/activity_task/activity_task_pb'
2
2
  require 'temporal/sdk/core/core_interface_pb'
3
+ require 'temporal/sdk/core/workflow_activation/workflow_activation_pb'
4
+ require 'temporal/sdk/core/workflow_completion/workflow_completion_pb'
3
5
 
4
6
  module Temporalio
5
7
  class Worker
@@ -19,45 +21,71 @@ module Temporalio
19
21
  def poll_activity_task
20
22
  with_queue do |done|
21
23
  core_worker.poll_activity_task do |task, error|
22
- done.call(task && Coresdk::ActivityTask::ActivityTask.decode(task), error)
24
+ done.call(task && Temporalio::Bridge::Api::ActivityTask::ActivityTask.decode(task), error)
23
25
  end
24
26
  end
25
27
  end
26
28
 
27
29
  def complete_activity_task_with_success(task_token, payload)
28
- result = Coresdk::ActivityResult::ActivityExecutionResult.new(
29
- completed: Coresdk::ActivityResult::Success.new(result: payload),
30
+ result = Temporalio::Bridge::Api::ActivityResult::ActivityExecutionResult.new(
31
+ completed: Temporalio::Bridge::Api::ActivityResult::Success.new(result: payload),
30
32
  )
31
33
 
32
34
  complete_activity_task(task_token, result)
33
35
  end
34
36
 
35
37
  def complete_activity_task_with_failure(task_token, failure)
36
- result = Coresdk::ActivityResult::ActivityExecutionResult.new(
37
- failed: Coresdk::ActivityResult::Failure.new(failure: failure),
38
+ result = Temporalio::Bridge::Api::ActivityResult::ActivityExecutionResult.new(
39
+ failed: Temporalio::Bridge::Api::ActivityResult::Failure.new(failure: failure),
38
40
  )
39
41
 
40
42
  complete_activity_task(task_token, result)
41
43
  end
42
44
 
43
45
  def complete_activity_task_with_cancellation(task_token, failure)
44
- result = Coresdk::ActivityResult::ActivityExecutionResult.new(
45
- cancelled: Coresdk::ActivityResult::Cancellation.new(failure: failure),
46
+ result = Temporalio::Bridge::Api::ActivityResult::ActivityExecutionResult.new(
47
+ cancelled: Temporalio::Bridge::Api::ActivityResult::Cancellation.new(failure: failure),
46
48
  )
47
49
 
48
50
  complete_activity_task(task_token, result)
49
51
  end
50
52
 
51
53
  def record_activity_heartbeat(task_token, payloads)
52
- proto = Coresdk::ActivityHeartbeat.new(
54
+ proto = Temporalio::Bridge::Api::CoreInterface::ActivityHeartbeat.new(
53
55
  task_token: task_token,
54
56
  details: payloads,
55
57
  )
56
- encoded_proto = Coresdk::ActivityHeartbeat.encode(proto)
58
+ encoded_proto = Temporalio::Bridge::Api::CoreInterface::ActivityHeartbeat.encode(proto)
57
59
 
58
60
  core_worker.record_activity_heartbeat(encoded_proto)
59
61
  end
60
62
 
63
+ def poll_workflow_activation
64
+ with_queue do |done|
65
+ core_worker.poll_workflow_activation do |task, error|
66
+ done.call(task && Temporalio::Bridge::Api::WorkflowActivation::WorkflowActivation.decode(task), error)
67
+ end
68
+ end
69
+ end
70
+
71
+ def complete_workflow_activation_with_success(run_id, commands)
72
+ proto = Temporalio::Bridge::Api::WorkflowCompletion::WorkflowActivationCompletion.new(
73
+ run_id: run_id,
74
+ successful: Temporalio::Bridge::Api::WorkflowCompletion::Success.new(commands: commands),
75
+ )
76
+
77
+ complete_workflow_activation(proto)
78
+ end
79
+
80
+ def complete_workflow_activation_with_failure(run_id, failure)
81
+ proto = Temporalio::Bridge::Api::WorkflowCompletion::WorkflowActivationCompletion.new(
82
+ run_id: run_id,
83
+ failed: Temporalio::Bridge::Api::WorkflowCompletion::Failure.new(failure: failure),
84
+ )
85
+
86
+ complete_workflow_activation(proto)
87
+ end
88
+
61
89
  private
62
90
 
63
91
  attr_reader :core_worker
@@ -73,16 +101,24 @@ module Temporalio
73
101
  end
74
102
 
75
103
  def complete_activity_task(task_token, result)
76
- proto = Coresdk::ActivityTaskCompletion.new(
104
+ proto = Temporalio::Bridge::Api::CoreInterface::ActivityTaskCompletion.new(
77
105
  task_token: task_token,
78
106
  result: result,
79
107
  )
80
- encoded_proto = Coresdk::ActivityTaskCompletion.encode(proto)
108
+ encoded_proto = Temporalio::Bridge::Api::CoreInterface::ActivityTaskCompletion.encode(proto)
81
109
 
82
110
  with_queue do |done|
83
111
  core_worker.complete_activity_task(encoded_proto, &done)
84
112
  end
85
113
  end
114
+
115
+ def complete_workflow_activation(proto)
116
+ encoded_proto = Temporalio::Bridge::Api::WorkflowCompletion::WorkflowActivationCompletion.encode(proto)
117
+
118
+ with_queue do |done|
119
+ core_worker.complete_workflow_activation(encoded_proto, &done)
120
+ end
121
+ end
86
122
  end
87
123
  end
88
124
  end
@@ -4,10 +4,11 @@ require 'temporalio/data_converter'
4
4
  require 'temporalio/runtime'
5
5
  require 'temporalio/worker/activity_worker'
6
6
  require 'temporalio/worker/runner'
7
+ require 'temporalio/worker/sync_worker'
7
8
  require 'temporalio/worker/thread_pool_executor'
8
9
 
9
10
  module Temporalio
10
- # Worker to process workflows and/or activities.
11
+ # Worker to process activities.
11
12
  #
12
13
  # Once created, workers can be run and shutdown explicitly via {#run} and {#shutdown}.
13
14
  class Worker
@@ -40,7 +41,7 @@ module Temporalio
40
41
  Runner.new(*workers).run(&block)
41
42
  end
42
43
 
43
- # Create a worker to process workflows and/or activities.
44
+ # Create a worker to process activities.
44
45
  #
45
46
  # @param connection [Temporalio::Connection] A connection to be used for this worker.
46
47
  # @param namespace [String] A namespace.
@@ -50,12 +51,14 @@ module Temporalio
50
51
  # to/from payloads.
51
52
  # @param activity_executor [ThreadPoolExecutor] Concurrent executor for all activities. Defaults
52
53
  # to a {ThreadPoolExecutor} with `:max_concurrent_activities` available threads.
54
+ # @param interceptors [Array<Temporalio::Interceptor::ActivityInbound, Temporalio::Interceptor::ActivityOutbound>]
55
+ # Collection of interceptors for this worker.
53
56
  # @param max_concurrent_activities [Integer] Number of concurrently running activities.
54
57
  # @param graceful_shutdown_timeout [Integer] Amount of time (in seconds) activities are given
55
58
  # after a shutdown to complete before they are cancelled. A default value of `nil` means that
56
59
  # activities are never cancelled when handling a shutdown.
57
60
  #
58
- # @raise [ArgumentError] When no activities or workflows have been provided.
61
+ # @raise [ArgumentError] When no activities have been provided.
59
62
  def initialize(
60
63
  connection,
61
64
  namespace,
@@ -63,10 +66,10 @@ module Temporalio
63
66
  activities: [],
64
67
  data_converter: Temporalio::DataConverter.new,
65
68
  activity_executor: nil,
69
+ interceptors: [],
66
70
  max_concurrent_activities: 100,
67
71
  graceful_shutdown_timeout: nil
68
72
  )
69
- # TODO: Add worker interceptors
70
73
  @started = false
71
74
  @shutdown = false
72
75
  @mutex = Mutex.new
@@ -77,22 +80,26 @@ module Temporalio
77
80
  connection.core_connection,
78
81
  namespace,
79
82
  task_queue,
83
+ 0, # maxCachedWorkflows disabled temporarily
84
+ # FIXME: expose enable_non_local_activities
85
+ activities.empty?,
80
86
  )
87
+ sync_worker = Worker::SyncWorker.new(@core_worker)
81
88
  @activity_worker =
82
89
  unless activities.empty?
83
90
  Worker::ActivityWorker.new(
84
91
  task_queue,
85
- @core_worker,
92
+ sync_worker,
86
93
  activities,
87
94
  data_converter,
95
+ interceptors,
88
96
  @activity_executor,
89
97
  graceful_shutdown_timeout,
90
98
  )
91
99
  end
92
- @workflow_worker = nil
93
100
 
94
- if !@activity_worker && !@workflow_worker
95
- raise ArgumentError, 'At least one activity or workflow must be specified'
101
+ unless @activity_worker
102
+ raise ArgumentError, 'At least one activity must be specified'
96
103
  end
97
104
  end
98
105
 
@@ -105,9 +112,9 @@ module Temporalio
105
112
  # run it again.
106
113
  #
107
114
  # @yield Optionally you can provide a block by the end of which the worker will shut itself
108
- # down. You can use this to stop a worker after some time has passed, your workflow has
109
- # finished or any other arbitrary implementation has completed. Any errors raised from this
110
- # block will be re-raised by this method.
115
+ # down. You can use this to stop a worker after some time has passed or any other arbitrary
116
+ # implementation has completed. Any errors raised from this block will be re-raised by this
117
+ # method.
111
118
  def run(&block)
112
119
  Runner.new(self).run(&block)
113
120
  end
@@ -141,9 +148,6 @@ module Temporalio
141
148
  shutdown(e) # initiate shutdown because of a fatal error
142
149
  end
143
150
  end
144
-
145
- # TODO: Pending implementation
146
- task.async { |task| workflow_worker.run(task) } if workflow_worker
147
151
  end
148
152
  end
149
153
 
@@ -158,17 +162,19 @@ module Temporalio
158
162
  mutex.synchronize do
159
163
  return unless running?
160
164
 
161
- # First initiate Core shutdown, which will start dropping poll requests
162
- core_worker.initiate_shutdown
163
- # Then let the runner know we're shutting down, so it can stop other workers
165
+ # Let the runner know we're shutting down, so it can stop other workers.
166
+ # This will cause a reentrant call to this method, but the mutex above will block that call.
164
167
  runner&.shutdown(exception)
168
+
169
+ # Initiate Core shutdown, which will start dropping poll requests
170
+ core_worker.initiate_shutdown
171
+ # Start the graceful activity shutdown timer, which will cancel activities after the timeout
172
+ activity_worker&.setup_graceful_shutdown_timer(runtime.reactor)
165
173
  # Wait for workers to drain any outstanding tasks
166
174
  activity_worker&.drain
167
- workflow_worker&.drain
168
- # Stop the executor (at this point there should already be nothing in it)
169
175
  activity_executor.shutdown
170
176
  # Finalize the shutdown by stopping the Core
171
- core_worker.shutdown
177
+ core_worker.finalize_shutdown
172
178
 
173
179
  @shutdown = true
174
180
  end
@@ -193,6 +199,6 @@ module Temporalio
193
199
  private
194
200
 
195
201
  attr_reader :mutex, :runtime, :activity_executor, :core_worker, :activity_worker,
196
- :workflow_worker, :runner
202
+ :runner
197
203
  end
198
204
  end
@@ -0,0 +1,46 @@
1
+ require 'temporalio/workflow/future'
2
+
3
+ module Temporalio
4
+ class Workflow
5
+ module Async
6
+ def self.run(&block)
7
+ Future.new do |future, resolve, reject|
8
+ Fiber.new do
9
+ Future.current = future
10
+ result = block.call
11
+ resolve.call(result)
12
+ rescue StandardError => e
13
+ reject.call(e)
14
+ end.resume
15
+ end
16
+ end
17
+
18
+ def self.all(*futures)
19
+ Future.new do |future, resolve, _reject|
20
+ future.on_cancel { futures.each(&:cancel) }
21
+
22
+ futures.each do |f|
23
+ f.then do
24
+ # Resolve the aggregate once all futures have been fulfilled (resolved or rejected)
25
+ resolve.call(nil) if futures.none?(&:pending?)
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ def self.any(*futures)
32
+ # This future is never rejected
33
+ Future.new do |future, resolve, _reject|
34
+ future.on_cancel { futures.each(&:cancel) }
35
+
36
+ futures.each do |f|
37
+ # Resolve the aggregate once the first future fulfills (resolved or rejected)
38
+ # NOTE: The the first completed future will be the resolved value and all subsequent
39
+ # calls to `resolve` will have no effect.
40
+ f.then { resolve.call(f) }
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,138 @@
1
+ module Temporalio
2
+ class Workflow
3
+ class Future
4
+ THREAD_KEY = :temporalio_workflow_future
5
+
6
+ class Rejected < StandardError; end
7
+
8
+ def self.current
9
+ Thread.current[THREAD_KEY]
10
+ end
11
+
12
+ def self.current=(future)
13
+ Thread.current[THREAD_KEY] = future
14
+ end
15
+
16
+ # Revist the reason for combining futures and cancellation scopes, maybe they are separate?
17
+ def initialize(&block)
18
+ @resolved = false
19
+ @value = nil
20
+ @rejected = false
21
+ @error = Rejected.new('Future rejected')
22
+ @cancel_requested = false
23
+ @blocked_fibers = []
24
+ @callbacks = []
25
+ @cancel_callbacks = []
26
+
27
+ # Chain cancellation into parent future if one exists
28
+ Future.current&.on_cancel { cancel }
29
+
30
+ # NOTE: resolve and reject methods are accessible via procs to avoid exposing
31
+ # them via the public interface.
32
+ block.call(
33
+ self,
34
+ ->(value) { resolve(value) },
35
+ ->(error) { reject(error) },
36
+ )
37
+ end
38
+
39
+ def then(&block)
40
+ Future.new do |future, resolve, reject|
41
+ # @type var wrapped_block: ^() -> void
42
+ wrapped_block = -> do # rubocop:disable Style/Lambda
43
+ Fiber.new do
44
+ Future.current = future
45
+ # The block is provided the Future on which #then was called
46
+ result = block.call(self)
47
+ resolve.call(result)
48
+ rescue StandardError => e
49
+ reject.call(e)
50
+ end.resume
51
+ end
52
+
53
+ if pending?
54
+ callbacks << wrapped_block
55
+ else
56
+ wrapped_block.call
57
+ end
58
+ end
59
+ end
60
+
61
+ def on_cancel(&block)
62
+ if pending? && !cancel_requested?
63
+ cancel_callbacks << block
64
+ else
65
+ block.call
66
+ end
67
+ end
68
+
69
+ def pending?
70
+ !resolved? && !rejected?
71
+ end
72
+
73
+ def resolved?
74
+ @resolved
75
+ end
76
+
77
+ def rejected?
78
+ @rejected
79
+ end
80
+
81
+ def await
82
+ if pending?
83
+ blocked_fibers << Fiber.current
84
+ # yield into the parent fiber
85
+ Fiber.yield while pending?
86
+ end
87
+
88
+ raise error if rejected?
89
+
90
+ value
91
+ end
92
+
93
+ def cancel
94
+ return unless pending?
95
+ return if cancel_requested?
96
+
97
+ @cancel_requested = true
98
+ cancel_callbacks.each(&:call)
99
+ end
100
+
101
+ private
102
+
103
+ attr_reader :value, :error, :blocked_fibers, :callbacks, :cancel_callbacks
104
+
105
+ def cancel_requested?
106
+ @cancel_requested
107
+ end
108
+
109
+ # TODO: Run callbacks in a Fiber to allow blocking calls
110
+ def run_callbacks
111
+ callbacks.each(&:call)
112
+ end
113
+
114
+ # Unblock every fiber that this future is awaited on
115
+ def resume_fibers
116
+ blocked_fibers.each(&:resume)
117
+ end
118
+
119
+ def resolve(value)
120
+ return unless pending?
121
+
122
+ @value = value
123
+ @resolved = true
124
+ run_callbacks
125
+ resume_fibers
126
+ end
127
+
128
+ def reject(error)
129
+ return unless pending?
130
+
131
+ @error = error
132
+ @rejected = true
133
+ run_callbacks
134
+ resume_fibers
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,76 @@
1
+ module Temporalio
2
+ class Workflow
3
+ # Class containing information about a workflow's parent.
4
+ class ParentInfo < Struct.new(
5
+ :namespace,
6
+ :run_id,
7
+ :workflow_id,
8
+ keyword_init: true,
9
+ )
10
+ # @!attribute [r] namespace
11
+ # @return [String] Namespace of the parent workflow.
12
+ # @!attribute [r] run_id
13
+ # @return [String] Run ID of the parent workflow.
14
+ # @!attribute [r] workflow_id
15
+ # @return [String] ID of the parent workflow.
16
+ end
17
+
18
+ # Class containing information about a workflow.
19
+ class Info < Struct.new(
20
+ :attempt,
21
+ :continued_run_id,
22
+ :cron_schedule,
23
+ :execution_timeout,
24
+ :headers,
25
+ :namespace,
26
+ :parent,
27
+ :raw_memo,
28
+ :retry_policy,
29
+ :run_id,
30
+ :run_timeout,
31
+ :search_attributes,
32
+ :start_time,
33
+ :task_queue,
34
+ :task_timeout,
35
+ :workflow_id,
36
+ :workflow_type,
37
+ keyword_init: true,
38
+ )
39
+ # @!attribute [r] attempt
40
+ # @return [Integer] Attempt of executing the workflow.
41
+ # @!attribute [r] continued_run_id
42
+ # @return [String] Run id of the previous workflow which continued-as-new or retired or cron
43
+ # executed into this workflow, if any.
44
+ # @!attribute [r] cron_schedule
45
+ # @return [String] Cron schedule of the workflow.
46
+ # @!attribute [r] execution_timeout
47
+ # @return [Float] Execution timeout of the workflow (in seconds).
48
+ # @!attribute [r] headers
49
+ # @return [Hash<String, any>] Headers for the workflow.
50
+ # @!attribute [r] namespace
51
+ # @return [String] Namespace of the workflow.
52
+ # @!attribute [r] parent
53
+ # @return [Temporalio::Workflow::ParentInfo] Info of the parent workflow.
54
+ # @!attribute [r] raw_memo
55
+ # @return [Hash<String, any>] Memo for the workflow.
56
+ # @!attribute [r] retry_policy
57
+ # @return [Temporalio::RetryPolicy] RetryPolicy of the workflow.
58
+ # @!attribute [r] run_id
59
+ # @return [String] Run ID of the workflow.
60
+ # @!attribute [r] run_timeout
61
+ # @return [Float] Run timeout of the workflow (in seconds).
62
+ # @!attribute [r] search_attributes
63
+ # @return [Hash<String, String>] Search attributes of the workflow.
64
+ # @!attribute [r] start_time
65
+ # @return [Time] Start time of the workflow.
66
+ # @!attribute [r] task_queue
67
+ # @return [String] Task queue of the workflow.
68
+ # @!attribute [r] task_timeout
69
+ # @return [Float] Task timeout of the workflow (in seconds).
70
+ # @!attribute [r] workflow_id
71
+ # @return [String] ID of the workflow.
72
+ # @!attribute [r] workflow_type
73
+ # @return [String] Type of the workflow.
74
+ end
75
+ end
76
+ end
data/temporalio.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.homepage = 'https://github.com/temporalio/sdk-ruby'
9
9
  spec.licenses = ['MIT']
10
10
 
11
- spec.authors = ['Anthony D']
12
- spec.email = ['anthony@temporal.io']
11
+ spec.authors = ['Temporal Technologies Inc.']
12
+ spec.email = ['sdk@temporal.io']
13
13
 
14
14
  spec.require_paths = ['lib']
15
15
  spec.extensions = ['ext/Rakefile']
@@ -35,11 +35,12 @@ Gem::Specification.new do |spec|
35
35
  spec.add_development_dependency 'protobuf' # Ruby implementation of protobufs (for rbs_protobuf)
36
36
  spec.add_development_dependency 'pry' # Debugger
37
37
  spec.add_development_dependency 'rake' # rake tasks
38
+ spec.add_development_dependency 'rbs', '>= 2.8.0', '< 3.0.0' # RBS - steep 1.3.0 crashes with RBS 3.0.0
38
39
  spec.add_development_dependency 'rbs_protobuf' # RBS generator for protobufs
39
40
  spec.add_development_dependency 'rspec' # specs
40
41
  spec.add_development_dependency 'rubocop' # linter
41
42
  spec.add_development_dependency 'rubocop-rspec' # spec linter
42
- spec.add_development_dependency 'steep' # type checker
43
+ spec.add_development_dependency 'steep', '~> 1.3.0' # type checker
43
44
  spec.add_development_dependency 'typeprof' # type generator
44
45
  spec.add_development_dependency 'yard' # docs
45
46
  end