Commit 8110bc6c authored by nanahira's avatar nanahira

use array back..

parent 4df3e5cf
...@@ -14,13 +14,7 @@ import { ...@@ -14,13 +14,7 @@ import {
} from '@nestjs/common'; } from '@nestjs/common';
import { AppService } from './app.service'; import { AppService } from './app.service';
import { ApiBody, ApiConsumes, ApiCreatedResponse, ApiOkResponse, ApiOperation, ApiParam, ApiQuery } from '@nestjs/swagger'; import { ApiBody, ApiConsumes, ApiCreatedResponse, ApiOkResponse, ApiOperation, ApiParam, ApiQuery } from '@nestjs/swagger';
import { import { BlankReturnMessageDto, GetAppReturnMessageDto, ReturnMessageDto, StringReturnMessageDto } from './dto/ReturnMessage.dto';
BlankReturnMessageDto,
BuildReturnMessageDto,
GetAppReturnMessageDto,
ReturnMessageDto,
StringReturnMessageDto,
} from './dto/ReturnMessage.dto';
import { FetchMyCardUser, MyCardUser } from './utility/mycard-auth'; import { FetchMyCardUser, MyCardUser } from './utility/mycard-auth';
import { AppsJson } from './utility/apps-json-type'; import { AppsJson } from './utility/apps-json-type';
import { MyCardAppMaintainerGuard } from './my-card-app-maintainer.guard'; import { MyCardAppMaintainerGuard } from './my-card-app-maintainer.guard';
...@@ -29,11 +23,9 @@ import { FileUploadDto } from './dto/FileUpload.dto'; ...@@ -29,11 +23,9 @@ import { FileUploadDto } from './dto/FileUpload.dto';
import { AssetsS3Service } from './assets-s3/assets-s3.service'; import { AssetsS3Service } from './assets-s3/assets-s3.service';
import Busboy from 'busboy'; import Busboy from 'busboy';
import { Request } from 'express'; import { Request } from 'express';
import { Stream } from 'stream';
import { PackageResult } from './dto/PackageResult.dto'; import { PackageResult } from './dto/PackageResult.dto';
import { platform } from 'os';
import AppClass = AppsJson.AppClass;
import { DepotDto } from './dto/Depot.dto'; import { DepotDto } from './dto/Depot.dto';
import AppClass = AppsJson.AppClass;
@Controller('api') @Controller('api')
export class AppController { export class AppController {
......
...@@ -16,7 +16,6 @@ import { UpdateController } from './update/update.controller'; ...@@ -16,7 +16,6 @@ import { UpdateController } from './update/update.controller';
import { UpdateService } from './update/update.service'; import { UpdateService } from './update/update.service';
import { ServeStaticModule } from '@nestjs/serve-static'; import { ServeStaticModule } from '@nestjs/serve-static';
import path from 'path'; import path from 'path';
import { ArchiveFile } from './entities/ArchiveFile.entity';
const configModule = ConfigModule.forRoot(); const configModule = ConfigModule.forRoot();
...@@ -33,7 +32,7 @@ const configModule = ConfigModule.forRoot(); ...@@ -33,7 +32,7 @@ const configModule = ConfigModule.forRoot();
useFactory: async (config: ConfigService) => { useFactory: async (config: ConfigService) => {
return { return {
type: 'postgres', type: 'postgres',
entities: [App, AppHistory, Archive, Build, Depot, ArchiveFile], // entities here entities: [App, AppHistory, Archive, Build, Depot], // entities here
synchronize: !config.get('DB_NO_INIT'), synchronize: !config.get('DB_NO_INIT'),
host: config.get('DB_HOST'), host: config.get('DB_HOST'),
port: parseInt(config.get('DB_PORT')) || 5432, port: parseInt(config.get('DB_PORT')) || 5432,
......
import { Connection, In, IsNull, Not, SelectQueryBuilder } from 'typeorm'; import { Connection, IsNull, Not, SelectQueryBuilder } from 'typeorm';
import { InjectConnection } from '@nestjs/typeorm'; import { InjectConnection } from '@nestjs/typeorm';
import { ConsoleLogger, forwardRef, Inject, Injectable } from '@nestjs/common'; import { ConsoleLogger, forwardRef, Inject, Injectable } from '@nestjs/common';
import { AppsJson } from './utility/apps-json-type'; import { AppsJson } from './utility/apps-json-type';
...@@ -15,8 +15,6 @@ import { Archive, ArchiveType } from './entities/Archive.entity'; ...@@ -15,8 +15,6 @@ import { Archive, ArchiveType } from './entities/Archive.entity';
import { PackageS3Service } from './package-s3/package-s3.service'; import { PackageS3Service } from './package-s3/package-s3.service';
import axios from 'axios'; import axios from 'axios';
import { createHash } from 'crypto'; import { createHash } from 'crypto';
import { ArchiveFile } from './entities/ArchiveFile.entity';
import _ from 'lodash';
@Injectable() @Injectable()
export class AppService extends ConsoleLogger { export class AppService extends ConsoleLogger {
...@@ -203,7 +201,9 @@ export class AppService extends ConsoleLogger { ...@@ -203,7 +201,9 @@ export class AppService extends ConsoleLogger {
const result = await this.packager.build(stream, app.packagePrefix, previousTracingBuildChecksums); const result = await this.packager.build(stream, app.packagePrefix, previousTracingBuildChecksums);
this.log(`Saving package info of ${app.id} ${version} for ${JSON.stringify(depot)}`); this.log(`Saving package info of ${app.id} ${version} for ${JSON.stringify(depot)}`);
build.checksum = result.checksum; build.checksum = result.checksum;
// build.archives = result.archives; build.archives = result.archives;
build = await this.db.getRepository(Build).save(build);
/*
await this.db.transaction(async (edb) => { await this.db.transaction(async (edb) => {
this.log(`Saving build info.`); this.log(`Saving build info.`);
build = await edb.getRepository(Build).save(build); build = await edb.getRepository(Build).save(build);
...@@ -226,6 +226,7 @@ export class AppService extends ConsoleLogger { ...@@ -226,6 +226,7 @@ export class AppService extends ConsoleLogger {
await edb.getRepository(Archive).save(archivePot); await edb.getRepository(Archive).save(archivePot);
} }
}); });
*/
this.log(`Finished packaging ${app.id} ${version} for ${JSON.stringify(depot)}`); this.log(`Finished packaging ${app.id} ${version} for ${JSON.stringify(depot)}`);
return new BlankReturnMessageDto(201, 'success'); return new BlankReturnMessageDto(201, 'success');
} catch (e) { } catch (e) {
...@@ -371,6 +372,7 @@ export class AppService extends ConsoleLogger { ...@@ -371,6 +372,7 @@ export class AppService extends ConsoleLogger {
return new BlankReturnMessageDto(200, 'success'); return new BlankReturnMessageDto(200, 'success');
} }
/*
async migrateFilesField() { async migrateFilesField() {
const archives = await this.db.getRepository(Archive).find({ select: ['id', 'files'], where: { files: IsNull() } }); const archives = await this.db.getRepository(Archive).find({ select: ['id', 'files'], where: { files: IsNull() } });
await this.db.transaction(async (edb) => { await this.db.transaction(async (edb) => {
...@@ -384,5 +386,5 @@ export class AppService extends ConsoleLogger { ...@@ -384,5 +386,5 @@ export class AppService extends ConsoleLogger {
}); });
this.log(`Done.`); this.log(`Done.`);
return new BlankReturnMessageDto(200, 'success'); return new BlankReturnMessageDto(200, 'success');
} }*/
} }
import { AppsJson } from '../utility/apps-json-type'; import { AppsJson } from '../utility/apps-json-type';
import Platform = AppsJson.Platform; import { ApiProperty } from '@nestjs/swagger';
import Locale = AppsJson.Locale; import { Brackets } from 'typeorm';
import { ApiParam, ApiProperty } from '@nestjs/swagger';
import { Brackets, SelectQueryBuilder } from 'typeorm';
export interface DepotLike { export interface DepotLike {
platform?: string; platform?: string;
......
import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from 'typeorm'; import { Column, Entity, Index, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
import { Build } from './Build.entity'; import { Build } from './Build.entity';
import { Index } from 'typeorm';
import { TimeBase } from './TimeBase.entity'; import { TimeBase } from './TimeBase.entity';
import { ArchiveFile } from './ArchiveFile.entity';
export enum ArchiveType { export enum ArchiveType {
Full = 'full', Full = 'full',
...@@ -15,11 +13,11 @@ export class Archive extends TimeBase { ...@@ -15,11 +13,11 @@ export class Archive extends TimeBase {
@PrimaryGeneratedColumn({ type: 'int8' }) @PrimaryGeneratedColumn({ type: 'int8' })
id: number; id: number;
@Column('varchar', { length: 256, array: true, nullable: true }) @Column('varchar', { length: 256, array: true, default: [] })
files: string[]; files: string[];
@OneToMany(() => ArchiveFile, (file) => file.archive, { cascade: true }) //@OneToMany(() => ArchiveFile, (file) => file.archive, { cascade: true })
containingFiles: ArchiveFile[]; //containingFiles: ArchiveFile[];
@Index() @Index()
@Column('varchar', { length: 128 }) @Column('varchar', { length: 128 })
...@@ -42,9 +40,9 @@ export class Archive extends TimeBase { ...@@ -42,9 +40,9 @@ export class Archive extends TimeBase {
return `${this.path}.tar.zst`; return `${this.path}.tar.zst`;
} }
get paramSize() { //get paramSize() {
return 5 + (this.containingFiles ? this.containingFiles.length * 2 : 0); // return 5 + (this.containingFiles ? this.containingFiles.length * 2 : 0);
} //}
toMetalinkView() { toMetalinkView() {
return { return {
......
import { Entity, Index, ManyToOne, PrimaryColumn } from 'typeorm'; import { Index, PrimaryColumn } from 'typeorm';
import { Archive } from './Archive.entity'; import { Archive } from './Archive.entity';
@Entity() //@Entity()
export class ArchiveFile { export class ArchiveFile {
@ManyToOne(() => Archive, (a) => a.containingFiles, { primary: true, onDelete: 'CASCADE' }) //@ManyToOne(() => Archive, (a) => a.containingFiles, { primary: true, onDelete: 'CASCADE' })
archive: Archive; archive: Archive;
@Index() @Index()
......
import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn, Unique } from 'typeorm'; import { Column, Entity, Index, ManyToOne, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
import { Depot } from './Depot.entity'; import { Depot } from './Depot.entity';
import { Archive } from './Archive.entity'; import { Archive } from './Archive.entity';
import { Index } from 'typeorm';
import { TimeBase } from './TimeBase.entity'; import { TimeBase } from './TimeBase.entity';
@Entity() @Entity()
......
...@@ -14,7 +14,6 @@ import { ConsoleLogger, forwardRef, Inject, Injectable } from '@nestjs/common'; ...@@ -14,7 +14,6 @@ import { ConsoleLogger, forwardRef, Inject, Injectable } from '@nestjs/common';
import { Archive, ArchiveType } from '../entities/Archive.entity'; import { Archive, ArchiveType } from '../entities/Archive.entity';
import { AppService } from '../app.service'; import { AppService } from '../app.service';
import { createHash } from 'crypto'; import { createHash } from 'crypto';
import { ArchiveFile } from '../entities/ArchiveFile.entity';
export interface FileWithHash { export interface FileWithHash {
file: readdirp.EntryInfo; file: readdirp.EntryInfo;
...@@ -45,8 +44,8 @@ export class ArchiveTask { ...@@ -45,8 +44,8 @@ export class ArchiveTask {
const archive = new Archive(); const archive = new Archive();
archive.path = this.path; archive.path = this.path;
archive.role = this.role; archive.role = this.role;
//archive.files = this.exactFilePaths; archive.files = this.exactFilePaths;
archive.containingFiles = this.exactFilePaths.map((filePath) => ArchiveFile.fromPath(filePath)); //archive.containingFiles = this.exactFilePaths.map((filePath) => ArchiveFile.fromPath(filePath));
return archive; return archive;
} }
......
import { Body, Controller, Get, Header, Param, ParseArrayPipe, Post, Query, Render, ValidationPipe } from '@nestjs/common'; import { Body, Controller, Get, Header, Param, ParseArrayPipe, Post, Query, Render, ValidationPipe } from '@nestjs/common';
import { UpdateService } from './update.service'; import { UpdateService } from './update.service';
import { ApiBody, ApiOkResponse, ApiOperation, ApiParam, ApiProperty, ApiQuery, ApiTags } from '@nestjs/swagger'; import { ApiBody, ApiOkResponse, ApiOperation, ApiParam, ApiQuery, ApiTags } from '@nestjs/swagger';
import { DepotDto } from '../dto/Depot.dto'; import { DepotDto } from '../dto/Depot.dto';
@Controller('update') @Controller('update')
......
...@@ -8,11 +8,9 @@ import { BlankReturnMessageDto } from '../dto/ReturnMessage.dto'; ...@@ -8,11 +8,9 @@ import { BlankReturnMessageDto } from '../dto/ReturnMessage.dto';
import { Archive, ArchiveType } from '../entities/Archive.entity'; import { Archive, ArchiveType } from '../entities/Archive.entity';
import { PackageS3Service } from '../package-s3/package-s3.service'; import { PackageS3Service } from '../package-s3/package-s3.service';
import _ from 'lodash'; import _ from 'lodash';
import { ArchiveFile } from '../entities/ArchiveFile.entity';
import * as os from 'os';
import moment from 'moment';
import { AppsJson } from '../utility/apps-json-type'; import { AppsJson } from '../utility/apps-json-type';
import Platform = AppsJson.Platform; import Platform = AppsJson.Platform;
import moment from 'moment';
@Injectable() @Injectable()
export class UpdateService extends ConsoleLogger { export class UpdateService extends ConsoleLogger {
...@@ -187,6 +185,21 @@ export class UpdateService extends ConsoleLogger { ...@@ -187,6 +185,21 @@ export class UpdateService extends ConsoleLogger {
return trafficCost + requestCost; return trafficCost + requestCost;
} }
private pickArchives(archives: Archive[], requestedFiles: string[]) {
const aset = archives.map((a) => ({ archive: a, files: new Set(a.files) }));
const result = new Set<Archive>();
for (const file of requestedFiles) {
try {
result.add(aset.find((a) => a.files.has(file)).archive);
} catch (e) {
//throw new BlankReturnMessageDto(404, `File ${file} not found in archives.`).toException();
}
}
return Array.from(result);
}
async getPartPackageMetalink(id: string, depotDto: DepotDto, version: string, requestedFiles: string[]) { async getPartPackageMetalink(id: string, depotDto: DepotDto, version: string, requestedFiles: string[]) {
const build = await this.getBuild(id, depotDto, version, (qb) => const build = await this.getBuild(id, depotDto, version, (qb) =>
qb qb
...@@ -194,20 +207,21 @@ export class UpdateService extends ConsoleLogger { ...@@ -194,20 +207,21 @@ export class UpdateService extends ConsoleLogger {
.leftJoin('build.archives', 'archive', 'archive.role = :partRole', { partRole: ArchiveType.Part }) .leftJoin('build.archives', 'archive', 'archive.role = :partRole', { partRole: ArchiveType.Part })
); );
// console.log(build.archives); // console.log(build.archives);
//let clock = moment(); let clock = moment();
//this.log('part 1'); this.log('part 1');
const tryExactArchiveQuery = this.db const tryExactArchiveQuery = this.db
.getRepository(Archive) .getRepository(Archive)
.createQueryBuilder('archive') .createQueryBuilder('archive')
.select(['archive.hash', 'archive.path', 'archive.size']) .select(['archive.hash', 'archive.path', 'archive.size'])
.where('archive.buildId = :buildId', { buildId: build.id }) .where('archive.buildId = :buildId', { buildId: build.id })
.andWhere('archive.role != :partRole', { partRole: ArchiveType.Part }); .andWhere('archive.role != :partRole', { partRole: ArchiveType.Part })
/*.addSelect(`array(${qb .andWhere(':requestedFiles = archive.files', { requestedFiles })
/*.addSelect(`array(${qb
.subQuery() .subQuery()
.select('file.path') .select('file.path')
.from(ArchiveFile, 'file') .from(ArchiveFile, 'file')
.where('file.archiveId = archive.id') .where('file.archiveId = archive.id')
.getQuery()})`, 'allFiles')*/ .getQuery()})`, 'allFiles')
tryExactArchiveQuery tryExactArchiveQuery
.andWhere( .andWhere(
`:requestedFiles = array(${tryExactArchiveQuery `:requestedFiles = array(${tryExactArchiveQuery
...@@ -217,7 +231,7 @@ export class UpdateService extends ConsoleLogger { ...@@ -217,7 +231,7 @@ export class UpdateService extends ConsoleLogger {
.where('file.archiveId = archive.id') .where('file.archiveId = archive.id')
.getQuery()})`, .getQuery()})`,
{ requestedFiles: requestedFiles } { requestedFiles: requestedFiles }
) )*/
// .orderBy('archive.size', 'ASC') // .orderBy('archive.size', 'ASC')
.limit(1); .limit(1);
const tryExactArchives = await tryExactArchiveQuery.getMany(); const tryExactArchives = await tryExactArchiveQuery.getMany();
...@@ -239,19 +253,21 @@ export class UpdateService extends ConsoleLogger { ...@@ -239,19 +253,21 @@ export class UpdateService extends ConsoleLogger {
.innerJoin('file.archive', 'archive') .innerJoin('file.archive', 'archive')
.andWhere('archive.buildId = :buildId', { buildId: build.id }) .andWhere('archive.buildId = :buildId', { buildId: build.id })
.getRawMany() .getRawMany()
).map((obj) => obj.archiveId); ).map((obj) => obj.archiveId);*/
this.log(`Time used: ${moment().diff(clock, 'seconds')} s`);*/ this.log(`Time used: ${moment().diff(clock, 'seconds')} s`);
//clock = moment(); clock = moment();
//this.log('part 2'); this.log('part 2');
const allPartArchivesQuery = this.db const allPossiblePartArchives = await this.db
.getRepository(Archive) .getRepository(Archive)
.createQueryBuilder('archive') .createQueryBuilder('archive')
.select(['archive.hash', 'archive.path', 'archive.size']) .select(['archive.hash', 'archive.path', 'archive.size', 'archive.files'])
.where('archive.buildId = :buildId', { buildId: build.id }) .where('archive.buildId = :buildId', { buildId: build.id })
.andWhere('archive.role = :partRole', { partRole: ArchiveType.Part }); .andWhere('archive.role = :partRole', { partRole: ArchiveType.Part })
.getMany();
//.innerJoin('archive.containingFiles', 'file') //.innerJoin('archive.containingFiles', 'file')
//.andWhere('file.path = any(:requestedFiles)', { requestedFiles: requestedFiles }); //.andWhere('file.path = any(:requestedFiles)', { requestedFiles: requestedFiles });
/*
allPartArchivesQuery.andWhere( allPartArchivesQuery.andWhere(
`archive.id in (${allPartArchivesQuery `archive.id in (${allPartArchivesQuery
.subQuery() .subQuery()
...@@ -261,11 +277,16 @@ export class UpdateService extends ConsoleLogger { ...@@ -261,11 +277,16 @@ export class UpdateService extends ConsoleLogger {
.andWhere('file.path = any(:requestedFiles)', { requestedFiles: requestedFiles }) .andWhere('file.path = any(:requestedFiles)', { requestedFiles: requestedFiles })
.getQuery()})` .getQuery()})`
); );
*/
const allPartArchives = await allPartArchivesQuery.getMany(); //const allPartArchives = await allPartArchivesQuery.getMany();
//this.log(`Time used: ${moment().diff(clock, 'seconds')} s`); this.log(`Time used: ${moment().diff(clock, 'seconds')} s`);
//clock = moment(); clock = moment();
//this.log('part 3'); this.log('part 3');
const allPartArchives = this.pickArchives(allPossiblePartArchives, requestedFiles);
this.log(`Time used: ${moment().diff(clock, 'seconds')} s`);
clock = moment();
this.log('part 4');
const fullArchive = await this.db const fullArchive = await this.db
.getRepository(Archive) .getRepository(Archive)
.createQueryBuilder('archive') .createQueryBuilder('archive')
...@@ -279,7 +300,7 @@ export class UpdateService extends ConsoleLogger { ...@@ -279,7 +300,7 @@ export class UpdateService extends ConsoleLogger {
if (!allPartArchives.length || (fullArchive && this.getCostOfArchives([fullArchive]) <= this.getCostOfArchives(allPartArchives))) { if (!allPartArchives.length || (fullArchive && this.getCostOfArchives([fullArchive]) <= this.getCostOfArchives(allPartArchives))) {
archives = [fullArchive]; archives = [fullArchive];
} }
//this.log(`Time used: ${moment().diff(clock, 'seconds')} s`); this.log(`Time used: ${moment().diff(clock, 'seconds')} s`);
return { return {
cdnUrl: this.cdnUrl, cdnUrl: this.cdnUrl,
archives, archives,
......
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