Lightning.Adaptors.Strategy behaviour (Lightning v2.19.0)
View SourceBehaviour every adaptor strategy implements.
A strategy is the sole boundary between the Lightning.Adaptors.*
subsystem and the outside world. It defines four callbacks:
fetch_adaptor/1returns aadaptor_record/0for one package name. Icon fields are not part of this record. The Scheduler stamps them on separately after joining the bulk icon pipeline.fetch_icon/2returns the raw bytes and extension of one icon variant. The Store calls it when an icon is missing on disk.fetch_icons/1bulk-fetches icons for every adaptor the strategy knows. The Scheduler runs it once per tick in parallel with its per-adaptor fan-out. See the callback docs for:prior_etags.list_adaptors/0is the cheap change signal:nameandlatest_versionfor every package the strategy knows, which the Scheduler diffs against theadaptorstable.
The active strategy module is resolved at runtime via
Lightning.Adaptors.Config.strategy/0. Implementations surface
transient failures (5xx, timeout, nxdomain) as {:error, term()} and
do not retry.
Summary
Types
The record returned by fetch_adaptor/1. Icon fields are not on it.
The Scheduler persists them separately after joining fetch_icons/1.
Fresh-fetch icon entry inside the fetch_icons/1 result map. :etag
is the upstream cache validator verbatim from the HTTP response, nil
when upstream sent none. Strategies with no transport-level validator,
such as Lightning.Adaptors.Local, omit the key entirely.
Per-shape value inside the fetch_icons/1 result map. Either a
fresh icon_entry/0 (a 200) or :not_modified (a 304), which is
only ever returned when the caller supplied a prior etag via
:prior_etags.
Bulk icon map returned by fetch_icons/1. A shape that is absent
means upstream has no such icon. :not_modified means it is unchanged
since the prior etag. A map is a fresh fetch to apply.
Per-version metadata extracted from an upstream packument or local
package.json.
Callbacks
Fetch the full structured record for a single adaptor package.
Fetch the raw bytes for one icon variant (:square or :rectangle)
of an adaptor package, together with the file extension.
Bulk fetch every available icon for every adaptor known to the strategy.
Cheap change signal: name and latest_version for every package the
strategy knows. The Scheduler diffs this against the adaptors table to
compute its work list.
Functions
Validate a schema body and pair it with its persisted digest.
Types
@type adaptor_record() :: %{ name: String.t(), description: String.t() | nil, homepage: String.t() | nil, repository: String.t() | nil, license: String.t() | nil, latest_version: String.t(), deprecated: boolean(), schema_data: String.t() | nil, schema_sha256: String.t() | nil, versions: [version_record()] }
The record returned by fetch_adaptor/1. Icon fields are not on it.
The Scheduler persists them separately after joining fetch_icons/1.
schema_data is the credential schema as a JSON binary. nil means
the source sees no schema for this version; the Scheduler decides
whether that replaces a stored one.
@type icon_entry() :: %{ :data => binary(), :ext => String.t(), :sha256 => binary(), optional(:etag) => String.t() | nil }
Fresh-fetch icon entry inside the fetch_icons/1 result map. :etag
is the upstream cache validator verbatim from the HTTP response, nil
when upstream sent none. Strategies with no transport-level validator,
such as Lightning.Adaptors.Local, omit the key entirely.
@type icon_shape_value() :: icon_entry() | :not_modified
Per-shape value inside the fetch_icons/1 result map. Either a
fresh icon_entry/0 (a 200) or :not_modified (a 304), which is
only ever returned when the caller supplied a prior etag via
:prior_etags.
@type icons_map() :: %{ required(String.t()) => %{ optional(:square) => icon_shape_value(), optional(:rectangle) => icon_shape_value() } }
Bulk icon map returned by fetch_icons/1. A shape that is absent
means upstream has no such icon. :not_modified means it is unchanged
since the prior etag. A map is a fresh fetch to apply.
@type version_record() :: %{ version: String.t(), integrity: String.t() | nil, tarball_url: String.t() | nil, size_bytes: integer() | nil, dependencies: map(), peer_dependencies: map(), published_at: DateTime.t() | nil, deprecated: boolean() }
Per-version metadata extracted from an upstream packument or local
package.json.
Callbacks
@callback fetch_adaptor(name :: String.t()) :: {:ok, adaptor_record()} | {:error, term()}
Fetch the full structured record for a single adaptor package.
@callback fetch_icon(name :: String.t(), :square | :rectangle) :: {:ok, %{data: binary(), ext: String.t()}} | {:error, term()}
Fetch the raw bytes for one icon variant (:square or :rectangle)
of an adaptor package, together with the file extension.
Bulk fetch every available icon for every adaptor known to the strategy.
Returns {:ok, icons_map} (see icons_map/0). A top-level
{:error, term()} is only
returned when the whole pipeline cannot proceed, for example when the
list_adaptors/0 call inside the bulk implementation fails.
Options
:prior_etags-%{name => %{optional(:square | :rectangle) => etag}}, sent asIf-None-Matchper(name, shape). Defaults to%{}. Strategies with no transport-level cache validator, such asLightning.Adaptors.Local, ignore it and never return:not_modified.
@callback list_adaptors() :: {:ok, [%{name: String.t(), latest_version: String.t()}]} | {:error, term()}
Cheap change signal: name and latest_version for every package the
strategy knows. The Scheduler diffs this against the adaptors table to
compute its work list.
{:ok, []} means the strategy looked and there is genuinely nothing
there, which settles the Store's first-load gate. A strategy that cannot
tell an empty source from an unreadable one must return {:error, _}:
Lightning.Adaptors.Local reports an empty checkout as {:ok, []},
Lightning.Adaptors.NPM reports an empty org listing as
{:error, :empty_listing}.
Functions
Validate a schema body and pair it with its persisted digest.
Returns {:ok, {body, sha256_hex}} when body decodes as JSON, with
sha256_hex lowercase hex, matching the adaptors.schema_sha256
column format. {:error, reason} when it doesn't decode.