feat: Implement ETag-based conditional caching for API and HTML, add immutable caching for images, and introduce concurrency control with resizing for picture syncing.
This commit is contained in:
@@ -9,10 +9,48 @@ class PictureSyncer {
|
||||
return PictureSyncer.instance;
|
||||
}
|
||||
this.cacheBaseDir = process.env.CACHE_LOCATION || '.';
|
||||
|
||||
// Track syncing state per group
|
||||
this.isSyncing = new Map(); // groupName -> boolean
|
||||
this.queuedSyncs = new Map(); // groupName -> { imageIds, groupName }
|
||||
|
||||
PictureSyncer.instance = this;
|
||||
}
|
||||
|
||||
async syncImages(imageIds, groupName) {
|
||||
// Check if already syncing this group
|
||||
if (this.isSyncing.get(groupName)) {
|
||||
if (this.queuedSyncs.has(groupName)) {
|
||||
console.log(`🚫 Image sync for '${groupName}' already in progress and queued. Ignoring.`);
|
||||
return;
|
||||
}
|
||||
console.log(`⏳ Image sync for '${groupName}' already in progress. Queuing.`);
|
||||
this.queuedSyncs.set(groupName, { imageIds, groupName });
|
||||
return;
|
||||
}
|
||||
|
||||
await this._doSync(imageIds, groupName);
|
||||
}
|
||||
|
||||
async _doSync(imageIds, groupName) {
|
||||
this.isSyncing.set(groupName, true);
|
||||
|
||||
try {
|
||||
await this._performSync(imageIds, groupName);
|
||||
} finally {
|
||||
this.isSyncing.set(groupName, false);
|
||||
|
||||
// Process queued sync for this group if any
|
||||
if (this.queuedSyncs.has(groupName)) {
|
||||
console.log(`🔄 Processing queued image sync for '${groupName}'...`);
|
||||
const queued = this.queuedSyncs.get(groupName);
|
||||
this.queuedSyncs.delete(groupName);
|
||||
setImmediate(() => this.syncImages(queued.imageIds, queued.groupName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async _performSync(imageIds, groupName) {
|
||||
const groupDir = path.join(this.cacheBaseDir, 'img', groupName);
|
||||
|
||||
// Ensure directory exists
|
||||
@@ -74,8 +112,12 @@ class PictureSyncer {
|
||||
for (const record of result.recordset) {
|
||||
if (record.bBild) {
|
||||
const filePath = path.join(dir, `${record.kBild}.avif`);
|
||||
// Convert to AVIF using sharp
|
||||
// Resize to 130x130 and convert to AVIF using sharp
|
||||
await sharp(record.bBild)
|
||||
.resize(130, 130, {
|
||||
fit: 'cover',
|
||||
position: 'center'
|
||||
})
|
||||
.avif({ quality: 80 })
|
||||
.toFile(filePath);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user