Skip to main content

offline_intelligence/
backend_target.rs

1// Server/src/backend_target.rs
2// Lock-free backend target using atomic pointer swapping
3
4use std::sync::Arc;
5use arc_swap::ArcSwap;
6use tracing::{info, warn};
7
8#[derive(Clone)]
9pub struct BackendTarget {
10    inner: Arc<ArcSwap<String>>,
11}
12
13impl BackendTarget {
14    pub fn new(initial: String) -> Self {
15        Self {
16            inner: Arc::new(ArcSwap::new(Arc::new(initial))),
17        }
18    }
19
20    pub async fn set(&self, new_target: String) {
21        let current = self.inner.load();
22        
23        // If current value is empty, always set it (no warning)
24        if current.is_empty() {
25            info!("🔄 Setting initial backend target to: {}", new_target);
26            self.inner.store(Arc::new(new_target));
27        } 
28        // Only warn if we're changing from one non-empty value to another
29        else if **current != new_target {
30            info!("🔄 Switching backend target from {} → {}", **current, new_target);
31            self.inner.store(Arc::new(new_target));
32        } else {
33            warn!("backend target set() called, but no change (still {})", new_target);
34        }
35    }
36
37    pub async fn get(&self) -> String {
38        (**self.inner.load()).clone()
39    }
40
41    /// Check if backend target is properly initialized
42    pub async fn is_initialized(&self) -> bool {
43        !self.inner.load().is_empty()
44    }
45
46    /// Main generation endpoint used by your Python code
47    /// Your Python Core_engine.rs calls the root endpoint "/"
48    pub async fn generate_url(&self) -> String {
49        let base = self.get().await;
50        if base.is_empty() {
51            warn!("Backend target not initialized yet, returning empty URL");
52        }
53        format!("{}/", base)
54    }
55
56    /// Health check endpoint for connection testing
57    pub async fn health_url(&self) -> String {
58        let base = self.get().await;
59        format!("{}/health", base)
60    }
61
62    /// Chat completions (OpenAI-compatible endpoint used by proxy)
63    pub async fn chat_completions_url(&self) -> String {
64        let base = self.get().await;
65        format!("{}/v1/chat/completions", base)
66    }
67
68    /// NEW: Direct endpoint for your Python code's current structure
69    /// This matches what your Core_engine.rs _post() method expects
70    pub async fn direct_generation_url(&self) -> String {
71        let base = self.get().await;
72        if base.is_empty() {
73            warn!("Backend target not initialized yet, returning empty URL");
74        }
75        format!("{}/", base)
76    }
77}