Skip to content

Commit fa6e2cf

Browse files
committed
CACHING switch
1 parent 86760d4 commit fa6e2cf

4 files changed

Lines changed: 98 additions & 30 deletions

File tree

cache/docs/CACHE_METRICS_REPORT.md

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# RERUM Cache Metrics & Functionality Report
22

3-
**Generated**: Fri Oct 24 16:38:52 CDT 2025
3+
**Generated**: Mon Oct 27 18:50:18 UTC 2025
44
**Test Duration**: Full integration and performance suite
55
**Server**: http://localhost:3001
66

77
---
88

99
## Executive Summary
1010

11-
**Overall Test Results**: 32 passed, 1 failed, 0 skipped (33 total)
11+
**Overall Test Results**: 37 passed, 0 failed, 0 skipped (37 total)
1212

1313
### Cache Performance Summary
1414

@@ -33,7 +33,7 @@
3333
| `/history` | ✅ Functional | Get object version history |
3434
| `/since` | ✅ Functional | Get objects modified since timestamp |
3535
| `/create` | ✅ Functional | Create new objects |
36-
| `/update` | ⚠️ Partial Failures (1/50) | Update existing objects |
36+
| `/update` | ✅ Functional | Update existing objects |
3737
| `/patch` | ✅ Functional | Patch existing object properties |
3838
| `/set` | ✅ Functional | Add new properties to objects |
3939
| `/unset` | ✅ Functional | Remove properties from objects |
@@ -48,12 +48,12 @@
4848

4949
| Endpoint | Cold Cache (DB) | Warm Cache (Memory) | Speedup | Benefit |
5050
|----------|-----------------|---------------------|---------|---------|
51-
| `/query` | 421 | N/A | N/A | N/A |
52-
| `/search` | 341 | N/A | N/A | N/A |
53-
| `/searchPhrase` | 62 | N/A | N/A | N/A |
54-
| `/id` | 502 | N/A | N/A | N/A |
55-
| `/history` | 867 | N/A | N/A | N/A |
56-
| `/since` | 858 | N/A | N/A | N/A |
51+
| `/query` | 348 | N/A | N/A | N/A |
52+
| `/search` | 104 | N/A | N/A | N/A |
53+
| `/searchPhrase` | 25 | N/A | N/A | N/A |
54+
| `/id` | 412 | N/A | N/A | N/A |
55+
| `/history` | 728 | N/A | N/A | N/A |
56+
| `/since` | 873 | N/A | N/A | N/A |
5757

5858
**Interpretation**:
5959
- **Cold Cache**: First request hits database (cache miss)
@@ -69,13 +69,13 @@
6969

7070
| Endpoint | Empty Cache | Full Cache (1000 entries) | Overhead | Impact |
7171
|----------|-------------|---------------------------|----------|--------|
72-
| `/create` | 251ms | 59ms | -192ms |None |
73-
| `/update` | N/A | N/A | N/A | N/A |
74-
| `/patch` | 668ms | 493ms | -175ms |None |
75-
| `/set` | 491ms | 478ms | -13ms | ✅ None |
76-
| `/unset` | 680ms | 498ms | -182ms |None |
77-
| `/delete` | 493ms | 473ms | -20ms | ✅ None |
78-
| `/overwrite` | 490ms | 680ms | +190ms | ⚠️ Moderate |
72+
| `/create` | 23ms | 23ms | +0ms |Negligible |
73+
| `/update` | 421ms | 437ms | +16ms | ⚠️ Moderate |
74+
| `/patch` | 420ms | 424ms | +4ms |Negligible |
75+
| `/set` | 431ms | 424ms | -7ms | ✅ None |
76+
| `/unset` | 423ms | 423ms | +0ms |Negligible |
77+
| `/delete` | 441ms | 460ms | +19ms | ⚠️ Moderate |
78+
| `/overwrite` | 422ms | 421ms | -1ms | ✅ None |
7979

8080
**Interpretation**:
8181
- **Empty Cache**: Write with no cache to invalidate
@@ -97,9 +97,9 @@
9797
- Net benefit on 1000 reads: ~0ms saved (assuming 70% hit rate)
9898

9999
**Cache Costs (Writes)**:
100-
- Average overhead per write: ~-65ms
101-
- Overhead percentage: ~-12%
102-
- Net cost on 1000 writes: ~-65000ms
100+
- Average overhead per write: ~4ms
101+
- Overhead percentage: ~1%
102+
- Net cost on 1000 writes: ~4000ms
103103
- Tested endpoints: create, update, patch, set, unset, delete, overwrite
104104

105105
**Break-Even Analysis**:
@@ -111,17 +111,17 @@ For a workload with:
111111

112112
```
113113
Without Cache:
114-
800 reads × 421ms = 336800ms
115-
200 writes × 251ms = 50200ms
116-
Total: 387000ms
114+
800 reads × 348ms = 278400ms
115+
200 writes × 23ms = 4600ms
116+
Total: 283000ms
117117
118118
With Cache:
119119
560 cached reads × 5ms = 2800ms
120-
240 uncached reads × 421ms = 101040ms
121-
200 writes × 59ms = 11800ms
122-
Total: 115640ms
120+
240 uncached reads × 348ms = 83520ms
121+
200 writes × 23ms = 4600ms
122+
Total: 90920ms
123123
124-
Net Improvement: 271360ms faster (~71% improvement)
124+
Net Improvement: 192080ms faster (~68% improvement)
125125
```
126126

127127
---
@@ -132,8 +132,8 @@ Net Improvement: 271360ms faster (~71% improvement)
132132

133133
The cache layer provides:
134134
1. **Significant read performance improvements** (0ms average speedup)
135-
2. **Minimal write overhead** (-65ms average, ~-12% of write time)
136-
3. **All endpoints functioning correctly** (32 passed tests)
135+
2. **Minimal write overhead** (4ms average, ~1% of write time)
136+
3. **All endpoints functioning correctly** (37 passed tests)
137137

138138
### 📊 Monitoring Recommendations
139139

@@ -164,7 +164,7 @@ Consider tuning based on:
164164
- Server: http://localhost:3001
165165
- Test Framework: Bash + curl
166166
- Metrics Collection: Millisecond-precision timing
167-
- Test Objects Created: 201
167+
- Test Objects Created: 202
168168
- All test objects cleaned up: ✅
169169

170170
**Test Coverage**:
@@ -176,6 +176,6 @@ Consider tuning based on:
176176

177177
---
178178

179-
**Report Generated**: Fri Oct 24 16:38:52 CDT 2025
179+
**Report Generated**: Mon Oct 27 18:50:18 UTC 2025
180180
**Format Version**: 1.0
181181
**Test Suite**: cache-metrics.sh

cache/docs/DETAILED.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ These are typically pre-installed on Linux/macOS systems. If missing, install vi
3939
## Cache Configuration
4040

4141
### Default Settings
42+
- **Enabled by default**: Set `CACHING=false` to disable
4243
- **Max Length**: 1000 entries
4344
- **Max Bytes**: 1GB (1,000,000,000 bytes)
4445
- **TTL (Time-To-Live)**: 5 minutes (300,000ms)
@@ -47,11 +48,23 @@ These are typically pre-installed on Linux/macOS systems. If missing, install vi
4748

4849
### Environment Variables
4950
```bash
51+
CACHING=true # Enable/disable caching layer (true/false)
5052
CACHE_MAX_LENGTH=1000 # Maximum number of cached entries
5153
CACHE_MAX_BYTES=1000000000 # Maximum memory usage in bytes
5254
CACHE_TTL=300000 # Time-to-live in milliseconds
5355
```
5456

57+
### Enabling/Disabling Cache
58+
59+
**To disable caching completely**, set `CACHING=false` in your `.env` file:
60+
- All cache middleware will be bypassed
61+
- No cache lookups, storage, or invalidation
62+
- No `X-Cache` headers in responses
63+
- No overhead from cache operations
64+
- Useful for debugging or performance comparison
65+
66+
**To enable caching** (default), set `CACHING=true` or leave it unset.
67+
5568
### Limit Enforcement Details
5669

5770
The cache implements **dual limits** for defense-in-depth:

cache/docs/SHORT.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,22 @@ Immediately clears all cached entries (useful for testing or troubleshooting).
9292
## Configuration
9393

9494
Cache behavior can be adjusted via environment variables:
95+
- `CACHING` - Enable/disable caching layer (default: `true`, set to `false` to disable)
9596
- `CACHE_MAX_LENGTH` - Maximum entries (default: 1000)
9697
- `CACHE_MAX_BYTES` - Maximum memory usage (default: 1GB)
9798
- `CACHE_TTL` - Time-to-live in milliseconds (default: 300000 = 5 minutes)
9899

99100
**Note**: Limits are well-balanced for typical usage. With standard RERUM queries (100 items per page), 1000 cached entries use only ~26 MB (~2.7% of the 1GB byte limit). The byte limit serves as a safety net for edge cases.
100101

102+
### Disabling Cache
103+
104+
To disable caching completely, set `CACHING=false` in your `.env` file. This will:
105+
- Skip all cache lookups (no cache hits)
106+
- Skip cache storage (no cache writes)
107+
- Skip cache invalidation (no overhead on writes)
108+
- Remove `X-Cache` headers from responses
109+
- Useful for debugging or when caching is not desired
110+
101111
## Backwards Compatibility
102112

103113
**Fully backwards compatible**

cache/middleware.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ import cache from './index.js'
1313
* Caches results based on query parameters, limit, and skip
1414
*/
1515
const cacheQuery = (req, res, next) => {
16+
// Skip caching if disabled
17+
if (process.env.CACHING !== 'true') {
18+
return next()
19+
}
20+
1621
// Only cache POST requests with body
1722
if (req.method !== 'POST' || !req.body) {
1823
return next()
@@ -61,6 +66,11 @@ const cacheQuery = (req, res, next) => {
6166
* Caches results based on search text and options
6267
*/
6368
const cacheSearch = (req, res, next) => {
69+
// Skip caching if disabled
70+
if (process.env.CACHING !== 'true') {
71+
return next()
72+
}
73+
6474
if (req.method !== 'POST' || !req.body) {
6575
return next()
6676
}
@@ -105,6 +115,11 @@ const cacheSearch = (req, res, next) => {
105115
* Caches results based on search phrase and options
106116
*/
107117
const cacheSearchPhrase = (req, res, next) => {
118+
// Skip caching if disabled
119+
if (process.env.CACHING !== 'true') {
120+
return next()
121+
}
122+
108123
if (req.method !== 'POST' || !req.body) {
109124
return next()
110125
}
@@ -149,6 +164,11 @@ const cacheSearchPhrase = (req, res, next) => {
149164
* Caches individual object lookups by ID
150165
*/
151166
const cacheId = (req, res, next) => {
167+
// Skip caching if disabled
168+
if (process.env.CACHING !== 'true') {
169+
return next()
170+
}
171+
152172
if (req.method !== 'GET') {
153173
return next()
154174
}
@@ -189,6 +209,11 @@ const cacheId = (req, res, next) => {
189209
* Caches version history lookups by ID
190210
*/
191211
const cacheHistory = (req, res, next) => {
212+
// Skip caching if disabled
213+
if (process.env.CACHING !== 'true') {
214+
return next()
215+
}
216+
192217
if (req.method !== 'GET') {
193218
return next()
194219
}
@@ -228,6 +253,11 @@ const cacheHistory = (req, res, next) => {
228253
* Caches descendant version lookups by ID
229254
*/
230255
const cacheSince = (req, res, next) => {
256+
// Skip caching if disabled
257+
if (process.env.CACHING !== 'true') {
258+
return next()
259+
}
260+
231261
if (req.method !== 'GET') {
232262
return next()
233263
}
@@ -267,6 +297,11 @@ const cacheSince = (req, res, next) => {
267297
* Invalidates cache entries when objects are created, updated, or deleted
268298
*/
269299
const invalidateCache = (req, res, next) => {
300+
// Skip cache invalidation if caching is disabled
301+
if (process.env.CACHING !== 'true') {
302+
return next()
303+
}
304+
270305
// Store original response methods
271306
const originalJson = res.json.bind(res)
272307
const originalSend = res.send.bind(res)
@@ -457,6 +492,11 @@ const cacheClear = (req, res) => {
457492
* Cache key includes ManuscriptWitness URI and pagination parameters
458493
*/
459494
const cacheGogFragments = (req, res, next) => {
495+
// Skip caching if disabled
496+
if (process.env.CACHING !== 'true') {
497+
return next()
498+
}
499+
460500
// Only cache if request has valid body with ManuscriptWitness
461501
const manID = req.body?.["ManuscriptWitness"]
462502
if (!manID || !manID.startsWith("http")) {
@@ -499,6 +539,11 @@ const cacheGogFragments = (req, res, next) => {
499539
* Cache key includes ManuscriptWitness URI and pagination parameters
500540
*/
501541
const cacheGogGlosses = (req, res, next) => {
542+
// Skip caching if disabled
543+
if (process.env.CACHING !== 'true') {
544+
return next()
545+
}
546+
502547
// Only cache if request has valid body with ManuscriptWitness
503548
const manID = req.body?.["ManuscriptWitness"]
504549
if (!manID || !manID.startsWith("http")) {

0 commit comments

Comments
 (0)