From 90989c641315ee00b897baec5746261a75d2347d Mon Sep 17 00:00:00 2001 From: Kazuki Yamada Date: Sat, 7 Jun 2025 17:22:30 +0900 Subject: [PATCH] perf(website/server): Make zlib operations asynchronous to prevent event loop blocking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace synchronous zlib.inflateSync/deflateSync with async alternatives to prevent blocking the event loop under high load. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- website/server/src/processZipFile.ts | 4 ++-- website/server/src/remoteRepo.ts | 4 ++-- website/server/src/utils/cache.ts | 14 +++++++++----- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/website/server/src/processZipFile.ts b/website/server/src/processZipFile.ts index 5535501..3f736bd 100644 --- a/website/server/src/processZipFile.ts +++ b/website/server/src/processZipFile.ts @@ -54,7 +54,7 @@ export async function processZipFile( ); // Check if the result is already cached - const cachedResult = cache.get(cacheKey); + const cachedResult = await cache.get(cacheKey); if (cachedResult) { return cachedResult; } @@ -123,7 +123,7 @@ export async function processZipFile( }; // Save the result to cache - cache.set(cacheKey, packResultData); + await cache.set(cacheKey, packResultData); return packResultData; } catch (error) { diff --git a/website/server/src/remoteRepo.ts b/website/server/src/remoteRepo.ts index 741924b..1e1f9c6 100644 --- a/website/server/src/remoteRepo.ts +++ b/website/server/src/remoteRepo.ts @@ -35,7 +35,7 @@ export async function processRemoteRepo( const cacheKey = generateCacheKey(validatedData.url, validatedData.format, validatedData.options, 'url'); // Check if the result is already cached - const cachedResult = cache.get(cacheKey); + const cachedResult = await cache.get(cacheKey); if (cachedResult) { return cachedResult; } @@ -100,7 +100,7 @@ export async function processRemoteRepo( }; // Save the result to cache - cache.set(cacheKey, packResultData); + await cache.set(cacheKey, packResultData); return packResultData; } catch (error) { diff --git a/website/server/src/utils/cache.ts b/website/server/src/utils/cache.ts index 2725ae9..a72fa0a 100644 --- a/website/server/src/utils/cache.ts +++ b/website/server/src/utils/cache.ts @@ -1,6 +1,10 @@ import * as zlib from 'node:zlib'; +import { promisify } from 'node:util'; import type { PackOptions } from '../types.js'; +const inflateAsync = promisify(zlib.inflate); +const deflateAsync = promisify(zlib.deflate); + interface CacheEntry { value: Uint8Array; // Compressed data timestamp: number; @@ -17,7 +21,7 @@ export class RequestCache { setInterval(() => this.cleanup(), ttlInSeconds * 1000); } - get(key: string): T | undefined { + async get(key: string): Promise { const entry = this.cache.get(key); if (!entry) { return undefined; @@ -31,8 +35,8 @@ export class RequestCache { try { // Decompress and return the data - const decompressedData = zlib.inflateSync(entry.value).toString('utf8'); - return JSON.parse(decompressedData); + const decompressedData = await inflateAsync(entry.value); + return JSON.parse(decompressedData.toString('utf8')); } catch (error) { console.error('Error decompressing cache entry:', error); this.cache.delete(key); @@ -40,11 +44,11 @@ export class RequestCache { } } - set(key: string, value: T): void { + async set(key: string, value: T): Promise { try { // Convert data to JSON string and compress const jsonString = JSON.stringify(value); - const compressedData = zlib.deflateSync(Buffer.from(jsonString, 'utf8')); + const compressedData = await deflateAsync(Buffer.from(jsonString, 'utf8')); this.cache.set(key, { value: compressedData,