0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-02-18 01:24:26 -05:00

refactor: migrate move repository to kysely (#15327)

* refactor: migrate move repository to kysely

* fix: tests

* fix: tests
This commit is contained in:
Alex 2025-01-13 22:22:03 -06:00 committed by GitHub
parent fc99c5f530
commit a35af2b242
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 56 additions and 35 deletions

View file

@ -183,7 +183,7 @@ export class StorageCore {
return; return;
} }
move = await this.moveRepository.update({ id: move.id, oldPath: actualPath, newPath }); move = await this.moveRepository.update(move.id, { id: move.id, oldPath: actualPath, newPath });
} else { } else {
move = await this.moveRepository.create({ entityId, pathType, oldPath, newPath }); move = await this.moveRepository.create({ entityId, pathType, oldPath, newPath });
} }
@ -225,7 +225,7 @@ export class StorageCore {
} }
await this.savePath(pathType, entityId, newPath); await this.savePath(pathType, entityId, newPath);
await this.moveRepository.delete(move); await this.moveRepository.delete(move.id);
} }
private async verifyNewPathContentsMatchesExpected( private async verifyNewPathContentsMatchesExpected(

View file

@ -1,3 +1,5 @@
import { Insertable, Updateable } from 'kysely';
import { MoveHistory } from 'src/db';
import { MoveEntity } from 'src/entities/move.entity'; import { MoveEntity } from 'src/entities/move.entity';
import { PathType } from 'src/enum'; import { PathType } from 'src/enum';
@ -6,8 +8,8 @@ export const IMoveRepository = 'IMoveRepository';
export type MoveCreate = Pick<MoveEntity, 'oldPath' | 'newPath' | 'entityId' | 'pathType'> & Partial<MoveEntity>; export type MoveCreate = Pick<MoveEntity, 'oldPath' | 'newPath' | 'entityId' | 'pathType'> & Partial<MoveEntity>;
export interface IMoveRepository { export interface IMoveRepository {
create(entity: MoveCreate): Promise<MoveEntity>; create(entity: Insertable<MoveHistory>): Promise<MoveEntity>;
getByEntity(entityId: string, pathType: PathType): Promise<MoveEntity | null>; getByEntity(entityId: string, pathType: PathType): Promise<MoveEntity | undefined>;
update(entity: Partial<MoveEntity>): Promise<MoveEntity>; update(id: string, entity: Updateable<MoveHistory>): Promise<MoveEntity>;
delete(move: MoveEntity): Promise<MoveEntity>; delete(id: string): Promise<MoveEntity>;
} }

View file

@ -1,18 +1,17 @@
-- NOTE: This file is auto generated by ./sql-generator -- NOTE: This file is auto generated by ./sql-generator
-- MoveRepository.getByEntity -- MoveRepository.getByEntity
SELECT select
"MoveEntity"."id" AS "MoveEntity_id", *
"MoveEntity"."entityId" AS "MoveEntity_entityId", from
"MoveEntity"."pathType" AS "MoveEntity_pathType", "move_history"
"MoveEntity"."oldPath" AS "MoveEntity_oldPath", where
"MoveEntity"."newPath" AS "MoveEntity_newPath" "entityId" = $1
FROM and "pathType" = $2
"move_history" "MoveEntity"
WHERE -- MoveRepository.delete
( delete from "move_history"
("MoveEntity"."entityId" = $1) where
AND ("MoveEntity"."pathType" = $2) "id" = $1
) returning
LIMIT *
1

View file

@ -1,29 +1,49 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { Insertable, Kysely, Updateable } from 'kysely';
import { InjectKysely } from 'nestjs-kysely';
import { DB, MoveHistory } from 'src/db';
import { DummyValue, GenerateSql } from 'src/decorators'; import { DummyValue, GenerateSql } from 'src/decorators';
import { MoveEntity } from 'src/entities/move.entity'; import { MoveEntity } from 'src/entities/move.entity';
import { PathType } from 'src/enum'; import { PathType } from 'src/enum';
import { IMoveRepository, MoveCreate } from 'src/interfaces/move.interface'; import { IMoveRepository } from 'src/interfaces/move.interface';
import { Repository } from 'typeorm';
@Injectable() @Injectable()
export class MoveRepository implements IMoveRepository { export class MoveRepository implements IMoveRepository {
constructor(@InjectRepository(MoveEntity) private repository: Repository<MoveEntity>) {} constructor(@InjectKysely() private db: Kysely<DB>) {}
create(entity: MoveCreate): Promise<MoveEntity> { create(entity: Insertable<MoveHistory>): Promise<MoveEntity> {
return this.repository.save(entity); return this.db
.insertInto('move_history')
.values(entity)
.returningAll()
.executeTakeFirstOrThrow() as Promise<MoveEntity>;
} }
@GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING] }) @GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING] })
getByEntity(entityId: string, pathType: PathType): Promise<MoveEntity | null> { getByEntity(entityId: string, pathType: PathType): Promise<MoveEntity | undefined> {
return this.repository.findOne({ where: { entityId, pathType } }); return this.db
.selectFrom('move_history')
.selectAll()
.where('entityId', '=', entityId)
.where('pathType', '=', pathType)
.executeTakeFirst() as Promise<MoveEntity | undefined>;
} }
update(entity: Partial<MoveEntity>): Promise<MoveEntity> { update(id: string, entity: Updateable<MoveHistory>): Promise<MoveEntity> {
return this.repository.save(entity); return this.db
.updateTable('move_history')
.set(entity)
.where('id', '=', id)
.returningAll()
.executeTakeFirstOrThrow() as unknown as Promise<MoveEntity>;
} }
delete(move: MoveEntity): Promise<MoveEntity> { @GenerateSql({ params: [DummyValue.UUID] })
return this.repository.remove(move); delete(id: string): Promise<MoveEntity> {
return this.db
.deleteFrom('move_history')
.where('id', '=', id)
.returningAll()
.executeTakeFirstOrThrow() as unknown as Promise<MoveEntity>;
} }
} }

View file

@ -235,7 +235,7 @@ describe(StorageTemplateService.name, () => {
expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.image.id], { exifInfo: true }); expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.image.id], { exifInfo: true });
expect(storageMock.checkFileExists).toHaveBeenCalledTimes(3); expect(storageMock.checkFileExists).toHaveBeenCalledTimes(3);
expect(storageMock.rename).toHaveBeenCalledWith(assetStub.image.originalPath, newPath); expect(storageMock.rename).toHaveBeenCalledWith(assetStub.image.originalPath, newPath);
expect(moveMock.update).toHaveBeenCalledWith({ expect(moveMock.update).toHaveBeenCalledWith('123', {
id: '123', id: '123',
oldPath: assetStub.image.originalPath, oldPath: assetStub.image.originalPath,
newPath, newPath,
@ -277,7 +277,7 @@ describe(StorageTemplateService.name, () => {
expect(storageMock.stat).toHaveBeenCalledWith(previousFailedNewPath); expect(storageMock.stat).toHaveBeenCalledWith(previousFailedNewPath);
expect(storageMock.rename).toHaveBeenCalledWith(previousFailedNewPath, newPath); expect(storageMock.rename).toHaveBeenCalledWith(previousFailedNewPath, newPath);
expect(storageMock.copyFile).not.toHaveBeenCalled(); expect(storageMock.copyFile).not.toHaveBeenCalled();
expect(moveMock.update).toHaveBeenCalledWith({ expect(moveMock.update).toHaveBeenCalledWith('123', {
id: '123', id: '123',
oldPath: previousFailedNewPath, oldPath: previousFailedNewPath,
newPath, newPath,