@fluid-experimental/tree 0.59.3000 → 0.59.3003
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/dist/SharedTree.d.ts +30 -89
- package/dist/SharedTree.d.ts.map +1 -1
- package/dist/SharedTree.js +58 -93
- package/dist/SharedTree.js.map +1 -1
- package/dist/SharedTreeEncoder.d.ts +1 -1
- package/dist/SharedTreeEncoder.d.ts.map +1 -1
- package/dist/SharedTreeEncoder.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/lib/SharedTree.d.ts +30 -89
- package/lib/SharedTree.d.ts.map +1 -1
- package/lib/SharedTree.js +59 -94
- package/lib/SharedTree.js.map +1 -1
- package/lib/SharedTreeEncoder.d.ts +1 -1
- package/lib/SharedTreeEncoder.d.ts.map +1 -1
- package/lib/SharedTreeEncoder.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/fuzz/SharedTreeFuzzTests.d.ts.map +1 -1
- package/lib/test/fuzz/SharedTreeFuzzTests.js +1 -3
- package/lib/test/fuzz/SharedTreeFuzzTests.js.map +1 -1
- package/lib/test/utilities/SharedTreeTests.d.ts.map +1 -1
- package/lib/test/utilities/SharedTreeTests.js +50 -27
- package/lib/test/utilities/SharedTreeTests.js.map +1 -1
- package/lib/test/utilities/SharedTreeVersioningTests.d.ts.map +1 -1
- package/lib/test/utilities/SharedTreeVersioningTests.js +19 -19
- package/lib/test/utilities/SharedTreeVersioningTests.js.map +1 -1
- package/lib/test/utilities/TestUtilities.d.ts.map +1 -1
- package/lib/test/utilities/TestUtilities.js +6 -4
- package/lib/test/utilities/TestUtilities.js.map +1 -1
- package/package.json +15 -15
- package/src/SharedTree.ts +46 -195
- package/src/SharedTreeEncoder.ts +1 -1
- package/src/index.ts +0 -4
package/lib/SharedTree.js
CHANGED
|
@@ -8,7 +8,7 @@ import { createSingleBlobSummary, serializeHandles, SharedObject, } from '@fluid
|
|
|
8
8
|
import { ChildLogger, PerformanceEvent } from '@fluidframework/telemetry-utils';
|
|
9
9
|
import { assert, assertNotUndefined, fail, copyPropertyIfDefined, noop } from './Common';
|
|
10
10
|
import { EditLog, getNumberOfHandlesFromEditLogSummary } from './EditLog';
|
|
11
|
-
import { isDetachedSequenceId
|
|
11
|
+
import { isDetachedSequenceId } from './Identifiers';
|
|
12
12
|
import { initialTree } from './InitialTree';
|
|
13
13
|
import { CachingLogViewer, } from './LogViewer';
|
|
14
14
|
import { deserialize, getSummaryStatistics } from './SummaryBackCompatibility';
|
|
@@ -24,15 +24,25 @@ import { ChangeType } from './ChangeTypes';
|
|
|
24
24
|
import { IdCompressor, createSessionId } from './id-compressor';
|
|
25
25
|
import { convertEditIds } from './IdConversion';
|
|
26
26
|
import { MutableStringInterner } from './StringInterner';
|
|
27
|
-
import { nilUuid } from './UuidUtilities';
|
|
28
27
|
/**
|
|
29
28
|
* Factory for SharedTree.
|
|
30
29
|
* Includes history in the summary.
|
|
31
30
|
* @public
|
|
32
31
|
*/
|
|
33
32
|
export class SharedTreeFactory {
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Get a factory for SharedTree to register with the data store.
|
|
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.
|
|
37
|
+
* @param summarizeHistory - Determines if the history is included in summaries and if edit chunks are uploaded when they are full.
|
|
38
|
+
* See the [breaking change migration documentation](docs/Breaking-Change-Migration) for more details on this scheme.
|
|
39
|
+
* @param expensiveValidation - Enables expensive asserts on SharedTree.
|
|
40
|
+
* @returns A factory that creates `SharedTree`s and loads them from storage.
|
|
41
|
+
*/
|
|
42
|
+
constructor(writeFormat, summarizeHistory = false, expensiveValidation = false) {
|
|
43
|
+
this.writeFormat = writeFormat;
|
|
44
|
+
this.summarizeHistory = summarizeHistory;
|
|
45
|
+
this.expensiveValidation = expensiveValidation;
|
|
36
46
|
}
|
|
37
47
|
/**
|
|
38
48
|
* {@inheritDoc @fluidframework/shared-object-base#ISharedObjectFactory."type"}
|
|
@@ -59,21 +69,15 @@ export class SharedTreeFactory {
|
|
|
59
69
|
* @param runtime - data store runtime that owns the new SharedTree
|
|
60
70
|
* @param id - optional name for the SharedTree
|
|
61
71
|
*/
|
|
62
|
-
create(runtime, id) {
|
|
72
|
+
create(runtime, id, expensiveValidation = false) {
|
|
73
|
+
this.expensiveValidation = expensiveValidation;
|
|
63
74
|
const sharedTree = this.createSharedTree(runtime, id);
|
|
64
75
|
sharedTree.initializeLocal();
|
|
65
76
|
return sharedTree;
|
|
66
77
|
}
|
|
67
78
|
createSharedTree(runtime, id) {
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
case WriteFormat.v0_0_2:
|
|
71
|
-
return new SharedTree(runtime, id, ...this.args);
|
|
72
|
-
case WriteFormat.v0_1_1:
|
|
73
|
-
return new SharedTree(runtime, id, ...this.args);
|
|
74
|
-
default:
|
|
75
|
-
fail('Unknown write format');
|
|
76
|
-
}
|
|
79
|
+
const sharedTree = new SharedTree(runtime, id, this.writeFormat, this.summarizeHistory, this.expensiveValidation);
|
|
80
|
+
return sharedTree;
|
|
77
81
|
}
|
|
78
82
|
}
|
|
79
83
|
/**
|
|
@@ -102,9 +106,20 @@ const sharedTreeTelemetryProperties = { all: { isSharedTreeEvent: true } };
|
|
|
102
106
|
* @public
|
|
103
107
|
*/
|
|
104
108
|
export class SharedTree extends SharedObject {
|
|
105
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Create a new SharedTreeFactory.
|
|
111
|
+
* @param runtime - The runtime the SharedTree will be associated with
|
|
112
|
+
* @param id - Unique ID for the SharedTree
|
|
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.
|
|
115
|
+
* @param summarizeHistory - Determines if the history is included in summaries and if edit chunks are uploaded when they are full.
|
|
116
|
+
* @param expensiveValidation - Enable expensive asserts.
|
|
117
|
+
*/
|
|
118
|
+
constructor(runtime, id, writeFormat, summarizeHistory = false, expensiveValidation = false) {
|
|
106
119
|
super(id, runtime, SharedTreeFactory.Attributes);
|
|
107
120
|
this.writeFormat = writeFormat;
|
|
121
|
+
this.expensiveValidation = expensiveValidation;
|
|
122
|
+
this.idCompressor = new IdCompressor(createSessionId(), reservedIdCount);
|
|
108
123
|
this.idNormalizer = {
|
|
109
124
|
tree: this,
|
|
110
125
|
get localSessionId() {
|
|
@@ -147,9 +162,8 @@ export class SharedTree extends SharedObject {
|
|
|
147
162
|
}
|
|
148
163
|
}
|
|
149
164
|
};
|
|
150
|
-
|
|
151
|
-
this.
|
|
152
|
-
this.uploadEditChunks = historyPolicy.uploadEditChunks;
|
|
165
|
+
this.summarizeHistory = summarizeHistory === false ? false : true;
|
|
166
|
+
this.uploadEditChunks = summarizeHistory === false ? false : summarizeHistory.uploadEditChunks;
|
|
153
167
|
// This code is somewhat duplicated from OldestClientObserver because it currently depends on the container runtime
|
|
154
168
|
// which SharedTree does not have access to.
|
|
155
169
|
// TODO:#55900: Get rid of copy-pasted OldestClientObserver code
|
|
@@ -161,12 +175,11 @@ export class SharedTree extends SharedObject {
|
|
|
161
175
|
runtime.on('disconnected', this.updateOldest);
|
|
162
176
|
this.logger = ChildLogger.create(runtime.logger, 'SharedTree', sharedTreeTelemetryProperties);
|
|
163
177
|
this.sequencedEditAppliedLogger = ChildLogger.create(this.logger, 'SequencedEditApplied', sharedTreeTelemetryProperties);
|
|
164
|
-
const attributionId = options.attributionId;
|
|
165
|
-
this.idCompressor = new IdCompressor(createSessionId(), reservedIdCount, attributionId);
|
|
166
178
|
const { editLog, cachingLogViewer } = this.initializeNewEditLogFromSummary({
|
|
167
179
|
editChunks: [],
|
|
168
180
|
editIds: [],
|
|
169
|
-
}, undefined, this.idCompressor,
|
|
181
|
+
}, undefined, this.idCompressor, // TODO: Attribution info
|
|
182
|
+
this.processEditResult, this.processSequencedEditResult, WriteFormat.v0_1_1);
|
|
170
183
|
this.editLog = editLog;
|
|
171
184
|
this.cachingLogViewer = cachingLogViewer;
|
|
172
185
|
this.encoder_0_0_2 = new SharedTreeEncoder_0_0_2(this.summarizeHistory);
|
|
@@ -178,39 +191,31 @@ export class SharedTree extends SharedObject {
|
|
|
178
191
|
static create(runtime, id) {
|
|
179
192
|
return runtime.createChannel(id, SharedTreeFactory.Type);
|
|
180
193
|
}
|
|
181
|
-
|
|
182
|
-
|
|
194
|
+
/**
|
|
195
|
+
* Get a factory for SharedTree to register with the data store.
|
|
196
|
+
* @param summarizeHistory - Determines if the history is included in summaries and if edit chunks are uploaded when they are full.
|
|
197
|
+
*
|
|
198
|
+
* On 0.1.1 documents, due to current code limitations, this parameter is only impactful for newly created documents.
|
|
199
|
+
* `SharedTree`s which load existing documents will summarize history if and only if the loaded summary included history.
|
|
200
|
+
*
|
|
201
|
+
* The technical limitations here relate to clients with mixed versions collaborating.
|
|
202
|
+
* In the future we may allow modification of whether or not a particular document saves history, but only via a consensus mechanism.
|
|
203
|
+
* See the skipped test in SharedTreeFuzzTests.ts for more details on this issue.
|
|
204
|
+
* See docs/Breaking-Change-Migration for more details on the consensus scheme.
|
|
205
|
+
* @param writeFormat - Determines the format version the SharedTree will write ops and summaries in.
|
|
206
|
+
* This format may be updated to a newer (supported) version at runtime if a collaborating shared-tree
|
|
207
|
+
* that was initialized with a newer write version connects to the session. Care must be taken when changing this value,
|
|
208
|
+
* as a staged rollout must of occurred such that all collaborating clients must have the code to read at least the version
|
|
209
|
+
* written.
|
|
210
|
+
* See [the write format documentation](../docs/Write-Format.md) for more information.
|
|
211
|
+
* @returns A factory that creates `SharedTree`s and loads them from storage.
|
|
212
|
+
*/
|
|
213
|
+
static getFactory(writeFormat, summarizeHistory = false) {
|
|
183
214
|
// On 0.1.1 documents, due to current code limitations, all clients MUST agree on the value of `summarizeHistory`.
|
|
184
215
|
// Note that this means staged rollout changing this value should not be attempted.
|
|
185
216
|
// It is possible to update shared-tree to correctly handle such a staged rollout, but that hasn't been implemented.
|
|
186
217
|
// See the skipped test in SharedTreeFuzzTests.ts for more details on this issue.
|
|
187
|
-
|
|
188
|
-
case WriteFormat.v0_0_2:
|
|
189
|
-
return new SharedTreeFactory(...args);
|
|
190
|
-
case WriteFormat.v0_1_1:
|
|
191
|
-
return new SharedTreeFactory(...args);
|
|
192
|
-
default:
|
|
193
|
-
fail('Unknown write format');
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* The UUID used for attribution of nodes created by this SharedTree. All shared trees with a write format of 0.1.1 or
|
|
198
|
-
* greater have a unique attribution ID which may be configured in the constructor. All other shared trees (i.e. those
|
|
199
|
-
* with a write format of 0.0.2) use the nil UUID as their attribution ID.
|
|
200
|
-
* @public
|
|
201
|
-
*/
|
|
202
|
-
get attributionId() {
|
|
203
|
-
switch (this.writeFormat) {
|
|
204
|
-
case WriteFormat.v0_0_2:
|
|
205
|
-
return nilUuid;
|
|
206
|
-
default: {
|
|
207
|
-
const { attributionId } = this.idCompressor;
|
|
208
|
-
if (attributionId === ghostSessionId) {
|
|
209
|
-
return nilUuid;
|
|
210
|
-
}
|
|
211
|
-
return attributionId;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
218
|
+
return new SharedTreeFactory(writeFormat, summarizeHistory);
|
|
214
219
|
}
|
|
215
220
|
/**
|
|
216
221
|
* Viewer for trees defined by editLog. This allows access to views of the tree at different revisions (various points in time).
|
|
@@ -218,27 +223,6 @@ export class SharedTree extends SharedObject {
|
|
|
218
223
|
get logViewer() {
|
|
219
224
|
return this.cachingLogViewer;
|
|
220
225
|
}
|
|
221
|
-
getHistoryPolicy(options) {
|
|
222
|
-
var _a;
|
|
223
|
-
const noCompatOptions = options;
|
|
224
|
-
if (typeof noCompatOptions.summarizeHistory === 'object') {
|
|
225
|
-
return {
|
|
226
|
-
summarizeHistory: true,
|
|
227
|
-
uploadEditChunks: noCompatOptions.summarizeHistory.uploadEditChunks,
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
else {
|
|
231
|
-
return {
|
|
232
|
-
summarizeHistory: (_a = noCompatOptions.summarizeHistory) !== null && _a !== void 0 ? _a : false,
|
|
233
|
-
uploadEditChunks: false,
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* The write format version currently used by this `SharedTree`. This is always initialized to the write format
|
|
239
|
-
* passed to the tree's constructor, but it may automatically upgrade over time (e.g. when connected to another
|
|
240
|
-
* SharedTree with a higher write format, or when loading a summary with a higher write format).
|
|
241
|
-
*/
|
|
242
226
|
getWriteFormat() {
|
|
243
227
|
return this.writeFormat;
|
|
244
228
|
}
|
|
@@ -335,25 +319,6 @@ export class SharedTree extends SharedObject {
|
|
|
335
319
|
tryConvertToNodeId(id) {
|
|
336
320
|
return this.idCompressor.tryRecompress(id);
|
|
337
321
|
}
|
|
338
|
-
/**
|
|
339
|
-
* Returns the attribution ID associated with the SharedTree that generated the given node ID. This is generally only useful for clients
|
|
340
|
-
* with a write format of 0.1.1 or greater since older clients cannot be given an attribution ID and will always use the default
|
|
341
|
-
* `attributionId` of the tree.
|
|
342
|
-
* @public
|
|
343
|
-
*/
|
|
344
|
-
attributeNodeId(id) {
|
|
345
|
-
switch (this.writeFormat) {
|
|
346
|
-
case WriteFormat.v0_0_2:
|
|
347
|
-
return nilUuid;
|
|
348
|
-
default: {
|
|
349
|
-
const attributionId = this.idCompressor.attributeId(id);
|
|
350
|
-
if (attributionId === ghostSessionId) {
|
|
351
|
-
return nilUuid;
|
|
352
|
-
}
|
|
353
|
-
return attributionId;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
322
|
/**
|
|
358
323
|
* @returns the edit history of the tree.
|
|
359
324
|
* @public
|
|
@@ -500,7 +465,7 @@ export class SharedTree extends SharedObject {
|
|
|
500
465
|
let convertedSummary;
|
|
501
466
|
switch (loadedSummaryVersion) {
|
|
502
467
|
case WriteFormat.v0_0_2:
|
|
503
|
-
convertedSummary = this.encoder_0_0_2.decodeSummary(summary
|
|
468
|
+
convertedSummary = this.encoder_0_0_2.decodeSummary(summary);
|
|
504
469
|
break;
|
|
505
470
|
case WriteFormat.v0_1_1: {
|
|
506
471
|
const typedSummary = summary;
|
|
@@ -511,7 +476,7 @@ export class SharedTree extends SharedObject {
|
|
|
511
476
|
this.uploadEditChunks = loadedSummaryIncludesHistory;
|
|
512
477
|
this.encoder_0_1_1 = new SharedTreeEncoder_0_1_1(this.summarizeHistory);
|
|
513
478
|
}
|
|
514
|
-
convertedSummary = this.encoder_0_1_1.decodeSummary(summary
|
|
479
|
+
convertedSummary = this.encoder_0_1_1.decodeSummary(summary); // TODO:#461: pass attribution info
|
|
515
480
|
break;
|
|
516
481
|
}
|
|
517
482
|
default:
|
|
@@ -799,7 +764,7 @@ export class SharedTree extends SharedObject {
|
|
|
799
764
|
this.interner = new MutableStringInterner([initialTree.definition]);
|
|
800
765
|
const oldIdCompressor = this.idCompressor;
|
|
801
766
|
// Create the IdCompressor that will be used after the upgrade
|
|
802
|
-
const newIdCompressor = new IdCompressor(createSessionId(), reservedIdCount
|
|
767
|
+
const newIdCompressor = new IdCompressor(createSessionId(), reservedIdCount); // TODO: attribution info
|
|
803
768
|
const newContext = getNodeIdContext(newIdCompressor);
|
|
804
769
|
// Generate all local IDs in the new compressor that were in the old compressor and preserve their UUIDs.
|
|
805
770
|
// This will allow the client to continue to use local IDs that were allocated pre-upgrade
|
|
@@ -813,7 +778,7 @@ export class SharedTree extends SharedObject {
|
|
|
813
778
|
}
|
|
814
779
|
};
|
|
815
780
|
// Construct a temporary "ghost" compressor which is used to generate final IDs that will be consistent across all upgrading clients
|
|
816
|
-
const ghostIdCompressor = new IdCompressor(ghostSessionId, reservedIdCount);
|
|
781
|
+
const ghostIdCompressor = new IdCompressor(ghostSessionId, reservedIdCount); // TODO: attribution info
|
|
817
782
|
const ghostContext = getNodeIdContext(ghostIdCompressor);
|
|
818
783
|
if (this.summarizeHistory) {
|
|
819
784
|
// All clients have the full history, and can therefore all "generate" the same final IDs for every ID in the history
|