temporalio 0.5.0 → 0.6.0

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +139 -125
  3. data/README.md +90 -5
  4. data/lib/temporalio/api/batch/v1/message.rb +4 -1
  5. data/lib/temporalio/api/cloud/cloudservice/v1/request_response.rb +12 -1
  6. data/lib/temporalio/api/cloud/cloudservice/v1/service.rb +1 -1
  7. data/lib/temporalio/api/cloud/connectivityrule/v1/message.rb +29 -0
  8. data/lib/temporalio/api/cloud/identity/v1/message.rb +1 -1
  9. data/lib/temporalio/api/cloud/namespace/v1/message.rb +2 -1
  10. data/lib/temporalio/api/cloud/operation/v1/message.rb +1 -1
  11. data/lib/temporalio/api/common/v1/message.rb +2 -1
  12. data/lib/temporalio/api/enums/v1/batch_operation.rb +1 -1
  13. data/lib/temporalio/api/enums/v1/task_queue.rb +2 -1
  14. data/lib/temporalio/api/history/v1/message.rb +1 -1
  15. data/lib/temporalio/api/payload_visitor.rb +19 -1
  16. data/lib/temporalio/api/sdk/v1/worker_config.rb +23 -0
  17. data/lib/temporalio/api/taskqueue/v1/message.rb +5 -1
  18. data/lib/temporalio/api/worker/v1/message.rb +2 -1
  19. data/lib/temporalio/api/workflowservice/v1/request_response.rb +10 -1
  20. data/lib/temporalio/api/workflowservice/v1/service.rb +1 -1
  21. data/lib/temporalio/cancellation.rb +16 -12
  22. data/lib/temporalio/client/connection/cloud_service.rb +75 -0
  23. data/lib/temporalio/client/connection/workflow_service.rb +45 -0
  24. data/lib/temporalio/client/connection.rb +2 -1
  25. data/lib/temporalio/contrib/open_telemetry.rb +9 -13
  26. data/lib/temporalio/converters/payload_converter/json_plain.rb +22 -5
  27. data/lib/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rb +1 -1
  28. data/lib/temporalio/internal/worker/workflow_instance/context.rb +5 -4
  29. data/lib/temporalio/internal/worker/workflow_instance/externally_immutable_hash.rb +2 -0
  30. data/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb +1 -1
  31. data/lib/temporalio/internal/worker/workflow_instance/replay_safe_logger.rb +5 -2
  32. data/lib/temporalio/internal/worker/workflow_instance/scheduler.rb +10 -4
  33. data/lib/temporalio/priority.rb +47 -6
  34. data/lib/temporalio/scoped_logger.rb +1 -1
  35. data/lib/temporalio/version.rb +1 -1
  36. data/lib/temporalio/worker/illegal_workflow_call_validator.rb +9 -0
  37. data/lib/temporalio/worker.rb +10 -1
  38. data/lib/temporalio/workflow/definition.rb +4 -6
  39. data/lib/temporalio/workflow.rb +74 -3
  40. metadata +3 -1
@@ -780,6 +780,81 @@ module Temporalio
780
780
  rpc_options:
781
781
  )
782
782
  end
783
+
784
+ # Calls CloudService.UpdateNamespaceTags API call.
785
+ #
786
+ # @param request [Temporalio::Api::Cloud::CloudService::V1::UpdateNamespaceTagsRequest] API request.
787
+ # @param rpc_options [RPCOptions, nil] Advanced RPC options.
788
+ # @return [Temporalio::Api::Cloud::CloudService::V1::UpdateNamespaceTagsResponse] API response.
789
+ def update_namespace_tags(request, rpc_options: nil)
790
+ invoke_rpc(
791
+ rpc: 'update_namespace_tags',
792
+ request_class: Temporalio::Api::Cloud::CloudService::V1::UpdateNamespaceTagsRequest,
793
+ response_class: Temporalio::Api::Cloud::CloudService::V1::UpdateNamespaceTagsResponse,
794
+ request:,
795
+ rpc_options:
796
+ )
797
+ end
798
+
799
+ # Calls CloudService.CreateConnectivityRule API call.
800
+ #
801
+ # @param request [Temporalio::Api::Cloud::CloudService::V1::CreateConnectivityRuleRequest] API request.
802
+ # @param rpc_options [RPCOptions, nil] Advanced RPC options.
803
+ # @return [Temporalio::Api::Cloud::CloudService::V1::CreateConnectivityRuleResponse] API response.
804
+ def create_connectivity_rule(request, rpc_options: nil)
805
+ invoke_rpc(
806
+ rpc: 'create_connectivity_rule',
807
+ request_class: Temporalio::Api::Cloud::CloudService::V1::CreateConnectivityRuleRequest,
808
+ response_class: Temporalio::Api::Cloud::CloudService::V1::CreateConnectivityRuleResponse,
809
+ request:,
810
+ rpc_options:
811
+ )
812
+ end
813
+
814
+ # Calls CloudService.GetConnectivityRule API call.
815
+ #
816
+ # @param request [Temporalio::Api::Cloud::CloudService::V1::GetConnectivityRuleRequest] API request.
817
+ # @param rpc_options [RPCOptions, nil] Advanced RPC options.
818
+ # @return [Temporalio::Api::Cloud::CloudService::V1::GetConnectivityRuleResponse] API response.
819
+ def get_connectivity_rule(request, rpc_options: nil)
820
+ invoke_rpc(
821
+ rpc: 'get_connectivity_rule',
822
+ request_class: Temporalio::Api::Cloud::CloudService::V1::GetConnectivityRuleRequest,
823
+ response_class: Temporalio::Api::Cloud::CloudService::V1::GetConnectivityRuleResponse,
824
+ request:,
825
+ rpc_options:
826
+ )
827
+ end
828
+
829
+ # Calls CloudService.GetConnectivityRules API call.
830
+ #
831
+ # @param request [Temporalio::Api::Cloud::CloudService::V1::GetConnectivityRulesRequest] API request.
832
+ # @param rpc_options [RPCOptions, nil] Advanced RPC options.
833
+ # @return [Temporalio::Api::Cloud::CloudService::V1::GetConnectivityRulesResponse] API response.
834
+ def get_connectivity_rules(request, rpc_options: nil)
835
+ invoke_rpc(
836
+ rpc: 'get_connectivity_rules',
837
+ request_class: Temporalio::Api::Cloud::CloudService::V1::GetConnectivityRulesRequest,
838
+ response_class: Temporalio::Api::Cloud::CloudService::V1::GetConnectivityRulesResponse,
839
+ request:,
840
+ rpc_options:
841
+ )
842
+ end
843
+
844
+ # Calls CloudService.DeleteConnectivityRule API call.
845
+ #
846
+ # @param request [Temporalio::Api::Cloud::CloudService::V1::DeleteConnectivityRuleRequest] API request.
847
+ # @param rpc_options [RPCOptions, nil] Advanced RPC options.
848
+ # @return [Temporalio::Api::Cloud::CloudService::V1::DeleteConnectivityRuleResponse] API response.
849
+ def delete_connectivity_rule(request, rpc_options: nil)
850
+ invoke_rpc(
851
+ rpc: 'delete_connectivity_rule',
852
+ request_class: Temporalio::Api::Cloud::CloudService::V1::DeleteConnectivityRuleRequest,
853
+ response_class: Temporalio::Api::Cloud::CloudService::V1::DeleteConnectivityRuleResponse,
854
+ request:,
855
+ rpc_options:
856
+ )
857
+ end
783
858
  end
784
859
  end
785
860
  end
@@ -1350,6 +1350,51 @@ module Temporalio
1350
1350
  rpc_options:
1351
1351
  )
1352
1352
  end
1353
+
1354
+ # Calls WorkflowService.UpdateTaskQueueConfig API call.
1355
+ #
1356
+ # @param request [Temporalio::Api::WorkflowService::V1::UpdateTaskQueueConfigRequest] API request.
1357
+ # @param rpc_options [RPCOptions, nil] Advanced RPC options.
1358
+ # @return [Temporalio::Api::WorkflowService::V1::UpdateTaskQueueConfigResponse] API response.
1359
+ def update_task_queue_config(request, rpc_options: nil)
1360
+ invoke_rpc(
1361
+ rpc: 'update_task_queue_config',
1362
+ request_class: Temporalio::Api::WorkflowService::V1::UpdateTaskQueueConfigRequest,
1363
+ response_class: Temporalio::Api::WorkflowService::V1::UpdateTaskQueueConfigResponse,
1364
+ request:,
1365
+ rpc_options:
1366
+ )
1367
+ end
1368
+
1369
+ # Calls WorkflowService.FetchWorkerConfig API call.
1370
+ #
1371
+ # @param request [Temporalio::Api::WorkflowService::V1::FetchWorkerConfigRequest] API request.
1372
+ # @param rpc_options [RPCOptions, nil] Advanced RPC options.
1373
+ # @return [Temporalio::Api::WorkflowService::V1::FetchWorkerConfigResponse] API response.
1374
+ def fetch_worker_config(request, rpc_options: nil)
1375
+ invoke_rpc(
1376
+ rpc: 'fetch_worker_config',
1377
+ request_class: Temporalio::Api::WorkflowService::V1::FetchWorkerConfigRequest,
1378
+ response_class: Temporalio::Api::WorkflowService::V1::FetchWorkerConfigResponse,
1379
+ request:,
1380
+ rpc_options:
1381
+ )
1382
+ end
1383
+
1384
+ # Calls WorkflowService.UpdateWorkerConfig API call.
1385
+ #
1386
+ # @param request [Temporalio::Api::WorkflowService::V1::UpdateWorkerConfigRequest] API request.
1387
+ # @param rpc_options [RPCOptions, nil] Advanced RPC options.
1388
+ # @return [Temporalio::Api::WorkflowService::V1::UpdateWorkerConfigResponse] API response.
1389
+ def update_worker_config(request, rpc_options: nil)
1390
+ invoke_rpc(
1391
+ rpc: 'update_worker_config',
1392
+ request_class: Temporalio::Api::WorkflowService::V1::UpdateWorkerConfigRequest,
1393
+ response_class: Temporalio::Api::WorkflowService::V1::UpdateWorkerConfigResponse,
1394
+ request:,
1395
+ rpc_options:
1396
+ )
1397
+ end
1353
1398
  end
1354
1399
  end
1355
1400
  end
@@ -124,7 +124,8 @@ module Temporalio
124
124
  # Options for HTTP CONNECT proxy for client connections.
125
125
  #
126
126
  # @!attribute target_host
127
- # @return [String] Target host:port for the HTTP CONNECT proxy.
127
+ # @return [String] Target for the HTTP CONNECT proxy. Use host:port for TCP, or unix:/path/to/unix.sock for Unix
128
+ # socket (meaning it'll start with "unix:/").
128
129
  # @!attribute basic_auth_user
129
130
  # @return [String, nil] User for HTTP basic auth for the proxy, must be combined with {basic_auth_pass}.
130
131
  # @!attribute basic_auth_pass
@@ -453,19 +453,15 @@ module Temporalio
453
453
  'temporalRunID' => Temporalio::Workflow.info.run_id }.merge(attributes)
454
454
 
455
455
  time = Temporalio::Workflow.now.dup
456
- # Disable illegal call tracing because OTel asks for full exception message which uses error highlighting and
457
- # such which accesses File#path, and they also use loggers accessing current time
458
- Temporalio::Workflow::Unsafe.illegal_call_tracing_disabled do
459
- # Disable durable scheduler because 1) synchronous/non-batch span processors in OTel use network (though
460
- # could have just used Unafe.io_enabled for this if not for the next point) and 2) OTel uses Ruby Timeout
461
- # which we don't want to use durable timers.
462
- Temporalio::Workflow::Unsafe.durable_scheduler_disabled do
463
- span = root.tracer.start_span(name, attributes:, links:, start_timestamp: time, kind:) # steep:ignore
464
- # Record exception if present
465
- span.record_exception(exception) if exception
466
- # Finish the span (returns self)
467
- span.finish(end_timestamp: time)
468
- end
456
+ # Disable durable scheduler because 1) synchronous/non-batch span processors in OTel use network (though could
457
+ # have just used Unafe.io_enabled for this if not for the next point) and 2) OTel uses Ruby Timeout which we
458
+ # don't want to use durable timers.
459
+ Temporalio::Workflow::Unsafe.durable_scheduler_disabled do
460
+ span = root.tracer.start_span(name, attributes:, links:, start_timestamp: time, kind:) # steep:ignore
461
+ # Record exception if present
462
+ span.record_exception(exception) if exception
463
+ # Finish the span (returns self)
464
+ span.finish(end_timestamp: time)
469
465
  end
470
466
  end
471
467
  end
@@ -3,6 +3,7 @@
3
3
  require 'json'
4
4
  require 'temporalio/api'
5
5
  require 'temporalio/converters/payload_converter/encoding'
6
+ require 'temporalio/workflow'
6
7
 
7
8
  module Temporalio
8
9
  module Converters
@@ -28,15 +29,31 @@ module Temporalio
28
29
 
29
30
  # (see Encoding.to_payload)
30
31
  def to_payload(value, hint: nil) # rubocop:disable Lint/UnusedMethodArgument
31
- Api::Common::V1::Payload.new(
32
- metadata: { 'encoding' => ENCODING },
33
- data: JSON.generate(value, @generate_options).b
34
- )
32
+ # For generate and parse, if we are in a workflow, we need to do this outside of the durable scheduler since
33
+ # some things like the recent https://github.com/ruby/json/pull/832 may make illegal File.expand_path calls.
34
+ # And other future things may be slightly illegal in JSON generate/parse and we don't want to break everyone
35
+ # when it happens.
36
+ data = if Temporalio::Workflow.in_workflow?
37
+ Temporalio::Workflow::Unsafe.durable_scheduler_disabled do
38
+ JSON.generate(value, @generate_options).b
39
+ end
40
+ else
41
+ JSON.generate(value, @generate_options).b
42
+ end
43
+
44
+ Api::Common::V1::Payload.new(metadata: { 'encoding' => ENCODING }, data:)
35
45
  end
36
46
 
37
47
  # (see Encoding.from_payload)
38
48
  def from_payload(payload, hint: nil) # rubocop:disable Lint/UnusedMethodArgument
39
- JSON.parse(payload.data, @parse_options)
49
+ # See comment in to_payload about why we have to do something different in workflow
50
+ if Temporalio::Workflow.in_workflow?
51
+ Temporalio::Workflow::Unsafe.durable_scheduler_disabled do
52
+ JSON.parse(payload.data, @parse_options)
53
+ end
54
+ else
55
+ JSON.parse(payload.data, @parse_options)
56
+ end
40
57
  end
41
58
  end
42
59
  end
@@ -17,7 +17,7 @@ require 'temporalio/internal/bridge/api/common/common'
17
17
  require 'temporalio/internal/bridge/api/nexus/nexus'
18
18
 
19
19
 
20
- descriptor_data = "\n?temporal/sdk/core/workflow_activation/workflow_activation.proto\x12\x1b\x63oresdk.workflow_activation\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a\x37temporal/sdk/core/activity_result/activity_result.proto\x1a\x35temporal/sdk/core/child_workflow/child_workflow.proto\x1a%temporal/sdk/core/common/common.proto\x1a#temporal/sdk/core/nexus/nexus.proto\"\xfa\x02\n\x12WorkflowActivation\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12-\n\ttimestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x14\n\x0cis_replaying\x18\x03 \x01(\x08\x12\x16\n\x0ehistory_length\x18\x04 \x01(\r\x12@\n\x04jobs\x18\x05 \x03(\x0b\x32\x32.coresdk.workflow_activation.WorkflowActivationJob\x12 \n\x18\x61vailable_internal_flags\x18\x06 \x03(\r\x12\x1a\n\x12history_size_bytes\x18\x07 \x01(\x04\x12!\n\x19\x63ontinue_as_new_suggested\x18\x08 \x01(\x08\x12T\n#deployment_version_for_current_task\x18\t \x01(\x0b\x32\'.coresdk.common.WorkerDeploymentVersion\"\xe0\n\n\x15WorkflowActivationJob\x12N\n\x13initialize_workflow\x18\x01 \x01(\x0b\x32/.coresdk.workflow_activation.InitializeWorkflowH\x00\x12<\n\nfire_timer\x18\x02 \x01(\x0b\x32&.coresdk.workflow_activation.FireTimerH\x00\x12K\n\x12update_random_seed\x18\x04 \x01(\x0b\x32-.coresdk.workflow_activation.UpdateRandomSeedH\x00\x12\x44\n\x0equery_workflow\x18\x05 \x01(\x0b\x32*.coresdk.workflow_activation.QueryWorkflowH\x00\x12\x46\n\x0f\x63\x61ncel_workflow\x18\x06 \x01(\x0b\x32+.coresdk.workflow_activation.CancelWorkflowH\x00\x12\x46\n\x0fsignal_workflow\x18\x07 \x01(\x0b\x32+.coresdk.workflow_activation.SignalWorkflowH\x00\x12H\n\x10resolve_activity\x18\x08 \x01(\x0b\x32,.coresdk.workflow_activation.ResolveActivityH\x00\x12G\n\x10notify_has_patch\x18\t \x01(\x0b\x32+.coresdk.workflow_activation.NotifyHasPatchH\x00\x12q\n&resolve_child_workflow_execution_start\x18\n \x01(\x0b\x32?.coresdk.workflow_activation.ResolveChildWorkflowExecutionStartH\x00\x12\x66\n resolve_child_workflow_execution\x18\x0b \x01(\x0b\x32:.coresdk.workflow_activation.ResolveChildWorkflowExecutionH\x00\x12\x66\n resolve_signal_external_workflow\x18\x0c \x01(\x0b\x32:.coresdk.workflow_activation.ResolveSignalExternalWorkflowH\x00\x12u\n(resolve_request_cancel_external_workflow\x18\r \x01(\x0b\x32\x41.coresdk.workflow_activation.ResolveRequestCancelExternalWorkflowH\x00\x12:\n\tdo_update\x18\x0e \x01(\x0b\x32%.coresdk.workflow_activation.DoUpdateH\x00\x12`\n\x1dresolve_nexus_operation_start\x18\x0f \x01(\x0b\x32\x37.coresdk.workflow_activation.ResolveNexusOperationStartH\x00\x12U\n\x17resolve_nexus_operation\x18\x10 \x01(\x0b\x32\x32.coresdk.workflow_activation.ResolveNexusOperationH\x00\x12I\n\x11remove_from_cache\x18\x32 \x01(\x0b\x32,.coresdk.workflow_activation.RemoveFromCacheH\x00\x42\t\n\x07variant\"\xd9\n\n\x12InitializeWorkflow\x12\x15\n\rworkflow_type\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x32\n\targuments\x18\x03 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x17\n\x0frandomness_seed\x18\x04 \x01(\x04\x12M\n\x07headers\x18\x05 \x03(\x0b\x32<.coresdk.workflow_activation.InitializeWorkflow.HeadersEntry\x12\x10\n\x08identity\x18\x06 \x01(\t\x12I\n\x14parent_workflow_info\x18\x07 \x01(\x0b\x32+.coresdk.common.NamespacedWorkflowExecution\x12=\n\x1aworkflow_execution_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\'\n\x1f\x63ontinued_from_execution_run_id\x18\x0b \x01(\t\x12J\n\x13\x63ontinued_initiator\x18\x0c \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12;\n\x11\x63ontinued_failure\x18\r \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x1e\n\x16\x66irst_execution_run_id\x18\x0f \x01(\t\x12\x39\n\x0cretry_policy\x18\x10 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x0f\n\x07\x61ttempt\x18\x11 \x01(\x05\x12\x15\n\rcron_schedule\x18\x12 \x01(\t\x12\x46\n\"workflow_execution_expiration_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\"cron_schedule_to_schedule_interval\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12*\n\x04memo\x18\x15 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x16 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\nstart_time\x18\x17 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\rroot_workflow\x18\x18 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x08priority\x18\x19 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"\x18\n\tFireTimer\x12\x0b\n\x03seq\x18\x01 \x01(\r\"m\n\x0fResolveActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12;\n\x06result\x18\x02 \x01(\x0b\x32+.coresdk.activity_result.ActivityResolution\x12\x10\n\x08is_local\x18\x03 \x01(\x08\"\xd1\x02\n\"ResolveChildWorkflowExecutionStart\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12[\n\tsucceeded\x18\x02 \x01(\x0b\x32\x46.coresdk.workflow_activation.ResolveChildWorkflowExecutionStartSuccessH\x00\x12X\n\x06\x66\x61iled\x18\x03 \x01(\x0b\x32\x46.coresdk.workflow_activation.ResolveChildWorkflowExecutionStartFailureH\x00\x12]\n\tcancelled\x18\x04 \x01(\x0b\x32H.coresdk.workflow_activation.ResolveChildWorkflowExecutionStartCancelledH\x00\x42\x08\n\x06status\";\n)ResolveChildWorkflowExecutionStartSuccess\x12\x0e\n\x06run_id\x18\x01 \x01(\t\"\xa6\x01\n)ResolveChildWorkflowExecutionStartFailure\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x15\n\rworkflow_type\x18\x02 \x01(\t\x12M\n\x05\x63\x61use\x18\x03 \x01(\x0e\x32>.coresdk.child_workflow.StartChildWorkflowExecutionFailedCause\"`\n+ResolveChildWorkflowExecutionStartCancelled\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\"i\n\x1dResolveChildWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12;\n\x06result\x18\x02 \x01(\x0b\x32+.coresdk.child_workflow.ChildWorkflowResult\"+\n\x10UpdateRandomSeed\x12\x17\n\x0frandomness_seed\x18\x01 \x01(\x04\"\x84\x02\n\rQueryWorkflow\x12\x10\n\x08query_id\x18\x01 \x01(\t\x12\x12\n\nquery_type\x18\x02 \x01(\t\x12\x32\n\targuments\x18\x03 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12H\n\x07headers\x18\x05 \x03(\x0b\x32\x37.coresdk.workflow_activation.QueryWorkflow.HeadersEntry\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\" \n\x0e\x43\x61ncelWorkflow\x12\x0e\n\x06reason\x18\x01 \x01(\t\"\x83\x02\n\x0eSignalWorkflow\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12.\n\x05input\x18\x02 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x10\n\x08identity\x18\x03 \x01(\t\x12I\n\x07headers\x18\x05 \x03(\x0b\x32\x38.coresdk.workflow_activation.SignalWorkflow.HeadersEntry\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"\"\n\x0eNotifyHasPatch\x12\x10\n\x08patch_id\x18\x01 \x01(\t\"_\n\x1dResolveSignalExternalWorkflow\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\"f\n$ResolveRequestCancelExternalWorkflow\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\"\xcb\x02\n\x08\x44oUpdate\x12\n\n\x02id\x18\x01 \x01(\t\x12\x1c\n\x14protocol_instance_id\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x43\n\x07headers\x18\x05 \x03(\x0b\x32\x32.coresdk.workflow_activation.DoUpdate.HeadersEntry\x12*\n\x04meta\x18\x06 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12\x15\n\rrun_validator\x18\x07 \x01(\x08\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"\xaa\x01\n\x1aResolveNexusOperationStart\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x19\n\x0foperation_token\x18\x02 \x01(\tH\x00\x12\x16\n\x0cstarted_sync\x18\x03 \x01(\x08H\x00\x12\x42\n\x16\x63\x61ncelled_before_start\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x08\n\x06status\"Y\n\x15ResolveNexusOperation\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x33\n\x06result\x18\x02 \x01(\x0b\x32#.coresdk.nexus.NexusOperationResult\"\xe0\x02\n\x0fRemoveFromCache\x12\x0f\n\x07message\x18\x01 \x01(\t\x12K\n\x06reason\x18\x02 \x01(\x0e\x32;.coresdk.workflow_activation.RemoveFromCache.EvictionReason\"\xee\x01\n\x0e\x45victionReason\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x0e\n\nCACHE_FULL\x10\x01\x12\x0e\n\nCACHE_MISS\x10\x02\x12\x12\n\x0eNONDETERMINISM\x10\x03\x12\r\n\tLANG_FAIL\x10\x04\x12\x12\n\x0eLANG_REQUESTED\x10\x05\x12\x12\n\x0eTASK_NOT_FOUND\x10\x06\x12\x15\n\x11UNHANDLED_COMMAND\x10\x07\x12\t\n\x05\x46\x41TAL\x10\x08\x12\x1f\n\x1bPAGINATION_OR_HISTORY_FETCH\x10\t\x12\x1d\n\x19WORKFLOW_EXECUTION_ENDING\x10\nB8\xea\x02\x35Temporalio::Internal::Bridge::Api::WorkflowActivationb\x06proto3"
20
+ descriptor_data = "\n?temporal/sdk/core/workflow_activation/workflow_activation.proto\x12\x1b\x63oresdk.workflow_activation\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a\x37temporal/sdk/core/activity_result/activity_result.proto\x1a\x35temporal/sdk/core/child_workflow/child_workflow.proto\x1a%temporal/sdk/core/common/common.proto\x1a#temporal/sdk/core/nexus/nexus.proto\"\xfa\x02\n\x12WorkflowActivation\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12-\n\ttimestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x14\n\x0cis_replaying\x18\x03 \x01(\x08\x12\x16\n\x0ehistory_length\x18\x04 \x01(\r\x12@\n\x04jobs\x18\x05 \x03(\x0b\x32\x32.coresdk.workflow_activation.WorkflowActivationJob\x12 \n\x18\x61vailable_internal_flags\x18\x06 \x03(\r\x12\x1a\n\x12history_size_bytes\x18\x07 \x01(\x04\x12!\n\x19\x63ontinue_as_new_suggested\x18\x08 \x01(\x08\x12T\n#deployment_version_for_current_task\x18\t \x01(\x0b\x32\'.coresdk.common.WorkerDeploymentVersion\"\xe0\n\n\x15WorkflowActivationJob\x12N\n\x13initialize_workflow\x18\x01 \x01(\x0b\x32/.coresdk.workflow_activation.InitializeWorkflowH\x00\x12<\n\nfire_timer\x18\x02 \x01(\x0b\x32&.coresdk.workflow_activation.FireTimerH\x00\x12K\n\x12update_random_seed\x18\x04 \x01(\x0b\x32-.coresdk.workflow_activation.UpdateRandomSeedH\x00\x12\x44\n\x0equery_workflow\x18\x05 \x01(\x0b\x32*.coresdk.workflow_activation.QueryWorkflowH\x00\x12\x46\n\x0f\x63\x61ncel_workflow\x18\x06 \x01(\x0b\x32+.coresdk.workflow_activation.CancelWorkflowH\x00\x12\x46\n\x0fsignal_workflow\x18\x07 \x01(\x0b\x32+.coresdk.workflow_activation.SignalWorkflowH\x00\x12H\n\x10resolve_activity\x18\x08 \x01(\x0b\x32,.coresdk.workflow_activation.ResolveActivityH\x00\x12G\n\x10notify_has_patch\x18\t \x01(\x0b\x32+.coresdk.workflow_activation.NotifyHasPatchH\x00\x12q\n&resolve_child_workflow_execution_start\x18\n \x01(\x0b\x32?.coresdk.workflow_activation.ResolveChildWorkflowExecutionStartH\x00\x12\x66\n resolve_child_workflow_execution\x18\x0b \x01(\x0b\x32:.coresdk.workflow_activation.ResolveChildWorkflowExecutionH\x00\x12\x66\n resolve_signal_external_workflow\x18\x0c \x01(\x0b\x32:.coresdk.workflow_activation.ResolveSignalExternalWorkflowH\x00\x12u\n(resolve_request_cancel_external_workflow\x18\r \x01(\x0b\x32\x41.coresdk.workflow_activation.ResolveRequestCancelExternalWorkflowH\x00\x12:\n\tdo_update\x18\x0e \x01(\x0b\x32%.coresdk.workflow_activation.DoUpdateH\x00\x12`\n\x1dresolve_nexus_operation_start\x18\x0f \x01(\x0b\x32\x37.coresdk.workflow_activation.ResolveNexusOperationStartH\x00\x12U\n\x17resolve_nexus_operation\x18\x10 \x01(\x0b\x32\x32.coresdk.workflow_activation.ResolveNexusOperationH\x00\x12I\n\x11remove_from_cache\x18\x32 \x01(\x0b\x32,.coresdk.workflow_activation.RemoveFromCacheH\x00\x42\t\n\x07variant\"\xd9\n\n\x12InitializeWorkflow\x12\x15\n\rworkflow_type\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x32\n\targuments\x18\x03 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x17\n\x0frandomness_seed\x18\x04 \x01(\x04\x12M\n\x07headers\x18\x05 \x03(\x0b\x32<.coresdk.workflow_activation.InitializeWorkflow.HeadersEntry\x12\x10\n\x08identity\x18\x06 \x01(\t\x12I\n\x14parent_workflow_info\x18\x07 \x01(\x0b\x32+.coresdk.common.NamespacedWorkflowExecution\x12=\n\x1aworkflow_execution_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\'\n\x1f\x63ontinued_from_execution_run_id\x18\x0b \x01(\t\x12J\n\x13\x63ontinued_initiator\x18\x0c \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12;\n\x11\x63ontinued_failure\x18\r \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x1e\n\x16\x66irst_execution_run_id\x18\x0f \x01(\t\x12\x39\n\x0cretry_policy\x18\x10 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x0f\n\x07\x61ttempt\x18\x11 \x01(\x05\x12\x15\n\rcron_schedule\x18\x12 \x01(\t\x12\x46\n\"workflow_execution_expiration_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\"cron_schedule_to_schedule_interval\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12*\n\x04memo\x18\x15 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x16 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\nstart_time\x18\x17 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\rroot_workflow\x18\x18 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x08priority\x18\x19 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"\x18\n\tFireTimer\x12\x0b\n\x03seq\x18\x01 \x01(\r\"m\n\x0fResolveActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12;\n\x06result\x18\x02 \x01(\x0b\x32+.coresdk.activity_result.ActivityResolution\x12\x10\n\x08is_local\x18\x03 \x01(\x08\"\xd1\x02\n\"ResolveChildWorkflowExecutionStart\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12[\n\tsucceeded\x18\x02 \x01(\x0b\x32\x46.coresdk.workflow_activation.ResolveChildWorkflowExecutionStartSuccessH\x00\x12X\n\x06\x66\x61iled\x18\x03 \x01(\x0b\x32\x46.coresdk.workflow_activation.ResolveChildWorkflowExecutionStartFailureH\x00\x12]\n\tcancelled\x18\x04 \x01(\x0b\x32H.coresdk.workflow_activation.ResolveChildWorkflowExecutionStartCancelledH\x00\x42\x08\n\x06status\";\n)ResolveChildWorkflowExecutionStartSuccess\x12\x0e\n\x06run_id\x18\x01 \x01(\t\"\xa6\x01\n)ResolveChildWorkflowExecutionStartFailure\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x15\n\rworkflow_type\x18\x02 \x01(\t\x12M\n\x05\x63\x61use\x18\x03 \x01(\x0e\x32>.coresdk.child_workflow.StartChildWorkflowExecutionFailedCause\"`\n+ResolveChildWorkflowExecutionStartCancelled\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\"i\n\x1dResolveChildWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12;\n\x06result\x18\x02 \x01(\x0b\x32+.coresdk.child_workflow.ChildWorkflowResult\"+\n\x10UpdateRandomSeed\x12\x17\n\x0frandomness_seed\x18\x01 \x01(\x04\"\x84\x02\n\rQueryWorkflow\x12\x10\n\x08query_id\x18\x01 \x01(\t\x12\x12\n\nquery_type\x18\x02 \x01(\t\x12\x32\n\targuments\x18\x03 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12H\n\x07headers\x18\x05 \x03(\x0b\x32\x37.coresdk.workflow_activation.QueryWorkflow.HeadersEntry\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\" \n\x0e\x43\x61ncelWorkflow\x12\x0e\n\x06reason\x18\x01 \x01(\t\"\x83\x02\n\x0eSignalWorkflow\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12.\n\x05input\x18\x02 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x10\n\x08identity\x18\x03 \x01(\t\x12I\n\x07headers\x18\x05 \x03(\x0b\x32\x38.coresdk.workflow_activation.SignalWorkflow.HeadersEntry\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"\"\n\x0eNotifyHasPatch\x12\x10\n\x08patch_id\x18\x01 \x01(\t\"_\n\x1dResolveSignalExternalWorkflow\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\"f\n$ResolveRequestCancelExternalWorkflow\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\"\xcb\x02\n\x08\x44oUpdate\x12\n\n\x02id\x18\x01 \x01(\t\x12\x1c\n\x14protocol_instance_id\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x43\n\x07headers\x18\x05 \x03(\x0b\x32\x32.coresdk.workflow_activation.DoUpdate.HeadersEntry\x12*\n\x04meta\x18\x06 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12\x15\n\rrun_validator\x18\x07 \x01(\x08\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"\x9a\x01\n\x1aResolveNexusOperationStart\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x19\n\x0foperation_token\x18\x02 \x01(\tH\x00\x12\x16\n\x0cstarted_sync\x18\x03 \x01(\x08H\x00\x12\x32\n\x06\x66\x61iled\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x08\n\x06status\"Y\n\x15ResolveNexusOperation\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x33\n\x06result\x18\x02 \x01(\x0b\x32#.coresdk.nexus.NexusOperationResult\"\xe0\x02\n\x0fRemoveFromCache\x12\x0f\n\x07message\x18\x01 \x01(\t\x12K\n\x06reason\x18\x02 \x01(\x0e\x32;.coresdk.workflow_activation.RemoveFromCache.EvictionReason\"\xee\x01\n\x0e\x45victionReason\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x0e\n\nCACHE_FULL\x10\x01\x12\x0e\n\nCACHE_MISS\x10\x02\x12\x12\n\x0eNONDETERMINISM\x10\x03\x12\r\n\tLANG_FAIL\x10\x04\x12\x12\n\x0eLANG_REQUESTED\x10\x05\x12\x12\n\x0eTASK_NOT_FOUND\x10\x06\x12\x15\n\x11UNHANDLED_COMMAND\x10\x07\x12\t\n\x05\x46\x41TAL\x10\x08\x12\x1f\n\x1bPAGINATION_OR_HISTORY_FETCH\x10\t\x12\x1d\n\x19WORKFLOW_EXECUTION_ENDING\x10\nB8\xea\x02\x35Temporalio::Internal::Bridge::Api::WorkflowActivationb\x06proto3"
21
21
 
22
22
  pool = ::Google::Protobuf::DescriptorPool.generated_pool
23
23
  pool.add_serialized_file(descriptor_data)
@@ -63,12 +63,13 @@ module Temporalio
63
63
  end
64
64
 
65
65
  def durable_scheduler_disabled(&)
66
- prev = Fiber.current_scheduler
67
- illegal_call_tracing_disabled { Fiber.set_scheduler(nil) }
68
- begin
66
+ prev = Fiber.scheduler
67
+ # Imply illegal call tracing disabled
68
+ illegal_call_tracing_disabled do
69
+ Fiber.set_scheduler(nil)
69
70
  yield
70
71
  ensure
71
- illegal_call_tracing_disabled { Fiber.set_scheduler(prev) }
72
+ Fiber.set_scheduler(prev)
72
73
  end
73
74
  end
74
75
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'delegate'
4
+
3
5
  module Temporalio
4
6
  module Internal
5
7
  module Worker
@@ -16,7 +16,7 @@ module Temporalio
16
16
  # @type var fixed_val: :all | Worker::IllegalWorkflowCallValidator | Hash[Symbol, TrueClass | Worker::IllegalWorkflowCallValidator] # rubocop:disable Layout/LineLength
17
17
  fixed_val = case val
18
18
  when Temporalio::Worker::IllegalWorkflowCallValidator
19
- if sub_val.method_name
19
+ if val.method_name
20
20
  raise ArgumentError,
21
21
  'Top level IllegalWorkflowCallValidator instances cannot have method name'
22
22
  end
@@ -27,8 +27,11 @@ module Temporalio
27
27
  return true
28
28
  end
29
29
 
30
- # Disable illegal call tracing for the log call
31
- @instance.illegal_call_tracing_disabled { super }
30
+ # Disable scheduler since logs technically have local mutexes in them that cannot be done durably or they
31
+ # will block workflows
32
+ @instance.context.durable_scheduler_disabled do
33
+ super
34
+ end
32
35
  end
33
36
  end
34
37
  end
@@ -40,10 +40,15 @@ module Temporalio
40
40
  cond_fiber = nil
41
41
  cond_result = nil
42
42
  @wait_conditions.each do |seq, cond|
43
+ # Evaluate condition or skip if not true
43
44
  next unless (cond_result = cond.first.call)
44
45
 
45
- cond_fiber = cond[1]
46
- @wait_conditions.delete(seq)
46
+ # There have been reports of this fiber being completed already, so we make sure not to process if it
47
+ # has, but we still delete it
48
+ deleted_cond = @wait_conditions.delete(seq)
49
+ next unless deleted_cond&.last&.alive?
50
+
51
+ cond_fiber = deleted_cond.last
47
52
  break
48
53
  end
49
54
  return unless cond_fiber
@@ -106,7 +111,7 @@ module Temporalio
106
111
  # We just yield because unblock will resume this. We will just wrap in timeout if needed.
107
112
  if timeout
108
113
  begin
109
- Timeout.timeout(timeout) { Fiber.yield }
114
+ Workflow.timeout(timeout) { Fiber.yield }
110
115
  true
111
116
  rescue Timeout::Error
112
117
  false
@@ -141,7 +146,8 @@ module Temporalio
141
146
  unless @instance.io_enabled
142
147
  raise Workflow::NondeterminismError,
143
148
  'Cannot perform IO from inside a workflow. If this is known to be safe, ' \
144
- 'the code can be run in a Temporalio::Workflow::Unsafe.io_enabled block.'
149
+ 'the code can be run in a Temporalio::Workflow::Unsafe.durable_scheduler_disabled ' \
150
+ 'or Temporalio::Workflow::Unsafe.io_enabled block.'
145
151
  end
146
152
 
147
153
  # Use regular Ruby behavior of blocking this thread. There is no Ruby implementation of io_wait we can just
@@ -4,7 +4,9 @@ require 'temporalio/api'
4
4
 
5
5
  module Temporalio
6
6
  Priority = Data.define(
7
- :priority_key
7
+ :priority_key,
8
+ :fairness_key,
9
+ :fairness_weight
8
10
  )
9
11
 
10
12
  # Priority contains metadata that controls relative ordering of task processing when tasks are
@@ -29,31 +31,70 @@ module Temporalio
29
31
  #
30
32
  # The default priority is (min+max)/2. With the default max of 5 and min of 1, that comes
31
33
  # out to 3.
34
+ #
35
+ # @!attribute fairness_key
36
+ # @return [String, nil] FairnessKey is a short string that's used as a key for a fairness
37
+ # balancing mechanism. It may correspond to a tenant id, or to a fixed
38
+ # string like "high" or "low". The default is the empty string.
39
+ #
40
+ # The fairness mechanism attempts to dispatch tasks for a given key in
41
+ # proportion to its weight. For example, using a thousand distinct tenant
42
+ # ids, each with a weight of 1.0 (the default) will result in each tenant
43
+ # getting a roughly equal share of task dispatch throughput.
44
+ #
45
+ # Fairness keys are limited to 64 bytes.
46
+ #
47
+ # @!attribute fairness_weight
48
+ # @return [Float, nil] Weight for a task can come from multiple sources for
49
+ # flexibility. From highest to lowest precedence:
50
+ # 1. Weights for a small set of keys can be overridden in task queue
51
+ # configuration with an API.
52
+ # 2. It can be attached to the workflow/activity in this field.
53
+ # 3. The default fairness_weight of 1.0 will be used.
54
+ #
55
+ # Weight values are clamped to the range [0.001, 1000].
32
56
  class Priority
33
57
  # @!visibility private
34
58
  def self._from_proto(priority)
35
59
  return default if priority.nil?
36
60
 
37
- new(priority_key: priority.priority_key.zero? ? nil : priority.priority_key)
61
+ new(
62
+ priority_key: priority.priority_key.zero? ? nil : priority.priority_key,
63
+ fairness_key: priority.fairness_key.empty? ? nil : priority.fairness_key,
64
+ fairness_weight: priority.fairness_weight.zero? ? nil : priority.fairness_weight
65
+ )
38
66
  end
39
67
 
40
68
  # The default priority instance.
41
69
  #
42
70
  # @return [Priority] The default priority
43
71
  def self.default
44
- @default ||= new(priority_key: nil)
72
+ @default ||= new(priority_key: nil, fairness_key: nil, fairness_weight: nil)
73
+ end
74
+
75
+ # Initialize a new Priority instance.
76
+ #
77
+ # @param priority_key [Integer, nil] The priority key
78
+ # @param fairness_key [String, nil] The fairness key
79
+ # @param fairness_weight [Float, nil] The fairness weight
80
+ def initialize(priority_key: nil, fairness_key: nil, fairness_weight: nil)
81
+ super
45
82
  end
46
83
 
47
84
  # @!visibility private
48
85
  def _to_proto
49
- return nil if priority_key.nil?
86
+ return nil if empty?
50
87
 
51
- Temporalio::Api::Common::V1::Priority.new(priority_key: priority_key || 0)
88
+ Temporalio::Api::Common::V1::Priority.new(
89
+ priority_key: priority_key || 0,
90
+ fairness_key: fairness_key || '',
91
+ fairness_weight: fairness_weight || 0.0
92
+ )
52
93
  end
53
94
 
54
95
  # @return [Boolean] True if this priority is empty/default
55
96
  def empty?
56
- priority_key.nil?
97
+ priority_key.nil? && fairness_key.nil? && fairness_weight.nil?
57
98
  end
58
99
  end
59
100
  end
@@ -17,7 +17,7 @@ module Temporalio
17
17
 
18
18
  # @see Logger.add
19
19
  def add(severity, message = nil, progname = nil)
20
- return true if (severity || Logger::Unknown) < level
20
+ return true if (severity || Logger::UNKNOWN) < level
21
21
  return super if scoped_values_getter.nil? || @disable_scoped_values
22
22
 
23
23
  scoped_values = scoped_values_getter.call
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Temporalio
4
- VERSION = '0.5.0'
4
+ VERSION = '0.6.0'
5
5
  end
@@ -39,6 +39,15 @@ module Temporalio
39
39
  ]
40
40
  end
41
41
 
42
+ # @return [IllegalWorkflowCallValidator] Workflow call validator that is tailored to disallow most Mutex calls,
43
+ # but let others through for certain situations.
44
+ def self.known_safe_mutex_validator
45
+ @known_safe_mutex_validator ||= IllegalWorkflowCallValidator.new do
46
+ # Only Google Protobuf use of Mutex is known to be safe, fail unless any caller location path has protobuf
47
+ raise 'disallowed' unless caller_locations&.any? { |loc| loc.path&.include?('google/protobuf/') }
48
+ end
49
+ end
50
+
42
51
  # @return [String, nil] Method name if this validator is specific to a method.
43
52
  attr_reader :method_name
44
53
 
@@ -267,7 +267,11 @@ module Temporalio
267
267
  #:write
268
268
  ],
269
269
  'Kernel' => %i[abort at_exit autoload autoload? eval exec exit fork gets load open rand readline readlines
270
- spawn srand system test trap],
270
+ sleep spawn srand system test trap],
271
+ # Loggers use mutexes in ways that can hang workflows, so users need to disable the durable scheduler to use
272
+ # them
273
+ 'Logger' => :all,
274
+ 'Monitor' => :all,
271
275
  'Net::HTTP' => :all,
272
276
  'Pathname' => :all,
273
277
  # TODO(cretz): Investigate why clock_gettime called from Timeout thread affects this code at all. Stack trace
@@ -282,9 +286,14 @@ module Temporalio
282
286
  'Signal' => :all,
283
287
  'Socket' => :all,
284
288
  'Tempfile' => :all,
289
+ 'Timeout' => :all,
285
290
  'Thread' => %i[abort_on_exception= exit fork handle_interrupt ignore_deadlock= kill new pass
286
291
  pending_interrupt? report_on_exception= start stop initialize join name= priority= raise run
287
292
  terminate thread_variable_set wakeup],
293
+ 'Thread::ConditionVariable' => :all,
294
+ 'Thread::Mutex' => IllegalWorkflowCallValidator.known_safe_mutex_validator,
295
+ 'Thread::SizedQueue' => :all,
296
+ 'Thread::Queue' => :all,
288
297
  'Time' => IllegalWorkflowCallValidator.default_time_validators
289
298
  } #: Hash[String, :all | Array[Symbol]]
290
299
  hash.each_value(&:freeze)
@@ -280,7 +280,7 @@ module Temporalio
280
280
  @workflow_update_validators ||= {}
281
281
  @defined_methods ||= []
282
282
 
283
- defn, hash, other_hashes =
283
+ defn, hash =
284
284
  case handler[:type]
285
285
  when :init
286
286
  raise "workflow_init was applied to #{method_name} instead of initialize" if method_name != :initialize
@@ -306,7 +306,7 @@ module Temporalio
306
306
  raw_args: handler[:raw_args],
307
307
  unfinished_policy: handler[:unfinished_policy],
308
308
  arg_hints: handler[:arg_hints]
309
- ), @workflow_signals, [@workflow_queries, @workflow_updates]]
309
+ ), @workflow_signals]
310
310
  when :query
311
311
  [Query.new(
312
312
  name: handler[:dynamic] ? nil : (handler[:name] || method_name).to_s,
@@ -315,7 +315,7 @@ module Temporalio
315
315
  raw_args: handler[:raw_args],
316
316
  arg_hints: handler[:arg_hints],
317
317
  result_hint: handler[:result_hint]
318
- ), @workflow_queries, [@workflow_signals, @workflow_updates]]
318
+ ), @workflow_queries]
319
319
  when :update
320
320
  [Update.new(
321
321
  name: handler[:dynamic] ? nil : (handler[:name] || method_name).to_s,
@@ -325,7 +325,7 @@ module Temporalio
325
325
  unfinished_policy: handler[:unfinished_policy],
326
326
  arg_hints: handler[:arg_hints],
327
327
  result_hint: handler[:result_hint]
328
- ), @workflow_updates, [@workflow_signals, @workflow_queries]]
328
+ ), @workflow_updates]
329
329
  when :dynamic_options
330
330
  raise 'Dynamic options method already set' if @dynamic_options_method
331
331
 
@@ -341,8 +341,6 @@ module Temporalio
341
341
  if other && other.to_invoke != method_name
342
342
  raise "Workflow #{handler[:type].name} #{defn.name || '<dynamic>'} defined on " \
343
343
  "different methods #{other.to_invoke} and #{method_name}"
344
- elsif defn.name && other_hashes.any? { |h| h.include?(defn.name) }
345
- raise "Workflow signal #{defn.name} already defined as a different handler type"
346
344
  end
347
345
  hash[defn.name] = defn
348
346