Storage profiles: where a library's bytes live (V205).
A library points at a profile (PhoenixKit.Modules.Storage.StorageProfile),
and the profile lists its buckets with how it uses each
(PhoenixKit.Modules.Storage.ProfileBucket: role, what it stores, write
priority, serve order, status) and how many copies an object gets. A
library with no profile uses the Default, seeded by V205 from the
install's buckets and storage_redundancy_copies under a fixed uuid
(default_uuid/0), so an install that never touches profiles behaves as
it did before.
Every change to a profile or its buckets bumps its revision
(bump_revision/1). A file records the profile and revision it was
placed by (placed_profile_uuid / placed_revision, NULL meaning the
Default at revision 1), which is how the reconciler finds the files that
are not where their library's profile wants them.
Summary
Functions
Puts a newly created bucket into the Default profile, the way every new
bucket joined the pool before profiles: primary, stores everything,
active, its priority as the write priority (0 is the shuffled pool),
served after the Default's other buckets (a local one before the remote
ones).
Bumps a profile's revision: every file it placed is stale, and the reconciler is queued to bring them up to date.
The number of copies profile wants of an object: :original for an
original upload, :derived for anything made from one.
Creates a profile with no buckets.
Creates the profile of a user's own storage, in one of two modes
Whether uuid is the Default profile's.
How many copies of an original the Default keeps (1 when there is no
Default yet, as storage_redundancy_copies defaulted to).
The Default profile, with its buckets.
The uuid of the Default profile, fixed on every install.
Deletes a profile. The Default cannot be deleted
({:error, :default}), nor a profile a library uses
({:error, :in_use}).
Removes a user's own profile (V206) and the buckets that were in it and are in no profile now: what is left of a user's storage once their library is purged. A site profile, or one a library still uses, is left alone.
The profile a file's library uses.
The profile library uses, with its buckets (see profile_uuid_for/1).
Falls back to the Default when the library's own is gone.
A profile with its buckets, or nil (also for anything not a uuid).
How many libraries (trashed ones included) use profile_uuid explicitly.
The site's profiles, the Default first, each with its buckets. A user's own profile (V206) is not here: the site's profile editor and pickers read this, and a user's storage is not something an admin assigns or edits.
The uuid of the profile library uses: its own, or the Default. Takes a
library, a library uuid, or nil (a file with no library is in Media).
Adds bucket_uuid to profile, or changes how the profile uses it, and
bumps the profile's revision.
Takes bucket_uuid out of profile and bumps the profile's revision.
Takes bucket_uuid out of every profile, bumping each one's revision.
Called when an empty bucket is deleted.
Points library at profile_uuid (nil for the Default). Its files
become stale unless the new profile is the one they were placed by.
Updates a profile's name or copy counts; a real change bumps its revision.
What each of these libraries keeps its files on, for the ones on a user's own
storage (V206): %{library_uuid => %{mode: :only | :backup, bucket: Bucket.t()}}.
A library on the site's storage has no entry. One query.
Functions
@spec add_to_default(PhoenixKit.Modules.Storage.Bucket.t()) :: :ok
Puts a newly created bucket into the Default profile, the way every new
bucket joined the pool before profiles: primary, stores everything,
active, its priority as the write priority (0 is the shuffled pool),
served after the Default's other buckets (a local one before the remote
ones).
@spec bump_revision(term()) :: :ok
Bumps a profile's revision: every file it placed is stale, and the reconciler is queued to bring them up to date.
@spec copies(PhoenixKit.Modules.Storage.StorageProfile.t(), :original | :derived) :: pos_integer()
The number of copies profile wants of an object: :original for an
original upload, :derived for anything made from one.
@spec create_profile(map()) :: {:ok, PhoenixKit.Modules.Storage.StorageProfile.t()} | {:error, Ecto.Changeset.t()}
Creates a profile with no buckets.
@spec create_user_profile( String.t(), PhoenixKit.Modules.Storage.Bucket.t(), :only | :backup ) :: {:ok, PhoenixKit.Modules.Storage.StorageProfile.t()} | {:error, :no_site_storage | :foreign_bucket | term()}
Creates the profile of a user's own storage, in one of two modes:
:only— the user's bucket is the profile's oneprimary: everything the library stores lives there.:backup— the site's buckets stay the primaries and the user's bucket is abackupof the originals. The site buckets are a snapshot of the Default profile taken now: a site bucket added later is not used by this library (removing or disabling one already reaches every profile). An original is kept on every one of those site buckets that is writable and stores originals (not only as many as the Default's copy count: placement writes all primaries before any backup, so the backup would otherwise never get one) and on the backup, at most 5 copies in all (the original-capable site rows are limited to four). An upload still succeeds on the Default's terms, counting the site's copies only; the backup copy is made by the reconciler if the write missed it. Sizes and tiles are not backed up (they can be regenerated), and the site's derived-only buckets are kept. A site with no writable bucket for originals has nothing to back up:{:error, :no_site_storage}.
The profile is the user's (owner_uuid), named by its own uuid (the name is
never shown), and bucket must be theirs. Returns {:error, :no_site_storage}
for :backup on a site with no site bucket to back up.
Whether uuid is the Default profile's.
@spec default_copies() :: pos_integer()
How many copies of an original the Default keeps (1 when there is no
Default yet, as storage_redundancy_copies defaulted to).
@spec default_profile() :: PhoenixKit.Modules.Storage.StorageProfile.t() | nil
The Default profile, with its buckets.
@spec default_uuid() :: String.t()
The uuid of the Default profile, fixed on every install.
@spec delete_profile(PhoenixKit.Modules.Storage.StorageProfile.t()) :: {:ok, PhoenixKit.Modules.Storage.StorageProfile.t()} | {:error, :default | :in_use | Ecto.Changeset.t()}
Deletes a profile. The Default cannot be deleted
({:error, :default}), nor a profile a library uses
({:error, :in_use}).
Removes a user's own profile (V206) and the buckets that were in it and are in no profile now: what is left of a user's storage once their library is purged. A site profile, or one a library still uses, is left alone.
Returns :ok, or {:error, reason} for the first bucket that could not go
(one that still holds file locations cannot be deleted).
@spec for_file(PhoenixKit.Modules.Storage.File.t()) :: PhoenixKit.Modules.Storage.StorageProfile.t() | nil
The profile a file's library uses.
@spec for_library(PhoenixKit.Modules.Storage.Library.t() | term()) :: PhoenixKit.Modules.Storage.StorageProfile.t() | nil
The profile library uses, with its buckets (see profile_uuid_for/1).
Falls back to the Default when the library's own is gone.
@spec get_profile(term()) :: PhoenixKit.Modules.Storage.StorageProfile.t() | nil
A profile with its buckets, or nil (also for anything not a uuid).
@spec libraries_using(term()) :: non_neg_integer()
How many libraries (trashed ones included) use profile_uuid explicitly.
@spec list_profiles() :: [PhoenixKit.Modules.Storage.StorageProfile.t()]
The site's profiles, the Default first, each with its buckets. A user's own profile (V206) is not here: the site's profile editor and pickers read this, and a user's storage is not something an admin assigns or edits.
@spec profile_uuid_for(PhoenixKit.Modules.Storage.Library.t() | term()) :: String.t()
The uuid of the profile library uses: its own, or the Default. Takes a
library, a library uuid, or nil (a file with no library is in Media).
@spec put_bucket(PhoenixKit.Modules.Storage.StorageProfile.t(), term(), map()) :: {:ok, PhoenixKit.Modules.Storage.ProfileBucket.t()} | {:error, Ecto.Changeset.t()}
Adds bucket_uuid to profile, or changes how the profile uses it, and
bumps the profile's revision.
@spec remove_bucket(PhoenixKit.Modules.Storage.StorageProfile.t(), term()) :: :ok
Takes bucket_uuid out of profile and bumps the profile's revision.
@spec remove_bucket_everywhere(term()) :: :ok
Takes bucket_uuid out of every profile, bumping each one's revision.
Called when an empty bucket is deleted.
@spec set_library_profile(PhoenixKit.Modules.Storage.Library.t(), term()) :: {:ok, PhoenixKit.Modules.Storage.Library.t()} | {:error, Ecto.Changeset.t() | :not_found | :user_storage_locked}
Points library at profile_uuid (nil for the Default). Its files
become stale unless the new profile is the one they were placed by.
@spec update_profile(PhoenixKit.Modules.Storage.StorageProfile.t(), map()) :: {:ok, PhoenixKit.Modules.Storage.StorageProfile.t()} | {:error, Ecto.Changeset.t()}
Updates a profile's name or copy counts; a real change bumps its revision.
@spec user_storage_for([PhoenixKit.Modules.Storage.Library.t()]) :: %{ required(String.t()) => %{ mode: :only | :backup, bucket: PhoenixKit.Modules.Storage.Bucket.t() } }
What each of these libraries keeps its files on, for the ones on a user's own
storage (V206): %{library_uuid => %{mode: :only | :backup, bucket: Bucket.t()}}.
A library on the site's storage has no entry. One query.