@fluidframework/container-loader 2.0.0-dev.5.3.2.178189 → 2.0.0-dev.6.4.0.191457
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/CHANGELOG.md +131 -0
- package/README.md +10 -6
- package/dist/audience.d.ts +1 -0
- package/dist/audience.d.ts.map +1 -1
- package/dist/audience.js +5 -3
- package/dist/audience.js.map +1 -1
- package/dist/catchUpMonitor.js +2 -2
- package/dist/catchUpMonitor.js.map +1 -1
- package/dist/connectionManager.d.ts +5 -5
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +97 -93
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +15 -14
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +50 -52
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +20 -9
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +327 -277
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +2 -7
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js +2 -14
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +12 -13
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +21 -8
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +3 -3
- package/dist/contracts.js.map +1 -1
- package/dist/debugLogger.d.ts +30 -0
- package/dist/debugLogger.d.ts.map +1 -0
- package/dist/debugLogger.js +95 -0
- package/dist/debugLogger.js.map +1 -0
- package/dist/deltaManager.d.ts +21 -10
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +114 -66
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaQueue.d.ts +1 -1
- package/dist/deltaQueue.d.ts.map +1 -1
- package/dist/deltaQueue.js +10 -10
- package/dist/deltaQueue.js.map +1 -1
- package/dist/disposal.d.ts +2 -2
- package/dist/disposal.d.ts.map +1 -1
- package/dist/disposal.js +1 -1
- package/dist/disposal.js.map +1 -1
- package/dist/error.d.ts +23 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +32 -0
- package/dist/error.js.map +1 -0
- package/dist/loader.d.ts +22 -3
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +82 -51
- package/dist/loader.js.map +1 -1
- package/dist/noopHeuristic.d.ts +2 -2
- package/dist/noopHeuristic.d.ts.map +1 -1
- package/dist/noopHeuristic.js +6 -5
- package/dist/noopHeuristic.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/protocol.d.ts +4 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +25 -4
- package/dist/protocol.js.map +1 -1
- package/dist/quorum.d.ts +4 -1
- package/dist/quorum.d.ts.map +1 -1
- package/dist/quorum.js +1 -13
- package/dist/quorum.js.map +1 -1
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +4 -4
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/utils.d.ts +8 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +30 -11
- package/dist/utils.js.map +1 -1
- package/lib/audience.d.ts +1 -0
- package/lib/audience.d.ts.map +1 -1
- package/lib/audience.js +4 -2
- package/lib/audience.js.map +1 -1
- package/lib/catchUpMonitor.js +1 -1
- package/lib/catchUpMonitor.js.map +1 -1
- package/lib/connectionManager.d.ts +5 -5
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +74 -67
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +15 -14
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +27 -29
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +20 -9
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +288 -238
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +2 -7
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js +2 -14
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +5 -6
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +21 -8
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js +3 -3
- package/lib/contracts.js.map +1 -1
- package/lib/debugLogger.d.ts +30 -0
- package/lib/debugLogger.d.ts.map +1 -0
- package/lib/debugLogger.js +91 -0
- package/lib/debugLogger.js.map +1 -0
- package/lib/deltaManager.d.ts +21 -10
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +88 -37
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaQueue.d.ts +1 -1
- package/lib/deltaQueue.d.ts.map +1 -1
- package/lib/deltaQueue.js +3 -3
- package/lib/deltaQueue.js.map +1 -1
- package/lib/disposal.d.ts +2 -2
- package/lib/disposal.d.ts.map +1 -1
- package/lib/disposal.js +1 -1
- package/lib/disposal.js.map +1 -1
- package/lib/error.d.ts +23 -0
- package/lib/error.d.ts.map +1 -0
- package/lib/error.js +28 -0
- package/lib/error.js.map +1 -0
- package/lib/loader.d.ts +22 -3
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +82 -51
- package/lib/loader.js.map +1 -1
- package/lib/noopHeuristic.d.ts +2 -2
- package/lib/noopHeuristic.d.ts.map +1 -1
- package/lib/noopHeuristic.js +2 -1
- package/lib/noopHeuristic.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/protocol.d.ts +4 -2
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +25 -4
- package/lib/protocol.js.map +1 -1
- package/lib/quorum.d.ts +4 -1
- package/lib/quorum.d.ts.map +1 -1
- package/lib/quorum.js +0 -11
- package/lib/quorum.js.map +1 -1
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +2 -2
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/utils.d.ts +8 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +25 -7
- package/lib/utils.js.map +1 -1
- package/package.json +26 -32
- package/src/audience.ts +7 -1
- package/src/catchUpMonitor.ts +1 -1
- package/src/connectionManager.ts +75 -51
- package/src/connectionStateHandler.ts +31 -38
- package/src/container.ts +335 -240
- package/src/containerContext.ts +0 -16
- package/src/containerStorageAdapter.ts +2 -1
- package/src/contracts.ts +27 -11
- package/src/debugLogger.ts +113 -0
- package/src/deltaManager.ts +84 -34
- package/src/deltaQueue.ts +2 -1
- package/src/disposal.ts +2 -2
- package/src/error.ts +44 -0
- package/src/loader.ts +83 -35
- package/src/noopHeuristic.ts +3 -2
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +33 -2
- package/src/quorum.ts +0 -10
- package/src/retriableDocumentStorageService.ts +2 -4
- package/src/utils.ts +33 -8
package/src/loader.ts
CHANGED
|
@@ -6,14 +6,13 @@
|
|
|
6
6
|
import { v4 as uuid } from "uuid";
|
|
7
7
|
import {
|
|
8
8
|
ITelemetryLoggerExt,
|
|
9
|
-
ChildLogger,
|
|
10
|
-
DebugLogger,
|
|
11
9
|
IConfigProviderBase,
|
|
12
|
-
loggerToMonitoringContext,
|
|
13
10
|
mixinMonitoringContext,
|
|
14
11
|
MonitoringContext,
|
|
15
12
|
PerformanceEvent,
|
|
16
13
|
sessionStorageConfigProvider,
|
|
14
|
+
createChildMonitoringContext,
|
|
15
|
+
UsageError,
|
|
17
16
|
} from "@fluidframework/telemetry-utils";
|
|
18
17
|
import {
|
|
19
18
|
ITelemetryBaseLogger,
|
|
@@ -39,18 +38,15 @@ import {
|
|
|
39
38
|
IResolvedUrl,
|
|
40
39
|
IUrlResolver,
|
|
41
40
|
} from "@fluidframework/driver-definitions";
|
|
42
|
-
import {
|
|
41
|
+
import { IClientDetails } from "@fluidframework/protocol-definitions";
|
|
43
42
|
import { Container, IPendingContainerState } from "./container";
|
|
44
43
|
import { IParsedUrl, parseUrl } from "./utils";
|
|
45
44
|
import { pkgVersion } from "./packageVersion";
|
|
46
45
|
import { ProtocolHandlerBuilder } from "./protocol";
|
|
46
|
+
import { DebugLogger } from "./debugLogger";
|
|
47
47
|
|
|
48
48
|
function canUseCache(request: IRequest): boolean {
|
|
49
|
-
|
|
50
|
-
return true;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return request.headers[LoaderHeader.cache] !== false;
|
|
49
|
+
return request.headers?.[LoaderHeader.cache] === true;
|
|
54
50
|
}
|
|
55
51
|
|
|
56
52
|
function ensureResolvedUrlDefined(
|
|
@@ -69,6 +65,9 @@ export class RelativeLoader implements ILoader {
|
|
|
69
65
|
private readonly loader: ILoader | undefined,
|
|
70
66
|
) {}
|
|
71
67
|
|
|
68
|
+
/**
|
|
69
|
+
* @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the Container's IFluidRouter/request.
|
|
70
|
+
*/
|
|
72
71
|
public get IFluidRouter(): IFluidRouter {
|
|
73
72
|
return this;
|
|
74
73
|
}
|
|
@@ -100,6 +99,9 @@ export class RelativeLoader implements ILoader {
|
|
|
100
99
|
return this.loader.resolve(request);
|
|
101
100
|
}
|
|
102
101
|
|
|
102
|
+
/**
|
|
103
|
+
* @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the Container's IFluidRouter/request.
|
|
104
|
+
*/
|
|
103
105
|
public async request(request: IRequest): Promise<IResponse> {
|
|
104
106
|
if (request.url.startsWith("/")) {
|
|
105
107
|
const container = await this.resolve(request);
|
|
@@ -149,7 +151,7 @@ export interface ICodeDetailsLoader extends Partial<IProvideFluidCodeDetailsComp
|
|
|
149
151
|
* Load the code module (package) that is capable to interact with the document.
|
|
150
152
|
*
|
|
151
153
|
* @param source - Code proposal that articulates the current schema the document is written in.
|
|
152
|
-
* @returns
|
|
154
|
+
* @returns Code module entry point along with the code details associated with it.
|
|
153
155
|
*/
|
|
154
156
|
load(source: IFluidCodeDetails): Promise<IFluidModuleWithDetails>;
|
|
155
157
|
}
|
|
@@ -343,15 +345,33 @@ export class Loader implements IHostLoader {
|
|
|
343
345
|
protocolHandlerBuilder,
|
|
344
346
|
subLogger: subMc.logger,
|
|
345
347
|
};
|
|
346
|
-
this.mc =
|
|
348
|
+
this.mc = createChildMonitoringContext({
|
|
349
|
+
logger: this.services.subLogger,
|
|
350
|
+
namespace: "Loader",
|
|
351
|
+
});
|
|
347
352
|
}
|
|
348
353
|
|
|
354
|
+
/**
|
|
355
|
+
* @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the Container's IFluidRouter/request.
|
|
356
|
+
*/
|
|
349
357
|
public get IFluidRouter(): IFluidRouter {
|
|
350
358
|
return this;
|
|
351
359
|
}
|
|
352
360
|
|
|
353
|
-
public async createDetachedContainer(
|
|
354
|
-
|
|
361
|
+
public async createDetachedContainer(
|
|
362
|
+
codeDetails: IFluidCodeDetails,
|
|
363
|
+
createDetachedProps?: {
|
|
364
|
+
canReconnect?: boolean;
|
|
365
|
+
clientDetailsOverride?: IClientDetails;
|
|
366
|
+
},
|
|
367
|
+
): Promise<IContainer> {
|
|
368
|
+
const container = await Container.createDetached(
|
|
369
|
+
{
|
|
370
|
+
...createDetachedProps,
|
|
371
|
+
...this.services,
|
|
372
|
+
},
|
|
373
|
+
codeDetails,
|
|
374
|
+
);
|
|
355
375
|
|
|
356
376
|
if (this.cachingEnabled) {
|
|
357
377
|
container.once("attached", () => {
|
|
@@ -366,8 +386,20 @@ export class Loader implements IHostLoader {
|
|
|
366
386
|
return container;
|
|
367
387
|
}
|
|
368
388
|
|
|
369
|
-
public async rehydrateDetachedContainerFromSnapshot(
|
|
370
|
-
|
|
389
|
+
public async rehydrateDetachedContainerFromSnapshot(
|
|
390
|
+
snapshot: string,
|
|
391
|
+
createDetachedProps?: {
|
|
392
|
+
canReconnect?: boolean;
|
|
393
|
+
clientDetailsOverride?: IClientDetails;
|
|
394
|
+
},
|
|
395
|
+
): Promise<IContainer> {
|
|
396
|
+
return Container.rehydrateDetachedFromSnapshot(
|
|
397
|
+
{
|
|
398
|
+
...createDetachedProps,
|
|
399
|
+
...this.services,
|
|
400
|
+
},
|
|
401
|
+
snapshot,
|
|
402
|
+
);
|
|
371
403
|
}
|
|
372
404
|
|
|
373
405
|
public async resolve(request: IRequest, pendingLocalState?: string): Promise<IContainer> {
|
|
@@ -381,6 +413,9 @@ export class Loader implements IHostLoader {
|
|
|
381
413
|
});
|
|
382
414
|
}
|
|
383
415
|
|
|
416
|
+
/**
|
|
417
|
+
* @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the Container's IFluidRouter/request.
|
|
418
|
+
*/
|
|
384
419
|
public async request(request: IRequest): Promise<IResponse> {
|
|
385
420
|
return PerformanceEvent.timedExecAsync(
|
|
386
421
|
this.mc.logger,
|
|
@@ -407,16 +442,23 @@ export class Loader implements IHostLoader {
|
|
|
407
442
|
this.containers.set(key, containerP);
|
|
408
443
|
containerP
|
|
409
444
|
.then((container) => {
|
|
410
|
-
// If the container is closed or becomes closed after we resolve it,
|
|
411
|
-
|
|
445
|
+
// If the container is closed/disposed or becomes closed/disposed after we resolve it,
|
|
446
|
+
// remove it from the cache.
|
|
447
|
+
if (container.closed || container.disposed) {
|
|
412
448
|
this.containers.delete(key);
|
|
413
449
|
} else {
|
|
414
450
|
container.once("closed", () => {
|
|
415
451
|
this.containers.delete(key);
|
|
416
452
|
});
|
|
453
|
+
container.once("disposed", () => {
|
|
454
|
+
this.containers.delete(key);
|
|
455
|
+
});
|
|
417
456
|
}
|
|
418
457
|
})
|
|
419
|
-
.catch((error) => {
|
|
458
|
+
.catch((error) => {
|
|
459
|
+
// If an error occured while resolving the container request, then remove it from the cache.
|
|
460
|
+
this.containers.delete(key);
|
|
461
|
+
});
|
|
420
462
|
}
|
|
421
463
|
|
|
422
464
|
private async resolveCore(
|
|
@@ -447,11 +489,29 @@ export class Loader implements IHostLoader {
|
|
|
447
489
|
// If set in both query string and headers, use query string. Also write the value from the query string into the header either way.
|
|
448
490
|
request.headers[LoaderHeader.version] =
|
|
449
491
|
parsed.version ?? request.headers[LoaderHeader.version];
|
|
492
|
+
const cacheHeader = request.headers[LoaderHeader.cache];
|
|
450
493
|
const canCache =
|
|
451
|
-
|
|
452
|
-
|
|
494
|
+
// Take header value if present, else use ILoaderOptions.cache value
|
|
495
|
+
(cacheHeader !== undefined ? cacheHeader === true : this.cachingEnabled) &&
|
|
453
496
|
pendingLocalState === undefined;
|
|
454
|
-
const fromSequenceNumber = request.headers[LoaderHeader.sequenceNumber]
|
|
497
|
+
const fromSequenceNumber = request.headers[LoaderHeader.sequenceNumber] as
|
|
498
|
+
| number
|
|
499
|
+
| undefined;
|
|
500
|
+
const opsBeforeReturn = request.headers[LoaderHeader.loadMode]?.opsBeforeReturn as
|
|
501
|
+
| string
|
|
502
|
+
| undefined;
|
|
503
|
+
|
|
504
|
+
if (
|
|
505
|
+
opsBeforeReturn === "sequenceNumber" &&
|
|
506
|
+
(fromSequenceNumber === undefined || fromSequenceNumber < 0)
|
|
507
|
+
) {
|
|
508
|
+
// If opsBeforeReturn is set to "sequenceNumber", then fromSequenceNumber should be set to a non-negative integer.
|
|
509
|
+
throw new UsageError("sequenceNumber must be set to a non-negative integer");
|
|
510
|
+
} else if (opsBeforeReturn !== "sequenceNumber" && fromSequenceNumber !== undefined) {
|
|
511
|
+
// If opsBeforeReturn is not set to "sequenceNumber", then fromSequenceNumber should be undefined (default value).
|
|
512
|
+
// In this case, we should throw an error since opsBeforeReturn is not explicitly set to "sequenceNumber".
|
|
513
|
+
throw new UsageError('opsBeforeReturn must be set to "sequenceNumber"');
|
|
514
|
+
}
|
|
455
515
|
|
|
456
516
|
let container: Container;
|
|
457
517
|
if (canCache) {
|
|
@@ -468,24 +528,11 @@ export class Loader implements IHostLoader {
|
|
|
468
528
|
container = await this.loadContainer(request, resolvedAsFluid, pendingLocalState);
|
|
469
529
|
}
|
|
470
530
|
|
|
471
|
-
if (container.deltaManager.lastSequenceNumber <= fromSequenceNumber) {
|
|
472
|
-
await new Promise<void>((resolve, reject) => {
|
|
473
|
-
function opHandler(message: ISequencedDocumentMessage) {
|
|
474
|
-
if (message.sequenceNumber > fromSequenceNumber) {
|
|
475
|
-
resolve();
|
|
476
|
-
container.removeListener("op", opHandler);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
container.on("op", opHandler);
|
|
481
|
-
});
|
|
482
|
-
}
|
|
483
|
-
|
|
484
531
|
return { container, parsed };
|
|
485
532
|
}
|
|
486
533
|
|
|
487
534
|
private get cachingEnabled() {
|
|
488
|
-
return this.services.options.cache
|
|
535
|
+
return this.services.options.cache === true;
|
|
489
536
|
}
|
|
490
537
|
|
|
491
538
|
private async loadContainer(
|
|
@@ -499,6 +546,7 @@ export class Loader implements IHostLoader {
|
|
|
499
546
|
version: request.headers?.[LoaderHeader.version] ?? undefined,
|
|
500
547
|
loadMode: request.headers?.[LoaderHeader.loadMode],
|
|
501
548
|
pendingLocalState,
|
|
549
|
+
loadToSequenceNumber: request.headers?.[LoaderHeader.sequenceNumber],
|
|
502
550
|
},
|
|
503
551
|
{
|
|
504
552
|
canReconnect: request.headers?.[LoaderHeader.reconnect],
|
package/src/noopHeuristic.ts
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
7
|
+
import { assert, Timer } from "@fluidframework/core-utils";
|
|
7
8
|
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
8
9
|
import { isRuntimeMessage } from "@fluidframework/driver-utils";
|
|
9
|
-
import { IEvent } from "@fluidframework/
|
|
10
|
+
import { IEvent } from "@fluidframework/core-interfaces";
|
|
10
11
|
|
|
11
12
|
const defaultNoopTimeFrequency = 2000;
|
|
12
13
|
const defaultNoopCountFrequency = 50;
|
package/src/packageVersion.ts
CHANGED
package/src/protocol.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { IAudienceOwner } from "@fluidframework/container-definitions";
|
|
7
|
+
import { canBeCoalescedByService } from "@fluidframework/driver-utils";
|
|
7
8
|
import {
|
|
8
9
|
IProtocolHandler as IBaseProtocolHandler,
|
|
9
10
|
IQuorumSnapshot,
|
|
@@ -11,8 +12,12 @@ import {
|
|
|
11
12
|
} from "@fluidframework/protocol-base";
|
|
12
13
|
import {
|
|
13
14
|
IDocumentAttributes,
|
|
15
|
+
IProcessMessageResult,
|
|
16
|
+
ISequencedClient,
|
|
17
|
+
ISequencedDocumentMessage,
|
|
14
18
|
ISignalClient,
|
|
15
19
|
ISignalMessage,
|
|
20
|
+
MessageType,
|
|
16
21
|
} from "@fluidframework/protocol-definitions";
|
|
17
22
|
|
|
18
23
|
// "term" was an experimental feature that is being removed. The only safe value to use is 1.
|
|
@@ -44,12 +49,12 @@ export class ProtocolHandler extends ProtocolOpHandler implements IProtocolHandl
|
|
|
44
49
|
attributes: IDocumentAttributes,
|
|
45
50
|
quorumSnapshot: IQuorumSnapshot,
|
|
46
51
|
sendProposal: (key: string, value: any) => number,
|
|
47
|
-
readonly audience: IAudienceOwner,
|
|
52
|
+
public readonly audience: IAudienceOwner,
|
|
53
|
+
private readonly shouldClientHaveLeft: (clientId: string) => boolean,
|
|
48
54
|
) {
|
|
49
55
|
super(
|
|
50
56
|
attributes.minimumSequenceNumber,
|
|
51
57
|
attributes.sequenceNumber,
|
|
52
|
-
OnlyValidTermValue,
|
|
53
58
|
quorumSnapshot.members,
|
|
54
59
|
quorumSnapshot.proposals,
|
|
55
60
|
quorumSnapshot.values,
|
|
@@ -66,6 +71,32 @@ export class ProtocolHandler extends ProtocolOpHandler implements IProtocolHandl
|
|
|
66
71
|
}
|
|
67
72
|
}
|
|
68
73
|
|
|
74
|
+
public processMessage(
|
|
75
|
+
message: ISequencedDocumentMessage,
|
|
76
|
+
local: boolean,
|
|
77
|
+
): IProcessMessageResult {
|
|
78
|
+
const client: ISequencedClient | undefined = this.quorum.getMember(message.clientId);
|
|
79
|
+
|
|
80
|
+
// Check and report if we're getting messages from a clientId that we previously
|
|
81
|
+
// flagged as shouldHaveLeft, or from a client that's not in the quorum but should be
|
|
82
|
+
if (message.clientId != null) {
|
|
83
|
+
if (client === undefined && message.type !== MessageType.ClientJoin) {
|
|
84
|
+
// pre-0.58 error message: messageClientIdMissingFromQuorum
|
|
85
|
+
throw new Error("Remote message's clientId is missing from the quorum");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Here checking canBeCoalescedByService is used as an approximation of "is benign to process despite being unexpected".
|
|
89
|
+
// It's still not good to see these messages from unexpected clientIds, but since they don't harm the integrity of the
|
|
90
|
+
// document we don't need to blow up aggressively.
|
|
91
|
+
if (this.shouldClientHaveLeft(message.clientId) && !canBeCoalescedByService(message)) {
|
|
92
|
+
// pre-0.58 error message: messageClientIdShouldHaveLeft
|
|
93
|
+
throw new Error("Remote message's clientId already should have left");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return super.processMessage(message, local);
|
|
98
|
+
}
|
|
99
|
+
|
|
69
100
|
public processSignal(message: ISignalMessage) {
|
|
70
101
|
const innerContent = message.content as { content: any; type: string };
|
|
71
102
|
switch (innerContent.type) {
|
package/src/quorum.ts
CHANGED
|
@@ -2,19 +2,9 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import { assert } from "@fluidframework/common-utils";
|
|
6
5
|
import { IFluidCodeDetails } from "@fluidframework/core-interfaces";
|
|
7
6
|
import { ICommittedProposal } from "@fluidframework/protocol-definitions";
|
|
8
7
|
|
|
9
|
-
export function getCodeDetailsFromQuorumValues(
|
|
10
|
-
quorumValues: [string, ICommittedProposal][],
|
|
11
|
-
): IFluidCodeDetails {
|
|
12
|
-
const qValuesMap = new Map(quorumValues);
|
|
13
|
-
const proposal = qValuesMap.get("code");
|
|
14
|
-
assert(proposal !== undefined, 0x2dc /* "Cannot find code proposal" */);
|
|
15
|
-
return proposal?.value as IFluidCodeDetails;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
8
|
export function initQuorumValuesFromCodeDetails(
|
|
19
9
|
source: IFluidCodeDetails,
|
|
20
10
|
): [string, ICommittedProposal][] {
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { assert } from "@fluidframework/
|
|
7
|
-
import { GenericError } from "@fluidframework/container-utils";
|
|
6
|
+
import { assert } from "@fluidframework/core-utils";
|
|
8
7
|
import {
|
|
9
8
|
FetchSource,
|
|
10
9
|
IDocumentStorageService,
|
|
@@ -19,8 +18,7 @@ import {
|
|
|
19
18
|
IVersion,
|
|
20
19
|
} from "@fluidframework/protocol-definitions";
|
|
21
20
|
import { IDisposable } from "@fluidframework/core-interfaces";
|
|
22
|
-
|
|
23
|
-
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
21
|
+
import { GenericError, ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
24
22
|
import { runWithRetry } from "@fluidframework/driver-utils";
|
|
25
23
|
|
|
26
24
|
export class RetriableDocumentStorageService implements IDocumentStorageService, IDisposable {
|
package/src/utils.ts
CHANGED
|
@@ -5,19 +5,16 @@
|
|
|
5
5
|
|
|
6
6
|
import { parse } from "url";
|
|
7
7
|
import { v4 as uuid } from "uuid";
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
stringToBuffer,
|
|
11
|
-
Uint8ArrayToArrayBuffer,
|
|
12
|
-
unreachableCase,
|
|
13
|
-
} from "@fluidframework/common-utils";
|
|
8
|
+
import { stringToBuffer, Uint8ArrayToArrayBuffer } from "@fluid-internal/client-utils";
|
|
9
|
+
import { assert, unreachableCase } from "@fluidframework/core-utils";
|
|
14
10
|
import { ISummaryTree, ISnapshotTree, SummaryType } from "@fluidframework/protocol-definitions";
|
|
15
11
|
import { LoggingError } from "@fluidframework/telemetry-utils";
|
|
16
12
|
import {
|
|
13
|
+
CombinedAppAndProtocolSummary,
|
|
17
14
|
DeltaStreamConnectionForbiddenError,
|
|
18
15
|
isCombinedAppAndProtocolSummary,
|
|
19
16
|
} from "@fluidframework/driver-utils";
|
|
20
|
-
import {
|
|
17
|
+
import { DriverErrorTypes } from "@fluidframework/driver-definitions";
|
|
21
18
|
|
|
22
19
|
// This is used when we rehydrate a container from the snapshot. Here we put the blob contents
|
|
23
20
|
// in separate property: blobContents.
|
|
@@ -51,6 +48,34 @@ export function parseUrl(url: string): IParsedUrl | undefined {
|
|
|
51
48
|
: undefined;
|
|
52
49
|
}
|
|
53
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Combine the app summary and protocol summary in 1 tree.
|
|
53
|
+
* @param appSummary - Summary of the app.
|
|
54
|
+
* @param protocolSummary - Summary of the protocol.
|
|
55
|
+
* @internal
|
|
56
|
+
*/
|
|
57
|
+
export function combineAppAndProtocolSummary(
|
|
58
|
+
appSummary: ISummaryTree,
|
|
59
|
+
protocolSummary: ISummaryTree,
|
|
60
|
+
): CombinedAppAndProtocolSummary {
|
|
61
|
+
assert(
|
|
62
|
+
!isCombinedAppAndProtocolSummary(appSummary),
|
|
63
|
+
0x5a8 /* app summary is already a combined tree! */,
|
|
64
|
+
);
|
|
65
|
+
assert(
|
|
66
|
+
!isCombinedAppAndProtocolSummary(protocolSummary),
|
|
67
|
+
0x5a9 /* protocol summary is already a combined tree! */,
|
|
68
|
+
);
|
|
69
|
+
const createNewSummary: CombinedAppAndProtocolSummary = {
|
|
70
|
+
type: SummaryType.Tree,
|
|
71
|
+
tree: {
|
|
72
|
+
".protocol": protocolSummary,
|
|
73
|
+
".app": appSummary,
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
return createNewSummary;
|
|
77
|
+
}
|
|
78
|
+
|
|
54
79
|
/**
|
|
55
80
|
* Converts summary tree (for upload) to snapshot tree (for download).
|
|
56
81
|
* Summary tree blobs contain contents, but snapshot tree blobs normally
|
|
@@ -156,6 +181,6 @@ export function isDeltaStreamConnectionForbiddenError(
|
|
|
156
181
|
return (
|
|
157
182
|
typeof error === "object" &&
|
|
158
183
|
error !== null &&
|
|
159
|
-
error?.errorType ===
|
|
184
|
+
error?.errorType === DriverErrorTypes.deltaStreamConnectionForbidden
|
|
160
185
|
);
|
|
161
186
|
}
|