Skip to content

Commit

Permalink
feat(cache): implement content-specific file system caching
Browse files Browse the repository at this point in the history
- Add CacheController to manage cache-related operations
- Update query service to use content_id in cache key and storage
- Introduce content-specific cache directory management
- Add method to clear cache for a specific content ID
  • Loading branch information
long2ice committed Feb 17, 2025
1 parent 413101a commit 87be864
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 8 deletions.
12 changes: 12 additions & 0 deletions api/src/api_models/cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ApiModel, ApiModelProperty } from 'swagger-express-ts';

@ApiModel({
description: 'Cache clear request object',
name: 'CacheClearRequest',
})
export class CacheClearRequest {
@ApiModelProperty({
description: 'Content id',
})
content_id: string;
}
39 changes: 39 additions & 0 deletions api/src/controller/cache.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { controller, httpPost, interfaces } from 'inversify-express-utils';
import { ApiOperationPost, ApiPath } from 'swagger-express-ts';
import { clearFsCache, clearFsCacheByContentId } from '../utils/fs_cache';
import { CacheClearRequest } from '../api_models/cache';
import express from 'express';
@ApiPath({
path: '/cache',
name: 'Cache',
})
@controller('/cache')
export class CacheController implements interfaces.Controller {
public static TARGET_NAME = 'Cache';

@ApiOperationPost({
path: '/clear',
description: 'Clear cache',
responses: {
200: { description: 'SUCCESS' },
},
})
@httpPost('/clear')
public async clear(): Promise<void> {
clearFsCache();
}

@ApiOperationPost({
path: '/clear/dashboard',
description: 'Clear cache by content id',
responses: {
200: { description: 'SUCCESS' },
},
})
@httpPost('/clear/dashboard')
public async clearByContentId(req: express.Request): Promise<void> {
const { content_id } = req.body as CacheClearRequest;
clearFsCacheByContentId(content_id);
}
}

6 changes: 6 additions & 0 deletions api/src/controller/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { DashboardContentController } from './dashboard_content.controller';
import { DashboardContentChangelogController } from './dashboard_content_changelog.controller';
import { CustomFunctionController } from './custom_function.controller';
import { SqlSnippetController } from './sql_snippet.controller';
import { CacheController } from './cache.controller';

export function bindControllers(container: Container) {
container
Expand Down Expand Up @@ -86,4 +87,9 @@ export function bindControllers(container: Container) {
.to(SqlSnippetController)
.inSingletonScope()
.whenTargetNamed(SqlSnippetController.TARGET_NAME);
container
.bind<interfaces.Controller>(TYPE.Controller)
.to(CacheController)
.inSingletonScope()
.whenTargetNamed(CacheController.TARGET_NAME);
}
4 changes: 2 additions & 2 deletions api/src/services/query.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ export class QueryService {
const fsCacheEnabled = await isFsCacheEnabled();
const cacheKey = getFsCacheKey(`${parsedType}:${parsedKey}:${q}`);
if (fsCacheEnabled && !refresh_cache) {
const cached = await getFsCache(cacheKey);
const cached = await getFsCache(content_id, cacheKey);
if (cached) {
return cached;
}
Expand All @@ -292,7 +292,7 @@ export class QueryService {
return null;
}
if (fsCacheEnabled) {
await putFsCache(cacheKey, result);
await putFsCache(content_id, cacheKey, result);
}
return result;
}
Expand Down
16 changes: 10 additions & 6 deletions api/src/utils/fs_cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,27 @@ export const clearFsCache = () => {
fs.emptyDirSync(cacheDir);
};

export const putFsCache = async (key: string, data: any): Promise<void> => {
export const clearFsCacheByContentId = (contentId: string) => {
fs.emptyDirSync(path.join(cacheDir, contentId));
};

export const putFsCache = async (contentId: string, key: string, data: any): Promise<void> => {
fs.ensureDirSync(cacheDir);
const filename = `${key}.json`;
await fs.writeJSON(path.join(cacheDir, filename), data);
await fs.writeJSON(path.join(cacheDir, contentId, filename), data);
};

export const getFsCache = async (key: string): Promise<any> => {
export const getFsCache = async (contentId: string, key: string): Promise<any> => {
fs.ensureDirSync(cacheDir);
const ttl = await getTTL();
const filename = `${key}.json`;
try {
const fileInfo = await fs.stat(path.join(cacheDir, filename));
const fileInfo = await fs.stat(path.join(cacheDir, contentId, filename));
if (fileInfo.mtimeMs + ttl * 1000 < Date.now()) {
await fs.remove(path.join(cacheDir, filename));
await fs.remove(path.join(cacheDir, contentId, filename));
return null;
}
return fs.readJSON(path.join(cacheDir, filename));
return fs.readJSON(path.join(cacheDir, contentId, filename));
} catch (err) {
return null;
}
Expand Down

0 comments on commit 87be864

Please sign in to comment.