typescript - Finnes det en måte å avbryte mongoose find-eksekvering på og returnere data fra redis i stedet?


Jeg prøver å implementere Redis-cache sammen med mongoose i nest.js, og jeg leter etter en måte å sjekke Redis-cache først før jeg utfører find eller findOne og returnerer dataene fra Redis, ellers utfør spørringen, lagre resultatet i Redis og returner resultatet. Grunnen til at jeg ikke implementerer caching som anbefalt av nest.js er at jeg også bruker Apollo Server for GraphQL.

@Injectable()
export class MyService {
    async getItem(where): Promise<ItemModel> {
        const fromCache = await this.cacheService.getValue('itemId');
        if(!!fromCache){
            return JSON.parse(fromCache);
        } else {
            const response = await this.ItemModel.find(where);
            this.cacheService.setValue('itemId', JSON.stringify(response));
            return response
        }
    }
}

Jeg vil gjerne flytte denne koden til ett sted slik at jeg ikke trenger å gjenta denne koden for hver spørring i koden min siden jeg har flere tjenester. Jeg vet at mongoose-mellomvare har en måte å kjøre pre- og post-funksjoner på spørringer, men jeg er bare ikke sikker på hvordan jeg skal få til dette ved å bruke.

Dette er versjonene jeg bruker:

  • nestjs v7
  • mongoose v5.10.0

Svar #1

Du kunne lage en metode-dekoratør der du flytter logikken til:

export const UseCache = (cacheKey:string) => (_target: any, _field: string, descriptor: TypedPropertyDescriptor<any>) => {
    const originalMethod = descriptor.value;
    // note: important to use non-arrow function here to preserve this-context
    descriptor.value     = async function(...args: any[]) {
        const fromCache = await this.cacheService.getValue(cacheKey);
        if(!!fromCache){
            return JSON.parse(fromCache);
        }
        const result = await originalMethod.apply(this, args);
        await this.cacheService.setValue(cacheKey, JSON.stringify(result));
        return result;
    };
}

Bruk det deretter med:

@Injectable()
export class MyService {   

    constructor(private readonly cacheService:CacheService) { .. }

    @UseCache('itemId')
    async getItem(where): Promise<ItemModel> {        
        return this.ItemModel.find(where);
    }

    @UseCache('anotherCacheKey')
    async anotherMethodWithCache(): Promise<any> {        
         // ...            
    }
}

Relaterte artikler