Skip to main content

shift_proxy/
optimize.rs

1//! Shared image optimization logic for provider route handlers.
2//!
3//! Extracted to avoid duplication between Anthropic and OpenAI routes.
4//! The optimization runs on a blocking thread to avoid starving the
5//! tokio event loop during CPU-intensive image operations.
6
7use shift_preflight::{Report, ShiftConfig};
8
9/// Run the SHIFT pipeline on a JSON payload.
10///
11/// Returns the transformed JSON string and report, or None if no optimization
12/// was needed or an error occurred (fail-safe: passthrough on error).
13///
14/// This function is synchronous (CPU-bound image operations) and MUST be
15/// called from `tokio::task::spawn_blocking`.
16pub fn optimize_payload(body: &str, config: &ShiftConfig) -> Option<(String, Report)> {
17    // Parse the payload
18    let payload: serde_json::Value = match serde_json::from_str(body) {
19        Ok(v) => v,
20        Err(e) => {
21            tracing::warn!("failed to parse payload as JSON: {}", e);
22            return None;
23        }
24    };
25
26    // Run the pipeline
27    let (result, report) = match shift_preflight::process(&payload, config) {
28        Ok(r) => r,
29        Err(e) => {
30            tracing::warn!("SHIFT pipeline error: {}", e);
31            return None;
32        }
33    };
34
35    // Only return if something actually changed
36    if !report.has_changes() {
37        return None;
38    }
39
40    // Serialize back to JSON (compact, not pretty — this is a wire payload)
41    match serde_json::to_string(&result) {
42        Ok(json) => Some((json, report)),
43        Err(e) => {
44            tracing::warn!("failed to serialize optimized payload: {}", e);
45            None
46        }
47    }
48}