Lightning.Channels (Lightning v2.19.0-pre)

View Source

Context for managing Channels — HTTP proxy configurations that forward requests from a client to a destination.

Summary

Functions

Creates a channel.

Deletes a channel.

Deletes ALL channel_requests for a project's channels.

Deletes channel_requests older than period_days for channels in the given project. Channel events are cascade-deleted by the database FK.

Gets a single channel by ID. Returns nil if not found.

Gets a single channel by ID. Raises Ecto.NoResultsError if not found.

Gets a channel by ID scoped to a project. Returns nil if the channel does not exist or belongs to a different project.

Returns a channel request with preloads, scoped to the given project.

Returns aggregate stats for all channels in a project.

Gets a channel by ID with all auth methods preloaded.

Get or create a snapshot for the channel's current lock_version.

Returns a paginated page of ChannelRequest records for a project.

Returns all channels for a project, ordered by name.

Returns channels for a project with aggregate stats from channel_requests.

Records a destination credential resolution failure as a ChannelRequest + ChannelEvent pair, atomically.

Updates a channel's config fields, bumping lock_version.

Functions

create_channel(attrs, list)

@spec create_channel(map(), [{:actor, Lightning.Accounts.User.t()}]) ::
  {:ok, Lightning.Channels.Channel.t()} | {:error, Ecto.Changeset.t()}

Creates a channel.

delete_channel(channel, list)

@spec delete_channel(Lightning.Channels.Channel.t(), [
  {:actor, Lightning.Accounts.User.t()}
]) ::
  {:ok, Lightning.Channels.Channel.t()} | {:error, Ecto.Changeset.t()}

Deletes a channel.

Explicitly deletes all channel_requests first (required because channel_requests.channel_id uses on_delete: :restrict). Channel events cascade automatically, and channel snapshots cascade via on_delete: :delete_all on channel_snapshots.channel_id.

delete_channel_requests_for_project(project)

@spec delete_channel_requests_for_project(Lightning.Projects.Project.t()) :: :ok

Deletes ALL channel_requests for a project's channels.

Used during project deletion to satisfy the RESTRICT FK constraint on channel_requests.channel_id before channels are cascade-deleted.

delete_expired_requests(project_id, period_days)

@spec delete_expired_requests(Ecto.UUID.t(), pos_integer()) :: :ok

Deletes channel_requests older than period_days for channels in the given project. Channel events are cascade-deleted by the database FK.

After deletion, removes orphaned channel_snapshots that are no longer referenced by any request and are not the current version.

get_channel(id, opts \\ [])

Gets a single channel by ID. Returns nil if not found.

Options

  • :include - list of associations to preload (default: [])

get_channel!(id, opts \\ [])

Gets a single channel by ID. Raises Ecto.NoResultsError if not found.

Accepts the same options as get_channel/2.

get_channel_for_project(project_id, channel_id, opts \\ [])

Gets a channel by ID scoped to a project. Returns nil if the channel does not exist or belongs to a different project.

get_channel_request_for_project(project_id, request_id)

@spec get_channel_request_for_project(Ecto.UUID.t(), String.t()) ::
  Lightning.Channels.ChannelRequest.t() | nil

Returns a channel request with preloads, scoped to the given project.

Returns nil if the request doesn't exist, belongs to a different project, or the ID is not a valid UUID.

Preloads: channel_events, channel, channel_snapshot, client_webhook_auth_method, and destination_credential (with its credential for display).

get_channel_stats_for_project(project_id)

Returns aggregate stats for all channels in a project.

Returns a map with:

  • :total_channels — number of channels in the project
  • :total_requests — total channel requests across all channels

Uses a single query with a LEFT JOIN so both counts are fetched in one database round-trip.

get_channel_with_auth(id)

Gets a channel by ID with all auth methods preloaded.

Preloads client auth methods (with webhook_auth_method) and destination auth method (with project_credential → credential). Returns nil if not found.

Used by ChannelProxyPlug for client authentication and destination credential resolution.

get_or_create_current_snapshot(channel)

Get or create a snapshot for the channel's current lock_version.

Returns an existing snapshot if one matches, or creates a minimal one from the current channel config. Handles concurrent creation race via ON CONFLICT DO NOTHING + re-fetch.

Full snapshot lifecycle management is in #4406.

list_channel_requests(project, search_params, params \\ %{})

Returns a paginated page of ChannelRequest records for a project.

Preloads :channel and :channel_events.

Parameters

  • project%Project{} struct; scopes results to this project
  • search_params%SearchParams{}; currently supports channel_id filter
  • params — Scrivener page params map, e.g. %{"page" => "2"}

list_channels_for_project(project_id)

Returns all channels for a project, ordered by name.

list_channels_for_project_with_stats(project_id)

Returns channels for a project with aggregate stats from channel_requests.

Each entry is a map with keys:

  • all Channel fields (via struct)
  • :request_count — total number of requests
  • :last_activity — datetime of most recent request, or nil

record_destination_credential_error(channel, req_attrs, event_attrs)

@spec record_destination_credential_error(
  Lightning.Channels.Channel.t(),
  map(),
  map()
) :: :ok

Records a destination credential resolution failure as a ChannelRequest + ChannelEvent pair, atomically.

The caller provides raw attribute maps for the request and event; this function applies the project's zero-persistence policy before insert. When the project's retention_policy is :erase_all, PII fields are dropped from both maps and the request is marked is_wiped: true.

The event's :channel_request_id is set automatically from the inserted request — callers should omit it.

Returns :ok either way: insert failures are logged but never propagate, so callers can respond with the same HTTP status regardless of persistence outcome.

update_channel(channel, attrs, list)

@spec update_channel(Lightning.Channels.Channel.t(), map(), [
  {:actor, Lightning.Accounts.User.t()}
]) ::
  {:ok, Lightning.Channels.Channel.t()} | {:error, Ecto.Changeset.t()}

Updates a channel's config fields, bumping lock_version.