### File

`src/core/interceptors/page.interceptor.ts`

### Description

Pagination-implementing interceptor

### Index

###### Properties

- Private Readonly ES_IP
- Private Readonly ES_PORT

###### Methods

- Async deletePIT
- Public Async getPIT
- Async intercept

### Constructor

`constructor(httpService: HttpService, cacheManager: Cache)`
Defined in src/core/interceptors/page.interceptor.ts:18

Injects needed dependencies and instantiates the storage object

Parameters :

Name | Type | Optional
httpService | `HttpService` | No
cacheManager | `Cache` | No

### Methods

Async deletePIT
`deletePIT(pitID: string)`
Defined in src/core/interceptors/page.interceptor.ts:117

Deletes the PIT specified by provided ID

Parameters :

Name | Type | Optional | Description
pitID | `string` | No | , ID of the PIT, that would be deleted

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:97

Acquires a PIT ID from Elasticsearch, needed for a request

Parameters :

Name | Type | Optional | Default value | Description
alive | `number` | No |  | , amount of time in minutes (defaults to 1). If time unit is not specified - defaults to minutes.
unit | `EsTime` | No | `EsTime.min` |

Returns : `Promise<EsPit>`

PIT object <EsPit> containing PIT ID and keep_alive value

Async intercept
`intercept(context: ExecutionContext, next: CallHandler<any>)`
Defined in src/core/interceptors/page.interceptor.ts:45

Override of intercept() method, specified in NestInterceptor interface

Parameters :

Name | Type | Optional
context | `ExecutionContext` | No
next | `CallHandler<any>` | No

Returns : `Promise<Observable<PageDto>>`

Page with content and metadata

### Properties

Private Readonly ES_IP
Default value : `process.env.ES_CONTAINER_NAME`
Defined in src/core/interceptors/page.interceptor.ts:37
Elastichsearch IP address

Private Readonly ES_PORT
Default value : `process.env.ES_PORT`
Defined in src/core/interceptors/page.interceptor.ts:32
Elastichsearch server port-number

    import { HttpService } from "@nestjs/axios";
    import { CACHE_MANAGER, CallHandler, ExecutionContext, Inject, Injectable, NestInterceptor } from "@nestjs/common";
    import { Observable, map, take, switchMap, of } from "rxjs";
    import { PageDto } from "../domain/dtos";
    import { EsQueryDto } from "../domain/dtos/elastic/es-query.dto";
    import { RequestDto } from "../domain/dtos/request.dto";
    import { SearchQueryDto } from "../domain/dtos/search-q.dto";
    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 request: RequestDto = context.switchToHttp().getRequest<RequestDto>();
            const query: SearchQueryDto = request.query;

            const offset = !query.offset ? 0 : query.offset;
            const limit = !query.limit ? 10 : query.limit;
            const order = !query.order ? Order.DESC : query.order;

            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]) return of(prev_page[0]);
            }

            // Contruct a body for querying Elasticsearch
            request.es_query = new EsQueryDto();
            request.es_query.query = {
                query_string: {
                    query: query.query,
                    default_field: 'content',
                }
            };
            request.es_query.from = offset;
            request.es_query.size = limit;

            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]);
                    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);
               }
           })
        }
    }

# results matching ""

# No results matching ""