Merged PR 827: CSV出力が失敗したときに手動で起動するためのFunctionsを作成

## 概要
[Task3860: CSV出力が失敗したときに手動で起動するためのFunctionsを作成](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3860)

- analysisLicensesについて手動で起動できる処理(analysisLicensesManualRetry)を追加しました
- データベース接続の初期化処理について共通化しました

## レビューポイント
- 特筆する部分はありません

## UIの変更
- 無し

## クエリの変更
- 無し

## 動作確認状況
- ローカルでpostmanからリクエストを行うことで起動できることを確認
- 行った修正がデグレを発生させていないことを確認できるか
  - 具体的にどのような確認をしたか
    - unit testが通ることを確認
    - タイマを暫定的に1分にして、ローカル環境で各タイマ処理が正常終了することを確認(DBアクセスが全処理行われることを確認)

## 補足
- 相談、参考資料などがあれば
This commit is contained in:
masaaki 2024-03-12 04:55:04 +00:00
parent 43561f237e
commit 340aa73bde
6 changed files with 149 additions and 105 deletions

View File

@ -0,0 +1,41 @@
import { User, UserArchive } from "../entity/user.entity";
import { Account, AccountArchive } from "../entity/account.entity";
import {
License,
LicenseAllocationHistory,
LicenseAllocationHistoryArchive,
LicenseArchive,
} from "../entity/license.entity";
import { InvocationContext, } from "@azure/functions";
import { DataSource} from "typeorm";
export async function initializeDataSource(
context: InvocationContext
): Promise<DataSource> {
try {
const datasource = new DataSource({
type: "mysql",
host: process.env.DB_HOST,
port: Number(process.env.DB_PORT),
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME_CCB,
entities: [
User,
UserArchive,
Account,
AccountArchive,
License,
LicenseArchive,
LicenseAllocationHistory,
LicenseAllocationHistoryArchive,
],
});
await datasource.initialize();
return datasource;
} catch (e) {
context.log("Database initialize failed.");
context.error(e);
throw e;
}
}

View File

@ -1,12 +1,21 @@
import { app, InvocationContext, Timer } from "@azure/functions";
import { DataSource, Between } from "typeorm";
import * as dotenv from "dotenv";
import { User, UserArchive } from "../entity/user.entity";
import { Account, AccountArchive } from "../entity/account.entity";
import { License, LicenseAllocationHistory, LicenseArchive, LicenseAllocationHistoryArchive } from "../entity/license.entity";
import {
License,
LicenseAllocationHistory,
LicenseArchive,
LicenseAllocationHistoryArchive,
} from "../entity/license.entity";
import { BlobstorageService } from "../blobstorage/blobstorage.service";
import { LICENSE_ALLOCATED_STATUS, TIERS, SWITCH_FROM_TYPE } from "../constants";
import {
LICENSE_ALLOCATED_STATUS,
TIERS,
SWITCH_FROM_TYPE,
} from "../constants";
import { DateWithDayEndTime } from "../common/types/types";
import { initializeDataSource } from "../database/initializeDataSource";
/**
*
@ -17,9 +26,8 @@ export async function analysisLicensesProcessing(
context: InvocationContext,
targetMonthYYYYMM: string,
datasource: DataSource,
blobstorageService: BlobstorageService,
blobstorageService: BlobstorageService
) {
try {
context.log("[IN]analysisLicensesProcessing");
@ -41,7 +49,6 @@ export async function analysisLicensesProcessing(
}
}
/**
* DBから取得する処理
* @param context
@ -66,10 +73,10 @@ export async function getBaseData(
},
relations: {
user: true,
userArchive: true
userArchive: true,
},
});
// 第五階層が保持する有効なライセンスを取得
const licenseRepository = datasource.getRepository(License);
// 現在時刻を起点とした23:59:59の日付
@ -185,12 +192,13 @@ export async function getBaseDataFromDeletedAccounts(
// 第五階層のアカウントとユーザーを取得する
// 第五のアカウントを取得
const accountArchiveRepository = datasource.getRepository(AccountArchive);
const deletedAccountsAndUsersFromTier5 = await accountArchiveRepository.find({
where: {
tier: TIERS.TIER5,
},
relations: { userArchive: true},
});
const deletedAccountsAndUsersFromTier5 =
await accountArchiveRepository.find({
where: {
tier: TIERS.TIER5,
},
relations: { userArchive: true },
});
// 第五階層が保持する有効なライセンスを取得
const licenseArchiveRepository = datasource.getRepository(LicenseArchive);
@ -296,7 +304,6 @@ export async function getBaseDataFromDeletedAccounts(
}
}
/**
* Azure Functionの関数として呼び出される処理
* @param myTimer
@ -310,34 +317,8 @@ export async function analysisLicenses(
dotenv.config({ path: ".env" });
dotenv.config({ path: ".env.local", override: true });
let datasource: DataSource;
try {
try {
datasource = new DataSource({
type: "mysql",
host: process.env.DB_HOST,
port: Number(process.env.DB_PORT),
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME_CCB,
entities: [
User,
Account,
License,
LicenseAllocationHistory,
UserArchive,
AccountArchive,
LicenseArchive,
LicenseAllocationHistoryArchive,
],
});
await datasource.initialize();
} catch (e) {
context.log("database initialize failed.");
context.error(e);
throw e;
}
const datasource = await initializeDataSource(context);
const blobstorageService = new BlobstorageService();
try {
@ -365,11 +346,10 @@ export async function analysisLicenses(
}
app.timer("analysisLicenses", {
schedule: "0 0 0 1 * *",
schedule: "0 0 0 1 * *",
handler: analysisLicenses,
});
type BaseData = {
// 存在するアカウントの集計元情報
accountsAndUsersFromTier5: Account[];

View File

@ -0,0 +1,76 @@
import {
HttpRequest,
HttpResponseInit,
InvocationContext,
app,
HttpMethod,
} from "@azure/functions";
import { analysisLicensesProcessing } from "./analysisLicenses";
import * as dotenv from "dotenv";
import { BlobstorageService } from "../blobstorage/blobstorage.service";
import { initializeDataSource } from "../database/initializeDataSource";
import { HTTP_METHODS, HTTP_STATUS_CODES } from "../constants";
export async function analysisLicensesManualRetry(
req: HttpRequest,
context: InvocationContext
): Promise<HttpResponseInit> {
context.log(req);
try {
if (req.method === HTTP_METHODS.POST) {
context.log("[IN]analysisLicensesManualRetry");
dotenv.config({ path: ".env" });
dotenv.config({ path: ".env.local", override: true });
const datasource = await initializeDataSource(context);
const blobstorageService = new BlobstorageService();
try {
// 現在の日付より、先月の年月をYYYYMM形式で取得
const currentDate = new Date();
currentDate.setMonth(currentDate.getMonth() - 1);
const year = currentDate.getFullYear();
const month = (currentDate.getMonth() + 1).toString().padStart(2, "0"); // 月は0から始まるため+1する
const formattedDate = `${year}${month}`;
await analysisLicensesProcessing(
context,
formattedDate,
datasource,
blobstorageService
);
return {
status: HTTP_STATUS_CODES.OK,
body: "analysisLicensesProcessing has been triggered.",
};
} catch (e) {
context.log("analysisLicensesProcessing failed.");
context.error(e);
throw e;
}
} else {
context.log(`Please use the POST method. method = [${req.method}]`);
return {
status: HTTP_STATUS_CODES.BAD_REQUEST,
body: `Please use the POST method. method = [${req.method}]`,
};
}
} catch (e) {
context.log("analysisLicensesManualRetry failed.");
context.error(e);
return {
status: HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
body: "analysisLicensesManualRetry failed.",
};
} finally {
context.log("[OUT]analysisLicensesManualRetry");
}
}
// httpトリガは定時処理licenseAutoAllocationの異常時の手動再実行用
app.http("analysisLicensesManualRetry", {
methods: [HTTP_METHODS.POST as HttpMethod],
authLevel: "function",
handler: analysisLicensesManualRetry,
});

View File

@ -1,6 +1,5 @@
import { app, InvocationContext, Timer } from "@azure/functions";
import { Between, DataSource, In, IsNull, MoreThan, Not } from "typeorm";
import { User } from "../entity/user.entity";
import { Account } from "../entity/account.entity";
import {
ADB2C_SIGN_IN_TYPE,
@ -29,6 +28,7 @@ import {
SEND_COMPLETE_PREFIX,
DONE,
} from "../common/cache/constants";
import { initializeDataSource } from "../database/initializeDataSource";
export async function licenseAlertProcessing(
context: InvocationContext,
@ -99,24 +99,7 @@ export async function licenseAlert(
dotenv.config({ path: ".env" });
dotenv.config({ path: ".env.local", override: true });
let datasource: DataSource;
try {
datasource = new DataSource({
type: "mysql",
host: process.env.DB_HOST,
port: Number(process.env.DB_PORT),
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME_CCB,
entities: [User, Account, License],
});
await datasource.initialize();
} catch (e) {
context.log("database initialize failed.");
context.error(e);
throw e;
}
const datasource = await initializeDataSource(context);
let redisClient: RedisClient;
try {
// redis接続

View File

@ -16,6 +16,7 @@ import {
DateWithZeroTime,
NewAllocatedLicenseExpirationDate,
} from "../common/types/types";
import { initializeDataSource } from "../database/initializeDataSource";
export async function licenseAutoAllocationProcessing(
context: InvocationContext,
@ -77,24 +78,7 @@ export async function licenseAutoAllocation(
context.log("[IN]licenseAutoAllocation");
dotenv.config({ path: ".env" });
dotenv.config({ path: ".env.local", override: true });
let datasource: DataSource;
try {
datasource = new DataSource({
type: "mysql",
host: process.env.DB_HOST,
port: Number(process.env.DB_PORT),
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME_CCB,
entities: [User, Account, License, LicenseAllocationHistory],
});
await datasource.initialize();
} catch (e) {
context.log("database initialize failed.");
context.error(e);
throw e;
}
const datasource = await initializeDataSource(context);
await licenseAutoAllocationProcessing(context, datasource);
} catch (e) {
context.log("licenseAutoAllocation failed.");

View File

@ -7,11 +7,8 @@ import {
} from "@azure/functions";
import { licenseAutoAllocationProcessing } from "./licenseAutoAllocation";
import * as dotenv from "dotenv";
import { DataSource } from "typeorm";
import { User } from "../entity/user.entity";
import { Account } from "../entity/account.entity";
import { License, LicenseAllocationHistory } from "../entity/license.entity";
import { HTTP_METHODS, HTTP_STATUS_CODES } from "../constants";
import { initializeDataSource } from "../database/initializeDataSource";
export async function licenseAutoAllocationManualRetry(
req: HttpRequest,
@ -40,24 +37,7 @@ export async function licenseAutoAllocationManualRetry(
context.log("[IN]licenseAutoAllocationManualRetry");
dotenv.config({ path: ".env" });
dotenv.config({ path: ".env.local", override: true });
let datasource: DataSource;
try {
datasource = new DataSource({
type: "mysql",
host: process.env.DB_HOST,
port: Number(process.env.DB_PORT),
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME_CCB,
entities: [User, Account, License, LicenseAllocationHistory],
});
await datasource.initialize();
} catch (e) {
context.log("database initialize failed.");
context.error(e);
throw e;
}
const datasource = await initializeDataSource(context);
await licenseAutoAllocationProcessing(context, datasource, dateToTrigger);
context.log("Automatic license allocation has been triggered.");
return {
@ -65,10 +45,10 @@ export async function licenseAutoAllocationManualRetry(
body: "Automatic license allocation has been triggered.",
};
} else {
context.log("Please use the POST method.");
context.log(`Please use the POST method. Requested method = [${req.method}]`);
return {
status: HTTP_STATUS_CODES.BAD_REQUEST,
body: "Please use the POST method.",
body: `Please use the POST method. method = [${req.method}]`,
};
}
} catch (e) {