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

222 lines
8.6 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 = exports.clearMaterializedData = void 0;
const node_schedule_1 = require("node-schedule");
const constant_1 = require("../constant/constant");
const DebugStore_1 = require("./DebugStore");
const assert_1 = require("oak-domain/lib/utils/assert");
const uuid_1 = require("oak-domain/lib/utils/uuid");
async function initDataInStore(store, initialData, stat) {
store.resetInitialData(initialData, stat);
}
async function getMaterializedData(loadFn) {
try {
const data = await loadFn(constant_1.LOCAL_STORAGE_KEYS.debugStore);
const stat = await loadFn(constant_1.LOCAL_STORAGE_KEYS.debugStoreStat);
if (data && stat) {
return {
data,
stat,
};
}
return;
}
catch (e) {
return;
}
}
let lastMaterializedVersion = 0;
async function materializeData(data, stat, saveFn) {
try {
await saveFn(constant_1.LOCAL_STORAGE_KEYS.debugStore, data);
await saveFn(constant_1.LOCAL_STORAGE_KEYS.debugStoreStat, stat);
lastMaterializedVersion = stat.commit;
console.log('物化数据', data);
}
catch (e) {
console.error(e);
}
}
function clearMaterializedData() {
if (process.env.OAK_PLATFORM === 'wechatMp') {
try {
wx.removeStorageSync(constant_1.LOCAL_STORAGE_KEYS.debugStore);
wx.removeStorageSync(constant_1.LOCAL_STORAGE_KEYS.debugStoreStat);
lastMaterializedVersion = 0;
wx.showToast({
title: '数据已清除',
icon: 'success',
});
console.log('清空数据');
}
catch (e) {
console.error(e);
wx.showToast({
title: '清空数据失败',
icon: 'error',
});
}
}
else if (process.env.OAK_PLATFORM === 'web') {
try {
window.localStorage.removeItem(constant_1.LOCAL_STORAGE_KEYS.debugStore);
window.localStorage.removeItem(constant_1.LOCAL_STORAGE_KEYS.debugStoreStat);
lastMaterializedVersion = 0;
console.log('清空数据');
// alert('数据已物化');
}
catch (e) {
console.error(e);
// alert('物化数据失败');
}
}
}
exports.clearMaterializedData = clearMaterializedData;
/**
* 在debug环境上创建watcher
* @param store
* @param watchers
*/
function initializeWatchers(store, contextBuilder, watchers) {
let count = 0;
async function doWatchers() {
count++;
const start = Date.now();
const context = await contextBuilder()(store);
for (const w of watchers) {
await context.begin();
try {
if (w.hasOwnProperty('actionData')) {
const { entity, action, filter, actionData } = w;
const filter2 = typeof filter === 'function' ? await filter() : filter;
const data = typeof actionData === 'function' ? await actionData() : actionData; // 这里有个奇怪的编译错误,不理解 by Xc
const result = await store.operate(entity, {
id: await (0, uuid_1.generateNewIdAsync)(),
action,
data,
filter: filter2
}, context, {
dontCollect: true,
});
console.log(`执行了watcher【${w.name}】,结果是:`, result);
}
else {
const { entity, projection, fn, filter } = w;
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,
});
if (rows.length > 0) {
const result = await fn(context, rows);
console.log(`执行了watcher【${w.name}】,结果是:`, result);
}
}
await context.commit();
}
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, fn, name } = timer;
(0, node_schedule_1.scheduleJob)(name, cron, async (date) => {
const start = Date.now();
const context = await contextBuilder()(store);
await context.begin();
console.log(`定时器【${name}】开始执行,时间是【${date.toLocaleTimeString()}`);
try {
const result = await fn(context);
console.log(`定时器【${name}】执行完成,耗时${Date.now() - start}毫秒,结果是【${result}`);
await context.commit();
}
catch (err) {
console.warn(`定时器【${name}】执行失败,耗时${Date.now() - start}毫秒,错误是`, err);
await context.rollback();
}
});
}
}
async function doRoutines(store, contextBuilder, routines) {
for (const routine of routines) {
const { name, fn } = routine;
const context = await contextBuilder()(store);
const start = Date.now();
await context.begin();
try {
const result = await fn(context);
console.log(`例程【${name}】执行完成,耗时${Date.now() - start}毫秒,结果是【${result}`);
await context.commit();
}
catch (err) {
console.warn(`例程【${name}】执行失败,耗时${Date.now() - start}毫秒,错误是`, err);
await context.rollback();
}
}
}
function createDebugStore(storageSchema, contextBuilder, triggers, checkers, watchers, timers, startRoutines, initialData, actionDict, authDeduceRelationMap, saveFn, loadFn, selectFreeEntities, updateFreeDict) {
const store = new DebugStore_1.DebugStore(storageSchema, contextBuilder, authDeduceRelationMap, selectFreeEntities, updateFreeDict);
triggers.forEach(ele => store.registerTrigger(ele));
checkers.forEach(ele => store.registerChecker(ele));
(0, assert_1.assert)(actionDict);
// 如果没有物化数据则使用initialData初始化debugStore
const loadInitialData = async () => {
const data = await getMaterializedData(loadFn);
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, saveFn);
}
});
// 启动watcher
initializeWatchers(store, contextBuilder, watchers);
// 启动timer
if (timers) {
initializeTimers(store, contextBuilder, timers);
}
// 启动startRoutine
if (startRoutines) {
doRoutines(store, contextBuilder, startRoutines);
}
return store;
}
exports.createDebugStore = createDebugStore;