ปูต้นฉบับตรวจกล่องหน้าสุดบนรางคิวก่อนคีบออก ขณะที่กล่องด้านหลังยังเรียงเดิม

Rust VecDeque::pop_front_if: หยิบหัวคิวเฉพาะเมื่อพร้อม

พี่โชว์Engineering

คิวงานมักมีกฎว่า “หยิบหัวคิวได้ต่อเมื่อถึงเวลา” ถ้าเขียน front() แล้วตามด้วย pop_front() เราต้องรักษาการยืมและเงื่อนไขสองจังหวะเองครับ VecDeque::pop_front_if ส่ง &mut T ของหัวคิวเข้า predicate และนำออกเฉพาะเมื่อได้ true

WHY: ตรวจบัตรตรงประตูเดียวกับที่ปล่อยคนออก

เหมือนเจ้าหน้าที่ดูตั๋วของคนหน้าสุดแล้วเปิดประตูเฉพาะตั๋วที่ถึงรอบ คนข้างหลังห้ามแซงและคิวเดิมไม่ถูกสแกนทั้งหมด API นี้เหมาะกับ priority ที่จัดไว้แล้ว, retry queue และ state machine ที่ตัดสินจากสมาชิกหัวสุด

use std::collections::VecDeque;

fn take_ready(queue: &mut VecDeque<(u64, &'static str)>, now: u64) -> Option<&'static str> {
    queue
        .pop_front_if(|(ready_at, _)| *ready_at <= now)
        .map(|(_, job)| job)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn keeps_unready_head_in_place() {
        let mut queue = VecDeque::from([(20, "later"), (10, "blocked-behind")]);
        assert_eq!(take_ready(&mut queue, 15), None);
        assert_eq!(queue.front(), Some(&(20, "later")));
        assert_eq!(queue.len(), 2);
    }

    #[test]
    fn removes_ready_head_once() {
        let mut queue = VecDeque::from([(10, "ready"), (20, "later")]);
        assert_eq!(take_ready(&mut queue, 15), Some("ready"));
        assert_eq!(queue.front(), Some(&(20, "later")));
    }
}

Predicate แก้ค่าได้ แม้สุดท้ายไม่ pop

เพราะ closure ได้ &mut T การแก้ค่าจะคงอยู่แม้คืน false เช่นเพิ่ม attempts แล้วตัดสินว่ายังไม่พร้อม พลังนี้มีประโยชน์แต่ควรใช้ให้เห็นชัด ถ้าต้องการเพียงอ่าน ให้ predicate ไม่ mutate เพื่อไม่ให้ reviewer ต้องตาม side effect ที่ซ่อนใน boolean

ฟังก์ชันนี้ไม่แก้ starvation หากงานหัวคิวติดถาวร สมาชิกด้านหลังจะยังถูกบัง ถ้าระบบต้องข้ามงานเสีย ควรกำหนด dead-letter, timeout หรือโครงสร้าง priority แยก อย่าวนเรียก pop_front_if แล้วหวังว่าคิวจะจัดตัวเอง

Recap

  • ใช้เมื่อ policy ตรวจเฉพาะหัวคิวจริง ๆ
  • false เก็บสมาชิกไว้ตำแหน่งเดิม
  • mutation ใน predicate คงอยู่แม้ไม่ pop
  • ออกแบบ starvation และ dead-letter แยกจาก API นี้