temporalio 0.4.0-x86_64-linux-musl → 0.6.0-x86_64-linux-musl

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 (145) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/lib/temporalio/activity/cancellation_details.rb +58 -0
  4. data/lib/temporalio/activity/context.rb +10 -1
  5. data/lib/temporalio/activity/definition.rb +41 -3
  6. data/lib/temporalio/activity/info.rb +25 -4
  7. data/lib/temporalio/activity.rb +2 -0
  8. data/lib/temporalio/api/activity/v1/message.rb +1 -1
  9. data/lib/temporalio/api/batch/v1/message.rb +7 -2
  10. data/lib/temporalio/api/cloud/account/v1/message.rb +1 -1
  11. data/lib/temporalio/api/cloud/cloudservice/v1/request_response.rb +22 -2
  12. data/lib/temporalio/api/cloud/cloudservice/v1/service.rb +2 -2
  13. data/lib/temporalio/api/cloud/connectivityrule/v1/message.rb +29 -0
  14. data/lib/temporalio/api/cloud/identity/v1/message.rb +7 -2
  15. data/lib/temporalio/api/cloud/namespace/v1/message.rb +7 -2
  16. data/lib/temporalio/api/cloud/nexus/v1/message.rb +3 -2
  17. data/lib/temporalio/api/cloud/operation/v1/message.rb +2 -2
  18. data/lib/temporalio/api/cloud/region/v1/message.rb +1 -1
  19. data/lib/temporalio/api/cloud/resource/v1/message.rb +1 -1
  20. data/lib/temporalio/api/cloud/sink/v1/message.rb +1 -1
  21. data/lib/temporalio/api/cloud/usage/v1/message.rb +1 -1
  22. data/lib/temporalio/api/command/v1/message.rb +2 -2
  23. data/lib/temporalio/api/common/v1/grpc_status.rb +1 -1
  24. data/lib/temporalio/api/common/v1/message.rb +4 -2
  25. data/lib/temporalio/api/deployment/v1/message.rb +3 -2
  26. data/lib/temporalio/api/enums/v1/batch_operation.rb +2 -2
  27. data/lib/temporalio/api/enums/v1/command_type.rb +1 -1
  28. data/lib/temporalio/api/enums/v1/common.rb +5 -2
  29. data/lib/temporalio/api/enums/v1/deployment.rb +3 -2
  30. data/lib/temporalio/api/enums/v1/event_type.rb +2 -2
  31. data/lib/temporalio/api/enums/v1/failed_cause.rb +2 -2
  32. data/lib/temporalio/api/enums/v1/namespace.rb +1 -1
  33. data/lib/temporalio/api/enums/v1/nexus.rb +1 -1
  34. data/lib/temporalio/api/enums/v1/query.rb +1 -1
  35. data/lib/temporalio/api/enums/v1/reset.rb +1 -1
  36. data/lib/temporalio/api/enums/v1/schedule.rb +1 -1
  37. data/lib/temporalio/api/enums/v1/task_queue.rb +3 -2
  38. data/lib/temporalio/api/enums/v1/update.rb +1 -1
  39. data/lib/temporalio/api/enums/v1/workflow.rb +2 -2
  40. data/lib/temporalio/api/errordetails/v1/message.rb +1 -1
  41. data/lib/temporalio/api/export/v1/message.rb +1 -1
  42. data/lib/temporalio/api/failure/v1/message.rb +3 -2
  43. data/lib/temporalio/api/filter/v1/message.rb +1 -1
  44. data/lib/temporalio/api/history/v1/message.rb +4 -2
  45. data/lib/temporalio/api/namespace/v1/message.rb +1 -1
  46. data/lib/temporalio/api/nexus/v1/message.rb +2 -2
  47. data/lib/temporalio/api/operatorservice/v1/request_response.rb +1 -1
  48. data/lib/temporalio/api/operatorservice/v1/service.rb +1 -1
  49. data/lib/temporalio/api/payload_visitor.rb +106 -1
  50. data/lib/temporalio/api/protocol/v1/message.rb +1 -1
  51. data/lib/temporalio/api/query/v1/message.rb +1 -1
  52. data/lib/temporalio/api/replication/v1/message.rb +1 -1
  53. data/lib/temporalio/api/rules/v1/message.rb +27 -0
  54. data/lib/temporalio/api/schedule/v1/message.rb +2 -2
  55. data/lib/temporalio/api/sdk/v1/enhanced_stack_trace.rb +1 -1
  56. data/lib/temporalio/api/sdk/v1/task_complete_metadata.rb +1 -1
  57. data/lib/temporalio/api/sdk/v1/user_metadata.rb +1 -1
  58. data/lib/temporalio/api/sdk/v1/worker_config.rb +23 -0
  59. data/lib/temporalio/api/sdk/v1/workflow_metadata.rb +1 -1
  60. data/lib/temporalio/api/taskqueue/v1/message.rb +6 -2
  61. data/lib/temporalio/api/testservice/v1/request_response.rb +1 -1
  62. data/lib/temporalio/api/testservice/v1/service.rb +1 -1
  63. data/lib/temporalio/api/update/v1/message.rb +1 -1
  64. data/lib/temporalio/api/version/v1/message.rb +1 -1
  65. data/lib/temporalio/api/worker/v1/message.rb +31 -0
  66. data/lib/temporalio/api/workflow/v1/message.rb +14 -2
  67. data/lib/temporalio/api/workflowservice/v1/request_response.rb +28 -2
  68. data/lib/temporalio/api/workflowservice/v1/service.rb +2 -2
  69. data/lib/temporalio/cancellation.rb +16 -12
  70. data/lib/temporalio/client/async_activity_handle.rb +12 -4
  71. data/lib/temporalio/client/connection/cloud_service.rb +135 -0
  72. data/lib/temporalio/client/connection/workflow_service.rb +150 -0
  73. data/lib/temporalio/client/connection.rb +2 -1
  74. data/lib/temporalio/client/interceptor.rb +25 -7
  75. data/lib/temporalio/client/schedule.rb +10 -2
  76. data/lib/temporalio/client/with_start_workflow_operation.rb +9 -1
  77. data/lib/temporalio/client/workflow_handle.rb +50 -10
  78. data/lib/temporalio/client/workflow_update_handle.rb +9 -3
  79. data/lib/temporalio/client.rb +110 -6
  80. data/lib/temporalio/common_enums.rb +14 -0
  81. data/lib/temporalio/contrib/open_telemetry.rb +7 -7
  82. data/lib/temporalio/converters/data_converter.rb +18 -8
  83. data/lib/temporalio/converters/failure_converter.rb +6 -3
  84. data/lib/temporalio/converters/payload_converter/binary_null.rb +2 -2
  85. data/lib/temporalio/converters/payload_converter/binary_plain.rb +2 -2
  86. data/lib/temporalio/converters/payload_converter/binary_protobuf.rb +2 -2
  87. data/lib/temporalio/converters/payload_converter/composite.rb +6 -4
  88. data/lib/temporalio/converters/payload_converter/encoding.rb +4 -2
  89. data/lib/temporalio/converters/payload_converter/json_plain.rb +24 -7
  90. data/lib/temporalio/converters/payload_converter/json_protobuf.rb +2 -2
  91. data/lib/temporalio/converters/payload_converter.rb +16 -6
  92. data/lib/temporalio/error/failure.rb +19 -1
  93. data/lib/temporalio/error.rb +1 -1
  94. data/lib/temporalio/internal/bridge/3.2/temporalio_bridge.so +0 -0
  95. data/lib/temporalio/internal/bridge/3.3/temporalio_bridge.so +0 -0
  96. data/lib/temporalio/internal/bridge/3.4/temporalio_bridge.so +0 -0
  97. data/lib/temporalio/internal/bridge/api/activity_result/activity_result.rb +1 -1
  98. data/lib/temporalio/internal/bridge/api/activity_task/activity_task.rb +3 -2
  99. data/lib/temporalio/internal/bridge/api/child_workflow/child_workflow.rb +1 -1
  100. data/lib/temporalio/internal/bridge/api/common/common.rb +1 -1
  101. data/lib/temporalio/internal/bridge/api/core_interface.rb +1 -1
  102. data/lib/temporalio/internal/bridge/api/external_data/external_data.rb +1 -1
  103. data/lib/temporalio/internal/bridge/api/nexus/nexus.rb +3 -2
  104. data/lib/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rb +2 -2
  105. data/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +3 -2
  106. data/lib/temporalio/internal/bridge/api/workflow_completion/workflow_completion.rb +1 -1
  107. data/lib/temporalio/internal/bridge/worker.rb +28 -4
  108. data/lib/temporalio/internal/bridge.rb +1 -1
  109. data/lib/temporalio/internal/client/implementation.rb +60 -52
  110. data/lib/temporalio/internal/proto_utils.rb +4 -4
  111. data/lib/temporalio/internal/worker/activity_worker.rb +93 -20
  112. data/lib/temporalio/internal/worker/workflow_instance/child_workflow_handle.rb +8 -6
  113. data/lib/temporalio/internal/worker/workflow_instance/context.rb +66 -24
  114. data/lib/temporalio/internal/worker/workflow_instance/details.rb +5 -2
  115. data/lib/temporalio/internal/worker/workflow_instance/external_workflow_handle.rb +2 -2
  116. data/lib/temporalio/internal/worker/workflow_instance/externally_immutable_hash.rb +2 -0
  117. data/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb +64 -18
  118. data/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +28 -14
  119. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_logger.rb +5 -2
  120. data/lib/temporalio/internal/worker/workflow_instance/scheduler.rb +10 -4
  121. data/lib/temporalio/internal/worker/workflow_instance.rb +58 -23
  122. data/lib/temporalio/internal/worker/workflow_worker.rb +16 -6
  123. data/lib/temporalio/priority.rb +100 -0
  124. data/lib/temporalio/scoped_logger.rb +1 -1
  125. data/lib/temporalio/testing/activity_environment.rb +17 -2
  126. data/lib/temporalio/testing/workflow_environment.rb +3 -3
  127. data/lib/temporalio/version.rb +1 -1
  128. data/lib/temporalio/versioning_override.rb +56 -0
  129. data/lib/temporalio/worker/deployment_options.rb +45 -0
  130. data/lib/temporalio/worker/illegal_workflow_call_validator.rb +73 -0
  131. data/lib/temporalio/worker/interceptor.rb +13 -1
  132. data/lib/temporalio/worker/poller_behavior.rb +61 -0
  133. data/lib/temporalio/worker/thread_pool.rb +1 -1
  134. data/lib/temporalio/worker/workflow_executor/thread_pool.rb +2 -1
  135. data/lib/temporalio/worker/workflow_replayer.rb +12 -13
  136. data/lib/temporalio/worker.rb +73 -28
  137. data/lib/temporalio/worker_deployment_version.rb +67 -0
  138. data/lib/temporalio/workflow/child_workflow_handle.rb +10 -2
  139. data/lib/temporalio/workflow/definition.rb +187 -39
  140. data/lib/temporalio/workflow/external_workflow_handle.rb +3 -1
  141. data/lib/temporalio/workflow/info.rb +4 -1
  142. data/lib/temporalio/workflow.rb +134 -11
  143. data/lib/temporalio.rb +1 -0
  144. data/temporalio.gemspec +1 -0
  145. metadata +13 -2
@@ -53,7 +53,7 @@ module Temporalio
53
53
  workflow_type: Api::Common::V1::WorkflowType.new(name: input.workflow),
54
54
  workflow_id: input.workflow_id,
55
55
  task_queue: Api::TaskQueue::V1::TaskQueue.new(name: input.task_queue.to_s),
56
- input: @client.data_converter.to_payloads(input.args),
56
+ input: @client.data_converter.to_payloads(input.args, hints: input.arg_hints),
57
57
  workflow_execution_timeout: ProtoUtils.seconds_to_duration(input.execution_timeout),
58
58
  workflow_run_timeout: ProtoUtils.seconds_to_duration(input.run_timeout),
59
59
  workflow_task_timeout: ProtoUtils.seconds_to_duration(input.task_timeout),
@@ -69,7 +69,9 @@ module Temporalio
69
69
  user_metadata: ProtoUtils.to_user_metadata(
70
70
  input.static_summary, input.static_details, @client.data_converter
71
71
  ),
72
- header: ProtoUtils.headers_to_proto(input.headers, @client.data_converter)
72
+ header: ProtoUtils.headers_to_proto(input.headers, @client.data_converter),
73
+ priority: input.priority._to_proto,
74
+ versioning_override: input.versioning_override&._to_proto
73
75
  )
74
76
 
75
77
  # Send request
@@ -101,7 +103,8 @@ module Temporalio
101
103
  id: input.workflow_id,
102
104
  run_id: nil,
103
105
  result_run_id: resp.run_id,
104
- first_execution_run_id: resp.run_id
106
+ first_execution_run_id: resp.run_id,
107
+ result_hint: input.result_hint
105
108
  )
106
109
  end
107
110
 
@@ -137,7 +140,7 @@ module Temporalio
137
140
  ),
138
141
  input: Api::Update::V1::Input.new(
139
142
  name: input.update,
140
- args: @client.data_converter.to_payloads(input.args),
143
+ args: @client.data_converter.to_payloads(input.args, hints: input.arg_hints),
141
144
  header: Internal::ProtoUtils.headers_to_proto(input.headers, @client.data_converter)
142
145
  )
143
146
  ),
@@ -167,7 +170,8 @@ module Temporalio
167
170
  id: start_options.id,
168
171
  run_id: nil,
169
172
  result_run_id: run_id,
170
- first_execution_run_id: run_id
173
+ first_execution_run_id: run_id,
174
+ result_hint: start_options.result_hint
171
175
  )
172
176
  )
173
177
  update_resp = resp.responses.last.update_workflow
@@ -243,7 +247,8 @@ module Temporalio
243
247
  id: input.update_id,
244
248
  workflow_id: start_options.id,
245
249
  workflow_run_id: run_id,
246
- known_outcome: update_resp.outcome
250
+ known_outcome: update_resp.outcome,
251
+ result_hint: input.result_hint
247
252
  )
248
253
  end
249
254
 
@@ -259,7 +264,7 @@ module Temporalio
259
264
  Api::WorkflowService::V1::SignalWithStartWorkflowExecutionRequest, start_options
260
265
  )
261
266
  req.signal_name = input.signal
262
- req.signal_input = @client.data_converter.to_payloads(input.args)
267
+ req.signal_input = @client.data_converter.to_payloads(input.args, hints: input.arg_hints)
263
268
 
264
269
  # Send request
265
270
  begin
@@ -292,7 +297,8 @@ module Temporalio
292
297
  id: start_options.id,
293
298
  run_id: nil,
294
299
  result_run_id: resp.run_id,
295
- first_execution_run_id: resp.run_id
300
+ first_execution_run_id: resp.run_id,
301
+ result_hint: start_options.result_hint
296
302
  )
297
303
  input.start_workflow_operation._set_workflow_handle(handle)
298
304
  handle
@@ -305,7 +311,7 @@ module Temporalio
305
311
  workflow_type: Api::Common::V1::WorkflowType.new(name: start_options.workflow),
306
312
  workflow_id: start_options.id,
307
313
  task_queue: Api::TaskQueue::V1::TaskQueue.new(name: start_options.task_queue.to_s),
308
- input: @client.data_converter.to_payloads(start_options.args),
314
+ input: @client.data_converter.to_payloads(start_options.args, hints: start_options.arg_hints),
309
315
  workflow_execution_timeout: ProtoUtils.seconds_to_duration(start_options.execution_timeout),
310
316
  workflow_run_timeout: ProtoUtils.seconds_to_duration(start_options.run_timeout),
311
317
  workflow_task_timeout: ProtoUtils.seconds_to_duration(start_options.task_timeout),
@@ -324,25 +330,24 @@ module Temporalio
324
330
  )
325
331
  end
326
332
 
327
- def list_workflows(input)
328
- Enumerator.new do |yielder|
329
- req = Api::WorkflowService::V1::ListWorkflowExecutionsRequest.new(
330
- namespace: @client.namespace,
331
- query: input.query || ''
332
- )
333
- loop do
334
- resp = @client.workflow_service.list_workflow_executions(
335
- req,
336
- rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
337
- )
338
- resp.executions.each do |raw_info|
339
- yielder << Temporalio::Client::WorkflowExecution.new(raw_info, @client.data_converter)
340
- end
341
- break if resp.next_page_token.empty?
342
-
343
- req.next_page_token = resp.next_page_token
344
- end
333
+ def list_workflow_page(input)
334
+ req = Api::WorkflowService::V1::ListWorkflowExecutionsRequest.new(
335
+ namespace: @client.namespace,
336
+ query: input.query || '',
337
+ next_page_token: input.next_page_token,
338
+ page_size: input.page_size
339
+ )
340
+ resp = @client.workflow_service.list_workflow_executions(
341
+ req,
342
+ rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
343
+ )
344
+ executions = resp.executions.map do |raw_info|
345
+ Temporalio::Client::WorkflowExecution.new(raw_info, @client.data_converter)
345
346
  end
347
+ Temporalio::Client::ListWorkflowPage.new(
348
+ executions: executions,
349
+ next_page_token: resp.next_page_token
350
+ )
346
351
  end
347
352
 
348
353
  def count_workflows(input)
@@ -412,7 +417,7 @@ module Temporalio
412
417
  run_id: input.run_id || ''
413
418
  ),
414
419
  signal_name: input.signal,
415
- input: @client.data_converter.to_payloads(input.args),
420
+ input: @client.data_converter.to_payloads(input.args, hints: input.arg_hints),
416
421
  header: Internal::ProtoUtils.headers_to_proto(input.headers, @client.data_converter),
417
422
  identity: @client.connection.identity,
418
423
  request_id: SecureRandom.uuid
@@ -433,7 +438,7 @@ module Temporalio
433
438
  ),
434
439
  query: Api::Query::V1::WorkflowQuery.new(
435
440
  query_type: input.query,
436
- query_args: @client.data_converter.to_payloads(input.args),
441
+ query_args: @client.data_converter.to_payloads(input.args, hints: input.arg_hints),
437
442
  header: Internal::ProtoUtils.headers_to_proto(input.headers, @client.data_converter)
438
443
  ),
439
444
  query_reject_condition: input.reject_condition || 0
@@ -453,7 +458,7 @@ module Temporalio
453
458
  ))
454
459
  end
455
460
 
456
- results = @client.data_converter.from_payloads(resp.query_result)
461
+ results = @client.data_converter.from_payloads(resp.query_result, hints: Array(input.result_hint))
457
462
  warn("Expected 0 or 1 query result, got #{results.size}") if results.size > 1
458
463
  results&.first
459
464
  end
@@ -476,7 +481,7 @@ module Temporalio
476
481
  ),
477
482
  input: Api::Update::V1::Input.new(
478
483
  name: input.update,
479
- args: @client.data_converter.to_payloads(input.args),
484
+ args: @client.data_converter.to_payloads(input.args, hints: input.arg_hints),
480
485
  header: Internal::ProtoUtils.headers_to_proto(input.headers, @client.data_converter)
481
486
  )
482
487
  ),
@@ -490,6 +495,10 @@ module Temporalio
490
495
  # the user cannot specify sooner than ACCEPTED)
491
496
  # @type var resp: untyped
492
497
  resp = nil
498
+ expected_stage = ProtoUtils.enum_to_int(Api::Enums::V1::UpdateWorkflowExecutionLifecycleStage,
499
+ req.wait_policy.lifecycle_stage)
500
+ accepted_stage = ProtoUtils.enum_to_int(Api::Enums::V1::UpdateWorkflowExecutionLifecycleStage,
501
+ Temporalio::Client::WorkflowUpdateWaitStage::ACCEPTED)
493
502
  loop do
494
503
  resp = @client.workflow_service.update_workflow_execution(
495
504
  req,
@@ -498,10 +507,8 @@ module Temporalio
498
507
 
499
508
  # We're only done if the response stage is after the requested stage
500
509
  # or the response stage is accepted
501
- if resp.stage >= req.wait_policy.lifecycle_stage ||
502
- resp.stage >= Temporalio::Client::WorkflowUpdateWaitStage::ACCEPTED
503
- break
504
- end
510
+ actual_stage = ProtoUtils.enum_to_int(Api::Enums::V1::UpdateWorkflowExecutionLifecycleStage, resp.stage)
511
+ break if actual_stage >= expected_stage || actual_stage >= accepted_stage
505
512
  rescue Error::RPCError => e
506
513
  # Deadline exceeded or cancel is a special error type
507
514
  if e.code == Error::RPCError::Code::DEADLINE_EXCEEDED || e.code == Error::RPCError::Code::CANCELED
@@ -531,7 +538,8 @@ module Temporalio
531
538
  id: input.update_id,
532
539
  workflow_id: input.workflow_id,
533
540
  workflow_run_id: input.run_id,
534
- known_outcome: resp.outcome
541
+ known_outcome: resp.outcome,
542
+ result_hint: input.result_hint
535
543
  )
536
544
  end
537
545
 
@@ -806,7 +814,7 @@ module Temporalio
806
814
  activity_id: input.task_token_or_id_reference.activity_id,
807
815
  namespace: @client.namespace,
808
816
  identity: @client.connection.identity,
809
- details: @client.data_converter.to_payloads(input.details)
817
+ details: @client.data_converter.to_payloads(input.details, hints: input.detail_hints)
810
818
  ),
811
819
  rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
812
820
  )
@@ -816,7 +824,7 @@ module Temporalio
816
824
  task_token: input.task_token_or_id_reference,
817
825
  namespace: @client.namespace,
818
826
  identity: @client.connection.identity,
819
- details: @client.data_converter.to_payloads(input.details)
827
+ details: @client.data_converter.to_payloads(input.details, hints: input.detail_hints)
820
828
  ),
821
829
  rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
822
830
  )
@@ -835,7 +843,7 @@ module Temporalio
835
843
  activity_id: input.task_token_or_id_reference.activity_id,
836
844
  namespace: @client.namespace,
837
845
  identity: @client.connection.identity,
838
- result: @client.data_converter.to_payloads([input.result])
846
+ result: @client.data_converter.to_payloads([input.result], hints: Array(input.result_hint))
839
847
  ),
840
848
  rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
841
849
  )
@@ -845,7 +853,7 @@ module Temporalio
845
853
  task_token: input.task_token_or_id_reference,
846
854
  namespace: @client.namespace,
847
855
  identity: @client.connection.identity,
848
- result: @client.data_converter.to_payloads([input.result])
856
+ result: @client.data_converter.to_payloads([input.result], hints: Array(input.result_hint))
849
857
  ),
850
858
  rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
851
859
  )
@@ -854,6 +862,14 @@ module Temporalio
854
862
  end
855
863
 
856
864
  def fail_async_activity(input)
865
+ last_heartbeat_details = if input.last_heartbeat_details.empty?
866
+ nil
867
+ else
868
+ @client.data_converter.to_payloads(
869
+ input.last_heartbeat_details,
870
+ hints: input.last_heartbeat_detail_hints
871
+ )
872
+ end
857
873
  if input.task_token_or_id_reference.is_a?(Temporalio::Client::ActivityIDReference)
858
874
  @client.workflow_service.respond_activity_task_failed_by_id(
859
875
  Api::WorkflowService::V1::RespondActivityTaskFailedByIdRequest.new(
@@ -863,11 +879,7 @@ module Temporalio
863
879
  namespace: @client.namespace,
864
880
  identity: @client.connection.identity,
865
881
  failure: @client.data_converter.to_failure(input.error),
866
- last_heartbeat_details: if input.last_heartbeat_details.empty?
867
- nil
868
- else
869
- @client.data_converter.to_payloads(input.last_heartbeat_details)
870
- end
882
+ last_heartbeat_details:
871
883
  ),
872
884
  rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
873
885
  )
@@ -878,11 +890,7 @@ module Temporalio
878
890
  namespace: @client.namespace,
879
891
  identity: @client.connection.identity,
880
892
  failure: @client.data_converter.to_failure(input.error),
881
- last_heartbeat_details: if input.last_heartbeat_details.empty?
882
- nil
883
- else
884
- @client.data_converter.to_payloads(input.last_heartbeat_details)
885
- end
893
+ last_heartbeat_details:
886
894
  ),
887
895
  rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
888
896
  )
@@ -899,7 +907,7 @@ module Temporalio
899
907
  activity_id: input.task_token_or_id_reference.activity_id,
900
908
  namespace: @client.namespace,
901
909
  identity: @client.connection.identity,
902
- details: @client.data_converter.to_payloads(input.details)
910
+ details: @client.data_converter.to_payloads(input.details, hints: input.detail_hints)
903
911
  ),
904
912
  rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
905
913
  )
@@ -909,7 +917,7 @@ module Temporalio
909
917
  task_token: input.task_token_or_id_reference,
910
918
  namespace: @client.namespace,
911
919
  identity: @client.connection.identity,
912
- details: @client.data_converter.to_payloads(input.details)
920
+ details: @client.data_converter.to_payloads(input.details, hints: input.detail_hints)
913
921
  ),
914
922
  rpc_options: Implementation.with_default_rpc_options(input.rpc_options)
915
923
  )
@@ -94,16 +94,16 @@ module Temporalio
94
94
  enum_val
95
95
  end
96
96
 
97
- def self.convert_from_payload_array(converter, payloads)
97
+ def self.convert_from_payload_array(converter, payloads, hints:)
98
98
  return [] if payloads.empty?
99
99
 
100
- converter.from_payloads(Api::Common::V1::Payloads.new(payloads:))
100
+ converter.from_payloads(Api::Common::V1::Payloads.new(payloads:), hints:)
101
101
  end
102
102
 
103
- def self.convert_to_payload_array(converter, values)
103
+ def self.convert_to_payload_array(converter, values, hints:)
104
104
  return [] if values.empty?
105
105
 
106
- converter.to_payloads(values).payloads.to_ary
106
+ converter.to_payloads(values, hints:).payloads.to_ary
107
107
  end
108
108
 
109
109
  def self.assert_non_reserved_name(name)
@@ -148,10 +148,18 @@ module Temporalio
148
148
  @scoped_logger.warn("Cannot find activity to cancel for token #{task_token}")
149
149
  return
150
150
  end
151
- activity._server_requested_cancel = true
152
- _, cancel_proc = activity.cancellation
153
151
  begin
154
- cancel_proc.call(reason: cancel.reason.to_s)
152
+ activity._cancel(
153
+ reason: cancel.reason.to_s,
154
+ details: Activity::CancellationDetails.new(
155
+ gone_from_server: cancel.details.is_not_found,
156
+ cancel_requested: cancel.details.is_cancelled,
157
+ timed_out: cancel.details.is_timed_out,
158
+ worker_shutdown: cancel.details.is_worker_shutdown,
159
+ paused: cancel.details.is_paused,
160
+ reset: cancel.details.is_reset
161
+ )
162
+ )
155
163
  rescue StandardError => e
156
164
  @scoped_logger.warn("Failed cancelling activity #{activity.info.activity_type} \
157
165
  with ID #{activity.info.activity_id}")
@@ -168,12 +176,15 @@ module Temporalio
168
176
  current_attempt_scheduled_time: Internal::ProtoUtils.timestamp_to_time(
169
177
  start.current_attempt_scheduled_time
170
178
  ) || raise, # Never nil
171
- heartbeat_details: ProtoUtils.convert_from_payload_array(
172
- @worker.options.client.data_converter,
173
- start.heartbeat_details.to_ary
174
- ),
175
179
  heartbeat_timeout: Internal::ProtoUtils.duration_to_seconds(start.heartbeat_timeout),
176
180
  local?: start.is_local,
181
+ priority: Priority._from_proto(start.priority),
182
+ raw_heartbeat_details: begin
183
+ payloads = start.heartbeat_details.to_ary
184
+ codec = @worker.options.client.data_converter.payload_codec
185
+ payloads = codec.decode(payloads) if codec
186
+ payloads.map { |p| Temporalio::Converters::RawValue.new(p) }
187
+ end,
177
188
  schedule_to_close_timeout: Internal::ProtoUtils.duration_to_seconds(start.schedule_to_close_timeout),
178
189
  scheduled_time: Internal::ProtoUtils.timestamp_to_time(start.scheduled_time) || raise, # Never nil
179
190
  start_to_close_timeout: Internal::ProtoUtils.duration_to_seconds(start.start_to_close_timeout),
@@ -184,7 +195,7 @@ module Temporalio
184
195
  workflow_namespace: start.workflow_namespace,
185
196
  workflow_run_id: start.workflow_execution.run_id,
186
197
  workflow_type: start.workflow_type
187
- ).freeze
198
+ )
188
199
 
189
200
  # Build input
190
201
  input = Temporalio::Worker::Interceptor::Activity::ExecuteInput.new(
@@ -196,8 +207,13 @@ module Temporalio
196
207
  payloads = codec.decode(payloads) if codec
197
208
  payloads.map { |p| Temporalio::Converters::RawValue.new(p) }
198
209
  else
199
- ProtoUtils.convert_from_payload_array(@worker.options.client.data_converter, start.input.to_ary)
210
+ ProtoUtils.convert_from_payload_array(
211
+ @worker.options.client.data_converter,
212
+ start.input.to_ary,
213
+ hints: defn.arg_hints
214
+ )
200
215
  end,
216
+ result_hint: defn.result_hint,
201
217
  headers: ProtoUtils.headers_from_proto_map(start.header_fields, @worker.options.client.data_converter) || {}
202
218
  )
203
219
 
@@ -250,7 +266,7 @@ module Temporalio
250
266
  impl = @worker._activity_interceptors.reverse_each.reduce(impl) do |acc, int|
251
267
  int.intercept_activity(acc)
252
268
  end
253
- impl.init(OutboundImplementation.new(self))
269
+ impl.init(OutboundImplementation.new(self, activity.info.task_token))
254
270
 
255
271
  # Execute
256
272
  result = impl.execute(input)
@@ -258,7 +274,7 @@ module Temporalio
258
274
  # Success
259
275
  Bridge::Api::ActivityResult::ActivityExecutionResult.new(
260
276
  completed: Bridge::Api::ActivityResult::Success.new(
261
- result: @worker.options.client.data_converter.to_payload(result)
277
+ result: @worker.options.client.data_converter.to_payload(result, hint: input.result_hint)
262
278
  )
263
279
  )
264
280
  rescue Exception => e # rubocop:disable Lint/RescueException -- We are intending to catch everything here
@@ -268,6 +284,30 @@ module Temporalio
268
284
  Bridge::Api::ActivityResult::ActivityExecutionResult.new(
269
285
  will_complete_async: Bridge::Api::ActivityResult::WillCompleteAsync.new
270
286
  )
287
+ elsif e.is_a?(Error::CanceledError) && activity.cancellation_details&.paused?
288
+ # Server requested pause
289
+ @scoped_logger.debug('Completing activity as failed due to exception caused by pause')
290
+ Bridge::Api::ActivityResult::ActivityExecutionResult.new(
291
+ failed: Bridge::Api::ActivityResult::Failure.new(
292
+ failure: @worker.options.client.data_converter.to_failure(
293
+ Error._with_backtrace_and_cause(
294
+ Error::ApplicationError.new('Activity paused', type: 'ActivityPause'), backtrace: nil, cause: e
295
+ )
296
+ )
297
+ )
298
+ )
299
+ elsif e.is_a?(Error::CanceledError) && activity.cancellation_details&.reset?
300
+ # Server requested reset
301
+ @scoped_logger.debug('Completing activity as failed due to exception caused by reset')
302
+ Bridge::Api::ActivityResult::ActivityExecutionResult.new(
303
+ failed: Bridge::Api::ActivityResult::Failure.new(
304
+ failure: @worker.options.client.data_converter.to_failure(
305
+ Error._with_backtrace_and_cause(
306
+ Error::ApplicationError.new('Activity reset', type: 'ActivityReset'), backtrace: nil, cause: e
307
+ )
308
+ )
309
+ )
310
+ )
271
311
  elsif e.is_a?(Error::CanceledError) && activity._server_requested_cancel
272
312
  # Server requested cancel
273
313
  @scoped_logger.debug('Completing activity as canceled')
@@ -278,8 +318,13 @@ module Temporalio
278
318
  )
279
319
  else
280
320
  # General failure
281
- @scoped_logger.warn('Completing activity as failed')
282
- @scoped_logger.warn(e)
321
+ log_level = if e.is_a?(Error::ApplicationError) && e.category == Error::ApplicationError::Category::BENIGN
322
+ Logger::DEBUG
323
+ else
324
+ Logger::WARN
325
+ end
326
+ @scoped_logger.add(log_level, 'Completing activity as failed')
327
+ @scoped_logger.add(log_level, e)
283
328
  Bridge::Api::ActivityResult::ActivityExecutionResult.new(
284
329
  failed: Bridge::Api::ActivityResult::Failure.new(
285
330
  failure: @worker.options.client.data_converter.to_failure(e)
@@ -297,9 +342,21 @@ module Temporalio
297
342
  )
298
343
  end
299
344
 
345
+ def assert_valid_activity(activity)
346
+ defn = @activities[activity]
347
+ defn = @activities[nil] if !defn && !Internal::ProtoUtils.reserved_name?(activity)
348
+
349
+ return unless defn.nil?
350
+
351
+ raise ArgumentError,
352
+ "Activity #{activity} " \
353
+ "is not registered on this worker, available activities: #{@activities.keys.sort.join(', ')}"
354
+ end
355
+
300
356
  class RunningActivity < Activity::Context
301
- attr_reader :info, :cancellation, :worker_shutdown_cancellation, :payload_converter, :logger
302
- attr_accessor :instance, :_outbound_impl, :_server_requested_cancel
357
+ attr_reader :info, :cancellation, :cancellation_details, :worker_shutdown_cancellation,
358
+ :payload_converter, :logger, :_server_requested_cancel
359
+ attr_accessor :instance, :_outbound_impl
303
360
 
304
361
  def initialize( # rubocop:disable Lint/MissingSuper
305
362
  worker:,
@@ -313,6 +370,7 @@ module Temporalio
313
370
  @worker = worker
314
371
  @info = info
315
372
  @cancellation = cancellation
373
+ @cancellation_details = nil
316
374
  @worker_shutdown_cancellation = worker_shutdown_cancellation
317
375
  @payload_converter = payload_converter
318
376
  @logger = logger
@@ -321,13 +379,15 @@ module Temporalio
321
379
  @_server_requested_cancel = false
322
380
  end
323
381
 
324
- def heartbeat(*details)
382
+ def heartbeat(*details, detail_hints: nil)
325
383
  raise 'Implementation not set yet' if _outbound_impl.nil?
326
384
 
327
385
  # No-op if local
328
386
  return if info.local?
329
387
 
330
- _outbound_impl.heartbeat(Temporalio::Worker::Interceptor::Activity::HeartbeatInput.new(details:))
388
+ _outbound_impl.heartbeat(
389
+ Temporalio::Worker::Interceptor::Activity::HeartbeatInput.new(details:, detail_hints:)
390
+ )
331
391
  end
332
392
 
333
393
  def metric_meter
@@ -343,6 +403,17 @@ module Temporalio
343
403
  def client
344
404
  @worker.client
345
405
  end
406
+
407
+ def _cancel(reason:, details:)
408
+ # Do not issue cancel if already canceled
409
+ return if @cancellation_details
410
+
411
+ @_server_requested_cancel = true
412
+ # Set the cancellation details _before_ issuing the cancel itself
413
+ @cancellation_details = details
414
+ _, cancel_proc = cancellation
415
+ cancel_proc.call(reason:)
416
+ end
346
417
  end
347
418
 
348
419
  class InboundImplementation < Temporalio::Worker::Interceptor::Activity::Inbound
@@ -364,17 +435,19 @@ module Temporalio
364
435
  end
365
436
 
366
437
  class OutboundImplementation < Temporalio::Worker::Interceptor::Activity::Outbound
367
- def initialize(worker)
438
+ def initialize(worker, task_token)
368
439
  super(nil) # steep:ignore
369
440
  @worker = worker
441
+ @task_token = task_token
370
442
  end
371
443
 
372
444
  def heartbeat(input)
373
445
  @worker.bridge_worker.record_activity_heartbeat(
374
446
  Bridge::Api::CoreInterface::ActivityHeartbeat.new(
375
- task_token: Activity::Context.current.info.task_token,
447
+ task_token: @task_token,
376
448
  details: ProtoUtils.convert_to_payload_array(@worker.worker.options.client.data_converter,
377
- input.details)
449
+ input.details,
450
+ hints: input.detail_hints)
378
451
  ).to_proto
379
452
  )
380
453
  end
@@ -10,18 +10,20 @@ module Temporalio
10
10
  class WorkflowInstance
11
11
  # Implementation of the child workflow handle.
12
12
  class ChildWorkflowHandle < Workflow::ChildWorkflowHandle
13
- attr_reader :id, :first_execution_run_id
13
+ attr_reader :id, :first_execution_run_id, :result_hint
14
14
 
15
- def initialize(id:, first_execution_run_id:, instance:, cancellation:, cancel_callback_key:) # rubocop:disable Lint/MissingSuper
15
+ def initialize(id:, first_execution_run_id:, instance:, # rubocop:disable Lint/MissingSuper
16
+ cancellation:, cancel_callback_key:, result_hint:)
16
17
  @id = id
17
18
  @first_execution_run_id = first_execution_run_id
18
19
  @instance = instance
19
20
  @cancellation = cancellation
20
21
  @cancel_callback_key = cancel_callback_key
22
+ @result_hint = result_hint
21
23
  @resolution = nil
22
24
  end
23
25
 
24
- def result
26
+ def result(result_hint: nil)
25
27
  # Notice that we actually provide a detached cancellation here instead of defaulting to workflow
26
28
  # cancellation because we don't want workflow cancellation (or a user-provided cancellation to this result
27
29
  # call) to be able to interrupt waiting on a child that may be processing the cancellation.
@@ -29,7 +31,7 @@ module Temporalio
29
31
 
30
32
  case @resolution.status
31
33
  when :completed
32
- @instance.payload_converter.from_payload(@resolution.completed.result)
34
+ @instance.payload_converter.from_payload(@resolution.completed.result, hint: result_hint || @result_hint)
33
35
  when :failed
34
36
  raise @instance.failure_converter.from_failure(@resolution.failed.failure, @instance.payload_converter)
35
37
  when :cancelled
@@ -44,8 +46,8 @@ module Temporalio
44
46
  @resolution = resolution
45
47
  end
46
48
 
47
- def signal(signal, *args, cancellation: Workflow.cancellation)
48
- @instance.context._signal_child_workflow(id:, signal:, args:, cancellation:)
49
+ def signal(signal, *args, cancellation: Workflow.cancellation, arg_hints: nil)
50
+ @instance.context._signal_child_workflow(id:, signal:, args:, cancellation:, arg_hints:)
49
51
  end
50
52
  end
51
53
  end