temporalio 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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