chore(repo): restructure as monorepo with server and client workspaces
- move NestJS app into server/ subdirectory - add client/ React+TypeScript (Vite) app with Hello World - update docker-compose to build and run both services - add root package.json declaring npm workspaces - update .gitignore to cover node_modules and dist at all depths
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { Interval } from "@nestjs/schedule";
|
||||
import { ConfigService } from "@nestjs/config";
|
||||
import { AppConfig } from "../config/app.config";
|
||||
import { TraceLogger } from "../common/trace-logger";
|
||||
import { SessionService } from "./session.service";
|
||||
import { SessionContextService } from "./session-context.service";
|
||||
|
||||
/**
|
||||
* Periodically:
|
||||
* 1. Closes sessions that have been idle for longer than SESSION_IDLE_TIMEOUT_MINUTES.
|
||||
* 2. Deletes closed sessions whose updatedAt is older than SESSION_DELETE_CLOSED_DAYS.
|
||||
*/
|
||||
@Injectable()
|
||||
export class SessionSchedulerService {
|
||||
private readonly logger = new TraceLogger(SessionSchedulerService.name);
|
||||
|
||||
constructor(
|
||||
private readonly sessionService: SessionService,
|
||||
private readonly sessionContextService: SessionContextService,
|
||||
private readonly config: ConfigService<AppConfig, true>,
|
||||
) {}
|
||||
|
||||
@Interval(60_000)
|
||||
async runScheduler(): Promise<void> {
|
||||
await this.closeExpired();
|
||||
await this.deleteOldClosed();
|
||||
}
|
||||
|
||||
private async closeExpired(): Promise<void> {
|
||||
const idleMinutes = this.config.get("SESSION_IDLE_TIMEOUT_MINUTES");
|
||||
const cutoff = new Date(Date.now() - idleMinutes * 60_000);
|
||||
const expired = await this.sessionService.findExpiredOpen(cutoff);
|
||||
for (const session of expired) {
|
||||
await this.sessionContextService.close(session.sessionName);
|
||||
this.logger.log(
|
||||
`Session "${session.sessionName}" closed (idle > ${idleMinutes} min)`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async deleteOldClosed(): Promise<void> {
|
||||
const days = this.config.get("SESSION_DELETE_CLOSED_DAYS");
|
||||
const cutoff = new Date(Date.now() - days * 86_400_000);
|
||||
const old = await this.sessionService.findOldClosed(cutoff);
|
||||
for (const session of old) {
|
||||
await this.sessionService.remove(session.id);
|
||||
this.logger.log(
|
||||
`Session "${session.sessionName}" deleted (closed > ${days} days ago)`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user