In programming, it’s common to deal with tasks that may take some time to complete. Often, we want to enforce a limit on how long we’re willing to wait for these tasks. The Effect.timeout function helps by placing a time constraint on an operation, ensuring it doesn’t run indefinitely.
Basic Usage
timeout
The Effect.timeout function employs a Duration parameter to establish a time limit on an operation. If the operation exceeds this limit, a TimeoutException is triggered, indicating a timeout has occurred.
Example (Setting a Timeout)
Here, the task completes within the timeout duration, so the result is returned successfully.
If the operation exceeds the specified duration, a TimeoutException is raised:
timeoutOption
If you want to handle timeouts more gracefully, consider using Effect.timeoutOption. This function treats timeouts as regular results, wrapping the outcome in an Option.
Example (Handling Timeout as an Option)
In this example, the first task completes successfully, while the second times out. The result of the timed-out task is represented as None in the Option type.
Handling Timeouts
When an operation does not finish within the specified duration, the behavior of the Effect.timeout depends on whether the operation is “uninterruptible”.
Interruptible Operation: If the operation can be interrupted, it is terminated immediately once the timeout threshold is reached, resulting in a TimeoutException.
Uninterruptible Operation: If the operation is uninterruptible, it continues until completion before the TimeoutException is assessed.
Disconnection on Timeout
The Effect.disconnect function provides a way to handle timeouts in uninterruptible effects more flexibly. It allows an uninterruptible effect to complete in the background, while the main control flow proceeds as if a timeout had occurred.
Here’s the distinction:
WithoutEffect.disconnect:
An uninterruptible effect will ignore the timeout and continue executing until it completes, after which the timeout error is assessed.
This can lead to delays in recognizing a timeout condition because the system must wait for the effect to complete.
WithEffect.disconnect:
The uninterruptible effect is allowed to continue in the background, independent of the main control flow.
The main control flow recognizes the timeout immediately and proceeds with the timeout error or alternative logic, without having to wait for the effect to complete.
This method is particularly useful when the operations of the effect do not need to block the continuation of the program, despite being marked as uninterruptible.
Example (Running Uninterruptible Tasks with Timeout and Background Completion)
Consider a scenario where a long-running data processing task is initiated, and you want to ensure the system remains responsive, even if the data processing takes too long:
In this example, the system detects the timeout after one second, but the long-running task continues and completes in the background, without blocking the program’s flow.
Customizing Timeout Behavior
In addition to the basic Effect.timeout function, there are variations available that allow you to customize the behavior when a timeout occurs.
timeoutFail
The Effect.timeoutFail function allows you to produce a specific error when a timeout happens.
Example (Custom Timeout Error)
timeoutFailCause
Effect.timeoutFailCause lets you define a specific defect to throw when a timeout occurs. This is helpful for treating timeouts as exceptional cases in your code.
Example (Custom Defect on Timeout)
timeoutTo
Effect.timeoutTo provides more flexibility compared to Effect.timeout, allowing you to define different outcomes for both successful and timed-out operations. This can be useful when you want to customize the result based on whether the operation completes in time or not.
Example (Handling Success and Timeout with Either)