Class EquinixAsync
- All Implemented Interfaces:
AutoCloseable
...Async variants, this
runs an arbitrary blocking SDK call on a virtual thread and hands the caller a
CompletableFuture, so a single small class covers Fabric, NetworkEdge, CustomerPortal and
every other domain.
Each submitted call runs on its own virtual thread from
Executors.newVirtualThreadPerTaskExecutor(). Virtual threads are cheap and park (rather
than pin a platform thread) while a request is blocked on I/O, so thousands of concurrent SDK
calls can be in flight without an explicit thread-pool size to tune.
Usage
try (EquinixAsync async = EquinixAsync.create()) {
CompletableFuture<Connection> f = async.call(() -> fabric.connections().getByUuid(id));
CompletableFuture<Void> v = async.run(() -> fabric.connections().getByUuid(id).delete());
// Fan out, then join:
List<CompletableFuture<Connection>> futures = ids.stream()
.map(id -> async.call(() -> fabric.connections().getByUuid(id)))
.toList();
List<Connection> connections = EquinixAsync.awaitAll(futures);
}
Exceptions thrown by the supplied call (for example an
EquinixServiceException or any other
RuntimeException) are not swallowed: the returned future completes exceptionally with the
original throwable as its cause, surfaced through CompletableFuture.join() /
CompletableFuture.get() as usual.
This class is AutoCloseable; closing it shuts down the backing executor and waits
(up to a bounded grace period) for in-flight calls to finish, so exiting a try-with-resources
block does not silently abandon submitted work. Calls submitted after close() are
rejected. Instances are thread-safe and intended to be shared, typically for the lifetime of
the work being parallelised.
- Author:
- ianjones
-
Method Summary
Modifier and TypeMethodDescriptionstatic <T> List<T> awaitAll(Collection<? extends CompletableFuture<? extends T>> futures) Awaits a collection of futures and collects their results in iteration order.<T> CompletableFuture<T> Runs a value-returning SDK call asynchronously on a virtual thread.voidclose()Shuts down the backing virtual-thread executor and blocks until in-flight calls finish.static EquinixAsynccreate()Creates a new facade backed by a fresh virtual-thread-per-task executor.Runs avoidSDK call (for example a delete or update) asynchronously on a virtual thread.
-
Method Details
-
create
Creates a new facade backed by a fresh virtual-thread-per-task executor.- Returns:
- a new
EquinixAsync; close it (ideally via try-with-resources) when done
-
call
Runs a value-returning SDK call asynchronously on a virtual thread.If
apiCallthrows, the returned future completes exceptionally with that throwable as the cause; otherwise it completes with the supplied result (which may benull).- Type Parameters:
T- the result type of the call- Parameters:
apiCall- the blocking SDK call to run, e.g.() -> fabric.connections().getByUuid(id)- Returns:
- a future completed with the call's result, or completed exceptionally on error
-
run
Runs avoidSDK call (for example a delete or update) asynchronously on a virtual thread.If
apiCallthrows, the returned future completes exceptionally with that throwable as the cause; otherwise it completes withnullonce the call returns.- Parameters:
apiCall- the blocking SDK call to run, e.g.() -> connection.delete()- Returns:
- a future completed when the call returns, or completed exceptionally on error
-
awaitAll
Awaits a collection of futures and collects their results in iteration order. This is a blocking convenience for the common "fan out, then join" pattern.If any future completes exceptionally, the first such failure (in iteration order) is rethrown as a
CompletionExceptionwhose cause is the original throwable, exactly asCompletableFuture.join()would surface it. If the calling thread is interrupted while waiting, anAsyncExceptionis thrown and the interrupt flag is restored.- Type Parameters:
T- the result type of the futures- Parameters:
futures- the futures to await; not modified- Returns:
- the results in the iteration order of
futures
-
close
public void close()Shuts down the backing virtual-thread executor and blocks until in-flight calls finish. New submissions viacall(Supplier)orrun(Runnable)after this point are rejected.In-flight calls are given a bounded grace period (60 seconds) to complete; anything still running after that is interrupted via
ExecutorService.shutdownNow(). Virtual threads are daemon threads, so without this wait a fire-and-forgetrun(...)inside try-with-resources could be silently killed by JVM exit. If the closing thread is itself interrupted while waiting, remaining work is interrupted immediately and the interrupt flag is restored. Idempotent.- Specified by:
closein interfaceAutoCloseable
-