对cache中的context进行了单例化,一个cache在一次begin/end之间使用唯一的context
This commit is contained in:
parent
1ce9e13101
commit
f00f50b45a
|
|
@ -5,7 +5,6 @@
|
|||
.title {
|
||||
padding-block: 20px 10px;
|
||||
padding-inline: 10px;
|
||||
color: #888;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
text-align: left;
|
||||
|
|
@ -24,6 +23,7 @@
|
|||
.renderLabel {
|
||||
min-width: 140px;
|
||||
margin-right: 16px;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
.renderValue {
|
||||
display: -webkit-box;
|
||||
|
|
|
|||
|
|
@ -20,13 +20,13 @@ export declare class Cache<ED extends EntityDict & BaseEntityDict, Cxt extends A
|
|||
private localStorage;
|
||||
private getFullDataFn;
|
||||
private refreshRecords;
|
||||
private context?;
|
||||
constructor(storageSchema: StorageSchema<ED>, aspectWrapper: AspectWrapper<ED, Cxt, AD>, frontendContextBuilder: () => (store: CacheStore<ED, FrontCxt>) => FrontCxt, checkers: Array<Checker<ED, keyof ED, FrontCxt | Cxt>>, getFullData: () => any, localStorage: LocalStorage, savedEntities?: (keyof ED)[], keepFreshPeriod?: number);
|
||||
/**
|
||||
* 处理cache中需要缓存的数据
|
||||
*/
|
||||
private initSavedLogic;
|
||||
getSchema(): StorageSchema<ED>;
|
||||
getCurrentUserId(allowUnloggedIn?: boolean): string | undefined;
|
||||
exec<K extends keyof AD>(name: K, params: Parameters<AD[K]>[0], callback?: (result: Awaited<ReturnType<AD[K]>>, opRecords?: OpRecord<ED>[]) => void, dontPublish?: true): Promise<{
|
||||
result: Awaited<ReturnType<AD[K]>>;
|
||||
message: string | null | undefined;
|
||||
|
|
@ -76,16 +76,16 @@ export declare class Cache<ED extends EntityDict & BaseEntityDict, Cxt extends A
|
|||
redoOperation(opers: Array<{
|
||||
entity: keyof ED;
|
||||
operation: ED[keyof ED]['Operation'];
|
||||
}>, context: FrontCxt): void;
|
||||
}>): void;
|
||||
private getInner;
|
||||
get<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], context?: FrontCxt, allowMiss?: boolean): Partial<ED[T]["Schema"]>[];
|
||||
get<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], allowMiss?: boolean): Partial<ED[T]["Schema"]>[];
|
||||
judgeRelation(entity: keyof ED, attr: string): string | 0 | 1 | string[] | 2;
|
||||
bindOnSync(callback: (opRecords: OpRecord<ED>[]) => void): void;
|
||||
unbindOnSync(callback: (opRecords: OpRecord<ED>[]) => void): void;
|
||||
getCachedData(): { [T in keyof ED]?: ED[T]["OpSchema"][] | undefined; };
|
||||
getFullData(): any;
|
||||
begin(): FrontCxt;
|
||||
commit(context: FrontCxt): void;
|
||||
rollback(context: FrontCxt): void;
|
||||
commit(): void;
|
||||
rollback(): void;
|
||||
}
|
||||
export {};
|
||||
|
|
|
|||
|
|
@ -58,10 +58,10 @@ var Cache = /** @class */ (function (_super) {
|
|||
Cache.prototype.getSchema = function () {
|
||||
return this.cacheStore.getSchema();
|
||||
};
|
||||
Cache.prototype.getCurrentUserId = function (allowUnloggedIn) {
|
||||
var context = this.contextBuilder && this.contextBuilder();
|
||||
return context === null || context === void 0 ? void 0 : context.getCurrentUserId(allowUnloggedIn);
|
||||
};
|
||||
/* getCurrentUserId(allowUnloggedIn?: boolean) {
|
||||
const context = this.contextBuilder && this.contextBuilder();
|
||||
return context?.getCurrentUserId(allowUnloggedIn);
|
||||
} */
|
||||
Cache.prototype.exec = function (name, params, callback, dontPublish) {
|
||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||
var _a, result, opRecords, message, e_1, opRecord;
|
||||
|
|
@ -426,14 +426,13 @@ var Cache = /** @class */ (function (_super) {
|
|||
*/
|
||||
Cache.prototype.tryRedoOperations = function (operations) {
|
||||
var e_4, _a;
|
||||
var context = this.contextBuilder();
|
||||
context.begin();
|
||||
this.begin();
|
||||
try {
|
||||
try {
|
||||
for (var operations_1 = tslib_1.__values(operations), operations_1_1 = operations_1.next(); !operations_1_1.done; operations_1_1 = operations_1.next()) {
|
||||
var oper = operations_1_1.value;
|
||||
var entity = oper.entity, operation = oper.operation;
|
||||
this.cacheStore.operate(entity, operation, context, {
|
||||
this.context.operate(entity, operation, {
|
||||
dontCollect: true,
|
||||
dontCreateOper: true,
|
||||
dontCreateModi: true,
|
||||
|
|
@ -447,11 +446,11 @@ var Cache = /** @class */ (function (_super) {
|
|||
}
|
||||
finally { if (e_4) throw e_4.error; }
|
||||
}
|
||||
context.rollback();
|
||||
this.rollback();
|
||||
return true;
|
||||
}
|
||||
catch (err) {
|
||||
context.rollback();
|
||||
this.rollback();
|
||||
if (!(err instanceof Exception_1.OakUserException)) {
|
||||
throw err;
|
||||
}
|
||||
|
|
@ -459,31 +458,39 @@ var Cache = /** @class */ (function (_super) {
|
|||
}
|
||||
};
|
||||
Cache.prototype.checkOperation = function (entity, action, data, filter, checkerTypes) {
|
||||
var context = this.contextBuilder();
|
||||
context.begin();
|
||||
var autoCommit = false;
|
||||
if (!this.context) {
|
||||
this.begin();
|
||||
autoCommit = true;
|
||||
}
|
||||
var operation = {
|
||||
action: action,
|
||||
filter: filter,
|
||||
data: data
|
||||
};
|
||||
try {
|
||||
this.cacheStore.check(entity, operation, context, checkerTypes);
|
||||
context.rollback();
|
||||
this.cacheStore.check(entity, operation, this.context, checkerTypes);
|
||||
if (autoCommit) {
|
||||
this.rollback();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (err) {
|
||||
context.rollback();
|
||||
if (autoCommit) {
|
||||
this.rollback();
|
||||
}
|
||||
if (!(err instanceof Exception_1.OakUserException)) {
|
||||
throw err;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Cache.prototype.redoOperation = function (opers, context) {
|
||||
Cache.prototype.redoOperation = function (opers) {
|
||||
var _this = this;
|
||||
(0, assert_1.default)(this.context);
|
||||
opers.forEach(function (oper) {
|
||||
var entity = oper.entity, operation = oper.operation;
|
||||
_this.cacheStore.operate(entity, operation, context, {
|
||||
_this.cacheStore.operate(entity, operation, _this.context, {
|
||||
dontCollect: true,
|
||||
dontCreateOper: true,
|
||||
blockTrigger: true,
|
||||
|
|
@ -492,16 +499,27 @@ var Cache = /** @class */ (function (_super) {
|
|||
});
|
||||
return;
|
||||
};
|
||||
Cache.prototype.getInner = function (entity, selection, context, allowMiss) {
|
||||
Cache.prototype.getInner = function (entity, selection, allowMiss) {
|
||||
var _this = this;
|
||||
var autoCommit = false;
|
||||
if (!this.context) {
|
||||
this.begin();
|
||||
autoCommit = true;
|
||||
}
|
||||
try {
|
||||
var result = this.cacheStore.select(entity, selection, context, {
|
||||
var result = this.cacheStore.select(entity, selection, this.context, {
|
||||
dontCollect: true,
|
||||
includedDeleted: true,
|
||||
});
|
||||
if (autoCommit) {
|
||||
this.commit();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (err) {
|
||||
if (autoCommit) {
|
||||
this.rollback();
|
||||
}
|
||||
if (err instanceof Exception_1.OakRowUnexistedException) {
|
||||
if (!this.refreshing && !allowMiss) {
|
||||
var missedRows_1 = err.getRows();
|
||||
|
|
@ -549,9 +567,8 @@ var Cache = /** @class */ (function (_super) {
|
|||
}
|
||||
}
|
||||
};
|
||||
Cache.prototype.get = function (entity, selection, context, allowMiss) {
|
||||
var context2 = context || this.contextBuilder();
|
||||
return this.getInner(entity, selection, context2, allowMiss);
|
||||
Cache.prototype.get = function (entity, selection, allowMiss) {
|
||||
return this.getInner(entity, selection, allowMiss);
|
||||
};
|
||||
Cache.prototype.judgeRelation = function (entity, attr) {
|
||||
return this.cacheStore.judgeRelation(entity, attr);
|
||||
|
|
@ -569,15 +586,20 @@ var Cache = /** @class */ (function (_super) {
|
|||
return this.getFullDataFn();
|
||||
};
|
||||
Cache.prototype.begin = function () {
|
||||
var context = this.contextBuilder();
|
||||
context.begin();
|
||||
return context;
|
||||
(0, assert_1.default)(!this.context);
|
||||
this.context = this.contextBuilder();
|
||||
this.context.begin();
|
||||
return this.context;
|
||||
};
|
||||
Cache.prototype.commit = function (context) {
|
||||
context.commit();
|
||||
Cache.prototype.commit = function () {
|
||||
(0, assert_1.default)(this.context);
|
||||
this.context.commit();
|
||||
this.context = undefined;
|
||||
};
|
||||
Cache.prototype.rollback = function (context) {
|
||||
context.rollback();
|
||||
Cache.prototype.rollback = function () {
|
||||
(0, assert_1.default)(this.context);
|
||||
this.context.rollback();
|
||||
this.context = undefined;
|
||||
};
|
||||
return Cache;
|
||||
}(Feature_1.Feature));
|
||||
|
|
|
|||
|
|
@ -179,13 +179,13 @@ var RelationAuth = /** @class */ (function (_super) {
|
|||
this.baseRelationAuth.checkRelationSync(entity, operation, context);
|
||||
}
|
||||
catch (err) {
|
||||
context.rollback();
|
||||
this.cache.rollback();
|
||||
if (!(err instanceof types_1.OakUserException)) {
|
||||
throw err;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
context.rollback();
|
||||
this.cache.rollback();
|
||||
return true;
|
||||
};
|
||||
RelationAuth.prototype.getRelationIdByName = function (entity, name, entityId) {
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ declare abstract class Node<ED extends EntityDict & BaseEntityDict, T extends ke
|
|||
isExecuting(): boolean;
|
||||
setExecuting(executing: boolean): void;
|
||||
getParent(): SingleNode<ED, keyof ED, Cxt, FrontCxt, AD> | ListNode<ED, T, Cxt, FrontCxt, AD> | VirtualNode<ED, Cxt, FrontCxt, AD> | undefined;
|
||||
protected getProjection(context?: FrontCxt): ED[T]['Selection']['data'] | undefined;
|
||||
protected getProjection(): ED[T]['Selection']['data'] | undefined;
|
||||
setProjection(projection: ED[T]['Selection']['data']): void;
|
||||
protected judgeRelation(attr: string): string | 0 | 1 | string[] | 2;
|
||||
}
|
||||
|
|
@ -95,7 +95,7 @@ declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof E
|
|||
addNamedSorter(sorter: NamedSorterItem<ED, T>, refresh?: boolean): void;
|
||||
removeNamedSorter(sorter: NamedSorterItem<ED, T>, refresh?: boolean): void;
|
||||
removeNamedSorterByName(name: string, refresh: boolean): void;
|
||||
getFreshValue(context: FrontCxt): Array<Partial<ED[T]['Schema']>>;
|
||||
getFreshValue(): Array<Partial<ED[T]['Schema']>>;
|
||||
addItem(item: Omit<ED[T]['CreateSingle']['data'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>): void;
|
||||
removeItem(id: string, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>): void;
|
||||
recoverItem(id: string): void;
|
||||
|
|
@ -116,9 +116,9 @@ declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof E
|
|||
entity: keyof ED;
|
||||
operation: ED[keyof ED]['Operation'];
|
||||
}> | undefined;
|
||||
getProjection(context?: FrontCxt): ED[T]["Selection"]["data"] | undefined;
|
||||
getProjection(): ED[T]["Selection"]["data"] | undefined;
|
||||
private constructFilters;
|
||||
constructSelection(withParent?: true, ignoreNewParent?: boolean, context?: FrontCxt, ignoreUnapplied?: true): {
|
||||
constructSelection(withParent?: true, ignoreNewParent?: boolean, ignoreUnapplied?: true): {
|
||||
data: ED[T]["Selection"]["data"];
|
||||
filter: ED[T]["Selection"]["filter"] | undefined;
|
||||
sorter: ED[T]["Selection"]["sorter"];
|
||||
|
|
@ -152,7 +152,7 @@ declare class SingleNode<ED extends EntityDict & BaseEntityDict, T extends keyof
|
|||
};
|
||||
addChild(path: string, node: SingleNode<ED, keyof ED, Cxt, FrontCxt, AD> | ListNode<ED, keyof ED, Cxt, FrontCxt, AD>): void;
|
||||
removeChild(path: string): void;
|
||||
getFreshValue(context?: FrontCxt): Partial<ED[T]['Schema']> | undefined;
|
||||
getFreshValue(): Partial<ED[T]['Schema']> | undefined;
|
||||
doBeforeTrigger(): Promise<void>;
|
||||
doAfterTrigger(): Promise<void>;
|
||||
create(data: Partial<Omit<ED[T]['CreateSingle']['data'], 'id'>>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>): void;
|
||||
|
|
@ -162,7 +162,7 @@ declare class SingleNode<ED extends EntityDict & BaseEntityDict, T extends keyof
|
|||
entity: keyof ED;
|
||||
operation: ED[keyof ED]['Operation'];
|
||||
}> | undefined;
|
||||
getProjection(context?: FrontCxt, withDecendants?: boolean): ED[T]["Selection"]["data"] | undefined;
|
||||
getProjection(withDecendants?: boolean): ED[T]["Selection"]["data"] | undefined;
|
||||
refresh(): Promise<void>;
|
||||
clean(): void;
|
||||
private getFilter;
|
||||
|
|
@ -173,7 +173,7 @@ declare class SingleNode<ED extends EntityDict & BaseEntityDict, T extends keyof
|
|||
* @param disableOperation
|
||||
* @returns
|
||||
*/
|
||||
getParentFilter<T2 extends keyof ED>(childNode: Node<ED, keyof ED, Cxt, FrontCxt, AD>, context?: FrontCxt, ignoreNewParent?: boolean): ED[T2]['Selection']['filter'] | undefined;
|
||||
getParentFilter<T2 extends keyof ED>(childNode: Node<ED, keyof ED, Cxt, FrontCxt, AD>, ignoreNewParent?: boolean): ED[T2]['Selection']['filter'] | undefined;
|
||||
}
|
||||
declare class VirtualNode<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>, AD extends CommonAspectDict<ED, Cxt>> extends Feature {
|
||||
private dirty;
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ var Node = /** @class */ (function (_super) {
|
|||
Node.prototype.getParent = function () {
|
||||
return this.parent;
|
||||
};
|
||||
Node.prototype.getProjection = function (context) {
|
||||
Node.prototype.getProjection = function () {
|
||||
var projection = typeof this.projection === 'function' ? this.projection() : (this.projection && (0, lodash_1.cloneDeep)(this.projection));
|
||||
return projection;
|
||||
};
|
||||
|
|
@ -241,7 +241,7 @@ var ListNode = /** @class */ (function (_super) {
|
|||
此时对userRelation的删除动作就会导致user不会被移出list
|
||||
*/
|
||||
if (needRefresh) {
|
||||
var _b = this.constructSelection(true, false, undefined, true), filter = _b.filter, sorter = _b.sorter;
|
||||
var _b = this.constructSelection(true, false, true), filter = _b.filter, sorter = _b.sorter;
|
||||
if (filter) {
|
||||
var result = this.cache.get(this.getEntity(), {
|
||||
data: {
|
||||
|
|
@ -400,7 +400,7 @@ var ListNode = /** @class */ (function (_super) {
|
|||
this.publish();
|
||||
}
|
||||
};
|
||||
ListNode.prototype.getFreshValue = function (context) {
|
||||
ListNode.prototype.getFreshValue = function () {
|
||||
var _this = this;
|
||||
/**
|
||||
* 满足当前结点的数据应当是所有满足当前filter条件且ids在当前ids中的数据
|
||||
|
|
@ -414,7 +414,7 @@ var ListNode = /** @class */ (function (_super) {
|
|||
*
|
||||
* 这里不能用sorter排序,enum的排序顺序目前前后台尚不一致 by Xc 20230809
|
||||
*/
|
||||
var _a = this.constructSelection(true, false, context, true), data = _a.data, filter = _a.filter;
|
||||
var _a = this.constructSelection(true, false, true), data = _a.data, filter = _a.filter;
|
||||
if (filter || this.ids) {
|
||||
var filter2 = filter && this.ids ? {
|
||||
$or: [filter, {
|
||||
|
|
@ -430,7 +430,7 @@ var ListNode = /** @class */ (function (_super) {
|
|||
var result = this.cache.get(this.entity, {
|
||||
data: data,
|
||||
filter: filter2,
|
||||
}, context, this.isLoading());
|
||||
}, this.isLoading());
|
||||
var r2_1 = result.filter(function (ele) { var _a; return ele.$$createAt$$ === 1 || ((_a = _this.ids) === null || _a === void 0 ? void 0 : _a.includes(ele.id)); }).sort(function (ele1, ele2) {
|
||||
if (ele1.$$createAt$$ === 1) {
|
||||
return -1;
|
||||
|
|
@ -464,7 +464,7 @@ var ListNode = /** @class */ (function (_super) {
|
|||
id: { $in: finalIds },
|
||||
},
|
||||
sorter,
|
||||
}, context, this.isLoading()); */
|
||||
}, this.isLoading()); */
|
||||
};
|
||||
ListNode.prototype.addItem = function (item, beforeExecute, afterExecute) {
|
||||
var id = (0, uuid_1.generateNewId)();
|
||||
|
|
@ -713,8 +713,8 @@ var ListNode = /** @class */ (function (_super) {
|
|||
}
|
||||
return operations;
|
||||
};
|
||||
ListNode.prototype.getProjection = function (context) {
|
||||
var projection = _super.prototype.getProjection.call(this, context);
|
||||
ListNode.prototype.getProjection = function () {
|
||||
var projection = _super.prototype.getProjection.call(this);
|
||||
// List必须自主决定Projection
|
||||
/* if (this.children.length > 0) {
|
||||
const subProjection = await this.children[0].getProjection();
|
||||
|
|
@ -722,7 +722,7 @@ var ListNode = /** @class */ (function (_super) {
|
|||
} */
|
||||
return projection;
|
||||
};
|
||||
ListNode.prototype.constructFilters = function (context, withParent, ignoreNewParent, ignoreUnapplied) {
|
||||
ListNode.prototype.constructFilters = function (withParent, ignoreNewParent, ignoreUnapplied) {
|
||||
var ownFilters = this.filters;
|
||||
var filters = ownFilters.filter(function (ele) { return !ignoreUnapplied || ele.applied === true || ele.applied === undefined; } // 如果是undefined,说明不可以移除(构造时就存在),也得返回
|
||||
).map(function (ele) {
|
||||
|
|
@ -734,7 +734,7 @@ var ListNode = /** @class */ (function (_super) {
|
|||
});
|
||||
if (withParent && this.parent) {
|
||||
if (this.parent instanceof SingleNode) {
|
||||
var filterOfParent = this.parent.getParentFilter(this, context, ignoreNewParent);
|
||||
var filterOfParent = this.parent.getParentFilter(this, ignoreNewParent);
|
||||
if (filterOfParent) {
|
||||
filters.push(filterOfParent);
|
||||
}
|
||||
|
|
@ -747,9 +747,9 @@ var ListNode = /** @class */ (function (_super) {
|
|||
// 返回的filter在上层做check的时候可能被改造掉
|
||||
return (0, lodash_1.cloneDeep)(filters);
|
||||
};
|
||||
ListNode.prototype.constructSelection = function (withParent, ignoreNewParent, context, ignoreUnapplied) {
|
||||
ListNode.prototype.constructSelection = function (withParent, ignoreNewParent, ignoreUnapplied) {
|
||||
var sorters = this.sorters;
|
||||
var data = this.getProjection(context);
|
||||
var data = this.getProjection();
|
||||
(0, assert_1.assert)(data, '取数据时找不到projection信息');
|
||||
var sorterArr = sorters.filter(function (ele) { return !ignoreUnapplied || ele.applied; }).map(function (ele) {
|
||||
var sorter = ele.sorter;
|
||||
|
|
@ -759,7 +759,7 @@ var ListNode = /** @class */ (function (_super) {
|
|||
return sorter;
|
||||
})
|
||||
.filter(function (ele) { return !!ele; });
|
||||
var filters = this.constructFilters(context, withParent, ignoreNewParent, ignoreUnapplied);
|
||||
var filters = this.constructFilters(withParent, ignoreNewParent, ignoreUnapplied);
|
||||
var filters2 = filters === null || filters === void 0 ? void 0 : filters.filter(function (ele) { return !!ele; });
|
||||
var filter = filters2 ? (0, filter_1.combineFilters)(this.entity, this.schema, filters2) : undefined;
|
||||
return {
|
||||
|
|
@ -992,8 +992,8 @@ var SingleNode = /** @class */ (function (_super) {
|
|||
SingleNode.prototype.removeChild = function (path) {
|
||||
(0, lodash_1.unset)(this.children, path);
|
||||
};
|
||||
SingleNode.prototype.getFreshValue = function (context) {
|
||||
var projection = this.getProjection(context, false);
|
||||
SingleNode.prototype.getFreshValue = function () {
|
||||
var projection = this.getProjection(false);
|
||||
var id = this.getId();
|
||||
if (projection) {
|
||||
var result = this.cache.get(this.entity, {
|
||||
|
|
@ -1001,7 +1001,7 @@ var SingleNode = /** @class */ (function (_super) {
|
|||
filter: {
|
||||
id: id,
|
||||
},
|
||||
}, context, this.isLoading());
|
||||
}, this.isLoading());
|
||||
if (this.aggr) {
|
||||
(0, lodash_1.merge)(result[0], this.aggr);
|
||||
}
|
||||
|
|
@ -1216,18 +1216,18 @@ var SingleNode = /** @class */ (function (_super) {
|
|||
}];
|
||||
}
|
||||
};
|
||||
SingleNode.prototype.getProjection = function (context, withDecendants) {
|
||||
SingleNode.prototype.getProjection = function (withDecendants) {
|
||||
var _a, _b, _c;
|
||||
if (this.parent && this.parent instanceof ListNode) {
|
||||
return this.parent.getProjection(context);
|
||||
return this.parent.getProjection();
|
||||
}
|
||||
var projection = _super.prototype.getProjection.call(this, context);
|
||||
var projection = _super.prototype.getProjection.call(this);
|
||||
if (projection && withDecendants) {
|
||||
for (var k in this.children) {
|
||||
if (k.indexOf(':') === -1) {
|
||||
var rel = this.judgeRelation(k);
|
||||
if (rel === 2) {
|
||||
var subProjection = this.children[k].getProjection(context, true);
|
||||
var subProjection = this.children[k].getProjection(true);
|
||||
Object.assign(projection, (_a = {
|
||||
entity: 1,
|
||||
entityId: 1
|
||||
|
|
@ -1236,7 +1236,7 @@ var SingleNode = /** @class */ (function (_super) {
|
|||
_a));
|
||||
}
|
||||
else if (typeof rel === 'string') {
|
||||
var subProjection = this.children[k].getProjection(context, true);
|
||||
var subProjection = this.children[k].getProjection(true);
|
||||
Object.assign(projection, (_b = {},
|
||||
_b["".concat(k, "Id")] = 1,
|
||||
_b[k] = subProjection,
|
||||
|
|
@ -1270,7 +1270,7 @@ var SingleNode = /** @class */ (function (_super) {
|
|||
this.publish();
|
||||
return [2 /*return*/];
|
||||
}
|
||||
projection = this.getProjection(undefined, true);
|
||||
projection = this.getProjection(true);
|
||||
filter = this.getFilter();
|
||||
if (!(projection && filter)) return [3 /*break*/, 5];
|
||||
this.setLoading(true);
|
||||
|
|
@ -1358,9 +1358,9 @@ var SingleNode = /** @class */ (function (_super) {
|
|||
* @param disableOperation
|
||||
* @returns
|
||||
*/
|
||||
SingleNode.prototype.getParentFilter = function (childNode, context, ignoreNewParent) {
|
||||
SingleNode.prototype.getParentFilter = function (childNode, ignoreNewParent) {
|
||||
var _a, _b, _c, _d;
|
||||
var value = this.getFreshValue(context);
|
||||
var value = this.getFreshValue();
|
||||
if (value && value.$$createAt$$ === 1 && ignoreNewParent) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -1830,20 +1830,20 @@ var RunningTree = /** @class */ (function (_super) {
|
|||
var root = this.root[paths[0]];
|
||||
var includeModi = path.includes(exports.MODI_NEXT_PATH_SUFFIX);
|
||||
if (node) {
|
||||
var context_1 = this.cache.begin();
|
||||
this.cache.begin();
|
||||
(0, assert_1.assert)(node instanceof ListNode || node instanceof SingleNode);
|
||||
if (includeModi) {
|
||||
var opers2 = node.getActiveModiOperations();
|
||||
if (opers2) {
|
||||
this.cache.redoOperation(opers2, context_1);
|
||||
this.cache.redoOperation(opers2);
|
||||
}
|
||||
}
|
||||
var opers = root === null || root === void 0 ? void 0 : root.composeOperations();
|
||||
if (opers) {
|
||||
this.cache.redoOperation(opers, context_1);
|
||||
this.cache.redoOperation(opers);
|
||||
}
|
||||
var value = node.getFreshValue(context_1);
|
||||
context_1.rollback();
|
||||
var value = node.getFreshValue();
|
||||
this.cache.rollback();
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ function initialize(storageSchema, frontendContextBuilder, backendContextBuilder
|
|||
case 0:
|
||||
context = features2.cache.begin();
|
||||
str = context.toString();
|
||||
context.commit();
|
||||
features2.cache.commit();
|
||||
return [4 /*yield*/, backendContextBuilder(str)(debugStore)];
|
||||
case 1:
|
||||
contextBackend = _a.sent();
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ function initialize(storageSchema, frontendContextBuilder, connector, checkers,
|
|||
switch (_b.label) {
|
||||
case 0:
|
||||
context = features2.cache.begin();
|
||||
context.commit();
|
||||
features.cache.commit();
|
||||
return [4 /*yield*/, connector.callAspect(name, params, context)];
|
||||
case 1:
|
||||
_a = _b.sent(), result = _a.result, opRecords = _a.opRecords, message = _a.message;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ export class Cache<
|
|||
private refreshRecords: {
|
||||
[T in keyof ED]?: Record<string, number>;
|
||||
} = {};
|
||||
private context?: FrontCxt;
|
||||
|
||||
constructor(
|
||||
storageSchema: StorageSchema<ED>,
|
||||
|
|
@ -105,10 +106,10 @@ export class Cache<
|
|||
return this.cacheStore.getSchema();
|
||||
}
|
||||
|
||||
getCurrentUserId(allowUnloggedIn?: boolean) {
|
||||
/* getCurrentUserId(allowUnloggedIn?: boolean) {
|
||||
const context = this.contextBuilder && this.contextBuilder();
|
||||
return context?.getCurrentUserId(allowUnloggedIn);
|
||||
}
|
||||
} */
|
||||
|
||||
async exec<K extends keyof AD>(
|
||||
name: K,
|
||||
|
|
@ -472,21 +473,20 @@ export class Cache<
|
|||
* @returns
|
||||
*/
|
||||
tryRedoOperations<T extends keyof ED>(operations: ({ operation: ED[T]['Operation']; entity: T })[]) {
|
||||
const context = this.contextBuilder!();
|
||||
context.begin();
|
||||
this.begin();
|
||||
try {
|
||||
for (const oper of operations) {
|
||||
const { entity, operation } = oper;
|
||||
this.cacheStore!.operate(entity, operation, context, {
|
||||
this.context!.operate(entity, operation, {
|
||||
dontCollect: true,
|
||||
dontCreateOper: true,
|
||||
dontCreateModi: true,
|
||||
});
|
||||
}
|
||||
context.rollback();
|
||||
this.rollback();
|
||||
return true;
|
||||
} catch (err) {
|
||||
context.rollback();
|
||||
this.rollback();
|
||||
if (!(err instanceof OakUserException)) {
|
||||
throw err;
|
||||
}
|
||||
|
|
@ -495,20 +495,27 @@ export class Cache<
|
|||
}
|
||||
|
||||
checkOperation<T extends keyof ED>(entity: T, action: ED[T]['Action'], data?: ED[T]['Update']['data'], filter?: ED[T]['Update']['filter'], checkerTypes?: CheckerType[]) {
|
||||
const context = this.contextBuilder!();
|
||||
context.begin();
|
||||
let autoCommit = false;
|
||||
if (!this.context) {
|
||||
this.begin();
|
||||
autoCommit = true;
|
||||
}
|
||||
const operation = {
|
||||
action,
|
||||
filter,
|
||||
data
|
||||
} as ED[T]['Update'];
|
||||
try {
|
||||
this.cacheStore!.check(entity, operation, context, checkerTypes);
|
||||
context.rollback();
|
||||
this.cacheStore!.check(entity, operation, this.context!, checkerTypes);
|
||||
if (autoCommit) {
|
||||
this.rollback();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (err) {
|
||||
context.rollback();
|
||||
if (autoCommit) {
|
||||
this.rollback();
|
||||
}
|
||||
if (!(err instanceof OakUserException)) {
|
||||
throw err;
|
||||
}
|
||||
|
|
@ -519,11 +526,12 @@ export class Cache<
|
|||
redoOperation(opers: Array<{
|
||||
entity: keyof ED;
|
||||
operation: ED[keyof ED]['Operation'];
|
||||
}>, context: FrontCxt) {
|
||||
}>) {
|
||||
assert(this.context);
|
||||
opers.forEach(
|
||||
(oper) => {
|
||||
const { entity, operation } = oper;
|
||||
this.cacheStore!.operate(entity, operation, context, {
|
||||
this.cacheStore!.operate(entity, operation, this.context!, {
|
||||
dontCollect: true,
|
||||
dontCreateOper: true,
|
||||
blockTrigger: true,
|
||||
|
|
@ -537,20 +545,30 @@ export class Cache<
|
|||
private getInner<T extends keyof ED>(
|
||||
entity: T,
|
||||
selection: ED[T]['Selection'],
|
||||
context: SyncContext<ED>,
|
||||
allowMiss?: boolean): Partial<ED[T]['Schema']>[] {
|
||||
let autoCommit = false;
|
||||
if (!this.context) {
|
||||
this.begin();
|
||||
autoCommit = true;
|
||||
}
|
||||
try {
|
||||
const result = this.cacheStore!.select(
|
||||
entity,
|
||||
selection,
|
||||
context,
|
||||
this.context!,
|
||||
{
|
||||
dontCollect: true,
|
||||
includedDeleted: true,
|
||||
}
|
||||
);
|
||||
if (autoCommit) {
|
||||
this.commit();
|
||||
}
|
||||
return result;
|
||||
} catch (err) {
|
||||
if (autoCommit) {
|
||||
this.rollback();
|
||||
}
|
||||
if (err instanceof OakRowUnexistedException) {
|
||||
if (!this.refreshing && !allowMiss) {
|
||||
const missedRows = err.getRows();
|
||||
|
|
@ -576,12 +594,9 @@ export class Cache<
|
|||
get<T extends keyof ED>(
|
||||
entity: T,
|
||||
selection: ED[T]['Selection'],
|
||||
context?: FrontCxt,
|
||||
allowMiss?: boolean
|
||||
) {
|
||||
const context2 = context || this.contextBuilder!();
|
||||
|
||||
return this.getInner(entity, selection, context2, allowMiss);
|
||||
return this.getInner(entity, selection, allowMiss);
|
||||
}
|
||||
|
||||
judgeRelation(entity: keyof ED, attr: string) {
|
||||
|
|
@ -605,16 +620,21 @@ export class Cache<
|
|||
}
|
||||
|
||||
begin() {
|
||||
const context = this.contextBuilder!();
|
||||
context.begin();
|
||||
return context;
|
||||
assert(!this.context);
|
||||
this.context = this.contextBuilder!();
|
||||
this.context.begin();
|
||||
return this.context;
|
||||
}
|
||||
|
||||
commit(context: FrontCxt) {
|
||||
context.commit();
|
||||
commit() {
|
||||
assert(this.context);
|
||||
this.context.commit();
|
||||
this.context = undefined;
|
||||
}
|
||||
|
||||
rollback(context: FrontCxt) {
|
||||
context.rollback();
|
||||
rollback() {
|
||||
assert(this.context);
|
||||
this.context.rollback();
|
||||
this.context = undefined;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,13 +240,13 @@ export class RelationAuth<
|
|||
this.baseRelationAuth.checkRelationSync(entity, operation, context);
|
||||
}
|
||||
catch (err) {
|
||||
context.rollback();
|
||||
this.cache.rollback();
|
||||
if (!(err instanceof OakUserException)) {
|
||||
throw err;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
context.rollback();
|
||||
this.cache.rollback();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ abstract class Node<
|
|||
return this.parent;
|
||||
}
|
||||
|
||||
protected getProjection(context?: FrontCxt): ED[T]['Selection']['data'] | undefined {
|
||||
protected getProjection(): ED[T]['Selection']['data'] | undefined {
|
||||
const projection = typeof this.projection === 'function' ? (this.projection as Function)() : (this.projection && cloneDeep(this.projection));
|
||||
|
||||
return projection;
|
||||
|
|
@ -320,7 +320,7 @@ class ListNode<
|
|||
此时对userRelation的删除动作就会导致user不会被移出list
|
||||
*/
|
||||
if (needRefresh) {
|
||||
const { filter, sorter } = this.constructSelection(true, false, undefined, true);
|
||||
const { filter, sorter } = this.constructSelection(true, false, true);
|
||||
if (filter) {
|
||||
const result = this.cache.get(this.getEntity(), {
|
||||
data: {
|
||||
|
|
@ -532,7 +532,7 @@ class ListNode<
|
|||
}
|
||||
}
|
||||
|
||||
getFreshValue(context: FrontCxt): Array<Partial<ED[T]['Schema']>> {
|
||||
getFreshValue(): Array<Partial<ED[T]['Schema']>> {
|
||||
/**
|
||||
* 满足当前结点的数据应当是所有满足当前filter条件且ids在当前ids中的数据
|
||||
* 但如果是当前事务create的行则例外(当前页面上正在create的数据)
|
||||
|
|
@ -545,7 +545,7 @@ class ListNode<
|
|||
*
|
||||
* 这里不能用sorter排序,enum的排序顺序目前前后台尚不一致 by Xc 20230809
|
||||
*/
|
||||
const { data, filter } = this.constructSelection(true, false, context, true);
|
||||
const { data, filter } = this.constructSelection(true, false, true);
|
||||
|
||||
if (filter || this.ids) {
|
||||
const filter2 = filter && this.ids ? {
|
||||
|
|
@ -562,7 +562,7 @@ class ListNode<
|
|||
const result = this.cache.get(this.entity, {
|
||||
data,
|
||||
filter: filter2,
|
||||
}, context, this.isLoading());
|
||||
}, this.isLoading());
|
||||
|
||||
|
||||
const r2 = result.filter(
|
||||
|
|
@ -607,7 +607,7 @@ class ListNode<
|
|||
id: { $in: finalIds },
|
||||
},
|
||||
sorter,
|
||||
}, context, this.isLoading()); */
|
||||
}, this.isLoading()); */
|
||||
}
|
||||
|
||||
addItem(
|
||||
|
|
@ -810,8 +810,8 @@ class ListNode<
|
|||
return operations;
|
||||
}
|
||||
|
||||
getProjection(context?: FrontCxt) {
|
||||
const projection = super.getProjection(context);
|
||||
getProjection() {
|
||||
const projection = super.getProjection();
|
||||
// List必须自主决定Projection
|
||||
/* if (this.children.length > 0) {
|
||||
const subProjection = await this.children[0].getProjection();
|
||||
|
|
@ -820,7 +820,7 @@ class ListNode<
|
|||
return projection;
|
||||
}
|
||||
|
||||
private constructFilters(context?: FrontCxt, withParent?: boolean, ignoreNewParent?: boolean, ignoreUnapplied?: true) {
|
||||
private constructFilters(withParent?: boolean, ignoreNewParent?: boolean, ignoreUnapplied?: true) {
|
||||
const { filters: ownFilters } = this;
|
||||
const filters = ownFilters.filter(
|
||||
ele => !ignoreUnapplied || ele.applied === true || ele.applied === undefined // 如果是undefined,说明不可以移除(构造时就存在),也得返回
|
||||
|
|
@ -834,7 +834,7 @@ class ListNode<
|
|||
|
||||
if (withParent && this.parent) {
|
||||
if (this.parent instanceof SingleNode) {
|
||||
const filterOfParent = this.parent.getParentFilter<T>(this, context, ignoreNewParent);
|
||||
const filterOfParent = this.parent.getParentFilter<T>(this, ignoreNewParent);
|
||||
if (filterOfParent) {
|
||||
filters.push(filterOfParent as any);
|
||||
} else {
|
||||
|
|
@ -848,9 +848,9 @@ class ListNode<
|
|||
return cloneDeep(filters);
|
||||
}
|
||||
|
||||
constructSelection(withParent?: true, ignoreNewParent?: boolean, context?: FrontCxt, ignoreUnapplied?: true) {
|
||||
constructSelection(withParent?: true, ignoreNewParent?: boolean, ignoreUnapplied?: true) {
|
||||
const { sorters } = this;
|
||||
const data = this.getProjection(context);
|
||||
const data = this.getProjection();
|
||||
assert(data, '取数据时找不到projection信息');
|
||||
const sorterArr = sorters.filter(
|
||||
ele => !ignoreUnapplied || ele.applied
|
||||
|
|
@ -863,7 +863,7 @@ class ListNode<
|
|||
})
|
||||
.filter((ele) => !!ele) as ED[T]['Selection']['sorter'];
|
||||
|
||||
const filters = this.constructFilters(context, withParent, ignoreNewParent, ignoreUnapplied);
|
||||
const filters = this.constructFilters(withParent, ignoreNewParent, ignoreUnapplied);
|
||||
|
||||
const filters2 = filters?.filter((ele) => !!ele);
|
||||
const filter = filters2 ? combineFilters<ED, T>(this.entity, this.schema, filters2) : undefined;
|
||||
|
|
@ -1122,8 +1122,8 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
unset(this.children, path);
|
||||
}
|
||||
|
||||
getFreshValue(context?: FrontCxt): Partial<ED[T]['Schema']> | undefined {
|
||||
const projection = this.getProjection(context, false);
|
||||
getFreshValue(): Partial<ED[T]['Schema']> | undefined {
|
||||
const projection = this.getProjection(false);
|
||||
const id = this.getId();
|
||||
if (projection) {
|
||||
const result = this.cache.get(this.entity, {
|
||||
|
|
@ -1131,7 +1131,7 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
filter: {
|
||||
id,
|
||||
},
|
||||
}, context, this.isLoading());
|
||||
}, this.isLoading());
|
||||
if (this.aggr) {
|
||||
merge(result[0], this.aggr);
|
||||
}
|
||||
|
|
@ -1311,17 +1311,17 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
}
|
||||
}
|
||||
|
||||
getProjection(context?: FrontCxt, withDecendants?: boolean) {
|
||||
getProjection(withDecendants?: boolean) {
|
||||
if (this.parent && this.parent instanceof ListNode) {
|
||||
return this.parent.getProjection(context);
|
||||
return this.parent.getProjection();
|
||||
}
|
||||
const projection = super.getProjection(context);
|
||||
const projection = super.getProjection();
|
||||
if (projection && withDecendants) {
|
||||
for (const k in this.children) {
|
||||
if (k.indexOf(':') === -1) {
|
||||
const rel = this.judgeRelation(k);
|
||||
if (rel === 2) {
|
||||
const subProjection = this.children[k].getProjection(context, true);
|
||||
const subProjection = this.children[k].getProjection(true);
|
||||
Object.assign(projection, {
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
|
|
@ -1329,7 +1329,7 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
});
|
||||
}
|
||||
else if (typeof rel === 'string') {
|
||||
const subProjection = this.children[k].getProjection(context, true);
|
||||
const subProjection = this.children[k].getProjection(true);
|
||||
Object.assign(projection, {
|
||||
[`${k}Id`]: 1,
|
||||
[k]: subProjection,
|
||||
|
|
@ -1359,7 +1359,7 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
return;
|
||||
}
|
||||
// SingleNode如果是非根结点,其id应该在第一次refresh的时候来确定
|
||||
const projection = this.getProjection(undefined, true);
|
||||
const projection = this.getProjection(true);
|
||||
const filter = this.getFilter();
|
||||
if (projection && filter) {
|
||||
this.setLoading(true);
|
||||
|
|
@ -1445,8 +1445,8 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
* @param disableOperation
|
||||
* @returns
|
||||
*/
|
||||
getParentFilter<T2 extends keyof ED>(childNode: Node<ED, keyof ED, Cxt, FrontCxt, AD>, context?: FrontCxt, ignoreNewParent?: boolean): ED[T2]['Selection']['filter'] | undefined {
|
||||
const value = this.getFreshValue(context);
|
||||
getParentFilter<T2 extends keyof ED>(childNode: Node<ED, keyof ED, Cxt, FrontCxt, AD>, ignoreNewParent?: boolean): ED[T2]['Selection']['filter'] | undefined {
|
||||
const value = this.getFreshValue();
|
||||
|
||||
if (value && value.$$createAt$$ === 1 && ignoreNewParent) {
|
||||
return;
|
||||
|
|
@ -1958,20 +1958,20 @@ export class RunningTree<
|
|||
const root = this.root[paths[0]];
|
||||
const includeModi = path.includes(MODI_NEXT_PATH_SUFFIX);
|
||||
if (node) {
|
||||
const context = this.cache.begin();
|
||||
this.cache.begin();
|
||||
assert(node instanceof ListNode || node instanceof SingleNode);
|
||||
if (includeModi) {
|
||||
const opers2 = node.getActiveModiOperations();
|
||||
if (opers2) {
|
||||
this.cache.redoOperation(opers2, context);
|
||||
this.cache.redoOperation(opers2);
|
||||
}
|
||||
}
|
||||
const opers = root?.composeOperations();
|
||||
if (opers) {
|
||||
this.cache.redoOperation(opers, context);
|
||||
this.cache.redoOperation(opers);
|
||||
}
|
||||
const value = node.getFreshValue(context);
|
||||
context.rollback();
|
||||
const value = node.getFreshValue();
|
||||
this.cache.rollback();
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ export function initialize<
|
|||
exec: async (name, params) => {
|
||||
const context = features2.cache.begin();
|
||||
const str = context.toString();
|
||||
context.commit();
|
||||
features2.cache.commit();
|
||||
const contextBackend = await backendContextBuilder(str)(debugStore);
|
||||
await contextBackend.begin();
|
||||
let result;
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ export function initialize<
|
|||
const wrapper: AspectWrapper<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> = {
|
||||
exec: async (name, params) => {
|
||||
const context = features2.cache.begin();
|
||||
context.commit();
|
||||
features.cache.commit();
|
||||
const { result, opRecords, message } = await connector.callAspect(name as string, params, context);
|
||||
return {
|
||||
result,
|
||||
|
|
|
|||
Loading…
Reference in New Issue