saito.k 36716dc408 Merged PR 547: 音声ファイルアップロード完了API修正(repository実装含む)
## 概要
[Task2971: 音声ファイルアップロード完了API修正(repository実装含む)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2971)

- 音声ファイルアップロード完了API修正
  - 自動ルーティング処理を追加
    - authorIDとworktypeの組み合わせでワークフロー(ルーティングルール)を取得し、そのワークフローに従って、タスクのチェックアウト候補を設定する。
  - チェックアウト候補に設定したユーザーに対して通知を行う処理を追加

## レビューポイント
- 自動ルーティング処理を実装しているメソッドのメソッド名はこれでよいか
  - ほかに思いつかなかったので
- AudioOptionItemのentityの定義はあっている?
  - がタスクにあるaudio_file_idに紐づいている感じになっている
- 自動ルーティング処理で失敗したときの挙動は認識あっているか
  - エラーログだけ出してAPIとしては成功とする
- テストケースは足りているか
- 古い形式で記述されていたタスク作成のテストを新しい形で作り替えたが、反映漏れている部分はあるか

## UIの変更
- Before/Afterのスクショなど
- スクショ置き場

## 動作確認状況
- ローカルで確認

## 補足
- 相談、参考資料などがあれば
2023-11-07 08:48:53 +00:00

111 lines
3.2 KiB
TypeScript

import {
CACHE_MANAGER,
Inject,
Injectable,
InternalServerErrorException,
Logger,
} from '@nestjs/common';
import { Cache } from 'cache-manager';
@Injectable()
export class RedisService {
private readonly logger = new Logger(RedisService.name);
constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}
/**
* キーに対応する値を設定する。
* @param key キー
* @param value キーに対応する値
* @param ttl 有効期限(秒)
*/
async set(
key: string,
value: unknown,
ttl?: number | undefined,
): Promise<void> {
try {
// cache-manager-redis-store がcache-managerのset形式と不一致な値の渡し方を採用しているため、
// @types/cache-managerのset形式を使用すると、redisに値が保存されない。
// そのため、{ttl : ttl} をany型として渡すことで、強引にcache-manager-redis-storeのsetを使用する。
// https://www.npmjs.com/package/cache-manager
await this.cacheManager.set(key, value, { ttl: ttl } as any);
} catch (error) {
this.logger.error(error);
}
}
/**
* 複数のキーとそのキーに対応する値を設定する。
* @template T
* @param records キーとそのキーに対応する値のペアの配列
* @param ttl 有効期限(秒)
*/
async mset<T>(
records: { key: string; value: T }[],
ttl?: number | undefined,
): Promise<void> {
try {
// cache-manager-redis-store のmsetが壊れており、利用できないため、
// 一つずつsetする。
for await (const record of records) {
await this.set(record.key, record.value, ttl);
}
} catch (error) {
this.logger.error(error);
}
}
/**
* キーに対応する値を取得する。
* @template T
* @param key キー
* @returns キーに対応する値
*/
async get<T>(key: string): Promise<T | undefined> {
try {
const value = await this.cacheManager.get<T>(key);
return value;
} catch (error) {
this.logger.error(error);
return undefined;
}
}
/**
* 複数のキーに対して、対応する値を取得する。
* キーに対応する値がなかった場合、valueにはnullがセットされる。
* @param keys キーの配列
* @returns キーとそのキーに対応する値のペアの配列
*/
async mget<T>(keys: string[]): Promise<{ key: string; value: T | null }[]> {
if (keys.length === 0) return []; // mget操作は0件の時エラーとなるため、0件は特別扱いする
try {
const records = await this.cacheManager.store.mget(...keys);
// getで取得した順序とKeysの順序は一致するはずなので、indexを利用してペアになるよう加工する
return records.map((record, index) => {
return {
key: keys[index],
value: record ? (record as T) : null,
};
});
} catch (error) {
this.logger.error(error);
return [];
}
}
/**
* キーに対応する値を削除する。
* @param key キー
*/
async del(key: string): Promise<void> {
try {
await this.cacheManager.del(key);
} catch (error) {
this.logger.error(error);
}
}
}