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