In this article, we review rageDetectors in Codebuff. We will look at:
What is
rageDetectorsused for?rageDetectorsdefinition.
I study patterns used in an open source project found on Github Trending. For this week, I reviewed Codebuff codebase and wrote this article.
What is rageDetectors used for?
In codebuff/npm-app/src/rage-detectors.ts, you will find the below comment:
/** * Global singleton instance of rage detectors. * This allows rage detection to be used anywhere in the application. */ export const rageDetectors: RageDetectors = createRageDetectors() It tells us that this detection mechanism can be used across the application, but what are these rage detectors? Codebuff classifies the following as rageDetectors:
keyMashingDetector
repeatInputDetector
exitAfterErrorDetector
webSocketHangDetector
startupTimeDetector
exitTimeDetector
You will find these functions are returned by createRageDetectors function.
rageDetectors definition.
The following is definition of rageDetectors:
export function createRageDetectors(): RageDetectors { return { keyMashingDetector: createCountDetector({ reason: 'key_mashing', mode: 'COUNT', threshold: 5, timeWindow: 1000, historyLimit: 20, debounceMs: 5_000, filter: ({ str, key }) => { }, }), repeatInputDetector: createCountDetector({ reason: 'repeat_input', mode: 'COUNT', threshold: 3, timeWindow: 30_000, historyLimit: 10, debounceMs: 10_000, }), exitAfterErrorDetector: createTimeBetweenDetector({ reason: 'exit_after_error', mode: 'TIME_BETWEEN', threshold: 10_000, operator: 'lt', }), webSocketHangDetector: createTimeoutDetector<WebSocketHangDetectorContext>({ reason: 'websocket_persistent_failure', timeoutMs: 60_000, shouldFire: async (context) => { if (!context || !context.getWebsocketState) { return false } // Add a 2-second grace period for reconnection await sleep(2000) // Only fire if the websocket is still not connected. // This prevents firing if the connection is restored right before the timeout. return context.getWebsocketState() !== WebSocket.OPEN }, }), startupTimeDetector: createTimeBetweenDetector({ reason: 'slow_startup', mode: 'TIME_BETWEEN', threshold: 5_000, operator: 'gte', debounceMs: 30_000, }), exitTimeDetector: createTimeBetweenDetector({ reason: 'slow_exit', mode: 'TIME_BETWEEN', threshold: 10_000, operator: 'gte', debounceMs: 30_000, }), } } createCountDetector, createTimeBetweenDetector, createTimeoutDetector are imported as shown below:
import { createCountDetector, createTimeBetweenDetector, createTimeoutDetector, } from './utils/rage-detector' You will find the following declaration in npm-app/src/utils/rage-detector.ts#L49.
// Factory function for COUNT-based detectors export function createCountDetector(options: CountDetectorOptions) { let history: EventRecord[] = [] let debounceTimer: NodeJS.Timeout | null = null const recordEvent = (value?: any) => { } const checkForRage = () => { } const fireEvent = (events: EventRecord[]) => { } return { recordEvent } } // Factory function for TIME_BETWEEN-based detectors export function createTimeBetweenDetector(options: TimeBetweenDetectorOptions) { let startEvent: EventRecord | null = null let coolDownTimer: NodeJS.Timeout | null = null const start = () => { startEvent = { timestamp: Date.now(), value: null } } const end = () => { } const fireEvent = (duration: number) => { } return { start, end } } // Factory function for TIMEOUT-based detectors export function createTimeoutDetector< TContext extends Record<string, any> = Record<string, any>, >(options: { reason: string timeoutMs: number onHang?: () => void context?: TContext shouldFire?: (context?: TContext) => boolean | Promise<boolean> }) { let timeoutHandle: NodeJS.Timeout | null = null const start = (context?: TContext) => { } const stop = () => { } return { start, stop } } About me:
Hey, my name is Ramu Narasinga. I study codebase architecture in large open-source projects.
Email: ramu.narasinga@gmail.com
Want to learn from open-source? Solve challenges inspired by open-source projects.

Top comments (0)