You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
4.4 KiB
144 lines
4.4 KiB
/**
|
|
* Outbox pressure management with telemetry
|
|
*/
|
|
|
|
import { OutboxPressureConfig, TelemetryMetrics } from './types';
|
|
import { DEFAULT_CONFIG } from './constants';
|
|
|
|
export class OutboxPressureManager {
|
|
private config: OutboxPressureConfig;
|
|
private metrics: TelemetryMetrics;
|
|
|
|
constructor(config: Partial<OutboxPressureConfig> = {}) {
|
|
this.config = {
|
|
maxUndelivered: config.maxUndelivered ?? DEFAULT_CONFIG.maxUndelivered,
|
|
cleanupIntervalMs: config.cleanupIntervalMs ?? DEFAULT_CONFIG.cleanupIntervalMs,
|
|
backpressureThreshold: config.backpressureThreshold ?? DEFAULT_CONFIG.backpressureThreshold,
|
|
evictionPolicy: config.evictionPolicy ?? 'fifo'
|
|
};
|
|
|
|
this.metrics = {
|
|
'starred_projects_outbox_size': 0,
|
|
'starred_projects_outbox_backpressure_active': 0
|
|
} as TelemetryMetrics;
|
|
}
|
|
|
|
async checkStoragePressure(undeliveredCount: number): Promise<boolean> {
|
|
// Update metrics
|
|
this.metrics['starred_projects_outbox_size'] = undeliveredCount;
|
|
|
|
const pressureRatio = undeliveredCount / this.config.maxUndelivered;
|
|
const backpressureActive = pressureRatio >= this.config.backpressureThreshold;
|
|
|
|
// Update backpressure metric
|
|
this.metrics['starred_projects_outbox_backpressure_active'] = backpressureActive ? 1 : 0;
|
|
|
|
if (pressureRatio >= 1.0) {
|
|
// Critical: Drop oldest notifications to make room
|
|
const evictCount = undeliveredCount - this.config.maxUndelivered;
|
|
await this.evictNotifications(evictCount);
|
|
return true; // Backpressure active
|
|
}
|
|
|
|
return backpressureActive;
|
|
}
|
|
|
|
async evictNotifications(count: number): Promise<void> {
|
|
if (count <= 0) return;
|
|
|
|
// Simulate eviction based on policy
|
|
switch (this.config.evictionPolicy) {
|
|
case 'fifo':
|
|
await this.evictFIFO(count);
|
|
break;
|
|
case 'lifo':
|
|
await this.evictLIFO(count);
|
|
break;
|
|
case 'priority':
|
|
await this.evictByPriority(count);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private async evictFIFO(count: number): Promise<void> {
|
|
// Simulate: DELETE FROM notification_outbox
|
|
// WHERE delivered_at IS NULL
|
|
// ORDER BY created_at ASC
|
|
// LIMIT count
|
|
console.log(`Evicting ${count} oldest notifications (FIFO)`);
|
|
}
|
|
|
|
private async evictLIFO(count: number): Promise<void> {
|
|
// Simulate: DELETE FROM notification_outbox
|
|
// WHERE delivered_at IS NULL
|
|
// ORDER BY created_at DESC
|
|
// LIMIT count
|
|
console.log(`Evicting ${count} newest notifications (LIFO)`);
|
|
}
|
|
|
|
private async evictByPriority(count: number): Promise<void> {
|
|
// Simulate: DELETE FROM notification_outbox
|
|
// WHERE delivered_at IS NULL
|
|
// ORDER BY priority ASC, created_at ASC
|
|
// LIMIT count
|
|
console.log(`Evicting ${count} lowest priority notifications`);
|
|
}
|
|
|
|
async cleanupDeliveredNotifications(): Promise<void> {
|
|
// Simulate: DELETE FROM notification_outbox
|
|
// WHERE delivered_at IS NOT NULL
|
|
// AND delivered_at < datetime('now', '-${cleanupIntervalMs / 1000} seconds')
|
|
console.log(`Cleaning up delivered notifications older than ${this.config.cleanupIntervalMs}ms`);
|
|
}
|
|
|
|
getMetrics(): TelemetryMetrics {
|
|
return { ...this.metrics };
|
|
}
|
|
|
|
getConfig(): OutboxPressureConfig {
|
|
return { ...this.config };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create default outbox pressure manager
|
|
*/
|
|
export function createDefaultOutboxPressureManager(): OutboxPressureManager {
|
|
return new OutboxPressureManager();
|
|
}
|
|
|
|
/**
|
|
* Create outbox pressure manager with custom config
|
|
*/
|
|
export function createOutboxPressureManager(config: Partial<OutboxPressureConfig>): OutboxPressureManager {
|
|
return new OutboxPressureManager(config);
|
|
}
|
|
|
|
/**
|
|
* Outbox pressure configuration presets
|
|
*/
|
|
export const OUTBOX_PRESSURE_PRESETS = {
|
|
// Conservative: Low memory usage, frequent cleanup
|
|
conservative: {
|
|
maxUndelivered: 500,
|
|
backpressureThreshold: 0.7,
|
|
cleanupIntervalMs: 1800000, // 30 minutes
|
|
evictionPolicy: 'fifo' as const
|
|
},
|
|
|
|
// Balanced: Good performance, reasonable memory usage
|
|
balanced: {
|
|
maxUndelivered: 1000,
|
|
backpressureThreshold: 0.8,
|
|
cleanupIntervalMs: 3600000, // 1 hour
|
|
evictionPolicy: 'fifo' as const
|
|
},
|
|
|
|
// Aggressive: High throughput, more memory usage
|
|
aggressive: {
|
|
maxUndelivered: 2000,
|
|
backpressureThreshold: 0.9,
|
|
cleanupIntervalMs: 7200000, // 2 hours
|
|
evictionPolicy: 'priority' as const
|
|
}
|
|
} as const;
|
|
|