Events
RunCache provides a comprehensive event system that allows you to monitor and respond to various cache lifecycle events. This page provides a complete reference for all event types, event objects, and event handling methods.
Event Types
RunCache defines several event types in the EVENT
enum:
enum EVENT {
EXPIRE = 'expire',
REFETCH = 'refetch',
REFETCH_FAILURE = 'refetch_failure',
TAG_INVALIDATION = 'tag_invalidation',
DEPENDENCY_INVALIDATION = 'dependency_invalidation'
}
Import the enum from the RunCache package:
import { RunCache, EVENT } from 'run-cache';
Event Objects
Each event type has a corresponding event object with specific properties:
ExpiryEvent
Triggered when a cache entry expires.
interface ExpiryEvent {
key: string; // The key of the expired entry
ttl: number; // The TTL value in milliseconds
updatedAt: number; // Timestamp when the entry was last updated
metadata?: any; // Optional custom metadata associated with the entry
}
RefetchEvent
Triggered when a cache entry is refreshed.
interface RefetchEvent {
key: string; // The key of the refreshed entry
metadata?: any; // Optional custom metadata associated with the entry
}
RefetchFailureEvent
Triggered when a cache refresh operation fails.
interface RefetchFailureEvent {
key: string; // The key of the entry that failed to refresh
error: Error; // The error that occurred during refresh
metadata?: any; // Optional custom metadata associated with the entry
}
TagInvalidationEvent
Triggered when a cache entry is invalidated by tag.
interface TagInvalidationEvent {
key: string; // The key of the invalidated entry
tag: string; // The tag that caused the invalidation
metadata?: any; // Optional custom metadata associated with the entry
}
DependencyInvalidationEvent
Triggered when a cache entry is invalidated due to a dependency.
interface DependencyInvalidationEvent {
key: string; // The key of the invalidated entry
dependencyKey: string; // The key of the dependency that caused the invalidation
metadata?: any; // Optional custom metadata associated with the entry
}
Global Event Listeners
Global event listeners are triggered for all cache entries that match the specified event type.
onExpiry
Registers a callback for all expiry events.
RunCache.onExpiry(callback: (event: ExpiryEvent) => void): void
Parameters:
callback
: Function to call when any entry expires
Example:
RunCache.onExpiry((event) => {
console.log(`Cache key ${event.key} expired at ${new Date(event.updatedAt + event.ttl).toISOString()}`);
});
onRefetch
Registers a callback for all refetch events.
RunCache.onRefetch(callback: (event: RefetchEvent) => void): void
Parameters:
callback
: Function to call when any entry is refreshed
Example:
RunCache.onRefetch((event) => {
console.log(`Cache key ${event.key} was refreshed at ${new Date().toISOString()}`);
});
onRefetchFailure
Registers a callback for all refetch failure events.
RunCache.onRefetchFailure(callback: (event: RefetchFailureEvent) => void): void
Parameters:
callback
: Function to call when any refresh fails
Example:
RunCache.onRefetchFailure((event) => {
console.error(`Failed to refresh cache key ${event.key}:`, event.error.message);
});
onTagInvalidation
Registers a callback for all tag invalidation events.
RunCache.onTagInvalidation(callback: (event: TagInvalidationEvent) => void): void
Parameters:
callback
: Function to call when any entry is invalidated by tag
Example:
RunCache.onTagInvalidation((event) => {
console.log(`Cache key ${event.key} was invalidated by tag: ${event.tag}`);
});
onDependencyInvalidation
Registers a callback for all dependency invalidation events.
RunCache.onDependencyInvalidation(callback: (event: DependencyInvalidationEvent) => void): void
Parameters:
callback
: Function to call when any entry is invalidated by dependency
Example:
RunCache.onDependencyInvalidation((event) => {
console.log(`Cache key ${event.key} was invalidated due to dependency on: ${event.dependencyKey}`);
});
Key-Specific Event Listeners
Key-specific event listeners are triggered only for cache entries with keys that match the specified key or pattern.
onKeyExpiry
Registers a callback for expiry events for a specific key or pattern.
RunCache.onKeyExpiry(key: string, callback: (event: ExpiryEvent) => void): void
Parameters:
key
: The key or pattern to watchcallback
: Function to call when matching entries expire
Example:
// Specific key
RunCache.onKeyExpiry("api-data", (event) => {
console.log(`API data cache expired`);
});
// Pattern matching
RunCache.onKeyExpiry("user:*:profile", (event) => {
console.log(`User profile ${event.key} expired`);
});
onKeyRefetch
Registers a callback for refetch events for a specific key or pattern.
RunCache.onKeyRefetch(key: string, callback: (event: RefetchEvent) => void): void
Parameters:
key
: The key or pattern to watchcallback
: Function to call when matching entries are refreshed
Example:
// Specific key
RunCache.onKeyRefetch("weather-data", (event) => {
console.log(`Weather data was refreshed`);
});
// Pattern matching
RunCache.onKeyRefetch("api:*:data", (event) => {
console.log(`API data ${event.key} was refreshed`);
});
onKeyRefetchFailure
Registers a callback for refetch failure events for a specific key or pattern.
RunCache.onKeyRefetchFailure(key: string, callback: (event: RefetchFailureEvent) => void): void
Parameters:
key
: The key or pattern to watchcallback
: Function to call when matching refreshes fail
Example:
// Specific key
RunCache.onKeyRefetchFailure("api-data", (event) => {
console.error(`API data refresh failed:`, event.error.message);
});
// Pattern matching
RunCache.onKeyRefetchFailure("api:*", (event) => {
console.error(`API data ${event.key} refresh failed:`, event.error.message);
});
onKeyTagInvalidation
Registers a callback for tag invalidation events for a specific key or pattern.
RunCache.onKeyTagInvalidation(key: string, callback: (event: TagInvalidationEvent) => void): void
Parameters:
key
: The key or pattern to watchcallback
: Function to call when matching entries are invalidated by tag
Example:
// Specific key
RunCache.onKeyTagInvalidation("user:1:profile", (event) => {
console.log(`User profile was invalidated by tag: ${event.tag}`);
});
// Pattern matching
RunCache.onKeyTagInvalidation("user:*:profile", (event) => {
console.log(`User profile ${event.key} was invalidated by tag: ${event.tag}`);
});
onKeyDependencyInvalidation
Registers a callback for dependency invalidation events for a specific key or pattern.
RunCache.onKeyDependencyInvalidation(key: string, callback: (event: DependencyInvalidationEvent) => void): void
Parameters:
key
: The key or pattern to watchcallback
: Function to call when matching entries are invalidated by dependency
Example:
// Specific key
RunCache.onKeyDependencyInvalidation("dashboard:main", (event) => {
console.log(`Main dashboard was invalidated due to dependency on: ${event.dependencyKey}`);
});
// Pattern matching
RunCache.onKeyDependencyInvalidation("dashboard:*", (event) => {
console.log(`Dashboard ${event.key} was invalidated due to dependency on: ${event.dependencyKey}`);
});
Managing Event Listeners
clearEventListeners
Removes event listeners based on the specified options.
RunCache.clearEventListeners(options?: {
event?: EVENT;
key?: string;
handler?: Function;
}): void
Parameters:
options?
: Options to specify which listeners to removeevent?
: The event type to remove listeners forkey?
: The key or pattern to remove listeners forhandler?
: The specific handler function to remove
Examples:
// Remove all event listeners
RunCache.clearEventListeners();
// Remove all expiry event listeners
RunCache.clearEventListeners({
event: EVENT.EXPIRE
});
// Remove all listeners for a specific key
RunCache.clearEventListeners({
key: "api-data"
});
// Remove specific event listeners for a key
RunCache.clearEventListeners({
event: EVENT.REFETCH,
key: "api-data"
});
// Remove a specific handler
const handler = (event) => console.log(event);
RunCache.onExpiry(handler);
// Later:
RunCache.clearEventListeners({
event: EVENT.EXPIRE,
handler: handler
});
Event Metadata
You can attach custom metadata to cache entries, which will be included in event objects:
// Set cache entry with metadata
await RunCache.set({
key: 'api-data',
value: JSON.stringify({ results: [...] }),
metadata: {
source: 'external-api',
version: '1.0',
timestamp: Date.now()
}
});
// Access metadata in event handlers
RunCache.onKeyExpiry('api-data', (event) => {
console.log(`API data expired. Source: ${event.metadata.source}, Version: ${event.metadata.version}`);
});
Practical Event System Use Cases
1. Logging and Monitoring
// Set up logging for all major events
RunCache.onExpiry((event) => {
logger.info(`Cache expired: ${event.key}`);
});
RunCache.onRefetch((event) => {
logger.info(`Cache refreshed: ${event.key}`);
});
RunCache.onRefetchFailure((event) => {
logger.error(`Cache refresh failed: ${event.key}`, event.error);
});
RunCache.onTagInvalidation((event) => {
logger.info(`Cache invalidated by tag: ${event.key} (tag: ${event.tag})`);
});
RunCache.onDependencyInvalidation((event) => {
logger.info(`Cache invalidated by dependency: ${event.key} (depends on: ${event.dependencyKey})`);
});
2. Implementing Retry Logic
// Set up retry logic with exponential backoff
RunCache.onRefetchFailure((event) => {
const retryCount = (event.metadata?.retryCount || 0) + 1;
if (retryCount <= 3) {
const delay = Math.pow(2, retryCount) * 1000; // Exponential backoff
console.log(`Retrying ${event.key} in ${delay}ms (attempt ${retryCount})`);
setTimeout(() => {
RunCache.refetch(event.key, {
metadata: { retryCount }
});
}, delay);
} else {
console.error(`Failed to refresh ${event.key} after ${retryCount} attempts`);
}
});
3. UI Updates
// React component example
function UserProfile({ userId }) {
const [profile, setProfile] = useState(null);
useEffect(() => {
// Set up event listener for cache refreshes
RunCache.onKeyRefetch(`user:${userId}:profile`, () => {
// Update UI when profile is refreshed
RunCache.get(`user:${userId}:profile`)
.then(data => data && setProfile(JSON.parse(data)));
});
// Initial data fetch
RunCache.get(`user:${userId}:profile`)
.then(data => data && setProfile(JSON.parse(data)));
// Clean up listener on unmount
return () => {
RunCache.clearEventListeners({
event: EVENT.REFETCH,
key: `user:${userId}:profile`
});
};
}, [userId]);
// Render profile...
}
4. Cache Analytics
// Set up analytics tracking
let metrics = {
expiryCount: 0,
refetchCount: 0,
refetchFailureCount: 0,
tagInvalidationCount: 0,
dependencyInvalidationCount: 0
};
RunCache.onExpiry(() => metrics.expiryCount++);
RunCache.onRefetch(() => metrics.refetchCount++);
RunCache.onRefetchFailure(() => metrics.refetchFailureCount++);
RunCache.onTagInvalidation(() => metrics.tagInvalidationCount++);
RunCache.onDependencyInvalidation(() => metrics.dependencyInvalidationCount++);
// Report metrics periodically
setInterval(() => {
console.log('Cache metrics:', metrics);
// Send metrics to monitoring system
sendMetricsToMonitoring(metrics);
// Reset counters
metrics = {
expiryCount: 0,
refetchCount: 0,
refetchFailureCount: 0,
tagInvalidationCount: 0,
dependencyInvalidationCount: 0
};
}, 60000); // Every minute
Best Practices for Event Handling
1. Keep Event Handlers Lightweight
Event handlers should be fast and non-blocking:
// Good - lightweight handler
RunCache.onExpiry((event) => {
console.log(`Cache expired: ${event.key}`);
});
// Avoid - heavy processing in handler
RunCache.onExpiry(async (event) => {
// DON'T do this - blocks the event loop
await heavyProcessing();
await networkRequest();
});
If you need to perform heavy work, delegate it to a separate process or queue.
2. Handle Errors in Event Handlers
Always handle errors in event handlers to prevent unhandled exceptions:
// Good - error handling
RunCache.onRefetch((event) => {
try {
processRefetchEvent(event);
} catch (error) {
console.error('Error in refetch handler:', error);
}
});
3. Use Specific Key Patterns
Use specific key patterns to minimize unnecessary event processing:
// Too broad - triggers for all keys
RunCache.onKeyExpiry('*', (event) => {
// This will run for EVERY expiry
});
// Better - more specific pattern
RunCache.onKeyExpiry('api:*', (event) => {
// This will only run for API-related expirations
});
4. Clean Up Event Listeners
Remove event listeners when they're no longer needed:
// In a component or module initialization
function initializeModule() {
// Set up event listeners
RunCache.onKeyRefetch('module-data', handleRefetch);
// Return cleanup function
return () => {
RunCache.clearEventListeners({
event: EVENT.REFETCH,
key: 'module-data'
});
};
}
// Later, when shutting down
const cleanup = initializeModule();
// When module is unloaded
cleanup();
Next Steps
RunCache API - Learn about the main RunCache API
Storage Adapters - Understand persistent storage options
Types - Explore TypeScript type definitions
Event System - Learn more about using events in your application
Last updated