mirror of
https://github.com/geoffsee/predict-otron-9001.git
synced 2025-09-08 22:46:44 +00:00
move cli into crates and stage for release
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "predict-otron-9000"
|
||||
version = "0.1.1"
|
||||
version.workspace = true
|
||||
edition = "2024"
|
||||
|
||||
[[bin]]
|
||||
@@ -44,4 +44,8 @@ port = 8080
|
||||
image = "ghcr.io/geoffsee/predict-otron-9000:latest"
|
||||
replicas = 1
|
||||
port = 8080
|
||||
env = { SERVER_CONFIG = "" }
|
||||
# SERVER_CONFIG Example: {\"serverMode\":\"HighAvailability\",\"services\":{\"inference_url\":\"http://custom-inference:9000\",\"embeddings_url\":\"http://custom-embeddings:9001\"}}
|
||||
# you can generate this via node to avoid toil
|
||||
# const server_config = {serverMode: "HighAvailability", services: {inference_url: "http://custom-inference:9000", embeddings_url: "http://custom-embeddings:9001"} };
|
||||
# console.log(JSON.stringify(server_config).replace(/"/g, '\\"'));
|
||||
env = { SERVER_CONFIG = "<your-json-value-here>" }
|
||||
|
@@ -2,7 +2,10 @@ use serde::{Deserialize, Serialize};
|
||||
use std::env;
|
||||
use tracing::info;
|
||||
use tracing::log::error;
|
||||
|
||||
/// # Generating `SERVER_CONFIG` with Node
|
||||
// # const server_config = {serverMode: "HighAvailability", services: {inference_url: "http://custom-inference:9000", embeddings_url: "http://custom-embeddings:9001"} };
|
||||
// # console.log(JSON.stringify(server_config).replace(/"/g, '\\"'));
|
||||
///
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ServerConfig {
|
||||
|
@@ -12,6 +12,120 @@ use std::time::Duration;
|
||||
|
||||
use crate::config::ServerConfig;
|
||||
|
||||
/// # Generating `SERVER_CONFIG` for TOML using Node.js
|
||||
///
|
||||
/// You can still use the Node.js REPL to build the JSON, but when pasting into
|
||||
/// a `.toml` file you must follow TOML's string rules. Below are the safest patterns.
|
||||
///
|
||||
/// ## 1) Generate the JSON in Node
|
||||
/// ```bash
|
||||
/// node
|
||||
/// ```
|
||||
/// ```javascript
|
||||
/// const myobject = {
|
||||
/// serverMode: "HighAvailability",
|
||||
/// services: {
|
||||
/// inference_url: "http://custom-inference:9000",
|
||||
/// embeddings_url: "http://custom-embeddings:9001"
|
||||
/// }
|
||||
/// };
|
||||
/// const json = JSON.stringify(myobject);
|
||||
/// json
|
||||
/// // -> '{"serverMode":"HighAvailability","services":{"inference_url":"http://custom-inference:9000","embeddings_url":"http://custom-embeddings:9001"}}'
|
||||
/// ```
|
||||
///
|
||||
/// ## 2) Put it into `.toml`
|
||||
///
|
||||
/// ### Option A (recommended): single-quoted TOML *literal* string
|
||||
/// Single quotes in TOML mean "no escaping", so your inner double quotes are safe.
|
||||
/// ```toml
|
||||
/// SERVER_CONFIG = '{"serverMode":"HighAvailability","services":{"inference_url":"http://custom-inference:9000","embeddings_url":"http://custom-embeddings:9001"}}'
|
||||
/// ```
|
||||
///
|
||||
/// ### Option B: double-quoted TOML string (must escape inner quotes)
|
||||
/// If you *must* use double quotes in TOML, escape all `"` inside the JSON.
|
||||
/// You can have Node do this for you:
|
||||
/// ```javascript
|
||||
/// // In Node:
|
||||
/// const jsonForToml = JSON.stringify(myobject).replace(/"/g, '\\"');
|
||||
/// jsonForToml
|
||||
/// // -> \"{\\\"serverMode\\\":\\\"HighAvailability\\\",...}\"
|
||||
/// ```
|
||||
/// Then paste into TOML:
|
||||
/// ```toml
|
||||
/// SERVER_CONFIG = "{\"serverMode\":\"HighAvailability\",\"services\":{\"inference_url\":\"http://custom-inference:9000\",\"embeddings_url\":\"http://custom-embeddings:9001\"}}"
|
||||
/// ```
|
||||
///
|
||||
/// ### Option C: multi-line literal (for pretty JSON)
|
||||
/// If you want pretty-printed JSON in the file, use TOML's triple single quotes:
|
||||
/// ```javascript
|
||||
/// // In Node (pretty with 2 spaces):
|
||||
/// const pretty = JSON.stringify(myobject, null, 2);
|
||||
/// ```
|
||||
/// ```toml
|
||||
/// SERVER_CONFIG = '''{
|
||||
/// "serverMode": "HighAvailability",
|
||||
/// "services": {
|
||||
/// "inference_url": "http://custom-inference:9000",
|
||||
/// "embeddings_url": "http://custom-embeddings:9001"
|
||||
/// }
|
||||
/// }'''
|
||||
/// ```
|
||||
///
|
||||
/// ## 3) Reading it in Rust
|
||||
///
|
||||
/// If `SERVER_CONFIG` is stored as a **string** in TOML (Options A/B/C):
|
||||
/// ```rust
|
||||
/// use serde_json::Value;
|
||||
///
|
||||
/// // Suppose you've already loaded your .toml into a struct or a toml::Value:
|
||||
/// // e.g., struct FileCfg { pub SERVER_CONFIG: String }
|
||||
/// fn parse_server_config(raw: &str) -> anyhow::Result<Value> {
|
||||
/// let v: Value = serde_json::from_str(raw)?;
|
||||
/// Ok(v)
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ### Alternative: store it as TOML tables and serialize to JSON at runtime
|
||||
/// Instead of a JSON string, you can make the TOML first-class tables:
|
||||
/// ```toml
|
||||
/// [SERVER_CONFIG]
|
||||
/// serverMode = "HighAvailability"
|
||||
///
|
||||
/// [SERVER_CONFIG.services]
|
||||
/// inference_url = "http://custom-inference:9000"
|
||||
/// embeddings_url = "http://custom-embeddings:9001"
|
||||
/// ```
|
||||
/// ```rust
|
||||
/// use serde::{Deserialize, Serialize};
|
||||
/// use serde_json::Value;
|
||||
///
|
||||
/// #[derive(Debug, Serialize, Deserialize)]
|
||||
/// struct Services {
|
||||
/// inference_url: String,
|
||||
/// embeddings_url: String,
|
||||
/// }
|
||||
///
|
||||
/// #[derive(Debug, Serialize, Deserialize)]
|
||||
/// struct ServerConfig {
|
||||
/// serverMode: String,
|
||||
/// services: Services,
|
||||
/// }
|
||||
///
|
||||
/// // After loading the .toml (e.g., via `toml::from_str`):
|
||||
/// // let cfg: ServerConfig = toml::from_str(toml_str)?;
|
||||
/// // Convert to JSON if needed:
|
||||
/// fn to_json(cfg: &ServerConfig) -> serde_json::Result<Value> {
|
||||
/// Ok(serde_json::to_value(cfg)?)
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Gotchas
|
||||
/// - Prefer **single-quoted** TOML strings for raw JSON to avoid escaping.
|
||||
/// - If you use **double-quoted** TOML strings, escape every inner `"` in the JSON.
|
||||
/// - Pretty JSON is fine in TOML using `''' ... '''`, but remember the newlines are part of the string.
|
||||
/// - If you control the consumer, TOML tables (the alternative above) are more ergonomic than embedding JSON.
|
||||
|
||||
/// HTTP client configured for proxying requests
|
||||
#[derive(Clone)]
|
||||
pub struct ProxyClient {
|
||||
@@ -31,7 +145,7 @@ impl ProxyClient {
|
||||
}
|
||||
|
||||
/// Create a router that proxies requests to external services in HighAvailability mode
|
||||
pub fn create_proxy_router(config: ServerConfig) -> Router {
|
||||
pub fn create_ha_router(config: ServerConfig) -> Router {
|
||||
let proxy_client = ProxyClient::new(config.clone());
|
||||
|
||||
Router::new()
|
@@ -1,16 +1,16 @@
|
||||
mod config;
|
||||
mod ha_mode;
|
||||
mod middleware;
|
||||
mod proxy;
|
||||
mod standalone;
|
||||
mod standalone_mode;
|
||||
|
||||
use crate::standalone::create_standalone_router;
|
||||
use crate::standalone_mode::create_standalone_router;
|
||||
use axum::response::IntoResponse;
|
||||
use axum::routing::get;
|
||||
use axum::{Router, http::Uri, response::Html, serve};
|
||||
use config::ServerConfig;
|
||||
use ha_mode::create_ha_router;
|
||||
use inference_engine::AppState;
|
||||
use middleware::{MetricsLayer, MetricsLoggerFuture, MetricsStore};
|
||||
use proxy::create_proxy_router;
|
||||
use rust_embed::Embed;
|
||||
use std::env;
|
||||
use std::path::Component::ParentDir;
|
||||
@@ -56,7 +56,7 @@ async fn main() {
|
||||
Ok(is_ha) => {
|
||||
if is_ha {
|
||||
log_config(server_config.clone());
|
||||
create_proxy_router(server_config.clone())
|
||||
create_ha_router(server_config.clone())
|
||||
} else {
|
||||
log_config(server_config.clone());
|
||||
create_standalone_router(server_config)
|
||||
|
Reference in New Issue
Block a user