import { BlobServiceClient, ContainerClient, StorageSharedKeyCredential, } from "@azure/storage-blob"; import { BLOB_STORAGE_REGION_AU, BLOB_STORAGE_REGION_EU, BLOB_STORAGE_REGION_US, } from "../constants"; import { InvocationContext } from "@azure/functions"; export class AudioBlobStorageService { private readonly sharedKeyCredentialUS: StorageSharedKeyCredential; private readonly sharedKeyCredentialEU: StorageSharedKeyCredential; private readonly sharedKeyCredentialAU: StorageSharedKeyCredential; private readonly blobServiceClientUS: BlobServiceClient; private readonly blobServiceClientEU: BlobServiceClient; private readonly blobServiceClientAU: BlobServiceClient; constructor() { if ( !process.env.STORAGE_ACCOUNT_ENDPOINT_US || !process.env.STORAGE_ACCOUNT_ENDPOINT_AU || !process.env.STORAGE_ACCOUNT_ENDPOINT_EU || !process.env.STORAGE_ACCOUNT_NAME_US || !process.env.STORAGE_ACCOUNT_KEY_US || !process.env.STORAGE_ACCOUNT_NAME_AU || !process.env.STORAGE_ACCOUNT_KEY_AU || !process.env.STORAGE_ACCOUNT_NAME_EU || !process.env.STORAGE_ACCOUNT_KEY_EU ) { throw new Error("Storage account information is missing"); } // リージョンごとのSharedKeyCredentialを生成 this.sharedKeyCredentialUS = new StorageSharedKeyCredential( process.env.STORAGE_ACCOUNT_NAME_US, process.env.STORAGE_ACCOUNT_KEY_US ); this.sharedKeyCredentialAU = new StorageSharedKeyCredential( process.env.STORAGE_ACCOUNT_NAME_AU, process.env.STORAGE_ACCOUNT_KEY_AU ); this.sharedKeyCredentialEU = new StorageSharedKeyCredential( process.env.STORAGE_ACCOUNT_NAME_EU, process.env.STORAGE_ACCOUNT_KEY_EU ); // Audioファイルの保存先のリージョンごとにBlobServiceClientを生成 this.blobServiceClientUS = new BlobServiceClient( process.env.STORAGE_ACCOUNT_ENDPOINT_US, this.sharedKeyCredentialUS ); this.blobServiceClientAU = new BlobServiceClient( process.env.STORAGE_ACCOUNT_ENDPOINT_AU, this.sharedKeyCredentialAU ); this.blobServiceClientEU = new BlobServiceClient( process.env.STORAGE_ACCOUNT_ENDPOINT_EU, this.sharedKeyCredentialEU ); } /** * 指定されたファイルを削除します。 * @param context * @param accountId * @param country * @param fileName * @returns file */ async deleteFile( context: InvocationContext, accountId: number, country: string, fileName: string ): Promise { context.log( `[IN] ${this.deleteFile.name} | params: { ` + `accountId: ${accountId} ` + `country: ${country} ` + `fileName: ${fileName} };` ); try { // 国に応じたリージョンでコンテナ名を指定してClientを取得 const containerClient = this.getContainerClient( context, accountId, country ); // コンテナ内のBlobパス名を指定してClientを取得 const blobClient = containerClient.getBlobClient(fileName); const { succeeded, errorCode, date } = await blobClient.deleteIfExists(); context.log( `succeeded: ${succeeded}, errorCode: ${errorCode}, date: ${date}` ); // 失敗時、Blobが存在しない場合以外はエラーとして例外をスローする // Blob不在の場合のエラーコードは「BlobNotFound」以下を参照 // https://learn.microsoft.com/ja-jp/rest/api/storageservices/blob-service-error-codes if (!succeeded && errorCode !== "BlobNotFound") { throw new Error( `delete blob failed. succeeded: ${succeeded}, errorCode: ${errorCode}, date: ${date}` ); } } catch (e) { context.error(`error=${e}`); throw e; } finally { context.log(`[OUT] ${this.deleteFile.name}`); } } /** * 指定してアカウントIDと国に応じたリージョンのコンテナクライアントを取得します。 * @param context * @param accountId * @param country * @returns */ private getContainerClient( context: InvocationContext, accountId: number, country: string ): ContainerClient { context.log( `[IN] ${this.getContainerClient.name} | params: { ` + `accountId: ${accountId}; country: ${country} };` ); const containerName = `account-${accountId}`; if (BLOB_STORAGE_REGION_US.includes(country)) { return this.blobServiceClientUS.getContainerClient(containerName); } else if (BLOB_STORAGE_REGION_AU.includes(country)) { return this.blobServiceClientAU.getContainerClient(containerName); } else if (BLOB_STORAGE_REGION_EU.includes(country)) { return this.blobServiceClientEU.getContainerClient(containerName); } else { throw new Error("invalid country"); } } }