fix(#338): Log ERROR on rate limiter fallback and track degraded mode
- Log at ERROR level when falling back to in-memory storage - Track and expose degraded mode status for health checks - Add isUsingFallback() method to check fallback state - Add getHealthStatus() method for health check endpoints - Add comprehensive tests for fallback behavior and health status Refs #338 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -53,8 +53,11 @@ export class ThrottlerValkeyStorageService implements ThrottlerStorage, OnModule
|
||||
this.logger.log("Valkey connected successfully for rate limiting");
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
this.logger.warn(`Failed to connect to Valkey for rate limiting: ${errorMessage}`);
|
||||
this.logger.warn("Falling back to in-memory rate limiting storage");
|
||||
this.logger.error(`Failed to connect to Valkey for rate limiting: ${errorMessage}`);
|
||||
this.logger.error(
|
||||
"DEGRADED MODE: Falling back to in-memory rate limiting storage. " +
|
||||
"Rate limits will not be shared across API instances."
|
||||
);
|
||||
this.useRedis = false;
|
||||
this.client = undefined;
|
||||
}
|
||||
@@ -168,6 +171,46 @@ export class ThrottlerValkeyStorageService implements ThrottlerStorage, OnModule
|
||||
return `${this.THROTTLER_PREFIX}${key}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the service is using fallback in-memory storage
|
||||
*
|
||||
* This indicates a degraded state where rate limits are not shared
|
||||
* across API instances. Use this for health checks.
|
||||
*
|
||||
* @returns true if using in-memory fallback, false if using Redis
|
||||
*/
|
||||
isUsingFallback(): boolean {
|
||||
return !this.useRedis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get rate limiter health status for health check endpoints
|
||||
*
|
||||
* @returns Health status object with storage mode and details
|
||||
*/
|
||||
getHealthStatus(): {
|
||||
healthy: boolean;
|
||||
mode: "redis" | "memory";
|
||||
degraded: boolean;
|
||||
message: string;
|
||||
} {
|
||||
if (this.useRedis) {
|
||||
return {
|
||||
healthy: true,
|
||||
mode: "redis",
|
||||
degraded: false,
|
||||
message: "Rate limiter using Redis storage (distributed mode)",
|
||||
};
|
||||
}
|
||||
return {
|
||||
healthy: true, // Service is functional, but degraded
|
||||
mode: "memory",
|
||||
degraded: true,
|
||||
message:
|
||||
"Rate limiter using in-memory fallback (degraded mode - limits not shared across instances)",
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up on module destroy
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user