@acodeninja/persist 3.0.0-next.22 → 3.0.0-next.24
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/package.json +1 -1
- package/src/Connection.js +27 -53
- package/src/engine/storage/StorageEngine.js +24 -8
package/package.json
CHANGED
package/src/Connection.js
CHANGED
@@ -7,24 +7,6 @@ import Model from './data/Model.js';
|
|
7
7
|
import SearchIndex from './data/SearchIndex.js';
|
8
8
|
import _ from 'lodash';
|
9
9
|
|
10
|
-
/**
|
11
|
-
* Represents a transactional operation to be executed, typically queued and later committed.
|
12
|
-
*
|
13
|
-
* Stores the method to invoke, the arguments to apply, and tracks the result or error state
|
14
|
-
* of the transaction once it's processed.
|
15
|
-
*
|
16
|
-
* @class Transaction
|
17
|
-
*/
|
18
|
-
export class Transaction {
|
19
|
-
constructor(method, ...args) {
|
20
|
-
this.method = method;
|
21
|
-
this.args = args;
|
22
|
-
this.original = undefined;
|
23
|
-
this.error = undefined;
|
24
|
-
this.committed = false;
|
25
|
-
}
|
26
|
-
}
|
27
|
-
|
28
10
|
/**
|
29
11
|
* @class Connection
|
30
12
|
*/
|
@@ -35,12 +17,6 @@ export default class Connection {
|
|
35
17
|
*/
|
36
18
|
#storage;
|
37
19
|
|
38
|
-
/**
|
39
|
-
* @private
|
40
|
-
* @property {CacheEngine|undefined}
|
41
|
-
*/
|
42
|
-
#cache;
|
43
|
-
|
44
20
|
/**
|
45
21
|
* @private
|
46
22
|
* @property {Record<String, Model.constructor>}
|
@@ -50,12 +26,10 @@ export default class Connection {
|
|
50
26
|
/**
|
51
27
|
* Create a new connection
|
52
28
|
* @param {StorageEngine} storage
|
53
|
-
* @param {CacheEngine|undefined} cache
|
54
29
|
* @param {Array<Model.constructor>} models
|
55
30
|
*/
|
56
|
-
constructor(storage,
|
31
|
+
constructor(storage, models) {
|
57
32
|
this.#storage = storage;
|
58
|
-
this.#cache = cache;
|
59
33
|
this.#models = Object.fromEntries((models ?? []).map(model => [model.name, model]));
|
60
34
|
|
61
35
|
if (!this.#storage) throw new MissingArgumentsConnectionError('No storage engine provided');
|
@@ -434,51 +408,51 @@ export default class Connection {
|
|
434
408
|
* @return {Connection}
|
435
409
|
*/
|
436
410
|
transaction() {
|
437
|
-
const
|
411
|
+
const operations = [];
|
438
412
|
|
439
|
-
const engine = CreateTransactionalStorageEngine(
|
413
|
+
const engine = CreateTransactionalStorageEngine(operations, this.#storage);
|
440
414
|
|
441
|
-
const transaction = new this.constructor(engine,
|
415
|
+
const transaction = new this.constructor(engine, Object.values(this.#models));
|
442
416
|
|
443
417
|
transaction.commit = async () => {
|
444
418
|
try {
|
445
|
-
for (const [index,
|
419
|
+
for (const [index, operation] of operations.entries()) {
|
446
420
|
try {
|
447
|
-
if (
|
448
|
-
|
421
|
+
if (operation.method === 'putModel')
|
422
|
+
operations[index].original = await this.#storage.getModel(operation.args[0].id).catch(() => undefined);
|
449
423
|
|
450
|
-
if (
|
451
|
-
|
424
|
+
if (operation.method === 'deleteModel')
|
425
|
+
operations[index].original = await this.#storage.getModel(operation.args[0]);
|
452
426
|
|
453
|
-
if (
|
454
|
-
|
427
|
+
if (operation.method === 'putIndex')
|
428
|
+
operations[index].original = await this.#storage.getIndex(operation.args[0]);
|
455
429
|
|
456
|
-
if (
|
457
|
-
|
430
|
+
if (operation.method === 'putSearchIndex')
|
431
|
+
operations[index].original = await this.#storage.getSearchIndex(operation.args[0]);
|
458
432
|
|
459
|
-
await this.#storage[
|
433
|
+
await this.#storage[operation.method](...operation.args);
|
460
434
|
|
461
|
-
|
435
|
+
operations[index].committed = true;
|
462
436
|
} catch (error) {
|
463
|
-
|
437
|
+
operations[index].error = error;
|
464
438
|
throw error;
|
465
439
|
}
|
466
440
|
}
|
467
441
|
} catch (error) {
|
468
|
-
for (const
|
469
|
-
if (
|
470
|
-
if (['putModel', 'deleteModel'].includes(
|
471
|
-
await this.#storage.putModel(
|
442
|
+
for (const operation of operations) {
|
443
|
+
if (operation.committed && operation.original) {
|
444
|
+
if (['putModel', 'deleteModel'].includes(operation.method))
|
445
|
+
await this.#storage.putModel(operation.original);
|
472
446
|
|
473
|
-
if ('putIndex'
|
474
|
-
await this.#storage.putIndex(
|
447
|
+
if (operation.method === 'putIndex')
|
448
|
+
await this.#storage.putIndex(operation.args[0], operation.original);
|
475
449
|
|
476
|
-
if ('putSearchIndex'
|
477
|
-
await this.#storage.putSearchIndex(
|
450
|
+
if (operation.method === 'putSearchIndex')
|
451
|
+
await this.#storage.putSearchIndex(operation.args[0], operation.original);
|
478
452
|
}
|
479
453
|
}
|
480
454
|
|
481
|
-
throw new CommitFailedTransactionError(
|
455
|
+
throw new CommitFailedTransactionError(operations, error);
|
482
456
|
}
|
483
457
|
};
|
484
458
|
|
@@ -632,11 +606,11 @@ class TransactionError extends Error {
|
|
632
606
|
export class CommitFailedTransactionError extends TransactionError {
|
633
607
|
/**
|
634
608
|
*
|
635
|
-
* @param {Array<
|
609
|
+
* @param {Array<Operation>} transactions
|
636
610
|
* @param {Error} error
|
637
611
|
*/
|
638
612
|
constructor(transactions, error) {
|
639
|
-
super('
|
613
|
+
super('Operation failed to commit.');
|
640
614
|
this.transactions = transactions;
|
641
615
|
this.error = error;
|
642
616
|
}
|
@@ -1,5 +1,3 @@
|
|
1
|
-
import {Transaction} from '../../Connection.js';
|
2
|
-
|
3
1
|
export default class StorageEngine {
|
4
2
|
/**
|
5
3
|
* @param {Object} configuration
|
@@ -142,32 +140,50 @@ export class DeleteHasUnintendedConsequencesStorageEngineError extends StorageEn
|
|
142
140
|
}
|
143
141
|
}
|
144
142
|
|
143
|
+
/**
|
144
|
+
* Represents a transactional operation to be executed, typically queued and later committed.
|
145
|
+
*
|
146
|
+
* Stores the method to invoke, the arguments to apply, and tracks the result or error state
|
147
|
+
* of the transaction once it's processed.
|
148
|
+
*
|
149
|
+
* @class Operation
|
150
|
+
*/
|
151
|
+
export class Operation {
|
152
|
+
constructor(method, ...args) {
|
153
|
+
this.method = method;
|
154
|
+
this.args = args;
|
155
|
+
this.original = undefined;
|
156
|
+
this.error = undefined;
|
157
|
+
this.committed = false;
|
158
|
+
}
|
159
|
+
}
|
160
|
+
|
145
161
|
/**
|
146
162
|
*
|
147
|
-
* @param {Array<
|
163
|
+
* @param {Array<Operation>} transactions
|
148
164
|
* @param {StorageEngine} engine
|
149
165
|
* @return {StorageEngine}
|
150
166
|
*/
|
151
|
-
export function CreateTransactionalStorageEngine(
|
167
|
+
export function CreateTransactionalStorageEngine(operations, engine) {
|
152
168
|
const transactionalEngine = Object.create(engine);
|
153
169
|
|
154
170
|
transactionalEngine.putModel = (...args) => {
|
155
|
-
|
171
|
+
operations.push(new Operation('putModel', ...args));
|
156
172
|
return Promise.resolve();
|
157
173
|
};
|
158
174
|
|
159
175
|
transactionalEngine.deleteModel = (...args) => {
|
160
|
-
|
176
|
+
operations.push(new Operation('deleteModel', ...args));
|
161
177
|
return Promise.resolve();
|
162
178
|
};
|
163
179
|
|
164
180
|
transactionalEngine.putIndex = (...args) => {
|
165
|
-
|
181
|
+
operations.push(new Operation('putIndex', ...args));
|
166
182
|
return Promise.resolve();
|
167
183
|
};
|
168
184
|
|
169
185
|
transactionalEngine.putSearchIndex = (...args) => {
|
170
|
-
|
186
|
+
operations.push(new Operation('putSearchIndex', ...args));
|
171
187
|
return Promise.resolve();
|
172
188
|
};
|
173
189
|
|