temporal-ruby 0.0.0 → 0.0.1.pre.pre1

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