function.future factory. i.e. calling my_function.future(1, 2, 3) returns a Future object
for the my_function(1, 2, 3) function call. The Future doesn’t start running until it’s started with its .run() or
.result() methods, used as a function call argument, or returned from a function. .result() method blocks until the
Future completes and returns the value returned by the function call or raises an exception on failure.
Future.wait(futures: Iterable[Future]) can be used to wait for multiple Futures to complete.
See more details at waiting for multiple Futures to complete.
Example: Running multiple function calls in parallel
Example: Non-blocking map and reduce operations
Usefunction.future.map(...) and function.future.reduce(...) to create Futures for map and reduce operations.
The arguments of these methods are the same for function.map(...) and function.reduce(...) described at
Map-Reduce page.
Waiting for multiple Futures to complete
Future.wait class method can be used to wait for multiple Futures to complete. This class method is inspired by the standard concurrent.futures.wait in Python.
It’s full signature is:
futures: An iterable of Future objects to wait for.timeout: An optional timeout in seconds. If specified, the method will return after the timeout even if not all Futures have completed.return_when: A flag indicating when to return. It can be one of the following values from theRETURN_WHENenum:RETURN_WHEN.ALL_COMPLETED: Wait until all Futures have completed.RETURN_WHEN.FIRST_COMPLETED: Wait until at least one Future has completed.RETURN_WHEN.FIRST_EXCEPTION: Wait until at least one Future has raised an exception or all have completed.
(done, not_done), where done is a list of Futures that have completed, and not_done is a list of Futures that have not completed yet.
If a future is not running yet, it’s started automatically when passed to Future.wait.
Future object
Future object has the following methods and properties:exception -> TensorlakeError|None: If the function call or another operation associated with this Future failed then this property will return the exception associated with the failure. Otherwise, it will returnNone. If the operation is not yet complete, this property will also returnNone.result(timeout: float|None = None) -> Any: Blocks until the operation completes and returns the result of the operation (i.e. value returned by function call). If the operation fails, theFunctionErrorwill be raised. See more about error handling. An optional timeout in seconds can be specified. If timeout is reached before the Future completes, aTimeoutErrorwill be raised.done() -> bool: ReturnsTrueif the operation has completed (either successfully or with an exception), otherwise returnsFalse.run() -> Future: Starts the Future’s operation. Returns the same Future object for chaining. A Future that hasn’t been started with.run()will be started automatically when passed as another operation input or returned as a tail call.__await__() -> Generator[Any]: Allows awaiting the Future in async functions. This is equivalent to calling.result(), but the call will not block the async event loop.coroutine() -> Coroutine: Converts the Future into a coroutine that can be used the same way as any coroutine returned by an async Tensorlake function. Returns the same coroutine object if called multiple times on the same Future. Can only be called before a Future is started with.run().
Passing Futures as inputs
Futures can be passed as arguments to function calls. When a Future gets passed this way, Tensorlake automatically runs it if not running, waits for the Future to complete and uses its result as the function call argument value. This allows building applications that can run multiple function calls in parallel without blocking on their results until it’s necessary.Wrapping Futures into Python objects is not allowed
When passing Futures as arguments to function calls, or returning them as tail calls, the Futures cannot be wrapped into other Python objects. For example:Tail calls
When a Tensorlake function calls another Tensorlake function or callsfuture.result(), the calling function blocks until the
function call or the future completes and returns its result.
Applications that make many of such calls can face multiple challenges:
- Wasted Resources: While waiting for the result, the calling function container cannot perform other tasks while still consuming its compute resources.
- Higher Resource Usage: More function containers are required to handle the same number of concurrent application requests if each request blocks multiple function containers.
- Higher Latency: Sequential blocking function calls or
future.result()calls can lead to increased overall latency, especially when multiple function calls are involved.
greet(...) application doesn’t have to wait for completion of any of its function calls.
greet(...) just returns almost immediately after telling Tensorlake what it needs to do for the request.
greet(...) then frees its container to process another request while Tensorlake is orchestrating the execution the most efficient
way possible. Once all function calls complete, Tensorlake will return the final result to the user.
See Also
Async Functions
Learn how to use async functions in Tensorlake applications.
Map-Reduce
Learn how to use map-reduce operations to run function calls in parallel and aggregate results.