Frontend leser fra SpacetimeDB, men workeren skrev kun til PG. Nå kalles edit_message-reduceren i SpacetimeDB etter vellykket AI-behandling, slik at resultatet vises umiddelbart i chatten. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
117 lines
3.2 KiB
Rust
117 lines
3.2 KiB
Rust
use clap::Parser;
|
|
use sqlx::postgres::PgPoolOptions;
|
|
use std::sync::Arc;
|
|
use tracing::{info, warn};
|
|
|
|
mod handlers;
|
|
mod sync;
|
|
mod warmup;
|
|
mod worker;
|
|
|
|
#[derive(Parser)]
|
|
#[command(name = "sidelinja-worker", about = "Jobbkø-worker for Sidelinja")]
|
|
struct Cli {
|
|
/// PostgreSQL connection string
|
|
#[arg(
|
|
long,
|
|
env = "DATABASE_URL",
|
|
default_value = "postgres://sidelinja:localdev@localhost:5432/sidelinja"
|
|
)]
|
|
database_url: String,
|
|
|
|
/// AI Gateway base URL
|
|
#[arg(
|
|
long,
|
|
env = "AI_GATEWAY_URL",
|
|
default_value = "http://localhost:4000/v1"
|
|
)]
|
|
ai_gateway_url: String,
|
|
|
|
/// AI Gateway API-nøkkel (LiteLLM master key)
|
|
#[arg(long, env = "AI_GATEWAY_KEY", default_value = "")]
|
|
ai_gateway_key: String,
|
|
|
|
/// Maks samtidige jobber
|
|
#[arg(long, default_value = "3")]
|
|
max_concurrent: usize,
|
|
|
|
/// Polling-intervall i sekunder
|
|
#[arg(long, default_value = "1")]
|
|
poll_interval: u64,
|
|
|
|
/// SpacetimeDB URL
|
|
#[arg(long, env = "SPACETIMEDB_URL", default_value = "http://localhost:3000")]
|
|
spacetimedb_url: String,
|
|
|
|
/// SpacetimeDB modulnavn
|
|
#[arg(long, env = "SPACETIMEDB_MODULE", default_value = "sidelinja-realtime")]
|
|
spacetimedb_module: String,
|
|
|
|
/// Sync-intervall i sekunder (SpacetimeDB → PG)
|
|
#[arg(long, default_value = "1")]
|
|
sync_interval: u64,
|
|
|
|
/// Maks meldinger per kanal ved oppvarming
|
|
#[arg(long, default_value = "100")]
|
|
warmup_limit: i64,
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> anyhow::Result<()> {
|
|
tracing_subscriber::fmt()
|
|
.with_env_filter(
|
|
tracing_subscriber::EnvFilter::try_from_default_env()
|
|
.unwrap_or_else(|_| "sidelinja_worker=info,sqlx=warn".into()),
|
|
)
|
|
.json()
|
|
.init();
|
|
|
|
let cli = Cli::parse();
|
|
|
|
info!(
|
|
max_concurrent = cli.max_concurrent,
|
|
poll_interval_s = cli.poll_interval,
|
|
"Starter sidelinja-worker"
|
|
);
|
|
|
|
let pool = PgPoolOptions::new()
|
|
.max_connections(cli.max_concurrent as u32 + 2)
|
|
.connect(&cli.database_url)
|
|
.await?;
|
|
|
|
info!("Tilkoblet PostgreSQL");
|
|
|
|
let registry = Arc::new(handlers::build_registry(
|
|
reqwest::Client::new(),
|
|
cli.ai_gateway_url,
|
|
cli.ai_gateway_key,
|
|
cli.spacetimedb_url.clone(),
|
|
cli.spacetimedb_module.clone(),
|
|
));
|
|
|
|
let registered: Vec<&str> = registry.keys().map(|k| k.as_str()).collect();
|
|
info!(?registered, "Registrerte jobbtyper");
|
|
|
|
// Oppvarming: last PG-data inn i SpacetimeDB
|
|
let http = reqwest::Client::new();
|
|
if let Err(e) = warmup::run(
|
|
&pool,
|
|
&http,
|
|
&cli.spacetimedb_url,
|
|
&cli.spacetimedb_module,
|
|
cli.warmup_limit,
|
|
).await {
|
|
warn!(error = %e, "Oppvarming feilet — fortsetter uten historikk i SpacetimeDB");
|
|
}
|
|
|
|
// Spawn sync-worker som parallell task
|
|
let sync_pool = pool.clone();
|
|
let spacetimedb_url = cli.spacetimedb_url.clone();
|
|
let spacetimedb_module = cli.spacetimedb_module.clone();
|
|
let sync_interval = cli.sync_interval;
|
|
tokio::spawn(async move {
|
|
sync::run(sync_pool, http, spacetimedb_url, spacetimedb_module, sync_interval).await;
|
|
});
|
|
|
|
worker::run(pool, registry, cli.max_concurrent, cli.poll_interval).await
|
|
}
|