From 340aa73bde7f5c23e1fb1f123e1c628ab547c098 Mon Sep 17 00:00:00 2001 From: masaaki Date: Tue, 12 Mar 2024 04:55:04 +0000 Subject: [PATCH] =?UTF-8?q?Merged=20PR=20827:=20CSV=E5=87=BA=E5=8A=9B?= =?UTF-8?q?=E3=81=8C=E5=A4=B1=E6=95=97=E3=81=97=E3=81=9F=E3=81=A8=E3=81=8D?= =?UTF-8?q?=E3=81=AB=E6=89=8B=E5=8B=95=E3=81=A7=E8=B5=B7=E5=8B=95=E3=81=99?= =?UTF-8?q?=E3=82=8B=E3=81=9F=E3=82=81=E3=81=AEFunctions=E3=82=92=E4=BD=9C?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 概要 [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アクセスが全処理行われることを確認) ## 補足 - 相談、参考資料などがあれば --- .../src/database/initializeDataSource.ts | 41 ++++++++++ .../src/functions/analysisLicenses.ts | 68 ++++++----------- .../functions/analysisLicensesManualRetry.ts | 76 +++++++++++++++++++ .../src/functions/licenseAlert.ts | 21 +---- .../src/functions/licenseAutoAllocation.ts | 20 +---- .../licenseAutoAllocationManualRetry.ts | 28 +------ 6 files changed, 149 insertions(+), 105 deletions(-) create mode 100644 dictation_function/src/database/initializeDataSource.ts create mode 100644 dictation_function/src/functions/analysisLicensesManualRetry.ts diff --git a/dictation_function/src/database/initializeDataSource.ts b/dictation_function/src/database/initializeDataSource.ts new file mode 100644 index 0000000..e573669 --- /dev/null +++ b/dictation_function/src/database/initializeDataSource.ts @@ -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 { + 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; + } +} diff --git a/dictation_function/src/functions/analysisLicenses.ts b/dictation_function/src/functions/analysisLicenses.ts index 3d40276..e3d0c83 100644 --- a/dictation_function/src/functions/analysisLicenses.ts +++ b/dictation_function/src/functions/analysisLicenses.ts @@ -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[]; diff --git a/dictation_function/src/functions/analysisLicensesManualRetry.ts b/dictation_function/src/functions/analysisLicensesManualRetry.ts new file mode 100644 index 0000000..d21c61b --- /dev/null +++ b/dictation_function/src/functions/analysisLicensesManualRetry.ts @@ -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 { + 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, +}); diff --git a/dictation_function/src/functions/licenseAlert.ts b/dictation_function/src/functions/licenseAlert.ts index a11af0d..da9f1d7 100644 --- a/dictation_function/src/functions/licenseAlert.ts +++ b/dictation_function/src/functions/licenseAlert.ts @@ -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接続 diff --git a/dictation_function/src/functions/licenseAutoAllocation.ts b/dictation_function/src/functions/licenseAutoAllocation.ts index a1ece5d..9313a6a 100644 --- a/dictation_function/src/functions/licenseAutoAllocation.ts +++ b/dictation_function/src/functions/licenseAutoAllocation.ts @@ -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."); diff --git a/dictation_function/src/functions/licenseAutoAllocationManualRetry.ts b/dictation_function/src/functions/licenseAutoAllocationManualRetry.ts index c34de46..f01542e 100644 --- a/dictation_function/src/functions/licenseAutoAllocationManualRetry.ts +++ b/dictation_function/src/functions/licenseAutoAllocationManualRetry.ts @@ -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) {