Funtion側もデータ型の変更に合わせる修正をいたしました。 動作確認状況 ``` Test Suites: 8 passed, 8 total Tests: 46 passed, 46 total Snapshots: 0 total Time: 85.851 s Ran all test suites. ```
1631 lines
49 KiB
TypeScript
1631 lines
49 KiB
TypeScript
import * as dotenv from "dotenv";
|
||
import { InvocationContext } from "@azure/functions";
|
||
import { DataSource } from "typeorm";
|
||
import { truncateAllTable } from "./common/init";
|
||
import {
|
||
deleteAudioFilesProcessing,
|
||
deleteRecords,
|
||
getProcessTargets,
|
||
} from "../functions/deleteAudioFiles";
|
||
import {
|
||
getAudioFiles,
|
||
getAudioOptionItems,
|
||
getTasks,
|
||
makeManyTestTasks,
|
||
makeTestAccount,
|
||
makeTestTask,
|
||
} from "./common/utility";
|
||
import { MANUAL_RECOVERY_REQUIRED, TASK_STATUS } from "../constants";
|
||
import { TestLogger } from "./common/logger";
|
||
import { AudioFile } from "../entity/audio_file.entity";
|
||
import { QueryDeepPartialEntity } from "typeorm/query-builder/QueryPartialEntity";
|
||
import { AudioBlobStorageService } from "../blobstorage/audioBlobStorage.service";
|
||
import { User, UserArchive } from "../entity/user.entity";
|
||
import { Account, AccountArchive } from "../entity/account.entity";
|
||
import { Task } from "../entity/task.entity";
|
||
import {
|
||
License,
|
||
LicenseAllocationHistory,
|
||
LicenseAllocationHistoryArchive,
|
||
LicenseArchive,
|
||
} from "../entity/license.entity";
|
||
import { AudioOptionItem } from "../entity/audio_option_item.entity";
|
||
import { TestInvocationContext } from "./common/context";
|
||
|
||
describe("getProcessTargets | 削除対象を特定するQueryが正常に動作するか確認する", () => {
|
||
let source: DataSource | null = null;
|
||
beforeAll(async () => {
|
||
dotenv.config({ path: ".env" });
|
||
dotenv.config({ path: ".env.test", override: true });
|
||
if (source == null) {
|
||
source = await (async () => {
|
||
const s = new DataSource({
|
||
type: "mysql",
|
||
host: "test_mysql_db",
|
||
port: 3306,
|
||
username: "user",
|
||
password: "password",
|
||
database: "odms",
|
||
entities: [__dirname + "/../../**/*.entity{.ts,.js}"],
|
||
synchronize: false, // trueにすると自動的にmigrationが行われるため注意
|
||
logger: new TestLogger("none"),
|
||
logging: true,
|
||
});
|
||
return await s.initialize();
|
||
})();
|
||
}
|
||
});
|
||
|
||
beforeEach(async () => {
|
||
if (source) {
|
||
await truncateAllTable(source);
|
||
}
|
||
});
|
||
|
||
afterAll(async () => {
|
||
await source?.destroy();
|
||
source = null;
|
||
});
|
||
|
||
it("ファイル削除対象のタスクが存在しない場合、空の配列が取得できる", async () => {
|
||
if (!source) fail();
|
||
|
||
// 2024/02/29 00:00:00を"今"とする
|
||
const now = new Date("2024-02-29T00:00:00Z");
|
||
|
||
const { account, admin } = await makeTestAccount(source, {
|
||
file_retention_days: 2,
|
||
auto_file_delete: true,
|
||
});
|
||
|
||
{
|
||
// ファイル削除対象のタスクが存在しない場合、空の配列が取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([]);
|
||
}
|
||
|
||
// ちょうど2日前(削除対象外)のタスクを作成
|
||
await makeTestTask(source, account.id, admin.id, "case01", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job01",
|
||
finished_at: new Date("2024-02-27T00:00:00Z"),
|
||
});
|
||
// ちょうど1日前(削除対象外)のタスクを作成
|
||
await makeTestTask(source, account.id, admin.id, "case02", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job02",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
|
||
{
|
||
// ファイル削除対象のタスクが存在しない場合、空の配列が取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([]);
|
||
}
|
||
});
|
||
|
||
it("ファイル削除対象のタスク情報のみを取得できる(対象となる期限切れのタスク情報のみが取れる)", async () => {
|
||
if (!source) fail();
|
||
|
||
// 2024/02/29 00:00:00を"今"とする
|
||
const now = new Date("2024-02-29T00:00:00Z");
|
||
|
||
const { account, admin } = await makeTestAccount(source, {
|
||
file_retention_days: 2,
|
||
auto_file_delete: true,
|
||
});
|
||
|
||
// ちょうど2日前(削除対象外)のタスクを作成
|
||
await makeTestTask(source, account.id, admin.id, "case01", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job01",
|
||
finished_at: new Date("2024-02-27T00:00:00Z"),
|
||
});
|
||
// ちょうど1日前(削除対象外)のタスクを作成
|
||
await makeTestTask(source, account.id, admin.id, "case02", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job02",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
// 2日と1秒前(削除対象)のタスクを作成
|
||
const { task, file } = await makeTestTask(
|
||
source,
|
||
account.id,
|
||
admin.id,
|
||
"case03",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job03",
|
||
finished_at: new Date("2024-02-26T23:59:59Z"),
|
||
}
|
||
);
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報1件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task.id,
|
||
audio_file_id: file.id,
|
||
raw_file_name: file.raw_file_name,
|
||
account_id: account.id,
|
||
country: account.country,
|
||
},
|
||
]);
|
||
}
|
||
|
||
// ちょうど3日前(削除対象)のタスクを作成
|
||
const { task: task2, file: file2 } = await makeTestTask(
|
||
source,
|
||
account.id,
|
||
admin.id,
|
||
"case04",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job04",
|
||
finished_at: new Date("2024-02-26T00:00:00Z"),
|
||
}
|
||
);
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報2件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task.id,
|
||
audio_file_id: file.id,
|
||
raw_file_name: file.raw_file_name,
|
||
account_id: account.id,
|
||
country: account.country,
|
||
},
|
||
{
|
||
id: task2.id,
|
||
audio_file_id: file2.id,
|
||
raw_file_name: file2.raw_file_name,
|
||
account_id: account.id,
|
||
country: account.country,
|
||
},
|
||
]);
|
||
}
|
||
|
||
// ちょうど1日前(削除対象外)のタスクを作成
|
||
await makeTestTask(source, account.id, admin.id, "case05", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job05",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報2件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task.id,
|
||
audio_file_id: file.id,
|
||
raw_file_name: file.raw_file_name,
|
||
account_id: account.id,
|
||
country: account.country,
|
||
},
|
||
{
|
||
id: task2.id,
|
||
audio_file_id: file2.id,
|
||
raw_file_name: file2.raw_file_name,
|
||
account_id: account.id,
|
||
country: account.country,
|
||
},
|
||
]);
|
||
}
|
||
|
||
// 100日と5時間前(削除対象)のタスクを作成
|
||
const { task: task3, file: file3 } = await makeTestTask(
|
||
source,
|
||
account.id,
|
||
admin.id,
|
||
"case06",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job06",
|
||
finished_at: new Date("2023-11-20T19:00:00Z"),
|
||
}
|
||
);
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報3件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task.id,
|
||
audio_file_id: file.id,
|
||
raw_file_name: file.raw_file_name,
|
||
account_id: account.id,
|
||
country: account.country,
|
||
},
|
||
{
|
||
id: task2.id,
|
||
audio_file_id: file2.id,
|
||
raw_file_name: file2.raw_file_name,
|
||
account_id: account.id,
|
||
country: account.country,
|
||
},
|
||
{
|
||
id: task3.id,
|
||
audio_file_id: file3.id,
|
||
raw_file_name: file3.raw_file_name,
|
||
account_id: account.id,
|
||
country: account.country,
|
||
},
|
||
]);
|
||
}
|
||
|
||
// 1日後(削除対象外。本来はミリ秒単位の未来方向の時刻違いを想定)のタスクを作成
|
||
await makeTestTask(source, account.id, admin.id, "case07", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job07",
|
||
finished_at: new Date("2024-03-01T00:00:00Z"),
|
||
});
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報3件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task.id,
|
||
audio_file_id: file.id,
|
||
raw_file_name: file.raw_file_name,
|
||
account_id: account.id,
|
||
country: account.country,
|
||
},
|
||
{
|
||
id: task2.id,
|
||
audio_file_id: file2.id,
|
||
raw_file_name: file2.raw_file_name,
|
||
account_id: account.id,
|
||
country: account.country,
|
||
},
|
||
{
|
||
id: task3.id,
|
||
audio_file_id: file3.id,
|
||
raw_file_name: file3.raw_file_name,
|
||
account_id: account.id,
|
||
country: account.country,
|
||
},
|
||
]);
|
||
}
|
||
});
|
||
|
||
it("ファイル削除対象のタスク情報のみを取得できる(auto_file_delete=falseのアカウントの情報のタスク情報は取れない)", async () => {
|
||
if (!source) fail();
|
||
|
||
// 2024/02/29 00:00:00を"今"とする
|
||
const now = new Date("2024-02-29T00:00:00Z");
|
||
|
||
// auto_file_deleteがtrueののアカウントを作成
|
||
const { account: account01, admin: admin01 } = await makeTestAccount(
|
||
source,
|
||
{
|
||
file_retention_days: 2,
|
||
auto_file_delete: true,
|
||
}
|
||
);
|
||
|
||
// auto_file_deleteがfalseののアカウントを作成
|
||
const { account: account02, admin: admin02 } = await makeTestAccount(
|
||
source,
|
||
{
|
||
file_retention_days: 2,
|
||
auto_file_delete: false,
|
||
}
|
||
);
|
||
|
||
// ちょうど2日前(削除対象外)のタスクを作成
|
||
await makeTestTask(source, account01.id, admin01.id, "case01", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job01",
|
||
finished_at: new Date("2024-02-27T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account02.id, admin02.id, "case01", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job01",
|
||
finished_at: new Date("2024-02-27T00:00:00Z"),
|
||
});
|
||
|
||
// ちょうど1日前(削除対象外)のタスクを作成
|
||
await makeTestTask(source, account01.id, admin01.id, "case02", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job02",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account02.id, admin02.id, "case02", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job02",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
|
||
// 2日と1秒前(削除対象)のタスクを作成
|
||
const { task, file } = await makeTestTask(
|
||
source,
|
||
account01.id,
|
||
admin01.id,
|
||
"case03",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job03",
|
||
finished_at: new Date("2024-02-26T23:59:59Z"),
|
||
}
|
||
);
|
||
await makeTestTask(source, account02.id, admin02.id, "case03", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job03",
|
||
finished_at: new Date("2024-02-26T23:59:59Z"),
|
||
});
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報1件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task.id,
|
||
audio_file_id: file.id,
|
||
raw_file_name: file.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
]);
|
||
}
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報1件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task.id,
|
||
audio_file_id: file.id,
|
||
raw_file_name: file.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
]);
|
||
}
|
||
|
||
// ちょうど3日前(削除対象)のタスクを作成
|
||
const { task: task2, file: file2 } = await makeTestTask(
|
||
source,
|
||
account01.id,
|
||
admin01.id,
|
||
"case04",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job04",
|
||
finished_at: new Date("2024-02-26T00:00:00Z"),
|
||
}
|
||
);
|
||
await makeTestTask(source, account02.id, admin02.id, "case04", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job04",
|
||
finished_at: new Date("2024-02-26T00:00:00Z"),
|
||
});
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報2件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task.id,
|
||
audio_file_id: file.id,
|
||
raw_file_name: file.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task2.id,
|
||
audio_file_id: file2.id,
|
||
raw_file_name: file2.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
]);
|
||
}
|
||
|
||
// ちょうど1日前(削除対象外)のタスクを作成
|
||
await makeTestTask(source, account01.id, admin01.id, "case05", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job05",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account02.id, admin02.id, "case05", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job05",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報2件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task.id,
|
||
audio_file_id: file.id,
|
||
raw_file_name: file.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task2.id,
|
||
audio_file_id: file2.id,
|
||
raw_file_name: file2.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
]);
|
||
}
|
||
|
||
// 100日と5時間前(削除対象)のタスクを作成
|
||
const { task: task3, file: file3 } = await makeTestTask(
|
||
source,
|
||
account01.id,
|
||
admin01.id,
|
||
"case06",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job06",
|
||
finished_at: new Date("2023-11-20T19:00:00Z"),
|
||
}
|
||
);
|
||
await makeTestTask(source, account02.id, admin02.id, "case06", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job06",
|
||
finished_at: new Date("2023-11-20T19:00:00Z"),
|
||
});
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報3件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task.id,
|
||
audio_file_id: file.id,
|
||
raw_file_name: file.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task2.id,
|
||
audio_file_id: file2.id,
|
||
raw_file_name: file2.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task3.id,
|
||
audio_file_id: file3.id,
|
||
raw_file_name: file3.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
]);
|
||
}
|
||
|
||
// 1日後(削除対象外。本来はミリ秒単位の未来方向の時刻違いを想定)のタスクを作成
|
||
await makeTestTask(source, account01.id, admin01.id, "case07", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job07",
|
||
finished_at: new Date("2024-03-01T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account02.id, admin02.id, "case07", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job07",
|
||
finished_at: new Date("2024-03-01T00:00:00Z"),
|
||
});
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報3件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task.id,
|
||
audio_file_id: file.id,
|
||
raw_file_name: file.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task2.id,
|
||
audio_file_id: file2.id,
|
||
raw_file_name: file2.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task3.id,
|
||
audio_file_id: file3.id,
|
||
raw_file_name: file3.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
]);
|
||
}
|
||
});
|
||
|
||
it("ファイル削除対象のタスク情報のみを取得できる(auto_file_delete=trueのアカウントの情報のタスク情報は全て取れる)", async () => {
|
||
if (!source) fail();
|
||
|
||
// 2024/02/29 00:00:00を"今"とする
|
||
const now = new Date("2024-02-29T00:00:00Z");
|
||
|
||
// auto_file_deleteがtrueののアカウントを作成
|
||
const { account: account01, admin: admin01 } = await makeTestAccount(
|
||
source,
|
||
{
|
||
file_retention_days: 2,
|
||
auto_file_delete: true,
|
||
}
|
||
);
|
||
const { account: account02, admin: admin02 } = await makeTestAccount(
|
||
source,
|
||
{
|
||
file_retention_days: 2,
|
||
auto_file_delete: true,
|
||
}
|
||
);
|
||
// auto_file_deleteがfalseののアカウントを作成
|
||
const { account: account03, admin: admin03 } = await makeTestAccount(
|
||
source,
|
||
{
|
||
file_retention_days: 2,
|
||
auto_file_delete: false,
|
||
}
|
||
);
|
||
|
||
// ちょうど2日前(削除対象外)のタスクを作成
|
||
await makeTestTask(source, account01.id, admin01.id, "case01", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job01",
|
||
finished_at: new Date("2024-02-27T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account02.id, admin02.id, "case01", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job01",
|
||
finished_at: new Date("2024-02-27T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account03.id, admin03.id, "case01", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job01",
|
||
finished_at: new Date("2024-02-27T00:00:00Z"),
|
||
});
|
||
|
||
// ちょうど1日前(削除対象外)のタスクを作成
|
||
await makeTestTask(source, account01.id, admin01.id, "case02", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job02",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account02.id, admin02.id, "case02", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job02",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account03.id, admin03.id, "case02", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job02",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
|
||
// 2日と1秒前(削除対象)のタスクを作成
|
||
const { task: task01, file: file01 } = await makeTestTask(
|
||
source,
|
||
account01.id,
|
||
admin01.id,
|
||
"case03",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job03",
|
||
finished_at: new Date("2024-02-26T23:59:59Z"),
|
||
}
|
||
);
|
||
const { task: task02, file: file02 } = await makeTestTask(
|
||
source,
|
||
account02.id,
|
||
admin02.id,
|
||
"case03",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job03",
|
||
finished_at: new Date("2024-02-26T23:59:59Z"),
|
||
}
|
||
);
|
||
await makeTestTask(source, account03.id, admin03.id, "case03", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job03",
|
||
finished_at: new Date("2024-02-26T23:59:59Z"),
|
||
});
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報2件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task01.id,
|
||
audio_file_id: file01.id,
|
||
raw_file_name: file01.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task02.id,
|
||
audio_file_id: file02.id,
|
||
raw_file_name: file02.raw_file_name,
|
||
account_id: account02.id,
|
||
country: account02.country,
|
||
},
|
||
]);
|
||
}
|
||
|
||
// ちょうど3日前(削除対象)のタスクを作成
|
||
const { task: task03, file: file03 } = await makeTestTask(
|
||
source,
|
||
account01.id,
|
||
admin01.id,
|
||
"case04",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job04",
|
||
finished_at: new Date("2024-02-26T00:00:00Z"),
|
||
}
|
||
);
|
||
const { task: task04, file: file04 } = await makeTestTask(
|
||
source,
|
||
account02.id,
|
||
admin02.id,
|
||
"case04",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job04",
|
||
finished_at: new Date("2024-02-26T00:00:00Z"),
|
||
}
|
||
);
|
||
await makeTestTask(source, account03.id, admin03.id, "case04", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job04",
|
||
finished_at: new Date("2024-02-26T00:00:00Z"),
|
||
});
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報4件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task01.id,
|
||
audio_file_id: file01.id,
|
||
raw_file_name: file01.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task02.id,
|
||
audio_file_id: file02.id,
|
||
raw_file_name: file02.raw_file_name,
|
||
account_id: account02.id,
|
||
country: account02.country,
|
||
},
|
||
{
|
||
id: task03.id,
|
||
audio_file_id: file03.id,
|
||
raw_file_name: file03.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task04.id,
|
||
audio_file_id: file04.id,
|
||
raw_file_name: file04.raw_file_name,
|
||
account_id: account02.id,
|
||
country: account02.country,
|
||
},
|
||
]);
|
||
}
|
||
|
||
// ちょうど1日前(削除対象外)のタスクを作成
|
||
await makeTestTask(source, account01.id, admin01.id, "case05", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job05",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account02.id, admin02.id, "case05", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job05",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account03.id, admin03.id, "case05", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job05",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報4件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task01.id,
|
||
audio_file_id: file01.id,
|
||
raw_file_name: file01.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task02.id,
|
||
audio_file_id: file02.id,
|
||
raw_file_name: file02.raw_file_name,
|
||
account_id: account02.id,
|
||
country: account02.country,
|
||
},
|
||
{
|
||
id: task03.id,
|
||
audio_file_id: file03.id,
|
||
raw_file_name: file03.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task04.id,
|
||
audio_file_id: file04.id,
|
||
raw_file_name: file04.raw_file_name,
|
||
account_id: account02.id,
|
||
country: account02.country,
|
||
},
|
||
]);
|
||
}
|
||
|
||
// 100日と5時間前(削除対象)のタスクを作成
|
||
const { task: task05, file: file05 } = await makeTestTask(
|
||
source,
|
||
account01.id,
|
||
admin01.id,
|
||
"case06",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job06",
|
||
finished_at: new Date("2023-11-20T19:00:00Z"),
|
||
}
|
||
);
|
||
const { task: task06, file: file06 } = await makeTestTask(
|
||
source,
|
||
account02.id,
|
||
admin02.id,
|
||
"case06",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job06",
|
||
finished_at: new Date("2023-11-20T19:00:00Z"),
|
||
}
|
||
);
|
||
await makeTestTask(source, account03.id, admin03.id, "case06", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job06",
|
||
finished_at: new Date("2023-11-20T19:00:00Z"),
|
||
});
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報6件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task01.id,
|
||
audio_file_id: file01.id,
|
||
raw_file_name: file01.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task02.id,
|
||
audio_file_id: file02.id,
|
||
raw_file_name: file02.raw_file_name,
|
||
account_id: account02.id,
|
||
country: account02.country,
|
||
},
|
||
{
|
||
id: task03.id,
|
||
audio_file_id: file03.id,
|
||
raw_file_name: file03.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task04.id,
|
||
audio_file_id: file04.id,
|
||
raw_file_name: file04.raw_file_name,
|
||
account_id: account02.id,
|
||
country: account02.country,
|
||
},
|
||
{
|
||
id: task05.id,
|
||
audio_file_id: file05.id,
|
||
raw_file_name: file05.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task06.id,
|
||
audio_file_id: file06.id,
|
||
raw_file_name: file06.raw_file_name,
|
||
account_id: account02.id,
|
||
country: account02.country,
|
||
},
|
||
]);
|
||
}
|
||
|
||
// 1日後(削除対象外。本来はミリ秒単位の未来方向の時刻違いを想定)のタスクを作成
|
||
await makeTestTask(source, account01.id, admin01.id, "case07", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job07",
|
||
finished_at: new Date("2024-03-01T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account02.id, admin02.id, "case07", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job07",
|
||
finished_at: new Date("2024-03-01T00:00:00Z"),
|
||
});
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報6件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task01.id,
|
||
audio_file_id: file01.id,
|
||
raw_file_name: file01.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task02.id,
|
||
audio_file_id: file02.id,
|
||
raw_file_name: file02.raw_file_name,
|
||
account_id: account02.id,
|
||
country: account02.country,
|
||
},
|
||
{
|
||
id: task03.id,
|
||
audio_file_id: file03.id,
|
||
raw_file_name: file03.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task04.id,
|
||
audio_file_id: file04.id,
|
||
raw_file_name: file04.raw_file_name,
|
||
account_id: account02.id,
|
||
country: account02.country,
|
||
},
|
||
{
|
||
id: task05.id,
|
||
audio_file_id: file05.id,
|
||
raw_file_name: file05.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task06.id,
|
||
audio_file_id: file06.id,
|
||
raw_file_name: file06.raw_file_name,
|
||
account_id: account02.id,
|
||
country: account02.country,
|
||
},
|
||
]);
|
||
}
|
||
});
|
||
});
|
||
|
||
describe("deleteRecords | 削除対象タスク等を削除できる", () => {
|
||
let source: DataSource | null = null;
|
||
beforeAll(async () => {
|
||
dotenv.config({ path: ".env" });
|
||
dotenv.config({ path: ".env.local", override: true });
|
||
if (source == null) {
|
||
source = await (async () => {
|
||
const s = new DataSource({
|
||
type: "mysql",
|
||
host: "test_mysql_db",
|
||
port: 3306,
|
||
username: "user",
|
||
password: "password",
|
||
database: "odms",
|
||
entities: [
|
||
User,
|
||
UserArchive,
|
||
Account,
|
||
AccountArchive,
|
||
Task,
|
||
AudioFile,
|
||
AudioOptionItem,
|
||
License,
|
||
LicenseArchive,
|
||
LicenseAllocationHistory,
|
||
LicenseAllocationHistoryArchive,
|
||
],
|
||
synchronize: false, // trueにすると自動的にmigrationが行われるため注意
|
||
logger: new TestLogger("none"),
|
||
logging: true,
|
||
});
|
||
return await s.initialize();
|
||
})();
|
||
}
|
||
});
|
||
|
||
beforeEach(async () => {
|
||
if (source) {
|
||
await truncateAllTable(source);
|
||
}
|
||
});
|
||
|
||
afterAll(async () => {
|
||
await source?.destroy();
|
||
source = null;
|
||
});
|
||
|
||
it("競合により存在しないタスクを削除しようとしても例外は発生せず、成功扱いとなる", async () => {
|
||
if (!source) fail();
|
||
|
||
await deleteRecords(source, [
|
||
{
|
||
id: 1,
|
||
audio_file_id: 1,
|
||
raw_file_name: "test",
|
||
account_id: 1,
|
||
country: "US",
|
||
},
|
||
]);
|
||
});
|
||
|
||
it("対象としたタスクやAudioFile等が削除される", async () => {
|
||
if (!source) fail();
|
||
|
||
// 2024/02/29 00:00:00を"今"とする
|
||
const now = new Date("2024-02-29T00:00:00Z");
|
||
|
||
// auto_file_deleteがtrueののアカウントを作成
|
||
const { account: account01, admin: admin01 } = await makeTestAccount(
|
||
source,
|
||
{
|
||
file_retention_days: 2,
|
||
auto_file_delete: true,
|
||
}
|
||
);
|
||
const { account: account02, admin: admin02 } = await makeTestAccount(
|
||
source,
|
||
{
|
||
file_retention_days: 2,
|
||
auto_file_delete: true,
|
||
}
|
||
);
|
||
// auto_file_deleteがfalseののアカウントを作成
|
||
const { account: account03, admin: admin03 } = await makeTestAccount(
|
||
source,
|
||
{
|
||
file_retention_days: 2,
|
||
auto_file_delete: false,
|
||
}
|
||
);
|
||
|
||
// ちょうど2日前(削除対象外)のタスクを作成
|
||
await makeTestTask(source, account01.id, admin01.id, "case01", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job01",
|
||
finished_at: new Date("2024-02-27T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account02.id, admin02.id, "case01", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job01",
|
||
finished_at: new Date("2024-02-27T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account03.id, admin03.id, "case01", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job01",
|
||
finished_at: new Date("2024-02-27T00:00:00Z"),
|
||
});
|
||
|
||
// ちょうど1日前(削除対象外)のタスクを作成
|
||
await makeTestTask(source, account01.id, admin01.id, "case02", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job02",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account02.id, admin02.id, "case02", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job02",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account03.id, admin03.id, "case02", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job02",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
|
||
// 2日と1秒前(削除対象)のタスクを作成
|
||
const { task: task01, file: file01 } = await makeTestTask(
|
||
source,
|
||
account01.id,
|
||
admin01.id,
|
||
"case03",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job03",
|
||
finished_at: new Date("2024-02-26T23:59:59Z"),
|
||
}
|
||
);
|
||
const { task: task02, file: file02 } = await makeTestTask(
|
||
source,
|
||
account02.id,
|
||
admin02.id,
|
||
"case03",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job03",
|
||
finished_at: new Date("2024-02-26T23:59:59Z"),
|
||
}
|
||
);
|
||
await makeTestTask(source, account03.id, admin03.id, "case03", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job03",
|
||
finished_at: new Date("2024-02-26T23:59:59Z"),
|
||
});
|
||
|
||
// ちょうど3日前(削除対象)のタスクを作成
|
||
const { task: task03, file: file03 } = await makeTestTask(
|
||
source,
|
||
account01.id,
|
||
admin01.id,
|
||
"case04",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job04",
|
||
finished_at: new Date("2024-02-26T00:00:00Z"),
|
||
}
|
||
);
|
||
const { task: task04, file: file04 } = await makeTestTask(
|
||
source,
|
||
account02.id,
|
||
admin02.id,
|
||
"case04",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job04",
|
||
finished_at: new Date("2024-02-26T00:00:00Z"),
|
||
}
|
||
);
|
||
await makeTestTask(source, account03.id, admin03.id, "case04", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job04",
|
||
finished_at: new Date("2024-02-26T00:00:00Z"),
|
||
});
|
||
|
||
// ちょうど1日前(削除対象外)のタスクを作成
|
||
await makeTestTask(source, account01.id, admin01.id, "case05", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job05",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account02.id, admin02.id, "case05", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job05",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account03.id, admin03.id, "case05", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job05",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
|
||
// 100日と5時間前(削除対象)のタスクを作成
|
||
const { task: task05, file: file05 } = await makeTestTask(
|
||
source,
|
||
account01.id,
|
||
admin01.id,
|
||
"case06",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job06",
|
||
finished_at: new Date("2023-11-20T19:00:00Z"),
|
||
}
|
||
);
|
||
const { task: task06, file: file06 } = await makeTestTask(
|
||
source,
|
||
account02.id,
|
||
admin02.id,
|
||
"case06",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job06",
|
||
finished_at: new Date("2023-11-20T19:00:00Z"),
|
||
}
|
||
);
|
||
await makeTestTask(source, account03.id, admin03.id, "case06", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job06",
|
||
finished_at: new Date("2023-11-20T19:00:00Z"),
|
||
});
|
||
|
||
// 1日後(削除対象外。本来はミリ秒単位の未来方向の時刻違いを想定)のタスクを作成
|
||
await makeTestTask(source, account01.id, admin01.id, "case07", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job07",
|
||
finished_at: new Date("2024-03-01T00:00:00Z"),
|
||
});
|
||
await makeTestTask(source, account02.id, admin02.id, "case07", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job07",
|
||
finished_at: new Date("2024-03-01T00:00:00Z"),
|
||
});
|
||
|
||
{
|
||
// ファイル削除対象のタスク情報6件のみを取得できる
|
||
const result = await getProcessTargets(source, now);
|
||
result.sort((a, b) => a.id - b.id);
|
||
expect(result).toEqual([
|
||
{
|
||
id: task01.id,
|
||
audio_file_id: file01.id,
|
||
raw_file_name: file01.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task02.id,
|
||
audio_file_id: file02.id,
|
||
raw_file_name: file02.raw_file_name,
|
||
account_id: account02.id,
|
||
country: account02.country,
|
||
},
|
||
{
|
||
id: task03.id,
|
||
audio_file_id: file03.id,
|
||
raw_file_name: file03.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task04.id,
|
||
audio_file_id: file04.id,
|
||
raw_file_name: file04.raw_file_name,
|
||
account_id: account02.id,
|
||
country: account02.country,
|
||
},
|
||
{
|
||
id: task05.id,
|
||
audio_file_id: file05.id,
|
||
raw_file_name: file05.raw_file_name,
|
||
account_id: account01.id,
|
||
country: account01.country,
|
||
},
|
||
{
|
||
id: task06.id,
|
||
audio_file_id: file06.id,
|
||
raw_file_name: file06.raw_file_name,
|
||
account_id: account02.id,
|
||
country: account02.country,
|
||
},
|
||
]);
|
||
|
||
{
|
||
// DB全体のレコードを確認
|
||
const tasks = await getTasks(source);
|
||
expect(tasks.length).toEqual(20);
|
||
const files = await getAudioFiles(source);
|
||
expect(files.length).toEqual(20);
|
||
const optionItems = await getAudioOptionItems(source);
|
||
expect(optionItems.length).toEqual(40);
|
||
}
|
||
|
||
// 削除対象のタスク情報を削除
|
||
await deleteRecords(source, result);
|
||
|
||
// 削除後のタスク情報を取得
|
||
const result2 = await getProcessTargets(source, now);
|
||
// 削除対象のタスク情報が削除されているので取得が0件になる
|
||
expect(result2).toEqual([]);
|
||
|
||
{
|
||
// DB全体のレコードを確認
|
||
// 削除対象外のタスク情報のみが残っている
|
||
const tasks = await getTasks(source);
|
||
expect(tasks.length).toEqual(14);
|
||
const files = await getAudioFiles(source);
|
||
expect(files.length).toEqual(14);
|
||
const optionItems = await getAudioOptionItems(source);
|
||
expect(optionItems.length).toEqual(28);
|
||
}
|
||
}
|
||
});
|
||
|
||
it("対象としたタスクやAudioFile等が大量に存在しても削除される", async () => {
|
||
if (!source) fail();
|
||
// 2024/02/29 00:00:00を"今"とする
|
||
const now = new Date("2024-02-29T00:00:00Z");
|
||
|
||
// "大量"の数を定義
|
||
const count = 10000;
|
||
|
||
// auto_file_deleteがtrueののアカウントを作成
|
||
const { account, admin } = await makeTestAccount(source, {
|
||
file_retention_days: 30,
|
||
auto_file_delete: true,
|
||
});
|
||
|
||
// ファイルを10000件作成
|
||
const createdFiles = [...Array(count).keys()].map(
|
||
(index): QueryDeepPartialEntity<AudioFile> => {
|
||
return {
|
||
account_id: account.id,
|
||
owner_user_id: admin.id,
|
||
url: `https://example.com/${index}`,
|
||
file_name: `test${index}.wav`,
|
||
raw_file_name: `test${index}.wav`,
|
||
author_id: "test_author",
|
||
work_type_id: "test_work_type",
|
||
started_at: new Date(),
|
||
duration: 0,
|
||
finished_at: new Date(),
|
||
uploaded_at: new Date(),
|
||
file_size: 1024,
|
||
priority: "01",
|
||
audio_format: "wav",
|
||
comment: `test_comment_${index}`,
|
||
deleted_at: new Date(),
|
||
is_encrypted: false,
|
||
};
|
||
}
|
||
);
|
||
|
||
// ファイルを元に、10年前に完了した扱いのタスクを作成
|
||
const finished_at = new Date("2014-02-26T23:59:59Z");
|
||
await makeManyTestTasks(source, createdFiles, finished_at);
|
||
|
||
{
|
||
// DB全体のレコードを確認
|
||
const tasks = await getTasks(source);
|
||
expect(tasks.length).toEqual(count);
|
||
|
||
const files = await getAudioFiles(source);
|
||
expect(files.length).toEqual(count);
|
||
|
||
const optionItems = await getAudioOptionItems(source);
|
||
expect(optionItems.length).toEqual(2 * count);
|
||
}
|
||
|
||
const result = await getProcessTargets(source, now);
|
||
expect(result.length).toEqual(count);
|
||
|
||
await deleteRecords(source, result);
|
||
|
||
{
|
||
// 削除後のタスク情報を取得
|
||
const tasks = await getTasks(source);
|
||
expect(tasks.length).toEqual(0);
|
||
|
||
const files = await getAudioFiles(source);
|
||
expect(files.length).toEqual(0);
|
||
|
||
const optionItems = await getAudioOptionItems(source);
|
||
expect(optionItems.length).toEqual(0);
|
||
}
|
||
}, 100000);
|
||
});
|
||
|
||
describe("deleteAudioFilesProcessing", () => {
|
||
let source: DataSource | null = null;
|
||
beforeAll(async () => {
|
||
dotenv.config({ path: ".env" });
|
||
dotenv.config({ path: ".env.test", override: true });
|
||
if (source == null) {
|
||
source = await (async () => {
|
||
const s = new DataSource({
|
||
type: "mysql",
|
||
host: "test_mysql_db",
|
||
port: 3306,
|
||
username: "user",
|
||
password: "password",
|
||
database: "odms",
|
||
entities: [__dirname + "/../../**/*.entity{.ts,.js}"],
|
||
synchronize: false, // trueにすると自動的にmigrationが行われるため注意
|
||
logger: new TestLogger("none"),
|
||
logging: true,
|
||
});
|
||
return await s.initialize();
|
||
})();
|
||
}
|
||
});
|
||
|
||
beforeEach(async () => {
|
||
if (source) {
|
||
await truncateAllTable(source);
|
||
}
|
||
});
|
||
|
||
afterAll(async () => {
|
||
await source?.destroy();
|
||
source = null;
|
||
});
|
||
|
||
it("BlobとDBの削除が正常に行われる", async () => {
|
||
if (!source) fail();
|
||
|
||
// 2024/02/29 00:00:00を"今"とする
|
||
const now = new Date("2024-02-29T00:00:00Z");
|
||
|
||
const { account: account01, admin: admin01 } = await makeTestAccount(
|
||
source,
|
||
{
|
||
file_retention_days: 2,
|
||
auto_file_delete: true,
|
||
}
|
||
);
|
||
|
||
const { account: account02, admin: admin02 } = await makeTestAccount(
|
||
source,
|
||
{
|
||
file_retention_days: 2,
|
||
auto_file_delete: true,
|
||
country: "JP",
|
||
}
|
||
);
|
||
|
||
// ちょうど2日前(削除対象外)のタスクを作成
|
||
await makeTestTask(source, account01.id, admin01.id, "case01", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job01",
|
||
finished_at: new Date("2024-02-27T00:00:00Z"),
|
||
});
|
||
// ちょうど1日前(削除対象外)のタスクを作成
|
||
await makeTestTask(source, account01.id, admin01.id, "case02", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job02",
|
||
finished_at: new Date("2024-02-28T00:00:00Z"),
|
||
});
|
||
// 2日と1秒前(削除対象)のタスクを作成
|
||
const { file: file1 } = await makeTestTask(
|
||
source,
|
||
account01.id,
|
||
admin01.id,
|
||
"case03",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job03",
|
||
finished_at: new Date("2024-02-26T23:59:59Z"),
|
||
}
|
||
);
|
||
// 2日と1秒前(削除対象)のタスクを作成
|
||
const { file: file2 } = await makeTestTask(
|
||
source,
|
||
account01.id,
|
||
admin01.id,
|
||
"case04",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job04",
|
||
finished_at: new Date("2024-02-26T23:59:59Z"),
|
||
}
|
||
);
|
||
|
||
// 2日と1秒前(削除対象)のタスクを作成
|
||
const { file: file3 } = await makeTestTask(
|
||
source,
|
||
account02.id,
|
||
admin02.id,
|
||
"case05",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job05",
|
||
finished_at: new Date("2024-02-26T23:59:59Z"),
|
||
}
|
||
);
|
||
|
||
const args: { accountId: number; fileName: string; country: string }[] = [];
|
||
const blobstorage = new AudioBlobStorageService();
|
||
Object.defineProperty(blobstorage, blobstorage.deleteFile.name, {
|
||
value: async (
|
||
context: InvocationContext,
|
||
accountId: number,
|
||
country: string,
|
||
fileName: string
|
||
): Promise<void> => {
|
||
args.push({ accountId, country, fileName });
|
||
},
|
||
writable: true,
|
||
});
|
||
|
||
{
|
||
// DB全体のレコードを確認
|
||
const tasks = await getTasks(source);
|
||
expect(tasks.length).toEqual(5);
|
||
const files = await getAudioFiles(source);
|
||
expect(files.length).toEqual(5);
|
||
const optionItems = await getAudioOptionItems(source);
|
||
expect(optionItems.length).toEqual(10);
|
||
}
|
||
|
||
const context = new InvocationContext();
|
||
await deleteAudioFilesProcessing(context, source, blobstorage, now);
|
||
|
||
// 想定通りの呼び出しが行われているか
|
||
{
|
||
const { accountId, country, fileName } = args[0];
|
||
expect(fileName).toEqual(file1.raw_file_name);
|
||
expect(accountId).toEqual(account01.id);
|
||
expect(country).toEqual(account01.country);
|
||
}
|
||
{
|
||
const { accountId, country, fileName } = args[1];
|
||
expect(fileName).toEqual(file2.raw_file_name);
|
||
expect(accountId).toEqual(account01.id);
|
||
expect(country).toEqual(account01.country);
|
||
}
|
||
{
|
||
const { accountId, country, fileName } = args[2];
|
||
expect(fileName).toEqual(file3.raw_file_name);
|
||
expect(accountId).toEqual(account02.id);
|
||
expect(country).toEqual(account02.country);
|
||
}
|
||
|
||
{
|
||
// DB全体のレコードを確認
|
||
const tasks = await getTasks(source);
|
||
expect(tasks.length).toEqual(2);
|
||
const files = await getAudioFiles(source);
|
||
expect(files.length).toEqual(2);
|
||
const optionItems = await getAudioOptionItems(source);
|
||
expect(optionItems.length).toEqual(4);
|
||
}
|
||
});
|
||
|
||
it("Blobの削除でエラーが発生した場合、アラーム発報用のログが出力される", async () => {
|
||
if (!source) fail();
|
||
|
||
// 2024/02/29 00:00:00を"今"とする
|
||
const now = new Date("2024-02-29T00:00:00Z");
|
||
|
||
const { account: account01, admin: admin01 } = await makeTestAccount(
|
||
source,
|
||
{
|
||
file_retention_days: 2,
|
||
auto_file_delete: true,
|
||
}
|
||
);
|
||
|
||
// 2日と1秒前(削除対象)のタスクを作成
|
||
const { file: file1 } = await makeTestTask(
|
||
source,
|
||
account01.id,
|
||
admin01.id,
|
||
"case03",
|
||
{
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job03",
|
||
finished_at: new Date("2024-02-26T23:59:59Z"),
|
||
}
|
||
);
|
||
|
||
const args: { accountId: number; fileName: string; country: string }[] = [];
|
||
const blobstorage = new AudioBlobStorageService();
|
||
Object.defineProperty(blobstorage, blobstorage.deleteFile.name, {
|
||
value: async (
|
||
context: InvocationContext,
|
||
accountId: number,
|
||
country: string,
|
||
fileName: string
|
||
): Promise<void> => {
|
||
throw new Error(
|
||
`delete blob failed. succeeded: ${false}, errorCode: ${"ERROR_CODE"}, date: ${"DATE"}`
|
||
);
|
||
},
|
||
writable: true,
|
||
});
|
||
|
||
{
|
||
// DB全体のレコードを確認
|
||
const tasks = await getTasks(source);
|
||
expect(tasks.length).toEqual(1);
|
||
const files = await getAudioFiles(source);
|
||
expect(files.length).toEqual(1);
|
||
const optionItems = await getAudioOptionItems(source);
|
||
expect(optionItems.length).toEqual(2);
|
||
}
|
||
|
||
const context = new TestInvocationContext();
|
||
await deleteAudioFilesProcessing(context, source, blobstorage, now);
|
||
|
||
const log = context
|
||
.getLogs()
|
||
.find((log) => log.includes(MANUAL_RECOVERY_REQUIRED));
|
||
expect(log).toBeDefined();
|
||
expect(log).toEqual(
|
||
`[MANUAL_RECOVERY_REQUIRED] file delete failed. target={"id":"1","audio_file_id":"1","account_id":"1","country":"US","raw_file_name":"testcase03.wav"}`
|
||
);
|
||
});
|
||
|
||
it("DBの削除でエラーが発生した場合、アラーム発報用のログが出力される", async () => {
|
||
if (!source) fail();
|
||
|
||
// 2024/02/29 00:00:00を"今"とする
|
||
const now = new Date("2024-02-29T00:00:00Z");
|
||
|
||
const { account: account01, admin: admin01 } = await makeTestAccount(
|
||
source,
|
||
{
|
||
file_retention_days: 2,
|
||
auto_file_delete: true,
|
||
}
|
||
);
|
||
|
||
// 2日と1秒前(削除対象)のタスクを作成
|
||
await makeTestTask(source, account01.id, admin01.id, "case03", {
|
||
status: TASK_STATUS.FINISHED,
|
||
job_number: "job03",
|
||
finished_at: new Date("2024-02-26T23:59:59Z"),
|
||
});
|
||
|
||
const args: { accountId: number; fileName: string; country: string }[] = [];
|
||
const blobstorage = new AudioBlobStorageService();
|
||
Object.defineProperty(blobstorage, blobstorage.deleteFile.name, {
|
||
value: async (
|
||
context: InvocationContext,
|
||
accountId: number,
|
||
country: string,
|
||
fileName: string
|
||
): Promise<void> => {
|
||
args.push({ accountId, country, fileName });
|
||
},
|
||
writable: true,
|
||
});
|
||
|
||
{
|
||
// DB全体のレコードを確認
|
||
const tasks = await getTasks(source);
|
||
expect(tasks.length).toEqual(1);
|
||
const files = await getAudioFiles(source);
|
||
expect(files.length).toEqual(1);
|
||
const optionItems = await getAudioOptionItems(source);
|
||
expect(optionItems.length).toEqual(2);
|
||
}
|
||
|
||
Object.defineProperty(source, "transaction", {
|
||
value: async () => {
|
||
throw new Error("transaction error");
|
||
},
|
||
writable: true,
|
||
});
|
||
|
||
const context = new TestInvocationContext();
|
||
|
||
await expect(
|
||
deleteAudioFilesProcessing(context, source, blobstorage, now)
|
||
).rejects.toThrow();
|
||
|
||
const log = context
|
||
.getLogs()
|
||
.find((log) => log.includes(MANUAL_RECOVERY_REQUIRED));
|
||
expect(log).toBeDefined();
|
||
expect(log).toEqual(
|
||
`[MANUAL_RECOVERY_REQUIRED] Failed to execute auto file deletion function. error=Error: transaction error`
|
||
);
|
||
});
|
||
});
|