temporalio 0.0.1 → 0.0.2

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 (232) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +175 -4
  3. data/bridge/Cargo.lock +44 -21
  4. data/bridge/Cargo.toml +1 -0
  5. data/bridge/sdk-core/Cargo.toml +1 -1
  6. data/bridge/sdk-core/README.md +1 -4
  7. data/bridge/sdk-core/client/Cargo.toml +1 -1
  8. data/bridge/sdk-core/client/src/lib.rs +12 -20
  9. data/bridge/sdk-core/client/src/raw.rs +9 -8
  10. data/bridge/sdk-core/client/src/retry.rs +100 -23
  11. data/bridge/sdk-core/core/Cargo.toml +7 -7
  12. data/bridge/sdk-core/core/benches/workflow_replay.rs +13 -10
  13. data/bridge/sdk-core/core/src/abstractions.rs +22 -22
  14. data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +146 -43
  15. data/bridge/sdk-core/core/src/core_tests/local_activities.rs +419 -9
  16. data/bridge/sdk-core/core/src/core_tests/queries.rs +247 -89
  17. data/bridge/sdk-core/core/src/core_tests/workers.rs +2 -2
  18. data/bridge/sdk-core/core/src/core_tests/workflow_cancels.rs +1 -1
  19. data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +47 -27
  20. data/bridge/sdk-core/core/src/lib.rs +139 -32
  21. data/bridge/sdk-core/core/src/protosext/mod.rs +1 -1
  22. data/bridge/sdk-core/core/src/replay/mod.rs +185 -41
  23. data/bridge/sdk-core/core/src/telemetry/log_export.rs +190 -0
  24. data/bridge/sdk-core/core/src/telemetry/metrics.rs +184 -139
  25. data/bridge/sdk-core/core/src/telemetry/mod.rs +310 -315
  26. data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +4 -3
  27. data/bridge/sdk-core/core/src/test_help/mod.rs +23 -9
  28. data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +12 -6
  29. data/bridge/sdk-core/core/src/worker/activities.rs +40 -23
  30. data/bridge/sdk-core/core/src/worker/client/mocks.rs +1 -1
  31. data/bridge/sdk-core/core/src/worker/client.rs +30 -4
  32. data/bridge/sdk-core/core/src/worker/mod.rs +23 -19
  33. data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +10 -19
  34. data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +99 -25
  35. data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +1 -5
  36. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +1 -5
  37. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +1 -5
  38. data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +3 -5
  39. data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +1 -5
  40. data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +2 -6
  41. data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +1 -5
  42. data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +24 -22
  43. data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +12 -38
  44. data/bridge/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +178 -0
  45. data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +1 -5
  46. data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +1 -5
  47. data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +1 -5
  48. data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +8 -2
  49. data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +1 -5
  50. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +1 -1
  51. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +233 -217
  52. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +1 -6
  53. data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +4 -4
  54. data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +13 -5
  55. data/bridge/sdk-core/core/src/worker/workflow/mod.rs +86 -29
  56. data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +2 -2
  57. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +56 -11
  58. data/bridge/sdk-core/core-api/Cargo.toml +4 -3
  59. data/bridge/sdk-core/core-api/src/lib.rs +1 -43
  60. data/bridge/sdk-core/core-api/src/telemetry.rs +147 -0
  61. data/bridge/sdk-core/core-api/src/worker.rs +13 -0
  62. data/bridge/sdk-core/etc/deps.svg +115 -140
  63. data/bridge/sdk-core/etc/regen-depgraph.sh +5 -0
  64. data/bridge/sdk-core/fsm/rustfsm_procmacro/tests/trybuild/no_handle_conversions_require_into_fail.stderr +1 -1
  65. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-23_history.bin +0 -0
  66. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-85_history.bin +0 -0
  67. data/bridge/sdk-core/protos/api_upstream/buf.yaml +0 -3
  68. data/bridge/sdk-core/protos/api_upstream/build/go.mod +7 -0
  69. data/bridge/sdk-core/protos/api_upstream/build/go.sum +5 -0
  70. data/bridge/sdk-core/protos/api_upstream/{temporal/api/update/v1/message.proto → build/tools.go} +6 -23
  71. data/bridge/sdk-core/protos/api_upstream/go.mod +6 -0
  72. data/bridge/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +12 -9
  73. data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +20 -19
  74. data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +2 -2
  75. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -2
  76. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +4 -4
  77. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +3 -2
  78. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +5 -3
  79. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +23 -2
  80. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/{cluster.proto → interaction_type.proto} +10 -11
  81. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +2 -2
  82. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +2 -2
  83. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -2
  84. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +2 -2
  85. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +2 -2
  86. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +2 -13
  87. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +2 -2
  88. data/bridge/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +2 -2
  89. data/bridge/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -2
  90. data/bridge/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +2 -2
  91. data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +26 -19
  92. data/bridge/sdk-core/protos/api_upstream/temporal/api/interaction/v1/message.proto +87 -0
  93. data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +2 -2
  94. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +21 -61
  95. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +2 -21
  96. data/bridge/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +2 -2
  97. data/bridge/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +2 -2
  98. data/bridge/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +110 -31
  99. data/bridge/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +4 -4
  100. data/bridge/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +2 -2
  101. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +3 -2
  102. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +60 -16
  103. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +17 -3
  104. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +2 -0
  105. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +8 -1
  106. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +2 -2
  107. data/bridge/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +2 -2
  108. data/bridge/sdk-core/sdk/Cargo.toml +2 -2
  109. data/bridge/sdk-core/sdk/src/interceptors.rs +36 -3
  110. data/bridge/sdk-core/sdk/src/lib.rs +7 -5
  111. data/bridge/sdk-core/sdk/src/workflow_context.rs +13 -2
  112. data/bridge/sdk-core/sdk/src/workflow_future.rs +3 -7
  113. data/bridge/sdk-core/sdk-core-protos/Cargo.toml +1 -1
  114. data/bridge/sdk-core/sdk-core-protos/build.rs +0 -1
  115. data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +65 -18
  116. data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +22 -22
  117. data/bridge/sdk-core/sdk-core-protos/src/lib.rs +104 -44
  118. data/bridge/sdk-core/test-utils/Cargo.toml +2 -1
  119. data/bridge/sdk-core/test-utils/src/lib.rs +81 -29
  120. data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +5 -2
  121. data/bridge/sdk-core/tests/integ_tests/metrics_tests.rs +37 -0
  122. data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +0 -13
  123. data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +167 -13
  124. data/bridge/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +53 -0
  125. data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +106 -20
  126. data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +18 -8
  127. data/bridge/sdk-core/tests/main.rs +6 -4
  128. data/bridge/src/connection.rs +81 -62
  129. data/bridge/src/lib.rs +92 -33
  130. data/bridge/src/runtime.rs +9 -2
  131. data/bridge/src/worker.rs +53 -2
  132. data/lib/bridge.so +0 -0
  133. data/lib/gen/temporal/api/batch/v1/message_pb.rb +8 -6
  134. data/lib/gen/temporal/api/command/v1/message_pb.rb +17 -9
  135. data/lib/gen/temporal/api/common/v1/message_pb.rb +1 -1
  136. data/lib/gen/temporal/api/enums/v1/batch_operation_pb.rb +2 -1
  137. data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +3 -1
  138. data/lib/gen/temporal/api/enums/v1/common_pb.rb +2 -1
  139. data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +3 -2
  140. data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +7 -1
  141. data/lib/gen/temporal/api/enums/v1/interaction_type_pb.rb +25 -0
  142. data/lib/gen/temporal/api/enums/v1/namespace_pb.rb +1 -1
  143. data/lib/gen/temporal/api/enums/v1/query_pb.rb +1 -1
  144. data/lib/gen/temporal/api/enums/v1/reset_pb.rb +1 -1
  145. data/lib/gen/temporal/api/enums/v1/schedule_pb.rb +1 -1
  146. data/lib/gen/temporal/api/enums/v1/task_queue_pb.rb +1 -1
  147. data/lib/gen/temporal/api/enums/v1/update_pb.rb +1 -6
  148. data/lib/gen/temporal/api/enums/v1/workflow_pb.rb +1 -1
  149. data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +1 -1
  150. data/lib/gen/temporal/api/failure/v1/message_pb.rb +1 -1
  151. data/lib/gen/temporal/api/filter/v1/message_pb.rb +1 -1
  152. data/lib/gen/temporal/api/history/v1/message_pb.rb +19 -18
  153. data/lib/gen/temporal/api/interaction/v1/message_pb.rb +49 -0
  154. data/lib/gen/temporal/api/namespace/v1/message_pb.rb +1 -1
  155. data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +11 -51
  156. data/lib/gen/temporal/api/operatorservice/v1/service_pb.rb +1 -1
  157. data/lib/gen/temporal/api/query/v1/message_pb.rb +1 -1
  158. data/lib/gen/temporal/api/replication/v1/message_pb.rb +1 -1
  159. data/lib/gen/temporal/api/schedule/v1/message_pb.rb +22 -1
  160. data/lib/gen/temporal/api/taskqueue/v1/message_pb.rb +2 -2
  161. data/lib/gen/temporal/api/version/v1/message_pb.rb +1 -1
  162. data/lib/gen/temporal/api/workflow/v1/message_pb.rb +2 -1
  163. data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +27 -10
  164. data/lib/gen/temporal/api/workflowservice/v1/service_pb.rb +1 -1
  165. data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +1 -0
  166. data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +5 -1
  167. data/lib/temporalio/activity/context.rb +97 -0
  168. data/lib/temporalio/activity/info.rb +67 -0
  169. data/lib/temporalio/activity.rb +85 -0
  170. data/lib/temporalio/bridge/error.rb +8 -0
  171. data/lib/temporalio/bridge.rb +14 -0
  172. data/lib/{temporal → temporalio}/client/implementation.rb +49 -48
  173. data/lib/{temporal → temporalio}/client/workflow_handle.rb +35 -35
  174. data/lib/{temporal → temporalio}/client.rb +19 -32
  175. data/lib/{temporal → temporalio}/connection.rb +238 -223
  176. data/lib/{temporal → temporalio}/data_converter.rb +76 -35
  177. data/lib/{temporal → temporalio}/error/failure.rb +6 -6
  178. data/lib/{temporal → temporalio}/error/workflow_failure.rb +4 -2
  179. data/lib/{temporal → temporalio}/errors.rb +19 -1
  180. data/lib/{temporal → temporalio}/failure_converter/base.rb +5 -5
  181. data/lib/{temporal → temporalio}/failure_converter/basic.rb +58 -52
  182. data/lib/temporalio/failure_converter.rb +7 -0
  183. data/lib/{temporal → temporalio}/interceptor/chain.rb +2 -1
  184. data/lib/{temporal → temporalio}/interceptor/client.rb +22 -1
  185. data/lib/{temporal → temporalio}/payload_codec/base.rb +5 -5
  186. data/lib/{temporal → temporalio}/payload_converter/base.rb +3 -3
  187. data/lib/{temporal → temporalio}/payload_converter/bytes.rb +4 -3
  188. data/lib/{temporal → temporalio}/payload_converter/composite.rb +7 -5
  189. data/lib/{temporal → temporalio}/payload_converter/encoding_base.rb +4 -4
  190. data/lib/{temporal → temporalio}/payload_converter/json.rb +4 -3
  191. data/lib/{temporal → temporalio}/payload_converter/nil.rb +4 -3
  192. data/lib/temporalio/payload_converter.rb +14 -0
  193. data/lib/{temporal → temporalio}/retry_policy.rb +4 -4
  194. data/lib/{temporal → temporalio}/retry_state.rb +1 -1
  195. data/lib/temporalio/runtime.rb +25 -0
  196. data/lib/{temporal → temporalio}/timeout_type.rb +2 -2
  197. data/lib/temporalio/version.rb +3 -0
  198. data/lib/temporalio/worker/activity_runner.rb +92 -0
  199. data/lib/temporalio/worker/activity_worker.rb +138 -0
  200. data/lib/temporalio/worker/reactor.rb +46 -0
  201. data/lib/temporalio/worker/runner.rb +63 -0
  202. data/lib/temporalio/worker/sync_worker.rb +88 -0
  203. data/lib/temporalio/worker/thread_pool_executor.rb +51 -0
  204. data/lib/temporalio/worker.rb +198 -0
  205. data/lib/{temporal → temporalio}/workflow/execution_info.rb +4 -4
  206. data/lib/{temporal → temporalio}/workflow/execution_status.rb +1 -1
  207. data/lib/{temporal → temporalio}/workflow/id_reuse_policy.rb +6 -6
  208. data/lib/{temporal → temporalio}/workflow/query_reject_condition.rb +5 -5
  209. data/lib/temporalio.rb +12 -3
  210. data/temporalio.gemspec +7 -3
  211. metadata +79 -56
  212. data/bridge/sdk-core/bridge-ffi/Cargo.toml +0 -24
  213. data/bridge/sdk-core/bridge-ffi/LICENSE.txt +0 -23
  214. data/bridge/sdk-core/bridge-ffi/build.rs +0 -25
  215. data/bridge/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -249
  216. data/bridge/sdk-core/bridge-ffi/src/lib.rs +0 -825
  217. data/bridge/sdk-core/bridge-ffi/src/wrappers.rs +0 -211
  218. data/bridge/sdk-core/core/src/log_export.rs +0 -62
  219. data/bridge/sdk-core/core/src/worker/workflow/machines/mutable_side_effect_state_machine.rs +0 -127
  220. data/bridge/sdk-core/core/src/worker/workflow/machines/side_effect_state_machine.rs +0 -71
  221. data/bridge/sdk-core/protos/api_upstream/temporal/api/cluster/v1/message.proto +0 -83
  222. data/bridge/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -210
  223. data/bridge/sdk-core/sdk/src/conversions.rs +0 -8
  224. data/lib/gen/temporal/api/cluster/v1/message_pb.rb +0 -67
  225. data/lib/gen/temporal/api/enums/v1/cluster_pb.rb +0 -26
  226. data/lib/gen/temporal/api/update/v1/message_pb.rb +0 -26
  227. data/lib/temporal/bridge.rb +0 -14
  228. data/lib/temporal/failure_converter.rb +0 -8
  229. data/lib/temporal/payload_converter.rb +0 -14
  230. data/lib/temporal/runtime.rb +0 -22
  231. data/lib/temporal/version.rb +0 -3
  232. data/lib/temporal.rb +0 -8
@@ -1,4 +1,4 @@
1
- module Temporal
1
+ module Temporalio
2
2
  module PayloadCodec
3
3
  # @abstract Use this Interface for implementing your payload codecs.
4
4
  #
@@ -6,10 +6,10 @@ module Temporal
6
6
  class Base
7
7
  # Encode the given payloads.
8
8
  #
9
- # @param _payloads [Array<Temporal::Api::Common::V1::Payload>] Payloads to encode.
9
+ # @param _payloads [Array<Temporalio::Api::Common::V1::Payload>] Payloads to encode.
10
10
  # This value should not be mutated.
11
11
  #
12
- # @return [Array<Temporal::Api::Common::V1::Payload>] Encoded payloads. Note, this does not
12
+ # @return [Array<Temporalio::Api::Common::V1::Payload>] Encoded payloads. Note, this does not
13
13
  # have to be the same number as payloads given, but must be at least one and cannot be more
14
14
  # than was given.
15
15
  def encode(_payloads)
@@ -18,10 +18,10 @@ module Temporal
18
18
 
19
19
  # Decode the given payloads.
20
20
  #
21
- # @param _payloads [Array<Temporal::Api::Common::V1::Payload>] Payloads to decode. This value
21
+ # @param _payloads [Array<Temporalio::Api::Common::V1::Payload>] Payloads to decode. This value
22
22
  # should not be mutated.
23
23
  #
24
- # @return [Array<Temporal::Api::Common::V1::Payload>] Decoded payloads. Note, this does not
24
+ # @return [Array<Temporalio::Api::Common::V1::Payload>] Decoded payloads. Note, this does not
25
25
  # have to be the same number as payloads given, but must be at least one and cannot be more
26
26
  # than was given.
27
27
  def decode(_payloads)
@@ -1,4 +1,4 @@
1
- module Temporal
1
+ module Temporalio
2
2
  module PayloadConverter
3
3
  # @abstract Use this Interface for implementing your payload converter.
4
4
  class Base
@@ -6,14 +6,14 @@ module Temporal
6
6
  #
7
7
  # @param _data [any] Ruby value to be converted.
8
8
  #
9
- # @return [Temporal::Api::Common::V1::Payload]
9
+ # @return [Temporalio::Api::Common::V1::Payload]
10
10
  def to_payload(_data)
11
11
  raise NoMethodError, 'must implement #to_payload'
12
12
  end
13
13
 
14
14
  # Convert a proto Payload to a Ruby value.
15
15
  #
16
- # @param _payload [Temporal::Api::Common::V1::Payload] Proto Payload to be converted.
16
+ # @param _payload [Temporalio::Api::Common::V1::Payload] Proto Payload to be converted.
17
17
  #
18
18
  # @return [any]
19
19
  def from_payload(_payload)
@@ -1,7 +1,8 @@
1
- require 'temporal/payload_converter/encoding_base'
1
+ require 'temporalio/payload_converter/encoding_base'
2
2
 
3
- module Temporal
3
+ module Temporalio
4
4
  module PayloadConverter
5
+ # A payload converter for encoding/decoding byte strings.
5
6
  class Bytes < EncodingBase
6
7
  ENCODING = 'binary/plain'.freeze
7
8
 
@@ -16,7 +17,7 @@ module Temporal
16
17
  def to_payload(data)
17
18
  return nil unless data.is_a?(String) && data.encoding == Encoding::ASCII_8BIT
18
19
 
19
- Temporal::Api::Common::V1::Payload.new(
20
+ Temporalio::Api::Common::V1::Payload.new(
20
21
  metadata: { 'encoding' => ENCODING },
21
22
  data: data,
22
23
  )
@@ -1,12 +1,14 @@
1
- require 'temporal/payload_converter/base'
2
- require 'temporal/errors'
1
+ require 'temporalio/payload_converter/base'
2
+ require 'temporalio/errors'
3
3
 
4
- module Temporal
4
+ module Temporalio
5
5
  module PayloadConverter
6
+ # A payload converter for combining multiple payload converters together.
6
7
  class Composite < Base
7
- class ConverterNotFound < Temporal::Error; end
8
- class EncodingNotSet < Temporal::Error; end
8
+ class ConverterNotFound < Temporalio::Error; end
9
+ class EncodingNotSet < Temporalio::Error; end
9
10
 
11
+ # @param converters [Array<Temporalio::PayloadConverter::Base>] List of converters
10
12
  def initialize(*converters)
11
13
  super()
12
14
 
@@ -1,9 +1,9 @@
1
1
  require 'temporal/api/common/v1/message_pb'
2
2
 
3
- module Temporal
3
+ module Temporalio
4
4
  module PayloadConverter
5
5
  # @abstract Use this Interface for implementing an encoding payload converter.
6
- # This is used as a converter for the {Temporal::PayloadConverter::Composite}.
6
+ # This is used as a converter for the {Temporalio::PayloadConverter::Composite}.
7
7
  class EncodingBase
8
8
  # A mime-type for the converter's encoding.
9
9
  #
@@ -16,7 +16,7 @@ module Temporal
16
16
  #
17
17
  # @param _data [any] Ruby value to be converted.
18
18
  #
19
- # @return [Temporal::Api::Common::V1::Payload, nil] Return `nil` if the received value is not
19
+ # @return [Temporalio::Api::Common::V1::Payload, nil] Return `nil` if the received value is not
20
20
  # supported by this converter.
21
21
  def to_payload(_data)
22
22
  raise NoMethodError, 'must implement #to_payload'
@@ -24,7 +24,7 @@ module Temporal
24
24
 
25
25
  # Convert a proto Payload to a Ruby value.
26
26
  #
27
- # @param _payload [Temporal::Api::Common::V1::Payload] Proto Payload to be converted.
27
+ # @param _payload [Temporalio::Api::Common::V1::Payload] Proto Payload to be converted.
28
28
  #
29
29
  # @return [any]
30
30
  def from_payload(_payload)
@@ -1,8 +1,9 @@
1
1
  require 'json/ext'
2
- require 'temporal/payload_converter/encoding_base'
2
+ require 'temporalio/payload_converter/encoding_base'
3
3
 
4
- module Temporal
4
+ module Temporalio
5
5
  module PayloadConverter
6
+ # A payload converter for encoding/decoding JSON data.
6
7
  class JSON < EncodingBase
7
8
  ENCODING = 'json/plain'.freeze
8
9
 
@@ -15,7 +16,7 @@ module Temporal
15
16
  end
16
17
 
17
18
  def to_payload(data)
18
- Temporal::Api::Common::V1::Payload.new(
19
+ Temporalio::Api::Common::V1::Payload.new(
19
20
  metadata: { 'encoding' => ENCODING },
20
21
  data: ::JSON.generate(data).b,
21
22
  )
@@ -1,7 +1,8 @@
1
- require 'temporal/payload_converter/encoding_base'
1
+ require 'temporalio/payload_converter/encoding_base'
2
2
 
3
- module Temporal
3
+ module Temporalio
4
4
  module PayloadConverter
5
+ # A payload converter for encoding/decoding nils.
5
6
  class Nil < EncodingBase
6
7
  ENCODING = 'binary/null'.freeze
7
8
 
@@ -16,7 +17,7 @@ module Temporal
16
17
  def to_payload(data)
17
18
  return nil unless data.nil?
18
19
 
19
- Temporal::Api::Common::V1::Payload.new(
20
+ Temporalio::Api::Common::V1::Payload.new(
20
21
  metadata: { 'encoding' => ENCODING },
21
22
  )
22
23
  end
@@ -0,0 +1,14 @@
1
+ require 'temporalio/payload_converter/bytes'
2
+ require 'temporalio/payload_converter/composite'
3
+ require 'temporalio/payload_converter/json'
4
+ require 'temporalio/payload_converter/nil'
5
+
6
+ module Temporalio
7
+ module PayloadConverter
8
+ DEFAULT = Temporalio::PayloadConverter::Composite.new(
9
+ Temporalio::PayloadConverter::Nil.new,
10
+ Temporalio::PayloadConverter::Bytes.new,
11
+ Temporalio::PayloadConverter::JSON.new,
12
+ )
13
+ end
14
+ end
@@ -1,12 +1,12 @@
1
1
  require 'temporal/api/common/v1/message_pb'
2
- require 'temporal/errors'
2
+ require 'temporalio/errors'
3
3
 
4
- module Temporal
4
+ module Temporalio
5
5
  # Options for retrying workflows and activities.
6
6
  #
7
7
  # @see https://docs.temporal.io/application-development/features/#workflow-retry-policy
8
8
  class RetryPolicy
9
- class Invalid < Temporal::Error; end
9
+ class Invalid < Temporalio::Error; end
10
10
 
11
11
  # @return [Integer] Backoff interval for the first retry.
12
12
  attr_reader :initial_interval
@@ -70,7 +70,7 @@ module Temporal
70
70
  end
71
71
 
72
72
  def to_proto
73
- Temporal::Api::Common::V1::RetryPolicy.new(
73
+ Temporalio::Api::Common::V1::RetryPolicy.new(
74
74
  initial_interval: Google::Protobuf::Duration.new(seconds: initial_interval),
75
75
  backoff_coefficient: backoff,
76
76
  maximum_interval: max_interval ? Google::Protobuf::Duration.new(seconds: max_interval) : nil,
@@ -1,4 +1,4 @@
1
- module Temporal
1
+ module Temporalio
2
2
  # Current retry state of the workflow/activity during error.
3
3
  module RetryState
4
4
  STATES = [
@@ -0,0 +1,25 @@
1
+ require 'singleton'
2
+ require 'temporalio/bridge'
3
+ require 'temporalio/worker/reactor'
4
+
5
+ module Temporalio
6
+ # @api private
7
+ class Runtime
8
+ include Singleton
9
+
10
+ attr_reader :core_runtime, :reactor
11
+
12
+ def initialize
13
+ @core_runtime = Temporalio::Bridge::Runtime.init
14
+ @reactor = Temporalio::Worker::Reactor.new
15
+ end
16
+
17
+ def ensure_callback_loop
18
+ return if @thread
19
+
20
+ @thread = Thread.new do
21
+ core_runtime.run_callback_loop
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,5 +1,5 @@
1
- module Temporal
2
- # Type of timeout for {Temporal::TimeoutError}.
1
+ module Temporalio
2
+ # Type of timeout for {Temporalio::TimeoutError}.
3
3
  module TimeoutType
4
4
  TYPES = [
5
5
  START_TO_CLOSE = :START_TO_CLOSE,
@@ -0,0 +1,3 @@
1
+ module Temporalio
2
+ VERSION = '0.0.2'.freeze
3
+ end
@@ -0,0 +1,92 @@
1
+ require 'google/protobuf/well_known_types'
2
+ require 'temporalio/activity/context'
3
+ require 'temporalio/activity/info'
4
+ require 'temporalio/error/failure'
5
+ require 'temporalio/errors'
6
+
7
+ module Temporalio
8
+ class Worker
9
+ # The main class for handling activity processing. It is expected to be executed from
10
+ # some threaded or async executor's context since methods called here might be blocking
11
+ # and this should not affect the main worker reactor.
12
+ #
13
+ # @api private
14
+ class ActivityRunner
15
+ def initialize(activity_class, start, task_queue, task_token, worker, converter)
16
+ @activity_class = activity_class
17
+ @start = start
18
+ @task_queue = task_queue
19
+ @task_token = task_token
20
+ @worker = worker
21
+ @converter = converter
22
+ end
23
+
24
+ def run
25
+ activity = activity_class.new(context)
26
+ input = converter.from_payload_array(start.input.to_a)
27
+
28
+ result = activity.execute(*input)
29
+
30
+ converter.to_payload(result)
31
+ rescue StandardError => e
32
+ # Temporal server ignores cancellation failures that were not requested by the server.
33
+ # However within the SDK cancellations are also used during the worker shutdown. In order
34
+ # to provide a seamless handling experience (same error raised within the Activity) we are
35
+ # using the ActivityCancelled error and then swapping it with a CancelledError here.
36
+ #
37
+ # In the future this will be handled by the SDK Core — https://github.com/temporalio/sdk-core/issues/461
38
+ if e.is_a?(Temporalio::Error::ActivityCancelled) && e.by_request?
39
+ e = Temporalio::Error::CancelledError.new(e.message)
40
+ end
41
+
42
+ converter.to_failure(e)
43
+ end
44
+
45
+ def cancel(reason, by_request:)
46
+ context.cancel(reason, by_request: by_request)
47
+ end
48
+
49
+ private
50
+
51
+ attr_reader :activity_class, :start, :task_queue, :task_token, :worker, :converter
52
+
53
+ def context
54
+ return @context if @context
55
+
56
+ heartbeat_proc = ->(*details) { heartbeat(*details) }
57
+ @context = Temporalio::Activity::Context.new(
58
+ generate_activity_info,
59
+ heartbeat_proc,
60
+ shielded: activity_class._shielded,
61
+ )
62
+ end
63
+
64
+ def generate_activity_info
65
+ Temporalio::Activity::Info.new(
66
+ activity_id: start.activity_id,
67
+ activity_type: start.activity_type,
68
+ attempt: start.attempt,
69
+ current_attempt_scheduled_time: start.current_attempt_scheduled_time&.to_time,
70
+ heartbeat_details: converter.from_payload_array(start.heartbeat_details.to_a),
71
+ heartbeat_timeout: start.heartbeat_timeout&.to_f,
72
+ local: !start.is_local.nil?,
73
+ schedule_to_close_timeout: start.schedule_to_close_timeout&.to_f,
74
+ scheduled_time: start.scheduled_time&.to_time,
75
+ start_to_close_timeout: start.start_to_close_timeout&.to_f,
76
+ started_time: start.started_time&.to_time,
77
+ task_queue: task_queue,
78
+ task_token: task_token,
79
+ workflow_id: start.workflow_execution&.workflow_id,
80
+ workflow_namespace: start.workflow_namespace,
81
+ workflow_run_id: start.workflow_execution&.run_id,
82
+ workflow_type: start.workflow_type,
83
+ ).freeze
84
+ end
85
+
86
+ def heartbeat(*details)
87
+ payloads = converter.to_payload_array(details)
88
+ worker.record_activity_heartbeat(task_token, payloads)
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,138 @@
1
+ require 'temporalio/error/failure'
2
+ require 'temporalio/errors'
3
+ require 'temporalio/worker/activity_runner'
4
+ require 'temporalio/worker/sync_worker'
5
+
6
+ module Temporalio
7
+ class Worker
8
+ # @api private
9
+ class ActivityWorker
10
+ def initialize(task_queue, core_worker, activities, converter, executor, graceful_timeout)
11
+ @task_queue = task_queue
12
+ @worker = SyncWorker.new(core_worker)
13
+ @activities = prepare_activities(activities)
14
+ @converter = converter
15
+ @executor = executor
16
+ @graceful_timeout = graceful_timeout
17
+ @running_activities = {}
18
+ @cancellations = []
19
+ @drain_queue = Queue.new
20
+ end
21
+
22
+ def run(reactor)
23
+ # @type var outstanding_tasks: Array[Async::Task]
24
+ outstanding_tasks = []
25
+
26
+ loop do
27
+ activity_task = worker.poll_activity_task
28
+ outstanding_tasks << reactor.async do |async_task|
29
+ if activity_task.start
30
+ handle_start_activity(activity_task.task_token, activity_task.start)
31
+ elsif activity_task.cancel
32
+ handle_cancel_activity(activity_task.task_token, activity_task.cancel)
33
+ end
34
+ ensure
35
+ outstanding_tasks.delete(async_task)
36
+ end
37
+ end
38
+ rescue Temporalio::Bridge::Error::WorkerShutdown
39
+ # No need to re-raise this error, it's a part of a normal shutdown
40
+ 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
49
+ end
50
+ end
51
+
52
+ outstanding_tasks.each(&:wait)
53
+ cancelation_task&.stop # all tasks completed, stop cancellations
54
+ drain_queue.close
55
+ end
56
+ end
57
+
58
+ def drain
59
+ drain_queue.pop
60
+ end
61
+
62
+ private
63
+
64
+ attr_reader :task_queue, :worker, :activities, :converter, :executor, :graceful_timeout,
65
+ :running_activities, :cancellations, :drain_queue
66
+
67
+ def prepare_activities(activities)
68
+ activities.each_with_object({}) do |activity, result|
69
+ unless activity.ancestors.include?(Temporalio::Activity)
70
+ raise ArgumentError, 'Activity must be a subclass of Temporalio::Activity'
71
+ end
72
+
73
+ if result[activity._name]
74
+ raise ArgumentError, "More than one activity named #{activity._name}"
75
+ end
76
+
77
+ result[activity._name] = activity
78
+ result
79
+ end
80
+ end
81
+
82
+ def lookup_activity(activity_type)
83
+ activities.fetch(activity_type) do
84
+ activity_names = activities.keys.sort.join(', ')
85
+ raise Temporalio::Error::ApplicationError.new(
86
+ "Activity #{activity_type} is not registered on this worker, available activities: #{activity_names}",
87
+ type: 'NotFoundError',
88
+ )
89
+ end
90
+ end
91
+
92
+ def run_activity(token, start)
93
+ activity_class = lookup_activity(start.activity_type)
94
+ runner = ActivityRunner.new(activity_class, start, task_queue, token, worker, converter)
95
+ running_activities[token] = runner
96
+ queue = Queue.new
97
+
98
+ executor.schedule do
99
+ queue << runner.run
100
+ end
101
+
102
+ queue.pop
103
+ rescue StandardError => e
104
+ converter.to_failure(e)
105
+ end
106
+
107
+ def handle_start_activity(task_token, start)
108
+ result = run_activity(task_token, start)
109
+
110
+ case result
111
+ when Temporalio::Api::Common::V1::Payload
112
+ worker.complete_activity_task_with_success(task_token, result)
113
+ when Temporalio::Api::Failure::V1::Failure
114
+ # only respond with a cancellation when it was requested, otherwise it's a regular failure
115
+ if result.canceled_failure_info && cancellations.include?(task_token)
116
+ worker.complete_activity_task_with_cancellation(task_token, result)
117
+ else
118
+ worker.complete_activity_task_with_failure(task_token, result)
119
+ end
120
+ end
121
+
122
+ running_activities.delete(task_token)
123
+ cancellations.delete(task_token)
124
+ end
125
+
126
+ def handle_cancel_activity(task_token, _cancel)
127
+ runner = running_activities.fetch(task_token) do
128
+ # TODO: Use logger instead when implemented
129
+ warn "Cannot find activity to cancel for token #{task_token}"
130
+ return # early escape
131
+ end
132
+
133
+ cancellations << task_token
134
+ runner&.cancel('Activity cancellation requested', by_request: true)
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,46 @@
1
+ require 'async'
2
+
3
+ module Temporalio
4
+ class Worker
5
+ # A shared async reactor.
6
+ #
7
+ # This class allows multiple workers to access the same Async reactor
8
+ # without forcing the SDK users to wrap their execution in an Async block. This
9
+ # is handled using a queue that is polled from within a running Async reactor,
10
+ # so all the blocks end up being executed within it.
11
+ #
12
+ # @api private
13
+ class Reactor
14
+ def initialize
15
+ @queue = Queue.new
16
+ @thread = nil
17
+ @mutex = Mutex.new
18
+ end
19
+
20
+ def async(&block)
21
+ ensure_reactor_thread
22
+ queue << block
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :queue, :mutex
28
+
29
+ def ensure_reactor_thread
30
+ mutex.synchronize do
31
+ @thread ||= Thread.new { run_loop }
32
+ end
33
+ end
34
+
35
+ def run_loop
36
+ reactor = Async::Reactor.new
37
+ reactor.run do |task|
38
+ loop do
39
+ block = queue.pop
40
+ task.async { |subtask| block.call(subtask) }
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,63 @@
1
+ require 'temporalio/errors'
2
+
3
+ module Temporalio
4
+ class Worker
5
+ # A class used to manage the lifecycle of running any number of workers.
6
+ #
7
+ # @api private
8
+ class Runner
9
+ def initialize(*workers)
10
+ if workers.empty?
11
+ raise ArgumentError, 'Must be initialized with at least one worker'
12
+ end
13
+
14
+ @workers = workers
15
+ @mutex = Mutex.new
16
+ @started = false
17
+ @shutdown = false
18
+ end
19
+
20
+ def run(&block)
21
+ @thread = Thread.current
22
+ @started = true
23
+ workers.each { |worker| worker.start(self) }
24
+
25
+ block ? block.call : sleep
26
+ rescue Temporalio::Error::WorkerShutdown
27
+ # Explicit shutdown requested, no need to raise
28
+ ensure
29
+ @shutdown = true
30
+ shutdown_workers
31
+ end
32
+
33
+ def shutdown(exception = Temporalio::Error::WorkerShutdown.new('Manual shutdown'))
34
+ mutex.synchronize do
35
+ return unless running?
36
+
37
+ @shutdown = true
38
+ end
39
+
40
+ # propagate shutdown to the running thread
41
+ thread&.raise(exception)
42
+ end
43
+
44
+ private
45
+
46
+ attr_reader :workers, :mutex, :thread
47
+
48
+ def running?
49
+ @started && !@shutdown
50
+ end
51
+
52
+ def shutdown_workers
53
+ # Protect shutdown from any outside raises
54
+ Thread.handle_interrupt(StandardError => :never) do
55
+ workers.map do |worker|
56
+ # Shut down each worker (and wait for it) concurrently in separate threads
57
+ Thread.new { worker.shutdown }
58
+ end.each(&:join)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,88 @@
1
+ require 'temporal/sdk/core/activity_task/activity_task_pb'
2
+ require 'temporal/sdk/core/core_interface_pb'
3
+
4
+ module Temporalio
5
+ class Worker
6
+ # This is a wrapper class for the Core Worker (provided via the Bridge) to abstract
7
+ # away its async nature allowing other modules/classes to interact with it without
8
+ # any callbacks (simplifying the code).
9
+ #
10
+ # CAUTION: This class will block the thread its running in unless it is used from
11
+ # within an Async reactor.
12
+ #
13
+ # @api private
14
+ class SyncWorker
15
+ def initialize(core_worker)
16
+ @core_worker = core_worker
17
+ end
18
+
19
+ def poll_activity_task
20
+ with_queue do |done|
21
+ core_worker.poll_activity_task do |task, error|
22
+ done.call(task && Coresdk::ActivityTask::ActivityTask.decode(task), error)
23
+ end
24
+ end
25
+ end
26
+
27
+ def complete_activity_task_with_success(task_token, payload)
28
+ result = Coresdk::ActivityResult::ActivityExecutionResult.new(
29
+ completed: Coresdk::ActivityResult::Success.new(result: payload),
30
+ )
31
+
32
+ complete_activity_task(task_token, result)
33
+ end
34
+
35
+ def complete_activity_task_with_failure(task_token, failure)
36
+ result = Coresdk::ActivityResult::ActivityExecutionResult.new(
37
+ failed: Coresdk::ActivityResult::Failure.new(failure: failure),
38
+ )
39
+
40
+ complete_activity_task(task_token, result)
41
+ end
42
+
43
+ def complete_activity_task_with_cancellation(task_token, failure)
44
+ result = Coresdk::ActivityResult::ActivityExecutionResult.new(
45
+ cancelled: Coresdk::ActivityResult::Cancellation.new(failure: failure),
46
+ )
47
+
48
+ complete_activity_task(task_token, result)
49
+ end
50
+
51
+ def record_activity_heartbeat(task_token, payloads)
52
+ proto = Coresdk::ActivityHeartbeat.new(
53
+ task_token: task_token,
54
+ details: payloads,
55
+ )
56
+ encoded_proto = Coresdk::ActivityHeartbeat.encode(proto)
57
+
58
+ core_worker.record_activity_heartbeat(encoded_proto)
59
+ end
60
+
61
+ private
62
+
63
+ attr_reader :core_worker
64
+
65
+ def with_queue(&block)
66
+ queue = Queue.new
67
+ done = ->(result, error = nil) { queue << [result, error] }
68
+ block.call(done)
69
+ (result, exception) = queue.pop
70
+ raise exception if exception
71
+
72
+ result
73
+ end
74
+
75
+ def complete_activity_task(task_token, result)
76
+ proto = Coresdk::ActivityTaskCompletion.new(
77
+ task_token: task_token,
78
+ result: result,
79
+ )
80
+ encoded_proto = Coresdk::ActivityTaskCompletion.encode(proto)
81
+
82
+ with_queue do |done|
83
+ core_worker.complete_activity_task(encoded_proto, &done)
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end