Обновлённая система кеширования и чистка кода.

This commit is contained in:
2024-09-26 01:37:44 +04:00
parent 811feff173
commit cd9dc319eb
7 changed files with 95 additions and 165 deletions

View File

@@ -14,7 +14,7 @@ import {
import { toNormalString, trimAll } from "../../../utility/string.util";
type InternalId = { row: number; column: number; name: string };
type InternalDay = InternalId & { lessons: Array<InternalId> };
type InternalDay = InternalId;
export class ScheduleParseResult {
etag: string;
@@ -107,7 +107,17 @@ export class ScheduleParser {
++row;
}
days.push({ row: row, column: 0, name: dayName, lessons: [] });
const dayMonthIdx = /[А-Яа-я]+\s(\d+)\.\d+\.\d+/.exec(
trimAll(dayName),
);
if (dayMonthIdx === null) continue;
days.push({
row: row,
column: 0,
name: dayName,
});
if (
days.length > 2 &&
@@ -130,15 +140,6 @@ export class ScheduleParser {
const downloadData = await this.xlsDownloader.downloadXLS();
if (downloadData.updateRequired && downloadData.etag.length === 0) {
return {
updateRequired: true,
groups: [],
etag: "",
affectedDays: [],
};
}
if (
!downloadData.new &&
this.lastResult &&
@@ -152,8 +153,6 @@ export class ScheduleParser {
return this.lastResult;
}
console.debug("Чтение кешированного XLS документа...");
const workBook = XLSX.read(downloadData.fileData);
const workSheet = workBook.Sheets[workBook.SheetNames[0]];

View File

@@ -5,7 +5,10 @@ import {
} from "./xls-downloader.base";
import axios from "axios";
import { JSDOM } from "jsdom";
import { NotAcceptableException } from "@nestjs/common";
import {
NotAcceptableException,
ServiceUnavailableException,
} from "@nestjs/common";
export class BasicXlsDownloader extends XlsDownloaderBase {
cache: XlsDownloaderResult | null = null;
@@ -85,13 +88,9 @@ export class BasicXlsDownloader extends XlsDownloaderBase {
return this.getCachedXLS();
if (!this.preparedData) {
return {
updateRequired: true,
etag: "",
new: true,
fileData: new ArrayBuffer(1),
updateDate: "",
};
throw new ServiceUnavailableException(
"Отсутствует начальная ссылка на скачивание!",
);
}
// noinspection Annotator

View File

@@ -10,6 +10,7 @@ import {
import { AuthGuard } from "../auth/auth.guard";
import { ScheduleService } from "./schedule.service";
import {
CacheStatusDto,
GroupScheduleDto,
GroupScheduleRequestDto,
ScheduleDto,
@@ -97,4 +98,17 @@ export class ScheduleController {
): Promise<void> {
return await this.scheduleService.updateSiteMainPage(siteMainPageDto);
}
@ApiExtraModels(CacheStatusDto)
@ApiOperation({
summary: "Получение информации о кеше",
tags: ["schedule", "cache"],
})
@ApiOkResponse({ description: "Получение данных прошло успешно" })
@ResultDto(CacheStatusDto)
@HttpCode(HttpStatus.OK)
@Get("cache-status")
getCacheStatus(): CacheStatusDto {
return this.scheduleService.getCacheStatus();
}
}

View File

@@ -1,9 +1,4 @@
import {
Inject,
Injectable,
NotFoundException,
ServiceUnavailableException,
} from "@nestjs/common";
import { Inject, Injectable, NotFoundException } from "@nestjs/common";
import {
ScheduleParser,
ScheduleParseResult,
@@ -11,6 +6,7 @@ import {
import { BasicXlsDownloader } from "./internal/xls-downloader/basic-xls-downloader";
import { XlsDownloaderCacheMode } from "./internal/xls-downloader/xls-downloader.base";
import {
CacheStatusDto,
GroupDto,
GroupScheduleDto,
ScheduleDto,
@@ -20,6 +16,7 @@ import {
import { Cache, CACHE_MANAGER } from "@nestjs/cache-manager";
import { instanceToPlain } from "class-transformer";
import { cacheGetOrFill } from "../utility/cache.util";
import * as crypto from "crypto";
@Injectable()
export class ScheduleService {
@@ -30,24 +27,33 @@ export class ScheduleService {
),
);
private lastCacheUpdate: Date = new Date(0);
private cacheUpdatedAt: Date = new Date(0);
private cacheHash: string = "0000000000000000000000000000000000000000";
private lastChangedDays: Array<Array<number>> = [];
constructor(@Inject(CACHE_MANAGER) private readonly cacheManager: Cache) {}
getCacheStatus(): CacheStatusDto {
return {
cacheHash: this.cacheHash,
cacheUpdateRequired:
(Date.now() - this.cacheUpdatedAt.valueOf()) / 1000 / 60 >= 5,
};
}
private async getSourceSchedule(): Promise<ScheduleParseResult> {
return cacheGetOrFill(this.cacheManager, "sourceSchedule", async () => {
this.lastCacheUpdate = new Date();
const schedule = await this.scheduleParser.getSchedule();
schedule.groups = ScheduleService.toObject(
schedule.groups,
) as Array<GroupDto>;
if (schedule.updateRequired && schedule.etag.length === 0)
throw new ServiceUnavailableException(
"Отсутствует начальная ссылка на скачивание!",
);
this.cacheUpdatedAt = new Date();
this.cacheHash = crypto
.createHash("sha1")
.update(schedule.etag)
.digest("hex");
return schedule;
});
@@ -62,24 +68,26 @@ export class ScheduleService {
}
async getSchedule(): Promise<ScheduleDto> {
return cacheGetOrFill(this.cacheManager, "schedule", async () => {
const sourceSchedule = await this.getSourceSchedule();
return cacheGetOrFill(
this.cacheManager,
"schedule",
async (): Promise<ScheduleDto> => {
const sourceSchedule = await this.getSourceSchedule();
for (const groupName in sourceSchedule.affectedDays) {
const affectedDays = sourceSchedule.affectedDays[groupName];
for (const groupName in sourceSchedule.affectedDays) {
const affectedDays = sourceSchedule.affectedDays[groupName];
if (affectedDays?.length !== 0)
this.lastChangedDays[groupName] = affectedDays;
}
if (affectedDays?.length !== 0)
this.lastChangedDays[groupName] = affectedDays;
}
return {
updatedAt: this.lastCacheUpdate,
groups: ScheduleService.toObject(sourceSchedule.groups),
etag: sourceSchedule.etag,
lastChangedDays: this.lastChangedDays,
updateRequired: sourceSchedule.updateRequired,
};
});
return {
updatedAt: this.cacheUpdatedAt,
groups: ScheduleService.toObject(sourceSchedule.groups),
lastChangedDays: this.lastChangedDays,
};
},
);
}
async getGroup(group: string): Promise<GroupScheduleDto> {
@@ -92,11 +100,9 @@ export class ScheduleService {
}
return {
updatedAt: this.lastCacheUpdate,
updatedAt: this.cacheUpdatedAt,
group: schedule.groups[group],
etag: schedule.etag,
lastChangedDays: this.lastChangedDays[group] ?? [],
updateRequired: schedule.updateRequired,
};
}
@@ -127,5 +133,6 @@ export class ScheduleService {
.setPreparedData(siteMainPageDto.mainPage);
await this.cacheManager.reset();
await this.getSourceSchedule();
}
}