@@ -61,6 +61,9 @@ opinions. Please communicate with us on [Slack](https://t.mp/slack) in the `#rub
6161 - [ Manual Time Skipping] ( #manual-time-skipping )
6262 - [ Mocking Activities] ( #mocking-activities )
6363 - [ 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 )
6467 - [ Activities] ( #activities )
6568 - [ Activity Definition] ( #activity-definition )
6669 - [ Activity Context] ( #activity-context )
@@ -716,6 +719,11 @@ Ruby workflows. This means there are several things workflows cannot do such as:
716719* Make any random calls
717720* Make any not-guaranteed-deterministic calls
718721
722+ This means you can't even call ` puts ` or logger calls outside of ` Temporalio::Workflow.logger ` because they use mutexes
723+ which may be hit during periods of high-contention, but they are not completely disabled since users may do quick
724+ debugging with them. See the [ Advanced Workflow Safety and Escaping] ( #advanced-workflow-safety-and-escaping ) section if
725+ needing to work around this.
726+
719727#### Workflow Testing
720728
721729Workflow testing can be done in an integration-test fashion against a real server. However, it is hard to simulate
918926
919927See the ` WorkflowReplayer ` API documentation for more details.
920928
929+ #### Advanced Workflow Safety and Escaping
930+
931+ Workflows use a custom fiber scheduler to make things like certain blocking calls and timeouts durable. There is also
932+ call tracing to prevent accidentally making illegal workflow calls. But sometimes in advanced situations, workarounds
933+ may be needed. This section describes advanced situations working with the workflow Fiber scheduler and illegal call
934+ tracer.
935+
936+ ##### Durable Fiber Scheduler
937+
938+ The custom fiber scheduler that powers workflows makes otherwise-local, blocking things durable. This is why ` sleep ` and
939+ ` Timeout.timeout ` and ` Queue ` and other things work durably. However, there are cases where it may be desired for these
940+ to work locally inside a workflow such as for logging or ` puts ` or other side-effecting, known-non-deterministic
941+ aspects.
942+
943+ Users can pass a block to ` Temporalio::Workflow::Unsafe.durable_scheduler_disabled ` to not use the durable scheduler.
944+ This should be used any time the scheduler needs to be bypassed, e.g. for local stdout. Not doing this can cause
945+ workflows to get hung in high contention situations. For instance, if there is a ` puts ` or a logger (that isn't the
946+ safe-to-use ` Temporalio::Workflow.logger ` ) in a workflow, _ technically_ Ruby surrounds the IO writes with a mutex and
947+ in extreme high contention that mutex may durably block and then the workflow task may complete causing hung workflows
948+ because no event comes to wake the mutex.
949+
950+ Also, by default anything that relies on IO wait that is not inside ` durable_scheduler_disabled ` will fail. It is
951+ recommended to put things that need this in ` durable_scheduler_disabled ` , but if the durable scheduler is still needed
952+ but IO wait is also needed, then a block passed to ` Temporalio::Workflow::Unsafe.io_enabled ` can be used.
953+
954+ Note ` durable_scheduler_disabled ` implies ` illegal_call_tracing_disabled ` (see next section). Many use of
955+ ` durable_scheduler_disabled ` , such as for tracing or logging, often surround themselves in a
956+ ` unless Temporalio::Workflow.replaying? ` block to make sure they don't duplicate the side effects on replay.
957+
958+ ##### Illegal Call Tracing
959+
960+ Ruby workflow threads employ a ` TracePoint ` to catch illegal calls such as ` Time.now ` or ` Thread.new ` . The set of
961+ illegal calls can be configured via the ` illegal_workflow_calls ` parameter when creating a worker. The default set is at
962+ ` Temporalio::Worker.default_illegal_workflow_calls ` .
963+
964+ When an illegal call is encountered, an exception is thrown. In advanced cases there may be a need to allow an illegal
965+ call that is known to be used deterministically. This code can be in a block passed to
966+ ` Temporalio::Workflow::Unsafe.illegal_call_tracing_disabled ` . If this has side-effecting behavior that needs to use the
967+ non-durable scheduler, use ` durable_scheduler_disabled ` instead (which implies this, see previous section).
968+
921969### Activities
922970
923971#### Activity Definition
0 commit comments