Skuld.ForeignResolver protocol (skuld_concurrency v0.32.0)

View Source

Protocol for resolving ForeignSuspend values across different platforms.

The protocol dispatches on the payload field of the first ForeignSuspend in the list. Consumers implement this protocol for their payload type to resolve foreign suspensions via platform-specific mechanisms (e.g., JS Promises, OS I/O completion ports).

The protocol uses continuation-passing style — the implementation calls continuation.(resolved) with a map of %{suspend_id => resolved_value} when ready, enabling both synchronous and asynchronous resolution.

Example (synchronous, for tests)

defmodule MyPayload do
  defstruct [:value]
end

defimpl Skuld.ForeignResolver, for: MyPayload do
  def await_resolutions(suspends, continuation) do
    resolved = Map.new(suspends, &{&1.id, &1.payload.value})
    continuation.(resolved)
  end
end

Example (async, for Hologram)

defimpl Skuld.ForeignResolver, for: Hologram.JS.PromiseRef do
  def await_resolutions(suspends, continuation) do
    promises = Enum.map(suspends, & &1.payload.promise)
    JS.Promise.all(promises).then(fn results ->
      resolved =
        suspends
        |> Enum.zip(results)
        |> Map.new(fn {s, val} -> {s.id, val} end)

      continuation.(resolved)
    end)
  end
end

Summary

Types

t()

All the types that implement this protocol.

Functions

Resolve the given foreign suspensions and call the continuation with a map of %{ForeignSuspend.id => resolved_value}.

Types

t()

@type t() :: term()

All the types that implement this protocol.

Functions

await_resolutions(payload, suspends, continuation)

@spec await_resolutions(payload :: term(), [Skuld.Comp.ForeignSuspend.t()], (map() ->
                                                                         term())) ::
  term()

Resolve the given foreign suspensions and call the continuation with a map of %{ForeignSuspend.id => resolved_value}.

The first parameter is any ForeignSuspend.payload value from the list, used for protocol dispatch. The full list of suspends is also passed so the implementation can batch-resolve them.

The implementation must call continuation.(resolved) exactly once. It may do so synchronously or asynchronously.