Commit f059f518 authored by nanahira's avatar nanahira

add AragamiCacheInterceptor

parent c6678c22
......@@ -28,3 +28,5 @@ export const InjectAragami = () => Inject(ARAGAMI_TOKEN);
exports: [ARAGAMI_TOKEN],
})
export class AragamiModule extends ConfigurableModuleClass {}
export * from './src/aragami-cache.interceptor';
{
"name": "myproject",
"name": "nestjs-aragami",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "myproject",
"name": "nestjs-aragami",
"version": "1.0.0",
"license": "MIT",
"devDependencies": {
......@@ -24,7 +24,8 @@
},
"peerDependencies": {
"@nestjs/common": "^9.1.2",
"aragami": "^1.1.2"
"aragami": "^1.1.2",
"rxjs": "^7.8.1"
}
},
"node_modules/@ampproject/remapping": {
......@@ -4347,9 +4348,9 @@
}
},
"node_modules/rxjs": {
"version": "7.5.7",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz",
"integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==",
"version": "7.8.1",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
"peer": true,
"dependencies": {
"tslib": "^2.1.0"
......@@ -8256,9 +8257,9 @@
}
},
"rxjs": {
"version": "7.5.7",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz",
"integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==",
"version": "7.8.1",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
"peer": true,
"requires": {
"tslib": "^2.1.0"
......
......@@ -54,6 +54,7 @@
},
"peerDependencies": {
"@nestjs/common": "^9.1.2",
"aragami": "^1.1.2"
"aragami": "^1.1.2",
"rxjs": "^7.8.1"
}
}
import {
CallHandler,
ExecutionContext,
HttpAdapterHost,
Inject,
NestInterceptor,
Optional,
} from '@nestjs/common';
import { sortParams } from './utility/sort-params';
import { InjectAragami } from '../index';
import { Aragami, CacheKey } from 'aragami';
import { reflector } from 'aragami/dist/src/metadata';
import { tap } from 'rxjs';
class RouteCache {
@CacheKey()
key: string;
value: any;
}
export class AragamiCacheInterceptor implements NestInterceptor {
@Optional()
@Inject()
protected readonly httpAdapterHost: HttpAdapterHost;
constructor(@InjectAragami() protected aragami: Aragami) {}
protected allowedMethods = ['GET'];
async intercept(context: ExecutionContext, next: CallHandler) {
const key = await this.trackBy(context);
if (!key) {
return next.handle();
}
const controllerCls = context.getClass();
const controllerMethodName = context.getHandler().name;
const ttl =
reflector.get('AragamiCacheTTL', controllerCls, controllerMethodName) ||
reflector.get('AragamiCacheTTL', controllerCls);
if (!ttl) {
return next.handle();
}
const cachedValue = await this.aragami.get(RouteCache, key);
if (cachedValue) {
return cachedValue.value;
}
return next
.handle()
.pipe(
tap((value) => this.aragami.set(RouteCache, { key, value }, { ttl })),
);
}
protected async trackBy(
context: ExecutionContext,
): Promise<string | undefined> {
if (!(await this.isRequestCacheable(context))) {
return;
}
const httpAdapter = this.httpAdapterHost.httpAdapter;
const isHttpApp = httpAdapter && !!httpAdapter.getRequestMethod;
if (!isHttpApp) {
return;
}
const url = new URL(httpAdapter.getRequestUrl(context), 'http://localhost');
return `${url.pathname}?${sortParams(url.searchParams)}`;
}
protected async isRequestCacheable(
context: ExecutionContext,
): Promise<boolean> {
const req = context.switchToHttp().getRequest();
return this.allowedMethods.includes(req.method);
}
}
import { Aragami } from 'aragami';
export class AragamiService extends Aragami {}
import { ConfigurableModuleBuilder } from '@nestjs/common';
import { AragamiOptions } from 'aragami';
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } =
new ConfigurableModuleBuilder<AragamiOptions>()
.setExtras(
{
isGlobal: true,
},
(definition, extras) => ({
...definition,
global: extras.isGlobal,
}),
)
.build();
export function sortParams(params: any) {
const param = new URLSearchParams(params);
const keys = Array.from(param.keys());
keys.sort();
const sortedParam = new URLSearchParams();
keys.forEach((key) => {
sortedParam.append(key, param.get(key));
});
return sortedParam.toString();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment