Repository navigation
Commit 442d6df
authored
fix(common-utils): expire cached table columns after 5 minutes (#3481)
## Summary
`getMetadata()` shares one module-level `MetadataCache`, and `getOrFetch` kept every entry for the life of the process. After an `ALTER TABLE` adds a column, the API keeps rendering queries with the column list from before the change until it restarts. As #3475 shows, a new MATERIALIZED column is not used for a filter on the Map key it covers, and grouping by it fails with `Unknown expression identifier`.
- `MetadataCache.getOrFetch` and `set` take an optional `ttlMs`. `get` drops an entry whose TTL has passed, so the next `getOrFetch` runs the query again. Entries stored without a TTL behave as before.
- `getColumns` stores its `DESCRIBE` result with a 5 minute TTL (`COLUMNS_CACHE_TTL_MS`). `getColumn`, `getMaterializedColumnsLookupTable` and the computed metric column lookup from #3191 all read `getColumns`, so they see a new column within 5 minutes.
The cost is one `DESCRIBE` per table every 5 minutes per process. Concurrent callers still share one pending query. The browser uses the same cache, so a page reload is no longer needed there either.
Things to be aware of:
- If the refresh fails (ClickHouse is down), the caller now gets the error instead of the old column list. The query that needs the columns would fail in that case anyway.
- Other cached schema data still has no TTL: skip indices, the text index lookups, `system.tables` metadata and TimeSeries table columns. I kept this PR to the column list from the issue. I can extend the TTL to those in a follow-up if you want.
- 5 minutes is a guess at "a few minutes" from the issue. Happy to change it.
### Tests
In `packages/common-utils/src/__tests__/metadata.test.ts`, with `Date.now` mocked:
- `MetadataCache`: a value stored with a TTL is returned from the cache until the TTL passes and fetched again after it. A value stored without a TTL is still cached a year later.
- `getMaterializedColumnsLookupTable`: the first `DESCRIBE` has no MATERIALIZED column, and a second one adds `__otel_materialized_k8s.namespace.name`. The lookup stays empty just before the TTL, and has `ResourceAttributes['k8s.namespace.name']` → `__otel_materialized_k8s.namespace.name` once the TTL has passed. `DESCRIBE` runs twice.
With this change all 156 tests in the file pass. With `metadata.ts` from `main`, the two TTL tests fail (the cache returns `first` instead of `second`, and the lookup stays empty). With the cache TTL but without the TTL on `getColumns`, the lookup test fails. ESLint, Prettier, `tsc` on the two changed files and `knip` for `common-utils` pass.
I did not run the issue's steps against a full `yarn dev` stack.
### How to reproduce
**Starting point:** `yarn dev`, with the steps from #3475 (the MCP `clickstack_timeseries` tool on the metrics source).
**On `main`:**
1. Call `clickstack_timeseries` on a gauge metric with `where: ResourceAttributes.k8s.namespace.name:foo`.
2. Add the `__otel_materialized_k8s.namespace.name` and `__otel_materialized_k8s.cluster.name` MATERIALIZED columns to `otel_metrics_gauge` (SQL in the issue).
3. Repeat step 1. `system.query_log` shows the filter still reads `ResourceAttributes['k8s.namespace.name']`, and grouping by `` `__otel_materialized_k8s.cluster.name` `` fails with `Unknown expression identifier`. This keeps happening until the API restarts.
**On this branch:**
1. Do the same steps, then wait 5 minutes after step 2.
2. Repeat step 1. The filter uses `__otel_materialized_k8s.namespace.name`, and the group-by works without a restart.
### How to test on Vercel preview
N/A — non-UI change.
### References
- Closes #3475
- Related: #3191 (computed metric columns), #32311 parent 821c2f9 commit 442d6df
3 files changed
Lines changed: 138 additions & 7 deletions
File tree
- .changeset
- packages/common-utils/src
- __tests__
- core
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
157 | 158 | | |
158 | 159 | | |
159 | 160 | | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
160 | 203 | | |
161 | 204 | | |
162 | 205 | | |
| |||
168 | 211 | | |
169 | 212 | | |
170 | 213 | | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
171 | 271 | | |
172 | 272 | | |
173 | 273 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
251 | 251 | | |
252 | 252 | | |
253 | 253 | | |
254 | | - | |
| 254 | + | |
255 | 255 | | |
256 | 256 | | |
257 | 257 | | |
258 | 258 | | |
259 | | - | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
260 | 265 | | |
261 | 266 | | |
262 | | - | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
263 | 273 | | |
264 | | - | |
| 274 | + | |
265 | 275 | | |
266 | 276 | | |
267 | 277 | | |
| |||
279 | 289 | | |
280 | 290 | | |
281 | 291 | | |
282 | | - | |
| 292 | + | |
283 | 293 | | |
284 | 294 | | |
285 | 295 | | |
286 | 296 | | |
287 | 297 | | |
288 | 298 | | |
289 | 299 | | |
290 | | - | |
291 | | - | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
292 | 305 | | |
293 | 306 | | |
294 | 307 | | |
| |||
353 | 366 | | |
354 | 367 | | |
355 | 368 | | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
356 | 374 | | |
357 | 375 | | |
358 | 376 | | |
| |||
619 | 637 | | |
620 | 638 | | |
621 | 639 | | |
| 640 | + | |
622 | 641 | | |
623 | 642 | | |
624 | 643 | | |
| |||
0 commit comments