ferogram 0.6.5

A native, elegant, and asynchronous MTProto framework in Rust for Telegram clients, bots, and applications.
Documentation
/*
 * Copyright (c) 2026 Ankit Chaubey <ankitchaubey.dev@gmail.com>
 * https://github.com/ankit-chaubey
 *
 * Project: ferogram
 * Website: https://ferogram.dev
 *
 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 * https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 * <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
 * This file may not be copied, modified, or distributed except according
 * to those terms.
 */

use std::collections::{HashSet, VecDeque};

/// Bounded ring-buffer dedup cache. Sits beneath the pts machinery as a
/// last-resort guard against edge-case duplicates (e.g. a live socket update
/// racing a diff replay that covers the same message).
///
/// Keyed by (canonical_peer_id, msg_id). Capacity-bounded: evicts the oldest
/// entry on overflow so memory stays O(1).
///
/// Uses a `HashSet` for O(1) membership checks alongside a `VecDeque` for
/// ordered eviction. Same memory profile as the old VecDeque-only approach,
/// ~10x faster at high message rates.
pub struct BoundedDedupeCache {
    // Ordered eviction queue.
    order: VecDeque<(i64, i32)>,
    // O(1) membership check; mirrors `order` exactly.
    set: HashSet<(i64, i32)>,
    capacity: usize,
    /// Total duplicates suppressed since creation.
    pub suppressed: u64,
}

impl BoundedDedupeCache {
    pub fn new(capacity: usize) -> Self {
        Self {
            order: VecDeque::with_capacity(capacity),
            set: HashSet::with_capacity(capacity),
            capacity,
            suppressed: 0,
        }
    }

    /// Returns true if (peer_id, msg_id) was already seen, meaning the update
    /// is a duplicate and should be dropped. Otherwise inserts and returns false.
    #[inline]
    pub fn check_and_insert(&mut self, peer_id: i64, msg_id: i32) -> bool {
        if self.set.contains(&(peer_id, msg_id)) {
            self.suppressed += 1;
            tracing::debug!(
                "[ferogram::persist] duplicate update suppressed (msg_id={msg_id}, peer={peer_id}, total_suppressed={})",
                self.suppressed
            );
            return true;
        }
        if self.order.len() >= self.capacity
            && let Some(evicted) = self.order.pop_front()
        {
            self.set.remove(&evicted);
        }
        self.order.push_back((peer_id, msg_id));
        self.set.insert((peer_id, msg_id));
        false
    }
}

impl Default for BoundedDedupeCache {
    fn default() -> Self {
        Self::new(512)
    }
}