oak-frontend-base/lib/debugStore/index.js

226 lines
8.9 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.createDebugStore = createDebugStore;
const node_schedule_1 = require("node-schedule");
const constant_1 = require("../constant/constant");
const DebugStore_1 = require("./DebugStore");
const IntrinsicLogics_1 = require("oak-domain/lib/store/IntrinsicLogics");
const uuid_1 = require("oak-domain/lib/utils/uuid");
const localStorage_1 = require("../features/localStorage");
const lodash_1 = require("oak-domain/lib/utils/lodash");
async function initDataInStore(store, initialData, stat) {
store.resetInitialData(initialData, stat);
}
async function getMaterializedData(localStorage) {
try {
const data = await localStorage.load(constant_1.LOCAL_STORAGE_KEYS.debugStore);
const stat = await localStorage.load(constant_1.LOCAL_STORAGE_KEYS.debugStoreStat);
if (data && stat) {
return {
data,
stat,
};
}
return;
}
catch (e) {
return;
}
}
let lastMaterializedVersion = 0;
async function materializeData(data, stat, localStorage) {
try {
await localStorage.save(constant_1.LOCAL_STORAGE_KEYS.debugStore, data);
await localStorage.save(constant_1.LOCAL_STORAGE_KEYS.debugStoreStat, stat);
lastMaterializedVersion = stat.commit;
console.log('物化数据', data);
}
catch (e) {
console.error(e);
}
}
async function execWatcher(store, watcher, context) {
if (watcher.hasOwnProperty('actionData')) {
const { entity, action, filter, actionData } = watcher;
const filter2 = typeof filter === 'function' ? await filter() : (0, lodash_1.cloneDeep)(filter);
const data = typeof actionData === 'function' ? await actionData() : (0, lodash_1.cloneDeep)(actionData); // 这里有个奇怪的编译错误,不理解 by Xc
const result = await store.operate(entity, {
id: await (0, uuid_1.generateNewIdAsync)(),
action: action,
data,
filter: filter2
}, context, {
dontCollect: true,
});
await context.commit();
return result;
}
else {
const { entity, projection, fn, filter } = watcher;
const filter2 = typeof filter === 'function' ? await filter() : filter;
const projection2 = typeof projection === 'function' ? await projection() : projection;
const rows = await store.select(entity, {
data: projection2,
filter: filter2,
}, context, {
dontCollect: true,
blockTrigger: true,
});
let result = {};
if (rows.length > 0) {
result = await fn(context, rows);
}
await context.commit();
return result;
}
}
/**
* 在debug环境上创建watcher
* @param store
* @param watchers
*/
function initializeWatchers(store, contextBuilder, watchers) {
let count = 0;
async function doWatchers() {
count++;
const start = Date.now();
const context = contextBuilder(store);
await context.begin();
await context.initialize();
for (const w of watchers) {
try {
const result = await execWatcher(store, w, context);
await context.commit();
console.log(`执行了watcher【${w.name}】成功,结果是:`, result);
}
catch (err) {
await context.rollback();
console.error(`尝试执行watcher【${w.name}】,发生错误:`, err);
}
}
const duration = Date.now() - start;
console.log(`${count}次执行watchers共执行${watchers.length}个,耗时${duration}毫秒`);
setTimeout(() => doWatchers(), 120000);
}
doWatchers();
}
function initializeTimers(store, contextBuilder, timers) {
if (process.env.OAK_PLATFORM === 'wechatMp') {
const { platform } = wx.getSystemInfoSync();
if (platform !== 'devtools') {
// 在真机调试环境下timer中调用Intl会挂
return;
}
}
for (const timer of timers) {
const { cron, name } = timer;
(0, node_schedule_1.scheduleJob)(name, cron, async (date) => {
const start = Date.now();
const context = contextBuilder(store);
await context.begin();
console.log(`定时器【${name}】开始执行,时间是【${date.toLocaleTimeString()}`);
try {
await context.initialize();
let result = {};
if (timer.hasOwnProperty('entity')) {
result = (await execWatcher(store, timer, context));
}
else {
const { timer: timerFn } = timer;
result = await timerFn(context);
}
await context.commit();
console.log(`定时器【${name}】执行完成,耗时${Date.now() - start}毫秒,结果是【${result}`);
}
catch (err) {
await context.rollback();
console.warn(`定时器【${name}】执行失败,耗时${Date.now() - start}毫秒,错误是`, err);
}
});
}
}
async function doRoutines(store, contextBuilder, routines) {
for (const routine of routines) {
if (routine.hasOwnProperty('entity')) {
const { name } = routine;
const context = contextBuilder(store);
const start = Date.now();
await context.begin();
try {
await context.initialize();
const result = await execWatcher(store, routine, context);
await context.commit();
console.log(`例程【${name}】执行完成,耗时${Date.now() - start}毫秒,结果是`, result);
}
catch (err) {
await context.rollback();
console.warn(`例程【${name}】执行失败,耗时${Date.now() - start}毫秒,错误是`, err);
}
}
else {
const { name, routine: routineFn } = routine;
const context = contextBuilder(store);
const start = Date.now();
await context.begin();
try {
await context.initialize();
const result = await routineFn(context, {});
await context.commit();
console.log(`例程【${name}】执行完成,耗时${Date.now() - start}毫秒,结果是`, result);
}
catch (err) {
await context.rollback();
console.warn(`例程【${name}】执行失败,耗时${Date.now() - start}毫秒,错误是`, err);
}
}
}
}
function createDebugStore(storageSchema, contextBuilder, triggers, checkers, watchers, timers, startRoutines, initialData, common) {
const store = new DebugStore_1.DebugStore(storageSchema, contextBuilder, common.authDeduceRelationMap, common.selectFreeEntities, common.updateFreeDict);
triggers.forEach(ele => store.registerTrigger(ele));
checkers.forEach(ele => store.registerChecker(ele));
const intrinsicLogics = (0, IntrinsicLogics_1.makeIntrinsicLogics)(storageSchema, common.actionDefDict, common.attrUpdateMatrix);
intrinsicLogics.checkers.forEach(ele => store.registerChecker(ele));
intrinsicLogics.triggers.forEach(ele => store.registerTrigger(ele));
const localStorage = new localStorage_1.LocalStorage();
// 如果没有物化数据则使用initialData初始化debugStore
const loadInitialData = async () => {
const data = await getMaterializedData(localStorage);
if (!data) {
initDataInStore(store, initialData);
console.log('使用初始化数据建立debugStore', initialData);
}
else {
// 对static的对象使用initialData剩下的使用物化数据
for (const entity in initialData) {
if (storageSchema[entity].static) {
data.data[entity] = initialData[entity];
}
}
initDataInStore(store, data.data, data.stat);
console.log('使用物化数据建立debugStore', data);
}
};
loadInitialData();
lastMaterializedVersion = store.getStat().commit;
// 当store中有更新事务提交时物化store数据
store.onCommit(async (result) => {
if (Object.keys(result).length > 0) {
const stat = store.getStat();
const data = store.getCurrentData();
await materializeData(data, stat, localStorage);
}
});
// 启动watcher
initializeWatchers(store, contextBuilder, watchers.concat(intrinsicLogics.watchers));
// 启动timer
if (timers) {
initializeTimers(store, contextBuilder, timers);
}
// 启动startRoutine
if (startRoutines) {
doRoutines(store, contextBuilder, startRoutines);
}
return store;
}