rowChecker增加了exception类型定义,允许通过环境变量disable modi对行的锁定

This commit is contained in:
Xu Chang 2025-01-07 08:08:33 +08:00
parent 39c7cef89f
commit bea9638dfc
6 changed files with 87 additions and 79 deletions

View File

@ -44,7 +44,7 @@ function translateCheckerInAsyncContext(checker, schema) {
};
}
case 'row': {
const { filter, errMsg, inconsistentRows } = checker;
const { filter, errMsg, err, inconsistentRows } = checker;
const fn = (async ({ operation }, context, option) => {
const { filter: operationFilter, data, action, bornAt } = operation;
const filter2 = typeof filter === 'function' ? await filter(operation, context, option) : filter;
@ -66,7 +66,7 @@ function translateCheckerInAsyncContext(checker, schema) {
dontCollect: true,
blockTrigger: true,
});
const e = new Exception_1.OakRowInconsistencyException(errMsg);
const e = new (err || (Exception_1.OakRowInconsistencyException))(errMsg);
e.addData(entity2, rows2, context.getSchema());
throw e;
}
@ -81,7 +81,7 @@ function translateCheckerInAsyncContext(checker, schema) {
dontCollect: true,
blockTrigger: true,
}); */
const e = new Exception_1.OakRowInconsistencyException(errMsg);
const e = new (err || (Exception_1.OakRowInconsistencyException))(errMsg);
// e.addData(entity, rows2);
throw e;
}

View File

@ -73,42 +73,79 @@ function createModiRelatedCheckers(schema) {
continue;
}
const restActions = (0, lodash_1.difference)(actions, action_1.appendOnlyActions);
checkers.push({
entity,
action: restActions,
type: 'row',
filter: (operation, context, option) => {
/**
* 只有一种情况可以通过即当前是在更新和active的modi所指向同一个父更新对象
* 比如先申请了一个公司company再申请修改公司companyApplyment这时所有的active modi都指向此条companyApplyment
* 这时
* 1再申请一条新的修改公司create companyApplyment应被拒绝
* 2申请修改原来的companyApplyment(update companyApplyment)可以通过
* 3在其它路径上对此company对象进行直接的更新应被拒绝
*/
if (option.modiParentEntity) {
const { modiParentEntity, modiParentId } = option;
(0, assert_1.default)(modiParentEntity);
(0, assert_1.default)(modiParentId);
if (!process.env.OAK_DISABLE_MODI_LOCK) {
checkers.push({
entity,
action: restActions,
type: 'row',
filter: (operation, context, option) => {
/**
* 只有一种情况可以通过即当前是在更新和active的modi所指向同一个父更新对象
* 比如先申请了一个公司company再申请修改公司companyApplyment这时所有的active modi都指向此条companyApplyment
* 这时
* 1再申请一条新的修改公司create companyApplyment应被拒绝
* 2申请修改原来的companyApplyment(update companyApplyment)可以通过
* 3在其它路径上对此company对象进行直接的更新应被拒绝
*/
if (option.modiParentEntity) {
const { modiParentEntity, modiParentId } = option;
(0, assert_1.default)(modiParentEntity);
(0, assert_1.default)(modiParentId);
return {
modiEntity$entity: {
'#sqp': 'not in',
entity,
modi: {
iState: 'active',
$or: [
{
entity: {
$ne: modiParentEntity,
},
},
{
entityId: {
$ne: modiParentId,
},
}
],
},
},
/* id: {
$nin: {
entity: 'modiEntity',
data: {
entityId: 1,
},
filter: {
entity,
modi: {
iState: 'active',
$or: [
{
entity: {
$ne: modiParentEntity,
},
},
{
entityId: {
$ne: modiParentId,
},
}
],
},
},
},
} */
};
}
return {
modiEntity$entity: {
'#sqp': 'not in',
entity,
modi: {
iState: 'active',
$or: [
{
entity: {
$ne: modiParentEntity,
},
},
{
entityId: {
$ne: modiParentId,
},
}
],
},
}
},
/* id: {
$nin: {
@ -120,50 +157,15 @@ function createModiRelatedCheckers(schema) {
entity,
modi: {
iState: 'active',
$or: [
{
entity: {
$ne: modiParentEntity,
},
},
{
entityId: {
$ne: modiParentId,
},
}
],
},
}
},
},
} */
};
}
return {
modiEntity$entity: {
'#sqp': 'not in',
entity,
modi: {
iState: 'active',
}
},
/* id: {
$nin: {
entity: 'modiEntity',
data: {
entityId: 1,
},
filter: {
entity,
modi: {
iState: 'active',
}
},
},
} */
};
},
errMsg: '您请求的更新对象上还有正在申请的更新,请等该更新结束后再试',
});
},
errMsg: '您请求的更新对象上还有正在申请的更新,请等该更新结束后再试',
});
}
}
return checkers;
}

3
lib/types/Auth.d.ts vendored
View File

@ -1,4 +1,4 @@
import { CascadeActionAuth, CascadeRelationAuth, ActionOnRemove, SyncOrAsync } from ".";
import { CascadeActionAuth, CascadeRelationAuth, ActionOnRemove, SyncOrAsync, OakException } from ".";
import { AsyncContext } from "../store/AsyncRowStore";
import { SyncContext } from "../store/SyncRowStore";
import { EntityDict, OperateOption, SelectOption } from "../types/Entity";
@ -25,6 +25,7 @@ export type RowChecker<ED extends EntityDict & BaseEntityDict, T extends keyof E
action: ED[T]['Action'] | Array<ED[T]['Action']>;
filter: ED[T]['Selection']['filter'] | ((operation: ED[T]['Operation'] | ED[T]['Selection'], context: Cxt, option: OperateOption | SelectOption) => SyncOrAsync<ED[T]['Selection']['filter']>);
errMsg?: string;
err?: new (msg?: string) => OakException<ED>;
inconsistentRows?: {
entity: keyof ED;
selection: (filter?: ED[T]['Selection']['filter']) => ED[keyof ED]['Selection'];

View File

@ -56,7 +56,7 @@ export function translateCheckerInAsyncContext<
};
}
case 'row': {
const { filter, errMsg, inconsistentRows } = checker;
const { filter, errMsg, err, inconsistentRows } = checker;
const fn = (async ({ operation }, context, option) => {
const { filter: operationFilter, data, action, bornAt } = operation;
const filter2 = typeof filter === 'function' ? await filter(operation, context, option) : filter;
@ -79,7 +79,7 @@ export function translateCheckerInAsyncContext<
blockTrigger: true,
});
const e = new OakRowInconsistencyException<ED>(errMsg);
const e = new (err || OakRowInconsistencyException<ED>)(errMsg);
e.addData(entity2, rows2, context.getSchema());
throw e;
}
@ -95,7 +95,7 @@ export function translateCheckerInAsyncContext<
blockTrigger: true,
}); */
const e = new OakRowInconsistencyException<ED>(errMsg);
const e = new (err || OakRowInconsistencyException<ED>)(errMsg);
// e.addData(entity, rows2);
throw e;
}

View File

@ -80,6 +80,9 @@ export function createModiRelatedCheckers<ED extends EntityDict & BaseEntityDict
continue;
}
const restActions = difference(actions, appendOnlyActions);
if (!process.env.OAK_DISABLE_MODI_LOCK) {
checkers.push({
entity,
action: restActions as any,
@ -170,7 +173,8 @@ export function createModiRelatedCheckers<ED extends EntityDict & BaseEntityDict
};
},
errMsg: '您请求的更新对象上还有正在申请的更新,请等该更新结束后再试',
})
});
}
}
return checkers;

View File

@ -1,4 +1,4 @@
import { CascadeActionAuth, CascadeRelationAuth, ActionOnRemove, SyncOrAsync } from ".";
import { CascadeActionAuth, CascadeRelationAuth, ActionOnRemove, SyncOrAsync, OakException } from ".";
import { AsyncContext } from "../store/AsyncRowStore";
import { SyncContext } from "../store/SyncRowStore";
import { EntityDict, OperateOption, SelectOption } from "../types/Entity";
@ -30,6 +30,7 @@ export type RowChecker<ED extends EntityDict & BaseEntityDict, T extends keyof E
(operation: ED[T]['Operation'] | ED[T]['Selection'], context: Cxt, option: OperateOption | SelectOption) => SyncOrAsync<ED[T]['Selection']['filter']>
); // 对行的额外检查条件
errMsg?: string;
err?: new (msg?: string) => OakException<ED>;
inconsistentRows?: { // 因为这里的限制不一定在本row上如果不传这个exception则默认返回本row上的exception
entity: keyof ED;
selection: (filter?: ED[T]['Selection']['filter']) => ED[keyof ED]['Selection'];