mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-04 19:45:34 +08:00
fix(pi): restore catalog and takeover authority boundaries
This commit is contained in:
@@ -13,9 +13,85 @@ use super::providers::delete_provider_on_tx;
|
||||
use crate::database::{lock_conn, Database};
|
||||
use crate::error::AppError;
|
||||
use crate::provider::{ProviderAggregate, ProviderMutationInput};
|
||||
use indexmap::IndexMap;
|
||||
use rusqlite::params;
|
||||
|
||||
impl Database {
|
||||
pub(crate) fn restore_pi_catalog_snapshot(
|
||||
&self,
|
||||
aggregates: &IndexMap<String, ProviderAggregate>,
|
||||
projections: &[PiProviderProjection],
|
||||
current_provider: Option<&str>,
|
||||
) -> Result<(), AppError> {
|
||||
let mut conn = lock_conn!(self.conn);
|
||||
let tx = conn
|
||||
.transaction()
|
||||
.map_err(|error| AppError::Database(error.to_string()))?;
|
||||
tx.execute("DELETE FROM pi_provider_projections", [])
|
||||
.map_err(|error| AppError::Database(error.to_string()))?;
|
||||
let current_ids = {
|
||||
let mut statement = tx
|
||||
.prepare("SELECT id FROM providers WHERE app_type = 'pi'")
|
||||
.map_err(|error| AppError::Database(error.to_string()))?;
|
||||
let ids = statement
|
||||
.query_map([], |row| row.get::<_, String>(0))
|
||||
.map_err(|error| AppError::Database(error.to_string()))?
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|error| AppError::Database(error.to_string()))?;
|
||||
ids
|
||||
};
|
||||
for provider_id in current_ids
|
||||
.iter()
|
||||
.filter(|provider_id| !aggregates.contains_key(provider_id.as_str()))
|
||||
{
|
||||
// Only rows created after the snapshot are removed. Updating
|
||||
// providers which existed in the snapshot preserves dependent
|
||||
// provider_health history instead of triggering ON DELETE CASCADE.
|
||||
delete_provider_on_tx(&tx, "pi", provider_id)?;
|
||||
}
|
||||
|
||||
for aggregate in aggregates.values() {
|
||||
let key = ProviderKey::new("pi", aggregate.provider.id.clone())?;
|
||||
let mut input = provider_mutation_input(aggregate);
|
||||
if let Some(meta) = input.meta.as_mut() {
|
||||
meta.custom_endpoints.clear();
|
||||
}
|
||||
let row = ProviderRowUpdate::from_input(&input)?;
|
||||
let endpoints = aggregate
|
||||
.endpoints
|
||||
.values()
|
||||
.cloned()
|
||||
.map(NewEndpoint::try_from)
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
restore_provider_aggregate_on_tx(
|
||||
&tx,
|
||||
&key,
|
||||
&row,
|
||||
aggregate.provider.created_at,
|
||||
aggregate.provider.sort_index,
|
||||
current_provider == Some(key.id()),
|
||||
aggregate.provider.in_failover_queue,
|
||||
&endpoints,
|
||||
)?;
|
||||
}
|
||||
for projection in projections {
|
||||
tx.execute(
|
||||
"INSERT INTO pi_provider_projections
|
||||
(provider_id, provider_key, created_at, updated_at)
|
||||
VALUES (?1, ?2, ?3, ?4)",
|
||||
params![
|
||||
projection.provider_id,
|
||||
projection.provider_key,
|
||||
projection.created_at,
|
||||
projection.updated_at
|
||||
],
|
||||
)
|
||||
.map_err(|error| AppError::Database(error.to_string()))?;
|
||||
}
|
||||
tx.commit()
|
||||
.map_err(|error| AppError::Database(error.to_string()))
|
||||
}
|
||||
|
||||
pub(crate) fn create_pi_catalog_provider(
|
||||
&self,
|
||||
input: NewProviderAggregate,
|
||||
|
||||
@@ -94,6 +94,9 @@ impl Database {
|
||||
let transaction = conn
|
||||
.transaction()
|
||||
.map_err(|error| AppError::Database(error.to_string()))?;
|
||||
transaction
|
||||
.execute("DELETE FROM prompts WHERE app_type = ?1", [app_type])
|
||||
.map_err(|error| AppError::Database(error.to_string()))?;
|
||||
{
|
||||
let mut statement = transaction
|
||||
.prepare(
|
||||
|
||||
Reference in New Issue
Block a user