CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-hapi--hapi

HTTP Server framework for Node.js with built-in authentication, validation, caching, logging, and plugin architecture

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

caching.mddocs/

Caching

Built-in caching system with support for multiple backends and policies for server methods and general purpose caching in @hapi/hapi.

Capabilities

Cache Policy Creation

Create cache policies for storing and retrieving data with configurable expiration and backend storage.

/**
 * Create a cache policy
 * @param options - Cache policy configuration
 * @returns Cache policy instance
 */
cache(options: CachePolicyOptions): CachePolicy;

interface CachePolicyOptions {
    /** Cache segment name */
    segment?: string;
    /** Cache partition name */
    partition?: string;
    /** Shared cache policy name */
    policy?: string;
    /** Cache expiration in milliseconds */
    expiresIn?: number;
    /** Cache expiration at specific time */
    expiresAt?: string;
    /** Stale cache usage time in milliseconds */
    staleIn?: number;
    /** Stale cache timeout in milliseconds */
    staleTimeout?: number;
    /** Generate cache key function */
    generateFunc?: Function;
    /** Generate cache timeout in milliseconds */
    generateTimeout?: number;
    /** Drop on generate error */
    dropOnError?: boolean;
    /** Pending generate timeout in milliseconds */
    pendingGenerateTimeout?: number;
    /** Cache provider */
    cache?: string;
}

interface CachePolicy {
    /** Get value from cache */
    get(key: string): Promise<CacheResult>;
    /** Set value in cache */
    set(key: string, value: any, ttl?: number): Promise<void>;
    /** Remove value from cache */
    drop(key: string): Promise<void>;
    /** Check if key exists in cache */
    isReady(): boolean;
    /** Cache statistics */
    stats: CacheStats;
}

Usage Examples:

const server = Hapi.server({ port: 3000 });

// Create basic cache policy
const cache = server.cache({
    segment: 'user-cache',
    expiresIn: 60 * 1000 // 1 minute
});

// Use cache in route handler
server.route({
    method: 'GET',
    path: '/users/{id}',
    handler: async (request, h) => {
        const userId = request.params.id;
        const cacheKey = `user-${userId}`;
        
        // Try to get from cache first
        const cached = await cache.get(cacheKey);
        if (cached) {
            return cached.item;
        }
        
        // Fetch from database
        const user = await database.getUser(userId);
        
        // Store in cache
        await cache.set(cacheKey, user);
        
        return user;
    }
});

// Cache with custom key generation
const sessionCache = server.cache({
    segment: 'sessions',
    expiresIn: 30 * 60 * 1000, // 30 minutes
    generateFunc: async (id) => {
        return await database.getSession(id);
    },
    generateTimeout: 5000
});

Server Method Caching

Cache server methods with automatic key generation and cache invalidation.

/**
 * Register server method with caching
 * @param name - Method name or method configuration
 * @param method - Method function (if name is string)
 * @param options - Method options including caching
 */
method(name: string | MethodObject, method?: Function, options?: MethodOptions): void;

interface MethodOptions {
    /** Context binding */
    bind?: object;
    /** Caching configuration */
    cache?: MethodCacheOptions;
    /** Generate key function */
    generateKey?: Function;
}

interface MethodCacheOptions {
    /** Cache expiration in milliseconds */
    expiresIn?: number;
    /** Cache expiration at specific time */
    expiresAt?: string;
    /** Stale cache usage time */
    staleIn?: number;
    /** Stale timeout */
    staleTimeout?: number;
    /** Generate function timeout */
    generateTimeout?: number;
    /** Generate on error flag */
    generateOnError?: boolean;
    /** Pending generate timeout */
    pendingGenerateTimeout?: number;
    /** Cache segment */
    segment?: string;
    /** Cache partition */
    partition?: string;
}

Usage Examples:

// Server method with caching
server.method('getUser', async (id) => {
    console.log('Fetching user from database:', id);
    return await database.getUser(id);
}, {
    cache: {
        expiresIn: 60 * 1000, // 1 minute
        generateTimeout: 5000
    },
    generateKey: (id) => `user:${id}`
});

// Use cached server method
server.route({
    method: 'GET',
    path: '/users/{id}',
    handler: async (request, h) => {
        // This will use cache automatically
        const user = await server.methods.getUser(request.params.id);
        return user;
    }
});

// Server method with complex caching
server.method('getPopularPosts', async (category, limit) => {
    return await database.getPopularPosts(category, limit);
}, {
    cache: {
        expiresIn: 10 * 60 * 1000, // 10 minutes
        staleIn: 5 * 60 * 1000,    // Allow stale for 5 minutes
        staleTimeout: 1000,         // 1 second stale timeout
        segment: 'popular-posts'
    },
    generateKey: (category, limit) => `popular:${category}:${limit}`
});

Cache Configuration

Configure cache providers and global cache settings.

interface ServerCacheOptions {
    /** Cache provider configuration */
    provider?: CacheProvider | string;
    /** Provider options */
    options?: object;
    /** Cache engine name */
    engine?: string;
    /** Cache partition */
    partition?: string;
    /** Shared cache instances */
    shared?: boolean;
}

interface CacheProvider {
    /** Provider constructor */
    constructor: Function;
    /** Provider options */
    options?: object;
}

Usage Examples:

// Server with Redis cache
const server = Hapi.server({
    port: 3000,
    cache: [
        {
            name: 'redis-cache',
            provider: {
                constructor: require('@hapi/catbox-redis'),
                options: {
                    host: 'localhost',
                    port: 6379,
                    database: 0
                }
            }
        },
        {
            name: 'memory-cache',
            provider: {
                constructor: require('@hapi/catbox-memory'),
                options: {
                    maxByteSize: 100 * 1024 * 1024 // 100MB
                }
            }
        }
    ]
});

// Use specific cache provider
const redisCache = server.cache({
    cache: 'redis-cache',
    segment: 'user-sessions',
    expiresIn: 24 * 60 * 60 * 1000 // 24 hours
});

Cache Result Handling

Handle cache results including stale data and cache misses.

interface CacheResult {
    /** Cached item */
    item: any;
    /** Item stored timestamp */
    stored: number;
    /** Item TTL in milliseconds */
    ttl: number;
    /** Whether item is stale */
    isStale: boolean;
}

Usage Examples:

server.route({
    method: 'GET',
    path: '/data/{id}',
    handler: async (request, h) => {
        const key = `data-${request.params.id}`;
        const result = await cache.get(key);
        
        if (result) {
            const response = h.response(result.item);
            
            // Add cache metadata headers
            response.header('X-Cache', 'HIT');
            response.header('X-Cache-Stored', new Date(result.stored).toISOString());
            response.header('X-Cache-TTL', Math.round(result.ttl / 1000));
            
            if (result.isStale) {
                response.header('X-Cache-Stale', 'true');
                // Refresh cache in background
                refreshDataInBackground(request.params.id, key);
            }
            
            return response;
        }
        
        // Cache miss - fetch and cache
        const data = await fetchData(request.params.id);
        await cache.set(key, data);
        
        return h.response(data).header('X-Cache', 'MISS');
    }
});

Cache Statistics and Monitoring

Monitor cache performance and statistics.

interface CacheStats {
    /** Cache hits */
    hits: number;
    /** Cache misses */
    misses: number;
    /** Cache sets */
    sets: number;
    /** Cache gets */
    gets: number;
    /** Cache errors */
    errors: number;
}

Usage Examples:

// Monitor cache performance
server.route({
    method: 'GET',
    path: '/cache/stats',
    handler: (request, h) => {
        const stats = cache.stats;
        const hitRate = stats.hits / (stats.hits + stats.misses) * 100;
        
        return {
            hits: stats.hits,
            misses: stats.misses,
            hitRate: `${hitRate.toFixed(2)}%`,
            sets: stats.sets,
            gets: stats.gets,
            errors: stats.errors
        };
    }
});

// Reset cache stats
server.route({
    method: 'POST',
    path: '/cache/reset-stats',
    handler: (request, h) => {
        cache.stats.reset();
        return { message: 'Cache stats reset' };
    }
});

Cache Warming and Management

Warm cache and manage cached data programmatically.

Usage Examples:

// Cache warming on server start
server.ext('onPostStart', async () => {
    console.log('Warming cache...');
    
    // Pre-populate frequently accessed data
    const popularUsers = await database.getPopularUsers();
    for (const user of popularUsers) {
        await cache.set(`user-${user.id}`, user);
    }
    
    console.log(`Warmed cache with ${popularUsers.length} users`);
});

// Cache invalidation
server.route({
    method: 'PUT',
    path: '/users/{id}',
    handler: async (request, h) => {
        const userId = request.params.id;
        
        // Update user
        const updatedUser = await database.updateUser(userId, request.payload);
        
        // Invalidate cache
        await cache.drop(`user-${userId}`);
        
        // Optionally warm cache with new data
        await cache.set(`user-${userId}`, updatedUser);
        
        return updatedUser;
    }
});

// Bulk cache operations
server.route({
    method: 'DELETE',
    path: '/cache/users',
    handler: async (request, h) => {
        const userIds = request.payload.userIds;
        
        // Drop multiple cache entries
        const promises = userIds.map(id => cache.drop(`user-${id}`));
        await Promise.all(promises);
        
        return { message: `Invalidated cache for ${userIds.length} users` };
    }
});

Advanced Caching Patterns

Complex caching scenarios and patterns.

Usage Examples:

// Cache with dependency invalidation
const createDependentCache = (server) => {
    const userCache = server.cache({
        segment: 'users',
        expiresIn: 60 * 60 * 1000 // 1 hour
    });
    
    const postCache = server.cache({
        segment: 'posts',
        expiresIn: 30 * 60 * 1000 // 30 minutes
    });
    
    return {
        async invalidateUser(userId) {
            await userCache.drop(`user-${userId}`);
            // Also invalidate user's posts
            const userPosts = await database.getUserPostIds(userId);
            for (const postId of userPosts) {
                await postCache.drop(`post-${postId}`);
            }
        }
    };
};

// Layered caching (L1 memory, L2 Redis)
const createLayeredCache = (server) => {
    const l1Cache = server.cache({
        cache: 'memory-cache',
        segment: 'l1',
        expiresIn: 5 * 60 * 1000 // 5 minutes
    });
    
    const l2Cache = server.cache({
        cache: 'redis-cache',
        segment: 'l2',
        expiresIn: 60 * 60 * 1000 // 1 hour
    });
    
    return {
        async get(key) {
            // Try L1 first
            let result = await l1Cache.get(key);
            if (result) {
                return result.item;
            }
            
            // Try L2
            result = await l2Cache.get(key);
            if (result) {
                // Populate L1
                await l1Cache.set(key, result.item);
                return result.item;
            }
            
            return null;
        },
        
        async set(key, value) {
            await Promise.all([
                l1Cache.set(key, value),
                l2Cache.set(key, value)
            ]);
        }
    };
};

Types

interface CacheProvisionOptions {
    /** Provider name */
    provider: string | CacheProvider;
    /** Provider options */
    options?: object;
}

interface MethodObject {
    /** Method name */
    name: string;
    /** Method function */
    method: Function;
    /** Method options */
    options?: MethodOptions;
}

docs

authentication.md

caching.md

extensions.md

index.md

plugin-system.md

request-processing.md

response-management.md

routing.md

server-management.md

validation.md

tile.json