This commit is contained in:
Xu Chang 2022-06-02 13:53:01 +08:00
parent 53a96f2cb7
commit 684f51a4fd
14 changed files with 84 additions and 41 deletions

View File

@ -3,7 +3,7 @@ export declare function operate<ED extends EntityDict, T extends keyof ED, Cxt e
entity: T;
operation: ED[T]['Operation'] | ED[T]['Operation'][];
params?: OperateParams;
}, context: Cxt): Promise<import("oak-domain/lib/types").OperationResult | Promise<import("oak-domain/lib/types").OperationResult>[]>;
}, context: Cxt): Promise<import("oak-domain/lib/types").OperationResult<ED> | Promise<import("oak-domain/lib/types").OperationResult<ED>>[]>;
export declare function select<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>>(options: {
entity: T;
selection: ED[T]['Selection'];

View File

@ -9,7 +9,7 @@ export declare class CacheStore<ED extends EntityDict, Cxt extends Context<ED>>
[ID: string]: ED[T]['OpSchema'];
};
});
operate<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Cxt, params?: Object): Promise<OperationResult>;
operate<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Cxt, params?: Object): Promise<OperationResult<ED>>;
select<T extends keyof ED, S extends ED[T]['Selection']>(entity: T, selection: S, context: Cxt, params?: Object): Promise<import("oak-domain/lib/types").SelectionResult<ED[T]["Schema"], S["data"]>>;
registerChecker<T extends keyof ED>(checker: Checker<ED, T, Cxt>): void;
}

View File

@ -17,9 +17,9 @@ export declare class DebugStore<ED extends EntityDict, Cxt extends Context<ED>>
remove: number;
commit: number;
});
protected cascadeUpdate<T extends keyof ED>(entity: T, operation: DeduceCreateOperation<ED[T]["Schema"]> | DeduceUpdateOperation<ED[T]["Schema"]> | DeduceRemoveOperation<ED[T]["Schema"]>, context: Cxt, params?: OperateParams): Promise<void>;
protected cascadeUpdate<T extends keyof ED>(entity: T, operation: DeduceCreateOperation<ED[T]["Schema"]> | DeduceUpdateOperation<ED[T]["Schema"]> | DeduceRemoveOperation<ED[T]["Schema"]>, context: Cxt, params?: OperateParams): Promise<OperationResult<ED>>;
protected cascadeSelect<T extends keyof ED>(entity: T, selection: ED[T]["Selection"], context: Cxt, params?: OperateParams): Promise<ED[T]["Schema"][]>;
operate<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Cxt, params?: DebugStoreOperationParams): Promise<OperationResult>;
operate<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Cxt, params?: DebugStoreOperationParams): Promise<OperationResult<ED>>;
select<T extends keyof ED, S extends ED[T]['Selection']>(entity: T, selection: S, context: Cxt, params?: DebugStoreOperationParams): Promise<SelectionResult<ED[T]["Schema"], S["data"]>>;
registerTrigger<T extends keyof ED>(trigger: Trigger<ED, T, Cxt>): void;
registerChecker<T extends keyof ED>(checker: Checker<ED, T, Cxt>): void;

View File

@ -1,5 +1,5 @@
import { DebugStore } from './debugStore';
import { Checker, Trigger, StorageSchema, FormCreateData, Context, EntityDict, RowStore, ActionDictOfEntityDict } from "oak-domain/lib/types";
export declare function createDebugStore<ED extends EntityDict, Cxt extends Context<ED>>(storageSchema: StorageSchema<ED>, createContext: (store: RowStore<ED, Cxt>, scene: string) => Cxt, triggers?: Array<Trigger<ED, keyof ED, Cxt>>, checkers?: Array<Checker<ED, keyof ED, Cxt>>, initialData?: {
import { Checker, Trigger, StorageSchema, FormCreateData, Context, EntityDict, RowStore, ActionDictOfEntityDict, Watcher } from "oak-domain/lib/types";
export declare function createDebugStore<ED extends EntityDict, Cxt extends Context<ED>>(storageSchema: StorageSchema<ED>, createContext: (store: RowStore<ED, Cxt>, scene: string) => Cxt, triggers: Array<Trigger<ED, keyof ED, Cxt>>, checkers: Array<Checker<ED, keyof ED, Cxt>>, watchers: Array<Watcher<ED, keyof ED, Cxt>>, initialData?: {
[T in keyof ED]?: Array<FormCreateData<ED[T]['OpSchema']>>;
}, actionDict?: ActionDictOfEntityDict<ED>): DebugStore<ED, Cxt>;

View File

@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.createDebugStore = void 0;
const debugStore_1 = require("./debugStore");
const actionDef_1 = require("oak-domain/lib/store/actionDef");
const watchers_1 = require("oak-domain/lib/store/watchers");
async function initDataInStore(store, createContext, initialData) {
store.startInitializing();
if (false) {
@ -62,7 +63,59 @@ function materializeData(data, stat) {
}
}
}
function createDebugStore(storageSchema, createContext, triggers, checkers, initialData, actionDict) {
/**
* 在debug环境上创建watcher
* @param store
* @param watchers
*/
function initializeWatchers(store, createContext, watchers) {
const schema = store.getSchema();
const intrinsicWatchers = (0, watchers_1.makeIntrinsicWatchers)(schema);
const totalWatchers = watchers.concat(intrinsicWatchers);
let count = 0;
async function doWatchers() {
count++;
const start = Date.now();
const context = createContext(store, 'doWatchers');
for (const w of totalWatchers) {
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, {
action,
data,
filter: filter2
}, context);
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 { result: rows } = await store.select(entity, {
data: projection2,
filter: filter2,
}, context);
const result = 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共执行${totalWatchers.length}个,耗时${duration}毫秒`);
setTimeout(() => doWatchers(), 120000);
}
doWatchers();
}
function createDebugStore(storageSchema, createContext, triggers, checkers, watchers, initialData, actionDict) {
const data = getMaterializedData();
const store = new debugStore_1.DebugStore(storageSchema, createContext, data && data.data, data && data.stat);
triggers?.forEach(ele => store.registerTrigger(ele));
@ -90,6 +143,8 @@ function createDebugStore(storageSchema, createContext, triggers, checkers, init
const data = store.getCurrentData();
materializeData(data, stat);
}, 10000);
// 启动watcher
initializeWatchers(store, createContext, watchers);
return store;
}
exports.createDebugStore = createDebugStore;

View File

@ -21,7 +21,7 @@ export declare class Cache<ED extends EntityDict, Cxt extends Context<ED>, AD ex
* @param params
* @returns
*/
operate<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], scene: string, params?: OperateParams): Promise<OperationResult>;
operate<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], scene: string, params?: OperateParams): Promise<OperationResult<ED>>;
get<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], scene: string, params?: object): Promise<import("oak-domain/lib/types").SelectRowShape<ED[T]["Schema"], ED[T]["Selection"]["data"]>[]>;
judgeRelation(entity: keyof ED, attr: string): string | 0 | 2 | 1 | string[];
bindOnSync(callback: (opRecords: OpRecord<ED>[]) => Promise<void>): void;

View File

@ -404,14 +404,13 @@ class ListNode extends Node {
if (e === this.entity) {
const { id } = d;
const filter = (0, filter_1.combineFilters)([{ id }, ...(this.filters).map(ele => ele.filter)]);
const { ids } = await this.cache.operate(e, {
const rows = await this.cache.get(e, {
data: {
id: 1,
},
filter,
action: 'select',
}, 'onRecordSynchoronized', { obscure: true });
if (ids.length > 0) {
if (rows.length > 0) {
// todo 这里更严格应该还要考虑sorter但前端可能没有完整的供sort用的cache数据
this.ids.push(id);
needReGetValue = true;
@ -439,14 +438,13 @@ class ListNode extends Node {
}
else {
const filter = (0, filter_1.combineFilters)([{ id }, ...(this.filters.map(ele => ele.filter))]);
const { ids } = await this.cache.operate(e, {
const rows = await this.cache.get(e, {
data: {
id: 1,
},
filter,
action: 'select',
}, 'onRecordSynchoronized', { obscure: true });
if (ids.length > 0) {
if (rows.length > 0) {
// todo 这里更严格应该还要考虑sorter但前端可能没有完整的供sort用的cache数据
this.ids.push(id);
needReGetValue = true;

View File

@ -1,11 +1,7 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];

4
lib/initialize.d.ts vendored
View File

@ -1,9 +1,9 @@
import { Aspect, Checker, Trigger, StorageSchema, Context, RowStore } from "oak-domain/lib/types";
import { Aspect, Checker, Trigger, StorageSchema, Context, RowStore, Watcher } from "oak-domain/lib/types";
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { Feature, subscribe } from './types/Feature';
import { BasicFeatures } from './features';
import { ActionDictOfEntityDict } from "oak-domain/lib/types/Action";
export declare function initialize<ED extends EntityDict, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD>>>(storageSchema: StorageSchema<ED>, createFeatures: (basicFeatures: BasicFeatures<ED, Cxt, AD>) => FD, createContext: (store: RowStore<ED, Cxt>, scene: string) => Cxt, triggers?: Array<Trigger<ED, keyof ED, Cxt>>, checkers?: Array<Checker<ED, keyof ED, Cxt>>, aspectDict?: AD, initialData?: {
export declare function initialize<ED extends EntityDict, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD>>>(storageSchema: StorageSchema<ED>, createFeatures: (basicFeatures: BasicFeatures<ED, Cxt, AD>) => FD, createContext: (store: RowStore<ED, Cxt>, scene: string) => Cxt, triggers?: Array<Trigger<ED, keyof ED, Cxt>>, checkers?: Array<Checker<ED, keyof ED, Cxt>>, watchers?: Array<Watcher<ED, keyof ED, Cxt>>, aspectDict?: AD, initialData?: {
[T in keyof ED]?: Array<ED[T]['OpSchema']>;
}, actionDict?: ActionDictOfEntityDict<ED>): {
subscribe: typeof subscribe;

View File

@ -1,11 +1,7 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
@ -25,14 +21,14 @@ const features_1 = require("./features");
const lodash_1 = require("lodash");
const aspects_1 = __importDefault(require("./aspects"));
const actionDef_1 = require("oak-domain/lib/store/actionDef");
function createAspectProxy(storageSchema, createContext, triggers, checkers, features, aspectDict, initialData, actionDict) {
function createAspectProxy(storageSchema, createContext, triggers, checkers, watchers, features, aspectDict, initialData, actionDict) {
if (process.env.NODE_ENV === 'production') {
// todo 发请求到后台获取数据
throw new Error('method not implemented');
}
else {
// todo initialData
const debugStore = (0, debugStore_1.createDebugStore)(storageSchema, createContext, triggers, checkers, initialData, actionDict);
const debugStore = (0, debugStore_1.createDebugStore)(storageSchema, createContext, triggers, checkers, watchers, initialData, actionDict);
const connectAspectToDebugStore = (aspect) => {
return async (params, scene) => {
const runningContext = createContext(debugStore, scene);
@ -61,7 +57,7 @@ function createAspectProxy(storageSchema, createContext, triggers, checkers, fea
return aspectProxy;
}
}
function initialize(storageSchema, createFeatures, createContext, triggers, checkers, aspectDict, initialData, actionDict) {
function initialize(storageSchema, createFeatures, createContext, triggers, checkers, watchers, aspectDict, initialData, actionDict) {
const basicFeatures = (0, features_1.initialize)(storageSchema, createContext, checkers);
if (actionDict) {
const { checkers: adCheckers } = (0, actionDef_1.analyzeActionDefDict)(storageSchema, actionDict);
@ -76,7 +72,7 @@ function initialize(storageSchema, createFeatures, createContext, triggers, chec
}
const features = (0, lodash_1.assign)(basicFeatures, userDefinedfeatures);
// todo default triggers
const aspectProxy = createAspectProxy(storageSchema, createContext, triggers || [], checkers || [], features, aspectDict, initialData, actionDict);
const aspectProxy = createAspectProxy(storageSchema, createContext, triggers || [], checkers || [], watchers || [], features, aspectDict, initialData, actionDict);
(0, lodash_1.keys)(features).forEach(ele => {
features[ele].setAspectProxy(aspectProxy);
});

View File

@ -1,6 +1,6 @@
/// <reference types="wechat-miniprogram" />
import './polyfill';
import { Aspect, Checker, Context, EntityDict, RowStore, StorageSchema, Trigger, ActionDictOfEntityDict, DeduceSorterItem, DeduceOperation, SelectRowShape } from "oak-domain/lib/types";
import { Aspect, Checker, Context, EntityDict, RowStore, StorageSchema, Trigger, ActionDictOfEntityDict, DeduceSorterItem, DeduceOperation, SelectRowShape, Watcher } from "oak-domain/lib/types";
import { Feature } from '../../types/Feature';
import { Pagination } from "../../types/Pagination";
import { BasicFeatures } from "../../features";
@ -133,7 +133,7 @@ declare type OakPageData = {
oakLegalActions: string[];
};
declare type OakComponentData = {} & OakPageData;
export declare function initialize<ED extends EntityDict, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD>>>(storageSchema: StorageSchema<ED>, createFeatures: (basicFeatures: BasicFeatures<ED, Cxt, AD>) => FD, createContext: (store: RowStore<ED, Cxt>, scene: string) => Cxt, exceptionRouters?: ExceptionRouters, triggers?: Array<Trigger<ED, keyof ED, Cxt>>, checkers?: Array<Checker<ED, keyof ED, Cxt>>, aspectDict?: AD, initialData?: {
export declare function initialize<ED extends EntityDict, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD>>>(storageSchema: StorageSchema<ED>, createFeatures: (basicFeatures: BasicFeatures<ED, Cxt, AD>) => FD, createContext: (store: RowStore<ED, Cxt>, scene: string) => Cxt, exceptionRouters?: ExceptionRouters, triggers?: Array<Trigger<ED, keyof ED, Cxt>>, checkers?: Array<Checker<ED, keyof ED, Cxt>>, watchers?: Array<Watcher<ED, keyof ED, Cxt>>, aspectDict?: AD, initialData?: {
[T in keyof ED]?: Array<ED[T]['OpSchema']>;
}, actionDict?: ActionDictOfEntityDict<ED>): {
OakPage: <T extends keyof ED, D extends WechatMiniprogram.Component.DataOption, P extends WechatMiniprogram.Component.PropertyOption, M extends WechatMiniprogram.Component.MethodOption, IsList extends boolean, Proj extends ED[T]["Selection"]["data"], IS extends WechatMiniprogram.IAnyObject = {}, FormedData extends WechatMiniprogram.Component.DataOption = {}>(options: OakPageOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList>, componentOptions?: WechatMiniprogram.Component.Options<D, P, M, IS & OakPageInstanceProperties<ED, Cxt, AD, FD>, true>) => string;

View File

@ -609,8 +609,8 @@ function mergeMethods(methods) {
}
return merged;
}
function initialize(storageSchema, createFeatures, createContext, exceptionRouters = [], triggers, checkers, aspectDict, initialData, actionDict) {
const { subscribe, features } = (0, initialize_1.initialize)(storageSchema, createFeatures, createContext, triggers, checkers, aspectDict, initialData, actionDict);
function initialize(storageSchema, createFeatures, createContext, exceptionRouters = [], triggers, checkers, watchers, aspectDict, initialData, actionDict) {
const { subscribe, features } = (0, initialize_1.initialize)(storageSchema, createFeatures, createContext, triggers, checkers, watchers, aspectDict, initialData, actionDict);
const exceptionRouterDict = {};
for (const router of exceptionRouters) {
(0, lodash_1.assign)(exceptionRouterDict, {

View File

@ -124,7 +124,7 @@ function initializeWatchers<ED extends EntityDict, Cxt extends Context<ED>>(
const duration = Date.now() - start;
console.log(`${count}次执行watchers共执行${totalWatchers.length}个,耗时${duration}毫秒`);
setTimeout(() => doWatchers(), 2000);
setTimeout(() => doWatchers(), 120000);
}
doWatchers();

View File

@ -465,14 +465,13 @@ class ListNode<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED
if (e === this.entity) {
const { id } = d;
const filter = combineFilters([{ id } as any, ...(this.filters).map(ele => ele.filter)]);
const { ids } = await this.cache.operate(e, {
const rows = await this.cache.get(e, {
data: {
id: 1,
} as any,
filter,
action: 'select',
}, 'onRecordSynchoronized', { obscure: true });
if (ids!.length > 0) {
if (rows.length > 0) {
// todo 这里更严格应该还要考虑sorter但前端可能没有完整的供sort用的cache数据
this.ids.push(id);
needReGetValue = true;
@ -500,14 +499,13 @@ class ListNode<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED
}
else {
const filter = combineFilters([{ id } as any, ...(this.filters.map(ele => ele.filter))]);
const { ids } = await this.cache.operate(e, {
const rows = await this.cache.get(e, {
data: {
id: 1,
} as any,
filter,
action: 'select',
}, 'onRecordSynchoronized', { obscure: true });
if (ids!.length > 0) {
if (rows!.length > 0) {
// todo 这里更严格应该还要考虑sorter但前端可能没有完整的供sort用的cache数据
this.ids.push(id);
needReGetValue = true;