@fluidframework/datastore 2.0.0-internal.3.0.5 → 2.0.0-internal.3.1.1

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.
Files changed (65) hide show
  1. package/.eslintrc.js +5 -7
  2. package/.mocharc.js +2 -2
  3. package/README.md +3 -0
  4. package/api-extractor.json +2 -2
  5. package/dist/channelContext.d.ts.map +1 -1
  6. package/dist/channelContext.js.map +1 -1
  7. package/dist/channelDeltaConnection.d.ts.map +1 -1
  8. package/dist/channelDeltaConnection.js.map +1 -1
  9. package/dist/channelStorageService.d.ts.map +1 -1
  10. package/dist/channelStorageService.js +1 -3
  11. package/dist/channelStorageService.js.map +1 -1
  12. package/dist/dataStoreRuntime.d.ts +11 -24
  13. package/dist/dataStoreRuntime.d.ts.map +1 -1
  14. package/dist/dataStoreRuntime.js +68 -86
  15. package/dist/dataStoreRuntime.js.map +1 -1
  16. package/dist/fluidHandle.d.ts.map +1 -1
  17. package/dist/fluidHandle.js.map +1 -1
  18. package/dist/localChannelContext.d.ts.map +1 -1
  19. package/dist/localChannelContext.js +9 -5
  20. package/dist/localChannelContext.js.map +1 -1
  21. package/dist/localChannelStorageService.d.ts.map +1 -1
  22. package/dist/localChannelStorageService.js.map +1 -1
  23. package/dist/packageVersion.d.ts +1 -1
  24. package/dist/packageVersion.js +1 -1
  25. package/dist/packageVersion.js.map +1 -1
  26. package/dist/remoteChannelContext.d.ts.map +1 -1
  27. package/dist/remoteChannelContext.js +2 -2
  28. package/dist/remoteChannelContext.js.map +1 -1
  29. package/lib/channelContext.d.ts.map +1 -1
  30. package/lib/channelContext.js.map +1 -1
  31. package/lib/channelDeltaConnection.d.ts.map +1 -1
  32. package/lib/channelDeltaConnection.js.map +1 -1
  33. package/lib/channelStorageService.d.ts.map +1 -1
  34. package/lib/channelStorageService.js +1 -3
  35. package/lib/channelStorageService.js.map +1 -1
  36. package/lib/dataStoreRuntime.d.ts +11 -24
  37. package/lib/dataStoreRuntime.d.ts.map +1 -1
  38. package/lib/dataStoreRuntime.js +71 -89
  39. package/lib/dataStoreRuntime.js.map +1 -1
  40. package/lib/fluidHandle.d.ts.map +1 -1
  41. package/lib/fluidHandle.js.map +1 -1
  42. package/lib/localChannelContext.d.ts.map +1 -1
  43. package/lib/localChannelContext.js +9 -5
  44. package/lib/localChannelContext.js.map +1 -1
  45. package/lib/localChannelStorageService.d.ts.map +1 -1
  46. package/lib/localChannelStorageService.js.map +1 -1
  47. package/lib/packageVersion.d.ts +1 -1
  48. package/lib/packageVersion.js +1 -1
  49. package/lib/packageVersion.js.map +1 -1
  50. package/lib/remoteChannelContext.d.ts.map +1 -1
  51. package/lib/remoteChannelContext.js +2 -2
  52. package/lib/remoteChannelContext.js.map +1 -1
  53. package/package.json +111 -110
  54. package/prettier.config.cjs +1 -1
  55. package/src/channelContext.ts +66 -65
  56. package/src/channelDeltaConnection.ts +50 -44
  57. package/src/channelStorageService.ts +58 -54
  58. package/src/dataStoreRuntime.ts +1122 -1086
  59. package/src/fluidHandle.ts +87 -91
  60. package/src/localChannelContext.ts +302 -255
  61. package/src/localChannelStorageService.ts +47 -45
  62. package/src/packageVersion.ts +1 -1
  63. package/src/remoteChannelContext.ts +300 -291
  64. package/tsconfig.esnext.json +6 -6
  65. package/tsconfig.json +9 -13
@@ -9,26 +9,26 @@ import { ITelemetryLogger } from "@fluidframework/common-definitions";
9
9
  import { IDocumentStorageService } from "@fluidframework/driver-definitions";
10
10
  import { ISequencedDocumentMessage, ISnapshotTree } from "@fluidframework/protocol-definitions";
11
11
  import {
12
- IChannel,
13
- IFluidDataStoreRuntime,
14
- IChannelFactory,
15
- IChannelAttributes,
12
+ IChannel,
13
+ IFluidDataStoreRuntime,
14
+ IChannelFactory,
15
+ IChannelAttributes,
16
16
  } from "@fluidframework/datastore-definitions";
17
17
  import {
18
- IFluidDataStoreContext,
19
- IGarbageCollectionData,
20
- ISummarizeResult,
21
- ITelemetryContext,
18
+ IFluidDataStoreContext,
19
+ IGarbageCollectionData,
20
+ ISummarizeResult,
21
+ ITelemetryContext,
22
22
  } from "@fluidframework/runtime-definitions";
23
23
  import { readAndParse } from "@fluidframework/driver-utils";
24
24
  import { DataProcessingError } from "@fluidframework/container-utils";
25
25
  import { assert, Lazy } from "@fluidframework/common-utils";
26
26
  import { IFluidHandle } from "@fluidframework/core-interfaces";
27
27
  import {
28
- createServiceEndpoints,
29
- IChannelContext,
30
- summarizeChannel,
31
- summarizeChannelAsync,
28
+ createServiceEndpoints,
29
+ IChannelContext,
30
+ summarizeChannel,
31
+ summarizeChannelAsync,
32
32
  } from "./channelContext";
33
33
  import { ChannelDeltaConnection } from "./channelDeltaConnection";
34
34
  import { ISharedObjectRegistry } from "./dataStoreRuntime";
@@ -38,276 +38,323 @@ import { ChannelStorageService } from "./channelStorageService";
38
38
  * Channel context for a locally created channel
39
39
  */
40
40
  export abstract class LocalChannelContextBase implements IChannelContext {
41
- public channel: IChannel | undefined;
42
- private globallyVisible = false;
43
- protected readonly pending: ISequencedDocumentMessage[] = [];
44
- protected factory: IChannelFactory | undefined;
45
- constructor(
46
- protected readonly id: string,
47
- protected readonly registry: ISharedObjectRegistry,
48
- protected readonly runtime: IFluidDataStoreRuntime,
49
- private readonly servicesGetter: () => Lazy<{
50
- readonly deltaConnection: ChannelDeltaConnection;
51
- readonly objectStorage: ChannelStorageService;
52
- }>,
53
- ) {
54
- assert(!this.id.includes("/"), 0x30f /* Channel context ID cannot contain slashes */);
55
- }
41
+ public channel: IChannel | undefined;
42
+ private globallyVisible = false;
43
+ protected readonly pending: ISequencedDocumentMessage[] = [];
44
+ protected factory: IChannelFactory | undefined;
45
+ constructor(
46
+ protected readonly id: string,
47
+ protected readonly registry: ISharedObjectRegistry,
48
+ protected readonly runtime: IFluidDataStoreRuntime,
49
+ private readonly servicesGetter: () => Lazy<{
50
+ readonly deltaConnection: ChannelDeltaConnection;
51
+ readonly objectStorage: ChannelStorageService;
52
+ }>,
53
+ ) {
54
+ assert(!this.id.includes("/"), 0x30f /* Channel context ID cannot contain slashes */);
55
+ }
56
56
 
57
- public async getChannel(): Promise<IChannel> {
58
- assert(this.channel !== undefined, 0x207 /* "Channel should be defined" */);
59
- return this.channel;
60
- }
57
+ public async getChannel(): Promise<IChannel> {
58
+ assert(this.channel !== undefined, 0x207 /* "Channel should be defined" */);
59
+ return this.channel;
60
+ }
61
61
 
62
- public get isLoaded(): boolean {
63
- return this.channel !== undefined;
64
- }
62
+ public get isLoaded(): boolean {
63
+ return this.channel !== undefined;
64
+ }
65
65
 
66
- public setConnectionState(connected: boolean, clientId?: string) {
67
- // Connection events are ignored if the data store is not yet globallyVisible or loaded
68
- if (this.globallyVisible && this.isLoaded) {
69
- this.servicesGetter().value.deltaConnection.setConnectionState(connected);
70
- }
71
- }
66
+ public setConnectionState(connected: boolean, clientId?: string) {
67
+ // Connection events are ignored if the data store is not yet globallyVisible or loaded
68
+ if (this.globallyVisible && this.isLoaded) {
69
+ this.servicesGetter().value.deltaConnection.setConnectionState(connected);
70
+ }
71
+ }
72
72
 
73
- public processOp(message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown): void {
74
- assert(this.globallyVisible, 0x2d3 /* "Local channel must be globally visible when processing op" */);
73
+ public processOp(
74
+ message: ISequencedDocumentMessage,
75
+ local: boolean,
76
+ localOpMetadata: unknown,
77
+ ): void {
78
+ assert(
79
+ this.globallyVisible,
80
+ 0x2d3 /* "Local channel must be globally visible when processing op" */,
81
+ );
75
82
 
76
- // A local channel may not be loaded in case where we rehydrate the container from a snapshot because of
77
- // delay loading. So after the container is attached and some other client joins which start generating
78
- // ops for this channel. So not loaded local channel can still receive ops and we store them to process later.
79
- if (this.isLoaded) {
80
- this.servicesGetter().value.deltaConnection.process(message, local, localOpMetadata);
81
- } else {
82
- assert(local === false,
83
- 0x189 /* "Should always be remote because a local dds shouldn't generate ops before loading" */);
84
- this.pending.push(message);
85
- }
86
- }
83
+ // A local channel may not be loaded in case where we rehydrate the container from a snapshot because of
84
+ // delay loading. So after the container is attached and some other client joins which start generating
85
+ // ops for this channel. So not loaded local channel can still receive ops and we store them to process later.
86
+ if (this.isLoaded) {
87
+ this.servicesGetter().value.deltaConnection.process(message, local, localOpMetadata);
88
+ } else {
89
+ assert(
90
+ local === false,
91
+ 0x189 /* "Should always be remote because a local dds shouldn't generate ops before loading" */,
92
+ );
93
+ this.pending.push(message);
94
+ }
95
+ }
87
96
 
88
- public reSubmit(content: any, localOpMetadata: unknown) {
89
- assert(this.isLoaded, 0x18a /* "Channel should be loaded to resubmit ops" */);
90
- assert(this.globallyVisible, 0x2d4 /* "Local channel must be globally visible when resubmitting op" */);
91
- this.servicesGetter().value.deltaConnection.reSubmit(content, localOpMetadata);
92
- }
93
- public rollback(content: any, localOpMetadata: unknown) {
94
- assert(this.isLoaded, 0x2ee /* "Channel should be loaded to rollback ops" */);
95
- assert(this.globallyVisible, 0x2ef /* "Local channel must be globally visible when rolling back op" */);
96
- this.servicesGetter().value.deltaConnection.rollback(content, localOpMetadata);
97
- }
97
+ public reSubmit(content: any, localOpMetadata: unknown) {
98
+ assert(this.isLoaded, 0x18a /* "Channel should be loaded to resubmit ops" */);
99
+ assert(
100
+ this.globallyVisible,
101
+ 0x2d4 /* "Local channel must be globally visible when resubmitting op" */,
102
+ );
103
+ this.servicesGetter().value.deltaConnection.reSubmit(content, localOpMetadata);
104
+ }
105
+ public rollback(content: any, localOpMetadata: unknown) {
106
+ assert(this.isLoaded, 0x2ee /* "Channel should be loaded to rollback ops" */);
107
+ assert(
108
+ this.globallyVisible,
109
+ 0x2ef /* "Local channel must be globally visible when rolling back op" */,
110
+ );
111
+ this.servicesGetter().value.deltaConnection.rollback(content, localOpMetadata);
112
+ }
98
113
 
99
- public applyStashedOp() {
100
- throw new Error("no stashed ops on local channel");
101
- }
114
+ public applyStashedOp() {
115
+ throw new Error("no stashed ops on local channel");
116
+ }
102
117
 
103
- /**
104
- * Returns a summary at the current sequence number.
105
- * @param fullTree - true to bypass optimizations and force a full summary tree
106
- * @param trackState - This tells whether we should track state from this summary.
107
- * @param telemetryContext - summary data passed through the layers for telemetry purposes
108
- */
109
- public async summarize(
110
- fullTree: boolean = false,
111
- trackState: boolean = false,
112
- telemetryContext?: ITelemetryContext,
113
- ): Promise<ISummarizeResult> {
114
- assert(this.isLoaded && this.channel !== undefined, 0x18c /* "Channel should be loaded to summarize" */);
115
- return summarizeChannelAsync(this.channel, fullTree, trackState, telemetryContext);
116
- }
118
+ /**
119
+ * Returns a summary at the current sequence number.
120
+ * @param fullTree - true to bypass optimizations and force a full summary tree
121
+ * @param trackState - This tells whether we should track state from this summary.
122
+ * @param telemetryContext - summary data passed through the layers for telemetry purposes
123
+ */
124
+ public async summarize(
125
+ fullTree: boolean = false,
126
+ trackState: boolean = false,
127
+ telemetryContext?: ITelemetryContext,
128
+ ): Promise<ISummarizeResult> {
129
+ assert(
130
+ this.isLoaded && this.channel !== undefined,
131
+ 0x18c /* "Channel should be loaded to summarize" */,
132
+ );
133
+ return summarizeChannelAsync(this.channel, fullTree, trackState, telemetryContext);
134
+ }
117
135
 
118
- public getAttachSummary(telemetryContext?: ITelemetryContext): ISummarizeResult {
119
- assert(this.isLoaded && this.channel !== undefined, 0x18d /* "Channel should be loaded to take snapshot" */);
120
- return summarizeChannel(this.channel, true /* fullTree */, false /* trackState */, telemetryContext);
121
- }
136
+ public getAttachSummary(telemetryContext?: ITelemetryContext): ISummarizeResult {
137
+ assert(
138
+ this.isLoaded && this.channel !== undefined,
139
+ 0x18d /* "Channel should be loaded to take snapshot" */,
140
+ );
141
+ return summarizeChannel(
142
+ this.channel,
143
+ true /* fullTree */,
144
+ false /* trackState */,
145
+ telemetryContext,
146
+ );
147
+ }
122
148
 
123
- public makeVisible(): void {
124
- if (this.globallyVisible) {
125
- throw new Error("Channel is already globally visible");
126
- }
149
+ public makeVisible(): void {
150
+ if (this.globallyVisible) {
151
+ throw new Error("Channel is already globally visible");
152
+ }
127
153
 
128
- if (this.isLoaded) {
129
- assert(!!this.channel, 0x192 /* "Channel should be there if loaded!!" */);
130
- this.channel.connect(this.servicesGetter().value);
131
- }
132
- this.globallyVisible = true;
133
- }
154
+ if (this.isLoaded) {
155
+ assert(!!this.channel, 0x192 /* "Channel should be there if loaded!!" */);
156
+ this.channel.connect(this.servicesGetter().value);
157
+ }
158
+ this.globallyVisible = true;
159
+ }
134
160
 
135
- /**
136
- * Returns the data used for garbage collection. This includes a list of GC nodes that represent this context.
137
- * Each node has a set of outbound routes to other GC nodes in the document. This should be called only after
138
- * the context has loaded.
139
- * @param fullGC - true to bypass optimizations and force full generation of GC data.
140
- */
141
- public async getGCData(fullGC: boolean = false): Promise<IGarbageCollectionData> {
142
- assert(this.isLoaded && this.channel !== undefined, 0x193 /* "Channel should be loaded to run GC" */);
143
- return this.channel.getGCData(fullGC);
144
- }
161
+ /**
162
+ * Returns the data used for garbage collection. This includes a list of GC nodes that represent this context.
163
+ * Each node has a set of outbound routes to other GC nodes in the document. This should be called only after
164
+ * the context has loaded.
165
+ * @param fullGC - true to bypass optimizations and force full generation of GC data.
166
+ */
167
+ public async getGCData(fullGC: boolean = false): Promise<IGarbageCollectionData> {
168
+ assert(
169
+ this.isLoaded && this.channel !== undefined,
170
+ 0x193 /* "Channel should be loaded to run GC" */,
171
+ );
172
+ return this.channel.getGCData(fullGC);
173
+ }
145
174
 
146
- public updateUsedRoutes(usedRoutes: string[]) {
147
- /**
148
- * Currently, DDSes are always considered referenced and are not garbage collected.
149
- * Once we have GC at DDS level, this channel context's used routes will be updated as per the passed
150
- * value. See - https://github.com/microsoft/FluidFramework/issues/4611
151
- */
152
- }
175
+ public updateUsedRoutes(usedRoutes: string[]) {
176
+ /**
177
+ * Currently, DDSes are always considered referenced and are not garbage collected.
178
+ * Once we have GC at DDS level, this channel context's used routes will be updated as per the passed
179
+ * value. See - https://github.com/microsoft/FluidFramework/issues/4611
180
+ */
181
+ }
153
182
  }
154
183
 
155
184
  export class RehydratedLocalChannelContext extends LocalChannelContextBase {
156
- private readonly services: Lazy<{
157
- readonly deltaConnection: ChannelDeltaConnection;
158
- readonly objectStorage: ChannelStorageService;
159
- }>;
185
+ private readonly services: Lazy<{
186
+ readonly deltaConnection: ChannelDeltaConnection;
187
+ readonly objectStorage: ChannelStorageService;
188
+ }>;
160
189
 
161
- private readonly dirtyFn: () => void;
190
+ private readonly dirtyFn: () => void;
162
191
 
163
- constructor(
164
- id: string,
165
- registry: ISharedObjectRegistry,
166
- runtime: IFluidDataStoreRuntime,
167
- dataStoreContext: IFluidDataStoreContext,
168
- storageService: IDocumentStorageService,
169
- logger: ITelemetryLogger,
170
- submitFn: (content: any, localOpMetadata: unknown) => void,
171
- dirtyFn: (address: string) => void,
172
- addedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void,
173
- private readonly snapshotTree: ISnapshotTree,
174
- ) {
175
- super(id, registry, runtime, () => this.services);
176
- const blobMap: Map<string, ArrayBufferLike> = new Map<string, ArrayBufferLike>();
177
- const clonedSnapshotTree = cloneDeep(this.snapshotTree);
178
- // 0.47 back-compat Need to sanitize if snapshotTree.blobs still contains blob contents too.
179
- // This is for older snapshot which is generated by loader <=0.47 version which still contains
180
- // the contents within blobs. After a couple of revisions we can remove it.
181
- if (this.isSnapshotInOldFormatAndCollectBlobs(clonedSnapshotTree, blobMap)) {
182
- this.sanitizeSnapshot(clonedSnapshotTree);
183
- }
192
+ constructor(
193
+ id: string,
194
+ registry: ISharedObjectRegistry,
195
+ runtime: IFluidDataStoreRuntime,
196
+ dataStoreContext: IFluidDataStoreContext,
197
+ storageService: IDocumentStorageService,
198
+ logger: ITelemetryLogger,
199
+ submitFn: (content: any, localOpMetadata: unknown) => void,
200
+ dirtyFn: (address: string) => void,
201
+ addedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void,
202
+ private readonly snapshotTree: ISnapshotTree,
203
+ ) {
204
+ super(id, registry, runtime, () => this.services);
205
+ const blobMap: Map<string, ArrayBufferLike> = new Map<string, ArrayBufferLike>();
206
+ const clonedSnapshotTree = cloneDeep(this.snapshotTree);
207
+ // 0.47 back-compat Need to sanitize if snapshotTree.blobs still contains blob contents too.
208
+ // This is for older snapshot which is generated by loader <=0.47 version which still contains
209
+ // the contents within blobs. After a couple of revisions we can remove it.
210
+ if (this.isSnapshotInOldFormatAndCollectBlobs(clonedSnapshotTree, blobMap)) {
211
+ this.sanitizeSnapshot(clonedSnapshotTree);
212
+ }
184
213
 
185
- this.services = new Lazy(() => {
186
- return createServiceEndpoints(
187
- this.id,
188
- dataStoreContext.connected,
189
- submitFn,
190
- this.dirtyFn,
191
- addedGCOutboundReferenceFn,
192
- storageService,
193
- logger,
194
- clonedSnapshotTree,
195
- blobMap,
196
- );
197
- });
198
- this.dirtyFn = () => { dirtyFn(id); };
199
- }
214
+ this.services = new Lazy(() => {
215
+ return createServiceEndpoints(
216
+ this.id,
217
+ dataStoreContext.connected,
218
+ submitFn,
219
+ this.dirtyFn,
220
+ addedGCOutboundReferenceFn,
221
+ storageService,
222
+ logger,
223
+ clonedSnapshotTree,
224
+ blobMap,
225
+ );
226
+ });
227
+ this.dirtyFn = () => {
228
+ dirtyFn(id);
229
+ };
230
+ }
200
231
 
201
- public async getChannel(): Promise<IChannel> {
202
- if (this.channel === undefined) {
203
- this.channel = await this.loadChannel()
204
- .catch((err) => {
205
- throw DataProcessingError.wrapIfUnrecognized(
206
- err, "rehydratedLocalChannelContextFailedToLoadChannel", undefined);
207
- });
208
- }
209
- return this.channel;
210
- }
232
+ public async getChannel(): Promise<IChannel> {
233
+ if (this.channel === undefined) {
234
+ this.channel = await this.loadChannel().catch((err) => {
235
+ throw DataProcessingError.wrapIfUnrecognized(
236
+ err,
237
+ "rehydratedLocalChannelContextFailedToLoadChannel",
238
+ undefined,
239
+ );
240
+ });
241
+ }
242
+ return this.channel;
243
+ }
211
244
 
212
- private async loadChannel(): Promise<IChannel> {
213
- assert(!this.isLoaded, 0x18e /* "Channel must not already be loaded when loading" */);
214
- assert(await this.services.value.objectStorage.contains(".attributes"),
215
- 0x190 /* ".attributes blob should be present" */);
216
- const attributes = await readAndParse<IChannelAttributes>(
217
- this.services.value.objectStorage,
218
- ".attributes");
245
+ private async loadChannel(): Promise<IChannel> {
246
+ assert(!this.isLoaded, 0x18e /* "Channel must not already be loaded when loading" */);
247
+ assert(
248
+ await this.services.value.objectStorage.contains(".attributes"),
249
+ 0x190 /* ".attributes blob should be present" */,
250
+ );
251
+ const attributes = await readAndParse<IChannelAttributes>(
252
+ this.services.value.objectStorage,
253
+ ".attributes",
254
+ );
219
255
 
220
- assert(this.factory === undefined, 0x208 /* "Factory should be undefined before loading" */);
221
- this.factory = this.registry.get(attributes.type);
222
- if (this.factory === undefined) {
223
- throw new Error(`Channel Factory ${attributes.type} not registered`);
224
- }
225
- // Services will be assigned during this load.
226
- const channel = await this.factory.load(
227
- this.runtime,
228
- this.id,
229
- this.services.value,
230
- attributes);
256
+ assert(
257
+ this.factory === undefined,
258
+ 0x208 /* "Factory should be undefined before loading" */,
259
+ );
260
+ this.factory = this.registry.get(attributes.type);
261
+ if (this.factory === undefined) {
262
+ throw new Error(`Channel Factory ${attributes.type} not registered`);
263
+ }
264
+ // Services will be assigned during this load.
265
+ const channel = await this.factory.load(
266
+ this.runtime,
267
+ this.id,
268
+ this.services.value,
269
+ attributes,
270
+ );
231
271
 
232
- // Commit changes.
233
- this.channel = channel;
272
+ // Commit changes.
273
+ this.channel = channel;
234
274
 
235
- // Send all pending messages to the channel
236
- for (const message of this.pending) {
237
- this.services.value.deltaConnection.process(message, false, undefined /* localOpMetadata */);
238
- }
239
- return this.channel;
240
- }
275
+ // Send all pending messages to the channel
276
+ for (const message of this.pending) {
277
+ this.services.value.deltaConnection.process(
278
+ message,
279
+ false,
280
+ undefined /* localOpMetadata */,
281
+ );
282
+ }
283
+ return this.channel;
284
+ }
241
285
 
242
- private isSnapshotInOldFormatAndCollectBlobs(
243
- snapshotTree: ISnapshotTree,
244
- blobMap: Map<string, ArrayBufferLike>,
245
- ): boolean {
246
- let sanitize = false;
247
- const blobsContents: { [path: string]: ArrayBufferLike; } = (snapshotTree as any).blobsContents;
248
- Object.entries(blobsContents).forEach(([key, value]) => {
249
- blobMap.set(key, value);
250
- if (snapshotTree.blobs[key] !== undefined) {
251
- sanitize = true;
252
- }
253
- });
254
- for (const value of Object.values(snapshotTree.trees)) {
255
- sanitize = sanitize || this.isSnapshotInOldFormatAndCollectBlobs(value, blobMap);
256
- }
257
- return sanitize;
258
- }
286
+ private isSnapshotInOldFormatAndCollectBlobs(
287
+ snapshotTree: ISnapshotTree,
288
+ blobMap: Map<string, ArrayBufferLike>,
289
+ ): boolean {
290
+ let sanitize = false;
291
+ const blobsContents: { [path: string]: ArrayBufferLike } = (snapshotTree as any)
292
+ .blobsContents;
293
+ Object.entries(blobsContents).forEach(([key, value]) => {
294
+ blobMap.set(key, value);
295
+ if (snapshotTree.blobs[key] !== undefined) {
296
+ sanitize = true;
297
+ }
298
+ });
299
+ for (const value of Object.values(snapshotTree.trees)) {
300
+ sanitize = sanitize || this.isSnapshotInOldFormatAndCollectBlobs(value, blobMap);
301
+ }
302
+ return sanitize;
303
+ }
259
304
 
260
- private sanitizeSnapshot(snapshotTree: ISnapshotTree) {
261
- const blobMapInitial = new Map(Object.entries(snapshotTree.blobs));
262
- for (const [blobName, blobId] of blobMapInitial.entries()) {
263
- const blobValue = blobMapInitial.get(blobId);
264
- if (blobValue === undefined) {
265
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
266
- delete snapshotTree.blobs[blobName];
267
- }
268
- }
269
- for (const value of Object.values(snapshotTree.trees)) {
270
- this.sanitizeSnapshot(value);
271
- }
272
- }
305
+ private sanitizeSnapshot(snapshotTree: ISnapshotTree) {
306
+ const blobMapInitial = new Map(Object.entries(snapshotTree.blobs));
307
+ for (const [blobName, blobId] of blobMapInitial.entries()) {
308
+ const blobValue = blobMapInitial.get(blobId);
309
+ if (blobValue === undefined) {
310
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
311
+ delete snapshotTree.blobs[blobName];
312
+ }
313
+ }
314
+ for (const value of Object.values(snapshotTree.trees)) {
315
+ this.sanitizeSnapshot(value);
316
+ }
317
+ }
273
318
  }
274
319
 
275
320
  export class LocalChannelContext extends LocalChannelContextBase {
276
- private readonly services: Lazy<{
277
- readonly deltaConnection: ChannelDeltaConnection;
278
- readonly objectStorage: ChannelStorageService;
279
- }>;
280
- private readonly dirtyFn: () => void;
281
- constructor(
282
- id: string,
283
- registry: ISharedObjectRegistry,
284
- type: string,
285
- runtime: IFluidDataStoreRuntime,
286
- dataStoreContext: IFluidDataStoreContext,
287
- storageService: IDocumentStorageService,
288
- logger: ITelemetryLogger,
289
- submitFn: (content: any, localOpMetadata: unknown) => void,
290
- dirtyFn: (address: string) => void,
291
- addedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void,
292
- ) {
293
- super(id, registry, runtime, () => this.services);
294
- assert(type !== undefined, 0x209 /* "Factory Type should be defined" */);
295
- this.factory = registry.get(type);
296
- if (this.factory === undefined) {
297
- throw new Error(`Channel Factory ${type} not registered`);
298
- }
299
- this.channel = this.factory.create(runtime, id);
300
- this.services = new Lazy(() => {
301
- return createServiceEndpoints(
302
- this.id,
303
- dataStoreContext.connected,
304
- submitFn,
305
- this.dirtyFn,
306
- addedGCOutboundReferenceFn,
307
- storageService,
308
- logger,
309
- );
310
- });
311
- this.dirtyFn = () => { dirtyFn(id); };
312
- }
321
+ private readonly services: Lazy<{
322
+ readonly deltaConnection: ChannelDeltaConnection;
323
+ readonly objectStorage: ChannelStorageService;
324
+ }>;
325
+ private readonly dirtyFn: () => void;
326
+ constructor(
327
+ id: string,
328
+ registry: ISharedObjectRegistry,
329
+ type: string,
330
+ runtime: IFluidDataStoreRuntime,
331
+ dataStoreContext: IFluidDataStoreContext,
332
+ storageService: IDocumentStorageService,
333
+ logger: ITelemetryLogger,
334
+ submitFn: (content: any, localOpMetadata: unknown) => void,
335
+ dirtyFn: (address: string) => void,
336
+ addedGCOutboundReferenceFn: (srcHandle: IFluidHandle, outboundHandle: IFluidHandle) => void,
337
+ ) {
338
+ super(id, registry, runtime, () => this.services);
339
+ assert(type !== undefined, 0x209 /* "Factory Type should be defined" */);
340
+ this.factory = registry.get(type);
341
+ if (this.factory === undefined) {
342
+ throw new Error(`Channel Factory ${type} not registered`);
343
+ }
344
+ this.channel = this.factory.create(runtime, id);
345
+ this.services = new Lazy(() => {
346
+ return createServiceEndpoints(
347
+ this.id,
348
+ dataStoreContext.connected,
349
+ submitFn,
350
+ this.dirtyFn,
351
+ addedGCOutboundReferenceFn,
352
+ storageService,
353
+ logger,
354
+ );
355
+ });
356
+ this.dirtyFn = () => {
357
+ dirtyFn(id);
358
+ };
359
+ }
313
360
  }