优化了runningTree在refresh的时候不去fetch missing row

This commit is contained in:
Xu Chang 2023-04-13 13:40:46 +08:00
parent d33a831f3f
commit 42e9639f5c
6 changed files with 44 additions and 25 deletions

View File

@ -45,7 +45,7 @@ export declare class Cache<ED extends EntityDict & BaseEntityDict, Cxt extends A
operation: ED[keyof ED]['Operation'];
}>, context: FrontCxt): void;
private getInner;
get<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], context?: FrontCxt): Partial<ED[T]["Schema"]>[];
get<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], context?: FrontCxt, allowMiss?: boolean): Partial<ED[T]["Schema"]>[];
judgeRelation(entity: keyof ED, attr: string): string | 0 | 1 | 2 | string[];
bindOnSync(callback: (opRecords: OpRecord<ED>[]) => void): void;
unbindOnSync(callback: (opRecords: OpRecord<ED>[]) => void): void;

View File

@ -232,18 +232,18 @@ var Cache = /** @class */ (function (_super) {
});
return;
};
Cache.prototype.getInner = function (entity, selection, context, includedDeleted) {
Cache.prototype.getInner = function (entity, selection, context, allowMiss) {
var _this = this;
try {
var result = this.cacheStore.select(entity, selection, context, {
dontCollect: true,
includedDeleted: includedDeleted || undefined,
includedDeleted: true,
});
return result;
}
catch (err) {
if (err instanceof Exception_1.OakRowUnexistedException) {
if (!this.refreshing) {
if (!this.refreshing && !allowMiss) {
var missedRows_1 = err.getRows();
this.exec('fetchRows', missedRows_1, function (result, opRecords) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
var _a, _b, record, d, missedRows_2, missedRows_2_1, mr;
@ -288,9 +288,9 @@ var Cache = /** @class */ (function (_super) {
}
}
};
Cache.prototype.get = function (entity, selection, context) {
Cache.prototype.get = function (entity, selection, context, allowMiss) {
var context2 = context || this.contextBuilder();
return this.getInner(entity, selection, context2);
return this.getInner(entity, selection, context2, allowMiss);
};
Cache.prototype.judgeRelation = function (entity, attr) {
return this.cacheStore.judgeRelation(entity, attr);

View File

@ -94,7 +94,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(context: FrontCxt, allowMiss?: boolean): 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;
@ -149,7 +149,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(context?: FrontCxt, allowMiss?: boolean): 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;
@ -219,6 +219,7 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict, Cxt ext
private schema;
private authDict;
private root;
private refreshing;
constructor(cache: Cache<ED, Cxt, FrontCxt, AD>, schema: StorageSchema<ED>, authDict: AuthDefDict<ED>);
createNode<T extends keyof ED>(options: CreateNodeOptions<ED, T>): SingleNode<ED, keyof ED, Cxt, FrontCxt, AD> | ListNode<ED, keyof ED, Cxt, FrontCxt, AD> | VirtualNode<ED, Cxt, FrontCxt, AD>;
private findNode;

View File

@ -568,7 +568,7 @@ var ListNode = /** @class */ (function (_super) {
this.publish();
}
};
ListNode.prototype.getFreshValue = function (context) {
ListNode.prototype.getFreshValue = function (context, allowMiss) {
var _this = this;
/**
* 满足当前结点的数据应当是所有满足当前filter条件且ids在当前ids中的数据
@ -579,7 +579,7 @@ var ListNode = /** @class */ (function (_super) {
data: data,
filter: filter,
sorter: sorter,
}, context);
}, context, allowMiss);
return result.filter(function (ele) { var _a; return ele.$$createAt$$ === 1 || ((_a = _this.ids) === null || _a === void 0 ? void 0 : _a.includes(ele.id)); });
};
ListNode.prototype.addItem = function (item, beforeExecute, afterExecute) {
@ -1075,7 +1075,7 @@ var SingleNode = /** @class */ (function (_super) {
SingleNode.prototype.removeChild = function (path) {
(0, lodash_1.unset)(this.children, path);
};
SingleNode.prototype.getFreshValue = function (context) {
SingleNode.prototype.getFreshValue = function (context, allowMiss) {
var projection = this.getProjection(context, false);
var id = this.id;
if (projection) {
@ -1084,7 +1084,7 @@ var SingleNode = /** @class */ (function (_super) {
filter: {
id: id,
},
}, context);
}, context, allowMiss);
return result[0];
}
};
@ -1704,6 +1704,7 @@ var RunningTree = /** @class */ (function (_super) {
tslib_1.__extends(RunningTree, _super);
function RunningTree(cache, schema, authDict) {
var _this = _super.call(this) || this;
_this.refreshing = false;
// this.aspectWrapper = aspectWrapper;
_this.cache = cache;
_this.schema = schema;
@ -1817,7 +1818,6 @@ var RunningTree = /** @class */ (function (_super) {
var node = this.findNode(path);
var paths = path.split('.');
var root = this.root[paths[0]];
// todo 判定modi
var includeModi = path.includes(':next');
if (node) {
var context_1 = this.cache.begin();
@ -1832,7 +1832,7 @@ var RunningTree = /** @class */ (function (_super) {
if (opers) {
this.cache.redoOperation(opers, context_1);
}
var value = node.getFreshValue(context_1);
var value = node.getFreshValue(context_1, this.refreshing);
context_1.rollback();
return value;
}
@ -1901,6 +1901,7 @@ var RunningTree = /** @class */ (function (_super) {
switch (_a.label) {
case 0:
node = this.findNode(path);
this.refreshing = true;
if (!(node instanceof ListNode)) return [3 /*break*/, 2];
return [4 /*yield*/, node.refresh(1, true)];
case 1:
@ -1912,7 +1913,9 @@ var RunningTree = /** @class */ (function (_super) {
case 3:
_a.sent();
_a.label = 4;
case 4: return [2 /*return*/];
case 4:
this.refreshing = false;
return [2 /*return*/];
}
});
});
@ -1924,10 +1927,12 @@ var RunningTree = /** @class */ (function (_super) {
switch (_a.label) {
case 0:
node = this.findNode(path);
this.refreshing = true;
(0, assert_1.assert)(node instanceof ListNode);
return [4 /*yield*/, node.loadMore()];
case 1:
_a.sent();
this.refreshing = false;
return [2 /*return*/];
}
});
@ -2081,6 +2086,7 @@ var RunningTree = /** @class */ (function (_super) {
operations = node.composeOperations();
entities = (0, lodash_1.uniq)(operations.filter(function (ele) { return !!ele; }).map(function (ele) { return ele.entity; }));
(0, assert_1.assert)(entities.length === 1);
this.refreshing = true;
return [4 /*yield*/, this.cache.operate(entities[0], operations
.filter(function (ele) { return !!ele; })
.map(function (ele) { return ele.operation; }), undefined, function () {
@ -2090,6 +2096,7 @@ var RunningTree = /** @class */ (function (_super) {
})];
case 3:
result = _a.sent();
this.refreshing = false;
return [4 /*yield*/, node.doAfterTrigger()];
case 4:
_a.sent();

View File

@ -235,7 +235,11 @@ export class Cache<
return;
}
private getInner<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], context: SyncContext<ED>, includedDeleted?: boolean): Partial<ED[T]['Schema']>[] {
private getInner<T extends keyof ED>(
entity: T,
selection: ED[T]['Selection'],
context: SyncContext<ED>,
allowMiss?: boolean): Partial<ED[T]['Schema']>[] {
try {
const result = this.cacheStore!.select(
entity,
@ -243,13 +247,13 @@ export class Cache<
context,
{
dontCollect: true,
includedDeleted: includedDeleted || undefined,
includedDeleted: true,
}
);
return result;
} catch (err) {
if (err instanceof OakRowUnexistedException) {
if (!this.refreshing) {
if (!this.refreshing && !allowMiss) {
const missedRows = err.getRows();
this.exec('fetchRows', missedRows, async (result, opRecords) => {
// missedRows理论上一定要取到不能为空集。否则就是程序员有遗漏
@ -273,10 +277,11 @@ export class Cache<
entity: T,
selection: ED[T]['Selection'],
context?: FrontCxt,
allowMiss?: boolean
) {
const context2 = context || this.contextBuilder!();
return this.getInner(entity, selection, context2);
return this.getInner(entity, selection, context2, allowMiss);
}
judgeRelation(entity: keyof ED, attr: string) {

View File

@ -691,7 +691,7 @@ class ListNode<
}
}
getFreshValue(context: FrontCxt): Array<Partial<ED[T]['Schema']>> {
getFreshValue(context: FrontCxt, allowMiss?: boolean): Array<Partial<ED[T]['Schema']>> {
/**
* filter条件且ids在当前ids中的数据
* create的行则例外create的数据
@ -702,7 +702,7 @@ class ListNode<
data,
filter,
sorter,
}, context);
}, context, allowMiss);
return result.filter(
ele => ele.$$createAt$$ === 1 || this.ids?.includes(ele.id!)
);
@ -1188,7 +1188,7 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
unset(this.children, path);
}
getFreshValue(context?: FrontCxt): Partial<ED[T]['Schema']> | undefined {
getFreshValue(context?: FrontCxt, allowMiss?: boolean): Partial<ED[T]['Schema']> | undefined {
const projection = this.getProjection(context, false);
const { id } = this;
if (projection) {
@ -1197,7 +1197,7 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
filter: {
id,
},
}, context);
}, context, allowMiss);
return result[0];
}
}
@ -1772,6 +1772,7 @@ export class RunningTree<
| ListNode<ED, keyof ED, Cxt, FrontCxt, AD>
| VirtualNode<ED, Cxt, FrontCxt, AD>
>;
private refreshing = false;
constructor(
cache: Cache<ED, Cxt, FrontCxt, AD>,
@ -1930,7 +1931,6 @@ export class RunningTree<
const node = this.findNode(path);
const paths = path.split('.');
const root = this.root[paths[0]];
// todo 判定modi
const includeModi = path.includes(':next');
if (node) {
const context = this.cache.begin();
@ -1945,7 +1945,7 @@ export class RunningTree<
if (opers) {
this.cache.redoOperation(opers, context);
}
const value = node.getFreshValue(context);
const value = node.getFreshValue(context, this.refreshing);
context.rollback();
return value;
}
@ -2056,17 +2056,21 @@ export class RunningTree<
async refresh(path: string) {
const node = this.findNode(path);
this.refreshing = true;
if (node instanceof ListNode) {
await node.refresh(1, true);
} else if (node) {
await node.refresh();
}
this.refreshing = false;
}
async loadMore(path: string) {
const node = this.findNode(path);
this.refreshing = true;
assert(node instanceof ListNode);
await node.loadMore();
this.refreshing = false;
}
getPagination(path: string) {
@ -2258,6 +2262,7 @@ export class RunningTree<
);
assert(entities.length === 1);
this.refreshing = true;
const result = await this.cache.operate(
entities[0],
operations
@ -2270,6 +2275,7 @@ export class RunningTree<
node.setExecuting(false);
}
);
this.refreshing = false;
await node.doAfterTrigger();