feat(server): use postgres-adapter for websockets (#5569)

* feat(server): use postgres-adapter for websockets

* refactor: create attachment table via migration
This commit is contained in:
Jason Rasmussen 2023-12-08 20:38:25 -05:00 committed by GitHub
parent a426ea8fbc
commit 92b4284b5a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 213 additions and 68 deletions

View file

@ -1,5 +1,5 @@
import { envName, getLogLevels, isDev, serverVersion } from '@app/domain';
import { RedisIoAdapter, enablePrefilter } from '@app/infra';
import { WebSocketAdapter, enablePrefilter } from '@app/infra';
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
@ -21,7 +21,7 @@ export async function bootstrap() {
if (isDev) {
app.enableCors();
}
app.useWebSocketAdapter(new RedisIoAdapter(app));
app.useWebSocketAdapter(new WebSocketAdapter(app));
useSwagger(app, isDev);
const excludePaths = ['/.well-known/immich', '/custom.css'];

View file

@ -2,4 +2,4 @@ export * from './database-locks';
export * from './database.config';
export * from './infra.config';
export * from './infra.module';
export * from './redis-io.adapter';
export * from './websocket.adapter';

View file

@ -0,0 +1,13 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class AddWebSocketAttachmentTable1702084989965 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'CREATE TABLE IF NOT EXISTS "socket_io_attachments" (id bigserial UNIQUE, created_at timestamptz DEFAULT NOW(), payload bytea);',
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "socket_io_attachments"`);
}
}

View file

@ -1,23 +0,0 @@
import { Logger } from '@nestjs/common';
import { IoAdapter } from '@nestjs/platform-socket.io';
import { createAdapter } from '@socket.io/redis-adapter';
import Redis from 'ioredis';
import { ServerOptions } from 'socket.io';
import { redisConfig } from './infra.config';
export class RedisIoAdapter extends IoAdapter {
private readonly logger = new Logger(RedisIoAdapter.name);
createIOServer(port: number, options?: ServerOptions): any {
const pubClient = new Redis(redisConfig);
pubClient.on('error', (error) => {
this.logger.error(`Redis pubClient: ${error}`);
});
const subClient = pubClient.duplicate();
subClient.on('error', (error) => {
this.logger.error(`Redis subClient: ${error}`);
});
const server = super.createIOServer(port, options);
server.adapter(createAdapter(pubClient, subClient));
return server;
}
}

View file

@ -0,0 +1,19 @@
import { INestApplicationContext } from '@nestjs/common';
import { IoAdapter } from '@nestjs/platform-socket.io';
import { createAdapter } from '@socket.io/postgres-adapter';
import { ServerOptions } from 'socket.io';
import { DataSource } from 'typeorm';
import { PostgresDriver } from 'typeorm/driver/postgres/PostgresDriver.js';
export class WebSocketAdapter extends IoAdapter {
constructor(private app: INestApplicationContext) {
super(app);
}
createIOServer(port: number, options?: ServerOptions): any {
const server = super.createIOServer(port, options);
const pool = (this.app.get(DataSource).driver as PostgresDriver).master;
server.adapter(createAdapter(pool));
return server;
}
}

View file

@ -1,5 +1,5 @@
import { envName, getLogLevels, serverVersion } from '@app/domain';
import { RedisIoAdapter, enablePrefilter } from '@app/infra';
import { WebSocketAdapter, enablePrefilter } from '@app/infra';
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppService } from './app.service';
@ -11,7 +11,7 @@ const port = Number(process.env.MICROSERVICES_PORT) || 3002;
export async function bootstrap() {
const app = await NestFactory.create(MicroservicesModule, { logger: getLogLevels() });
app.useWebSocketAdapter(new RedisIoAdapter(app));
app.useWebSocketAdapter(new WebSocketAdapter(app));
await enablePrefilter();
await app.get(AppService).init();