Commit dfb739a7 authored by nanahira's avatar nanahira

too slow

parent c56eb3b5
...@@ -36,11 +36,7 @@ export class UpdateService extends ConsoleLogger { ...@@ -36,11 +36,7 @@ export class UpdateService extends ConsoleLogger {
if (platform === 'generic') { if (platform === 'generic') {
continue; continue;
} }
/*const depotDto = new DepotDto();
depotDto.locale = 'generic';
depotDto.arch = 'generic';
depotDto.platform = platform;*/
// this.log(platform);
for (const app of data) { for (const app of data) {
app.version ??= {}; app.version ??= {};
const tryCache = appVersionCacheMap.get(app.id); const tryCache = appVersionCacheMap.get(app.id);
...@@ -199,10 +195,11 @@ export class UpdateService extends ConsoleLogger { ...@@ -199,10 +195,11 @@ export class UpdateService extends ConsoleLogger {
const result = new Set<Archive>(); const result = new Set<Archive>();
for (const file of requestedFiles) { for (const file of requestedFiles) {
try { const satisfyingArchive = aset.find((a) => a.files.has(file))?.archive;
result.add(aset.find((a) => a.files.has(file)).archive); if (satisfyingArchive) {
} catch (e) { result.add(satisfyingArchive);
//throw new BlankReturnMessageDto(404, `File ${file} not found in archives.`).toException(); } else {
// Ignore missing file for now
} }
} }
return Array.from(result); return Array.from(result);
...@@ -213,22 +210,35 @@ export class UpdateService extends ConsoleLogger { ...@@ -213,22 +210,35 @@ export class UpdateService extends ConsoleLogger {
throw new BlankReturnMessageDto(400, 'empty files').toException(); throw new BlankReturnMessageDto(400, 'empty files').toException();
} }
const build = await this.getBuild(id, depotDto, version, (qb) => qb.select('build.id')); const build = await this.getBuild(id, depotDto, version, (qb) => qb.select('build.id'));
const tryExactArchiveQuery = this.db console.log(1);
const bestUpdateArchive = 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 = :updateRole', { updateRole: ArchiveType.Update })
.andWhere(':requestedFiles = archive.files', { requestedFiles }) .andWhere(':requestedFiles @> archive.files', { requestedFiles })
.limit(1); .orderBy('array_length(archive.files, 1)', 'DESC')
const tryExactArchives = await tryExactArchiveQuery.getMany(); .take(1)
if (tryExactArchives.length) { .getOne();
return {
cdnUrl: this.cdnUrl, console.log(1.5);
archives: tryExactArchives, let remainingFiles: string[];
}; if (bestUpdateArchive) {
const exactFiles = new Set(bestUpdateArchive.files);
remainingFiles = requestedFiles.filter((f) => !exactFiles.has(f));
// If single update archive satisfies all requested files, return it.
if (!remainingFiles.length) {
await this.mirror.lookForArchivesMirror([bestUpdateArchive]);
return {
cdnUrl: this.cdnUrl,
archives: [bestUpdateArchive],
};
}
} }
const packagePlans: Archive[][] = [];
console.log(2);
const allPossiblePartArchives = await this.db const allPossiblePartArchives = await this.db
.getRepository(Archive) .getRepository(Archive)
.createQueryBuilder('archive') .createQueryBuilder('archive')
...@@ -237,20 +247,41 @@ export class UpdateService extends ConsoleLogger { ...@@ -237,20 +247,41 @@ export class UpdateService extends ConsoleLogger {
.andWhere('archive.role = :partRole', { partRole: ArchiveType.Part }) .andWhere('archive.role = :partRole', { partRole: ArchiveType.Part })
.getMany(); .getMany();
// Plan 1: use all part archives
console.log(3);
const allPartArchives = this.pickArchives(allPossiblePartArchives, requestedFiles); const allPartArchives = this.pickArchives(allPossiblePartArchives, requestedFiles);
const fullArchive = await this.db if (allPartArchives.length) {
packagePlans.push(allPartArchives);
}
// Plan 2: use a smallest single as-large-possible archive
console.log(4);
const smallestSingleArchive = 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'])
.where('archive.buildId = :buildId', { buildId: build.id }) .where('archive.buildId = :buildId', { buildId: build.id })
.andWhere('archive.role = :fullRole', { fullRole: ArchiveType.Full }) .andWhere('archive.role != :partRole', { partRole: ArchiveType.Part })
.andWhere('archive.files @> :requestedFiles', { requestedFiles })
.orderBy('archive.size', 'ASC')
.limit(1) .limit(1)
.getOne(); .getOne();
if (smallestSingleArchive) {
packagePlans.push([smallestSingleArchive]);
}
let archives = allPartArchives; if (bestUpdateArchive) {
if (!allPartArchives.length || (fullArchive && this.getCostOfArchives([fullArchive]) <= this.getCostOfArchives(allPartArchives))) { console.log(5);
archives = [fullArchive]; // Plan 3: use single update archive + part archives for remaining files
const remainingPartArchives = this.pickArchives(allPossiblePartArchives, remainingFiles);
if (remainingPartArchives.length) {
packagePlans.push([bestUpdateArchive, ...remainingPartArchives]);
}
} }
console.log(6);
const archives = _.minBy(packagePlans, (plan) => this.getCostOfArchives(plan));
console.log(archives);
await this.mirror.lookForArchivesMirror(archives); await this.mirror.lookForArchivesMirror(archives);
return { return {
cdnUrl: this.cdnUrl, cdnUrl: this.cdnUrl,
......
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