In this article, we review rageDetectors
in Codebuff. We will look at:
What is
rageDetectors
used for?rageDetectors
definition.
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)