reactronic 0.22.302 → 0.22.303
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/build/dist/source/Logging.d.ts +6 -6
- package/build/dist/source/Rx.d.ts +1 -0
- package/build/dist/source/Rx.js +5 -4
- package/build/dist/source/api.d.ts +1 -1
- package/build/dist/source/api.js +3 -3
- package/build/dist/source/impl/Changeset.d.ts +60 -0
- package/build/dist/source/impl/Changeset.js +361 -0
- package/build/dist/source/impl/Data.d.ts +20 -15
- package/build/dist/source/impl/Data.js +20 -11
- package/build/dist/source/impl/Hooks.d.ts +41 -12
- package/build/dist/source/impl/Hooks.js +84 -44
- package/build/dist/source/impl/Journal.d.ts +2 -2
- package/build/dist/source/impl/Journal.js +56 -45
- package/build/dist/source/impl/Meta.d.ts +2 -2
- package/build/dist/source/impl/Meta.js +7 -7
- package/build/dist/source/impl/Operation.d.ts +7 -7
- package/build/dist/source/impl/Operation.js +123 -122
- package/build/dist/source/impl/Transaction.d.ts +2 -2
- package/build/dist/source/impl/Transaction.js +23 -23
- package/package.json +1 -1
- package/build/dist/source/impl/Snapshot.d.ts +0 -60
- package/build/dist/source/impl/Snapshot.js +0 -353
|
@@ -5,19 +5,19 @@ const Dbg_1 = require("../util/Dbg");
|
|
|
5
5
|
const Options_1 = require("../Options");
|
|
6
6
|
const Controller_1 = require("../Controller");
|
|
7
7
|
const Data_1 = require("./Data");
|
|
8
|
-
const
|
|
8
|
+
const Changeset_1 = require("./Changeset");
|
|
9
9
|
const Transaction_1 = require("./Transaction");
|
|
10
10
|
const Monitor_1 = require("./Monitor");
|
|
11
11
|
const Hooks_1 = require("./Hooks");
|
|
12
12
|
const Journal_1 = require("./Journal");
|
|
13
13
|
const BOOT_ARGS = [];
|
|
14
14
|
const BOOT_CAUSE = '<boot>';
|
|
15
|
-
const
|
|
15
|
+
const EMPTY_HANDLE = new Data_1.ObjectHandle(undefined, undefined, Hooks_1.Hooks.handler, Changeset_1.EMPTY_SNAPSHOT, '<empty>');
|
|
16
16
|
class OperationController extends Controller_1.Controller {
|
|
17
|
-
constructor(
|
|
17
|
+
constructor(h, m) {
|
|
18
18
|
super();
|
|
19
|
-
this.
|
|
20
|
-
this.memberName =
|
|
19
|
+
this.objectHandle = h;
|
|
20
|
+
this.memberName = m;
|
|
21
21
|
}
|
|
22
22
|
configure(options) { return OperationController.configureImpl(this, options); }
|
|
23
23
|
get options() { return this.peek(undefined).operation.options; }
|
|
@@ -25,35 +25,35 @@ class OperationController extends Controller_1.Controller {
|
|
|
25
25
|
get args() { return this.use().operation.args; }
|
|
26
26
|
get result() { return this.useOrRun(true, undefined).content; }
|
|
27
27
|
get error() { return this.use().operation.error; }
|
|
28
|
-
get stamp() { return this.use().
|
|
28
|
+
get stamp() { return this.use().snapshot.changeset.timestamp; }
|
|
29
29
|
get isUpToDate() { return this.use().isUpToDate; }
|
|
30
|
-
markObsolete() { Transaction_1.Transaction.run({ hint: Dbg_1.Log.isOn ? `markObsolete(${
|
|
30
|
+
markObsolete() { Transaction_1.Transaction.run({ hint: Dbg_1.Log.isOn ? `markObsolete(${Changeset_1.Dump.obj(this.objectHandle, this.memberName)})` : 'markObsolete()' }, OperationController.markObsolete, this); }
|
|
31
31
|
pullLastResult(args) { return this.useOrRun(true, args).content; }
|
|
32
32
|
useOrRun(weak, args) {
|
|
33
33
|
var _a;
|
|
34
34
|
let oc = this.peek(args);
|
|
35
|
-
const ctx = oc.
|
|
35
|
+
const ctx = oc.changeset;
|
|
36
36
|
const op = oc.operation;
|
|
37
37
|
const opts = op.options;
|
|
38
|
-
if (!oc.isUpToDate && oc.
|
|
38
|
+
if (!oc.isUpToDate && !oc.snapshot.disposed
|
|
39
39
|
&& (!weak || op.cause === BOOT_CAUSE || !op.successor ||
|
|
40
40
|
op.successor.transaction.isFinished)) {
|
|
41
41
|
const outerOpts = (_a = Operation.current) === null || _a === void 0 ? void 0 : _a.options;
|
|
42
42
|
const standalone = weak || opts.standalone || opts.kind === Options_1.Kind.Reaction ||
|
|
43
43
|
(opts.kind === Options_1.Kind.Transaction && outerOpts && (outerOpts.noSideEffects || outerOpts.kind === Options_1.Kind.Cache)) ||
|
|
44
|
-
(opts.kind === Options_1.Kind.Cache && (oc.
|
|
45
|
-
oc.
|
|
44
|
+
(opts.kind === Options_1.Kind.Cache && (oc.snapshot.changeset.sealed ||
|
|
45
|
+
oc.snapshot.former.snapshot !== Changeset_1.EMPTY_SNAPSHOT));
|
|
46
46
|
const token = opts.noSideEffects ? this : undefined;
|
|
47
47
|
const oc2 = this.run(oc, standalone, opts, token, args);
|
|
48
|
-
const ctx2 = oc2.operation.
|
|
48
|
+
const ctx2 = oc2.operation.changeset;
|
|
49
49
|
if (!weak || ctx === ctx2 || (ctx2.sealed && ctx.timestamp >= ctx2.timestamp))
|
|
50
50
|
oc = oc2;
|
|
51
51
|
}
|
|
52
52
|
else if (Dbg_1.Log.isOn && Dbg_1.Log.opt.operation && (opts.logging === undefined ||
|
|
53
53
|
opts.logging.operation === undefined || opts.logging.operation === true))
|
|
54
|
-
Dbg_1.Log.write(Transaction_1.Transaction.current.isFinished ? '' : '║', ' (=)', `${
|
|
54
|
+
Dbg_1.Log.write(Transaction_1.Transaction.current.isFinished ? '' : '║', ' (=)', `${Changeset_1.Dump.snapshot2(oc.operation.controller.objectHandle, oc.changeset, this.memberName)} result is reused from T${oc.operation.transaction.id}[${oc.operation.transaction.hint}]`);
|
|
55
55
|
const t = oc.operation;
|
|
56
|
-
|
|
56
|
+
Changeset_1.Changeset.markUsed(t, oc.snapshot, this.memberName, this.objectHandle, t.options.kind, weak);
|
|
57
57
|
return t;
|
|
58
58
|
}
|
|
59
59
|
static of(method) {
|
|
@@ -105,75 +105,74 @@ class OperationController extends Controller_1.Controller {
|
|
|
105
105
|
return op ? op.dependencies() : ['Rx.dependencies should be called from inside of reactive method'];
|
|
106
106
|
}
|
|
107
107
|
peek(args) {
|
|
108
|
-
const ctx =
|
|
109
|
-
const
|
|
110
|
-
const op = this.
|
|
108
|
+
const ctx = Changeset_1.Changeset.current();
|
|
109
|
+
const os = ctx.seekSnapshot(this.objectHandle, this.memberName);
|
|
110
|
+
const op = this.acquireFromSnapshot(os, args);
|
|
111
111
|
const isValid = op.options.kind !== Options_1.Kind.Transaction && op.cause !== BOOT_CAUSE &&
|
|
112
|
-
(ctx === op.
|
|
112
|
+
(ctx === op.changeset || ctx.timestamp < op.obsoleteSince) &&
|
|
113
113
|
(!op.options.triggeringArgs || args === undefined ||
|
|
114
|
-
op.args.length === args.length && op.args.every((t, i) => t === args[i])) ||
|
|
115
|
-
|
|
116
|
-
return { operation: op, isUpToDate: isValid, snapshot: ctx, revision: r };
|
|
114
|
+
op.args.length === args.length && op.args.every((t, i) => t === args[i])) || os.disposed;
|
|
115
|
+
return { operation: op, isUpToDate: isValid, changeset: ctx, snapshot: os };
|
|
117
116
|
}
|
|
118
117
|
use() {
|
|
119
118
|
const oc = this.peek(undefined);
|
|
120
|
-
|
|
119
|
+
Changeset_1.Changeset.markUsed(oc.operation, oc.snapshot, this.memberName, this.objectHandle, oc.operation.options.kind, true);
|
|
121
120
|
return oc;
|
|
122
121
|
}
|
|
123
122
|
edit() {
|
|
124
|
-
const h = this.
|
|
123
|
+
const h = this.objectHandle;
|
|
125
124
|
const m = this.memberName;
|
|
126
|
-
const ctx =
|
|
127
|
-
const
|
|
128
|
-
let op = this.
|
|
129
|
-
if (op.
|
|
130
|
-
const op2 = new Operation(this,
|
|
131
|
-
|
|
132
|
-
ctx.bumpBy(
|
|
133
|
-
|
|
125
|
+
const ctx = Changeset_1.Changeset.edit();
|
|
126
|
+
const os = ctx.getEditableSnapshot(h, m, Data_1.Meta.Handle, this);
|
|
127
|
+
let op = this.acquireFromSnapshot(os, undefined);
|
|
128
|
+
if (op.changeset !== os.changeset) {
|
|
129
|
+
const op2 = new Operation(this, os.changeset, op);
|
|
130
|
+
os.data[m] = op2.reenterOver(op);
|
|
131
|
+
ctx.bumpBy(os.former.snapshot.changeset.timestamp);
|
|
132
|
+
Changeset_1.Changeset.markEdited(op, op2, true, os, m, h);
|
|
134
133
|
op = op2;
|
|
135
134
|
}
|
|
136
|
-
return { operation: op, isUpToDate: true,
|
|
135
|
+
return { operation: op, isUpToDate: true, changeset: ctx, snapshot: os };
|
|
137
136
|
}
|
|
138
|
-
|
|
137
|
+
acquireFromSnapshot(os, args) {
|
|
139
138
|
const m = this.memberName;
|
|
140
|
-
let op =
|
|
139
|
+
let op = os.data[m];
|
|
141
140
|
if (op.controller !== this) {
|
|
142
|
-
if (
|
|
143
|
-
const hint = Dbg_1.Log.isOn ? `${
|
|
144
|
-
const standalone =
|
|
141
|
+
if (os.changeset !== Changeset_1.EMPTY_SNAPSHOT.changeset) {
|
|
142
|
+
const hint = Dbg_1.Log.isOn ? `${Changeset_1.Dump.obj(this.objectHandle, m)}/boot` : 'MethodController/init';
|
|
143
|
+
const standalone = os.changeset.sealed || os.former.snapshot !== Changeset_1.EMPTY_SNAPSHOT;
|
|
145
144
|
op = Transaction_1.Transaction.run({ hint, standalone, token: this }, () => {
|
|
146
|
-
const h = this.
|
|
147
|
-
let r2 =
|
|
145
|
+
const h = this.objectHandle;
|
|
146
|
+
let r2 = Changeset_1.Changeset.current().getRelevantSnapshot(h, m);
|
|
148
147
|
let op2 = r2.data[m];
|
|
149
148
|
if (op2.controller !== this) {
|
|
150
|
-
r2 =
|
|
151
|
-
const t = new Operation(this, r2.
|
|
149
|
+
r2 = Changeset_1.Changeset.edit().getEditableSnapshot(h, m, Data_1.Meta.Handle, this);
|
|
150
|
+
const t = new Operation(this, r2.changeset, op2);
|
|
152
151
|
if (args)
|
|
153
152
|
t.args = args;
|
|
154
153
|
t.cause = BOOT_CAUSE;
|
|
155
154
|
r2.data[m] = t;
|
|
156
|
-
|
|
155
|
+
Changeset_1.Changeset.markEdited(op2, t, true, r2, m, h);
|
|
157
156
|
op2 = t;
|
|
158
157
|
}
|
|
159
158
|
return op2;
|
|
160
159
|
});
|
|
161
160
|
}
|
|
162
161
|
else {
|
|
163
|
-
const t = new Operation(this,
|
|
162
|
+
const t = new Operation(this, os.changeset, op);
|
|
164
163
|
if (args)
|
|
165
164
|
t.args = args;
|
|
166
165
|
t.cause = BOOT_CAUSE;
|
|
167
|
-
|
|
166
|
+
os.data[m] = t;
|
|
168
167
|
op = t;
|
|
169
168
|
if (Dbg_1.Log.isOn && Dbg_1.Log.opt.write)
|
|
170
|
-
Dbg_1.Log.write('║', '
|
|
169
|
+
Dbg_1.Log.write('║', ' ⎘⎘', `${Changeset_1.Dump.obj(this.objectHandle, m)} - new snapshot is created outside of transaction (revision ${os.revision})`);
|
|
171
170
|
}
|
|
172
171
|
}
|
|
173
172
|
return op;
|
|
174
173
|
}
|
|
175
174
|
run(existing, standalone, options, token, args) {
|
|
176
|
-
const hint = Dbg_1.Log.isOn ? `${
|
|
175
|
+
const hint = Dbg_1.Log.isOn ? `${Changeset_1.Dump.obj(this.objectHandle, this.memberName)}${args && args.length > 0 && (typeof args[0] === 'number' || typeof args[0] === 'string') ? ` - ${args[0]}` : ''}` : `${Changeset_1.Dump.obj(this.objectHandle, this.memberName)}`;
|
|
177
176
|
let oc = existing;
|
|
178
177
|
const opts = { hint, standalone, journal: options.journal, logging: options.logging, token };
|
|
179
178
|
const result = Transaction_1.Transaction.run(opts, (argsx) => {
|
|
@@ -181,7 +180,7 @@ class OperationController extends Controller_1.Controller {
|
|
|
181
180
|
oc = this.edit();
|
|
182
181
|
if (Dbg_1.Log.isOn && Dbg_1.Log.opt.operation)
|
|
183
182
|
Dbg_1.Log.write('║', ' 𝑓', `${oc.operation.why()}`);
|
|
184
|
-
oc.operation.run(this.
|
|
183
|
+
oc.operation.run(this.objectHandle.proxy, argsx);
|
|
185
184
|
}
|
|
186
185
|
else {
|
|
187
186
|
oc = this.peek(argsx);
|
|
@@ -189,7 +188,7 @@ class OperationController extends Controller_1.Controller {
|
|
|
189
188
|
oc = this.edit();
|
|
190
189
|
if (Dbg_1.Log.isOn && Dbg_1.Log.opt.operation)
|
|
191
190
|
Dbg_1.Log.write('║', ' 𝑓', `${oc.operation.why()}`);
|
|
192
|
-
oc.operation.run(this.
|
|
191
|
+
oc.operation.run(this.objectHandle.proxy, argsx);
|
|
193
192
|
}
|
|
194
193
|
}
|
|
195
194
|
return oc.operation.result;
|
|
@@ -199,18 +198,18 @@ class OperationController extends Controller_1.Controller {
|
|
|
199
198
|
}
|
|
200
199
|
static markObsolete(self) {
|
|
201
200
|
const oc = self.peek(undefined);
|
|
202
|
-
const ctx = oc.
|
|
203
|
-
oc.operation.markObsoleteDueTo(oc.operation, self.memberName,
|
|
201
|
+
const ctx = oc.changeset;
|
|
202
|
+
oc.operation.markObsoleteDueTo(oc.operation, self.memberName, Changeset_1.EMPTY_SNAPSHOT.changeset, EMPTY_HANDLE, BOOT_CAUSE, ctx.timestamp, ctx.reactions);
|
|
204
203
|
}
|
|
205
204
|
}
|
|
206
205
|
exports.OperationController = OperationController;
|
|
207
206
|
class Operation extends Data_1.Subscription {
|
|
208
|
-
constructor(controller,
|
|
207
|
+
constructor(controller, changeset, former) {
|
|
209
208
|
super(undefined);
|
|
210
209
|
this.margin = Operation.current ? Operation.current.margin + 1 : 1;
|
|
211
210
|
this.transaction = Transaction_1.Transaction.current;
|
|
212
211
|
this.controller = controller;
|
|
213
|
-
this.
|
|
212
|
+
this.changeset = changeset;
|
|
214
213
|
this.subscriptions = new Map();
|
|
215
214
|
if (former instanceof Operation) {
|
|
216
215
|
this.options = former.options;
|
|
@@ -228,8 +227,8 @@ class Operation extends Data_1.Subscription {
|
|
|
228
227
|
this.successor = undefined;
|
|
229
228
|
}
|
|
230
229
|
get isOperation() { return true; }
|
|
231
|
-
get originSnapshotId() { return this.
|
|
232
|
-
hint() { return `${
|
|
230
|
+
get originSnapshotId() { return this.changeset.id; }
|
|
231
|
+
hint() { return `${Changeset_1.Dump.snapshot2(this.controller.objectHandle, this.changeset, this.controller.memberName)}`; }
|
|
233
232
|
get order() { return this.options.order; }
|
|
234
233
|
get ['#this']() {
|
|
235
234
|
return `Operation: ${this.why()}`;
|
|
@@ -241,7 +240,7 @@ class Operation extends Data_1.Subscription {
|
|
|
241
240
|
else if (this.controller.options.kind === Options_1.Kind.Transaction)
|
|
242
241
|
cause = ' << operation';
|
|
243
242
|
else
|
|
244
|
-
cause = ` << T${this.
|
|
243
|
+
cause = ` << T${this.changeset.id}[${this.changeset.hint}]`;
|
|
245
244
|
return `${this.hint()}${cause}`;
|
|
246
245
|
}
|
|
247
246
|
briefWhy() {
|
|
@@ -268,39 +267,39 @@ class Operation extends Data_1.Subscription {
|
|
|
268
267
|
run(proxy, args) {
|
|
269
268
|
if (args)
|
|
270
269
|
this.args = args;
|
|
271
|
-
this.obsoleteSince =
|
|
270
|
+
this.obsoleteSince = Changeset_1.MAX_REVISION;
|
|
272
271
|
if (!this.error)
|
|
273
272
|
OperationController.runWithin(this, Operation.run, this, proxy);
|
|
274
273
|
else
|
|
275
274
|
this.result = Promise.reject(this.error);
|
|
276
275
|
}
|
|
277
|
-
markObsoleteDueTo(subscription,
|
|
276
|
+
markObsoleteDueTo(subscription, m, changeset, h, outer, since, reactions) {
|
|
278
277
|
var _a, _b, _c;
|
|
279
278
|
if (this.subscriptions !== undefined) {
|
|
280
279
|
const skip = !subscription.isOperation &&
|
|
281
|
-
|
|
280
|
+
changeset === this.changeset;
|
|
282
281
|
if (!skip) {
|
|
283
|
-
const why = `${
|
|
284
|
-
this.
|
|
282
|
+
const why = `${Changeset_1.Dump.snapshot2(h, changeset, m, subscription)} << ${outer}`;
|
|
283
|
+
const isReaction = this.options.kind === Options_1.Kind.Reaction;
|
|
285
284
|
this.obsoleteDueTo = why;
|
|
286
285
|
this.obsoleteSince = since;
|
|
287
|
-
const isReaction = this.options.kind === Options_1.Kind.Reaction;
|
|
288
286
|
if (Dbg_1.Log.isOn && (Dbg_1.Log.opt.obsolete || ((_a = this.options.logging) === null || _a === void 0 ? void 0 : _a.obsolete)))
|
|
289
|
-
Dbg_1.Log.write(Dbg_1.Log.opt.transaction && !
|
|
287
|
+
Dbg_1.Log.write(Dbg_1.Log.opt.transaction && !Changeset_1.Changeset.current().sealed ? '║' : ' ', isReaction ? '█' : '▒', isReaction && changeset === Changeset_1.EMPTY_SNAPSHOT.changeset
|
|
290
288
|
? `${this.hint()} is a reaction and will run automatically (order ${this.options.order})`
|
|
291
|
-
: `${this.hint()} is obsolete due to ${
|
|
289
|
+
: `${this.hint()} is obsolete due to ${Changeset_1.Dump.snapshot2(h, changeset, m)} since v${since}${isReaction ? ` and will run automatically (order ${this.options.order})` : ''}`);
|
|
290
|
+
this.unsubscribeFromAllSubscriptions();
|
|
292
291
|
if (isReaction)
|
|
293
292
|
reactions.push(this);
|
|
294
293
|
else
|
|
295
|
-
(_b = this.subscribers) === null || _b === void 0 ? void 0 : _b.forEach(s => s.markObsoleteDueTo(this, this.controller.memberName, this.
|
|
294
|
+
(_b = this.subscribers) === null || _b === void 0 ? void 0 : _b.forEach(s => s.markObsoleteDueTo(this, this.controller.memberName, this.changeset, this.controller.objectHandle, why, since, reactions));
|
|
296
295
|
const tran = this.transaction;
|
|
297
|
-
if (tran.
|
|
296
|
+
if (tran.changeset === changeset) {
|
|
298
297
|
}
|
|
299
298
|
else if (!tran.isFinished && this !== subscription)
|
|
300
|
-
tran.cancel(new Error(`T${tran.id}[${tran.hint}] is canceled due to obsolete ${
|
|
299
|
+
tran.cancel(new Error(`T${tran.id}[${tran.hint}] is canceled due to obsolete ${Changeset_1.Dump.snapshot2(h, changeset, m)} changed by T${changeset.id}[${changeset.hint}]`), null);
|
|
301
300
|
}
|
|
302
301
|
else if (Dbg_1.Log.isOn && (Dbg_1.Log.opt.obsolete || ((_c = this.options.logging) === null || _c === void 0 ? void 0 : _c.obsolete)))
|
|
303
|
-
Dbg_1.Log.write(' ', 'x', `${this.hint()} is not obsolete due to its own change to ${
|
|
302
|
+
Dbg_1.Log.write(' ', 'x', `${this.hint()} is not obsolete due to its own change to ${Changeset_1.Dump.snapshot2(h, changeset, m)}`);
|
|
304
303
|
}
|
|
305
304
|
}
|
|
306
305
|
runIfNotUpToDate(now, nothrow) {
|
|
@@ -384,7 +383,7 @@ class Operation extends Data_1.Subscription {
|
|
|
384
383
|
if (this.options.monitor)
|
|
385
384
|
this.monitorEnter(this.options.monitor);
|
|
386
385
|
if (Dbg_1.Log.isOn && Dbg_1.Log.opt.operation)
|
|
387
|
-
Dbg_1.Log.write('║', '‾\\', `${this.hint()} - enter`, undefined, ` [ ${
|
|
386
|
+
Dbg_1.Log.write('║', '‾\\', `${this.hint()} - enter`, undefined, ` [ ${Changeset_1.Dump.obj(this.controller.objectHandle, this.controller.memberName)} ]`);
|
|
388
387
|
this.started = Date.now();
|
|
389
388
|
}
|
|
390
389
|
leaveOrAsync() {
|
|
@@ -453,24 +452,24 @@ class Operation extends Data_1.Subscription {
|
|
|
453
452
|
for (const x of reactions)
|
|
454
453
|
x.runIfNotUpToDate(true, true);
|
|
455
454
|
}
|
|
456
|
-
static markUsed(subscription,
|
|
455
|
+
static markUsed(subscription, os, m, h, kind, weak) {
|
|
457
456
|
if (kind !== Options_1.Kind.Transaction) {
|
|
458
457
|
const op = Operation.current;
|
|
459
458
|
if (op && op.options.kind !== Options_1.Kind.Transaction &&
|
|
460
|
-
op.transaction === Transaction_1.Transaction.current && m !== Data_1.Meta.
|
|
461
|
-
const ctx =
|
|
462
|
-
if (ctx !==
|
|
463
|
-
ctx.bumpBy(
|
|
459
|
+
op.transaction === Transaction_1.Transaction.current && m !== Data_1.Meta.Handle) {
|
|
460
|
+
const ctx = Changeset_1.Changeset.current();
|
|
461
|
+
if (ctx !== os.changeset)
|
|
462
|
+
ctx.bumpBy(os.changeset.timestamp);
|
|
464
463
|
const t = weak ? -1 : ctx.timestamp;
|
|
465
|
-
if (!op.subscribeTo(subscription,
|
|
466
|
-
op.markObsoleteDueTo(subscription, m,
|
|
464
|
+
if (!op.subscribeTo(subscription, os, m, h, t))
|
|
465
|
+
op.markObsoleteDueTo(subscription, m, os.changeset, h, BOOT_CAUSE, ctx.timestamp, ctx.reactions);
|
|
467
466
|
}
|
|
468
467
|
}
|
|
469
468
|
}
|
|
470
|
-
static markEdited(oldValue, newValue, edited,
|
|
471
|
-
edited ?
|
|
469
|
+
static markEdited(oldValue, newValue, edited, os, m, h) {
|
|
470
|
+
edited ? os.changes.add(m) : os.changes.delete(m);
|
|
472
471
|
if (Dbg_1.Log.isOn && Dbg_1.Log.opt.write)
|
|
473
|
-
edited ? Dbg_1.Log.write('║', ' ✎', `${
|
|
472
|
+
edited ? Dbg_1.Log.write('║', ' ✎', `${Changeset_1.Dump.snapshot2(h, os.changeset, m)} is changed from ${valueHint(oldValue, m)} to ${valueHint(newValue, m)}`) : Dbg_1.Log.write('║', ' ✎', `${Changeset_1.Dump.snapshot2(h, os.changeset, m)} is changed from ${valueHint(oldValue, m)} to ${valueHint(newValue, m)}`, undefined, ' (same as previous)');
|
|
474
473
|
}
|
|
475
474
|
static isConflicting(oldValue, newValue) {
|
|
476
475
|
let result = oldValue !== newValue;
|
|
@@ -478,32 +477,36 @@ class Operation extends Data_1.Subscription {
|
|
|
478
477
|
result = oldValue instanceof Operation && oldValue.cause !== BOOT_CAUSE;
|
|
479
478
|
return result;
|
|
480
479
|
}
|
|
481
|
-
static propagateAllChangesThroughSubscriptions(
|
|
480
|
+
static propagateAllChangesThroughSubscriptions(changeset) {
|
|
482
481
|
var _a;
|
|
483
|
-
const since =
|
|
484
|
-
const reactions =
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
482
|
+
const since = changeset.timestamp;
|
|
483
|
+
const reactions = changeset.reactions;
|
|
484
|
+
changeset.items.forEach((os, h) => {
|
|
485
|
+
Operation.propagateMemberChangeThroughSubscriptions(false, since, os, Data_1.Meta.Revision, h, reactions);
|
|
486
|
+
if (!os.disposed)
|
|
487
|
+
os.changes.forEach((o, m) => Operation.propagateMemberChangeThroughSubscriptions(false, since, os, m, h, reactions));
|
|
488
488
|
else
|
|
489
|
-
for (const m in
|
|
490
|
-
Operation.propagateMemberChangeThroughSubscriptions(true, since,
|
|
489
|
+
for (const m in os.former.snapshot.data)
|
|
490
|
+
Operation.propagateMemberChangeThroughSubscriptions(true, since, os, m, h, reactions);
|
|
491
491
|
});
|
|
492
492
|
reactions.sort(compareReactionsByOrder);
|
|
493
|
-
(_a =
|
|
493
|
+
(_a = changeset.options.journal) === null || _a === void 0 ? void 0 : _a.edited(Journal_1.JournalImpl.buildPatch(changeset.hint, changeset.items));
|
|
494
494
|
}
|
|
495
|
-
static revokeAllSubscriptions(
|
|
496
|
-
|
|
495
|
+
static revokeAllSubscriptions(changeset) {
|
|
496
|
+
changeset.items.forEach((os, h) => {
|
|
497
|
+
Operation.propagateMemberChangeThroughSubscriptions(true, changeset.timestamp, os, Data_1.Meta.Revision, h, undefined);
|
|
498
|
+
os.changes.forEach((o, m) => Operation.propagateMemberChangeThroughSubscriptions(true, changeset.timestamp, os, m, h, undefined));
|
|
499
|
+
});
|
|
497
500
|
}
|
|
498
|
-
static propagateMemberChangeThroughSubscriptions(unsubscribe, timestamp,
|
|
501
|
+
static propagateMemberChangeThroughSubscriptions(unsubscribe, timestamp, os, m, h, reactions) {
|
|
499
502
|
var _a;
|
|
500
|
-
const curr =
|
|
503
|
+
const curr = os.data[m];
|
|
501
504
|
if (reactions) {
|
|
502
|
-
const former =
|
|
505
|
+
const former = os.former.snapshot.data[m];
|
|
503
506
|
if (former !== undefined && former instanceof Data_1.Subscription) {
|
|
504
|
-
const why = `T${
|
|
507
|
+
const why = `T${os.changeset.id}[${os.changeset.hint}]`;
|
|
505
508
|
if (former instanceof Operation) {
|
|
506
|
-
if ((former.obsoleteSince ===
|
|
509
|
+
if ((former.obsoleteSince === Changeset_1.MAX_REVISION || former.obsoleteSince <= 0)) {
|
|
507
510
|
former.obsoleteDueTo = why;
|
|
508
511
|
former.obsoleteSince = timestamp;
|
|
509
512
|
former.unsubscribeFromAllSubscriptions();
|
|
@@ -511,16 +514,16 @@ class Operation extends Data_1.Subscription {
|
|
|
511
514
|
const formerSuccessor = former.successor;
|
|
512
515
|
if (formerSuccessor !== curr) {
|
|
513
516
|
if (formerSuccessor && !formerSuccessor.transaction.isFinished)
|
|
514
|
-
formerSuccessor.transaction.cancel(new Error(`T${formerSuccessor.transaction.id}[${formerSuccessor.transaction.hint}] is canceled by T${
|
|
517
|
+
formerSuccessor.transaction.cancel(new Error(`T${formerSuccessor.transaction.id}[${formerSuccessor.transaction.hint}] is canceled by T${os.changeset.id}[${os.changeset.hint}] and will not run anymore`), null);
|
|
515
518
|
}
|
|
516
519
|
else
|
|
517
520
|
former.successor = undefined;
|
|
518
521
|
}
|
|
519
|
-
(_a = former.subscribers) === null || _a === void 0 ? void 0 : _a.forEach(s => s.markObsoleteDueTo(former, m,
|
|
522
|
+
(_a = former.subscribers) === null || _a === void 0 ? void 0 : _a.forEach(s => s.markObsoleteDueTo(former, m, os.changeset, h, why, timestamp, reactions));
|
|
520
523
|
}
|
|
521
524
|
}
|
|
522
525
|
if (curr instanceof Operation) {
|
|
523
|
-
if (curr.
|
|
526
|
+
if (curr.changeset === os.changeset && curr.subscriptions !== undefined) {
|
|
524
527
|
if (Hooks_1.Hooks.repetitiveUsageWarningThreshold < Number.MAX_SAFE_INTEGER) {
|
|
525
528
|
curr.subscriptions.forEach((info, v) => {
|
|
526
529
|
if (info.usageCount > Hooks_1.Hooks.repetitiveUsageWarningThreshold)
|
|
@@ -558,13 +561,13 @@ class Operation extends Data_1.Subscription {
|
|
|
558
561
|
var _a;
|
|
559
562
|
value.subscribers.delete(this);
|
|
560
563
|
if (Dbg_1.Log.isOn && (Dbg_1.Log.opt.read || ((_a = this.options.logging) === null || _a === void 0 ? void 0 : _a.read)))
|
|
561
|
-
Dbg_1.Log.write(Dbg_1.Log.opt.transaction && !
|
|
564
|
+
Dbg_1.Log.write(Dbg_1.Log.opt.transaction && !Changeset_1.Changeset.current().sealed ? '║' : ' ', '-', `${this.hint()} is unsubscribed from ${info.memberHint}`);
|
|
562
565
|
});
|
|
563
566
|
this.subscriptions = undefined;
|
|
564
567
|
}
|
|
565
|
-
subscribeTo(subscription,
|
|
568
|
+
subscribeTo(subscription, os, m, h, timestamp) {
|
|
566
569
|
var _a, _b, _c;
|
|
567
|
-
const ok = Operation.canSubscribe(subscription,
|
|
570
|
+
const ok = Operation.canSubscribe(subscription, os, m, h, timestamp);
|
|
568
571
|
if (ok) {
|
|
569
572
|
let times = 0;
|
|
570
573
|
if (Hooks_1.Hooks.repetitiveUsageWarningThreshold < Number.MAX_SAFE_INTEGER) {
|
|
@@ -574,23 +577,23 @@ class Operation extends Data_1.Subscription {
|
|
|
574
577
|
if (this.subscriptions !== undefined) {
|
|
575
578
|
if (!subscription.subscribers)
|
|
576
579
|
subscription.subscribers = new Set();
|
|
577
|
-
const info = { memberHint:
|
|
580
|
+
const info = { memberHint: Changeset_1.Dump.snapshot2(h, os.changeset, m), usageCount: times };
|
|
578
581
|
subscription.subscribers.add(this);
|
|
579
582
|
this.subscriptions.set(subscription, info);
|
|
580
583
|
if (Dbg_1.Log.isOn && (Dbg_1.Log.opt.read || ((_a = this.options.logging) === null || _a === void 0 ? void 0 : _a.read)))
|
|
581
|
-
Dbg_1.Log.write('║', ' ∞ ', `${this.hint()} is subscribed to ${
|
|
584
|
+
Dbg_1.Log.write('║', ' ∞ ', `${this.hint()} is subscribed to ${Changeset_1.Dump.snapshot2(h, os.changeset, m)}${info.usageCount > 1 ? ` (${info.usageCount} times)` : ''}`);
|
|
582
585
|
}
|
|
583
586
|
else if (Dbg_1.Log.isOn && (Dbg_1.Log.opt.read || ((_b = this.options.logging) === null || _b === void 0 ? void 0 : _b.read)))
|
|
584
|
-
Dbg_1.Log.write('║', ' x ', `${this.hint()} is obsolete and is NOT subscribed to ${
|
|
587
|
+
Dbg_1.Log.write('║', ' x ', `${this.hint()} is obsolete and is NOT subscribed to ${Changeset_1.Dump.snapshot2(h, os.changeset, m)}`);
|
|
585
588
|
}
|
|
586
589
|
else {
|
|
587
590
|
if (Dbg_1.Log.isOn && (Dbg_1.Log.opt.read || ((_c = this.options.logging) === null || _c === void 0 ? void 0 : _c.read)))
|
|
588
|
-
Dbg_1.Log.write('║', ' x ', `${this.hint()} is NOT subscribed to already obsolete ${
|
|
591
|
+
Dbg_1.Log.write('║', ' x ', `${this.hint()} is NOT subscribed to already obsolete ${Changeset_1.Dump.snapshot2(h, os.changeset, m)}`);
|
|
589
592
|
}
|
|
590
593
|
return ok;
|
|
591
594
|
}
|
|
592
|
-
static canSubscribe(subscription,
|
|
593
|
-
let result = !
|
|
595
|
+
static canSubscribe(subscription, os, m, h, timestamp) {
|
|
596
|
+
let result = !os.changeset.sealed || subscription === h.head.data[m];
|
|
594
597
|
if (result && timestamp !== -1)
|
|
595
598
|
result = !(subscription instanceof Operation && timestamp >= subscription.obsoleteSince);
|
|
596
599
|
return result;
|
|
@@ -606,9 +609,9 @@ class Operation extends Data_1.Subscription {
|
|
|
606
609
|
static rememberOperationOptions(proto, m, getter, setter, enumerable, configurable, options, implicit) {
|
|
607
610
|
const initial = Data_1.Meta.acquire(proto, Data_1.Meta.Initial);
|
|
608
611
|
let op = initial[m];
|
|
609
|
-
const ctl = op ? op.controller : new OperationController(
|
|
612
|
+
const ctl = op ? op.controller : new OperationController(EMPTY_HANDLE, m);
|
|
610
613
|
const opts = op ? op.options : Hooks_1.OptionsImpl.INITIAL;
|
|
611
|
-
initial[m] = op = new Operation(ctl,
|
|
614
|
+
initial[m] = op = new Operation(ctl, Changeset_1.EMPTY_SNAPSHOT.changeset, new Hooks_1.OptionsImpl(getter, setter, opts, options, implicit));
|
|
612
615
|
if (op.options.kind === Options_1.Kind.Reaction && op.options.throttling < Number.MAX_SAFE_INTEGER) {
|
|
613
616
|
const reactions = Data_1.Meta.acquire(proto, Data_1.Meta.Reactions);
|
|
614
617
|
reactions[m] = op;
|
|
@@ -622,13 +625,13 @@ class Operation extends Data_1.Subscription {
|
|
|
622
625
|
static init() {
|
|
623
626
|
Object.freeze(BOOT_ARGS);
|
|
624
627
|
Dbg_1.Log.getMergedLoggingOptions = getMergedLoggingOptions;
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
628
|
+
Changeset_1.Dump.valueHint = valueHint;
|
|
629
|
+
Changeset_1.Changeset.markUsed = Operation.markUsed;
|
|
630
|
+
Changeset_1.Changeset.markEdited = Operation.markEdited;
|
|
631
|
+
Changeset_1.Changeset.isConflicting = Operation.isConflicting;
|
|
632
|
+
Changeset_1.Changeset.propagateAllChangesThroughSubscriptions = Operation.propagateAllChangesThroughSubscriptions;
|
|
633
|
+
Changeset_1.Changeset.revokeAllSubscriptions = Operation.revokeAllSubscriptions;
|
|
634
|
+
Changeset_1.Changeset.enqueueReactionsToRun = Operation.enqueueReactionsToRun;
|
|
632
635
|
Hooks_1.Hooks.createOperation = Operation.createOperation;
|
|
633
636
|
Hooks_1.Hooks.rememberOperationOptions = Operation.rememberOperationOptions;
|
|
634
637
|
Promise.prototype.then = reactronicHookedThen;
|
|
@@ -666,22 +669,20 @@ function valueHint(value, m) {
|
|
|
666
669
|
else if (value instanceof Map)
|
|
667
670
|
result = `Map(${value.size})`;
|
|
668
671
|
else if (value instanceof Operation)
|
|
669
|
-
result = `${
|
|
670
|
-
else if (value === Data_1.Meta.Disposed)
|
|
671
|
-
result = '<disposed>';
|
|
672
|
+
result = `${Changeset_1.Dump.snapshot2(value.controller.objectHandle, value.changeset, m)}`;
|
|
672
673
|
else if (value === Data_1.Meta.Undefined)
|
|
673
|
-
result = '
|
|
674
|
+
result = 'undefined';
|
|
674
675
|
else if (typeof (value) === 'string')
|
|
675
676
|
result = `"${value.toString().slice(0, 20)}"`;
|
|
676
677
|
else if (value !== undefined && value !== null)
|
|
677
|
-
result = value.toString().slice(0,
|
|
678
|
+
result = value.toString().slice(0, 40);
|
|
678
679
|
else
|
|
679
|
-
result = '
|
|
680
|
+
result = 'undefined';
|
|
680
681
|
return result;
|
|
681
682
|
}
|
|
682
683
|
function getMergedLoggingOptions(local) {
|
|
683
684
|
const t = Transaction_1.Transaction.current;
|
|
684
|
-
let res = Dbg_1.Log.merge(t.options.logging, t.id > 1 ? 31 + t.id % 6 : 37, t.id > 1 ? `T${t.id}` : `-${
|
|
685
|
+
let res = Dbg_1.Log.merge(t.options.logging, t.id > 1 ? 31 + t.id % 6 : 37, t.id > 1 ? `T${t.id}` : `-${Changeset_1.Changeset.idGen.toString().replace(/[0-9]/g, '-')}`, Dbg_1.Log.global);
|
|
685
686
|
res = Dbg_1.Log.merge({ margin1: t.margin }, undefined, undefined, res);
|
|
686
687
|
if (Operation.current)
|
|
687
688
|
res = Dbg_1.Log.merge({ margin2: Operation.current.margin }, undefined, undefined, res);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { F } from '../util/Utils';
|
|
2
2
|
import { Worker } from '../Worker';
|
|
3
3
|
import { SnapshotOptions } from '../Options';
|
|
4
|
-
import {
|
|
4
|
+
import { Changeset } from './Changeset';
|
|
5
5
|
export declare abstract class Transaction implements Worker {
|
|
6
6
|
static get current(): Transaction;
|
|
7
7
|
abstract readonly id: number;
|
|
@@ -9,7 +9,7 @@ export declare abstract class Transaction implements Worker {
|
|
|
9
9
|
abstract readonly options: SnapshotOptions;
|
|
10
10
|
abstract readonly timestamp: number;
|
|
11
11
|
abstract readonly error: Error | undefined;
|
|
12
|
-
abstract readonly
|
|
12
|
+
abstract readonly changeset: Changeset;
|
|
13
13
|
abstract readonly margin: number;
|
|
14
14
|
abstract run<T>(func: F<T>, ...args: any[]): T;
|
|
15
15
|
abstract inspect<T>(func: F<T>, ...args: any[]): T;
|