temporal-ruby 0.0.0 → 0.0.1.pre.pre1

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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +19 -42
  3. data/lib/gen/temporal/api/command/v1/message_pb.rb +146 -0
  4. data/lib/gen/temporal/api/common/v1/message_pb.rb +67 -0
  5. data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +35 -0
  6. data/lib/gen/temporal/api/enums/v1/common_pb.rb +34 -0
  7. data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +62 -0
  8. data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +60 -0
  9. data/lib/gen/temporal/api/enums/v1/namespace_pb.rb +31 -0
  10. data/lib/gen/temporal/api/enums/v1/query_pb.rb +31 -0
  11. data/lib/gen/temporal/api/enums/v1/task_queue_pb.rb +30 -0
  12. data/lib/gen/temporal/api/enums/v1/workflow_pb.rb +82 -0
  13. data/lib/gen/temporal/api/errordetails/v1/message_pb.rb +55 -0
  14. data/lib/gen/temporal/api/failure/v1/message_pb.rb +81 -0
  15. data/lib/gen/temporal/api/filter/v1/message_pb.rb +38 -0
  16. data/lib/gen/temporal/api/history/v1/message_pb.rb +423 -0
  17. data/lib/gen/temporal/api/namespace/v1/message_pb.rb +55 -0
  18. data/lib/gen/temporal/api/query/v1/message_pb.rb +36 -0
  19. data/lib/gen/temporal/api/replication/v1/message_pb.rb +27 -0
  20. data/lib/gen/temporal/api/taskqueue/v1/message_pb.rb +60 -0
  21. data/lib/gen/temporal/api/version/v1/message_pb.rb +28 -0
  22. data/lib/gen/temporal/api/workflow/v1/message_pb.rb +83 -0
  23. data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +538 -0
  24. data/lib/gen/temporal/api/workflowservice/v1/service_pb.rb +19 -0
  25. data/lib/gen/temporal/api/workflowservice/v1/service_services_pb.rb +223 -0
  26. data/lib/temporal-ruby.rb +1 -0
  27. data/lib/temporal.rb +137 -0
  28. data/lib/temporal/activity.rb +33 -0
  29. data/lib/temporal/activity/async_token.rb +34 -0
  30. data/lib/temporal/activity/context.rb +64 -0
  31. data/lib/temporal/activity/poller.rb +79 -0
  32. data/lib/temporal/activity/task_processor.rb +78 -0
  33. data/lib/temporal/activity/workflow_convenience_methods.rb +41 -0
  34. data/lib/temporal/client.rb +21 -0
  35. data/lib/temporal/client/errors.rb +8 -0
  36. data/lib/temporal/client/grpc_client.rb +345 -0
  37. data/lib/temporal/client/serializer.rb +31 -0
  38. data/lib/temporal/client/serializer/base.rb +23 -0
  39. data/lib/temporal/client/serializer/cancel_timer.rb +19 -0
  40. data/lib/temporal/client/serializer/complete_workflow.rb +20 -0
  41. data/lib/temporal/client/serializer/fail_workflow.rb +20 -0
  42. data/lib/temporal/client/serializer/failure.rb +29 -0
  43. data/lib/temporal/client/serializer/payload.rb +25 -0
  44. data/lib/temporal/client/serializer/record_marker.rb +23 -0
  45. data/lib/temporal/client/serializer/request_activity_cancellation.rb +19 -0
  46. data/lib/temporal/client/serializer/schedule_activity.rb +53 -0
  47. data/lib/temporal/client/serializer/start_child_workflow.rb +51 -0
  48. data/lib/temporal/client/serializer/start_timer.rb +20 -0
  49. data/lib/temporal/concerns/executable.rb +37 -0
  50. data/lib/temporal/concerns/typed.rb +40 -0
  51. data/lib/temporal/configuration.rb +44 -0
  52. data/lib/temporal/errors.rb +38 -0
  53. data/lib/temporal/executable_lookup.rb +25 -0
  54. data/lib/temporal/execution_options.rb +35 -0
  55. data/lib/temporal/json.rb +18 -0
  56. data/lib/temporal/metadata.rb +68 -0
  57. data/lib/temporal/metadata/activity.rb +27 -0
  58. data/lib/temporal/metadata/base.rb +17 -0
  59. data/lib/temporal/metadata/workflow.rb +22 -0
  60. data/lib/temporal/metadata/workflow_task.rb +25 -0
  61. data/lib/temporal/metrics.rb +37 -0
  62. data/lib/temporal/metrics_adapters/log.rb +33 -0
  63. data/lib/temporal/metrics_adapters/null.rb +9 -0
  64. data/lib/temporal/middleware/chain.rb +30 -0
  65. data/lib/temporal/middleware/entry.rb +9 -0
  66. data/lib/temporal/retry_policy.rb +27 -0
  67. data/lib/temporal/saga/concern.rb +23 -0
  68. data/lib/temporal/saga/result.rb +22 -0
  69. data/lib/temporal/saga/saga.rb +24 -0
  70. data/lib/temporal/testing.rb +50 -0
  71. data/lib/temporal/testing/future_registry.rb +27 -0
  72. data/lib/temporal/testing/local_activity_context.rb +17 -0
  73. data/lib/temporal/testing/local_workflow_context.rb +178 -0
  74. data/lib/temporal/testing/temporal_override.rb +121 -0
  75. data/lib/temporal/testing/workflow_execution.rb +44 -0
  76. data/lib/temporal/testing/workflow_override.rb +36 -0
  77. data/lib/temporal/thread_local_context.rb +14 -0
  78. data/lib/temporal/thread_pool.rb +63 -0
  79. data/lib/temporal/types.rb +7 -0
  80. data/lib/temporal/uuid.rb +19 -0
  81. data/lib/temporal/version.rb +1 -1
  82. data/lib/temporal/worker.rb +88 -0
  83. data/lib/temporal/workflow.rb +42 -0
  84. data/lib/temporal/workflow/command.rb +39 -0
  85. data/lib/temporal/workflow/command_state_machine.rb +48 -0
  86. data/lib/temporal/workflow/context.rb +243 -0
  87. data/lib/temporal/workflow/convenience_methods.rb +34 -0
  88. data/lib/temporal/workflow/dispatcher.rb +31 -0
  89. data/lib/temporal/workflow/execution_info.rb +51 -0
  90. data/lib/temporal/workflow/executor.rb +45 -0
  91. data/lib/temporal/workflow/future.rb +77 -0
  92. data/lib/temporal/workflow/history.rb +76 -0
  93. data/lib/temporal/workflow/history/event.rb +69 -0
  94. data/lib/temporal/workflow/history/event_target.rb +75 -0
  95. data/lib/temporal/workflow/history/window.rb +40 -0
  96. data/lib/temporal/workflow/poller.rb +67 -0
  97. data/lib/temporal/workflow/replay_aware_logger.rb +36 -0
  98. data/lib/temporal/workflow/state_manager.rb +342 -0
  99. data/lib/temporal/workflow/task_processor.rb +78 -0
  100. data/rbi/temporal-ruby.rbi +43 -0
  101. data/temporal.gemspec +10 -2
  102. metadata +186 -6
@@ -0,0 +1,31 @@
1
+ require 'temporal/workflow/command'
2
+ require 'temporal/client/serializer/schedule_activity'
3
+ require 'temporal/client/serializer/start_child_workflow'
4
+ require 'temporal/client/serializer/request_activity_cancellation'
5
+ require 'temporal/client/serializer/record_marker'
6
+ require 'temporal/client/serializer/start_timer'
7
+ require 'temporal/client/serializer/cancel_timer'
8
+ require 'temporal/client/serializer/complete_workflow'
9
+ require 'temporal/client/serializer/fail_workflow'
10
+
11
+ module Temporal
12
+ module Client
13
+ module Serializer
14
+ SERIALIZERS_MAP = {
15
+ Workflow::Command::ScheduleActivity => Serializer::ScheduleActivity,
16
+ Workflow::Command::StartChildWorkflow => Serializer::StartChildWorkflow,
17
+ Workflow::Command::RequestActivityCancellation => Serializer::RequestActivityCancellation,
18
+ Workflow::Command::RecordMarker => Serializer::RecordMarker,
19
+ Workflow::Command::StartTimer => Serializer::StartTimer,
20
+ Workflow::Command::CancelTimer => Serializer::CancelTimer,
21
+ Workflow::Command::CompleteWorkflow => Serializer::CompleteWorkflow,
22
+ Workflow::Command::FailWorkflow => Serializer::FailWorkflow
23
+ }.freeze
24
+
25
+ def self.serialize(object)
26
+ serializer = SERIALIZERS_MAP[object.class]
27
+ serializer.new(object).to_proto
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+ require 'oj'
2
+ require 'gen/temporal/api/common/v1/message_pb'
3
+ require 'gen/temporal/api/command/v1/message_pb'
4
+
5
+ module Temporal
6
+ module Client
7
+ module Serializer
8
+ class Base
9
+ def initialize(object)
10
+ @object = object
11
+ end
12
+
13
+ def to_proto
14
+ raise NotImplementedError, 'serializer needs to implement #to_proto'
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :object
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ require 'temporal/client/serializer/base'
2
+
3
+ module Temporal
4
+ module Client
5
+ module Serializer
6
+ class CancelTimer < Base
7
+ def to_proto
8
+ Temporal::Api::Decision::V1::Command.new(
9
+ command_type: Temporal::Api::Enums::V1::CommandType::COMMAND_TYPE_CANCEL_TIMER,
10
+ cancel_timer_command_attributes:
11
+ Temporal::Api::Decision::V1::CancelTimerCommandAttributes.new(
12
+ timer_id: object.timer_id.to_s
13
+ )
14
+ )
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ require 'temporal/client/serializer/base'
2
+ require 'temporal/client/serializer/payload'
3
+
4
+ module Temporal
5
+ module Client
6
+ module Serializer
7
+ class CompleteWorkflow < Base
8
+ def to_proto
9
+ Temporal::Api::Decision::V1::Command.new(
10
+ command_type: Temporal::Api::Enums::V1::CommandType::COMMAND_TYPE_COMPLETE_WORKFLOW_EXECUTION,
11
+ complete_workflow_execution_command_attributes:
12
+ Temporal::Api::Decision::V1::CompleteWorkflowExecutionCommandAttributes.new(
13
+ result: Payload.new(object.result).to_proto
14
+ )
15
+ )
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ require 'temporal/client/serializer/base'
2
+ require 'temporal/json'
3
+
4
+ module Temporal
5
+ module Client
6
+ module Serializer
7
+ class FailWorkflow < Base
8
+ def to_proto
9
+ Temporal::Api::Decision::V1::Command.new(
10
+ command_type: Temporal::Api::Enums::V1::CommandType::COMMAND_TYPE_FAIL_WORKFLOW_EXECUTION,
11
+ fail_workflow_execution_command_attributes:
12
+ Temporal::Api::Decision::V1::FailWorkflowExecutionCommandAttributes.new(
13
+ failure: Failure.new(object.exception).to_proto
14
+ )
15
+ )
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,29 @@
1
+ require 'temporal/client/serializer/base'
2
+ require 'temporal/json'
3
+
4
+ module Temporal
5
+ module Client
6
+ module Serializer
7
+ class Failure < Base
8
+ def to_proto
9
+ Temporal::Api::Failure::V1::Failure.new(
10
+ message: object.message,
11
+ stack_trace: stack_trace_from(object.backtrace),
12
+ application_failure_info: Temporal::Api::Failure::V1::ApplicationFailureInfo.new(
13
+ type: object.class.name,
14
+ details: Payload.new(object.message).to_proto
15
+ )
16
+ )
17
+ end
18
+
19
+ private
20
+
21
+ def stack_trace_from(backtrace)
22
+ return unless backtrace
23
+
24
+ backtrace.join("\n")
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ require 'temporal/client/serializer/base'
2
+ require 'temporal/json'
3
+
4
+ module Temporal
5
+ module Client
6
+ module Serializer
7
+ class Payload < Base
8
+ JSON_ENCODING = 'json/plain'.freeze
9
+
10
+ def to_proto
11
+ return if object.nil?
12
+
13
+ Temporal::Api::Common::V1::Payloads.new(
14
+ payloads: [
15
+ Temporal::Api::Common::V1::Payload.new(
16
+ metadata: { 'encoding' => JSON_ENCODING },
17
+ data: JSON.serialize(object)
18
+ )
19
+ ]
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,23 @@
1
+ require 'temporal/client/serializer/base'
2
+ require 'temporal/client/serializer/payload'
3
+
4
+ module Temporal
5
+ module Client
6
+ module Serializer
7
+ class RecordMarker < Base
8
+ def to_proto
9
+ Temporal::Api::Decision::V1::Command.new(
10
+ command_type: Temporal::Api::Enums::V1::CommandType::COMMAND_TYPE_RECORD_MARKER,
11
+ record_marker_command_attributes:
12
+ Temporal::Api::Decision::V1::RecordMarkerCommandAttributes.new(
13
+ marker_name: object.name,
14
+ details: {
15
+ 'data' => Payload.new(object.details).to_proto
16
+ }
17
+ )
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ require 'temporal/client/serializer/base'
2
+
3
+ module Temporal
4
+ module Client
5
+ module Serializer
6
+ class RequestActivityCancellation < Base
7
+ def to_proto
8
+ Temporal::Api::Decision::V1::Command.new(
9
+ command_type: Temporal::Api::Enums::V1::CommandType::COMMAND_TYPE_REQUEST_CANCEL_ACTIVITY_TASK,
10
+ request_cancel_activity_task_command_attributes:
11
+ Temporal::Api::Decision::V1::RequestCancelActivityTaskCommandAttributes.new(
12
+ scheduled_event_id: object.activity_id.to_i
13
+ )
14
+ )
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,53 @@
1
+ require 'temporal/client/serializer/base'
2
+ require 'temporal/client/serializer/payload'
3
+
4
+ module Temporal
5
+ module Client
6
+ module Serializer
7
+ class ScheduleActivity < Base
8
+ def to_proto
9
+ Temporal::Api::Decision::V1::Command.new(
10
+ command_type: Temporal::Api::Enums::V1::CommandType::COMMAND_TYPE_SCHEDULE_ACTIVITY_TASK,
11
+ schedule_activity_task_command_attributes:
12
+ Temporal::Api::Decision::V1::ScheduleActivityTaskCommandAttributes.new(
13
+ activity_id: object.activity_id.to_s,
14
+ activity_type: Temporal::Api::Common::V1::ActivityType.new(name: object.activity_type),
15
+ input: Payload.new(object.input).to_proto,
16
+ namespace: object.namespace,
17
+ task_queue: Temporal::Api::TaskQueue::V1::TaskQueue.new(name: object.task_queue),
18
+ schedule_to_close_timeout: object.timeouts[:schedule_to_close],
19
+ schedule_to_start_timeout: object.timeouts[:schedule_to_start],
20
+ start_to_close_timeout: object.timeouts[:start_to_close],
21
+ heartbeat_timeout: object.timeouts[:heartbeat],
22
+ retry_policy: serialize_retry_policy(object.retry_policy),
23
+ header: serialize_headers(object.headers)
24
+ )
25
+ )
26
+ end
27
+
28
+ private
29
+
30
+ def serialize_retry_policy(retry_policy)
31
+ return unless retry_policy
32
+
33
+ non_retriable_errors = Array(retry_policy.non_retriable_errors).map(&:name)
34
+ options = {
35
+ initial_interval: retry_policy.interval,
36
+ backoff_coefficient: retry_policy.backoff,
37
+ maximum_interval: retry_policy.max_interval,
38
+ maximum_attempts: retry_policy.max_attempts,
39
+ non_retryable_error_types: non_retriable_errors
40
+ }.compact
41
+
42
+ Temporal::Api::Common::V1::RetryPolicy.new(options)
43
+ end
44
+
45
+ def serialize_headers(headers)
46
+ return unless headers
47
+
48
+ Temporal::Api::Common::V1::Header.new(fields: object.headers)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,51 @@
1
+ require 'temporal/client/serializer/base'
2
+ require 'temporal/client/serializer/payload'
3
+
4
+ module Temporal
5
+ module Client
6
+ module Serializer
7
+ class StartChildWorkflow < Base
8
+ def to_proto
9
+ Temporal::Api::Decision::V1::Command.new(
10
+ command_type: Temporal::Api::Enums::V1::CommandType::COMMAND_TYPE_START_CHILD_WORKFLOW_EXECUTION,
11
+ start_child_workflow_execution_command_attributes:
12
+ Temporal::Api::Decision::V1::StartChildWorkflowExecutionCommandAttributes.new(
13
+ namespace: object.namespace,
14
+ workflow_id: object.workflow_id.to_s,
15
+ workflow_type: Temporal::Api::Common::V1::WorkflowType.new(name: object.workflow_type),
16
+ task_queue: Temporal::Api::TaskQueue::V1::TaskQueue.new(name: object.task_queue),
17
+ input: Payload.new(object.input).to_proto,
18
+ workflow_execution_timeout: object.timeouts[:execution],
19
+ workflow_task_timeout: object.timeouts[:task],
20
+ retry_policy: serialize_retry_policy(object.retry_policy),
21
+ header: serialize_headers(object.headers)
22
+ )
23
+ )
24
+ end
25
+
26
+ private
27
+
28
+ def serialize_retry_policy(retry_policy)
29
+ return unless retry_policy
30
+
31
+ non_retriable_errors = Array(retry_policy.non_retriable_errors).map(&:name)
32
+ options = {
33
+ initial_interval: retry_policy.interval,
34
+ backoff_coefficient: retry_policy.backoff,
35
+ maximum_interval: retry_policy.max_interval,
36
+ maximum_attempts: retry_policy.max_attempts,
37
+ non_retriable_error_reasons: non_retriable_errors,
38
+ }.compact
39
+
40
+ Temporal::Api::Common::V1::RetryPolicy.new(options)
41
+ end
42
+
43
+ def serialize_headers(headers)
44
+ return unless headers
45
+
46
+ Temporal::Api::Common::V1::Header.new(fields: object.headers)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,20 @@
1
+ require 'temporal/client/serializer/base'
2
+
3
+ module Temporal
4
+ module Client
5
+ module Serializer
6
+ class StartTimer < Base
7
+ def to_proto
8
+ Temporal::Api::Decision::V1::Command.new(
9
+ command_type: Temporal::Api::Enums::V1::CommandType::COMMAND_TYPE_START_TIMER,
10
+ start_timer_command_attributes:
11
+ Temporal::Api::Decision::V1::StartTimerCommandAttributes.new(
12
+ timer_id: object.timer_id.to_s,
13
+ start_to_fire_timeout: object.timeout
14
+ )
15
+ )
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,37 @@
1
+ require 'temporal/retry_policy'
2
+
3
+ module Temporal
4
+ module Concerns
5
+ module Executable
6
+ def namespace(*args)
7
+ return @namespace if args.empty?
8
+ @namespace = args.first
9
+ end
10
+
11
+ def task_queue(*args)
12
+ return @task_queue if args.empty?
13
+ @task_queue = args.first
14
+ end
15
+
16
+ def task_list(*args)
17
+ task_queue(*args)
18
+ end
19
+
20
+ def retry_policy(*args)
21
+ return @retry_policy if args.empty?
22
+ @retry_policy = Temporal::RetryPolicy.new(args.first)
23
+ @retry_policy.validate!
24
+ end
25
+
26
+ def timeouts(*args)
27
+ return @timeouts if args.empty?
28
+ @timeouts = args.first
29
+ end
30
+
31
+ def headers(*args)
32
+ return @headers if args.empty?
33
+ @headers = args.first
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,40 @@
1
+ require 'dry-struct'
2
+ require 'temporal/types'
3
+
4
+ module Temporal
5
+ module Concerns
6
+ module Typed
7
+ def self.included(base)
8
+ base.extend ClassMethods
9
+ end
10
+
11
+ module ClassMethods
12
+ attr_reader :input_class
13
+
14
+ def execute_in_context(context, input)
15
+ input = input_class[*input] if input_class
16
+
17
+ super(context, input)
18
+ end
19
+
20
+ def input(klass = nil, &block)
21
+ if klass
22
+ unless klass.is_a?(Dry::Types::Type)
23
+ raise 'Unsupported input class. Use one of the provided Temporal::Types'
24
+ end
25
+ @input_class = klass
26
+ else
27
+ @input_class = generate_struct
28
+ @input_class.instance_eval(&block)
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def generate_struct
35
+ Class.new(Dry::Struct::Value) { transform_keys(&:to_sym) }
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,44 @@
1
+ require 'logger'
2
+ require 'temporal/metrics_adapters/null'
3
+
4
+ module Temporal
5
+ class Configuration
6
+ attr_reader :timeouts
7
+ attr_accessor :client_type, :host, :port, :logger, :metrics_adapter, :namespace, :task_queue, :headers
8
+
9
+ DEFAULT_TIMEOUTS = {
10
+ execution: 60, # End-to-end workflow time
11
+ task: 10, # Workflow task processing time
12
+ schedule_to_close: nil, # End-to-end activity time (default: schedule_to_start + start_to_close)
13
+ schedule_to_start: 10, # Queue time for an activity
14
+ start_to_close: 30, # Time spent processing an activity
15
+ heartbeat: nil # Max time between heartbeats (off by default)
16
+ }.freeze
17
+
18
+ DEFAULT_HEADERS = {}.freeze
19
+ DEFAULT_NAMESPACE = 'default-namespace'.freeze
20
+ DEFAULT_TASK_QUEUE = 'default-task-queue'.freeze
21
+
22
+ def initialize
23
+ @client_type = :grpc
24
+ @logger = Logger.new(STDOUT, progname: 'temporal_client')
25
+ @metrics_adapter = MetricsAdapters::Null.new
26
+ @timeouts = DEFAULT_TIMEOUTS
27
+ @namespace = DEFAULT_NAMESPACE
28
+ @task_queue = DEFAULT_TASK_QUEUE
29
+ @headers = DEFAULT_HEADERS
30
+ end
31
+
32
+ def task_list
33
+ @task_queue
34
+ end
35
+
36
+ def task_list=(name)
37
+ self.task_queue = name
38
+ end
39
+
40
+ def timeouts=(new_timeouts)
41
+ @timeouts = DEFAULT_TIMEOUTS.merge(new_timeouts)
42
+ end
43
+ end
44
+ end