@fluid-experimental/tree 0.58.3000-61081 → 0.59.2000-61729
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/README.md +156 -43
- package/dist/ChangeTypes.d.ts +9 -14
- package/dist/ChangeTypes.d.ts.map +1 -1
- package/dist/ChangeTypes.js.map +1 -1
- package/dist/Checkout.d.ts.map +1 -1
- package/dist/Checkout.js +3 -2
- package/dist/Checkout.js.map +1 -1
- package/dist/LogViewer.d.ts +2 -3
- package/dist/LogViewer.d.ts.map +1 -1
- package/dist/LogViewer.js +5 -4
- package/dist/LogViewer.js.map +1 -1
- package/dist/NodeIdUtilities.d.ts +26 -11
- package/dist/NodeIdUtilities.d.ts.map +1 -1
- package/dist/NodeIdUtilities.js.map +1 -1
- package/dist/SharedTree.d.ts +61 -22
- package/dist/SharedTree.d.ts.map +1 -1
- package/dist/SharedTree.js +75 -30
- package/dist/SharedTree.js.map +1 -1
- package/dist/Transaction.d.ts +22 -4
- package/dist/Transaction.d.ts.map +1 -1
- package/dist/Transaction.js +27 -11
- package/dist/Transaction.js.map +1 -1
- package/dist/TransactionInternal.d.ts +3 -6
- package/dist/TransactionInternal.d.ts.map +1 -1
- package/dist/TransactionInternal.js +8 -4
- package/dist/TransactionInternal.js.map +1 -1
- package/dist/TreeCompressor.d.ts +0 -1
- package/dist/TreeCompressor.d.ts.map +1 -1
- package/dist/TreeCompressor.js +31 -26
- package/dist/TreeCompressor.js.map +1 -1
- package/dist/TreeView.d.ts.map +1 -1
- package/dist/TreeView.js +3 -2
- package/dist/TreeView.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/docs/Write-Format.md +19 -0
- package/lib/ChangeTypes.d.ts +9 -14
- package/lib/ChangeTypes.d.ts.map +1 -1
- package/lib/ChangeTypes.js.map +1 -1
- package/lib/Checkout.d.ts.map +1 -1
- package/lib/Checkout.js +3 -2
- package/lib/Checkout.js.map +1 -1
- package/lib/LogViewer.d.ts +2 -3
- package/lib/LogViewer.d.ts.map +1 -1
- package/lib/LogViewer.js +5 -4
- package/lib/LogViewer.js.map +1 -1
- package/lib/NodeIdUtilities.d.ts +26 -11
- package/lib/NodeIdUtilities.d.ts.map +1 -1
- package/lib/NodeIdUtilities.js.map +1 -1
- package/lib/SharedTree.d.ts +61 -22
- package/lib/SharedTree.d.ts.map +1 -1
- package/lib/SharedTree.js +75 -30
- package/lib/SharedTree.js.map +1 -1
- package/lib/Transaction.d.ts +22 -4
- package/lib/Transaction.d.ts.map +1 -1
- package/lib/Transaction.js +26 -10
- package/lib/Transaction.js.map +1 -1
- package/lib/TransactionInternal.d.ts +3 -6
- package/lib/TransactionInternal.d.ts.map +1 -1
- package/lib/TransactionInternal.js +8 -4
- package/lib/TransactionInternal.js.map +1 -1
- package/lib/TreeCompressor.d.ts +0 -1
- package/lib/TreeCompressor.d.ts.map +1 -1
- package/lib/TreeCompressor.js +31 -26
- package/lib/TreeCompressor.js.map +1 -1
- package/lib/TreeView.d.ts.map +1 -1
- package/lib/TreeView.js +3 -2
- package/lib/TreeView.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/test/LogViewer.tests.js +13 -10
- package/lib/test/LogViewer.tests.js.map +1 -1
- package/lib/test/Transaction.tests.js +36 -2
- package/lib/test/Transaction.tests.js.map +1 -1
- package/lib/test/TreeView.tests.js +29 -0
- package/lib/test/TreeView.tests.js.map +1 -1
- package/lib/test/Virtualization.tests.js +1 -2
- package/lib/test/Virtualization.tests.js.map +1 -1
- package/lib/test/fuzz/SharedTreeFuzzTests.d.ts.map +1 -1
- package/lib/test/fuzz/SharedTreeFuzzTests.js +19 -2
- package/lib/test/fuzz/SharedTreeFuzzTests.js.map +1 -1
- package/lib/test/utilities/SharedTreeVersioningTests.d.ts.map +1 -1
- package/lib/test/utilities/SharedTreeVersioningTests.js +26 -1
- package/lib/test/utilities/SharedTreeVersioningTests.js.map +1 -1
- package/package.json +18 -18
- package/src/ChangeTypes.ts +9 -14
- package/src/Checkout.ts +3 -3
- package/src/LogViewer.ts +4 -4
- package/src/NodeIdUtilities.ts +26 -11
- package/src/SharedTree.ts +81 -28
- package/src/Transaction.ts +39 -13
- package/src/TransactionInternal.ts +9 -10
- package/src/TreeCompressor.ts +31 -40
- package/src/TreeView.ts +3 -2
- package/src/index.ts +0 -1
- package/docs/Future.md +0 -155
package/lib/SharedTree.js
CHANGED
|
@@ -21,7 +21,6 @@ import { RevisionView } from './RevisionView';
|
|
|
21
21
|
import { SharedTreeEncoder_0_0_2, SharedTreeEncoder_0_1_1 } from './SharedTreeEncoder';
|
|
22
22
|
import { revert } from './HistoryEditFactory';
|
|
23
23
|
import { ChangeType } from './ChangeTypes';
|
|
24
|
-
import { TransactionInternal } from './TransactionInternal';
|
|
25
24
|
import { IdCompressor, createSessionId } from './id-compressor';
|
|
26
25
|
import { convertEditIds } from './IdConversion';
|
|
27
26
|
import { MutableStringInterner } from './StringInterner';
|
|
@@ -33,13 +32,10 @@ import { MutableStringInterner } from './StringInterner';
|
|
|
33
32
|
export class SharedTreeFactory {
|
|
34
33
|
/**
|
|
35
34
|
* Get a factory for SharedTree to register with the data store.
|
|
36
|
-
* @param writeFormat - Determines the format version the SharedTree will write summaries in.
|
|
37
|
-
*
|
|
38
|
-
* that was initialized with a newer write version connects to the session. Care must be taken when changing this value,
|
|
39
|
-
* as a staged rollout must have occurred such that all collaborating clients must have the code to read at least the version
|
|
40
|
-
* written.
|
|
35
|
+
* @param writeFormat - Determines the format version the SharedTree will write ops and summaries in. See [the write format
|
|
36
|
+
* documentation](../docs/Write-Format.md) for more information.
|
|
41
37
|
* @param summarizeHistory - Determines if the history is included in summaries and if edit chunks are uploaded when they are full.
|
|
42
|
-
* See docs/Breaking-Change-Migration for more details on this scheme.
|
|
38
|
+
* See the [breaking change migration documentation](docs/Breaking-Change-Migration) for more details on this scheme.
|
|
43
39
|
* @param expensiveValidation - Enables expensive asserts on SharedTree.
|
|
44
40
|
* @returns A factory that creates `SharedTree`s and loads them from storage.
|
|
45
41
|
*/
|
|
@@ -106,7 +102,7 @@ const snapshotFileName = 'header';
|
|
|
106
102
|
const sortedWriteVersions = [WriteFormat.v0_0_2, WriteFormat.v0_1_1];
|
|
107
103
|
const sharedTreeTelemetryProperties = { all: { isSharedTreeEvent: true } };
|
|
108
104
|
/**
|
|
109
|
-
* A distributed tree.
|
|
105
|
+
* A [distributed tree](../Readme.md).
|
|
110
106
|
* @public
|
|
111
107
|
*/
|
|
112
108
|
export class SharedTree extends SharedObject {
|
|
@@ -114,7 +110,8 @@ export class SharedTree extends SharedObject {
|
|
|
114
110
|
* Create a new SharedTreeFactory.
|
|
115
111
|
* @param runtime - The runtime the SharedTree will be associated with
|
|
116
112
|
* @param id - Unique ID for the SharedTree
|
|
117
|
-
* @param writeFormat - Determines the format version the SharedTree will write summaries in.
|
|
113
|
+
* @param writeFormat - Determines the format version the SharedTree will write ops and summaries in. See [the write format
|
|
114
|
+
* documentation](../docs/Write-Format.md) for more information.
|
|
118
115
|
* @param summarizeHistory - Determines if the history is included in summaries and if edit chunks are uploaded when they are full.
|
|
119
116
|
* @param expensiveValidation - Enable expensive asserts.
|
|
120
117
|
*/
|
|
@@ -148,7 +145,6 @@ export class SharedTree extends SharedObject {
|
|
|
148
145
|
};
|
|
149
146
|
this.emit(SharedTreeEvent.SequencedEditApplied, eventArguments);
|
|
150
147
|
};
|
|
151
|
-
this.transactionFactory = TransactionInternal.factory;
|
|
152
148
|
/**
|
|
153
149
|
* Re-computes currentIsOldest and emits an event if it has changed.
|
|
154
150
|
* TODO:#55900: Get rid of copy-pasted OldestClientObserver code
|
|
@@ -198,6 +194,7 @@ export class SharedTree extends SharedObject {
|
|
|
198
194
|
/**
|
|
199
195
|
* Get a factory for SharedTree to register with the data store.
|
|
200
196
|
* @param summarizeHistory - Determines if the history is included in summaries and if edit chunks are uploaded when they are full.
|
|
197
|
+
*
|
|
201
198
|
* On 0.1.1 documents, due to current code limitations, this parameter is only impactful for newly created documents.
|
|
202
199
|
* `SharedTree`s which load existing documents will summarize history if and only if the loaded summary included history.
|
|
203
200
|
*
|
|
@@ -205,14 +202,19 @@ export class SharedTree extends SharedObject {
|
|
|
205
202
|
* In the future we may allow modification of whether or not a particular document saves history, but only via a consensus mechanism.
|
|
206
203
|
* See the skipped test in SharedTreeFuzzTests.ts for more details on this issue.
|
|
207
204
|
* See docs/Breaking-Change-Migration for more details on the consensus scheme.
|
|
208
|
-
* @param writeFormat - Determines the format version the SharedTree will write summaries in.
|
|
205
|
+
* @param writeFormat - Determines the format version the SharedTree will write ops and summaries in.
|
|
209
206
|
* This format may be updated to a newer (supported) version at runtime if a collaborating shared-tree
|
|
210
207
|
* that was initialized with a newer write version connects to the session. Care must be taken when changing this value,
|
|
211
208
|
* as a staged rollout must of occurred such that all collaborating clients must have the code to read at least the version
|
|
212
209
|
* written.
|
|
210
|
+
* See [the write format documentation](../docs/Write-Format.md) for more information.
|
|
213
211
|
* @returns A factory that creates `SharedTree`s and loads them from storage.
|
|
214
212
|
*/
|
|
215
213
|
static getFactory(writeFormat, summarizeHistory = false) {
|
|
214
|
+
// On 0.1.1 documents, due to current code limitations, all clients MUST agree on the value of `summarizeHistory`.
|
|
215
|
+
// Note that this means staged rollout changing this value should not be attempted.
|
|
216
|
+
// It is possible to update shared-tree to correctly handle such a staged rollout, but that hasn't been implemented.
|
|
217
|
+
// See the skipped test in SharedTreeFuzzTests.ts for more details on this issue.
|
|
216
218
|
return new SharedTreeFactory(writeFormat, summarizeHistory);
|
|
217
219
|
}
|
|
218
220
|
/**
|
|
@@ -260,27 +262,60 @@ export class SharedTree extends SharedObject {
|
|
|
260
262
|
return this.logViewer.getRevisionViewInSession(Number.POSITIVE_INFINITY);
|
|
261
263
|
}
|
|
262
264
|
/**
|
|
263
|
-
*
|
|
265
|
+
* Generates a node identifier.
|
|
266
|
+
* The returned IDs may be used as the identifier of a node in the SharedTree.
|
|
267
|
+
* `NodeId`s are *always* unique and stable within the scope of the tree and session that generated them. They are *not* unique within
|
|
268
|
+
* a Fluid container, and *cannot* be compared across instances of a SharedTree. They are *not* stable across sessions/lifetimes of a
|
|
269
|
+
* SharedTree, and *cannot* be persisted (e.g. stored in payloads, uploaded in blobs, etc.). If stable persistence is needed,
|
|
270
|
+
* NodeIdConverter.convertToStableNodeId may be used to return a corresponding UUID that is globally unique and stable.
|
|
271
|
+
* @param override - if supplied, calls to `convertToStableNodeId` using the returned node ID will return the override instead of
|
|
272
|
+
* the UUID. Calls to `generateNodeId` with the same override always return the same ID. Performance note: passing an override string
|
|
273
|
+
* incurs a storage cost that is significantly higher that a node ID without one, and should be avoided if possible.
|
|
264
274
|
* @public
|
|
265
275
|
*/
|
|
266
276
|
generateNodeId(override) {
|
|
267
277
|
return this.idCompressor.generateCompressedId(override);
|
|
268
278
|
}
|
|
269
|
-
/**
|
|
279
|
+
/**
|
|
280
|
+
* Given a NodeId, returns the corresponding stable ID or throws if the supplied node ID was not generated with this tree (`NodeId`s
|
|
281
|
+
* may not be used across SharedTree instances, see `generateNodeId` for more).
|
|
282
|
+
* The returned value will be a UUID, unless the creation of `id` used an override string (see `generateNodeId` for more).
|
|
283
|
+
* The result is safe to persist and re-use across `SharedTree` instances, unlike `NodeId`.
|
|
284
|
+
* @public
|
|
285
|
+
*/
|
|
270
286
|
convertToStableNodeId(id) {
|
|
271
287
|
var _a;
|
|
272
288
|
return (_a = this.idCompressor.tryDecompress(id)) !== null && _a !== void 0 ? _a : fail('Node id is not known to this SharedTree');
|
|
273
289
|
}
|
|
274
|
-
/**
|
|
290
|
+
/**
|
|
291
|
+
* Given a NodeId, attempt to return the corresponding stable ID.
|
|
292
|
+
* The returned value will be a UUID, unless the creation of `id` used an override string (see `generateNodeId` for more).
|
|
293
|
+
* The returned stable ID is undefined if `id` was never created with this SharedTree. If a stable ID is returned, this does not imply
|
|
294
|
+
* that there is a node with `id` in the current revision of the tree, only that `id` was at some point generated by some instance of
|
|
295
|
+
* this tree.
|
|
296
|
+
* @public
|
|
297
|
+
*/
|
|
275
298
|
tryConvertToStableNodeId(id) {
|
|
276
299
|
return this.idCompressor.tryDecompress(id);
|
|
277
300
|
}
|
|
278
|
-
/**
|
|
301
|
+
/**
|
|
302
|
+
* Given a stable ID, return the corresponding NodeId or throws if the supplied stable ID was never generated with this tree, either
|
|
303
|
+
* as a UUID corresponding to a `NodeId` or as an override passed to `generateNodeId`.
|
|
304
|
+
* If a stable ID is returned, this does not imply that there is a node with `id` in the current revision of the tree, only that
|
|
305
|
+
* `id` was at some point generated by an instance of this SharedTree.
|
|
306
|
+
* @public
|
|
307
|
+
*/
|
|
279
308
|
convertToNodeId(id) {
|
|
280
309
|
var _a;
|
|
281
310
|
return ((_a = this.idCompressor.tryRecompress(id)) !== null && _a !== void 0 ? _a : fail('Stable node id is not known to this SharedTree'));
|
|
282
311
|
}
|
|
283
|
-
/**
|
|
312
|
+
/**
|
|
313
|
+
* Given a stable ID, return the corresponding NodeId or return undefined if the supplied stable ID was never generated with this tree,
|
|
314
|
+
* either as a UUID corresponding to a `NodeId` or as an override passed to `generateNodeId`.
|
|
315
|
+
* If a stable ID is returned, this does not imply that there is a node with `id` in the current revision of the tree, only that
|
|
316
|
+
* `id` was at some point generated by an instance of this SharedTree.
|
|
317
|
+
* @public
|
|
318
|
+
*/
|
|
284
319
|
tryConvertToNodeId(id) {
|
|
285
320
|
return this.idCompressor.tryRecompress(id);
|
|
286
321
|
}
|
|
@@ -524,7 +559,7 @@ export class SharedTree extends SharedObject {
|
|
|
524
559
|
// TODO:#47830: Store multiple checkpoints in summary.
|
|
525
560
|
knownRevisions = [[editLog.length, { view: currentView }]];
|
|
526
561
|
}
|
|
527
|
-
const logViewer = new CachingLogViewer(editLog, RevisionView.fromTree(initialTree, this), knownRevisions, this.expensiveValidation, editStatusCallback, sequencedEditResultCallback,
|
|
562
|
+
const logViewer = new CachingLogViewer(editLog, RevisionView.fromTree(initialTree, this), knownRevisions, this.expensiveValidation, editStatusCallback, sequencedEditResultCallback, 0);
|
|
528
563
|
this.editLog = editLog;
|
|
529
564
|
this.cachingLogViewer = logViewer;
|
|
530
565
|
return { editLog, cachingLogViewer: logViewer };
|
|
@@ -547,7 +582,7 @@ export class SharedTree extends SharedObject {
|
|
|
547
582
|
}
|
|
548
583
|
}
|
|
549
584
|
/**
|
|
550
|
-
* Compares this shared tree to another for equality. Should only be used for correctness testing.
|
|
585
|
+
* Compares this shared tree to another for equality. Should only be used for internal correctness testing.
|
|
551
586
|
*
|
|
552
587
|
* Equality means that the histories as captured by the EditLogs are equivalent.
|
|
553
588
|
*
|
|
@@ -615,7 +650,9 @@ export class SharedTree extends SharedObject {
|
|
|
615
650
|
}
|
|
616
651
|
// TODO: This cast can be removed on typescript 4.6
|
|
617
652
|
const edit = this.parseSequencedEdit(op);
|
|
618
|
-
|
|
653
|
+
if (op.version === WriteFormat.v0_1_1) {
|
|
654
|
+
this.internStringsFromEdit(edit);
|
|
655
|
+
}
|
|
619
656
|
this.processSequencedEdit(edit, typedMessage);
|
|
620
657
|
}
|
|
621
658
|
}
|
|
@@ -735,9 +772,8 @@ export class SharedTree extends SharedObject {
|
|
|
735
772
|
}
|
|
736
773
|
}
|
|
737
774
|
upgradeFrom_0_0_2_to_0_1_1() {
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
}
|
|
775
|
+
// Reset the string interner, re-populate only with information that there is consensus on
|
|
776
|
+
this.interner = new MutableStringInterner([initialTree.definition]);
|
|
741
777
|
const oldIdCompressor = this.idCompressor;
|
|
742
778
|
// Create the IdCompressor that will be used after the upgrade
|
|
743
779
|
const newIdCompressor = new IdCompressor(createSessionId(), reservedIdCount); // TODO: attribution info
|
|
@@ -760,12 +796,21 @@ export class SharedTree extends SharedObject {
|
|
|
760
796
|
// All clients have the full history, and can therefore all "generate" the same final IDs for every ID in the history
|
|
761
797
|
// via the ghost compressor.
|
|
762
798
|
unifyHistoricalIds(ghostContext);
|
|
799
|
+
// The same logic applies to string interning, so intern all the strings in the history (superset of those in the current view)
|
|
800
|
+
for (let i = 0; i < this.editLog.numberOfSequencedEdits; i++) {
|
|
801
|
+
this.internStringsFromEdit(this.editsInternal.getEditInSessionAtIndex(i));
|
|
802
|
+
}
|
|
763
803
|
}
|
|
764
804
|
else {
|
|
765
805
|
// Clients do not have the full history, but all share the same current view (sequenced). They can all finalize the same final
|
|
766
806
|
// IDs for every ID in the view via the ghost compressor.
|
|
807
|
+
// The same logic applies for the string interner.
|
|
767
808
|
for (const node of this.logViewer.getRevisionViewInSession(this.editLog.numberOfSequencedEdits)) {
|
|
768
809
|
ghostContext.generateNodeId(this.convertToStableNodeId(node.identifier));
|
|
810
|
+
this.interner.getOrCreateInternedId(node.definition);
|
|
811
|
+
for (const label of [...node.traits.keys()].sort()) {
|
|
812
|
+
this.interner.getOrCreateInternedId(label);
|
|
813
|
+
}
|
|
769
814
|
}
|
|
770
815
|
// Every node in this client's history can simply be generated in the new compressor as well, preserving the UUID
|
|
771
816
|
unifyHistoricalIds(newContext);
|
|
@@ -774,13 +819,8 @@ export class SharedTree extends SharedObject {
|
|
|
774
819
|
newIdCompressor.finalizeCreationRange(ghostIdCompressor.takeNextCreationRange());
|
|
775
820
|
this.idCompressor = newIdCompressor;
|
|
776
821
|
}
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
* External users should use one of the more specialized functions, like applyEdit which handles constructing the actual `Edit` object.
|
|
780
|
-
* This is exposed as it is useful for testing, particularly with invalid and malformed Edits.
|
|
781
|
-
* @internal
|
|
782
|
-
*/
|
|
783
|
-
applyEdit(...changes) {
|
|
822
|
+
applyEdit(headOrChanges, ...tail) {
|
|
823
|
+
const changes = Array.isArray(headOrChanges) ? headOrChanges : [headOrChanges, ...tail];
|
|
784
824
|
const id = newEditId();
|
|
785
825
|
const internalEdit = {
|
|
786
826
|
id,
|
|
@@ -791,6 +831,10 @@ export class SharedTree extends SharedObject {
|
|
|
791
831
|
return internalEdit;
|
|
792
832
|
}
|
|
793
833
|
/**
|
|
834
|
+
* Applies a set of internal changes to this tree. The result will be reflected in `SharedTree.currentView`.
|
|
835
|
+
* External users should use one of the more specialized functions, like `applyEdit` which handles constructing the actual `Edit`
|
|
836
|
+
* and uses public Change types.
|
|
837
|
+
* This is exposed for internal use only.
|
|
794
838
|
* @internal
|
|
795
839
|
*/
|
|
796
840
|
applyEditInternal(editOrChanges) {
|
|
@@ -807,7 +851,8 @@ export class SharedTree extends SharedObject {
|
|
|
807
851
|
return edit;
|
|
808
852
|
}
|
|
809
853
|
/**
|
|
810
|
-
*
|
|
854
|
+
* Converts a public Change type to an internal representation.
|
|
855
|
+
* This is exposed for internal use only.
|
|
811
856
|
* @internal
|
|
812
857
|
*/
|
|
813
858
|
internalizeChange(change) {
|