Commit f050b10
feat(cubestore): add stale-while-revalidate timeout for SQL query cache (cube-js#10822)
* feat(cubestore): add stale-while-revalidate timeout for SQL query cache
Add CUBESTORE_QUERY_CACHE_STALE_WHILE_REVALIDATE env config param that
enables stale-while-revalidate behavior for CubeStore's SQL result cache.
When enabled (set to a number of seconds, e.g. 30), the cache maintains
a secondary lookup keyed only by SQL query text + inline tables (ignoring
partition/chunk IDs). If a query arrives and the exact cache key (which
includes current partition/chunk snapshot) misses, but a stale entry
exists and was created within the configured timeout, the stale result is
served immediately while a background task refreshes the cache with fresh
data.
This is disabled by default (0 = disabled). The feature reduces query
latency during compaction or partition changes when the underlying data
hasn't materially changed.
Changes:
- config/mod.rs: Add query_cache_stale_while_revalidate_secs to ConfigObj
trait and ConfigObjImpl, parsed from CUBESTORE_QUERY_CACHE_STALE_WHILE_REVALIDATE
- sql/cache.rs: Add stale_cache (Moka cache keyed by SqlQueueCacheKey),
stale-while-revalidate lookup in get(), background refresh via tokio::spawn
- app_metrics.rs: Add DATA_QUERIES_CACHE_STALE_HIT counter metric
- Unit test for stale-while-revalidate behavior
Co-authored-by: Pavel Tiunov <pavel.tiunov@gmail.com>
* refactor(cubestore): use queue cache for background stale-while-revalidate refresh
The background refresh spawned by stale-while-revalidate now integrates
with the queue cache dedup mechanism:
- Extract try_register_background() which atomically checks if a query is
already in flight in the queue cache and registers a new entry if not.
- On stale hit, try_register_background() is called first. If another
execution is already in flight (from a previous stale hit or a
concurrent foreground request), we skip spawning entirely.
- The background spawn registers a watch::Sender in the queue cache, so
any concurrent foreground get() for the same SQL that doesn't hit the
stale cache will join as a waiter instead of starting a duplicate
execution.
- Queue cache entry cleanup happens lazily: sender is dropped when the
background task completes, closing the channel. The next get() for that
key detects the closed channel via has_changed().is_err() and pops it.
Co-authored-by: Pavel Tiunov <pavel.tiunov@gmail.com>
* refactor(cubestore): reuse queue cache flow for background stale-while-revalidate
Extract get_inner() with is_background_refresh flag from get(). The
background spawn now calls get_inner(true) which skips the stale cache
check but reuses the entire queue cache dedup flow — no separate
implementation for the background path.
- get() is a thin wrapper: delegates to get_inner(false)
- get_inner(is_background_refresh=true) skips stale check, goes
straight to queue cache logic for natural dedup
- get() now takes self: &Arc<Self> so the spawn can clone the Arc
- get_inner() takes self: Arc<Self> and returns Pin<Box<dyn Future>>
to satisfy Send + 'static bounds for tokio::spawn
- Removed try_register_background() and all duplicated cache update
logic from previous approach
Co-authored-by: Pavel Tiunov <pavel.tiunov@gmail.com>
* fix(cubestore): fix stale-while-revalidate test to simulate partition change
The test now invalidates the exact result cache before the second get()
call to simulate a partition/chunk change that would make the exact cache
key miss while the stale entry (keyed by SQL only) still matches.
Co-authored-by: Pavel Tiunov <pavel.tiunov@gmail.com>
* fix(cubestore): address review feedback on stale-while-revalidate cache
- Add weigher to stale_cache so max_capacity is in bytes, not entry count
- Fix clippy: use Duration::from_secs as method reference instead of closure
- Add test: background refresh failure preserves stale entry for next request
- Add test: stale timeout expiry falls through to fresh execution
Co-authored-by: Pavel Tiunov <pavel.tiunov@gmail.com>
* feat(cubestore): add size/weight metrics for stale cache
Add cs.sql.query.data.cache.stale.size and cs.sql.query.data.cache.stale.weight
gauge metrics mirroring the existing result cache metrics. Reported alongside
result cache metrics on cache mutations and zeroed on drop.
Co-authored-by: Pavel Tiunov <pavel.tiunov@gmail.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>1 parent 9bdafd8 commit f050b10
5 files changed
Lines changed: 439 additions & 66 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| 16 | + | |
| 17 | + | |
16 | 18 | | |
17 | 19 | | |
18 | 20 | | |
19 | 21 | | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
20 | 26 | | |
21 | 27 | | |
22 | 28 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
510 | 510 | | |
511 | 511 | | |
512 | 512 | | |
| 513 | + | |
| 514 | + | |
513 | 515 | | |
514 | 516 | | |
515 | 517 | | |
| |||
643 | 645 | | |
644 | 646 | | |
645 | 647 | | |
| 648 | + | |
646 | 649 | | |
647 | 650 | | |
648 | 651 | | |
| |||
956 | 959 | | |
957 | 960 | | |
958 | 961 | | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
959 | 965 | | |
960 | 966 | | |
961 | 967 | | |
| |||
1233 | 1239 | | |
1234 | 1240 | | |
1235 | 1241 | | |
| 1242 | + | |
| 1243 | + | |
1236 | 1244 | | |
1237 | 1245 | | |
1238 | 1246 | | |
| |||
1528 | 1536 | | |
1529 | 1537 | | |
1530 | 1538 | | |
| 1539 | + | |
| 1540 | + | |
| 1541 | + | |
| 1542 | + | |
| 1543 | + | |
| 1544 | + | |
| 1545 | + | |
1531 | 1546 | | |
1532 | 1547 | | |
1533 | 1548 | | |
| |||
1740 | 1755 | | |
1741 | 1756 | | |
1742 | 1757 | | |
| 1758 | + | |
1743 | 1759 | | |
1744 | 1760 | | |
1745 | 1761 | | |
| |||
2393 | 2409 | | |
2394 | 2410 | | |
2395 | 2411 | | |
| 2412 | + | |
2396 | 2413 | | |
2397 | 2414 | | |
2398 | 2415 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1063 | 1063 | | |
1064 | 1064 | | |
1065 | 1065 | | |
1066 | | - | |
| 1066 | + | |
1067 | 1067 | | |
1068 | 1068 | | |
1069 | 1069 | | |
| |||
0 commit comments