temporalio 0.4.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.
- checksums.yaml +4 -4
- data/.yardopts +1 -1
- data/Cargo.lock +735 -479
- data/Cargo.toml +5 -5
- data/README.md +188 -39
- data/ext/Cargo.toml +3 -3
- data/lib/temporalio/activity/cancellation_details.rb +58 -0
- data/lib/temporalio/activity/context.rb +10 -1
- data/lib/temporalio/activity/definition.rb +41 -3
- data/lib/temporalio/activity/info.rb +25 -4
- data/lib/temporalio/activity.rb +2 -0
- data/lib/temporalio/api/activity/v1/message.rb +1 -1
- data/lib/temporalio/api/batch/v1/message.rb +7 -2
- data/lib/temporalio/api/cloud/account/v1/message.rb +1 -1
- data/lib/temporalio/api/cloud/cloudservice/v1/request_response.rb +22 -2
- data/lib/temporalio/api/cloud/cloudservice/v1/service.rb +2 -2
- data/lib/temporalio/api/cloud/connectivityrule/v1/message.rb +29 -0
- data/lib/temporalio/api/cloud/identity/v1/message.rb +7 -2
- data/lib/temporalio/api/cloud/namespace/v1/message.rb +7 -2
- data/lib/temporalio/api/cloud/nexus/v1/message.rb +3 -2
- data/lib/temporalio/api/cloud/operation/v1/message.rb +2 -2
- data/lib/temporalio/api/cloud/region/v1/message.rb +1 -1
- data/lib/temporalio/api/cloud/resource/v1/message.rb +1 -1
- data/lib/temporalio/api/cloud/sink/v1/message.rb +1 -1
- data/lib/temporalio/api/cloud/usage/v1/message.rb +1 -1
- data/lib/temporalio/api/command/v1/message.rb +2 -2
- data/lib/temporalio/api/common/v1/grpc_status.rb +1 -1
- data/lib/temporalio/api/common/v1/message.rb +4 -2
- data/lib/temporalio/api/deployment/v1/message.rb +3 -2
- data/lib/temporalio/api/enums/v1/batch_operation.rb +2 -2
- data/lib/temporalio/api/enums/v1/command_type.rb +1 -1
- data/lib/temporalio/api/enums/v1/common.rb +5 -2
- data/lib/temporalio/api/enums/v1/deployment.rb +3 -2
- data/lib/temporalio/api/enums/v1/event_type.rb +2 -2
- data/lib/temporalio/api/enums/v1/failed_cause.rb +2 -2
- data/lib/temporalio/api/enums/v1/namespace.rb +1 -1
- data/lib/temporalio/api/enums/v1/nexus.rb +1 -1
- data/lib/temporalio/api/enums/v1/query.rb +1 -1
- data/lib/temporalio/api/enums/v1/reset.rb +1 -1
- data/lib/temporalio/api/enums/v1/schedule.rb +1 -1
- data/lib/temporalio/api/enums/v1/task_queue.rb +3 -2
- data/lib/temporalio/api/enums/v1/update.rb +1 -1
- data/lib/temporalio/api/enums/v1/workflow.rb +2 -2
- data/lib/temporalio/api/errordetails/v1/message.rb +1 -1
- data/lib/temporalio/api/export/v1/message.rb +1 -1
- data/lib/temporalio/api/failure/v1/message.rb +3 -2
- data/lib/temporalio/api/filter/v1/message.rb +1 -1
- data/lib/temporalio/api/history/v1/message.rb +4 -2
- data/lib/temporalio/api/namespace/v1/message.rb +1 -1
- data/lib/temporalio/api/nexus/v1/message.rb +2 -2
- data/lib/temporalio/api/operatorservice/v1/request_response.rb +1 -1
- data/lib/temporalio/api/operatorservice/v1/service.rb +1 -1
- data/lib/temporalio/api/payload_visitor.rb +106 -1
- data/lib/temporalio/api/protocol/v1/message.rb +1 -1
- data/lib/temporalio/api/query/v1/message.rb +1 -1
- data/lib/temporalio/api/replication/v1/message.rb +1 -1
- data/lib/temporalio/api/rules/v1/message.rb +27 -0
- data/lib/temporalio/api/schedule/v1/message.rb +2 -2
- data/lib/temporalio/api/sdk/v1/enhanced_stack_trace.rb +1 -1
- data/lib/temporalio/api/sdk/v1/task_complete_metadata.rb +1 -1
- data/lib/temporalio/api/sdk/v1/user_metadata.rb +1 -1
- data/lib/temporalio/api/sdk/v1/worker_config.rb +23 -0
- data/lib/temporalio/api/sdk/v1/workflow_metadata.rb +1 -1
- data/lib/temporalio/api/taskqueue/v1/message.rb +6 -2
- data/lib/temporalio/api/testservice/v1/request_response.rb +1 -1
- data/lib/temporalio/api/testservice/v1/service.rb +1 -1
- data/lib/temporalio/api/update/v1/message.rb +1 -1
- data/lib/temporalio/api/version/v1/message.rb +1 -1
- data/lib/temporalio/api/worker/v1/message.rb +31 -0
- data/lib/temporalio/api/workflow/v1/message.rb +14 -2
- data/lib/temporalio/api/workflowservice/v1/request_response.rb +28 -2
- data/lib/temporalio/api/workflowservice/v1/service.rb +2 -2
- data/lib/temporalio/cancellation.rb +16 -12
- data/lib/temporalio/client/async_activity_handle.rb +12 -4
- data/lib/temporalio/client/connection/cloud_service.rb +135 -0
- data/lib/temporalio/client/connection/workflow_service.rb +150 -0
- data/lib/temporalio/client/connection.rb +2 -1
- data/lib/temporalio/client/interceptor.rb +25 -7
- data/lib/temporalio/client/schedule.rb +10 -2
- data/lib/temporalio/client/with_start_workflow_operation.rb +9 -1
- data/lib/temporalio/client/workflow_handle.rb +50 -10
- data/lib/temporalio/client/workflow_update_handle.rb +9 -3
- data/lib/temporalio/client.rb +110 -6
- data/lib/temporalio/common_enums.rb +14 -0
- data/lib/temporalio/contrib/open_telemetry.rb +7 -7
- data/lib/temporalio/converters/data_converter.rb +18 -8
- data/lib/temporalio/converters/failure_converter.rb +6 -3
- data/lib/temporalio/converters/payload_converter/binary_null.rb +2 -2
- data/lib/temporalio/converters/payload_converter/binary_plain.rb +2 -2
- data/lib/temporalio/converters/payload_converter/binary_protobuf.rb +2 -2
- data/lib/temporalio/converters/payload_converter/composite.rb +6 -4
- data/lib/temporalio/converters/payload_converter/encoding.rb +4 -2
- data/lib/temporalio/converters/payload_converter/json_plain.rb +24 -7
- data/lib/temporalio/converters/payload_converter/json_protobuf.rb +2 -2
- data/lib/temporalio/converters/payload_converter.rb +16 -6
- data/lib/temporalio/error/failure.rb +19 -1
- data/lib/temporalio/error.rb +1 -1
- data/lib/temporalio/internal/bridge/api/activity_result/activity_result.rb +1 -1
- data/lib/temporalio/internal/bridge/api/activity_task/activity_task.rb +3 -2
- data/lib/temporalio/internal/bridge/api/child_workflow/child_workflow.rb +1 -1
- data/lib/temporalio/internal/bridge/api/common/common.rb +1 -1
- data/lib/temporalio/internal/bridge/api/core_interface.rb +1 -1
- data/lib/temporalio/internal/bridge/api/external_data/external_data.rb +1 -1
- data/lib/temporalio/internal/bridge/api/nexus/nexus.rb +3 -2
- data/lib/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rb +2 -2
- data/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +3 -2
- data/lib/temporalio/internal/bridge/api/workflow_completion/workflow_completion.rb +1 -1
- data/lib/temporalio/internal/bridge/worker.rb +28 -4
- data/lib/temporalio/internal/bridge.rb +1 -1
- data/lib/temporalio/internal/client/implementation.rb +60 -52
- data/lib/temporalio/internal/proto_utils.rb +4 -4
- data/lib/temporalio/internal/worker/activity_worker.rb +93 -20
- data/lib/temporalio/internal/worker/workflow_instance/child_workflow_handle.rb +8 -6
- data/lib/temporalio/internal/worker/workflow_instance/context.rb +66 -24
- data/lib/temporalio/internal/worker/workflow_instance/details.rb +5 -2
- data/lib/temporalio/internal/worker/workflow_instance/external_workflow_handle.rb +2 -2
- data/lib/temporalio/internal/worker/workflow_instance/externally_immutable_hash.rb +2 -0
- data/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb +64 -18
- data/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +28 -14
- data/lib/temporalio/internal/worker/workflow_instance/replay_safe_logger.rb +5 -2
- data/lib/temporalio/internal/worker/workflow_instance/scheduler.rb +10 -4
- data/lib/temporalio/internal/worker/workflow_instance.rb +58 -23
- data/lib/temporalio/internal/worker/workflow_worker.rb +16 -6
- data/lib/temporalio/priority.rb +100 -0
- data/lib/temporalio/scoped_logger.rb +1 -1
- data/lib/temporalio/testing/activity_environment.rb +17 -2
- data/lib/temporalio/testing/workflow_environment.rb +3 -3
- data/lib/temporalio/version.rb +1 -1
- data/lib/temporalio/versioning_override.rb +56 -0
- data/lib/temporalio/worker/deployment_options.rb +45 -0
- data/lib/temporalio/worker/illegal_workflow_call_validator.rb +73 -0
- data/lib/temporalio/worker/interceptor.rb +13 -1
- data/lib/temporalio/worker/poller_behavior.rb +61 -0
- data/lib/temporalio/worker/thread_pool.rb +1 -1
- data/lib/temporalio/worker/workflow_executor/thread_pool.rb +2 -1
- data/lib/temporalio/worker/workflow_replayer.rb +12 -13
- data/lib/temporalio/worker.rb +73 -28
- data/lib/temporalio/worker_deployment_version.rb +67 -0
- data/lib/temporalio/workflow/child_workflow_handle.rb +10 -2
- data/lib/temporalio/workflow/definition.rb +187 -39
- data/lib/temporalio/workflow/external_workflow_handle.rb +3 -1
- data/lib/temporalio/workflow/info.rb +4 -1
- data/lib/temporalio/workflow.rb +134 -11
- data/lib/temporalio.rb +1 -0
- data/temporalio.gemspec +1 -0
- metadata +14 -3
data/Cargo.toml
CHANGED
@@ -13,13 +13,13 @@ license-file = "LICENSE"
|
|
13
13
|
|
14
14
|
[workspace.dependencies]
|
15
15
|
derive_builder = "0.20"
|
16
|
-
derive_more = { version = "
|
16
|
+
derive_more = { version = "2.0", features = ["constructor", "display", "from", "into", "debug", "try_into"] }
|
17
17
|
thiserror = "2"
|
18
|
-
tonic = "0.
|
19
|
-
tonic-build = "0.
|
20
|
-
opentelemetry = { version = "0.
|
18
|
+
tonic = "0.13"
|
19
|
+
tonic-build = "0.13"
|
20
|
+
opentelemetry = { version = "0.30", features = ["metrics"] }
|
21
21
|
prost = "0.13"
|
22
22
|
prost-types = "0.13"
|
23
23
|
|
24
24
|
[workspace.lints.rust]
|
25
|
-
unreachable_pub = "warn"
|
25
|
+
unreachable_pub = "warn"
|
data/README.md
CHANGED
@@ -42,7 +42,8 @@ opinions. Please communicate with us on [Slack](https://t.mp/slack) in the `#rub
|
|
42
42
|
- [Cloud Client Using mTLS](#cloud-client-using-mtls)
|
43
43
|
- [Cloud Client Using API Key](#cloud-client-using-api-key)
|
44
44
|
- [Data Conversion](#data-conversion)
|
45
|
-
- [
|
45
|
+
- [ActiveModel](#activemodel)
|
46
|
+
- [Converter Hints](#converter-hints)
|
46
47
|
- [Workers](#workers)
|
47
48
|
- [Workflows](#workflows)
|
48
49
|
- [Workflow Definition](#workflow-definition)
|
@@ -60,6 +61,9 @@ opinions. Please communicate with us on [Slack](https://t.mp/slack) in the `#rub
|
|
60
61
|
- [Manual Time Skipping](#manual-time-skipping)
|
61
62
|
- [Mocking Activities](#mocking-activities)
|
62
63
|
- [Workflow Replay](#workflow-replay)
|
64
|
+
- [Advanced Workflow Safety and Escaping](#advanced-workflow-safety-and-escaping)
|
65
|
+
- [Durable Fiber Scheduler](#durable-fiber-scheduler)
|
66
|
+
- [Illegal Call Tracing](#illegal-call-tracing)
|
63
67
|
- [Activities](#activities)
|
64
68
|
- [Activity Definition](#activity-definition)
|
65
69
|
- [Activity Context](#activity-context)
|
@@ -71,8 +75,13 @@ opinions. Please communicate with us on [Slack](https://t.mp/slack) in the `#rub
|
|
71
75
|
- [Metrics](#metrics)
|
72
76
|
- [OpenTelemetry Tracing](#opentelemetry-tracing)
|
73
77
|
- [OpenTelemetry Tracing in Workflows](#opentelemetry-tracing-in-workflows)
|
78
|
+
- [Rails](#rails)
|
79
|
+
- [ActiveRecord](#activerecord)
|
80
|
+
- [Lazy/Eager Loading](#lazyeager-loading)
|
81
|
+
- [Forking](#forking)
|
74
82
|
- [Ractors](#ractors)
|
75
83
|
- [Platform Support](#platform-support)
|
84
|
+
- [Migration from Coinbase Ruby SDK](#migration-from-coinbase-ruby-sdk)
|
76
85
|
- [Development](#development)
|
77
86
|
- [Build](#build)
|
78
87
|
- [Build Platform-specific Gem](#build-platform-specific-gem)
|
@@ -295,57 +304,62 @@ will be tried in order until one accepts (default falls through to the JSON one)
|
|
295
304
|
`encoding` metadata value which is used to know which converter to use on deserialize. Custom encoding converters can be
|
296
305
|
created, or even the entire payload converter can be replaced with a different implementation.
|
297
306
|
|
298
|
-
|
307
|
+
**NOTE:** For ActiveRecord, or other general/ORM models that are used for a different purpose, it is not recommended to
|
308
|
+
try to reuse them as Temporal models. Eventually model purposes diverge and models for a Temporal workflows/activities
|
309
|
+
should be specific to their use for clarity and compatibility reasons. Also many Ruby ORMs do many lazy things and
|
310
|
+
therefore provide unclear serialization semantics. Instead, consider having models specific for workflows/activities and
|
311
|
+
translate to/from existing models as needed. See the next section on how to do this with ActiveModel objects.
|
299
312
|
|
300
|
-
|
301
|
-
|
313
|
+
##### ActiveModel
|
314
|
+
|
315
|
+
By default, ActiveModel objects do not natively support the `JSON` module. A mixin can be created to add this support
|
316
|
+
for ActiveRecord, for example:
|
302
317
|
|
303
318
|
```ruby
|
304
|
-
module
|
319
|
+
module ActiveModelJSONSupport
|
305
320
|
extend ActiveSupport::Concern
|
306
321
|
include ActiveModel::Serializers::JSON
|
307
322
|
|
308
323
|
included do
|
324
|
+
def as_json(*)
|
325
|
+
super.merge(::JSON.create_id => self.class.name)
|
326
|
+
end
|
327
|
+
|
309
328
|
def to_json(*args)
|
310
|
-
|
311
|
-
hash[::JSON.create_id] = self.class.name
|
312
|
-
hash.to_json(*args)
|
329
|
+
as_json.to_json(*args)
|
313
330
|
end
|
314
331
|
|
315
332
|
def self.json_create(object)
|
333
|
+
object = object.dup
|
316
334
|
object.delete(::JSON.create_id)
|
317
|
-
|
318
|
-
ret.attributes = object
|
319
|
-
ret
|
335
|
+
new(**object.symbolize_keys)
|
320
336
|
end
|
321
337
|
end
|
322
338
|
end
|
323
339
|
```
|
324
340
|
|
325
|
-
|
341
|
+
Now if `include ActiveModelJSONSupport` is present on any ActiveModel class, on serialization `to_json` will be used
|
342
|
+
which will use `as_json` which calls the super `as_json` but also includes the fully qualified class name as the JSON
|
343
|
+
`create_id` key. On deserialization, Ruby JSON then uses this key to know what class to call `json_create` on.
|
326
344
|
|
327
|
-
|
328
|
-
module ActiveModelJSONSupport
|
329
|
-
extend ActiveSupport::Concern
|
330
|
-
include ActiveRecordJSONSupport
|
345
|
+
##### Converter Hints
|
331
346
|
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
end
|
337
|
-
end
|
347
|
+
In most places where objects are converted to payloads or vice versa, a "hint" can be provided to tell the converter
|
348
|
+
something else about the object/payload to assist conversion. The default converters ignore these hints, but custom
|
349
|
+
converters can be written to take advantage of them. For example, hints may be used to provide a custom converter the
|
350
|
+
Ruby type to deserialize a payload into.
|
338
351
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
352
|
+
These hints manifest themselves various ways throughout the API. The most obvious way is when making definitions. An
|
353
|
+
activity can define `activity_arg_hint` (which accepts multiple) and/or `activity_result_hint` for activity-level hints.
|
354
|
+
Similarly, a workflow can define `workflow_arg_hint` and/or `workflow_result_hint` for workflow-level hints.
|
355
|
+
`workflow_signal`, `workflow_query`, and `workflow_update` all similarly accept `arg_hints` and `result_hint` (except
|
356
|
+
signal of course). These definition-level hints are passed to converters both from the caller side and the
|
357
|
+
implementation side.
|
345
358
|
|
346
|
-
|
347
|
-
|
348
|
-
|
359
|
+
There are some advanced payload uses in the SDK that do not currently have a way to set hints. These include
|
360
|
+
workflow/schedule memo, workflow get/upsert memo, and application error details. In some cases, users can use
|
361
|
+
`Temporalio::Converters::RawValue` and then manually convert with hints. For others, hints can be added as needed,
|
362
|
+
please open an issue or otherwise contact Temporal.
|
349
363
|
|
350
364
|
### Workers
|
351
365
|
|
@@ -418,7 +432,7 @@ class GreetingWorkflow < Temporalio::Workflow::Definition
|
|
418
432
|
# on wait_condition calls, so Cancellation object doesn't need to be passed
|
419
433
|
# explicitly.
|
420
434
|
Temporalio::Workflow.wait_condition { @greeting_params_update || @complete }
|
421
|
-
|
435
|
+
|
422
436
|
# If there was an update, exchange and rerun. If it's _only_ a complete, finish
|
423
437
|
# workflow with the greeting.
|
424
438
|
if @greeting_params_update
|
@@ -490,7 +504,8 @@ definition/behavior of the method:
|
|
490
504
|
side effects, meaning they should never mutate state or try to wait on anything.
|
491
505
|
|
492
506
|
Workflows can be inherited, but subclass workflow-level decorators override superclass ones, and the same method can't
|
493
|
-
be decorated with different handler types/names in the hierarchy.
|
507
|
+
be decorated with different handler types/names in the hierarchy. Workflow handlers (execute or any marked method)
|
508
|
+
cannot accept keyword arguments.
|
494
509
|
|
495
510
|
#### Running Workflows
|
496
511
|
|
@@ -556,9 +571,7 @@ Some things to note about the above code:
|
|
556
571
|
|
557
572
|
* A timer is represented by `Temporalio::Workflow.sleep`.
|
558
573
|
* Timers are also started on `Temporalio::Workflow.timeout`.
|
559
|
-
*
|
560
|
-
forms are encouraged because they accept more options and are not subject to Ruby standard library implementation
|
561
|
-
changes.
|
574
|
+
* `Kernel.sleep` and `Timeout.timeout` are considered illegal by default.
|
562
575
|
* Each timer accepts a `Cancellation`, but if none is given, it defaults to `Temporalio::Workflow.cancellation`.
|
563
576
|
* `Temporalio::Workflow.wait_condition` accepts a block that waits until the evaluated block result is truthy, then
|
564
577
|
returns the value.
|
@@ -571,7 +584,10 @@ Some things to note about the above code:
|
|
571
584
|
#### Workflow Fiber Scheduling and Cancellation
|
572
585
|
|
573
586
|
Workflows are backed by a custom, deterministic `Fiber::Scheduler`. All fiber calls inside a workflow use this scheduler
|
574
|
-
to ensure coroutines run deterministically.
|
587
|
+
to ensure coroutines run deterministically. Although this means that `Kernel.sleep` and `Mutex` and such should work and
|
588
|
+
since they are Fiber-aware, Temporal intentionally disables their use by default to prevent accidental use. See
|
589
|
+
"Workflow Logic Constraints" and "Advanced Workflow Safety and Escaping" for more details, and see "Workflow Utilities"
|
590
|
+
for alternatives.
|
575
591
|
|
576
592
|
Every workflow contains a `Temporalio::Cancellation` at `Temporalio::Workflow.cancellation`. This is canceled when the
|
577
593
|
workflow is canceled. For all workflow calls that accept a cancellation token, this is the default. So if a workflow is
|
@@ -663,6 +679,9 @@ from workflows including:
|
|
663
679
|
nil key for dynamic). `[]=` or `store` can be called on these to update the handlers, though defined handlers are
|
664
680
|
encouraged over runtime-set ones.
|
665
681
|
|
682
|
+
There are also classes for `Temporalio::Workflow::Mutex`, `Temporalio::Workflow::Queue`, and
|
683
|
+
`Temporalio::Workflow::SizedQueue` that are workflow-safe wrappers around the standard library forms.
|
684
|
+
|
666
685
|
`Temporalio::Workflow::ContinueAsNewError` can be raised to continue-as-new the workflow. It accepts positional args and
|
667
686
|
defaults the workflow to the same as the current, though it can be changed with the `workflow` kwarg. See API
|
668
687
|
documentation for other details.
|
@@ -699,11 +718,16 @@ Ruby workflows. This means there are several things workflows cannot do such as:
|
|
699
718
|
|
700
719
|
* Perform IO (network, disk, stdio, etc)
|
701
720
|
* Access/alter external mutable state
|
702
|
-
* Do any threading
|
721
|
+
* Do any threading or blocking calls
|
703
722
|
* Do anything using the system clock (e.g. `Time.Now`)
|
704
723
|
* Make any random calls
|
705
724
|
* Make any not-guaranteed-deterministic calls
|
706
725
|
|
726
|
+
This means you can't even use logger calls outside of `Temporalio::Workflow.logger` because they use mutexes which may
|
727
|
+
be hit during periods of high-contention, but they are not completely disabled since users may do quick debugging with
|
728
|
+
them. See the [Advanced Workflow Safety and Escaping](#advanced-workflow-safety-and-escaping) section if needing to work
|
729
|
+
around this.
|
730
|
+
|
707
731
|
#### Workflow Testing
|
708
732
|
|
709
733
|
Workflow testing can be done in an integration-test fashion against a real server. However, it is hard to simulate
|
@@ -906,6 +930,44 @@ end
|
|
906
930
|
|
907
931
|
See the `WorkflowReplayer` API documentation for more details.
|
908
932
|
|
933
|
+
#### Advanced Workflow Safety and Escaping
|
934
|
+
|
935
|
+
Workflows use a custom fiber scheduler to make fibers durable. There is also call tracing to prevent accidentally making
|
936
|
+
illegal workflow calls. But sometimes in advanced situations, workarounds may be needed. This section describes advanced
|
937
|
+
situations working with the workflow Fiber scheduler and illegal call tracer.
|
938
|
+
|
939
|
+
##### Durable Fiber Scheduler
|
940
|
+
|
941
|
+
By default, Temporal considers `Logger`, `sleep`, `Timeout.timeout`, `Queue`, etc illegal. However, there are cases
|
942
|
+
where it may be desired for these to work locally inside a workflow such as for logging or other side-effecting,
|
943
|
+
known-non-deterministic aspects.
|
944
|
+
|
945
|
+
Users can pass a block to `Temporalio::Workflow::Unsafe.durable_scheduler_disabled` to not use the durable scheduler.
|
946
|
+
This should be used any time the scheduler needs to be bypassed, e.g. for local stdout. Not doing this can cause
|
947
|
+
workflows to get hung in high contention situations. For instance, if there is a logger (that isn't the safe-to-use
|
948
|
+
`Temporalio::Workflow.logger`) in a workflow, _technically_ Ruby surrounds the IO writes with a mutex and in extreme
|
949
|
+
high contention that mutex may durably block and then the workflow task may complete causing hung workflows because no
|
950
|
+
event comes to wake the mutex.
|
951
|
+
|
952
|
+
Also, by default anything that relies on IO wait that is not inside `durable_scheduler_disabled` will fail. It is
|
953
|
+
recommended to put things that need this in `durable_scheduler_disabled`, but if the durable scheduler is still needed
|
954
|
+
but IO wait is also needed, then a block passed to `Temporalio::Workflow::Unsafe.io_enabled` can be used.
|
955
|
+
|
956
|
+
Note `durable_scheduler_disabled` implies `illegal_call_tracing_disabled` (see next section). Many use of
|
957
|
+
`durable_scheduler_disabled`, such as for tracing or logging, often surround themselves in a
|
958
|
+
`unless Temporalio::Workflow.replaying?` block to make sure they don't duplicate the side effects on replay.
|
959
|
+
|
960
|
+
##### Illegal Call Tracing
|
961
|
+
|
962
|
+
Ruby workflow threads employ a `TracePoint` to catch illegal calls such as `sleep` or `Time.now` or `Thread.new`. The
|
963
|
+
set of illegal calls can be configured via the `illegal_workflow_calls` parameter when creating a worker. The default
|
964
|
+
set is at `Temporalio::Worker.default_illegal_workflow_calls`.
|
965
|
+
|
966
|
+
When an illegal call is encountered, an exception is thrown. In advanced cases there may be a need to allow an illegal
|
967
|
+
call that is known to be used deterministically. This code can be in a block passed to
|
968
|
+
`Temporalio::Workflow::Unsafe.illegal_call_tracing_disabled`. If this has side-effecting behavior that needs to use the
|
969
|
+
non-durable scheduler, use `durable_scheduler_disabled` instead (which implies this, see previous section).
|
970
|
+
|
909
971
|
### Activities
|
910
972
|
|
911
973
|
#### Activity Definition
|
@@ -955,6 +1017,7 @@ Some notes about activity definition:
|
|
955
1017
|
* `workflow_raw_args` can be used to have activity arguments delivered to `execute` as
|
956
1018
|
`Temporalio::Converters::RawValue`s. These are wrappers for the raw payloads that have not been converted to types
|
957
1019
|
(but they have been decoded by the codec if present). They can be converted with `payload_converter` on the context.
|
1020
|
+
* Activities cannot accept keyword arguments.
|
958
1021
|
|
959
1022
|
#### Activity Context
|
960
1023
|
|
@@ -1154,6 +1217,53 @@ workflow and time to run the activity attempt respectively), but the other spans
|
|
1154
1217
|
are created in workflows and closed immediately since long-lived spans cannot work for durable software that may resume
|
1155
1218
|
on other machines.
|
1156
1219
|
|
1220
|
+
### Rails
|
1221
|
+
|
1222
|
+
Temporal Ruby SDK is a generic Ruby library that can work in any Ruby environment. However, there are some common
|
1223
|
+
conventions for Rails users to be aware of.
|
1224
|
+
|
1225
|
+
See the [rails_app](https://github.com/temporalio/samples-ruby/tree/main/rails_app) sample for an example of using
|
1226
|
+
Temporal from Rails.
|
1227
|
+
|
1228
|
+
#### ActiveRecord
|
1229
|
+
|
1230
|
+
For ActiveRecord, or other general/ORM models that are used for a different purpose, it is not recommended to
|
1231
|
+
try to reuse them as Temporal models. Eventually model purposes diverge and models for a Temporal workflows/activities
|
1232
|
+
should be specific to their use for clarity and compatibility reasons. Also many Ruby ORMs do many lazy things and
|
1233
|
+
therefore provide unclear serialization semantics. Instead, consider having models specific for workflows/activities and
|
1234
|
+
translate to/from existing models as needed. See the [ActiveModel](#activemodel) section on how to do this with
|
1235
|
+
ActiveModel objects.
|
1236
|
+
|
1237
|
+
#### Lazy/Eager Loading
|
1238
|
+
|
1239
|
+
By default, Rails
|
1240
|
+
[eagerly loads](https://guides.rubyonrails.org/v7.2/autoloading_and_reloading_constants.html#eager-loading) all
|
1241
|
+
application code on application start in production, but lazily loads it in non-production environments. Temporal
|
1242
|
+
workflows by default disallow use of IO during the workflow run. With lazy loading enabled in dev/test environments,
|
1243
|
+
when an activity class is referenced in a workflow before it has been explicitly `require`d, it can give an error like:
|
1244
|
+
|
1245
|
+
> Cannot access File path from inside a workflow. If this is known to be safe, the code can be run in a
|
1246
|
+
> Temporalio::Workflow::Unsafe.illegal_call_tracing_disabled block.
|
1247
|
+
|
1248
|
+
This comes from `bootsnap` via `zeitwork` because it is lazily loading a class/module at workflow runtime. It is not
|
1249
|
+
good to lazily load code durnig a workflow run because it can be side effecting. Workflows and the classes they
|
1250
|
+
reference should not be eagerly loaded.
|
1251
|
+
|
1252
|
+
To resolve this, either always eagerly load (e.g. `config.eager_load = true`) or explicitly `require` what is used by a
|
1253
|
+
workflow at the top of the file.
|
1254
|
+
|
1255
|
+
Note, this only affects non-production environments.
|
1256
|
+
|
1257
|
+
### Forking
|
1258
|
+
|
1259
|
+
Objects created with the Temporal Ruby SDK cannot be used across forks. This includes runtimes, clients, and workers. By
|
1260
|
+
default, using `Client.connect` uses `Runtime.default` which is lazily created. If it was already created on the parent,
|
1261
|
+
an exception will occur when trying to reuse it to create clients or workers in a forked child. Similarly any RPC
|
1262
|
+
invocation or worker execution inside of a forked child separate from where the runtime or client or worker were created
|
1263
|
+
will raise an exception.
|
1264
|
+
|
1265
|
+
If forking must be used, make sure Temporal objects are only created _inside_ the fork.
|
1266
|
+
|
1157
1267
|
### Ractors
|
1158
1268
|
|
1159
1269
|
It was an original goal to have workflows actually be Ractors for deterministic state isolation and have the library
|
@@ -1190,6 +1300,40 @@ section for how to build a the repository.
|
|
1190
1300
|
The SDK works on Ruby 3.2+, but due to [an issue](https://github.com/temporalio/sdk-ruby/issues/162), fibers (and
|
1191
1301
|
`async` gem) are only supported on Ruby versions 3.3 and newer.
|
1192
1302
|
|
1303
|
+
### Migration from Coinbase Ruby SDK
|
1304
|
+
|
1305
|
+
The [Coinbase Ruby SDK](https://github.com/coinbase/temporal-ruby) predates this official Temporal SDK and has been a
|
1306
|
+
popular approach to developing in Temporal with Ruby. While Temporal encourages users to use the official SDK to get new
|
1307
|
+
features and support, this section covers differences from the Coinbase SDK to help those looking to migrate.
|
1308
|
+
|
1309
|
+
See [this Ruby sample](https://github.com/temporalio/samples-ruby/tree/main/coinbase_ruby) which demonstrates
|
1310
|
+
interoperability between Coinbase Ruby and Temporal Ruby clients, workflows, and activities. Specifically, it discusses
|
1311
|
+
how to disable API class loading on the Coinbase Ruby side if needing to use both dependencies in the same project,
|
1312
|
+
since two sets of API classes cannot both be present.
|
1313
|
+
|
1314
|
+
Migration cannot be done on a live, running workflow. Overall, Coinbase Ruby workflow events are incompatible with
|
1315
|
+
Temporal Ruby workflow events at runtime, so both SDK versions cannot have workers for the same task queue. A live
|
1316
|
+
workflow migration cannot occur, an separate task queue would be needed. However, Coinbase Ruby clients, workflows, and
|
1317
|
+
activities can be used with Temporal Ruby clients, workflows, and activities in either direction. Migrating from the
|
1318
|
+
Coinbase Ruby SDK to the Temporal Ruby SDK would be similar to migrating from Temporal Go SDK to Temporal Java SDK. You
|
1319
|
+
can interact across, but the workflow events are incompatible and therefore the task queues cannot be served by both at
|
1320
|
+
the same time.
|
1321
|
+
|
1322
|
+
Here is an overview of the primary differences between the SDKs:
|
1323
|
+
|
1324
|
+
| Feature | Coinbase Ruby | Temporal Ruby |
|
1325
|
+
| --- | --- | --- |
|
1326
|
+
| Base module | `Temporal::` | `Temporalio::` |
|
1327
|
+
| Client + start workflow | Global `Temporal.configure` + `Temporal.start_workflow` | `Temporalio::Client.connect` + `my_client.start_workflow` |
|
1328
|
+
| Client implementation | Ruby gRPC | Rust gRPC |
|
1329
|
+
| Activity definition | Extend `Temporal::Activity` + impl `execute` | Extend `Temporalio::Activity::Definition` + impl `execute` |
|
1330
|
+
| Workflow definition | Extend `Temporal::Workflow` + impl `execute` | Extend `Temporalio::Workflow::Definition` + impl `execute` |
|
1331
|
+
| Invoke activity from workflow | `MyActivity.execute!` or `workflow.execute_activity!(MyActivity)` | `Workflow.execute_activity(MyActivity)` |
|
1332
|
+
| Handle signal/query/update in workflow | `workflow.on_signal`/`workflow.on_query`/update-unsupported | Decorate with `workflow_signal`/`workflow_query`/`workflow_update` |
|
1333
|
+
| Run worker | `Temporal::Worker.new` + `start` | `Temporalio::Worker.new` + `run` |
|
1334
|
+
|
1335
|
+
This is just a high-level overview, there are many more differences on more specific Temporal components.
|
1336
|
+
|
1193
1337
|
## Development
|
1194
1338
|
|
1195
1339
|
### Build
|
@@ -1203,9 +1347,11 @@ Prerequisites:
|
|
1203
1347
|
|
1204
1348
|
First, install dependencies:
|
1205
1349
|
|
1350
|
+
# Optional: Change bundler install path to be local
|
1351
|
+
bundle config --local path $(pwd)/.bundle
|
1206
1352
|
bundle install
|
1207
1353
|
|
1208
|
-
To build shared library for development use:
|
1354
|
+
To build shared library for development use (ensure you have cloned submodules) :
|
1209
1355
|
|
1210
1356
|
bundle exec rake compile
|
1211
1357
|
|
@@ -1237,6 +1383,9 @@ the gem at `lib/temporalio/internal/bridge/3.2/temporalio_bridge.so` and
|
|
1237
1383
|
|
1238
1384
|
### Testing
|
1239
1385
|
|
1386
|
+
Note you can set `TEMPORAL_TEST_CLIENT_TARGET_HOST` and `TEMPORAL_TEST_CLIENT_TARGET_NAMESPACE`
|
1387
|
+
(optional, defaults to 'default') environment variables to use an existing server.
|
1388
|
+
|
1240
1389
|
This project uses `minitest`. To test:
|
1241
1390
|
|
1242
1391
|
bundle exec rake test
|
data/ext/Cargo.toml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
[package]
|
2
2
|
name = "temporalio_bridge"
|
3
3
|
version = "0.1.0"
|
4
|
-
edition = "
|
4
|
+
edition = "2024"
|
5
5
|
authors = ["Chad Retz <chad@temporal.io>"]
|
6
6
|
license = "MIT"
|
7
7
|
publish = false
|
@@ -19,9 +19,9 @@ temporal-client = { version = "0.1.0", path = "./sdk-core/client" }
|
|
19
19
|
temporal-sdk-core = { version = "0.1.0", path = "./sdk-core/core", features = ["ephemeral-server"] }
|
20
20
|
temporal-sdk-core-api = { version = "0.1.0", path = "./sdk-core/core-api" }
|
21
21
|
temporal-sdk-core-protos = { version = "0.1.0", path = "./sdk-core/sdk-core-protos" }
|
22
|
-
tokio = "1.
|
22
|
+
tokio = "1.37"
|
23
23
|
tokio-stream = "0.1"
|
24
24
|
tokio-util = "0.7"
|
25
|
-
tonic = "0.
|
25
|
+
tonic = "0.13"
|
26
26
|
tracing = "0.1"
|
27
27
|
url = "2.2"
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'temporalio/error'
|
4
|
+
|
5
|
+
module Temporalio
|
6
|
+
module Activity
|
7
|
+
# Details that are set when an activity is cancelled. This is only valid at the time the cancel was received, the
|
8
|
+
# state may change on the server after it is received.
|
9
|
+
class CancellationDetails
|
10
|
+
def initialize(
|
11
|
+
gone_from_server: false,
|
12
|
+
cancel_requested: true,
|
13
|
+
timed_out: false,
|
14
|
+
worker_shutdown: false,
|
15
|
+
paused: false,
|
16
|
+
reset: false
|
17
|
+
)
|
18
|
+
@gone_from_server = gone_from_server
|
19
|
+
@cancel_requested = cancel_requested
|
20
|
+
@timed_out = timed_out
|
21
|
+
@worker_shutdown = worker_shutdown
|
22
|
+
@paused = paused
|
23
|
+
@reset = reset
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Boolean] Whether the activity no longer exists on the server (may already be completed or its workflow
|
27
|
+
# may be completed).
|
28
|
+
def gone_from_server?
|
29
|
+
@gone_from_server
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Boolean] Whether the activity was explicitly cancelled.
|
33
|
+
def cancel_requested?
|
34
|
+
@cancel_requested
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [Boolean] Whether the activity timeout caused activity to be marked cancelled.
|
38
|
+
def timed_out?
|
39
|
+
@timed_out
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [Boolean] Whether the worker the activity is running on is shutting down.
|
43
|
+
def worker_shutdown?
|
44
|
+
@worker_shutdown
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [Boolean] Whether the activity was explicitly paused.
|
48
|
+
def paused?
|
49
|
+
@paused
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [Boolean] Whether the activity was explicitly reset.
|
53
|
+
def reset?
|
54
|
+
@reset
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -61,7 +61,8 @@ module Temporalio
|
|
61
61
|
# Users do not have to be concerned with burdening the server by calling this too frequently.
|
62
62
|
#
|
63
63
|
# @param details [Array<Object>] Details to record with the heartbeat.
|
64
|
-
|
64
|
+
# @param detail_hints [Array<Object>, nil] Hints to pass to converter.
|
65
|
+
def heartbeat(*details, detail_hints: nil)
|
65
66
|
raise NotImplementedError
|
66
67
|
end
|
67
68
|
|
@@ -70,6 +71,14 @@ module Temporalio
|
|
70
71
|
raise NotImplementedError
|
71
72
|
end
|
72
73
|
|
74
|
+
# @return [CancellationDetails, nil] Cancellation details if canceled. These are set just before cancellation is
|
75
|
+
# actually canceled. These details only represent when the cancel was first performed. Once set, this object is
|
76
|
+
# never mutated. Therefore, the situation on the server may have changed (e.g. unpause), but this still
|
77
|
+
# represents the values when cancellation first occurred for this attempt.
|
78
|
+
def cancellation_details
|
79
|
+
raise NotImplementedError
|
80
|
+
end
|
81
|
+
|
73
82
|
# @return [Cancellation] Cancellation that is canceled when the worker is shutting down. On worker shutdown, this
|
74
83
|
# is canceled, then the `graceful_shutdown_period` is waited (default 0s), then the activity is canceled.
|
75
84
|
def worker_shutdown_cancellation
|
@@ -78,6 +78,21 @@ module Temporalio
|
|
78
78
|
|
79
79
|
@activity_raw_args = value
|
80
80
|
end
|
81
|
+
|
82
|
+
# Add activity hints to be passed to converter for activity args.
|
83
|
+
#
|
84
|
+
# @param hints [Array<Object>] Hints to add.
|
85
|
+
def activity_arg_hint(*hints)
|
86
|
+
@activity_arg_hints ||= []
|
87
|
+
@activity_arg_hints.concat(hints)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Set activity result hint to be passed to converter for activity result.
|
91
|
+
#
|
92
|
+
# @param hint [Object] Hint to set.
|
93
|
+
def activity_result_hint(hint)
|
94
|
+
@activity_result_hint = hint
|
95
|
+
end
|
81
96
|
end
|
82
97
|
|
83
98
|
# @!visibility private
|
@@ -85,13 +100,20 @@ module Temporalio
|
|
85
100
|
activity_name = @activity_name
|
86
101
|
raise 'Cannot have activity name specified for dynamic activity' if activity_name && @activity_dynamic
|
87
102
|
|
103
|
+
# Disallow kwargs in execute parameters
|
104
|
+
if instance_method(:execute).parameters.any? { |t, _| t == :key || t == :keyreq }
|
105
|
+
raise 'Activity execute cannot have keyword arguments'
|
106
|
+
end
|
107
|
+
|
88
108
|
# Default to unqualified class name if not dynamic
|
89
109
|
activity_name ||= name.to_s.split('::').last unless @activity_dynamic
|
90
110
|
{
|
91
111
|
activity_name:,
|
92
112
|
activity_executor: @activity_executor || :default,
|
93
113
|
activity_cancel_raise: @activity_cancel_raise.nil? || @activity_cancel_raise,
|
94
|
-
activity_raw_args: @activity_raw_args.nil? ? false : @activity_raw_args
|
114
|
+
activity_raw_args: @activity_raw_args.nil? ? false : @activity_raw_args,
|
115
|
+
activity_arg_hints: @activity_arg_hints,
|
116
|
+
activity_result_hint: @activity_result_hint
|
95
117
|
}
|
96
118
|
end
|
97
119
|
|
@@ -122,6 +144,12 @@ module Temporalio
|
|
122
144
|
# @return [Boolean] Whether to use {Converters::RawValue}s as arguments.
|
123
145
|
attr_reader :raw_args
|
124
146
|
|
147
|
+
# @return [Array<Object>, nil] Argument hints.
|
148
|
+
attr_reader :arg_hints
|
149
|
+
|
150
|
+
# @return [Object, nil] Result hint
|
151
|
+
attr_reader :result_hint
|
152
|
+
|
125
153
|
# Obtain definition info representing the given activity, which can be a class, instance, or definition info.
|
126
154
|
#
|
127
155
|
# @param activity [Definition, Class<Definition>, Info] Activity to get info for.
|
@@ -142,7 +170,9 @@ module Temporalio
|
|
142
170
|
instance: proc { activity.new },
|
143
171
|
executor: details[:activity_executor],
|
144
172
|
cancel_raise: details[:activity_cancel_raise],
|
145
|
-
raw_args: details[:activity_raw_args]
|
173
|
+
raw_args: details[:activity_raw_args],
|
174
|
+
arg_hints: details[:activity_arg_hints],
|
175
|
+
result_hint: details[:activity_result_hint]
|
146
176
|
) { |*args| Context.current.instance&.execute(*args) }
|
147
177
|
when Definition
|
148
178
|
details = activity.class._activity_definition_details
|
@@ -151,7 +181,9 @@ module Temporalio
|
|
151
181
|
instance: activity,
|
152
182
|
executor: details[:activity_executor],
|
153
183
|
cancel_raise: details[:activity_cancel_raise],
|
154
|
-
raw_args: details[:activity_raw_args]
|
184
|
+
raw_args: details[:activity_raw_args],
|
185
|
+
arg_hints: details[:activity_arg_hints],
|
186
|
+
result_hint: details[:activity_result_hint]
|
155
187
|
) { |*args| Context.current.instance&.execute(*args) }
|
156
188
|
when Info
|
157
189
|
activity
|
@@ -167,6 +199,8 @@ module Temporalio
|
|
167
199
|
# @param executor [Symbol] Name of the executor.
|
168
200
|
# @param cancel_raise [Boolean] Whether to raise in thread/fiber on cancellation.
|
169
201
|
# @param raw_args [Boolean] Whether to use {Converters::RawValue}s as arguments.
|
202
|
+
# @param arg_hints [Array<Object>, nil] Argument hints.
|
203
|
+
# @param result_hint [Object, nil] Result hint.
|
170
204
|
# @yield Use this block as the activity.
|
171
205
|
def initialize(
|
172
206
|
name:,
|
@@ -174,6 +208,8 @@ module Temporalio
|
|
174
208
|
executor: :default,
|
175
209
|
cancel_raise: true,
|
176
210
|
raw_args: false,
|
211
|
+
arg_hints: nil,
|
212
|
+
result_hint: nil,
|
177
213
|
&block
|
178
214
|
)
|
179
215
|
@name = name
|
@@ -184,6 +220,8 @@ module Temporalio
|
|
184
220
|
@executor = executor
|
185
221
|
@cancel_raise = cancel_raise
|
186
222
|
@raw_args = raw_args
|
223
|
+
@arg_hints = arg_hints
|
224
|
+
@result_hint = result_hint
|
187
225
|
Internal::ProtoUtils.assert_non_reserved_name(name)
|
188
226
|
end
|
189
227
|
end
|
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'temporalio/activity/context'
|
4
|
+
require 'temporalio/internal/proto_utils'
|
5
|
+
|
3
6
|
module Temporalio
|
4
7
|
module Activity
|
5
8
|
Info = Data.define(
|
@@ -7,9 +10,10 @@ module Temporalio
|
|
7
10
|
:activity_type,
|
8
11
|
:attempt,
|
9
12
|
:current_attempt_scheduled_time,
|
10
|
-
:heartbeat_details,
|
11
13
|
:heartbeat_timeout,
|
12
14
|
:local?,
|
15
|
+
:priority,
|
16
|
+
:raw_heartbeat_details,
|
13
17
|
:schedule_to_close_timeout,
|
14
18
|
:scheduled_time,
|
15
19
|
:start_to_close_timeout,
|
@@ -32,12 +36,15 @@ module Temporalio
|
|
32
36
|
# @return [Integer] Attempt the activity is on.
|
33
37
|
# @!attribute current_attempt_scheduled_time
|
34
38
|
# @return [Time] When the current attempt was scheduled.
|
35
|
-
# @!attribute heartbeat_details
|
36
|
-
# @return [Array<Object>] Details from the last heartbeat of the last attempt.
|
37
39
|
# @!attribute heartbeat_timeout
|
38
40
|
# @return [Float, nil] Heartbeat timeout set by the caller.
|
39
41
|
# @!attribute local?
|
40
42
|
# @return [Boolean] Whether the activity is a local activity or not.
|
43
|
+
# @!attribute priority
|
44
|
+
# @return [Priority] The priority of this activity.
|
45
|
+
# @!attribute raw_heartbeat_details
|
46
|
+
# @return [Array<Converter::RawValue>] Raw details from the last heartbeat of the last attempt. Can use
|
47
|
+
# {heartbeat_details} to get lazily-converted values.
|
41
48
|
# @!attribute schedule_to_close_timeout
|
42
49
|
# @return [Float, nil] Schedule to close timeout set by the caller.
|
43
50
|
# @!attribute scheduled_time
|
@@ -62,6 +69,20 @@ module Temporalio
|
|
62
69
|
#
|
63
70
|
# @note WARNING: This class may have required parameters added to its constructor. Users should not instantiate this
|
64
71
|
# class or it may break in incompatible ways.
|
65
|
-
class Info
|
72
|
+
class Info
|
73
|
+
# Convert raw heartbeat details into Ruby types.
|
74
|
+
#
|
75
|
+
# Note, this live-converts every invocation.
|
76
|
+
#
|
77
|
+
# @param hints [Array<Object>, nil] Hints, if any, to assist conversion.
|
78
|
+
# @return [Array<Object>] Converted details.
|
79
|
+
def heartbeat_details(hints: nil)
|
80
|
+
Internal::ProtoUtils.convert_from_payload_array(
|
81
|
+
Context.current.payload_converter,
|
82
|
+
raw_heartbeat_details.map(&:payload),
|
83
|
+
hints:
|
84
|
+
)
|
85
|
+
end
|
86
|
+
end
|
66
87
|
end
|
67
88
|
end
|
data/lib/temporalio/activity.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'temporalio/activity/cancellation_details'
|
3
4
|
require 'temporalio/activity/complete_async_error'
|
4
5
|
require 'temporalio/activity/context'
|
5
6
|
require 'temporalio/activity/definition'
|
6
7
|
require 'temporalio/activity/info'
|
8
|
+
require 'temporalio/priority'
|
7
9
|
|
8
10
|
module Temporalio
|
9
11
|
# All activity related classes.
|