bindizr-service 0.1.0-beta.4

Application services for bindizr zone, record, token, and notification workflows
Documentation
use super::{ZoneService, validation::normalize_zone_lookup_name};
use crate::{
    error::ServiceError, log_error, log_info, model::zone::Zone, repository::RepositoryService,
    serial::generate_serial, zone::snapshot::save_zone_snapshot_tx,
};

impl ZoneService {
    pub async fn force_increment_serial(
        zone_name: Option<&str>,
    ) -> Result<Vec<Zone>, ServiceError> {
        match zone_name {
            Some(name) => {
                let zone = Self::force_increment_zone_serial(name).await?;
                Ok(vec![zone])
            }
            None => {
                let zones = Self::list().await?;
                let mut bumped_zones = Vec::with_capacity(zones.len());

                for zone in zones {
                    bumped_zones.push(Self::force_increment_zone_serial(&zone.name).await?);
                }

                Ok(bumped_zones)
            }
        }
    }

    async fn force_increment_zone_serial(zone_name: &str) -> Result<Zone, ServiceError> {
        let lookup_name = normalize_zone_lookup_name(zone_name)?;
        let mut tx = RepositoryService::begin_tx("Failed to force increment zone serial").await?;

        let apply_result = async {
            let zone = match RepositoryService::get_zone_by_name_tx(&mut tx, &lookup_name).await {
                Ok(Some(zone)) => zone,
                Ok(None) => {
                    return Err(ServiceError::NotFound(format!(
                        "Zone with name '{}' not found",
                        zone_name
                    )));
                }
                Err(e) => {
                    log_error!("Failed to fetch zone: {}", e);
                    return Err(ServiceError::Internal(
                        "Failed to force increment zone serial".to_string(),
                    ));
                }
            };

            let new_serial = generate_serial(Some(zone.serial));
            let updated_zone = RepositoryService::update_zone_tx(
                &mut tx,
                Zone {
                    serial: new_serial,
                    ..zone.clone()
                },
            )
            .await
            .map_err(|e| {
                log_error!("Failed to force increment zone serial: {}", e);
                ServiceError::Internal("Failed to force increment zone serial".to_string())
            })?;

            save_zone_snapshot_tx(&mut tx, &updated_zone, new_serial).await?;

            Ok::<Zone, ServiceError>(updated_zone)
        }
        .await;

        let updated_zone =
            RepositoryService::finish_tx(tx, apply_result, "Failed to force increment zone serial")
                .await?;

        log_info!(
            "event=zone_force_serial zone={} new_serial={} zone_id={}",
            updated_zone.name,
            updated_zone.serial,
            updated_zone.id
        );

        Ok(updated_zone)
    }
}