增加了cacheInsesativeActions配置

This commit is contained in:
Xu Chang 2025-04-25 15:46:23 +08:00
parent ff67645f62
commit 22b66e824f
19 changed files with 56 additions and 43 deletions

View File

@ -113,7 +113,7 @@ export declare class Cache<ED extends EntityDict & BaseEntityDict> extends Featu
action: ED[T]['Action'];
data?: ED[T]['Operation']['data'];
filter?: ED[T]['Filter'];
}, checkerTypes?: CheckerType[]): boolean | { [A in ED[T]["Action"]]: boolean | OakUserException<ED>; }[ED[T]["Action"]];
}, checkerTypes?: CheckerType[], cacheInsensative?: true): boolean | { [A in ED[T]["Action"]]: boolean | OakUserException<ED>; }[ED[T]["Action"]];
redoOperation(opers: Array<{
entity: keyof ED;
operation: ED[keyof ED]['Operation'];

View File

@ -360,17 +360,19 @@ export class Cache extends Feature {
}
return result;
}
checkOperation(entity, operation, checkerTypes) {
checkOperation(entity, operation, checkerTypes, cacheInsensative) {
// 缓存同一id对同一action的判断避免性能低下
const { action, data, filter } = operation;
let id;
let ts;
const checkTypeString = checkerTypes ? checkerTypes.join('-') : '$$all';
if (filter && !data && typeof filter.id === 'string') {
id = filter.id;
ts = this.cacheStore.getLastUpdateTs();
if (this.entityActionAuthDict[ts]?.[entity]?.[id]?.[checkTypeString]?.hasOwnProperty(action)) {
return this.entityActionAuthDict[ts][entity][id][checkTypeString][action];
if (!cacheInsensative) {
if (filter && !data && typeof filter.id === 'string') {
id = filter.id;
ts = this.cacheStore.getLastUpdateTs();
if (this.entityActionAuthDict[ts]?.[entity]?.[id]?.[checkTypeString]?.hasOwnProperty(action)) {
return this.entityActionAuthDict[ts][entity][id][checkTypeString][action];
}
}
}
let rollback = this.begin(true);

View File

@ -242,7 +242,7 @@ function checkActionsAndCascadeEntities(rows, option) {
const filter = (filter1 && filter2) ? combineFilters(this.state.oakEntity, this.features.cache.getSchema(), [
filter1, filter2
]) : (filter1 || filter2);
if (filter && this.checkOperation(this.state.oakEntity, { action: a2, filter }, checkTypes) === true) {
if (filter && this.checkOperation(this.state.oakEntity, { action: a2, filter }, checkTypes, option.cacheInsensativeActions?.includes(a2) || undefined) === true) {
const action2 = checkActionAttrsIfNecessary(this.features.cache, this.state.oakEntity, action, rows.id);
legalActions.push(action2);
if (rows['#oakLegalActions']) {

View File

@ -185,12 +185,12 @@ const oakBehavior = Behavior({
select(entity, selection) {
return select.call(this, entity, selection);
},
checkOperation(entity, { action, data, filter }, checkerTypes) {
checkOperation(entity, { action, data, filter }, checkerTypes, cacheInsensative) {
return this.features.cache.checkOperation(entity, {
action,
data,
filter,
}, checkerTypes);
}, checkerTypes, cacheInsensative);
},
tryExecute(path, action) {
const path2 = path

2
es/page.react.d.ts vendored
View File

@ -76,7 +76,7 @@ export declare function createComponent<IsList extends boolean, ED extends Entit
isDirty(path?: string | undefined): boolean;
getFreshValue(path?: string | undefined): Partial<import("oak-domain/lib/types").GeneralEntityShape> | Partial<import("oak-domain/lib/types").GeneralEntityShape>[] | undefined;
select<T2_2 extends keyof ED>(entity: T2_2, selection: ED[T2_2]["Selection"]): Partial<import("oak-domain/lib/types").GeneralEntityShape>[];
checkOperation<T2_3 extends keyof ED>(entity: T2_3, operation: Omit<ED[T2_3]["Operation"], "id">, checkerTypes?: CheckerType[] | undefined): boolean | { [A in ED[T2_3]["Action"]]: boolean | import("oak-domain/lib/types").OakUserException<ED>; }[ED[T2_3]["Action"]];
checkOperation<T2_3 extends keyof ED>(entity: T2_3, operation: Omit<ED[T2_3]["Operation"], "id">, checkerTypes?: CheckerType[] | undefined, cacheInsensative?: true | undefined): boolean | { [A in ED[T2_3]["Action"]]: boolean | import("oak-domain/lib/types").OakUserException<ED>; }[ED[T2_3]["Action"]];
tryExecute(path?: string | undefined, action?: string | undefined): boolean | { [A_1 in ED[keyof ED]["Action"]]: boolean | import("oak-domain/lib/types").OakUserException<ED>; }[ED[keyof ED]["Action"]];
getOperations<T_7 extends keyof ED>(path?: string | undefined): {
entity: keyof ED;

View File

@ -179,8 +179,8 @@ class OakComponentBase extends React.PureComponent {
select(entity, selection) {
return select.call(this, entity, selection);
}
checkOperation(entity, operation, checkerTypes) {
return this.features.cache.checkOperation(entity, operation, checkerTypes);
checkOperation(entity, operation, checkerTypes, cacheInsensative) {
return this.features.cache.checkOperation(entity, operation, checkerTypes, cacheInsensative);
}
tryExecute(path, action) {
const path2 = path

3
es/types/Page.d.ts vendored
View File

@ -63,6 +63,7 @@ interface ComponentOption<IsList extends boolean, ED extends EntityDict & BaseEn
* actions
*/
actions?: ActionDef<ED, T>[] | ((this: ComponentPublicThisType<ED, T, Cxt, FrontCxt, AD, FD, FormedData, IsList, TData, TProperty, TMethod, EMethod>) => ActionDef<ED, T>[]);
cacheInsensativeActions?: ActionDef<ED, T>[];
/**
*
* list中list组件能够覆盖子组件的projection
@ -269,7 +270,7 @@ export type OakCommonComponentMethods<ED extends EntityDict & BaseEntityDict, T
action: ED[T2]['Action'];
data?: ED[T2]['Operation']['data'];
filter?: ED[T2]['Filter'];
}, checkerTypes?: CheckerType[]) => boolean | OakUserException<ED>;
}, checkerTypes?: CheckerType[], cacheInsensative?: true) => boolean | OakUserException<ED>;
tryExecute: (path?: string, action?: ED[T]['Action']) => boolean | OakUserException<ED>;
getOperations: (path?: string) => {
operation: ED[T]['Operation'];

View File

@ -113,7 +113,7 @@ export declare class Cache<ED extends EntityDict & BaseEntityDict> extends Featu
action: ED[T]['Action'];
data?: ED[T]['Operation']['data'];
filter?: ED[T]['Filter'];
}, checkerTypes?: CheckerType[]): boolean | { [A in ED[T]["Action"]]: boolean | OakUserException<ED>; }[ED[T]["Action"]];
}, checkerTypes?: CheckerType[], cacheInsensative?: true): boolean | { [A in ED[T]["Action"]]: boolean | OakUserException<ED>; }[ED[T]["Action"]];
redoOperation(opers: Array<{
entity: keyof ED;
operation: ED[keyof ED]['Operation'];

View File

@ -363,17 +363,19 @@ class Cache extends Feature_1.Feature {
}
return result;
}
checkOperation(entity, operation, checkerTypes) {
checkOperation(entity, operation, checkerTypes, cacheInsensative) {
// 缓存同一id对同一action的判断避免性能低下
const { action, data, filter } = operation;
let id;
let ts;
const checkTypeString = checkerTypes ? checkerTypes.join('-') : '$$all';
if (filter && !data && typeof filter.id === 'string') {
id = filter.id;
ts = this.cacheStore.getLastUpdateTs();
if (this.entityActionAuthDict[ts]?.[entity]?.[id]?.[checkTypeString]?.hasOwnProperty(action)) {
return this.entityActionAuthDict[ts][entity][id][checkTypeString][action];
if (!cacheInsensative) {
if (filter && !data && typeof filter.id === 'string') {
id = filter.id;
ts = this.cacheStore.getLastUpdateTs();
if (this.entityActionAuthDict[ts]?.[entity]?.[id]?.[checkTypeString]?.hasOwnProperty(action)) {
return this.entityActionAuthDict[ts][entity][id][checkTypeString][action];
}
}
}
let rollback = this.begin(true);

View File

@ -246,7 +246,7 @@ function checkActionsAndCascadeEntities(rows, option) {
const filter = (filter1 && filter2) ? (0, filter_1.combineFilters)(this.state.oakEntity, this.features.cache.getSchema(), [
filter1, filter2
]) : (filter1 || filter2);
if (filter && this.checkOperation(this.state.oakEntity, { action: a2, filter }, checkTypes) === true) {
if (filter && this.checkOperation(this.state.oakEntity, { action: a2, filter }, checkTypes, option.cacheInsensativeActions?.includes(a2) || undefined) === true) {
const action2 = checkActionAttrsIfNecessary(this.features.cache, this.state.oakEntity, action, rows.id);
legalActions.push(action2);
if (rows['#oakLegalActions']) {

View File

@ -188,12 +188,12 @@ const oakBehavior = Behavior({
select(entity, selection) {
return page_common_1.select.call(this, entity, selection);
},
checkOperation(entity, { action, data, filter }, checkerTypes) {
checkOperation(entity, { action, data, filter }, checkerTypes, cacheInsensative) {
return this.features.cache.checkOperation(entity, {
action,
data,
filter,
}, checkerTypes);
}, checkerTypes, cacheInsensative);
},
tryExecute(path, action) {
const path2 = path

2
lib/page.react.d.ts vendored
View File

@ -76,7 +76,7 @@ export declare function createComponent<IsList extends boolean, ED extends Entit
isDirty(path?: string | undefined): boolean;
getFreshValue(path?: string | undefined): Partial<import("oak-domain/lib/types").GeneralEntityShape> | Partial<import("oak-domain/lib/types").GeneralEntityShape>[] | undefined;
select<T2_2 extends keyof ED>(entity: T2_2, selection: ED[T2_2]["Selection"]): Partial<import("oak-domain/lib/types").GeneralEntityShape>[];
checkOperation<T2_3 extends keyof ED>(entity: T2_3, operation: Omit<ED[T2_3]["Operation"], "id">, checkerTypes?: CheckerType[] | undefined): boolean | { [A in ED[T2_3]["Action"]]: boolean | import("oak-domain/lib/types").OakUserException<ED>; }[ED[T2_3]["Action"]];
checkOperation<T2_3 extends keyof ED>(entity: T2_3, operation: Omit<ED[T2_3]["Operation"], "id">, checkerTypes?: CheckerType[] | undefined, cacheInsensative?: true | undefined): boolean | { [A in ED[T2_3]["Action"]]: boolean | import("oak-domain/lib/types").OakUserException<ED>; }[ED[T2_3]["Action"]];
tryExecute(path?: string | undefined, action?: string | undefined): boolean | { [A_1 in ED[keyof ED]["Action"]]: boolean | import("oak-domain/lib/types").OakUserException<ED>; }[ED[keyof ED]["Action"]];
getOperations<T_7 extends keyof ED>(path?: string | undefined): {
entity: keyof ED;

View File

@ -184,8 +184,8 @@ class OakComponentBase extends react_1.default.PureComponent {
select(entity, selection) {
return page_common_1.select.call(this, entity, selection);
}
checkOperation(entity, operation, checkerTypes) {
return this.features.cache.checkOperation(entity, operation, checkerTypes);
checkOperation(entity, operation, checkerTypes, cacheInsensative) {
return this.features.cache.checkOperation(entity, operation, checkerTypes, cacheInsensative);
}
tryExecute(path, action) {
const path2 = path

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

@ -63,6 +63,7 @@ interface ComponentOption<IsList extends boolean, ED extends EntityDict & BaseEn
* actions
*/
actions?: ActionDef<ED, T>[] | ((this: ComponentPublicThisType<ED, T, Cxt, FrontCxt, AD, FD, FormedData, IsList, TData, TProperty, TMethod, EMethod>) => ActionDef<ED, T>[]);
cacheInsensativeActions?: ActionDef<ED, T>[];
/**
*
* list中list组件能够覆盖子组件的projection
@ -269,7 +270,7 @@ export type OakCommonComponentMethods<ED extends EntityDict & BaseEntityDict, T
action: ED[T2]['Action'];
data?: ED[T2]['Operation']['data'];
filter?: ED[T2]['Filter'];
}, checkerTypes?: CheckerType[]) => boolean | OakUserException<ED>;
}, checkerTypes?: CheckerType[], cacheInsensative?: true) => boolean | OakUserException<ED>;
tryExecute: (path?: string, action?: ED[T]['Action']) => boolean | OakUserException<ED>;
getOperations: (path?: string) => {
operation: ED[T]['Operation'];

View File

@ -50,7 +50,7 @@ export class Cache<ED extends EntityDict & BaseEntityDict> extends Feature {
private attrUpdateMatrix?: AttrUpdateMatrix<ED>;
private connector: Connector<ED, SyncContext<ED>>;
private baseRelationAuth: BaseRelationAuth<ED>;
// 缓存在某一时间戳状态下对某行进行某个action的判断结果
private entityActionAuthDict: {
[ts: number]: {
@ -288,7 +288,7 @@ export class Cache<ED extends EntityDict & BaseEntityDict> extends Feature {
else {
if (oldest > 0) {
// 说明key曾经都取过了只取updateAt在oldest之后的数据
selection.filter = selection.filter ?combineFilters(entity, this.getSchema(), [selection.filter, {
selection.filter = selection.filter ? combineFilters(entity, this.getSchema(), [selection.filter, {
$$updateAt$$: {
$gte: oldest,
}
@ -500,19 +500,21 @@ export class Cache<ED extends EntityDict & BaseEntityDict> extends Feature {
data?: ED[T]['Operation']['data'],
filter?: ED[T]['Filter'],
},
checkerTypes?: CheckerType[]
checkerTypes?: CheckerType[],
cacheInsensative?: true,
) {
// 缓存同一id对同一action的判断避免性能低下
const { action, data, filter } = operation;
let id: string | undefined;
let ts: number | undefined;
const checkTypeString = checkerTypes ? checkerTypes.join('-') : '$$all';
if (filter && !data && typeof filter.id === 'string') {
id = filter.id;
ts = this.cacheStore.getLastUpdateTs();
if (this.entityActionAuthDict[ts]?.[entity]?.[id]?.[checkTypeString]?.hasOwnProperty(action)) {
return this.entityActionAuthDict[ts]![entity]![id]![checkTypeString]![action]!;
if (!cacheInsensative) {
if (filter && !data && typeof filter.id === 'string') {
id = filter.id;
ts = this.cacheStore.getLastUpdateTs();
if (this.entityActionAuthDict[ts]?.[entity]?.[id]?.[checkTypeString]?.hasOwnProperty(action)) {
return this.entityActionAuthDict[ts]![entity]![id]![checkTypeString]![action]!;
}
}
}

View File

@ -314,7 +314,7 @@ function checkActionsAndCascadeEntities<
const filter = (filter1 && filter2) ? combineFilters<ED, T>(this.state.oakEntity, this.features.cache.getSchema(), [
filter1, filter2
]) : (filter1 || filter2);
if (filter && this.checkOperation(this.state.oakEntity, { action: a2, filter }, checkTypes) === true) {
if (filter && this.checkOperation(this.state.oakEntity, { action: a2, filter }, checkTypes, option.cacheInsensativeActions?.includes(a2) || undefined) === true) {
const action2 = checkActionAttrsIfNecessary(this.features.cache, this.state.oakEntity, action, rows.id!);
legalActions.push(action2);
if (rows['#oakLegalActions']) {

View File

@ -315,7 +315,7 @@ const oakBehavior = Behavior<
return select.call(this as any, entity as any, selection);
},
checkOperation(entity, { action, data, filter }, checkerTypes) {
checkOperation(entity, { action, data, filter }, checkerTypes, cacheInsensative) {
return this.features.cache.checkOperation(
entity,
{
@ -323,7 +323,8 @@ const oakBehavior = Behavior<
data,
filter,
},
checkerTypes as CheckerType[]
checkerTypes as CheckerType[],
cacheInsensative
);
},

View File

@ -354,12 +354,14 @@ abstract class OakComponentBase<
checkOperation<T2 extends keyof ED>(
entity: T2,
operation: Omit<ED[T2]['Operation'], 'id'>,
checkerTypes?: CheckerType[]
checkerTypes?: CheckerType[],
cacheInsensative?: true,
) {
return this.features.cache.checkOperation(
entity,
operation,
checkerTypes as CheckerType[]
checkerTypes as CheckerType[],
cacheInsensative
);
}

View File

@ -163,6 +163,7 @@ interface ComponentOption<
* actions
*/
actions?: ActionDef<ED, T>[] | ((this: ComponentPublicThisType<ED, T, Cxt, FrontCxt, AD, FD, FormedData, IsList, TData, TProperty, TMethod, EMethod>) => ActionDef<ED, T>[]);
cacheInsensativeActions?: ActionDef<ED, T>[];
/**
*
* list中list组件能够覆盖子组件的projection
@ -494,7 +495,8 @@ export type OakCommonComponentMethods<
data?: ED[T2]['Operation']['data'],
filter?: ED[T2]['Filter'],
},
checkerTypes?: CheckerType[]
checkerTypes?: CheckerType[],
cacheInsensative?: true
) => boolean | OakUserException<ED>;
tryExecute: (path?: string, action?: ED[T]['Action']) => boolean | OakUserException<ED>;
getOperations: (