Merged PR 711: Repositoryロック対応
## 概要 [Task3523: Repositoryロック対応](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3523) LicensesRepository - allocateLicense 割当先ユーザ取得しロックする処理を追加 WorkflowRepository - createtWorkflows authorの存在確認時にロックを追加 - updatetWorkflows authorの存在確認時にロックを追加 UserGroup&UserGroupMemberのロックを追加 AccountsRepository - updateAccountInfo プライマリ/セカンダリ管理者ユーザーの存在チェックのロック (行ロック横展開1で修正されていた) TasksRepository - create タスクの所有者の存在確認とロックを追加 - checkout 対象ユーザの存在確認とロックを追加 - changeCheckoutPermission 対象ユーザの存在確認とロックを追加 UserGroupsRepository - createTypistGroup 対象ユーザ達のロックを追加 - updateTypistGroup 対象ユーザ達のロックを追加 ## レビューポイント ラフスケッチの、 ``` 競合ケース E-3. Typistが削除条件判定を行った直後に、チェックアウト候補に削除ユーザーが含まれるTypistGroupが割り当てられる TypistGroupに割り当たっている時点で削除条件を満たさないので、このケースはないはず ``` ここは未対応でよい認識か。 ## 動作確認状況 - ローカルで確認 ## 補足 - 相談、参考資料などがあれば
This commit is contained in:
parent
6d6eee91e0
commit
e877942175
@ -39,6 +39,8 @@ import {
|
||||
updateEntity,
|
||||
} from '../../common/repository';
|
||||
import { Context } from '../../common/log';
|
||||
import { User } from '../users/entity/user.entity';
|
||||
import { UserNotFoundError } from '../users/errors/types';
|
||||
|
||||
@Injectable()
|
||||
export class LicensesRepositoryService {
|
||||
@ -559,6 +561,19 @@ export class LicensesRepositoryService {
|
||||
accountId: number,
|
||||
): Promise<void> {
|
||||
await this.dataSource.transaction(async (entityManager) => {
|
||||
// 対象ユーザの存在チェック
|
||||
const userRepo = entityManager.getRepository(User);
|
||||
const user = await userRepo.findOne({
|
||||
where: {
|
||||
id: userId,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (!user) {
|
||||
throw new UserNotFoundError(`User not exist. userId: ${userId}`);
|
||||
}
|
||||
|
||||
const licenseRepo = entityManager.getRepository(License);
|
||||
const licenseAllocationHistoryRepo = entityManager.getRepository(
|
||||
LicenseAllocationHistory,
|
||||
|
||||
@ -48,6 +48,7 @@ import {
|
||||
deleteEntity,
|
||||
} from '../../common/repository';
|
||||
import { Context } from '../../common/log';
|
||||
import { UserNotFoundError } from '../users/errors/types';
|
||||
|
||||
@Injectable()
|
||||
export class TasksRepositoryService {
|
||||
@ -167,6 +168,20 @@ export class TasksRepositoryService {
|
||||
permittedSourceStatus: TaskStatus[],
|
||||
): Promise<void> {
|
||||
await this.dataSource.transaction(async (entityManager) => {
|
||||
// 対象ユーザの存在確認
|
||||
const userRepo = entityManager.getRepository(User);
|
||||
const user = await userRepo.findOne({
|
||||
where: {
|
||||
id: user_id,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (!user) {
|
||||
throw new TypistUserNotFoundError(
|
||||
`Typist user not exists. user_id:${user_id}`,
|
||||
);
|
||||
}
|
||||
const taskRepo = entityManager.getRepository(Task);
|
||||
// 指定した音声ファイルIDに紐づくTaskの中でStatusが[Uploaded,Inprogress,Pending]であるものを取得
|
||||
const task = await taskRepo.findOne({
|
||||
@ -846,6 +861,22 @@ export class TasksRepositoryService {
|
||||
|
||||
const createdEntity = await this.dataSource.transaction(
|
||||
async (entityManager) => {
|
||||
// タスクの所有者の存在確認
|
||||
const userRepo = entityManager.getRepository(User);
|
||||
const user = await userRepo.findOne({
|
||||
where: {
|
||||
id: owner_user_id,
|
||||
account_id: account_id,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (!user) {
|
||||
throw new UserNotFoundError(
|
||||
`User not exists. owner_user_id:${owner_user_id}`,
|
||||
);
|
||||
}
|
||||
|
||||
const audioFileRepo = entityManager.getRepository(AudioFile);
|
||||
const newAudioFile = audioFileRepo.create(audioFile);
|
||||
const savedAudioFile = await insertEntity(
|
||||
@ -967,6 +998,7 @@ export class TasksRepositoryService {
|
||||
deleted_at: IsNull(),
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
// idはユニークであるため取得件数の一致でユーザーの存在を確認
|
||||
if (typistUserIds.length !== userRecords.length) {
|
||||
|
||||
@ -123,6 +123,7 @@ export class UserGroupsRepositoryService {
|
||||
email_verified: true,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (userRecords.length !== typistIds.length) {
|
||||
throw new TypistIdInvalidError(
|
||||
@ -189,6 +190,7 @@ export class UserGroupsRepositoryService {
|
||||
email_verified: true,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (userRecords.length !== typistIds.length) {
|
||||
throw new TypistIdInvalidError(
|
||||
|
||||
@ -87,6 +87,7 @@ export class WorkflowsRepositoryService {
|
||||
const author = await userRepo.findOne({
|
||||
where: { account_id: accountId, id: authorId, email_verified: true },
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (!author) {
|
||||
throw new UserNotFoundError(
|
||||
@ -227,6 +228,37 @@ export class WorkflowsRepositoryService {
|
||||
): Promise<void> {
|
||||
return await this.dataSource.transaction(async (entityManager) => {
|
||||
const workflowRepo = entityManager.getRepository(Workflow);
|
||||
// authorの存在確認
|
||||
const userRepo = entityManager.getRepository(User);
|
||||
const author = await userRepo.findOne({
|
||||
where: { account_id: accountId, id: authorId, email_verified: true },
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (!author) {
|
||||
throw new UserNotFoundError(
|
||||
`author not found or email not verified. id: ${authorId}`,
|
||||
);
|
||||
}
|
||||
|
||||
// ルーティング候補ユーザーの存在確認
|
||||
const typistIds = typists.flatMap((typist) =>
|
||||
typist.typistId ? [typist.typistId] : [],
|
||||
);
|
||||
const typistUsers = await userRepo.find({
|
||||
where: {
|
||||
account_id: accountId,
|
||||
id: In(typistIds),
|
||||
email_verified: true,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (typistUsers.length !== typistIds.length) {
|
||||
throw new UserNotFoundError(
|
||||
`typist not found or email not verified. ids: ${typistIds}`,
|
||||
);
|
||||
}
|
||||
|
||||
// ワークフローの存在確認
|
||||
const targetWorkflow = await workflowRepo.findOne({
|
||||
@ -239,18 +271,6 @@ export class WorkflowsRepositoryService {
|
||||
);
|
||||
}
|
||||
|
||||
// authorの存在確認
|
||||
const userRepo = entityManager.getRepository(User);
|
||||
const author = await userRepo.findOne({
|
||||
where: { account_id: accountId, id: authorId, email_verified: true },
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
});
|
||||
if (!author) {
|
||||
throw new UserNotFoundError(
|
||||
`author not found or email not verified. id: ${authorId}`,
|
||||
);
|
||||
}
|
||||
|
||||
// worktypeの存在確認
|
||||
if (worktypeId !== undefined) {
|
||||
const worktypeRepo = entityManager.getRepository(Worktype);
|
||||
@ -279,24 +299,6 @@ export class WorkflowsRepositoryService {
|
||||
}
|
||||
}
|
||||
|
||||
// ルーティング候補ユーザーの存在確認
|
||||
const typistIds = typists.flatMap((typist) =>
|
||||
typist.typistId ? [typist.typistId] : [],
|
||||
);
|
||||
const typistUsers = await userRepo.find({
|
||||
where: {
|
||||
account_id: accountId,
|
||||
id: In(typistIds),
|
||||
email_verified: true,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
});
|
||||
if (typistUsers.length !== typistIds.length) {
|
||||
throw new UserNotFoundError(
|
||||
`typist not found or email not verified. ids: ${typistIds}`,
|
||||
);
|
||||
}
|
||||
|
||||
// ルーティング候補ユーザーグループの存在確認
|
||||
const groupIds = typists.flatMap((typist) => {
|
||||
return typist.typistGroupId ? [typist.typistGroupId] : [];
|
||||
@ -305,6 +307,7 @@ export class WorkflowsRepositoryService {
|
||||
const typistGroups = await userGroupRepo.find({
|
||||
where: { account_id: accountId, id: In(groupIds) },
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (typistGroups.length !== groupIds.length) {
|
||||
throw new TypistGroupNotExistError(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user