Skip to main content

rskit_media/
executor.rs

1//! Backend executor trait for media processing.
2
3use rskit_errors::AppResult;
4use rskit_storage::{FileSink, FileSource};
5use tokio_util::sync::CancellationToken;
6
7use crate::{ops::MediaOp, pipeline::Progress};
8
9/// Backend that can execute a media pipeline.
10#[async_trait::async_trait]
11pub trait MediaExecutor: Send + Sync {
12    /// Execute a sequence of operations on a source.
13    async fn execute(
14        &self,
15        source: &FileSource,
16        ops: &[MediaOp],
17        sink: Option<&FileSink>,
18    ) -> AppResult<FileSource>;
19
20    /// Execute with progress reporting.
21    async fn execute_with_progress(
22        &self,
23        source: &FileSource,
24        ops: &[MediaOp],
25        sink: Option<&FileSink>,
26        on_progress: Box<dyn Fn(Progress) + Send + Sync>,
27    ) -> AppResult<FileSource>;
28
29    /// Execute with cancellation support.
30    ///
31    /// The default implementation ignores the token and delegates to [`execute`](MediaExecutor::execute).
32    /// Backends should override this to honour cancellation (e.g. kill a subprocess).
33    async fn execute_cancellable(
34        &self,
35        source: &FileSource,
36        ops: &[MediaOp],
37        sink: Option<&FileSink>,
38        on_progress: Option<Box<dyn Fn(Progress) + Send + Sync>>,
39        _cancel: CancellationToken,
40    ) -> AppResult<FileSource> {
41        match on_progress {
42            Some(cb) => self.execute_with_progress(source, ops, sink, cb).await,
43            None => self.execute(source, ops, sink).await,
44        }
45    }
46
47    /// Check if this executor supports a given operation.
48    fn supports(&self, op: &MediaOp) -> bool;
49
50    /// Dry run: return the command(s) that would be executed.
51    fn preview(&self, source: &FileSource, ops: &[MediaOp]) -> AppResult<Vec<String>>;
52}