Merge branch 'dev' of gitea.51mars.com:Oak-Team/oak-domain into dev

This commit is contained in:
Xu Chang 2024-07-19 19:27:54 +08:00
commit 34018c09b3
13 changed files with 90 additions and 15 deletions

View File

@ -29,6 +29,12 @@ export declare abstract class AsyncContext<ED extends EntityDict> implements Con
private resetEvents; private resetEvents;
on(event: 'commit' | 'rollback', callback: (records: OpRecord<ED>[], cxtStr: string) => Promise<void>): void; on(event: 'commit' | 'rollback', callback: (records: OpRecord<ED>[], cxtStr: string) => Promise<void>): void;
saveOpRecord<T extends keyof ED>(entity: T, operation: ED[T]['Operation']): void; saveOpRecord<T extends keyof ED>(entity: T, operation: ED[T]['Operation']): void;
/**
* operation所处理的row ids
* operation还未执行row idafter的trigger中ids值row id
* @param id
*/
getRowIdsOfOperation(operation: ED[keyof ED]['Operation']): string[];
/** /**
* context中不应该有并发的事务使 * context中不应该有并发的事务使
* @param options * @param options

View File

@ -4,6 +4,7 @@ exports.AsyncContext = void 0;
const tslib_1 = require("tslib"); const tslib_1 = require("tslib");
const action_1 = require("../actions/action"); const action_1 = require("../actions/action");
const assert_1 = tslib_1.__importDefault(require("assert")); const assert_1 = tslib_1.__importDefault(require("assert"));
const filter_1 = require("./filter");
/** /**
* 服务器端执行的异步环境的底层抽象 * 服务器端执行的异步环境的底层抽象
*/ */
@ -75,7 +76,7 @@ class AsyncContext {
id, id,
a: 'c', a: 'c',
e: entity, e: entity,
d: data d: data,
}); });
break; break;
} }
@ -100,6 +101,35 @@ class AsyncContext {
} }
} }
} }
/**
* 查询某operation所处理的row ids
* 如果该operation还未执行可能返回空数组不知道实际关联的row id但是在after的trigger中返回是准确的ids值此时如果是空数组说明没有有关row id
* @param id
*/
getRowIdsOfOperation(operation) {
const { id, action, data, filter } = operation;
if (action === 'create') {
if (data instanceof Array) {
return data.map(ele => ele.id);
}
return [data.id];
}
else if (filter) {
const ids = (0, filter_1.getRelevantIds)(filter);
if (ids.length > 0) {
return ids;
}
}
const oper = this.opRecords.find(ele => ele.id === id);
if (oper) {
const { a } = oper;
(0, assert_1.default)(a !== 'create');
const { f } = oper;
(0, assert_1.default)(f && f?.id?.$in && f.id.$in instanceof Array);
return f.id.$in;
}
return [];
}
/** /**
* 一个context中不应该有并发的事务这里将事务串行化使用的时候千万要注意不要自己等自己 * 一个context中不应该有并发的事务这里将事务串行化使用的时候千万要注意不要自己等自己
* @param options * @param options

View File

@ -1217,6 +1217,7 @@ class CascadeStore extends RowStore_1.RowStore {
}; };
const rows = await this.selectAbjointRowAsync(entity, selection, context, { const rows = await this.selectAbjointRowAsync(entity, selection, context, {
dontCollect: true, dontCollect: true,
forUpdate: true,
}); });
ids.push(...(rows.map(ele => ele.id))); ids.push(...(rows.map(ele => ele.id)));
} }

View File

@ -79,7 +79,7 @@ function createUniqueCheckers(schema) {
entity, entity,
action: 'create', action: 'create',
type: 'logicalData', type: 'logicalData',
priority: types_1.CHECKER_MAX_PRIORITY, priority: types_1.CHECKER_MAX_PRIORITY, // 优先级要放在最低所有前置的checker/trigger将数据完整之后再在这里检测
checker: (operation, context) => { checker: (operation, context) => {
const { data } = operation; const { data } = operation;
if (data instanceof Array) { if (data instanceof Array) {
@ -95,9 +95,9 @@ function createUniqueCheckers(schema) {
} }
}, { }, {
entity, entity,
action: 'update', action: 'update', // 只检查update其它状态转换的action应该不会涉及unique约束的属性
type: 'logicalData', type: 'logicalData',
priority: types_1.CHECKER_MAX_PRIORITY, priority: types_1.CHECKER_MAX_PRIORITY, // 优先级要放在最低所有前置的checker/trigger将数据完整之后再在这里检测
checker: (operation, context) => { checker: (operation, context) => {
const { data, filter: operationFilter } = operation; const { data, filter: operationFilter } = operation;
if (data) { if (data) {
@ -227,7 +227,7 @@ function createActionTransformerCheckers(actionDefDict) {
action: 'create', action: 'create',
type: 'logical', type: 'logical',
entity, entity,
priority: 10, priority: 10, // 优先级要高先于真正的data检查进行
checker: (operation) => { checker: (operation) => {
const { data } = operation; const { data } = operation;
if (data instanceof Array) { if (data instanceof Array) {

View File

@ -647,6 +647,7 @@ function judgeValueRelation(value1, value2, contained) {
else if (r) { else if (r) {
return false; return false;
} }
return;
} }
// 互斥 // 互斥
if (r) { if (r) {

View File

@ -1,3 +1,4 @@
/// <reference types="node" />
/** /**
* assert打包体积过大 * assert打包体积过大
*/ */

View File

@ -60,7 +60,7 @@ function destructRelationPath(schema, entity, path, relationFilter, recursive) {
}, },
filter: relationFilter, filter: relationFilter,
} // as ED['userRelation']['Selection'] } // as ED['userRelation']['Selection']
}, }, // as ED[keyof ED]['Selection']['data'],
getData: (d) => { getData: (d) => {
return d.userRelation$entity; return d.userRelation$entity;
}, },

View File

@ -6,7 +6,7 @@ declare const url: {
revokeObjectURL(url: string): void; revokeObjectURL(url: string): void;
}; };
declare const urlSearchParams: { declare const urlSearchParams: {
new (init?: string | Record<string, string> | string[][] | URLSearchParams | undefined): URLSearchParams; new (init?: string | string[][] | Record<string, string> | URLSearchParams | undefined): URLSearchParams;
prototype: URLSearchParams; prototype: URLSearchParams;
}; };
export { url, urlSearchParams }; export { url, urlSearchParams };

View File

@ -6,7 +6,7 @@ declare const url: {
revokeObjectURL(url: string): void; revokeObjectURL(url: string): void;
}; };
declare const urlSearchParams: { declare const urlSearchParams: {
new (init?: string | Record<string, string> | string[][] | URLSearchParams | undefined): URLSearchParams; new (init?: string | string[][] | Record<string, string> | URLSearchParams | undefined): URLSearchParams;
prototype: URLSearchParams; prototype: URLSearchParams;
}; };
export { url, urlSearchParams }; export { url, urlSearchParams };

View File

@ -1,6 +1,6 @@
{ {
"name": "oak-domain", "name": "oak-domain",
"version": "5.0.16", "version": "5.0.17",
"author": { "author": {
"name": "XuChang" "name": "XuChang"
}, },

View File

@ -1,8 +1,9 @@
import { EntityDict, RowStore, OperateOption, OperationResult, SelectOption, Context, TxnOption, OpRecord, AggregationResult, ClusterInfo } from "../types"; import { EntityDict, RowStore, OperateOption, OperationResult, SelectOption, Context, TxnOption, OpRecord, AggregationResult, ClusterInfo, CreateOpResult, UpdateOpResult } from "../types";
import { readOnlyActions } from '../actions/action'; import { readOnlyActions } from '../actions/action';
import assert from "assert"; import assert from "assert";
import { IncomingHttpHeaders } from "http"; import { IncomingHttpHeaders } from "http";
import { getRelevantIds } from "./filter";
/** /**
* *
@ -91,7 +92,7 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
id, id,
a: 'c', a: 'c',
e: entity, e: entity,
d: data as ED[T]['OpSchema'] d: data as ED[T]['OpSchema'],
}); });
break; break;
} }
@ -117,6 +118,39 @@ export abstract class AsyncContext<ED extends EntityDict> implements Context {
} }
} }
/**
* operation所处理的row ids
* operation还未执行row idafter的trigger中ids值row id
* @param id
*/
getRowIdsOfOperation(operation: ED[keyof ED]['Operation']): string[] {
const { id, action, data, filter } = operation;
if (action === 'create') {
if (data instanceof Array) {
return data.map(ele => ele.id);
}
return [data.id!];
}
else if (filter) {
const ids = getRelevantIds(filter);
if (ids.length > 0 ) {
return ids;
}
}
const oper = this.opRecords.find(
ele => (ele as CreateOpResult<ED, keyof ED>).id === id
);
if (oper) {
const { a } = oper;
assert (a !== 'create');
const { f } = oper as UpdateOpResult<ED, keyof ED>;
assert(f && f?.id?.$in && f!.id!.$in! instanceof Array);
return f!.id!.$in!;
}
return [];
}
/** /**
* context中不应该有并发的事务使 * context中不应该有并发的事务使
* @param options * @param options

View File

@ -1490,6 +1490,7 @@ export abstract class CascadeStore<ED extends EntityDict & BaseEntityDict> exten
}; };
const rows = await this.selectAbjointRowAsync(entity, selection, context, { const rows = await this.selectAbjointRowAsync(entity, selection, context, {
dontCollect: true, dontCollect: true,
forUpdate: true,
}); });
ids.push(...(rows.map(ele => ele.id! as string))); ids.push(...(rows.map(ele => ele.id! as string)));
} }

View File

@ -18,9 +18,9 @@ export function translateCreateDataToFilter<ED extends EntityDict & BaseEntityDi
if (rel === 1) { if (rel === 1) {
// 只需要记住id和各种外键属性不这样处理有些古怪的属性比如coordinate其作为createdata和作为filter并不同构 // 只需要记住id和各种外键属性不这样处理有些古怪的属性比如coordinate其作为createdata和作为filter并不同构
if (![ if (![
'geometry', 'geometry',
'geography', 'geography',
'st_geometry', 'st_geometry',
'st_point', 'st_point',
'function', 'function',
'sequence', 'sequence',
@ -744,6 +744,7 @@ export function judgeValueRelation(value1: any, value2: any, contained: boolean)
else if (r) { else if (r) {
return false; return false;
} }
return;
} }
// 互斥 // 互斥
if (r) { if (r) {
@ -1856,7 +1857,7 @@ export function checkFilterContains<ED extends EntityDict & BaseEntityDict, T ex
filter?: ED[T]['Selection']['filter'], filter?: ED[T]['Selection']['filter'],
dataCompare?: true, dataCompare?: true,
warningOnDataCompare?: true): boolean | Promise<boolean> { warningOnDataCompare?: true): boolean | Promise<boolean> {
assert(filter); assert(filter);
const schema = context.getSchema(); const schema = context.getSchema();