Created
January 19, 2026 22:57
-
-
Save greenido/6a43bade6c5c985f806c0c53870a7c36 to your computer and use it in GitHub Desktop.
An example that demonstrates the priority queue behavior with 25 events of mixed priorities. We'll enqueue them in a somewhat realistic mixed order, then dequeue them step-by-step while showing: 1) When normal priority order is respected 2) When aging (temporal priority boost) starts kicking in after ~X seconds
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class PriorityQueue { | |
| constructor(X = 5) { // X in seconds – events older than this get promoted | |
| this.high = []; // edr_security | |
| this.medium = []; // scripts_edr | |
| this.low = []; // extension | |
| this.X = X * 1000; // milliseconds | |
| } | |
| enqueue(eventData, type) { | |
| const event = { | |
| id: eventData.id || Date.now(), // just for demo identification | |
| data: eventData.data || eventData, | |
| type, | |
| timestamp: Date.now() | |
| }; | |
| if (type === 'edr_security') this.high.push(event); | |
| else if (type === 'scripts_edr') this.medium.push(event); | |
| else if (type === 'extension') this.low.push(event); | |
| else throw new Error('Unknown event type'); | |
| } | |
| dequeue() { | |
| const now = Date.now(); | |
| // Promote aged low → medium | |
| while (this.low.length > 0 && now - this.low[0].timestamp > this.X) { | |
| const aged = this.low.shift(); | |
| aged.promoted = aged.promoted ? aged.promoted + 1 : 1; | |
| this.medium.push(aged); | |
| } | |
| // Promote aged medium → high | |
| while (this.medium.length > 0 && now - this.medium[0].timestamp > this.X) { | |
| const aged = this.medium.shift(); | |
| aged.promoted = aged.promoted ? aged.promoted + 1 : 1; | |
| this.high.push(aged); | |
| } | |
| if (this.high.length > 0) return this.high.shift(); | |
| if (this.medium.length > 0) return this.medium.shift(); | |
| if (this.low.length > 0) return this.low.shift(); | |
| return null; | |
| } | |
| isEmpty() { return this.high.length + this.medium.length + this.low.length === 0; } | |
| size() { return this.high.length + this.medium.length + this.low.length; } | |
| } | |
| // ──────────────────────────────────────────────── | |
| // DEMO WITH 25 EVENTS + AGING | |
| // ──────────────────────────────────────────────── | |
| const pq = new PriorityQueue(5); // promote after 5 seconds | |
| // Mock time control (in real app remove this) | |
| let mockTime = Date.now(); | |
| const originalNow = Date.now; | |
| Date.now = () => mockTime; | |
| // Helper to add event with shorthand | |
| function add(id, type) { | |
| pq.enqueue({ id, data: `${type} #${id}` }, type); | |
| } | |
| // Enqueue 25 mixed events (not in perfect order) | |
| add(1, 'edr_security'); // H1 | |
| add(2, 'extension'); // L1 | |
| add(3, 'scripts_edr'); // M1 | |
| add(4, 'edr_security'); // H2 | |
| add(5, 'extension'); // L2 | |
| add(6, 'extension'); // L3 | |
| add(7, 'scripts_edr'); // M2 | |
| add(8, 'edr_security'); // H3 | |
| add(9, 'extension'); // L4 | |
| add(10, 'scripts_edr'); // M3 | |
| add(11, 'edr_security'); // H4 | |
| add(12, 'extension'); // L5 | |
| add(13, 'scripts_edr'); // M4 | |
| add(14, 'extension'); // L6 | |
| add(15, 'edr_security'); // H5 | |
| add(16, 'extension'); // L7 | |
| add(17, 'scripts_edr'); // M5 | |
| add(18, 'extension'); // L8 | |
| add(19, 'edr_security'); // H6 | |
| add(20, 'extension'); // L9 | |
| add(21, 'scripts_edr'); // M6 | |
| add(22, 'extension'); // L10 | |
| add(23, 'edr_security'); // H7 | |
| add(24, 'scripts_edr'); // M7 | |
| add(25, 'extension'); // L11 | |
| console.log(`Initial queue size: ${pq.size()}\n`); | |
| // ── Phase 1: Dequeue while time = 0 (no aging yet) ── | |
| console.log("Phase 1 – Fresh queue (no aging):"); | |
| for (let i = 1; i <= 7 && !pq.isEmpty(); i++) { | |
| const e = pq.dequeue(); | |
| console.log(` ${i}. ${e.type[0].toUpperCase()} ${e.data} (age: 0s)`); | |
| } | |
| // → Should get all 7 high-priority events first (H1–H7) | |
| // ── Advance time by 6 seconds → low & medium start promoting ── | |
| mockTime += 6000; | |
| console.log(`\nTime advanced +6s → aging begins\n`); | |
| console.log("Phase 2 – After 6 seconds (low → medium, medium → high):"); | |
| let count = 8; | |
| while (!pq.isEmpty() && count <= 18) { | |
| const e = pq.dequeue(); | |
| const ageSec = Math.round((mockTime - e.timestamp) / 1000); | |
| const prom = e.promoted ? ` (promoted ×${e.promoted})` : ''; | |
| console.log(` ${count}. ${e.type[0].toUpperCase()} ${e.data} (age: ${ageSec}s${prom})`); | |
| count++; | |
| } | |
| // ── Advance another 6 seconds (more promotions) ── | |
| mockTime += 6000; | |
| console.log(`\nTime advanced another +6s (total 12s)\n`); | |
| console.log("Phase 3 – Further aging:"); | |
| while (!pq.isEmpty()) { | |
| const e = pq.dequeue(); | |
| const ageSec = Math.round((mockTime - e.timestamp) / 1000); | |
| const prom = e.promoted ? ` (promoted ×${e.promoted})` : ''; | |
| console.log(` ${count}. ${e.type[0].toUpperCase()} ${e.data} (age: ${ageSec}s${prom})`); | |
| count++; | |
| } | |
| console.log(`\nFinal queue size: ${pq.size()}`); | |
| // Restore real time | |
| Date.now = originalNow; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment