湯本 開 ac3d523c0e Merged PR 826: Azure Functions実装(音声ファイル削除)
## 概要
[Task3880: Azure Functions実装(音声ファイル削除)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3880)

- 自動音声ファイル削除を実装
- 上記のテストを実装
- テストにMySQLを使用する仕組みを導入

## レビューポイント
- テストケースは十分か
- テスト内容は妥当か
- developにデプロイする前の動作確認・ユニットテストとして十分か

## クエリの変更
- 新規処理のため、既存からの変更はなし

## 動作確認状況
- DBが空の状態でローカル環境で実行し、0件削除のログが出ることを確認
  - 削除対象が正しいか等はdevelopでチェック予定
- 行った修正がデグレを発生させていないことを確認できるか
  - 既存処理の変更はなし
2024-03-19 07:36:03 +00:00

130 lines
3.1 KiB
TypeScript

import { Logger, QueryRunner } from "typeorm";
import * as fs from "fs";
import * as path from "path";
interface IOutput {
initialize(): void;
write(message: string): void;
}
class ConsoleOutput implements IOutput {
initialize(): void {
// do nothing
}
write(message: string): void {
console.log(message);
}
}
class FileOutput implements IOutput {
private logPath = path.join("/app/dictation_function/.test", "logs");
private fileName = new Date().getTime();
initialize(): void {
if (!fs.existsSync(this.logPath)) {
fs.mkdirSync(this.logPath, { recursive: true });
}
}
write(message: string): void {
const logFile = path.join(this.logPath, `${this.fileName}.log`);
fs.appendFileSync(logFile, `${message}\n`);
}
}
class NoneOutput implements IOutput {
initialize(): void {
// do nothing
}
write(message: string): void {
// do nothing
}
}
export class TestLogger implements Logger {
out: IOutput;
constructor(output: "none" | "file" | "console") {
switch (output) {
case "none":
this.out = new NoneOutput();
break;
case "file":
this.out = new FileOutput();
break;
case "console":
this.out = new ConsoleOutput();
break;
default:
this.out = new NoneOutput();
break;
}
this.out.initialize();
}
private write(message: string): void {
this.out.write(message);
}
logQuery(query: string, parameters?: any[], queryRunner?: QueryRunner) {
const raw = `Query: ${query} -- Parameters: ${JSON.stringify(parameters)}`;
// ex: 2024-03-08T06:38:43.125Z を TIME という文字列に置換
const dateRemoved = raw.replace(
/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/g,
"TIME"
);
// ex: /* コメント内容 */ を /* コメント */ という文字列に置換
const commentRemoved = dateRemoved.replace(
/\/\*.*\*\//g,
"/* RequestID */"
);
// UUIDを固定文字列に置換する ex: 88a9c78e-115a-439c-9e23-731d649f0c27 を XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX という文字列に置換
const uuidRemoved = commentRemoved.replace(
/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/g,
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
);
this.write(uuidRemoved);
}
logQueryError(
error: string,
query: string,
parameters?: any[],
queryRunner?: QueryRunner
) {
this.write(
`ERROR: ${error} -- Query: ${query} -- Parameters: ${JSON.stringify(
parameters
)}`
);
}
logQuerySlow(
time: number,
query: string,
parameters?: any[],
queryRunner?: QueryRunner
) {
this.write(
`SLOW QUERY: ${time}ms -- Query: ${query} -- Parameters: ${JSON.stringify(
parameters
)}`
);
}
logSchemaBuild(message: string, queryRunner?: QueryRunner) {
this.write(`Schema Build: ${message}`);
}
logMigration(message: string, queryRunner?: QueryRunner) {
this.write(`Migration: ${message}`);
}
log(level: "log" | "info" | "warn", message: any, queryRunner?: QueryRunner) {
this.write(`${level.toUpperCase()}: ${message}`);
}
}