nesoi 3.3.20 → 3.3.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/elements/edge/controller/adapters/controller_adapter.d.ts +4 -1
- package/lib/elements/edge/controller/adapters/controller_adapter.js +8 -4
- package/lib/elements/edge/controller/controller.js +3 -3
- package/lib/elements/edge/controller/controller.schema.d.ts +2 -1
- package/lib/elements/edge/controller/controller.schema.js +3 -1
- package/lib/elements/entities/bucket/adapters/bucket_adapter.d.ts +25 -3
- package/lib/elements/entities/bucket/adapters/bucket_adapter.js +21 -2
- package/lib/elements/entities/bucket/adapters/memory.nql.js +80 -44
- package/lib/elements/entities/bucket/adapters/test.bucket_adapter.d.ts +22 -0
- package/lib/elements/entities/bucket/adapters/test.bucket_adapter.js +23 -0
- package/lib/elements/entities/bucket/bucket.js +2 -2
- package/lib/elements/entities/bucket/cache/bucket_cache.d.ts +16 -1
- package/lib/elements/entities/bucket/cache/bucket_cache.js +36 -15
- package/lib/elements/entities/bucket/graph/bucket_graph.js +28 -18
- package/lib/elements/entities/bucket/query/nql.schema.d.ts +3 -0
- package/lib/elements/entities/bucket/query/nql_compiler.d.ts +10 -4
- package/lib/elements/entities/bucket/query/nql_compiler.js +42 -35
- package/lib/elements/entities/bucket/query/nql_engine.d.ts +4 -1
- package/lib/elements/entities/bucket/query/nql_engine.js +3 -5
- package/lib/elements/entities/message/template/message_template_field.builder.d.ts +2 -0
- package/lib/elements/entities/message/template/message_template_field.builder.js +5 -0
- package/lib/engine/daemon.d.ts +19 -0
- package/lib/engine/daemon.js +40 -2
- package/lib/engine/data/tree.d.ts +1 -2
- package/lib/engine/data/tree.js +6 -94
- package/lib/engine/transaction/nodes/bucket.trx_node.d.ts +1 -1
- package/lib/engine/transaction/nodes/bucket.trx_node.js +15 -15
- package/lib/engine/transaction/nodes/bucket_query.trx_node.js +2 -2
- package/lib/engine/transaction/nodes/external.trx_node.d.ts +3 -1
- package/lib/engine/transaction/nodes/external.trx_node.js +54 -4
- package/lib/engine/transaction/nodes/job.trx_node.js +3 -2
- package/lib/engine/transaction/nodes/machine.trx_node.js +1 -1
- package/lib/engine/transaction/nodes/queue.trx_node.js +1 -1
- package/lib/engine/transaction/nodes/resource.trx_node.js +1 -1
- package/lib/engine/transaction/nodes/topic.trx_node.js +1 -1
- package/lib/engine/transaction/trx.d.ts +7 -1
- package/lib/engine/transaction/trx.js +15 -1
- package/lib/engine/transaction/trx_engine.config.d.ts +6 -1
- package/lib/engine/transaction/trx_engine.d.ts +5 -5
- package/lib/engine/transaction/trx_engine.js +59 -36
- package/lib/engine/transaction/trx_node.d.ts +1 -1
- package/lib/engine/transaction/trx_node.js +1 -1
- package/package.json +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -39,7 +39,7 @@ class BucketTrxNode {
|
|
|
39
39
|
/*
|
|
40
40
|
Wrap
|
|
41
41
|
*/
|
|
42
|
-
async wrap(action, input, fn, fmtTrxOut) {
|
|
42
|
+
async wrap(action, input, fn, fmtTrxOut, idempotent = false) {
|
|
43
43
|
const wrapped = async (parentTrx, bucket) => {
|
|
44
44
|
const trx = trx_node_1.TrxNode.makeChildNode(parentTrx, bucket.schema.module, 'bucket', bucket.schema.name);
|
|
45
45
|
trx_node_1.TrxNode.open(trx, action, input);
|
|
@@ -54,8 +54,8 @@ class BucketTrxNode {
|
|
|
54
54
|
return out;
|
|
55
55
|
};
|
|
56
56
|
if (this.external) {
|
|
57
|
-
const ext = new external_trx_node_1.ExternalTrxNode(this.trx, this.tag);
|
|
58
|
-
return ext.
|
|
57
|
+
const ext = new external_trx_node_1.ExternalTrxNode(this.trx, this.tag, idempotent);
|
|
58
|
+
return ext.run_and_hold(trx => dependency_1.Tag.element(this.tag, trx), wrapped);
|
|
59
59
|
}
|
|
60
60
|
else {
|
|
61
61
|
return wrapped(this.trx, this.bucket);
|
|
@@ -72,7 +72,7 @@ class BucketTrxNode {
|
|
|
72
72
|
return this.wrap('readOne', { id }, (trx, bucket) => bucket.readOne(trx, id, {
|
|
73
73
|
silent: true,
|
|
74
74
|
no_tenancy: !this.enableTenancy
|
|
75
|
-
}));
|
|
75
|
+
}), undefined, true);
|
|
76
76
|
}
|
|
77
77
|
/**
|
|
78
78
|
* Returns one object by `id` formated with the specified view,
|
|
@@ -84,7 +84,7 @@ class BucketTrxNode {
|
|
|
84
84
|
return this.wrap('viewOne', { id }, (trx, bucket) => bucket.viewOne(trx, id, view, {
|
|
85
85
|
silent: true,
|
|
86
86
|
no_tenancy: !this.enableTenancy
|
|
87
|
-
}));
|
|
87
|
+
}), undefined, true);
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
90
90
|
* Returns one object by `id`, without pre-formatting,
|
|
@@ -93,7 +93,7 @@ class BucketTrxNode {
|
|
|
93
93
|
async readOneOrFail(id) {
|
|
94
94
|
return this.wrap('readOneOrFail', { id }, (trx, bucket) => bucket.readOne(trx, id, {
|
|
95
95
|
no_tenancy: !this.enableTenancy
|
|
96
|
-
}));
|
|
96
|
+
}), undefined, true);
|
|
97
97
|
}
|
|
98
98
|
/**
|
|
99
99
|
* Returns one object by `id`, without pre-formatting,
|
|
@@ -104,7 +104,7 @@ class BucketTrxNode {
|
|
|
104
104
|
async viewOneOrFail(id, view = 'default') {
|
|
105
105
|
return this.wrap('viewOneOrFail', { id }, (trx, bucket) => bucket.viewOne(trx, id, view, {
|
|
106
106
|
no_tenancy: !this.enableTenancy
|
|
107
|
-
}));
|
|
107
|
+
}), undefined, true);
|
|
108
108
|
}
|
|
109
109
|
/*
|
|
110
110
|
Read/View All
|
|
@@ -115,7 +115,7 @@ class BucketTrxNode {
|
|
|
115
115
|
async readAll() {
|
|
116
116
|
return this.wrap('readAll', {}, (trx, bucket) => bucket.readAll(trx, {
|
|
117
117
|
no_tenancy: !this.enableTenancy
|
|
118
|
-
}), objs => ({ length: objs.length }));
|
|
118
|
+
}), objs => ({ length: objs.length }), true);
|
|
119
119
|
}
|
|
120
120
|
/**
|
|
121
121
|
* Returns a list of all objects formated with the specified view.
|
|
@@ -125,7 +125,7 @@ class BucketTrxNode {
|
|
|
125
125
|
async viewAll(view = 'default') {
|
|
126
126
|
return this.wrap('viewAll', {}, (trx, bucket) => bucket.viewAll(trx, view, {
|
|
127
127
|
no_tenancy: !this.enableTenancy
|
|
128
|
-
}), objs => ({ length: objs.length }));
|
|
128
|
+
}), objs => ({ length: objs.length }), true);
|
|
129
129
|
}
|
|
130
130
|
/*
|
|
131
131
|
Query
|
|
@@ -154,7 +154,7 @@ class BucketTrxNode {
|
|
|
154
154
|
silent: true,
|
|
155
155
|
no_tenancy: !this.enableTenancy,
|
|
156
156
|
index
|
|
157
|
-
}));
|
|
157
|
+
}), undefined, true);
|
|
158
158
|
}
|
|
159
159
|
/**
|
|
160
160
|
* Returns one or more objects referenced by the graph link,
|
|
@@ -165,7 +165,7 @@ class BucketTrxNode {
|
|
|
165
165
|
silent: true,
|
|
166
166
|
no_tenancy: !this.enableTenancy,
|
|
167
167
|
indexes
|
|
168
|
-
}));
|
|
168
|
+
}), undefined, true);
|
|
169
169
|
}
|
|
170
170
|
/**
|
|
171
171
|
* Returns one or more objects referenced by the graph link built with a view,
|
|
@@ -175,7 +175,7 @@ class BucketTrxNode {
|
|
|
175
175
|
return this.wrap('viewLink', { id, link, view }, (trx, bucket) => bucket.viewLink(trx, id, link, view, {
|
|
176
176
|
silent: true,
|
|
177
177
|
no_tenancy: !this.enableTenancy
|
|
178
|
-
}));
|
|
178
|
+
}), undefined, true);
|
|
179
179
|
}
|
|
180
180
|
/**
|
|
181
181
|
* Returns one or more objects referenced by the graph link,
|
|
@@ -184,7 +184,7 @@ class BucketTrxNode {
|
|
|
184
184
|
async readLinkOrFail(id, link) {
|
|
185
185
|
return this.wrap('readLinkOrFail', { id, link }, (trx, bucket) => bucket.readLink(trx, id, link, {
|
|
186
186
|
no_tenancy: !this.enableTenancy
|
|
187
|
-
}));
|
|
187
|
+
}), undefined, true);
|
|
188
188
|
}
|
|
189
189
|
/**
|
|
190
190
|
* Returns one or more objects referenced by the graph link built with a view,
|
|
@@ -193,7 +193,7 @@ class BucketTrxNode {
|
|
|
193
193
|
async viewLinkOrFail(id, link, view = 'default') {
|
|
194
194
|
return this.wrap('viewLinkOrFail', { id, link, view }, (trx, bucket) => bucket.viewLink(trx, id, link, view, {
|
|
195
195
|
no_tenancy: !this.enableTenancy
|
|
196
|
-
}));
|
|
196
|
+
}), undefined, true);
|
|
197
197
|
}
|
|
198
198
|
/**
|
|
199
199
|
* Returns `true` if the graph link resolves to at least 1 object.
|
|
@@ -201,7 +201,7 @@ class BucketTrxNode {
|
|
|
201
201
|
async hasLink(id, link) {
|
|
202
202
|
return this.wrap('hasLink', { id, link }, (trx, bucket) => bucket.hasLink(trx, id, link, {
|
|
203
203
|
no_tenancy: !this.enableTenancy
|
|
204
|
-
}));
|
|
204
|
+
}), undefined, true);
|
|
205
205
|
}
|
|
206
206
|
/*
|
|
207
207
|
Create
|
|
@@ -70,8 +70,8 @@ class BucketQueryTrxNode {
|
|
|
70
70
|
return out;
|
|
71
71
|
};
|
|
72
72
|
if (this.external) {
|
|
73
|
-
const ext = new external_trx_node_1.ExternalTrxNode(this.trx, this.tag);
|
|
74
|
-
return ext.
|
|
73
|
+
const ext = new external_trx_node_1.ExternalTrxNode(this.trx, this.tag, true);
|
|
74
|
+
return ext.run_and_hold(trx => dependency_1.Tag.element(this.tag, trx), wrapped);
|
|
75
75
|
}
|
|
76
76
|
else {
|
|
77
77
|
return wrapped(this.trx, this.bucket);
|
|
@@ -9,7 +9,9 @@ import { Tag } from "../../dependency";
|
|
|
9
9
|
export declare class ExternalTrxNode<M extends $Module, $ extends $Topic> {
|
|
10
10
|
private trx;
|
|
11
11
|
private tag;
|
|
12
|
+
private idempotent;
|
|
12
13
|
private daemon;
|
|
13
|
-
constructor(trx: TrxNode<any, M, any>, tag: Tag);
|
|
14
|
+
constructor(trx: TrxNode<any, M, any>, tag: Tag, idempotent?: boolean);
|
|
15
|
+
run_and_hold(element: (trx: AnyTrxNode) => any, fn: (trx: AnyTrxNode, element: any) => Promise<any>): Promise<any>;
|
|
14
16
|
run(element: (trx: AnyTrxNode) => any, fn: (trx: AnyTrxNode, element: any) => Promise<any>): Promise<any>;
|
|
15
17
|
}
|
|
@@ -10,17 +10,19 @@ const error_1 = require("../../data/error");
|
|
|
10
10
|
class ExternalTrxNode {
|
|
11
11
|
trx;
|
|
12
12
|
tag;
|
|
13
|
+
idempotent;
|
|
13
14
|
daemon;
|
|
14
|
-
constructor(trx, tag) {
|
|
15
|
+
constructor(trx, tag, idempotent = false) {
|
|
15
16
|
this.trx = trx;
|
|
16
17
|
this.tag = tag;
|
|
18
|
+
this.idempotent = idempotent;
|
|
17
19
|
const _module = trx_node_1.TrxNode.getModule(trx);
|
|
18
20
|
if (!_module.daemon) {
|
|
19
21
|
throw error_1.NesoiError.Trx.DaemonNotFound(_module.name);
|
|
20
22
|
}
|
|
21
23
|
this.daemon = _module.daemon;
|
|
22
24
|
}
|
|
23
|
-
async
|
|
25
|
+
async run_and_hold(element, fn) {
|
|
24
26
|
const root = this.trx.trx;
|
|
25
27
|
const module = trx_node_1.TrxNode.getModule(this.trx);
|
|
26
28
|
const trx = trx_node_1.TrxNode.makeChildNode(this.trx, module.name, 'externals', this.tag.full);
|
|
@@ -29,7 +31,14 @@ class ExternalTrxNode {
|
|
|
29
31
|
});
|
|
30
32
|
let out;
|
|
31
33
|
try {
|
|
32
|
-
const
|
|
34
|
+
const dtrx = await this.daemon.trx(this.tag.module)
|
|
35
|
+
.origin('ext:' + root.id);
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
37
|
+
if (this.idempotent)
|
|
38
|
+
dtrx.idempotent;
|
|
39
|
+
else
|
|
40
|
+
dtrx.idempotent_inherit(trx);
|
|
41
|
+
const res = await dtrx
|
|
33
42
|
.auth_inherit(trx)
|
|
34
43
|
.run_and_hold(async (extTrx) => {
|
|
35
44
|
try {
|
|
@@ -46,7 +55,48 @@ class ExternalTrxNode {
|
|
|
46
55
|
throw res.status.error;
|
|
47
56
|
}
|
|
48
57
|
out = res.status.output;
|
|
49
|
-
|
|
58
|
+
if (!trx.trx.idempotent) {
|
|
59
|
+
root.holdNode(res);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
throw trx_node_1.TrxNode.error(trx, e);
|
|
64
|
+
}
|
|
65
|
+
trx_node_1.TrxNode.ok(trx, out);
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
async run(element, fn) {
|
|
69
|
+
const root = this.trx.trx;
|
|
70
|
+
const module = trx_node_1.TrxNode.getModule(this.trx);
|
|
71
|
+
const trx = trx_node_1.TrxNode.makeChildNode(this.trx, module.name, 'externals', this.tag.full);
|
|
72
|
+
trx_node_1.TrxNode.open(trx, '~', {
|
|
73
|
+
tag: this.tag
|
|
74
|
+
});
|
|
75
|
+
let out;
|
|
76
|
+
try {
|
|
77
|
+
const dtrx = await this.daemon.trx(this.tag.module);
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
79
|
+
if (this.idempotent)
|
|
80
|
+
dtrx.idempotent;
|
|
81
|
+
else
|
|
82
|
+
dtrx.idempotent_inherit(trx);
|
|
83
|
+
const res = await dtrx
|
|
84
|
+
.auth_inherit(trx)
|
|
85
|
+
.run(async (extTrx) => {
|
|
86
|
+
try {
|
|
87
|
+
return await fn(extTrx, element(extTrx));
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
throw trx_node_1.TrxNode.error(extTrx, e);
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
trx_node_1.TrxNode.merge(trx, extTrx);
|
|
94
|
+
}
|
|
95
|
+
}, root.id);
|
|
96
|
+
if (res.state === 'error') {
|
|
97
|
+
throw res.error;
|
|
98
|
+
}
|
|
99
|
+
out = res.output;
|
|
50
100
|
}
|
|
51
101
|
catch (e) {
|
|
52
102
|
throw trx_node_1.TrxNode.error(trx, e);
|
|
@@ -46,8 +46,9 @@ class JobTrxNode {
|
|
|
46
46
|
return out;
|
|
47
47
|
};
|
|
48
48
|
if (this.external) {
|
|
49
|
-
const
|
|
50
|
-
|
|
49
|
+
const root = this.trx.trx;
|
|
50
|
+
const ext = new external_trx_node_1.ExternalTrxNode(this.trx, this.tag, root.idempotent);
|
|
51
|
+
return ext.run_and_hold(trx => dependency_1.Tag.element(this.tag, trx), wrapped);
|
|
51
52
|
}
|
|
52
53
|
else {
|
|
53
54
|
return wrapped(this.trx, this.job);
|
|
@@ -45,7 +45,7 @@ class MachineTrxNode {
|
|
|
45
45
|
};
|
|
46
46
|
if (this.external) {
|
|
47
47
|
const ext = new external_trx_node_1.ExternalTrxNode(this.trx, this.tag);
|
|
48
|
-
return ext.
|
|
48
|
+
return ext.run_and_hold(trx => dependency_1.Tag.element(this.tag, trx), wrapped);
|
|
49
49
|
}
|
|
50
50
|
else {
|
|
51
51
|
return wrapped(this.trx, this.machine);
|
|
@@ -45,7 +45,7 @@ class QueueTrxNode {
|
|
|
45
45
|
};
|
|
46
46
|
if (this.external) {
|
|
47
47
|
const ext = new external_trx_node_1.ExternalTrxNode(this.trx, this.tag);
|
|
48
|
-
return ext.
|
|
48
|
+
return ext.run_and_hold(trx => dependency_1.Tag.element(this.tag, trx), wrapped);
|
|
49
49
|
}
|
|
50
50
|
else {
|
|
51
51
|
return wrapped(this.trx, this.queue);
|
|
@@ -45,7 +45,7 @@ class ResourceTrxNode {
|
|
|
45
45
|
};
|
|
46
46
|
if (this.external) {
|
|
47
47
|
const ext = new external_trx_node_1.ExternalTrxNode(this.trx, this.tag);
|
|
48
|
-
return ext.
|
|
48
|
+
return ext.run_and_hold(trx => dependency_1.Tag.element(this.tag, trx), wrapped);
|
|
49
49
|
}
|
|
50
50
|
else {
|
|
51
51
|
return wrapped(this.trx, this.resource);
|
|
@@ -45,7 +45,7 @@ class TopicTrxNode {
|
|
|
45
45
|
};
|
|
46
46
|
if (this.external) {
|
|
47
47
|
const ext = new external_trx_node_1.ExternalTrxNode(this.trx, this.tag);
|
|
48
|
-
return ext.
|
|
48
|
+
return ext.run_and_hold(trx => dependency_1.Tag.element(this.tag, trx), wrapped);
|
|
49
49
|
}
|
|
50
50
|
else {
|
|
51
51
|
return wrapped(this.trx, this.resource);
|
|
@@ -7,6 +7,7 @@ import { NesoiDatetime } from '../data/datetime';
|
|
|
7
7
|
import { NesoiError } from '../data/error';
|
|
8
8
|
import { AnyBucketCache } from "../../elements/entities/bucket/cache/bucket_cache";
|
|
9
9
|
import { AnyBucket } from "../../elements/entities/bucket/bucket";
|
|
10
|
+
import { NQLRunner } from "../../elements/entities/bucket/query/nql_engine";
|
|
10
11
|
type TrxOrigin = TrxEngineOrigin | `trx:${string}`;
|
|
11
12
|
type TrxState = 'open' | 'hold' | 'ok' | 'error';
|
|
12
13
|
/**
|
|
@@ -34,6 +35,7 @@ export declare class Trx<S extends $Space, M extends $Module, AuthUsers extends
|
|
|
34
35
|
private module;
|
|
35
36
|
id: string;
|
|
36
37
|
private origin;
|
|
38
|
+
idempotent: boolean;
|
|
37
39
|
root: TrxNode<S, M, AuthUsers>;
|
|
38
40
|
nodes: Record<string, TrxNode<S, M, AuthUsers>>;
|
|
39
41
|
holds: Record<string, TrxNodeHold<any>>;
|
|
@@ -42,7 +44,7 @@ export declare class Trx<S extends $Space, M extends $Module, AuthUsers extends
|
|
|
42
44
|
ctx: Record<string, any>;
|
|
43
45
|
cache_config: Record<string, 'eager'>;
|
|
44
46
|
cache: Record<string, AnyBucketCache>;
|
|
45
|
-
constructor(engine: AnyTrxEngine, module: Module<S, M>, origin: TrxOrigin, auth?: {
|
|
47
|
+
constructor(engine: AnyTrxEngine, module: Module<S, M>, origin: TrxOrigin, idempotent?: boolean, auth?: {
|
|
46
48
|
tokens: AuthRequest<any>;
|
|
47
49
|
users: AuthUsers;
|
|
48
50
|
}, id?: string, root?: TrxNode<S, M, AuthUsers>, nodes?: Record<string, TrxNode<S, M, AuthUsers>>);
|
|
@@ -56,6 +58,10 @@ export declare class Trx<S extends $Space, M extends $Module, AuthUsers extends
|
|
|
56
58
|
* These are configured through the TrxNode.cache method.
|
|
57
59
|
*/
|
|
58
60
|
static getCache(node: AnyTrxNode, bucket: AnyBucket): Promise<AnyBucketCache | undefined>;
|
|
61
|
+
static getCacheCustomBuckets(node: AnyTrxNode): Record<string, {
|
|
62
|
+
scope: string;
|
|
63
|
+
nql: NQLRunner;
|
|
64
|
+
}>;
|
|
59
65
|
/**
|
|
60
66
|
* Context Manipulation
|
|
61
67
|
*
|
|
@@ -70,6 +70,7 @@ class Trx {
|
|
|
70
70
|
module;
|
|
71
71
|
id;
|
|
72
72
|
origin;
|
|
73
|
+
idempotent;
|
|
73
74
|
root;
|
|
74
75
|
nodes;
|
|
75
76
|
holds = {};
|
|
@@ -78,11 +79,12 @@ class Trx {
|
|
|
78
79
|
ctx = {};
|
|
79
80
|
cache_config = {};
|
|
80
81
|
cache = {};
|
|
81
|
-
constructor(engine, module, origin, auth, id, root, nodes) {
|
|
82
|
+
constructor(engine, module, origin, idempotent, auth, id, root, nodes) {
|
|
82
83
|
this.engine = engine;
|
|
83
84
|
this.module = module;
|
|
84
85
|
this.id = id || (Math.random() + 1).toString(36).substring(7);
|
|
85
86
|
this.origin = origin;
|
|
87
|
+
this.idempotent = idempotent ?? false;
|
|
86
88
|
this.root = root || new trx_node_1.TrxNode('root', this, undefined, module, auth, false, id);
|
|
87
89
|
this.nodes = nodes || {};
|
|
88
90
|
}
|
|
@@ -129,6 +131,18 @@ class Trx {
|
|
|
129
131
|
}
|
|
130
132
|
return cache;
|
|
131
133
|
}
|
|
134
|
+
static getCacheCustomBuckets(node) {
|
|
135
|
+
const trx = node.trx;
|
|
136
|
+
const buckets = {};
|
|
137
|
+
for (const tag in trx.cache) {
|
|
138
|
+
const adapter = trx.cache[tag].innerAdapter;
|
|
139
|
+
buckets[tag] = {
|
|
140
|
+
scope: `__cache_${tag}`,
|
|
141
|
+
nql: adapter.nql
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return buckets;
|
|
145
|
+
}
|
|
132
146
|
/**
|
|
133
147
|
* Context Manipulation
|
|
134
148
|
*
|
|
@@ -10,5 +10,10 @@ export type TrxEngineConfig<S extends $Space, M extends $Module, AuthUsers exten
|
|
|
10
10
|
* Adapter used to store transactions of this module.
|
|
11
11
|
*/
|
|
12
12
|
adapter?: (schema: M) => BucketAdapter<TrxData>;
|
|
13
|
-
wrap?:
|
|
13
|
+
wrap?: {
|
|
14
|
+
begin: <T extends Trx<S, M, AuthUsers>>(trx: T, services: Services) => Promise<void>;
|
|
15
|
+
continue: <T extends Trx<S, M, AuthUsers>>(trx: T, services: Services) => Promise<void>;
|
|
16
|
+
commit: <T extends Trx<S, M, AuthUsers>>(trx: T, services: Services) => Promise<void>;
|
|
17
|
+
rollback: <T extends Trx<S, M, AuthUsers>>(trx: T, services: Services) => Promise<void>;
|
|
18
|
+
}[];
|
|
14
19
|
};
|
|
@@ -20,8 +20,8 @@ export type TrxData = {
|
|
|
20
20
|
export type HeldTrxNode<Output> = {
|
|
21
21
|
id: string;
|
|
22
22
|
status: TrxStatus<Output>;
|
|
23
|
-
commit: () => Promise<
|
|
24
|
-
rollback: (error: string) => Promise<
|
|
23
|
+
commit: () => Promise<any>;
|
|
24
|
+
rollback: (error: string) => Promise<any>;
|
|
25
25
|
};
|
|
26
26
|
export type BucketMetadata = ReturnType<AnyBucket['getQueryMeta']> & {
|
|
27
27
|
tag: Tag;
|
|
@@ -45,9 +45,9 @@ export declare class TrxEngine<S extends $Space, M extends $Module, AuthUsers ex
|
|
|
45
45
|
private adapter;
|
|
46
46
|
constructor(origin: TrxEngineOrigin, module: Module<S, M>, authnProviders?: AuthUsers | undefined, config?: TrxEngineConfig<S, M, any, any> | undefined, services?: Record<string, IService>);
|
|
47
47
|
getModule(): Module<S, M>;
|
|
48
|
-
get(id?: string): Promise<Trx<S, M, any>>;
|
|
49
|
-
trx(fn: (trx: TrxNode<S, M, any>) => Promise<TrxNodeStatus>, id?: string, tokens?: AuthRequest<keyof AuthUsers>, users?: Partial<AuthUsers
|
|
50
|
-
trx_hold(fn: (trx: TrxNode<S, M, any>) => Promise<any>, id?: string, authn?: AuthRequest<keyof AuthUsers>, users?: Partial<AuthUsers
|
|
48
|
+
get(id?: string, origin?: string, idempotent?: boolean): Promise<Trx<S, M, any>>;
|
|
49
|
+
trx(fn: (trx: TrxNode<S, M, any>) => Promise<TrxNodeStatus>, id?: string, tokens?: AuthRequest<keyof AuthUsers>, users?: Partial<AuthUsers>, origin?: string, idempotent?: boolean): Promise<TrxStatus<any>>;
|
|
50
|
+
trx_hold(fn: (trx: TrxNode<S, M, any>) => Promise<any>, id?: string, authn?: AuthRequest<keyof AuthUsers>, users?: Partial<AuthUsers>, origin?: string, idempotent?: boolean): Promise<HeldTrxNode<any>>;
|
|
51
51
|
getBucketMetadata(tag: Tag): BucketMetadata;
|
|
52
52
|
getBucketDrive(tag: Tag): DriveAdapter | undefined;
|
|
53
53
|
authenticate(node: TrxNode<S, M, any>, tokens?: AuthRequest<keyof AuthUsers>, users?: AnyUsers, force?: boolean): Promise<void>;
|
|
@@ -32,7 +32,7 @@ class TrxEngine {
|
|
|
32
32
|
this.authnProviders = authnProviders;
|
|
33
33
|
this.config = config;
|
|
34
34
|
this.services = services;
|
|
35
|
-
this.innerTrx = new trx_1.Trx(this, this.module, `trx:${origin}
|
|
35
|
+
this.innerTrx = new trx_1.Trx(this, this.module, `trx:${origin}`, true);
|
|
36
36
|
this.$TrxBucket = new elements_1.$Bucket(this.module.name, '__trx__', `Transaction of Module '${this.module.name}'`, new bucket_model_schema_1.$BucketModel({
|
|
37
37
|
id: new bucket_model_schema_1.$BucketModelField('id', 'id', 'string', 'ID', true),
|
|
38
38
|
origin: new bucket_model_schema_1.$BucketModelField('origin', 'origin', 'string', 'Origin', true),
|
|
@@ -45,39 +45,59 @@ class TrxEngine {
|
|
|
45
45
|
getModule() {
|
|
46
46
|
return this.module;
|
|
47
47
|
}
|
|
48
|
-
async get(id) {
|
|
48
|
+
async get(id, origin, idempotent = false) {
|
|
49
|
+
const _origin = origin ?? this.origin;
|
|
49
50
|
let trx;
|
|
50
51
|
if (!id) {
|
|
51
|
-
trx = new trx_1.Trx(this, this.module,
|
|
52
|
-
log_1.Log.info('module', this.module.name, `Begin ${(0, log_1.scopeTag)('trx', trx.id)} @ ${(0, log_1.anyScopeTag)(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
trx = new trx_1.Trx(this, this.module, _origin, idempotent);
|
|
53
|
+
log_1.Log.info('module', this.module.name, `Begin ${(0, log_1.scopeTag)('trx', trx.id)}${idempotent ? '*' : ''} @ ${(0, log_1.anyScopeTag)(_origin)}`);
|
|
54
|
+
for (const wrap of this.config?.wrap || []) {
|
|
55
|
+
await wrap.begin(trx, this.services);
|
|
56
|
+
}
|
|
57
|
+
if (!idempotent) {
|
|
58
|
+
await this.adapter.create(this.innerTrx.root, {
|
|
59
|
+
id: trx.id,
|
|
60
|
+
origin: trx.origin,
|
|
61
|
+
start: trx.start,
|
|
62
|
+
end: trx.end,
|
|
63
|
+
module: this.module.name
|
|
64
|
+
});
|
|
65
|
+
}
|
|
60
66
|
return trx;
|
|
61
67
|
}
|
|
62
68
|
else {
|
|
69
|
+
if (idempotent) {
|
|
70
|
+
log_1.Log.debug('module', this.module.name, `Continue Idempotent ${(0, log_1.scopeTag)('trx', id)}* @ ${(0, log_1.anyScopeTag)(_origin)}`);
|
|
71
|
+
const trx = new trx_1.Trx(this, this.module, _origin, idempotent, undefined, id);
|
|
72
|
+
for (const wrap of this.config?.wrap || []) {
|
|
73
|
+
await wrap.continue(trx, this.services);
|
|
74
|
+
}
|
|
75
|
+
return trx;
|
|
76
|
+
}
|
|
63
77
|
const trxData = await this.adapter.get(this.innerTrx.root, id);
|
|
64
78
|
if (trxData) {
|
|
65
|
-
log_1.Log.
|
|
79
|
+
log_1.Log.debug('module', this.module.name, `Continue ${(0, log_1.scopeTag)('trx', trxData.id)} @ ${(0, log_1.anyScopeTag)(_origin)}`);
|
|
66
80
|
// Objects read from adapters are not the proper JS class, so they don't
|
|
67
81
|
// carry methods. This must be used to recover the methods.
|
|
68
|
-
trx = Object.assign(new trx_1.Trx(this, this.module,
|
|
82
|
+
trx = Object.assign(new trx_1.Trx(this, this.module, _origin, idempotent), {
|
|
69
83
|
id: trxData.id,
|
|
70
84
|
origin: trxData.origin,
|
|
71
85
|
start: trxData.start,
|
|
72
86
|
end: trxData.end
|
|
73
87
|
});
|
|
88
|
+
for (const wrap of this.config?.wrap || []) {
|
|
89
|
+
await wrap.continue(trx, this.services);
|
|
90
|
+
}
|
|
74
91
|
}
|
|
75
92
|
else {
|
|
76
|
-
log_1.Log.info('module', this.module.name, `Chain ${(0, log_1.scopeTag)('trx', id)} @ ${(0, log_1.anyScopeTag)(
|
|
77
|
-
trx = new trx_1.Trx(this, this.module,
|
|
93
|
+
log_1.Log.info('module', this.module.name, `Chain ${(0, log_1.scopeTag)('trx', id)} @ ${(0, log_1.anyScopeTag)(_origin)}`);
|
|
94
|
+
trx = new trx_1.Trx(this, this.module, _origin, idempotent, undefined, id);
|
|
95
|
+
for (const wrap of this.config?.wrap || []) {
|
|
96
|
+
await wrap.begin(trx, this.services);
|
|
97
|
+
}
|
|
78
98
|
await this.adapter.create(this.innerTrx.root, {
|
|
79
99
|
id: trx.id,
|
|
80
|
-
origin:
|
|
100
|
+
origin: _origin,
|
|
81
101
|
start: trx.start,
|
|
82
102
|
end: trx.end,
|
|
83
103
|
module: this.module.name
|
|
@@ -86,17 +106,11 @@ class TrxEngine {
|
|
|
86
106
|
}
|
|
87
107
|
return trx;
|
|
88
108
|
}
|
|
89
|
-
async trx(fn, id, tokens, users) {
|
|
90
|
-
const trx = await this.get(id);
|
|
109
|
+
async trx(fn, id, tokens, users, origin, idempotent = false) {
|
|
110
|
+
const trx = await this.get(id, origin, idempotent);
|
|
91
111
|
try {
|
|
92
112
|
await this.authenticate(trx.root, tokens, users);
|
|
93
|
-
|
|
94
|
-
if (this.config?.wrap) {
|
|
95
|
-
output = await this.config?.wrap(trx, fn, this.services);
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
output = await fn(trx.root);
|
|
99
|
-
}
|
|
113
|
+
const output = await fn(trx.root);
|
|
100
114
|
await this.commit(trx, output);
|
|
101
115
|
}
|
|
102
116
|
catch (e) {
|
|
@@ -104,17 +118,12 @@ class TrxEngine {
|
|
|
104
118
|
}
|
|
105
119
|
return trx.status();
|
|
106
120
|
}
|
|
107
|
-
async trx_hold(fn, id, authn, users) {
|
|
108
|
-
const trx = await this.get(id);
|
|
121
|
+
async trx_hold(fn, id, authn, users, origin, idempotent = false) {
|
|
122
|
+
const trx = await this.get(id, origin, idempotent);
|
|
109
123
|
let output = {};
|
|
110
124
|
try {
|
|
111
125
|
await this.authenticate(trx.root, authn, users);
|
|
112
|
-
|
|
113
|
-
output = await this.config?.wrap(trx, fn, this.services);
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
output = await fn(trx.root);
|
|
117
|
-
}
|
|
126
|
+
output = await fn(trx.root);
|
|
118
127
|
await this.hold(trx, output);
|
|
119
128
|
}
|
|
120
129
|
catch (e) {
|
|
@@ -146,6 +155,8 @@ class TrxEngine {
|
|
|
146
155
|
const _users = { ...users };
|
|
147
156
|
const _tokens = {};
|
|
148
157
|
for (const providerName in this.authnProviders) {
|
|
158
|
+
if (providerName in _users)
|
|
159
|
+
continue;
|
|
149
160
|
const provider = this.authnProviders[providerName];
|
|
150
161
|
if (!provider) {
|
|
151
162
|
throw error_1.NesoiError.Auth.NoProviderRegisteredForModule(this.module.name, providerName);
|
|
@@ -163,8 +174,10 @@ class TrxEngine {
|
|
|
163
174
|
}
|
|
164
175
|
//
|
|
165
176
|
async hold(trx, output) {
|
|
166
|
-
log_1.Log.
|
|
177
|
+
log_1.Log.debug('module', this.module.name, `Hold ${(0, log_1.scopeTag)('trx', trx.id)} @ ${(0, log_1.anyScopeTag)(this.origin)}`);
|
|
167
178
|
trx_node_1.TrxNode.hold(trx.root, output);
|
|
179
|
+
if (trx.idempotent)
|
|
180
|
+
return trx;
|
|
168
181
|
await this.adapter.put(this.innerTrx.root, {
|
|
169
182
|
id: trx.id,
|
|
170
183
|
origin: this.origin,
|
|
@@ -175,9 +188,11 @@ class TrxEngine {
|
|
|
175
188
|
return trx;
|
|
176
189
|
}
|
|
177
190
|
async commit(trx, output) {
|
|
178
|
-
log_1.Log.info('module', this.module.name, `Commit ${(0, log_1.scopeTag)('trx', trx.id)} @ ${(0, log_1.anyScopeTag)(this.origin)}`);
|
|
179
191
|
trx_node_1.TrxNode.ok(trx.root, output);
|
|
180
192
|
trx.end = datetime_1.NesoiDatetime.now();
|
|
193
|
+
if (trx.idempotent)
|
|
194
|
+
return trx;
|
|
195
|
+
log_1.Log.info('module', this.module.name, `Commit ${(0, log_1.scopeTag)('trx', trx.id)} @ ${(0, log_1.anyScopeTag)(this.origin)}`);
|
|
181
196
|
await this.adapter.put(this.innerTrx.root, {
|
|
182
197
|
id: trx.id,
|
|
183
198
|
origin: this.origin,
|
|
@@ -186,13 +201,18 @@ class TrxEngine {
|
|
|
186
201
|
module: this.module.name
|
|
187
202
|
});
|
|
188
203
|
await trx_1.Trx.onCommit(trx);
|
|
204
|
+
for (const wrap of this.config?.wrap || []) {
|
|
205
|
+
await wrap.commit(trx, this.services);
|
|
206
|
+
}
|
|
189
207
|
return trx;
|
|
190
208
|
}
|
|
191
209
|
async rollback(trx, error) {
|
|
192
210
|
log_1.Log.error('module', this.module.name, `[${error.status}] ${error.toString()}`, error.stack);
|
|
193
|
-
log_1.Log.warn('module', this.module.name, `Rollback ${(0, log_1.scopeTag)('trx', trx.id)} @ ${(0, log_1.anyScopeTag)(this.origin)}`);
|
|
194
211
|
trx_node_1.TrxNode.error(trx.root, error);
|
|
195
212
|
trx.end = datetime_1.NesoiDatetime.now();
|
|
213
|
+
if (trx.idempotent)
|
|
214
|
+
return trx;
|
|
215
|
+
log_1.Log.warn('module', this.module.name, `Rollback ${(0, log_1.scopeTag)('trx', trx.id)} @ ${(0, log_1.anyScopeTag)(this.origin)}`);
|
|
196
216
|
await this.adapter.put(this.innerTrx.root, {
|
|
197
217
|
id: trx.id,
|
|
198
218
|
origin: this.origin,
|
|
@@ -201,6 +221,9 @@ class TrxEngine {
|
|
|
201
221
|
module: this.module.name
|
|
202
222
|
});
|
|
203
223
|
await trx_1.Trx.onRollback(trx);
|
|
224
|
+
for (const wrap of this.config?.wrap || []) {
|
|
225
|
+
await wrap.rollback(trx, this.services);
|
|
226
|
+
}
|
|
204
227
|
return trx;
|
|
205
228
|
}
|
|
206
229
|
}
|
|
@@ -56,7 +56,7 @@ export declare class TrxNode<Space extends $Space, M extends $Module, AuthUsers
|
|
|
56
56
|
message<Raw extends M['#input']['#raw'], Msg extends $Message = M['messages'][Raw['$'] & keyof M['messages']]>(raw: Raw): Promise<M['#input']['#parsed']>;
|
|
57
57
|
value<K extends keyof M['constants']['values']>(name: K): M['constants']['values'][K]['value'];
|
|
58
58
|
enum<EnumName extends keyof M['constants']['enums']>(name: EnumName): Enum<M['constants']['enums'][EnumName]>;
|
|
59
|
-
cache(config: Record<keyof M['buckets'], 'eager'
|
|
59
|
+
cache(config: Partial<Record<keyof M['buckets'], 'eager'>>): this;
|
|
60
60
|
bucket<Name extends keyof M['buckets'], Bucket extends M['buckets'][Name]>(name: Name): BucketTrxNode<M, Bucket>;
|
|
61
61
|
job<Name extends keyof M['jobs'], Job extends M['jobs'][Name]>(name: Name): JobTrxNode<M, Job>;
|
|
62
62
|
static jobWithCustomCtx<M extends $Module, JobName extends keyof M['jobs'], Job extends M['jobs'][JobName]>(node: AnyTrxNode, name: string, ctx?: Record<string, any>): JobTrxNode<M, Job>;
|
|
@@ -120,7 +120,6 @@ class TrxNode {
|
|
|
120
120
|
}
|
|
121
121
|
return new constants_1.Enum(this.module.schema.constants.enums[key]);
|
|
122
122
|
}
|
|
123
|
-
// Blocks
|
|
124
123
|
/*
|
|
125
124
|
Cache
|
|
126
125
|
*/
|
|
@@ -132,6 +131,7 @@ class TrxNode {
|
|
|
132
131
|
}
|
|
133
132
|
return this;
|
|
134
133
|
}
|
|
134
|
+
// Blocks
|
|
135
135
|
bucket(name) {
|
|
136
136
|
const tag = dependency_1.Tag.fromNameOrShort(this.module.name, 'bucket', name);
|
|
137
137
|
return new bucket_trx_node_1.BucketTrxNode(this, tag);
|