"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; }