File

src/session/session.service.ts

Index

Methods

Constructor

constructor(sessionRepository: Repository<Session>, configService: ConfigService, schedulerRegistry: SchedulerRegistry, sessionsCounter: Gauge)
Parameters :
Name Type Optional
sessionRepository Repository<Session> No
configService ConfigService No
schedulerRegistry SchedulerRegistry No
sessionsCounter Gauge<string> No

Methods

add
add(issuer_state: string, values: QueryDeepPartialEntity<Session>)

Update an existing session.

Parameters :
Name Type Optional
issuer_state string No
values QueryDeepPartialEntity<Session> No
Returns : any
Async create
create(session: DeepPartial<Session>)

Create a new session.

Parameters :
Name Type Optional
session DeepPartial<Session> No
Returns : unknown
get
get(state: string)

Get a session by its state.

Parameters :
Name Type Optional
state string No
Returns : any
getAll
getAll()

Get all sessions.

Returns : Promise<Session[]>
getBy
getBy(where: FindOptionsWhere<Session>)

Get a session by a specific condition.

Parameters :
Name Type Optional
where FindOptionsWhere<Session> No
Returns : any
Async onApplicationBootstrap
onApplicationBootstrap()

Register the tidy up cron job on application bootstrap. This will run every hour by default, but can be configured via the SESSION_TIDY_UP_INTERVAL config variable.

Returns : unknown
Async setState
setState(session: Session, status: SessionStatus)

Marks the session as successful or failed.

Parameters :
Name Type Optional
session Session No
status SessionStatus No
Returns : any
tidyUpSessions
tidyUpSessions()

Tidy up sessions that are older than 1 day.

Returns : any
import { Injectable, OnApplicationBootstrap } from '@nestjs/common';
import { Session, SessionStatus } from './entities/session.entity';
import { InjectRepository } from '@nestjs/typeorm';
import {
    DeepPartial,
    FindOptionsWhere,
    IsNull,
    LessThan,
    Not,
    Repository,
} from 'typeorm';
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
import { SchedulerRegistry } from '@nestjs/schedule';
import { ConfigService } from '@nestjs/config';
import { Gauge } from 'prom-client';
import { InjectMetric } from '@willsoto/nestjs-prometheus/dist/injector';

@Injectable()
export class SessionService implements OnApplicationBootstrap {
    constructor(
        @InjectRepository(Session)
        private sessionRepository: Repository<Session>,
        private readonly configService: ConfigService,
        private readonly schedulerRegistry: SchedulerRegistry,
        @InjectMetric('sessions')
        private sessionsCounter: Gauge<string>,
    ) {}

    /**
     * Register the tidy up cron job on application bootstrap.
     * This will run every hour by default, but can be configured via the `SESSION_TIDY_UP_INTERVAL` config variable.
     * @returns
     */
    async onApplicationBootstrap() {
        const callback = () => {
            void this.tidyUpSessions();
        };
        const intervalTime =
            this.configService.getOrThrow<number>('SESSION_TIDY_UP_INTERVAL') *
            1000;
        const interval = setInterval(callback, intervalTime);
        this.schedulerRegistry.addInterval('tidyUpSessions', interval);

        //set default values for session metrics
        const tenantId = 'root';
        const states: SessionStatus[] = [
            'active',
            'completed',
            'expired',
            'failed',
        ];
        for (const state of states) {
            const issuanceCounter = await this.sessionRepository.countBy({
                tenantId,
                issuanceId: Not(IsNull()),
                status: state,
            });
            this.sessionsCounter.set(
                {
                    tenant_id: tenantId,
                    session_type: 'issuance',
                    status: state,
                },
                issuanceCounter,
            );
            const verificationCounter = await this.sessionRepository.countBy({
                tenantId,
                issuanceId: IsNull(),
                status: state,
            });
            this.sessionsCounter.set(
                {
                    tenant_id: tenantId,
                    session_type: 'verification',
                    status: state,
                },
                verificationCounter,
            );
        }

        return this.tidyUpSessions();
    }

    /**
     * Create a new session.
     * @param session
     * @returns
     */
    async create(session: DeepPartial<Session>) {
        const createdSession = await this.sessionRepository.save(session);

        // Count total sessions created
        this.sessionsCounter.inc({
            tenant_id: createdSession.tenantId,
            session_type: createdSession.issuanceId
                ? 'issuance'
                : 'verification',
            status: 'active',
        });

        return createdSession;
    }

    /**
     * Marks the session as successful or failed.
     * @param session
     * @param status
     */
    async setState(session: Session, status: SessionStatus) {
        const sessionType = session.issuanceId ? 'issuance' : 'verification';

        await this.sessionRepository.update({ id: session.id }, { status });

        // Count completed sessions (success or failure)
        this.sessionsCounter.inc({
            tenant_id: session.tenantId,
            session_type: sessionType,
            status,
        });

        // Decrease active sessions count
        this.sessionsCounter.dec({
            tenant_id: session.tenantId,
            session_type: sessionType,
            status: 'active',
        });
    }

    /**
     * Update an existing session.
     * @param issuer_state
     * @param values
     * @returns
     */
    add(issuer_state: string, values: QueryDeepPartialEntity<Session>) {
        return this.sessionRepository.update({ id: issuer_state }, values);
    }

    /**
     * Get all sessions.
     * @returns
     */
    getAll(): Promise<Session[]> {
        return this.sessionRepository.find();
    }

    /**
     * Get a session by its state.
     * @param state
     * @returns
     */
    get(state: string) {
        return this.sessionRepository.findOneByOrFail({ id: state });
    }

    /**
     * Get a session by a specific condition.
     * @param where
     * @returns
     */
    getBy(where: FindOptionsWhere<Session>) {
        return this.sessionRepository.findOneByOrFail(where);
    }

    /**
     * Tidy up sessions that are older than 1 day.
     */
    tidyUpSessions() {
        const ttl = this.configService.getOrThrow<number>('SESSION_TTL') * 1000;
        return this.sessionRepository.delete({
            createdAt: LessThan(new Date(Date.now() - ttl)),
        });
    }
}

results matching ""

    No results matching ""