codex-helper-core 0.15.0

Core library for codex-helper.
Documentation
use std::collections::HashSet;

use axum::http::StatusCode;

use crate::lb::{CooldownBackoff, LoadBalancer};

use super::ProxyService;
use super::attempt_health::penalize_attempt_target;
use super::attempt_target::AttemptTarget;
use super::passive_health::record_passive_upstream_failure;

pub(super) struct TerminalUpstreamFailureParams<'a> {
    pub(super) proxy: &'a ProxyService,
    pub(super) lb: Option<&'a LoadBalancer>,
    pub(super) target: &'a AttemptTarget,
    pub(super) error_class: &'a str,
    pub(super) penalize_reason: Option<&'a str>,
    pub(super) cooldown_secs: u64,
    pub(super) cooldown_backoff: CooldownBackoff,
    pub(super) error_message: String,
    pub(super) avoid_set: &'a mut HashSet<usize>,
    pub(super) avoided_total: &'a mut usize,
    pub(super) last_err: &'a mut Option<(StatusCode, String)>,
}

pub(super) async fn apply_terminal_upstream_failure(params: TerminalUpstreamFailureParams<'_>) {
    let TerminalUpstreamFailureParams {
        proxy,
        lb,
        target,
        error_class,
        penalize_reason,
        cooldown_secs,
        cooldown_backoff,
        error_message,
        avoid_set,
        avoided_total,
        last_err,
    } = params;

    if let Some(reason) = penalize_reason {
        penalize_attempt_target(
            proxy.state.as_ref(),
            proxy.service_name,
            lb,
            target,
            cooldown_secs,
            reason,
            cooldown_backoff,
        )
        .await;
    }

    if let Some(station_name) = target.compatibility_station_name() {
        record_passive_upstream_failure(
            proxy.state.as_ref(),
            proxy.service_name,
            station_name,
            &target.upstream().base_url,
            Some(StatusCode::BAD_GATEWAY.as_u16()),
            Some(error_class),
            Some(error_message.clone()),
        )
        .await;
    }

    if avoid_set.insert(target.attempt_avoid_index()) {
        *avoided_total = avoided_total.saturating_add(1);
    }
    *last_err = Some((StatusCode::BAD_GATEWAY, error_message));
}