src/core/interceptors/page.interceptor.ts
Pagination-implementing interceptor
Properties |
Methods |
constructor(httpService: HttpService, cacheManager: Cache)
|
|||||||||
Defined in src/core/interceptors/page.interceptor.ts:15
|
|||||||||
Injects needed dependencies and instantiates the storage object
Parameters :
|
Async deletePIT | ||||||||
deletePIT(pitID: string)
|
||||||||
Deletes the PIT specified by provided ID
Parameters :
Returns :
Promise<boolean>
true/false, depending on the result of deletion of the PIT |
Public Async getPIT | |||||||||||||||
getPIT(alive: number, unit: EsTime)
|
|||||||||||||||
Defined in src/core/interceptors/page.interceptor.ts:86
|
|||||||||||||||
Acquires a PIT ID from Elasticsearch, needed for a request
Parameters :
Returns :
Promise<EsPit>
PIT object |
Async intercept | |||||||||
intercept(context: ExecutionContext, next: CallHandler
|
|||||||||
Defined in src/core/interceptors/page.interceptor.ts:42
|
|||||||||
Override of intercept() method, specified in NestInterceptor interface
Parameters :
Returns :
Promise<Observable<PageDto>>
Page with content and metadata |
Private Readonly ES_IP |
Default value : process.env.ES_CONTAINER_NAME
|
Defined in src/core/interceptors/page.interceptor.ts:34
|
Elastichsearch IP address |
Private Readonly ES_PORT |
Default value : process.env.ES_PORT
|
Defined in src/core/interceptors/page.interceptor.ts:29
|
Elastichsearch server port-number |
import { HttpService } from "@nestjs/axios";
import { BadRequestException, CACHE_MANAGER, CallHandler, ExecutionContext, Inject, Injectable, InternalServerErrorException, NestInterceptor } from "@nestjs/common";
import { Observable, map, take, switchMap, of } from "rxjs";
import { PageDto } from "../domain/dtos";
import { EsTime } from "../domain/enums/es-time.enum";
import { Order, toOrder } from "../domain/enums/page-order.enum";
import { EsPit } from "../domain/interfaces/elastic/es-pit.interface";
import { Cache } from 'cache-manager'
import { PageMetaDto } from "../domain/dtos/page-meta.dto";
/**
* Pagination-implementing interceptor
*/
@Injectable()
export class PageInterceptor implements NestInterceptor {
/**
* Injects needed dependencies and instantiates the storage object
* @param httpService
* @param searchService
*/
constructor(
private readonly httpService: HttpService,
@Inject(CACHE_MANAGER) private cacheManager: Cache
) {}
/**
* Elastichsearch server port-number
*/
private readonly ES_PORT = process.env.ES_PORT;
/**
* Elastichsearch IP address
*/
private readonly ES_IP = process.env.ES_CONTAINER_NAME;
/**
* Override of intercept() method, specified in NestInterceptor interface
* @param context
* @param next
* @returns Page with content and metadata
*/
async intercept(context: ExecutionContext, next: CallHandler<any>): Promise<Observable<PageDto>> {
const query = context.switchToHttp().getRequest().query;
const offset = query.offset;
const limit = query.limit;
const order = query.order;
const query_string = query.query;
const prev_page = await this.cacheManager.get('prev_page');
if (prev_page) {
if (offset == prev_page[1] &&
limit == prev_page[2] &&
order == prev_page[3] &&
query_string === prev_page[4]) return of(prev_page[0]);
}
return next.handle().pipe(
switchMap(async (res) => {
// Setting the page meta-data
let meta: PageMetaDto = {
total: res.hits.total.value,
order: toOrder(order),
};
// Check if the performed search is a backwards search
let data = res?.hits?.hits;
// Omitting the redundant info and leaving only the document
data = data.map((el) => el._source);
// Change the order if set
if (order == Order.ASC) data.reverse();
// Cache and return the page
const page: PageDto = new PageDto(data, meta);
await this.cacheManager.set('prev_page', [page, offset, limit, order, query_string]);
return page;
})
);
}
/**
* Acquires a PIT ID from Elasticsearch, needed for a request
* @param alive, amount of time in minutes (defaults to 1). If time unit is not specified - defaults to minutes.
* @returns PIT object <EsPit> containing PIT ID and keep_alive value
*/
public async getPIT(alive: number, unit: EsTime = EsTime.min): Promise<EsPit> {
return new Promise((resolve, reject) => {
try {
this.httpService.post<EsPit>(`http://${this.ES_IP}:${this.ES_PORT}/papers/_pit?keep_alive=${alive+unit}`)
.pipe(take(1), map(axiosRes => axiosRes.data))
.subscribe((res: EsPit) => {
res.keep_alive = alive + unit;
resolve(res);
});
} catch (error) {
reject(error);
}
});
}
/**
* Deletes the PIT specified by provided ID
* @param pitID, ID of the PIT, that would be deleted
* @returns true/false, depending on the result of deletion of the PIT
*/
async deletePIT(pitID: string): Promise<boolean> {
return new Promise((resolve, reject) => {
try {
this.httpService.delete(`http://${this.ES_IP}:${this.ES_PORT}/_pit`, {
data: { id: pitID },
headers: { 'Content-Type': 'application/json' },
})
.pipe(take(1), map(axiosRes => axiosRes.data))
.subscribe((res) => {
resolve(res.succeeded);
});
} catch (error) {
reject(error);
}
})
}
}