this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

add cache debug log (#911)

authored by

Victor Berchet and committed by
GitHub
5d0042bd e0886d12

+85 -33
+13 -6
packages/cloudflare/src/api/durable-objects/sharded-tag-cache.ts
··· 1 1 import { DurableObject } from "cloudflare:workers"; 2 2 3 + import { debugCache } from "../overrides/internal.js"; 4 + 3 5 export class DOShardedTagCache extends DurableObject<CloudflareEnv> { 4 6 sql: SqlStorage; 5 7 ··· 19 21 ...tags 20 22 ) 21 23 .toArray(); 22 - if (result.length === 0) return 0; 23 - // We only care about the most recent revalidation 24 - return result[0]?.time as number; 24 + 25 + const timeMs = (result[0]?.time ?? 0) as number; 26 + debugCache("DOShardedTagCache", `getLastRevalidated tags=${tags} -> time=${timeMs}`); 27 + return timeMs; 25 28 } catch (e) { 26 29 console.error(e); 27 30 // By default we don't want to crash here, so we return 0 ··· 30 33 } 31 34 32 35 async hasBeenRevalidated(tags: string[], lastModified?: number): Promise<boolean> { 33 - return ( 36 + const revalidated = 34 37 this.sql 35 38 .exec( 36 39 `SELECT 1 FROM revalidations WHERE tag IN (${tags.map(() => "?").join(", ")}) AND revalidatedAt > ? LIMIT 1`, 37 40 ...tags, 38 41 lastModified ?? Date.now() 39 42 ) 40 - .toArray().length > 0 41 - ); 43 + .toArray().length > 0; 44 + 45 + debugCache("DOShardedTagCache", `hasBeenRevalidated tags=${tags} -> revalidated=${revalidated}`); 46 + return revalidated; 42 47 } 43 48 44 49 async writeTags(tags: string[], lastModified: number): Promise<void> { 50 + debugCache("DOShardedTagCache", `writeTags tags=${tags} time=${lastModified}`); 51 + 45 52 tags.forEach((tag) => { 46 53 this.sql.exec( 47 54 `INSERT OR REPLACE INTO revalidations (tag, revalidatedAt) VALUES (?, ?)`,
+3 -3
packages/cloudflare/src/api/overrides/incremental-cache/kv-incremental-cache.ts
··· 36 36 const kv = getCloudflareContext().env[BINDING_NAME]; 37 37 if (!kv) throw new IgnorableError("No KV Namespace"); 38 38 39 - debugCache(`Get ${key}`); 39 + debugCache("KVIncrementalCache", `get ${key}`); 40 40 41 41 try { 42 42 const entry = await kv.get<IncrementalCacheEntry<CacheType>>(this.getKVKey(key, cacheType), "json"); ··· 66 66 const kv = getCloudflareContext().env[BINDING_NAME]; 67 67 if (!kv) throw new IgnorableError("No KV Namespace"); 68 68 69 - debugCache(`Set ${key}`); 69 + debugCache("KVIncrementalCache", `set ${key}`); 70 70 71 71 try { 72 72 await kv.put( ··· 89 89 const kv = getCloudflareContext().env[BINDING_NAME]; 90 90 if (!kv) throw new IgnorableError("No KV Namespace"); 91 91 92 - debugCache(`Delete ${key}`); 92 + debugCache("KVIncrementalCache", `delete ${key}`); 93 93 94 94 try { 95 95 // Only cache that gets deleted is the ISR/SSG cache.
+3 -3
packages/cloudflare/src/api/overrides/incremental-cache/r2-incremental-cache.ts
··· 33 33 const r2 = getCloudflareContext().env[BINDING_NAME]; 34 34 if (!r2) throw new IgnorableError("No R2 bucket"); 35 35 36 - debugCache(`Get ${key}`); 36 + debugCache("R2IncrementalCache", `get ${key}`); 37 37 38 38 try { 39 39 const r2Object = await r2.get(this.getR2Key(key, cacheType)); ··· 57 57 const r2 = getCloudflareContext().env[BINDING_NAME]; 58 58 if (!r2) throw new IgnorableError("No R2 bucket"); 59 59 60 - debugCache(`Set ${key}`); 60 + debugCache("R2IncrementalCache", `set ${key}`); 61 61 62 62 try { 63 63 await r2.put(this.getR2Key(key, cacheType), JSON.stringify(value)); ··· 70 70 const r2 = getCloudflareContext().env[BINDING_NAME]; 71 71 if (!r2) throw new IgnorableError("No R2 bucket"); 72 72 73 - debugCache(`Delete ${key}`); 73 + debugCache("R2IncrementalCache", `delete ${key}`); 74 74 75 75 try { 76 76 await r2.delete(this.getR2Key(key));
+7 -1
packages/cloudflare/src/api/overrides/incremental-cache/regional-cache.ts
··· 105 105 106 106 // Check for a cached entry as this will be faster than the store response. 107 107 const cachedResponse = await cache.match(urlKey); 108 + 108 109 if (cachedResponse) { 109 - debugCache("Get - cached response"); 110 + debugCache("RegionalCache", `get ${key} -> cached response`); 110 111 111 112 // Re-fetch from the store and update the regional cache in the background. 112 113 // Note: this is only useful when the Cache API is not purged automatically. ··· 134 135 const { value, lastModified } = rawEntry ?? {}; 135 136 if (!value || typeof lastModified !== "number") return null; 136 137 138 + debugCache("RegionalCache", `get ${key} -> put to cache`); 139 + 137 140 // Update the locale cache after retrieving from the store. 138 141 getCloudflareContext().ctx.waitUntil( 139 142 this.putToCache({ key, cacheType, entry: { value, lastModified } }) ··· 152 155 cacheType?: CacheType 153 156 ): Promise<void> { 154 157 try { 158 + debugCache("RegionalCache", `set ${key}`); 159 + 155 160 await this.store.set(key, value, cacheType); 156 161 157 162 await this.putToCache({ ··· 170 175 } 171 176 172 177 async delete(key: string): Promise<void> { 178 + debugCache("RegionalCache", `delete ${key}`); 173 179 try { 174 180 await this.store.delete(key); 175 181
+8 -4
packages/cloudflare/src/api/overrides/incremental-cache/static-assets-incremental-cache.ts
··· 30 30 const assets = getCloudflareContext().env.ASSETS; 31 31 if (!assets) throw new IgnorableError("No Static Assets"); 32 32 33 - debugCache(`Get ${key}`); 33 + debugCache("StaticAssetsIncrementalCache", `get ${key}`); 34 34 35 35 try { 36 36 const response = await assets.fetch(this.getAssetUrl(key, cacheType)); ··· 49 49 } 50 50 } 51 51 52 - async set(): Promise<void> { 53 - error("Failed to set to read-only cache"); 52 + async set<CacheType extends CacheEntryType = "cache">( 53 + key: string, 54 + _value: CacheValue<CacheType>, 55 + cacheType?: CacheType 56 + ): Promise<void> { 57 + error(`StaticAssetsIncrementalCache: Failed to set to read-only cache key=${key} type=${cacheType}`); 54 58 } 55 59 56 60 async delete(): Promise<void> { 57 - error("Failed to delete from read-only cache"); 61 + error("StaticAssetsIncrementalCache: Failed to delete from read-only cache"); 58 62 } 59 63 60 64 protected getAssetUrl(key: string, cacheType?: CacheEntryType): string {
+14 -5
packages/cloudflare/src/api/overrides/tag-cache/d1-next-tag-cache.ts
··· 23 23 .bind(...tags.map((tag) => this.getCacheKey(tag))) 24 24 .run(); 25 25 26 - if (result.results.length === 0) return 0; 27 - // We only care about the most recent revalidation 28 - return (result.results[0]?.time ?? 0) as number; 26 + const timeMs = (result.results[0]?.time ?? 0) as number; 27 + debugCache("D1NextModeTagCache", `getLastRevalidated tags=${tags} -> ${timeMs}`); 28 + return timeMs; 29 29 } catch (e) { 30 30 // By default we don't want to crash here, so we return false 31 31 // We still log the error though so we can debug it ··· 45 45 .bind(...tags.map((tag) => this.getCacheKey(tag)), lastModified ?? Date.now()) 46 46 .raw(); 47 47 48 - return result.length > 0; 48 + const revalidated = result.length > 0; 49 + debugCache( 50 + "D1NextModeTagCache", 51 + `hasBeenRevalidated tags=${tags} at=${lastModified} -> ${revalidated}` 52 + ); 53 + return revalidated; 49 54 } catch (e) { 50 55 error(e); 51 56 // By default we don't want to crash here, so we return false ··· 57 62 async writeTags(tags: string[]): Promise<void> { 58 63 const { isDisabled, db } = this.getConfig(); 59 64 if (isDisabled || tags.length === 0) return Promise.resolve(); 65 + 66 + const nowMs = Date.now(); 60 67 61 68 await db.batch( 62 69 tags.map((tag) => 63 70 db 64 71 .prepare(`INSERT INTO revalidations (tag, revalidatedAt) VALUES (?, ?)`) 65 - .bind(this.getCacheKey(tag), Date.now()) 72 + .bind(this.getCacheKey(tag), nowMs) 66 73 ) 67 74 ); 75 + 76 + debugCache("D1NextModeTagCache", `writeTags tags=${tags} time=${nowMs}`); 68 77 69 78 // TODO: See https://github.com/opennextjs/opennextjs-aws/issues/986 70 79 if (isPurgeCacheEnabled()) {
+23 -6
packages/cloudflare/src/api/overrides/tag-cache/do-sharded-tag-cache.ts
··· 140 140 const cachedValue = await this.getFromRegionalCache({ doId, tags }); 141 141 // If all the value were found in the regional cache, we can just return the max value 142 142 if (cachedValue.length === tags.length) { 143 - return Math.max(...cachedValue.map((item) => item.time)); 143 + const timeMs = Math.max(...cachedValue.map((item) => item.time as number)); 144 + debugCache("ShardedDOTagCache", `getLastRevalidated tags=${tags} -> ${timeMs} (regional cache)`); 145 + return timeMs; 144 146 } 145 147 // Otherwise we need to check the durable object on the ones that were not found in the cache 146 148 const filteredTags = deduplicatedTags.filter( ··· 150 152 const stub = this.getDurableObjectStub(doId); 151 153 const lastRevalidated = await stub.getLastRevalidated(filteredTags); 152 154 153 - const result = Math.max(...cachedValue.map((item) => item.time), lastRevalidated); 155 + const timeMs = Math.max(...cachedValue.map((item) => item.time), lastRevalidated); 154 156 155 157 // We then need to populate the regional cache with the missing tags 156 158 getCloudflareContext().ctx.waitUntil(this.putToRegionalCache({ doId, tags }, stub)); 157 159 158 - return result; 160 + debugCache("ShardedDOTagCache", `getLastRevalidated tags=${tags} -> ${timeMs}`); 161 + return timeMs; 159 162 }) 160 163 ); 161 164 return Math.max(...shardedTagRevalidationOutcomes); ··· 187 190 }); 188 191 189 192 if (cacheHasBeenRevalidated) { 193 + debugCache( 194 + "ShardedDOTagCache", 195 + `hasBeenRevalidated tags=${tags} at=${lastModified} -> true (regional cache)` 196 + ); 197 + 190 198 return true; 191 199 } 192 200 const stub = this.getDurableObjectStub(doId); ··· 200 208 ); 201 209 } 202 210 211 + debugCache( 212 + "ShardedDOTagCache", 213 + `hasBeenRevalidated tags=${tags} at=${lastModified} -> ${_hasBeenRevalidated}` 214 + ); 215 + 203 216 return _hasBeenRevalidated; 204 217 }) 205 218 ); ··· 219 232 public async writeTags(tags: string[]): Promise<void> { 220 233 const { isDisabled } = this.getConfig(); 221 234 if (isDisabled) return; 222 - const shardedTagGroups = this.groupTagsByDO({ tags, generateAllReplicas: true }); 235 + 223 236 // We want to use the same revalidation time for all tags 224 - const currentTime = Date.now(); 237 + const nowMs = Date.now(); 238 + 239 + debugCache("ShardedDOTagCache", `writeTags tags=${tags} time=${nowMs}`); 240 + 241 + const shardedTagGroups = this.groupTagsByDO({ tags, generateAllReplicas: true }); 225 242 await Promise.all( 226 243 shardedTagGroups.map(async ({ doId, tags }) => { 227 - await this.performWriteTagsWithRetry(doId, tags, currentTime); 244 + await this.performWriteTagsWithRetry(doId, tags, nowMs); 228 245 }) 229 246 ); 230 247
+14 -5
packages/cloudflare/src/api/overrides/tag-cache/kv-next-tag-cache.ts
··· 2 2 import type { NextModeTagCache } from "@opennextjs/aws/types/overrides.js"; 3 3 4 4 import { getCloudflareContext } from "../../cloudflare-context.js"; 5 - import { FALLBACK_BUILD_ID, isPurgeCacheEnabled, purgeCacheByTags } from "../internal.js"; 5 + import { debugCache, FALLBACK_BUILD_ID, isPurgeCacheEnabled, purgeCacheByTags } from "../internal.js"; 6 6 7 7 export const NAME = "kv-next-mode-tag-cache"; 8 8 ··· 37 37 38 38 const revalidations = [...result.values()].filter((v) => v != null); 39 39 40 - return revalidations.length === 0 ? 0 : Math.max(...revalidations); 40 + const timeMs = revalidations.length === 0 ? 0 : Math.max(...revalidations); 41 + debugCache("KVNextModeTagCache", `getLastRevalidated tags=${tags} -> time=${timeMs}`); 42 + return timeMs; 41 43 } catch (e) { 42 44 // By default we don't want to crash here, so we return false 43 45 // We still log the error though so we can debug it ··· 47 49 } 48 50 49 51 async hasBeenRevalidated(tags: string[], lastModified?: number): Promise<boolean> { 50 - return (await this.getLastRevalidated(tags)) > (lastModified ?? Date.now()); 52 + const revalidated = (await this.getLastRevalidated(tags)) > (lastModified ?? Date.now()); 53 + debugCache( 54 + "KVNextModeTagCache", 55 + `hasBeenRevalidated tags=${tags} lastModified=${lastModified} -> ${revalidated}` 56 + ); 57 + return revalidated; 51 58 } 52 59 53 60 async writeTags(tags: string[]): Promise<void> { ··· 56 63 return Promise.resolve(); 57 64 } 58 65 59 - const timeMs = String(Date.now()); 66 + const nowMs = Date.now(); 60 67 61 68 await Promise.all( 62 69 tags.map(async (tag) => { 63 - await kv.put(this.getCacheKey(tag), timeMs); 70 + await kv.put(this.getCacheKey(tag), String(nowMs)); 64 71 }) 65 72 ); 73 + 74 + debugCache("KVNextModeTagCache", `writeTags tags=${tags} time=${nowMs}`); 66 75 67 76 // TODO: See https://github.com/opennextjs/opennextjs-aws/issues/986 68 77 if (isPurgeCacheEnabled()) {