oak-frontend-base/lib/features/cache.js

337 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Cache = void 0;
var tslib_1 = require("tslib");
var Feature_1 = require("../types/Feature");
var lodash_1 = require("oak-domain/lib/utils/lodash");
var Exception_1 = require("oak-domain/lib/types/Exception");
var assert_1 = tslib_1.__importDefault(require("assert"));
var Cache = /** @class */ (function (_super) {
tslib_1.__extends(Cache, _super);
function Cache(aspectWrapper, contextBuilder, store) {
var _this = _super.call(this) || this;
_this.refreshing = false;
_this.aspectWrapper = aspectWrapper;
_this.syncEventsCallbacks = [];
_this.contextBuilder = contextBuilder;
_this.cacheStore = store;
return _this;
// 在这里把wrapper的返回opRecords截取到并同步到cache中
/* const { exec } = aspectWrapper;
aspectWrapper.exec = async <T extends keyof AD>(
name: T,
params: any
) => {
const { result, opRecords } = await exec(name, params);
this.sync(opRecords);
return {
result,
opRecords,
};
}; */
}
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);
};
Cache.prototype.exec = function (name, params, callback) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _a, result, opRecords, message, e_1, opRecord;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
_b.trys.push([0, 2, , 3]);
return [4 /*yield*/, this.aspectWrapper.exec(name, params)];
case 1:
_a = _b.sent(), result = _a.result, opRecords = _a.opRecords, message = _a.message;
this.refreshing = false;
if (opRecords) {
this.sync(opRecords);
}
callback && callback(result, opRecords);
this.publish();
return [2 /*return*/, {
result: result,
message: message,
}];
case 2:
e_1 = _b.sent();
// 如果是数据不一致错误,这里可以让用户知道
if (e_1 instanceof Exception_1.OakException) {
opRecord = e_1.opRecord;
if (opRecord) {
this.sync([opRecord]);
this.publish();
}
}
throw e_1;
case 3: return [2 /*return*/];
}
});
});
};
Cache.prototype.refresh = function (entity, selection, option, getCount, callback) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _a, ids, count, aggr, selection2, data;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
this.refreshing = true;
return [4 /*yield*/, this.exec('select', {
entity: entity,
selection: selection,
option: option,
getCount: getCount,
}, callback)];
case 1:
_a = (_b.sent()).result, ids = _a.ids, count = _a.count, aggr = _a.aggr;
selection2 = Object.assign({}, selection, {
filter: {
id: {
$in: ids,
}
}
});
data = this.get(entity, selection2);
if (aggr) {
(0, lodash_1.merge)(data, aggr);
}
return [2 /*return*/, {
data: data,
count: count,
}];
}
});
});
};
Cache.prototype.aggregate = function (entity, aggregation, option) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var result;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.aspectWrapper.exec('aggregate', {
entity: entity,
aggregation: aggregation,
option: option,
})];
case 1:
result = (_a.sent()).result;
return [2 /*return*/, result];
}
});
});
};
Cache.prototype.operate = function (entity, operation, option, callback) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var result;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
this.refreshing = true;
return [4 /*yield*/, this.exec('operate', {
entity: entity,
operation: operation,
option: option,
}, callback)];
case 1:
result = _a.sent();
return [2 /*return*/, result];
}
});
});
};
Cache.prototype.count = function (entity, selection, option, callback) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var result;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.exec('count', {
entity: entity,
selection: selection,
option: option,
}, callback)];
case 1:
result = (_a.sent()).result;
return [2 /*return*/, result];
}
});
});
};
Cache.prototype.sync = function (records) {
// sync会异步并发的调用不能用this.context;
var context = this.contextBuilder();
this.cacheStore.sync(records, context);
// 唤起同步注册的回调
this.syncEventsCallbacks.map(function (ele) { return ele(records); });
};
/**
* 前端缓存做operation只可能是测试权限必然回滚
* @param entity
* @param operation
* @returns
*/
Cache.prototype.tryRedoOperations = function (operations) {
var e_2, _a;
var context = this.contextBuilder();
context.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, {
dontCollect: true,
dontCreateOper: true,
dontCreateModi: true,
});
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (operations_1_1 && !operations_1_1.done && (_a = operations_1.return)) _a.call(operations_1);
}
finally { if (e_2) throw e_2.error; }
}
context.rollback();
return true;
}
catch (err) {
context.rollback();
if (!(err instanceof Exception_1.OakUserException)) {
throw err;
}
return err;
}
};
Cache.prototype.checkOperation = function (entity, action, data, filter, checkerTypes) {
var context = this.contextBuilder();
context.begin();
var operation = {
action: action,
filter: filter,
data: data
};
try {
this.cacheStore.check(entity, operation, context, checkerTypes);
context.rollback();
return true;
}
catch (err) {
context.rollback();
if (!(err instanceof Exception_1.OakUserException)) {
throw err;
}
return false;
}
};
Cache.prototype.redoOperation = function (opers, context) {
var _this = this;
opers.forEach(function (oper) {
var entity = oper.entity, operation = oper.operation;
_this.cacheStore.operate(entity, operation, context, {
dontCollect: true,
dontCreateOper: true,
blockTrigger: true,
dontCreateModi: true,
});
});
return;
};
Cache.prototype.getInner = function (entity, selection, context, allowMiss) {
var _this = this;
try {
var result = this.cacheStore.select(entity, selection, context, {
dontCollect: true,
includedDeleted: true,
});
return result;
}
catch (err) {
if (err instanceof Exception_1.OakRowUnexistedException) {
if (!this.refreshing && !allowMiss) {
var missedRows_1 = err.getRows();
this.refreshing = true;
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;
var e_3, _c, e_4, _d;
return tslib_1.__generator(this, function (_e) {
try {
// missedRows理论上一定要取到不能为空集。否则就是程序员有遗漏
for (_a = tslib_1.__values(opRecords), _b = _a.next(); !_b.done; _b = _a.next()) {
record = _b.value;
d = record.d;
(0, assert_1.default)(Object.keys(d).length > 0, '在通过fetchRow取不一致数据时返回了空数据请拿该程序员祭天。');
try {
for (missedRows_2 = (e_4 = void 0, tslib_1.__values(missedRows_1)), missedRows_2_1 = missedRows_2.next(); !missedRows_2_1.done; missedRows_2_1 = missedRows_2.next()) {
mr = missedRows_2_1.value;
(0, assert_1.default)(Object.keys(d[mr.entity]).length > 0, "\u5728\u901A\u8FC7fetchRow\u53D6\u4E0D\u4E00\u81F4\u6570\u636E\u65F6\u8FD4\u56DE\u4E86\u7A7A\u6570\u636E\uFF0C\u8BF7\u62FF\u8BE5\u7A0B\u5E8F\u5458\u796D\u5929\u3002entity\u662F".concat(mr.entity));
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (missedRows_2_1 && !missedRows_2_1.done && (_d = missedRows_2.return)) _d.call(missedRows_2);
}
finally { if (e_4) throw e_4.error; }
}
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
}
finally { if (e_3) throw e_3.error; }
}
return [2 /*return*/];
});
}); });
}
return [];
}
else {
throw err;
}
}
};
Cache.prototype.get = function (entity, selection, context, allowMiss) {
var context2 = context || this.contextBuilder();
return this.getInner(entity, selection, context2, allowMiss);
};
Cache.prototype.judgeRelation = function (entity, attr) {
return this.cacheStore.judgeRelation(entity, attr);
};
Cache.prototype.bindOnSync = function (callback) {
this.syncEventsCallbacks.push(callback);
};
Cache.prototype.unbindOnSync = function (callback) {
(0, lodash_1.pull)(this.syncEventsCallbacks, callback);
};
Cache.prototype.getCachedData = function () {
return this.cacheStore.getCurrentData();
};
Cache.prototype.getFullData = function () {
return this.cacheStore.getFullData();
};
Cache.prototype.resetInitialData = function () {
return this.cacheStore.resetInitialData();
};
Cache.prototype.begin = function () {
var context = this.contextBuilder();
context.begin();
return context;
};
Cache.prototype.commit = function (context) {
context.commit();
};
Cache.prototype.rollback = function (context) {
context.rollback();
};
return Cache;
}(Feature_1.Feature));
exports.Cache = Cache;