Commit 1b6e065e authored by nanahira's avatar nanahira

use file relation

parent a3afc3fd
......@@ -35,10 +35,17 @@ export class AdminController {
@Post('migrate/hash')
@ApiOperation({ summary: '迁移 hash' })
@ApiCreatedResponse({ type: BlankReturnMessageDto })
async migrateHash(@UploadedFile('file') file: Express.Multer.File): Promise<BlankReturnMessageDto> {
async migrateHash(): Promise<BlankReturnMessageDto> {
return this.appService.migrateHashes();
}
@Post('migrate/filesField')
@ApiOperation({ summary: '迁移 file 字段' })
@ApiCreatedResponse({ type: BlankReturnMessageDto })
async migrateFilesField(): Promise<BlankReturnMessageDto> {
return this.appService.migrateFilesField();
}
@Put('app/:id')
@ApiOperation({ summary: '创建 app' })
@ApiOkResponse({ type: BlankReturnMessageDto })
......
......@@ -16,6 +16,7 @@ import { UpdateController } from './update/update.controller';
import { UpdateService } from './update/update.service';
import { ServeStaticModule } from '@nestjs/serve-static';
import path from 'path';
import { ArchiveFile } from './entities/ArchiveFile.entity';
const configModule = ConfigModule.forRoot();
......@@ -32,14 +33,14 @@ const configModule = ConfigModule.forRoot();
useFactory: async (config: ConfigService) => {
return {
type: 'postgres',
entities: [App, AppHistory, Archive, Build, Depot], // entities here
entities: [App, AppHistory, Archive, Build, Depot, ArchiveFile], // entities here
synchronize: !config.get('DB_NO_INIT'),
host: config.get('DB_HOST'),
port: parseInt(config.get('DB_PORT')) || 5432,
username: config.get('DB_USER'),
password: config.get('DB_PASS'),
database: config.get('DB_NAME'),
logging: true,
//logging: true,
};
},
}),
......
......@@ -15,6 +15,8 @@ import { Archive, ArchiveType } from './entities/Archive.entity';
import { PackageS3Service } from './package-s3/package-s3.service';
import axios from 'axios';
import { createHash } from 'crypto';
import { ArchiveFile } from './entities/ArchiveFile.entity';
import _ from 'lodash';
@Injectable()
export class AppService extends ConsoleLogger {
......@@ -294,7 +296,9 @@ export class AppService extends ConsoleLogger {
}
await this.purgeRelatedArchives(build);
await this.db.transaction(async (edb) => {
await edb.getRepository(Archive).delete({ build });
//const archives = await edb.getRepository(Archive).find({ where: { build } });
//await edb.getRepository(ArchiveFile).delete({ archive: In(archives) });
//await edb.getRepository(Archive).delete({ build });
await edb.getRepository(Build).delete(build);
});
return new BlankReturnMessageDto(200, 'success');
......@@ -340,4 +344,21 @@ export class AppService extends ConsoleLogger {
await this.db.getRepository(Archive).save(archivesToDo);
return new BlankReturnMessageDto(200, 'success');
}
async migrateFilesField() {
const archives = await this.db.getRepository(Archive).find({ select: ['id', 'files'] });
await this.db.transaction(async (edb) => {
for (const a of archives) {
this.log(`Processing archive ${a.id} with ${a.files.length} files.`);
const files = a.files.map((f) => {
const fileEnt = ArchiveFile.fromPath(f);
fileEnt.archive = a;
return fileEnt;
});
await edb.getRepository(ArchiveFile).save(files);
}
});
this.log(`Done.`);
return new BlankReturnMessageDto(200, 'success');
}
}
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
import { Build } from './Build.entity';
import { Index } from 'typeorm';
import { TimeBase } from './TimeBase.entity';
import { ArchiveFile } from './ArchiveFile.entity';
export enum ArchiveType {
Full = 'full',
......@@ -17,6 +18,9 @@ export class Archive extends TimeBase {
@Column('varchar', { length: 256, array: true })
files: string[];
@OneToMany(() => ArchiveFile, (file) => file.archive, { cascade: true })
containingFiles: ArchiveFile[];
@Index()
@Column('varchar', { length: 128 })
path: string;
......@@ -27,7 +31,7 @@ export class Archive extends TimeBase {
@Column('int', { unsigned: true })
size: number;
@ManyToOne((type) => Build, (build) => build.archives)
@ManyToOne((type) => Build, (build) => build.archives, { onDelete: 'CASCADE' })
build: Build;
@Index()
......
import { Entity, ManyToOne, PrimaryColumn } from 'typeorm';
import { Archive } from './Archive.entity';
@Entity()
export class ArchiveFile {
@ManyToOne(() => Archive, (a) => a.containingFiles, { primary: true, onDelete: 'CASCADE' })
archive: Archive;
@PrimaryColumn('varchar', { length: 256 })
path: string;
static fromPath(path: string) {
const archiveFile = new ArchiveFile();
archiveFile.path = path;
return archiveFile;
}
}
......@@ -16,6 +16,7 @@ import { Archive, ArchiveType } from '../entities/Archive.entity';
import { Build } from '../entities/Build.entity';
import { AppService } from '../app.service';
import { createHash } from 'crypto';
import { ArchiveFile } from '../entities/ArchiveFile.entity';
export interface FileWithHash {
file: readdirp.EntryInfo;
......@@ -46,7 +47,8 @@ export class ArchiveTask {
const archive = new Archive();
archive.path = this.path;
archive.role = this.role;
archive.files = this.exactFilePaths;
archive.files = [];
archive.containingFiles = this.exactFilePaths.map((filePath) => ArchiveFile.fromPath(filePath));
return archive;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment