tgqe 0.0.1

The Great Qin Empire —— A centralized system for integrating and summarizing common compiler front-end library errors and span error output libraries, with optional Ariadne integration.
/**

 *  - Copyright (c) 星灿长风v(Starwindv) 2026/08/03
 *  - License: BSD-3
 *  - Author: 星灿长风v(StarWindv)
 *  - Location: tgqe/src/modules/channel/bus.rs
 */
use std::sync::atomic::Ordering;

use crate::base_types::TgqeCtx;
use crate::channel::renderer::Renderer;
use crate::singletons::{
    Configure, ERROR_COUNTER,
};

#[cfg(feature = "store-to-db")]
use crate::singletons::DBManager;

/**

 * ## I. What
 *
 * ### 1.1 Description
 *
 * This structure is the "bus" of the whole library.
 *
 * It receives a batch of `TgqeCtx`, renders the ones within
 * the render limit one by one, and stores the rest into the
 * database (when the `store-to-db` feature is enabled).
 *
 * ---
 *
 * ## II. Memory Layout
 *
 * ### 2.1 Analyze
 *
 * ```text
 * TgqeBus <
 *     mailbox: Vec<TgqeCtx>, // 24
 * > // 24
 * ```
 *
 * ---
 *
 * ## III. Default Value:
 * - mailbox: empty vector
 */
pub struct TgqeBus {
    mailbox: Vec<TgqeCtx>,
}

impl TgqeBus {
    pub(crate) fn new() -> Self {
        Self {
            mailbox: Vec::new(),
        }
    }

    pub async fn report(
        &mut self,
        ctxs: &mut Vec<TgqeCtx>,
    ) {
        self.mailbox.append(ctxs);
        self.auto_report().await;
    }

    async fn auto_report(&mut self) {
        let errors = std::mem::take(
            &mut self.mailbox,
        );

        let mut render_count = 0usize;
        for (i, ctx) in
            errors.iter().enumerate()
        {
            ERROR_COUNTER.fetch_add(
                1,
                Ordering::Relaxed,
            );
            if ERROR_COUNTER
                .load(Ordering::Relaxed)
                > Configure.render_limit
            {
                break;
            }
            Renderer::draw(ctx);
            render_count = i + 1;
        }

        let rest = errors
            .into_iter()
            .skip(render_count);

        #[cfg(feature = "store-to-db")]
        {
            let rest: Vec<TgqeCtx> =
                rest.collect();
            if !rest.is_empty() {
                self.save(rest).await;
            }
        }

        #[cfg(not(feature = "store-to-db"))]
        for ctx in rest {
            ERROR_COUNTER.fetch_add(
                1,
                Ordering::Relaxed,
            );
            Renderer::draw(&ctx);
        }
    }

    #[cfg(feature = "store-to-db")]
    async fn save(
        &self,
        errors: Vec<TgqeCtx>,
    ) {
        let mut db =
            DBManager.lock().unwrap();
        if let Err(e) =
            db.batch_save(&errors).await
        {
            eprintln!(
                "[TGQE] Failed to store to the database: {e}"
            );
        }
        ERROR_COUNTER.fetch_add(
            errors.len() as u64,
            Ordering::Relaxed,
        );
    }
}