1use async_trait::async_trait;
6use std::collections::HashMap;
7use tonic::server::NamedService;
8use tonic::{Request, Response, Status};
9
10#[derive(Clone, PartialEq, Debug, Default)]
16pub struct WorkerCapabilities {
17 pub cpu_cores: u32,
18 pub memory_bytes: u64,
19 pub gpu_devices: Vec<String>,
20 pub supported_codecs: Vec<String>,
21 pub supported_hwaccels: Vec<String>,
22 pub relative_speed: f32,
23 pub max_concurrent_jobs: u32,
24}
25
26#[derive(Clone, PartialEq, Debug, Default)]
28pub struct WorkerRegistration {
29 pub worker_id: String,
30 pub hostname: String,
31 pub ip_address: String,
32 pub port: u32,
33 pub capabilities: Option<Box<WorkerCapabilities>>,
34 pub metadata: HashMap<String, String>,
35}
36
37#[derive(Clone, PartialEq, Debug, Default)]
38pub struct WorkerRegistrationResponse {
39 pub success: bool,
40 pub message: String,
41 pub assigned_worker_id: String,
42}
43
44#[derive(Clone, PartialEq, Debug, Default)]
46pub struct WorkerHeartbeat {
47 pub worker_id: String,
48 pub status: Option<Box<WorkerStatus>>,
49 pub active_job_ids: Vec<String>,
50 pub metrics: Option<Box<WorkerMetrics>>,
51}
52
53#[derive(Clone, PartialEq, Debug, Default)]
54pub struct HeartbeatResponse {
55 pub acknowledged: bool,
56 pub jobs_to_cancel: Vec<String>,
57 pub should_drain: bool,
58}
59
60#[derive(Clone, PartialEq, Debug, Default)]
62pub struct WorkerStatus {
63 pub state: i32,
64 pub active_jobs: u32,
65 pub queued_jobs: u32,
66}
67
68#[derive(Clone, PartialEq, Debug, Default)]
70pub struct WorkerMetrics {
71 pub cpu_usage: f32,
72 pub memory_usage: f32,
73 pub gpu_usage: f32,
74 pub bytes_processed: u64,
75 pub frames_encoded: u32,
76}
77
78#[derive(Clone, PartialEq, Debug, Default)]
80pub struct WorkerUnregistration {
81 pub worker_id: String,
82 pub reason: String,
83}
84
85#[derive(Clone, PartialEq, Debug, Default)]
86pub struct UnregistrationResponse {
87 pub success: bool,
88}
89
90#[derive(Clone, PartialEq, Debug, Default)]
92pub struct JobRequest {
93 pub worker_id: String,
94 pub max_jobs: u32,
95 pub preferred_codecs: Vec<String>,
96}
97
98pub mod job_assignment {
99 use super::EncodingTask;
100
101 #[derive(Clone, PartialEq, Debug, Default)]
102 pub struct Job {
103 pub job_id: String,
104 pub task: Option<Box<EncodingTask>>,
105 pub priority: u32,
106 pub deadline_timestamp: i64,
107 }
108}
109
110#[derive(Clone, PartialEq, Debug, Default)]
111pub struct JobAssignment {
112 pub jobs: Vec<job_assignment::Job>,
113 pub has_more: bool,
114}
115
116#[derive(Clone, PartialEq, Debug, Default)]
117pub struct Job {
118 pub job_id: String,
119 pub task: Option<Box<EncodingTask>>,
120 pub priority: u32,
121 pub deadline_timestamp: i64,
122}
123
124#[derive(Clone, PartialEq, Debug, Default)]
126pub struct EncodingTask {
127 pub task_id: String,
128 pub source_url: String,
129 pub codec: String,
130 pub strategy: i32,
131 pub params: Option<Box<EncodingParams>>,
132 pub output_url: String,
133}
134
135#[derive(Clone, PartialEq, Debug, Default)]
136pub struct EncodingParams {
137 pub bitrate: u32,
138 pub width: u32,
139 pub height: u32,
140 pub preset: String,
141 pub profile: String,
142 pub crf: u32,
143 pub extra_params: HashMap<String, String>,
144}
145
146#[derive(Clone, PartialEq, Debug, Default)]
148pub struct TimeSegment {
149 pub start_time: f64,
150 pub end_time: f64,
151 pub overlap: f64,
152}
153
154#[derive(Clone, PartialEq, Debug, Default)]
156pub struct TileSegment {
157 pub tile_x: u32,
158 pub tile_y: u32,
159 pub tile_width: u32,
160 pub tile_height: u32,
161}
162
163#[derive(Clone, PartialEq, Debug, Default)]
165pub struct GopSegment {
166 pub start_frame: u64,
167 pub end_frame: u64,
168 pub keyframe_indices: Vec<u64>,
169}
170
171#[derive(Clone, PartialEq, Debug, Default)]
173pub struct ProgressReport {
174 pub job_id: String,
175 pub worker_id: String,
176 pub progress: f32,
177 pub frames_encoded: u64,
178 pub bytes_written: u64,
179 pub encoding_speed: f32,
180 pub estimated_completion_timestamp: i64,
181}
182
183#[derive(Clone, PartialEq, Debug, Default)]
184pub struct ProgressAcknowledgment {
185 pub acknowledged: bool,
186}
187
188#[derive(Clone, PartialEq, Debug, Default)]
190pub struct JobResult {
191 pub job_id: String,
192 pub worker_id: String,
193 pub output_url: String,
194 pub output_size: u64,
195 pub encoding_time: f64,
196 pub metadata: Option<Box<ResultMetadata>>,
197}
198
199#[derive(Clone, PartialEq, Debug, Default)]
200pub struct ResultMetadata {
201 pub frames_encoded: u64,
202 pub average_bitrate: f64,
203 pub checksum: String,
204 pub extra_metadata: HashMap<String, String>,
205}
206
207#[derive(Clone, PartialEq, Debug, Default)]
208pub struct ResultAcknowledgment {
209 pub acknowledged: bool,
210 pub next_job_id: String,
211}
212
213#[derive(Clone, PartialEq, Debug, Default)]
215pub struct JobFailure {
216 pub job_id: String,
217 pub worker_id: String,
218 pub error_message: String,
219 pub error_code: String,
220 pub is_transient: bool,
221}
222
223#[derive(Clone, PartialEq, Debug, Default)]
224pub struct FailureAcknowledgment {
225 pub should_retry: bool,
226 pub reassigned_job_id: String,
227}
228
229pub mod worker_status_request {
231 #[derive(Clone, PartialEq, Debug)]
232 pub enum Query {
233 WorkerId(String),
234 AllWorkers(bool),
235 }
236}
237
238#[derive(Clone, PartialEq, Debug, Default)]
239pub struct WorkerStatusRequest {
240 pub query: Option<worker_status_request::Query>,
241}
242
243#[derive(Clone, PartialEq, Debug, Default)]
244pub struct WorkerStatusResponse {
245 pub workers: Vec<WorkerInfo>,
246}
247
248#[derive(Clone, PartialEq, Debug, Default)]
249pub struct WorkerInfo {
250 pub worker_id: String,
251 pub hostname: String,
252 pub status: Option<Box<WorkerStatus>>,
253 pub metrics: Option<Box<WorkerMetrics>>,
254 pub last_heartbeat_timestamp: i64,
255}
256
257pub mod job_status_request {
258 #[derive(Clone, PartialEq, Debug)]
259 pub enum Query {
260 JobId(String),
261 TaskId(String),
262 }
263}
264
265#[derive(Clone, PartialEq, Debug, Default)]
266pub struct JobStatusRequest {
267 pub query: Option<job_status_request::Query>,
268}
269
270#[derive(Clone, PartialEq, Debug, Default)]
271pub struct JobStatusResponse {
272 pub job_id: String,
273 pub state: i32,
274 pub assigned_worker_id: String,
275 pub progress: f32,
276 pub started_timestamp: i64,
277 pub completed_timestamp: i64,
278}
279
280pub mod job_cancellation {
282 #[derive(Clone, PartialEq, Debug)]
283 pub enum Target {
284 JobId(String),
285 TaskId(String),
286 }
287}
288
289#[derive(Clone, PartialEq, Debug, Default)]
290pub struct JobCancellation {
291 pub target: Option<job_cancellation::Target>,
292}
293
294#[derive(Clone, PartialEq, Debug, Default)]
295pub struct CancellationResponse {
296 pub success: bool,
297 pub cancelled_job_ids: Vec<String>,
298}
299
300pub mod coordinator_service_server {
305 use super::{
306 async_trait, CancellationResponse, FailureAcknowledgment, HeartbeatResponse, JobAssignment,
307 JobCancellation, JobFailure, JobRequest, JobResult, JobStatusRequest, JobStatusResponse,
308 NamedService, ProgressAcknowledgment, ProgressReport, Request, Response,
309 ResultAcknowledgment, Status, UnregistrationResponse, WorkerHeartbeat, WorkerRegistration,
310 WorkerRegistrationResponse, WorkerStatusRequest, WorkerStatusResponse,
311 WorkerUnregistration,
312 };
313
314 #[async_trait]
315 pub trait CoordinatorService: Send + Sync + 'static {
316 async fn register_worker(
317 &self,
318 request: Request<WorkerRegistration>,
319 ) -> Result<Response<WorkerRegistrationResponse>, Status>;
320 async fn heartbeat(
321 &self,
322 request: Request<WorkerHeartbeat>,
323 ) -> Result<Response<HeartbeatResponse>, Status>;
324 async fn unregister_worker(
325 &self,
326 request: Request<WorkerUnregistration>,
327 ) -> Result<Response<UnregistrationResponse>, Status>;
328 async fn request_job(
329 &self,
330 request: Request<JobRequest>,
331 ) -> Result<Response<JobAssignment>, Status>;
332 async fn report_progress(
333 &self,
334 request: Request<ProgressReport>,
335 ) -> Result<Response<ProgressAcknowledgment>, Status>;
336 async fn submit_result(
337 &self,
338 request: Request<JobResult>,
339 ) -> Result<Response<ResultAcknowledgment>, Status>;
340 async fn report_failure(
341 &self,
342 request: Request<JobFailure>,
343 ) -> Result<Response<FailureAcknowledgment>, Status>;
344 async fn get_worker_status(
345 &self,
346 request: Request<WorkerStatusRequest>,
347 ) -> Result<Response<WorkerStatusResponse>, Status>;
348 async fn get_job_status(
349 &self,
350 request: Request<JobStatusRequest>,
351 ) -> Result<Response<JobStatusResponse>, Status>;
352 async fn cancel_job(
353 &self,
354 request: Request<JobCancellation>,
355 ) -> Result<Response<CancellationResponse>, Status>;
356 }
357
358 #[derive(Clone)]
359 #[allow(dead_code)]
360 pub struct CoordinatorServiceServer<T> {
361 inner: std::sync::Arc<T>,
362 }
363
364 impl<T: CoordinatorService> CoordinatorServiceServer<T> {
365 pub fn new(inner: T) -> Self {
366 Self {
367 inner: std::sync::Arc::new(inner),
368 }
369 }
370
371 #[must_use]
372 pub fn inner_ref(&self) -> &T {
373 &self.inner
374 }
375 }
376
377 impl<T> NamedService for CoordinatorServiceServer<T> {
378 const NAME: &'static str = "coordinator.CoordinatorService";
379 }
380}
381
382pub mod coordinator_service_client {
383 use super::{
384 CancellationResponse, FailureAcknowledgment, HeartbeatResponse, JobAssignment,
385 JobCancellation, JobFailure, JobRequest, JobResult, JobStatusRequest, JobStatusResponse,
386 ProgressAcknowledgment, ProgressReport, Request, Response, ResultAcknowledgment, Status,
387 UnregistrationResponse, WorkerHeartbeat, WorkerRegistration, WorkerRegistrationResponse,
388 WorkerStatusRequest, WorkerStatusResponse, WorkerUnregistration,
389 };
390 use tonic::transport::Channel;
391
392 #[derive(Clone)]
393 pub struct CoordinatorServiceClient<T> {
394 inner: T,
395 }
396
397 impl CoordinatorServiceClient<Channel> {
398 pub async fn connect<D>(
399 dst: D,
400 ) -> std::result::Result<Self, Box<dyn std::error::Error + Send + Sync>>
401 where
402 D: std::convert::TryInto<tonic::transport::Endpoint> + Clone,
403 D::Error: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
404 {
405 let endpoint: tonic::transport::Endpoint =
406 dst.try_into().map_err(std::convert::Into::into)?;
407 let channel = endpoint.connect().await?;
408 Ok(Self::new(channel))
409 }
410 }
411
412 impl<T> CoordinatorServiceClient<T> {
413 pub fn new(inner: T) -> Self {
414 Self { inner }
415 }
416
417 pub fn inner_ref(&self) -> &T {
418 &self.inner
419 }
420 }
421
422 impl CoordinatorServiceClient<Channel> {
423 pub async fn register_worker(
424 &mut self,
425 _request: Request<WorkerRegistration>,
426 ) -> Result<Response<WorkerRegistrationResponse>, Status> {
427 Ok(Response::new(WorkerRegistrationResponse::default()))
428 }
429
430 pub async fn heartbeat(
431 &mut self,
432 _request: Request<WorkerHeartbeat>,
433 ) -> Result<Response<HeartbeatResponse>, Status> {
434 Ok(Response::new(HeartbeatResponse::default()))
435 }
436
437 pub async fn unregister_worker(
438 &mut self,
439 _request: Request<WorkerUnregistration>,
440 ) -> Result<Response<UnregistrationResponse>, Status> {
441 Ok(Response::new(UnregistrationResponse::default()))
442 }
443
444 pub async fn request_job(
445 &mut self,
446 _request: Request<JobRequest>,
447 ) -> Result<Response<JobAssignment>, Status> {
448 Ok(Response::new(JobAssignment::default()))
449 }
450
451 pub async fn report_progress(
452 &mut self,
453 _request: Request<ProgressReport>,
454 ) -> Result<Response<ProgressAcknowledgment>, Status> {
455 Ok(Response::new(ProgressAcknowledgment::default()))
456 }
457
458 pub async fn submit_result(
459 &mut self,
460 _request: Request<JobResult>,
461 ) -> Result<Response<ResultAcknowledgment>, Status> {
462 Ok(Response::new(ResultAcknowledgment::default()))
463 }
464
465 pub async fn report_failure(
466 &mut self,
467 _request: Request<JobFailure>,
468 ) -> Result<Response<FailureAcknowledgment>, Status> {
469 Ok(Response::new(FailureAcknowledgment::default()))
470 }
471
472 pub async fn get_worker_status(
473 &mut self,
474 _request: Request<WorkerStatusRequest>,
475 ) -> Result<Response<WorkerStatusResponse>, Status> {
476 Ok(Response::new(WorkerStatusResponse::default()))
477 }
478
479 pub async fn get_job_status(
480 &mut self,
481 _request: Request<JobStatusRequest>,
482 ) -> Result<Response<JobStatusResponse>, Status> {
483 Ok(Response::new(JobStatusResponse::default()))
484 }
485
486 pub async fn cancel_job(
487 &mut self,
488 _request: Request<JobCancellation>,
489 ) -> Result<Response<CancellationResponse>, Status> {
490 Ok(Response::new(CancellationResponse::default()))
491 }
492 }
493}