Created
October 28, 2024 17:39
-
-
Save tranlehaiquan/d71fb76981458819ae7fbcc7a9fb5947 to your computer and use it in GitHub Desktop.
Next.js custom cache-handler.js for GCP Storage
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { CacheHandler } = require('@neshca/cache-handler'); | |
const { Storage } = require('@google-cloud/storage'); | |
const CACHE_PREFIX = 'cache-'; | |
const ENV = process.env.NEXT_ENV || 'dev'; | |
const CACHE_BUCKET_NAME = `your-bucket-${ENV}`; | |
CacheHandler.onCreation(async (params) => { | |
const buildId = params.buildId || 'dev'; | |
const storageBucket = CACHE_BUCKET_NAME; | |
const prefix = CACHE_PREFIX + buildId; | |
const cacheExtension = 'json'; | |
const gcpStorage = new Storage(); | |
const bucket = gcpStorage.bucket(storageBucket); | |
const handler = { | |
async get(key) { | |
console.log('Getting cache', key); | |
if (!bucket) { | |
console.error('Bucket not found'); | |
console.error(CACHE_BUCKET_NAME, GCP_PROJECT_ID); | |
return null; | |
} | |
const contents = await bucket.file(`${prefix}-${key}.${cacheExtension}`).download(); | |
if (!contents) { | |
return null; | |
} | |
console.log('Cache found', key); | |
return JSON.parse(contents.toString()); | |
}, | |
async set(key, value) { | |
console.log('Setting cache', key); | |
const file_key = `${prefix}-${key}.${cacheExtension}`; | |
const tags = value?.tags; | |
const expireAt = value.lifespan.expireAt; | |
const cacheValue = value; | |
const customMetadata = { | |
tags: JSON.stringify(tags), | |
} | |
await bucket.file(file_key).save(JSON.stringify(cacheValue), { | |
contentType: 'application/json', | |
gzip: true, | |
metadata: { | |
cacheControl: `max-age=${Math.floor(expireAt - Date.now() / 1000)}`, | |
contentType: 'application/json', | |
metadata: customMetadata, | |
}, | |
}); | |
}, | |
async revalidateTag(tag) { | |
const [files] = await bucket.getFiles(); | |
const deleteKeys = []; | |
for (const file of files) { | |
const [metadata] = await file?.getMetadata(); | |
const fileMetadata = metadata.metadata; | |
let metaDataTags = []; | |
if (fileMetadata?.tags && typeof fileMetadata?.tags === 'string') { | |
metaDataTags = JSON.parse(fileMetadata.tags); | |
} | |
if (metaDataTags.includes(tag)) { | |
deleteKeys.push(file.name); | |
} | |
} | |
await Promise.all(deleteKeys.map((key) => bucket.file(key).delete())); | |
}, | |
}; | |
return { | |
handlers: [handler], | |
}; | |
}); | |
module.exports = CacheHandler; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment