Skip to main content

MediaManager

Struct MediaManager 

Source
pub struct MediaManager { /* private fields */ }
Expand description

Glue between the Media model and a StorageRegistry. Cheap to clone — internal state is Arc-shared.

v0.38 — tri-dialect. Every query method dispatches per backend (PG / MySQL 8+ / SQLite) via the unified crate::sql::Pool enum. PG-specific idioms (ANY($1), NOW() - INTERVAL, DELETE … USING, ON CONFLICT DO UPDATE, INSERT … RETURNING) are rewritten as portable equivalents (pre-computed timestamps bound from Rust, IN (?, ?, …) expansions, subquery rewrites, ON DUPLICATE KEY UPDATE on MySQL, SELECT … LAST_INSERT_ID() in a transaction on MySQL).

Implementations§

Source§

impl MediaManager

Source

pub fn new(pool: PgPool, registry: StorageRegistry) -> Self

PG back-compat constructor.

Source

pub fn new_pool(pool: impl Into<Pool>, registry: StorageRegistry) -> Self

Tri-dialect constructor (v0.38).

Source

pub fn registry(&self) -> &StorageRegistry

Source

pub fn pool(&self) -> &PgPool

PG back-compat accessor. Panics if the manager wraps a non-PG pool — prefer Self::pool_dyn for tri-dialect code.

Source

pub fn pool_dyn(&self) -> &Pool

Tri-dialect accessor — the unified crate::sql::Pool enum.

Source

pub async fn save_bytes(&self, opts: SaveOpts) -> Result<Media, MediaError>

Write opts.bytes to the storage backend, then insert a Media row in the Ready state. Returns the inserted row.

§Errors

UnknownDisk if the disk isn’t registered, Storage for any upload failure, Db for the row insert.

Source

pub async fn begin_upload( &self, intent: UploadIntent, ) -> Result<UploadTicket, MediaError>

Issue a presigned PUT URL for direct browser upload, and pre-create a Media row in Pending state. The browser PUTs directly to S3 (or compatible); the server later calls Self::finalize_upload to verify the object landed and flip the row to Ready.

§Errors

UnknownDisk / Db / a Storage error if the backend doesn’t support presigned URLs.

Source

pub async fn finalize_upload(&self, media_id: i64) -> Result<Media, MediaError>

Confirm the storage object exists for media_id and flip the row from Pending to Ready. If the object isn’t there, flip to Failed instead so a purge sweep can clean it up.

Returns the (possibly-updated) row regardless.

§Errors

Db if the row doesn’t exist or the update fails. Storage for transport failures during the exists check.

Source

pub async fn get(&self, id: i64) -> Result<Option<Media>, MediaError>

Fetch by id. Soft-deleted rows are excluded; pass through to Self::get_including_deleted when you want them.

Source

pub async fn get_including_deleted( &self, id: i64, ) -> Result<Option<Media>, MediaError>

Like Self::get but returns soft-deleted rows too. Use from admin / restore flows.

Source

pub fn url(&self, m: &Media) -> Option<String>

CDN-aware URL for m. Returns None when neither the disk’s CDN prefix nor the backend’s public URL is available.

Source

pub fn origin_url(&self, m: &Media) -> Option<String>

Bare backend URL (no CDN). For internal admin / debug.

Source

pub async fn presigned_get(&self, m: &Media, ttl: Duration) -> Option<String>

Time-limited download link suitable for <a href=...>. Returns None when the disk’s backend can’t sign.

Source

pub async fn load_bytes(&self, m: &Media) -> Result<Vec<u8>, MediaError>

Read the file bytes server-side.

Source

pub async fn delete(&self, m: &Media) -> Result<(), MediaError>

Soft-delete: mark deleted_at = NOW(). The storage object stays put — purge it later via Self::purge or wait for the purge_orphans sweep.

Source

pub async fn purge(&self, m: &Media) -> Result<(), MediaError>

Hard-delete: remove the storage object AND the row. Use for “I’m sure I want this gone right now” — typically called by the post_delete signal once delete() has soft-deleted.

Source

pub async fn purge_orphans( &self, older_than: Duration, ) -> Result<u64, MediaError>

Hard-delete every soft-deleted Media row older than older_than, removing the storage object as we go. Returns the count of rows purged.

Run from the crate::scheduler (e.g. nightly) to keep orphan storage objects from accumulating.

Source

pub async fn purge_pending( &self, older_than: Duration, ) -> Result<u64, MediaError>

Hard-delete every Media row stuck in Pending for longer than older_than. Direct-browser-upload flows leave Pending rows behind when the browser abandons before calling finalize_upload; this sweep cleans them up.

Source

pub async fn create_collection( &self, name: impl Into<String>, slug: impl Into<String>, parent: Option<i64>, description: impl Into<String>, ) -> Result<MediaCollection, MediaError>

Create a new collection. slug must be unique. parent may be None (root) or another collection’s id (sub-folder).

§Errors

Db for unique-constraint violations on slug or any other underlying sqlx error.

Source

pub async fn get_collection( &self, id: i64, ) -> Result<Option<MediaCollection>, MediaError>

Look up by id (excludes soft-deleted).

Source

pub async fn get_collection_by_slug( &self, slug: &str, ) -> Result<Option<MediaCollection>, MediaError>

Look up by slug (excludes soft-deleted).

Source

pub async fn list_collections(&self) -> Result<Vec<MediaCollection>, MediaError>

List every non-deleted collection, ordered by (parent_id, name) so siblings group together — handy for tree-renderers.

Source

pub async fn collection_path(&self, id: i64) -> Result<String, MediaError>

Build the slug-joined path for a collection: "products/2026/launch". Walks up the parent chain. Cycles raise Other.

Source

pub async fn delete_collection(&self, id: i64) -> Result<(), MediaError>

Soft-delete a collection. Media inside it is NOT deleted — rows are orphaned (collection_id set to NULL) so they remain queryable and the storage objects survive.

Source

pub async fn move_to_collection( &self, media_id: i64, collection_id: Option<i64>, ) -> Result<(), MediaError>

Move a Media into a collection (or None to set “loose”).

Source

pub async fn list_in_collection( &self, collection_id: i64, recursive: bool, ) -> Result<Vec<Media>, MediaError>

List media in collection_id. When recursive, descends into every nested collection.

Source

pub async fn ensure_tag(&self, slug: &str) -> Result<MediaTag, MediaError>

Find or create a tag by slug (auto-derives name from slug if creating).

Source

pub async fn get_tag_by_slug( &self, slug: &str, ) -> Result<Option<MediaTag>, MediaError>

Look up a tag by slug.

Source

pub async fn tag(&self, media_id: i64, slugs: &[&str]) -> Result<(), MediaError>

Apply tags to a media row. Auto-creates missing tags. Idempotent — duplicates ignored.

Source

pub async fn untag(&self, media_id: i64, slug: &str) -> Result<(), MediaError>

Remove a single tag from a media row.

Source

pub async fn set_tags( &self, media_id: i64, slugs: &[&str], ) -> Result<(), MediaError>

Replace the entire tag set for a media row. Tags not in slugs are removed; tags in slugs are added (auto-created if needed).

Source

pub async fn tags_for(&self, media_id: i64) -> Result<Vec<MediaTag>, MediaError>

List tags applied to a media row, alphabetically by slug.

Source

pub async fn list_with_tag( &self, slug: &str, limit: i64, offset: i64, ) -> Result<Vec<Media>, MediaError>

List media that carry slug. Soft-deleted media excluded.

Source

pub async fn popular_tags( &self, limit: i64, ) -> Result<Vec<(MediaTag, i64)>, MediaError>

Top tags by usage count, descending. Limit clamped at 1000.

Trait Implementations§

Source§

impl Clone for MediaManager

Source§

fn clone(&self) -> MediaManager

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> MaybeMyFromRow for T

Source§

impl<T> MaybeMyLoadRelated for T

Source§

impl<T> MaybeSqliteFromRow for T

Source§

impl<T> MaybeSqliteLoadRelated for T