๐ cacheSelf() Demo - Component Caching
This page demonstrates the new component $cache.cacheSelf() functionality!
This entire page is cached for 1 minute with a 10 second busy lock.
How It Works
At the top of this page (in <%%init>):
<%%init>
// Cache this entire page for 1 minute with busy lock
if (await $cache.cacheSelf({
expiresIn: '1 minute',
busyLock: '10 sec'
})) {
return; // Cached version served, skip rest of execution
}
// This code only runs on cache miss
const generatedAt = new Date().toISOString();
</init%%>
Current Page State
Page Generated At: 2025-12-26T12:33:14.460Z
Random Number: 0.772625888040491
Current Request Time: 2025-12-26T12:33:14.462Z
๐งช Try This:
- Refresh this page multiple times within 1 minute
- Notice that "Page Generated At" and "Random Number" don't change
- But "Current Request Time" always shows the cached value
- Wait 1 minute and refresh again
- Now the values change (cache expired!)
Key Features
Human-Readable TTL
Use natural time expressions: '1 minute', '3 hours', '30 sec', '7 days'
Busy Lock
Prevents thundering herd - only one request regenerates expired cache
Custom Keys
Default: request URI. Or specify custom key for fine-grained control
URI-Based for Dhandlers
Dhandlers cache by request URI, not file path - solves dhandler caching!
More Examples
Example 1: Default Caching (URI-based)
<%%init>
// Cache for 3 hours, automatic key based on URI
if (await $cache.cacheSelf({ expiresIn: '3 hours' })) {
return;
}
</init%%>
Example 2: Custom Key
<%%init>
// Cache with custom key (useful for user-specific caching)
if (await $cache.cacheSelf({
key: `user-dashboard:${$session.userId}`,
expiresIn: '30 minutes',
busyLock: '10 sec'
})) {
return;
}
</init%%>
Example 3: Dhandler with Per-URL Caching
// In /demo/css/dhandler
<%%init>
// Each CSS file cached separately!
// /demo/css/abc123.css โ key: '/demo/css/abc123.css'
// /demo/css/xyz789.css โ key: '/demo/css/xyz789.css'
if (await $cache.cacheSelf({
expiresIn: '1 day',
busyLock: '5 sec'
})) {
return;
}
// Generate CSS based on $req.path...
const commitHash = $req.path.split('/').pop().replace('.css', '');
</init%%>
Partial Caching (Already Supported)
You can also cache parts of a page using the existing $cache methods:
<%
// Cache just the expensive database query
const users = await $cache.remember('all-users', '5 minutes', async () => {
return await $db.query('SELECT * FROM users');
});
%>
API Reference
$cache.cacheSelf(options)
| Option | Type | Default | Description |
|---|---|---|---|
key |
string | $req.path |
Custom cache key (optional) |
expiresIn |
string|number | 3600 | TTL in human format or seconds |
busyLock |
string|number | '30 sec' | Busy lock timeout |
Time Format Examples
| Format | Seconds |
|---|---|
| '30 sec' | 30 |
| '1 minute' | 60 |
| '5 minutes' | 300 |
| '1 hour' | 3600 |
| '3 hours' | 10800 |
| '1 day' | 86400 |
| '7 days' | 604800 |
| '1 week' | 604800 |
โ Benefits
- Performance: Expensive operations run once, results cached
- Scalability: Busy lock prevents cache stampede under load
- Flexibility: URI-based keys work perfectly with dhandlers