nesoi 3.3.24 → 3.3.26

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.
@@ -38,7 +38,7 @@ class TrxEngine {
38
38
  origin: new bucket_model_schema_1.$BucketModelField('origin', 'origin', 'string', 'Origin', true),
39
39
  module: new bucket_model_schema_1.$BucketModelField('module', 'module', 'string', 'Module', true),
40
40
  start: new bucket_model_schema_1.$BucketModelField('start', 'start', 'datetime', 'Start', true),
41
- end: new bucket_model_schema_1.$BucketModelField('end', 'end', 'datetime', 'Start', false),
41
+ end: new bucket_model_schema_1.$BucketModelField('end', 'end', 'datetime', 'End', false),
42
42
  }), new bucket_graph_schema_1.$BucketGraph(), {});
43
43
  this.adapter = config?.adapter?.(module.schema) || new memory_bucket_adapter_1.MemoryBucketAdapter(this.$TrxBucket, {});
44
44
  }
@@ -48,9 +48,10 @@ class TrxEngine {
48
48
  async get(id, origin, idempotent = false) {
49
49
  const _origin = origin ?? this.origin;
50
50
  let trx;
51
+ // New transaction
51
52
  if (!id) {
52
53
  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
+ log_1.Log.info('module', this.module.name, `Begin${idempotent ? '*' : ''} ${(0, log_1.scopeTag)('trx', trx.id + trx.root.id)} @ ${(0, log_1.anyScopeTag)(_origin)}`);
54
55
  for (const wrap of this.config?.wrap || []) {
55
56
  await wrap.begin(trx, this.services);
56
57
  }
@@ -60,38 +61,52 @@ class TrxEngine {
60
61
  origin: trx.origin,
61
62
  start: trx.start,
62
63
  end: trx.end,
63
- module: this.module.name
64
+ module: this.module.name,
64
65
  });
65
66
  }
66
67
  return trx;
67
68
  }
69
+ // Chain/Continue transaction
68
70
  else {
71
+ const trxData = await this.adapter.get(this.innerTrx.root, id);
72
+ // If a transaction is being continued it cannot become idempotent,
73
+ // since the data it needs is inside the transaction.
74
+ // > Started as NOT idempotent on this module, is NEVER idempotent
75
+ // This only affects services which need this info for deciding whether
76
+ // to commit/rollback a transaction. The trx engine still uses the requested
77
+ // idempotent value to decide whether to run or not a commit/rollback,
78
+ // because otherwise it would commit/rollback partially idempotent transactions
79
+ // before they're actually finished.
80
+ if (trxData)
81
+ idempotent = false;
82
+ // Differently, a transaction with specific id which doesn't exist can
83
+ // be either an ongoing idempotent transaction from this module or an
84
+ // external transaction starting at a different module.
85
+ // On either case, it's allowed to become idempotent.
86
+ // > Not stored, can become idempotent.
87
+ // if (!trxData) idempotent = idempotent;
88
+ trx = new trx_1.Trx(this, this.module, _origin, idempotent, undefined, id);
89
+ // (Continue*)
69
90
  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);
91
+ log_1.Log.info('module', this.module.name, `Continue* ${(0, log_1.scopeTag)('trx', id)} @ ${(0, log_1.anyScopeTag)(_origin)}`);
72
92
  for (const wrap of this.config?.wrap || []) {
73
93
  await wrap.continue(trx, this.services);
74
94
  }
75
95
  return trx;
76
96
  }
77
- const trxData = await this.adapter.get(this.innerTrx.root, id);
97
+ // (Continue)
78
98
  if (trxData) {
79
- log_1.Log.debug('module', this.module.name, `Continue ${(0, log_1.scopeTag)('trx', trxData.id)} @ ${(0, log_1.anyScopeTag)(_origin)}`);
80
- // Objects read from adapters are not the proper JS class, so they don't
81
- // carry methods. This must be used to recover the methods.
82
- trx = Object.assign(new trx_1.Trx(this, this.module, _origin, idempotent), {
83
- id: trxData.id,
84
- origin: trxData.origin,
85
- start: trxData.start,
86
- end: trxData.end
87
- });
99
+ // Update transaction with data read from adapter
100
+ trx.start = trxData.start;
101
+ trx.end = trxData.end;
102
+ log_1.Log.info('module', this.module.name, `Continue ${(0, log_1.scopeTag)('trx', trx.id + trx.root.id)} @ ${(0, log_1.anyScopeTag)(_origin)}`);
88
103
  for (const wrap of this.config?.wrap || []) {
89
104
  await wrap.continue(trx, this.services);
90
105
  }
91
106
  }
107
+ // (Chain)
92
108
  else {
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);
109
+ log_1.Log.info('module', this.module.name, `Chain ${(0, log_1.scopeTag)('trx', id + trx.root.id)} @ ${(0, log_1.anyScopeTag)(_origin)}`);
95
110
  for (const wrap of this.config?.wrap || []) {
96
111
  await wrap.begin(trx, this.services);
97
112
  }
@@ -100,7 +115,7 @@ class TrxEngine {
100
115
  origin: _origin,
101
116
  start: trx.start,
102
117
  end: trx.end,
103
- module: this.module.name
118
+ module: this.module.name,
104
119
  });
105
120
  }
106
121
  }
@@ -111,10 +126,10 @@ class TrxEngine {
111
126
  try {
112
127
  await this.authenticate(trx.root, tokens, users);
113
128
  const output = await fn(trx.root);
114
- await this.commit(trx, output);
129
+ await this.commit(trx, output, idempotent);
115
130
  }
116
131
  catch (e) {
117
- await this.rollback(trx, e);
132
+ await this.rollback(trx, e, idempotent);
118
133
  }
119
134
  return trx.status();
120
135
  }
@@ -124,16 +139,16 @@ class TrxEngine {
124
139
  try {
125
140
  await this.authenticate(trx.root, authn, users);
126
141
  output = await fn(trx.root);
127
- await this.hold(trx, output);
142
+ await this.hold(trx, output, idempotent);
128
143
  }
129
144
  catch (e) {
130
- await this.rollback(trx, e);
145
+ await this.rollback(trx, e, idempotent);
131
146
  }
132
147
  return {
133
148
  id: trx.id,
134
149
  status: trx.status(),
135
- commit: () => this.commit(trx, output),
136
- rollback: (error) => this.rollback(trx, error)
150
+ commit: () => this.commit(trx, output, idempotent),
151
+ rollback: (error) => this.rollback(trx, error, idempotent)
137
152
  };
138
153
  }
139
154
  /* Metadata sharing between modules */
@@ -173,54 +188,54 @@ class TrxEngine {
173
188
  trx_node_1.TrxNode.addAuthn(node, _tokens, _users);
174
189
  }
175
190
  //
176
- async hold(trx, output) {
191
+ async hold(trx, output, idempotent) {
177
192
  log_1.Log.debug('module', this.module.name, `Hold ${(0, log_1.scopeTag)('trx', trx.id)} @ ${(0, log_1.anyScopeTag)(this.origin)}`);
178
193
  trx_node_1.TrxNode.hold(trx.root, output);
179
- if (trx.idempotent)
194
+ if (idempotent)
180
195
  return trx;
181
196
  await this.adapter.put(this.innerTrx.root, {
182
197
  id: trx.id,
183
198
  origin: this.origin,
184
199
  start: trx.start,
185
200
  end: trx.end,
186
- module: this.module.name
201
+ module: this.module.name,
187
202
  });
188
203
  return trx;
189
204
  }
190
- async commit(trx, output) {
205
+ async commit(trx, output, idempotent) {
191
206
  trx_node_1.TrxNode.ok(trx.root, output);
192
207
  trx.end = datetime_1.NesoiDatetime.now();
193
- if (trx.idempotent)
208
+ if (idempotent)
194
209
  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)}`);
210
+ await trx_1.Trx.onCommit(trx);
211
+ log_1.Log.info('module', this.module.name, `Commit ${(0, log_1.scopeTag)('trx', trx.id)} @ ${(0, log_1.anyScopeTag)(this.origin)} (held: ${Object.keys(trx.holds).length})`);
196
212
  await this.adapter.put(this.innerTrx.root, {
197
213
  id: trx.id,
198
214
  origin: this.origin,
199
215
  start: trx.start,
200
216
  end: trx.end,
201
- module: this.module.name
217
+ module: this.module.name,
202
218
  });
203
- await trx_1.Trx.onCommit(trx);
204
219
  for (const wrap of this.config?.wrap || []) {
205
220
  await wrap.commit(trx, this.services);
206
221
  }
207
222
  return trx;
208
223
  }
209
- async rollback(trx, error) {
224
+ async rollback(trx, error, idempotent) {
210
225
  log_1.Log.error('module', this.module.name, `[${error.status}] ${error.toString()}`, error.stack);
211
226
  trx_node_1.TrxNode.error(trx.root, error);
212
227
  trx.end = datetime_1.NesoiDatetime.now();
213
- if (trx.idempotent)
228
+ if (idempotent)
214
229
  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)}`);
230
+ await trx_1.Trx.onRollback(trx);
231
+ log_1.Log.warn('module', this.module.name, `Rollback ${(0, log_1.scopeTag)('trx', trx.id)} @ ${(0, log_1.anyScopeTag)(this.origin)} (held: ${Object.keys(trx.holds).length})`);
216
232
  await this.adapter.put(this.innerTrx.root, {
217
233
  id: trx.id,
218
234
  origin: this.origin,
219
235
  start: trx.start,
220
236
  end: trx.end,
221
- module: this.module.name
237
+ module: this.module.name,
222
238
  });
223
- await trx_1.Trx.onRollback(trx);
224
239
  for (const wrap of this.config?.wrap || []) {
225
240
  await wrap.rollback(trx, this.services);
226
241
  }
@@ -55,7 +55,7 @@ class TrxNode {
55
55
  this.id = id || (Math.random() + 1).toString(36).substring(7);
56
56
  }
57
57
  else {
58
- this.id = '#';
58
+ this.id = '#' + (Math.random() + 1).toString(36).substring(7);
59
59
  }
60
60
  this.globalId = `${this.trx.id}.${this.id}`;
61
61
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nesoi",
3
- "version": "3.3.24",
3
+ "version": "3.3.26",
4
4
  "description": "Declarative framework for data-driven applications",
5
5
  "repository": {
6
6
  "type": "git",