@fluidframework/driver-utils 2.81.1 → 2.82.0
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 +4 -0
- package/dist/adapters/compression/documentServiceCompressionAdapter.d.ts +2 -2
- package/dist/adapters/compression/documentServiceCompressionAdapter.d.ts.map +1 -1
- package/dist/adapters/compression/documentServiceCompressionAdapter.js.map +1 -1
- package/dist/adapters/compression/documentServiceFactoryCompressionAdapter.d.ts +4 -4
- package/dist/adapters/compression/documentServiceFactoryCompressionAdapter.d.ts.map +1 -1
- package/dist/adapters/compression/documentServiceFactoryCompressionAdapter.js.map +1 -1
- package/dist/adapters/compression/index.d.ts +1 -1
- package/dist/adapters/compression/index.d.ts.map +1 -1
- package/dist/adapters/compression/index.js.map +1 -1
- package/dist/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.d.ts +2 -2
- package/dist/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.d.ts.map +1 -1
- package/dist/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.js +15 -11
- package/dist/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.js.map +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/predefinedAdapters.d.ts +3 -3
- package/dist/adapters/predefinedAdapters.d.ts.map +1 -1
- package/dist/adapters/predefinedAdapters.js +4 -1
- package/dist/adapters/predefinedAdapters.js.map +1 -1
- package/dist/blob.d.ts +2 -1
- package/dist/blob.d.ts.map +1 -1
- package/dist/blob.js +3 -1
- package/dist/blob.js.map +1 -1
- package/dist/buildSnapshotTree.d.ts +1 -1
- package/dist/buildSnapshotTree.d.ts.map +1 -1
- package/dist/buildSnapshotTree.js.map +1 -1
- package/dist/cacheUtils.js +1 -1
- package/dist/cacheUtils.js.map +1 -1
- package/dist/documentServiceFactoryProxy.d.ts +3 -3
- package/dist/documentServiceFactoryProxy.d.ts.map +1 -1
- package/dist/documentServiceFactoryProxy.js.map +1 -1
- package/dist/documentServiceProxy.d.ts +3 -3
- package/dist/documentServiceProxy.d.ts.map +1 -1
- package/dist/documentServiceProxy.js.map +1 -1
- package/dist/documentStorageServiceProxy.d.ts +2 -2
- package/dist/documentStorageServiceProxy.d.ts.map +1 -1
- package/dist/documentStorageServiceProxy.js +3 -1
- package/dist/documentStorageServiceProxy.js.map +1 -1
- package/dist/error.d.ts +2 -2
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/insecureUrlResolver.d.ts +2 -2
- package/dist/insecureUrlResolver.d.ts.map +1 -1
- package/dist/insecureUrlResolver.js +4 -4
- package/dist/insecureUrlResolver.js.map +1 -1
- package/dist/messageRecognition.d.ts +3 -1
- package/dist/messageRecognition.d.ts.map +1 -1
- package/dist/messageRecognition.js +2 -0
- package/dist/messageRecognition.js.map +1 -1
- package/dist/network.d.ts +10 -6
- package/dist/network.d.ts.map +1 -1
- package/dist/network.js +18 -3
- package/dist/network.js.map +1 -1
- package/dist/networkUtils.d.ts +4 -3
- package/dist/networkUtils.d.ts.map +1 -1
- package/dist/networkUtils.js +6 -0
- package/dist/networkUtils.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/parallelRequests.d.ts +8 -4
- package/dist/parallelRequests.d.ts.map +1 -1
- package/dist/parallelRequests.js +24 -21
- package/dist/parallelRequests.js.map +1 -1
- package/dist/prefetchDocumentStorageService.d.ts.map +1 -1
- package/dist/prefetchDocumentStorageService.js +8 -10
- package/dist/prefetchDocumentStorageService.js.map +1 -1
- package/dist/protocol/gitHelper.d.ts +1 -1
- package/dist/protocol/gitHelper.d.ts.map +1 -1
- package/dist/protocol/gitHelper.js +12 -6
- package/dist/protocol/gitHelper.js.map +1 -1
- package/dist/readAndParse.d.ts +1 -1
- package/dist/readAndParse.d.ts.map +1 -1
- package/dist/readAndParse.js.map +1 -1
- package/dist/runWithRetry.d.ts +4 -2
- package/dist/runWithRetry.d.ts.map +1 -1
- package/dist/runWithRetry.js +14 -11
- package/dist/runWithRetry.js.map +1 -1
- package/dist/storageUtils.d.ts +1 -1
- package/dist/storageUtils.d.ts.map +1 -1
- package/dist/storageUtils.js.map +1 -1
- package/dist/summaryForCreateNew.d.ts +2 -2
- package/dist/summaryForCreateNew.d.ts.map +1 -1
- package/dist/summaryForCreateNew.js.map +1 -1
- package/dist/treeConversions.d.ts +2 -2
- package/dist/treeConversions.d.ts.map +1 -1
- package/dist/treeConversions.js +3 -1
- package/dist/treeConversions.js.map +1 -1
- package/eslint.config.mts +2 -2
- package/lib/adapters/compression/documentServiceCompressionAdapter.d.ts +2 -2
- package/lib/adapters/compression/documentServiceCompressionAdapter.d.ts.map +1 -1
- package/lib/adapters/compression/documentServiceCompressionAdapter.js.map +1 -1
- package/lib/adapters/compression/documentServiceFactoryCompressionAdapter.d.ts +4 -4
- package/lib/adapters/compression/documentServiceFactoryCompressionAdapter.d.ts.map +1 -1
- package/lib/adapters/compression/documentServiceFactoryCompressionAdapter.js.map +1 -1
- package/lib/adapters/compression/index.d.ts +1 -1
- package/lib/adapters/compression/index.d.ts.map +1 -1
- package/lib/adapters/compression/index.js.map +1 -1
- package/lib/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.d.ts +2 -2
- package/lib/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.d.ts.map +1 -1
- package/lib/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.js +15 -11
- package/lib/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.js.map +1 -1
- package/lib/adapters/index.d.ts +1 -1
- package/lib/adapters/index.d.ts.map +1 -1
- package/lib/adapters/index.js.map +1 -1
- package/lib/adapters/predefinedAdapters.d.ts +3 -3
- package/lib/adapters/predefinedAdapters.d.ts.map +1 -1
- package/lib/adapters/predefinedAdapters.js +4 -1
- package/lib/adapters/predefinedAdapters.js.map +1 -1
- package/lib/blob.d.ts +2 -1
- package/lib/blob.d.ts.map +1 -1
- package/lib/blob.js +4 -2
- package/lib/blob.js.map +1 -1
- package/lib/buildSnapshotTree.d.ts +1 -1
- package/lib/buildSnapshotTree.d.ts.map +1 -1
- package/lib/buildSnapshotTree.js.map +1 -1
- package/lib/cacheUtils.js +1 -1
- package/lib/cacheUtils.js.map +1 -1
- package/lib/documentServiceFactoryProxy.d.ts +3 -3
- package/lib/documentServiceFactoryProxy.d.ts.map +1 -1
- package/lib/documentServiceFactoryProxy.js.map +1 -1
- package/lib/documentServiceProxy.d.ts +3 -3
- package/lib/documentServiceProxy.d.ts.map +1 -1
- package/lib/documentServiceProxy.js.map +1 -1
- package/lib/documentStorageServiceProxy.d.ts +2 -2
- package/lib/documentStorageServiceProxy.d.ts.map +1 -1
- package/lib/documentStorageServiceProxy.js +3 -1
- package/lib/documentStorageServiceProxy.js.map +1 -1
- package/lib/error.d.ts +2 -2
- package/lib/error.d.ts.map +1 -1
- package/lib/error.js.map +1 -1
- package/lib/index.d.ts +4 -4
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/insecureUrlResolver.d.ts +2 -2
- package/lib/insecureUrlResolver.d.ts.map +1 -1
- package/lib/insecureUrlResolver.js +4 -4
- package/lib/insecureUrlResolver.js.map +1 -1
- package/lib/messageRecognition.d.ts +3 -1
- package/lib/messageRecognition.d.ts.map +1 -1
- package/lib/messageRecognition.js +2 -0
- package/lib/messageRecognition.js.map +1 -1
- package/lib/network.d.ts +10 -6
- package/lib/network.d.ts.map +1 -1
- package/lib/network.js +18 -3
- package/lib/network.js.map +1 -1
- package/lib/networkUtils.d.ts +4 -3
- package/lib/networkUtils.d.ts.map +1 -1
- package/lib/networkUtils.js +6 -0
- package/lib/networkUtils.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/parallelRequests.d.ts +8 -4
- package/lib/parallelRequests.d.ts.map +1 -1
- package/lib/parallelRequests.js +24 -21
- package/lib/parallelRequests.js.map +1 -1
- package/lib/prefetchDocumentStorageService.d.ts.map +1 -1
- package/lib/prefetchDocumentStorageService.js +8 -10
- package/lib/prefetchDocumentStorageService.js.map +1 -1
- package/lib/protocol/gitHelper.d.ts +1 -1
- package/lib/protocol/gitHelper.d.ts.map +1 -1
- package/lib/protocol/gitHelper.js +12 -6
- package/lib/protocol/gitHelper.js.map +1 -1
- package/lib/readAndParse.d.ts +1 -1
- package/lib/readAndParse.d.ts.map +1 -1
- package/lib/readAndParse.js.map +1 -1
- package/lib/runWithRetry.d.ts +4 -2
- package/lib/runWithRetry.d.ts.map +1 -1
- package/lib/runWithRetry.js +15 -12
- package/lib/runWithRetry.js.map +1 -1
- package/lib/storageUtils.d.ts +1 -1
- package/lib/storageUtils.d.ts.map +1 -1
- package/lib/storageUtils.js.map +1 -1
- package/lib/summaryForCreateNew.d.ts +2 -2
- package/lib/summaryForCreateNew.d.ts.map +1 -1
- package/lib/summaryForCreateNew.js +1 -1
- package/lib/summaryForCreateNew.js.map +1 -1
- package/lib/treeConversions.d.ts +2 -2
- package/lib/treeConversions.d.ts.map +1 -1
- package/lib/treeConversions.js +3 -1
- package/lib/treeConversions.js.map +1 -1
- package/package.json +10 -9
- package/src/adapters/compression/documentServiceCompressionAdapter.ts +2 -2
- package/src/adapters/compression/documentServiceFactoryCompressionAdapter.ts +4 -4
- package/src/adapters/compression/index.ts +1 -1
- package/src/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.ts +25 -21
- package/src/adapters/index.ts +1 -1
- package/src/adapters/predefinedAdapters.ts +7 -4
- package/src/blob.ts +3 -7
- package/src/buildSnapshotTree.ts +6 -6
- package/src/cacheUtils.ts +1 -1
- package/src/documentServiceFactoryProxy.ts +3 -3
- package/src/documentServiceProxy.ts +3 -3
- package/src/documentStorageServiceProxy.ts +4 -2
- package/src/error.ts +2 -2
- package/src/index.ts +4 -4
- package/src/insecureUrlResolver.ts +7 -7
- package/src/messageRecognition.ts +4 -2
- package/src/network.ts +26 -12
- package/src/networkUtils.ts +12 -4
- package/src/packageVersion.ts +1 -1
- package/src/parallelRequests.ts +33 -30
- package/src/prefetchDocumentStorageService.ts +10 -10
- package/src/protocol/gitHelper.ts +15 -9
- package/src/readAndParse.ts +1 -1
- package/src/runWithRetry.ts +20 -14
- package/src/storageUtils.ts +1 -1
- package/src/summaryForCreateNew.ts +5 -1
- package/src/treeConversions.ts +5 -3
- package/biome.jsonc +0 -4
package/src/adapters/compression/summaryblob/documentStorageServiceSummaryBlobCompressionAdapter.ts
CHANGED
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
import { type Buffer, IsoBuffer } from "@fluid-internal/client-utils";
|
|
7
7
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
8
8
|
import {
|
|
9
|
-
ISummaryBlob,
|
|
10
|
-
ISummaryHandle,
|
|
11
|
-
ISummaryTree,
|
|
12
|
-
SummaryObject,
|
|
9
|
+
type ISummaryBlob,
|
|
10
|
+
type ISummaryHandle,
|
|
11
|
+
type ISummaryTree,
|
|
12
|
+
type SummaryObject,
|
|
13
13
|
SummaryType,
|
|
14
14
|
} from "@fluidframework/driver-definitions";
|
|
15
|
-
import {
|
|
15
|
+
import type {
|
|
16
16
|
IDocumentStorageService,
|
|
17
17
|
ISummaryContext,
|
|
18
18
|
ISnapshotTree,
|
|
@@ -74,10 +74,10 @@ export class DocumentStorageServiceCompressionAdapter extends DocumentStorageSer
|
|
|
74
74
|
* @param blob - The maybe compressed blob.
|
|
75
75
|
*/
|
|
76
76
|
private static readAlgorithmFromBlob(blob: ArrayBufferLike): number {
|
|
77
|
-
return
|
|
78
|
-
?
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
return this.hasPrefix(blob)
|
|
78
|
+
? // eslint-disable-next-line no-bitwise
|
|
79
|
+
IsoBuffer.from(blob)[0] & 0x0f
|
|
80
|
+
: SummaryCompressionAlgorithm.None;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/**
|
|
@@ -202,7 +202,7 @@ export class DocumentStorageServiceCompressionAdapter extends DocumentStorageSer
|
|
|
202
202
|
} else if (algorithm === SummaryCompressionAlgorithm.None) {
|
|
203
203
|
maybeCompressed = file;
|
|
204
204
|
} else if (algorithm === SummaryCompressionAlgorithm.LZ4) {
|
|
205
|
-
const compressed = compress(file) as ArrayBufferLike;
|
|
205
|
+
const compressed = compress(file as Uint8Array) as ArrayBufferLike;
|
|
206
206
|
maybeCompressed = compressed;
|
|
207
207
|
} else {
|
|
208
208
|
throw new Error(`Unknown Algorithm ${config.algorithm}`);
|
|
@@ -221,8 +221,9 @@ export class DocumentStorageServiceCompressionAdapter extends DocumentStorageSer
|
|
|
221
221
|
*/
|
|
222
222
|
private static decodeBlob(file: ArrayBufferLike): ArrayBufferLike {
|
|
223
223
|
let decompressed: ArrayBufferLike;
|
|
224
|
-
|
|
225
|
-
let
|
|
224
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: use a real type
|
|
225
|
+
let originalBlob: any;
|
|
226
|
+
let algorithm: SummaryCompressionAlgorithm;
|
|
226
227
|
if (this.hasPrefix(file)) {
|
|
227
228
|
algorithm = DocumentStorageServiceCompressionAdapter.readAlgorithmFromBlob(file);
|
|
228
229
|
originalBlob = this.removePrefixFromBlobIfPresent(file);
|
|
@@ -231,8 +232,10 @@ export class DocumentStorageServiceCompressionAdapter extends DocumentStorageSer
|
|
|
231
232
|
originalBlob = file;
|
|
232
233
|
}
|
|
233
234
|
if (algorithm === SummaryCompressionAlgorithm.None) {
|
|
235
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
234
236
|
decompressed = originalBlob;
|
|
235
237
|
} else if (algorithm === SummaryCompressionAlgorithm.LZ4) {
|
|
238
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment
|
|
236
239
|
decompressed = decompress(originalBlob) as ArrayBufferLike;
|
|
237
240
|
} else {
|
|
238
241
|
throw new Error(`Unknown Algorithm ${algorithm}`);
|
|
@@ -267,12 +270,13 @@ export class DocumentStorageServiceCompressionAdapter extends DocumentStorageSer
|
|
|
267
270
|
}
|
|
268
271
|
let clone: object | undefined;
|
|
269
272
|
for (const key of Object.keys(input)) {
|
|
270
|
-
|
|
273
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
274
|
+
const value: SummaryObject = input[key];
|
|
271
275
|
|
|
272
276
|
if (Boolean(value) && typeof value === "object") {
|
|
273
277
|
const replaced = this.recursivelyReplace(
|
|
274
278
|
isEncode,
|
|
275
|
-
value
|
|
279
|
+
value,
|
|
276
280
|
encoder,
|
|
277
281
|
decoder,
|
|
278
282
|
config,
|
|
@@ -396,13 +400,13 @@ export class DocumentStorageServiceCompressionAdapter extends DocumentStorageSer
|
|
|
396
400
|
*/
|
|
397
401
|
public override async readBlob(id: string): Promise<ArrayBufferLike> {
|
|
398
402
|
const originalBlob = await super.readBlob(id);
|
|
399
|
-
if (
|
|
400
|
-
return originalBlob;
|
|
401
|
-
} else {
|
|
403
|
+
if (this._isCompressionEnabled) {
|
|
402
404
|
const decompressedBlob =
|
|
403
405
|
DocumentStorageServiceCompressionAdapter.decodeBlob(originalBlob);
|
|
404
406
|
// console.log(`Miso summary-blob Blob read END : ${id} ${decompressedBlob.byteLength}`);
|
|
405
407
|
return decompressedBlob;
|
|
408
|
+
} else {
|
|
409
|
+
return originalBlob;
|
|
406
410
|
}
|
|
407
411
|
}
|
|
408
412
|
|
|
@@ -451,14 +455,14 @@ export class DocumentStorageServiceCompressionAdapter extends DocumentStorageSer
|
|
|
451
455
|
*/
|
|
452
456
|
public override async downloadSummary(id: ISummaryHandle): Promise<ISummaryTree> {
|
|
453
457
|
const summary = await super.downloadSummary(id);
|
|
454
|
-
return
|
|
455
|
-
?
|
|
456
|
-
: (DocumentStorageServiceCompressionAdapter.recursivelyReplace(
|
|
458
|
+
return this._isCompressionEnabled
|
|
459
|
+
? (DocumentStorageServiceCompressionAdapter.recursivelyReplace(
|
|
457
460
|
false,
|
|
458
461
|
summary,
|
|
459
462
|
DocumentStorageServiceCompressionAdapter.blobEncoder,
|
|
460
463
|
DocumentStorageServiceCompressionAdapter.blobDecoder,
|
|
461
464
|
this._config,
|
|
462
|
-
) as ISummaryTree)
|
|
465
|
+
) as ISummaryTree)
|
|
466
|
+
: summary;
|
|
463
467
|
}
|
|
464
468
|
}
|
package/src/adapters/index.ts
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
7
|
-
import { IDocumentServiceFactory } from "@fluidframework/driver-definitions/internal";
|
|
7
|
+
import type { IDocumentServiceFactory } from "@fluidframework/driver-definitions/internal";
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
10
|
DefaultCompressionStorageConfig,
|
|
11
11
|
DocumentServiceFactoryCompressionAdapter,
|
|
12
|
-
ICompressionStorageConfig,
|
|
12
|
+
type ICompressionStorageConfig,
|
|
13
13
|
} from "./compression/index.js";
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -67,9 +67,12 @@ function applyStorageCompressionInternal(
|
|
|
67
67
|
* This method checks whether given objects contains
|
|
68
68
|
* a properties expected for the interface ICompressionStorageConfig.
|
|
69
69
|
*/
|
|
70
|
-
export function isCompressionConfig(config:
|
|
70
|
+
export function isCompressionConfig(config: unknown): config is ICompressionStorageConfig {
|
|
71
71
|
return (
|
|
72
72
|
config !== undefined &&
|
|
73
|
-
|
|
73
|
+
typeof config === "object" &&
|
|
74
|
+
config !== null &&
|
|
75
|
+
((config as Partial<ICompressionStorageConfig>).algorithm !== undefined ||
|
|
76
|
+
(config as Partial<ICompressionStorageConfig>).minSizeToCompress !== undefined)
|
|
74
77
|
);
|
|
75
78
|
}
|
package/src/blob.ts
CHANGED
|
@@ -3,13 +3,8 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
IAttachment,
|
|
9
|
-
IBlob,
|
|
10
|
-
ITree,
|
|
11
|
-
TreeEntry,
|
|
12
|
-
} from "@fluidframework/driver-definitions/internal";
|
|
6
|
+
import type { IAttachment, IBlob, ITree } from "@fluidframework/driver-definitions/internal";
|
|
7
|
+
import { FileMode, TreeEntry } from "@fluidframework/driver-definitions/internal";
|
|
13
8
|
|
|
14
9
|
/**
|
|
15
10
|
* Basic implementation of a blob ITreeEntry
|
|
@@ -29,6 +24,7 @@ export class BlobTreeEntry {
|
|
|
29
24
|
constructor(
|
|
30
25
|
public readonly path: string,
|
|
31
26
|
contents: string,
|
|
27
|
+
// eslint-disable-next-line unicorn/text-encoding-identifier-case
|
|
32
28
|
encoding: "utf-8" | "base64" = "utf-8",
|
|
33
29
|
) {
|
|
34
30
|
this.value = { contents, encoding };
|
package/src/buildSnapshotTree.ts
CHANGED
|
@@ -7,10 +7,10 @@ import { stringToBuffer } from "@fluid-internal/client-utils";
|
|
|
7
7
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
8
8
|
import {
|
|
9
9
|
FileMode,
|
|
10
|
-
IGitTree,
|
|
11
|
-
IGitTreeEntry,
|
|
12
|
-
ISnapshotTree,
|
|
13
|
-
ITreeEntry,
|
|
10
|
+
type IGitTree,
|
|
11
|
+
type IGitTreeEntry,
|
|
12
|
+
type ISnapshotTree,
|
|
13
|
+
type ITreeEntry,
|
|
14
14
|
TreeEntry,
|
|
15
15
|
} from "@fluidframework/driver-definitions/internal";
|
|
16
16
|
import { v4 as uuid } from "uuid";
|
|
@@ -33,7 +33,7 @@ function flattenCore(
|
|
|
33
33
|
blobMap.set(id, buffer);
|
|
34
34
|
|
|
35
35
|
const entry: IGitTreeEntry = {
|
|
36
|
-
mode: FileMode[treeEntry.mode],
|
|
36
|
+
mode: FileMode[treeEntry.mode] as string,
|
|
37
37
|
path: subPath,
|
|
38
38
|
sha: id,
|
|
39
39
|
size: 0,
|
|
@@ -48,7 +48,7 @@ function flattenCore(
|
|
|
48
48
|
);
|
|
49
49
|
const t = treeEntry.value;
|
|
50
50
|
const entry: IGitTreeEntry = {
|
|
51
|
-
mode: FileMode[treeEntry.mode],
|
|
51
|
+
mode: FileMode[treeEntry.mode] as string,
|
|
52
52
|
path: subPath,
|
|
53
53
|
sha: "",
|
|
54
54
|
size: -1,
|
package/src/cacheUtils.ts
CHANGED
|
@@ -22,6 +22,6 @@ export const maximumCacheDurationMs: FiveDaysMs = 432_000_000; // 5 days in ms
|
|
|
22
22
|
* @internal
|
|
23
23
|
*/
|
|
24
24
|
export function getKeyForCacheEntry(entry: ICacheEntry): string {
|
|
25
|
-
const version = entry.file.fileVersion
|
|
25
|
+
const version = entry.file.fileVersion === undefined ? "" : `_${entry.file.fileVersion}`;
|
|
26
26
|
return `${entry.file.docId}${version}_${entry.type}_${entry.key}`;
|
|
27
27
|
}
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type { ILayerCompatDetails } from "@fluid-internal/client-utils";
|
|
7
|
-
import { ITelemetryBaseLogger,
|
|
8
|
-
import { ISummaryTree } from "@fluidframework/driver-definitions";
|
|
9
|
-
import {
|
|
7
|
+
import type { ITelemetryBaseLogger, FluidObject } from "@fluidframework/core-interfaces";
|
|
8
|
+
import type { ISummaryTree } from "@fluidframework/driver-definitions";
|
|
9
|
+
import type {
|
|
10
10
|
IDocumentService,
|
|
11
11
|
IDocumentServiceFactory,
|
|
12
12
|
IResolvedUrl,
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
7
|
-
import { IClient } from "@fluidframework/driver-definitions";
|
|
8
|
-
import {
|
|
7
|
+
import type { IClient } from "@fluidframework/driver-definitions";
|
|
8
|
+
import type {
|
|
9
9
|
IDocumentDeltaConnection,
|
|
10
10
|
IDocumentDeltaStorageService,
|
|
11
11
|
IDocumentService,
|
|
@@ -43,7 +43,7 @@ export abstract class DocumentServiceProxy
|
|
|
43
43
|
return this._service.connectToDeltaStream(client);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
public dispose(error?:
|
|
46
|
+
public dispose(error?: unknown): void {
|
|
47
47
|
this._service.dispose(error);
|
|
48
48
|
}
|
|
49
49
|
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { ISummaryHandle, ISummaryTree } from "@fluidframework/driver-definitions";
|
|
7
|
-
import {
|
|
6
|
+
import type { ISummaryHandle, ISummaryTree } from "@fluidframework/driver-definitions";
|
|
7
|
+
import type {
|
|
8
8
|
FetchSource,
|
|
9
9
|
IDocumentStorageService,
|
|
10
10
|
IDocumentStorageServicePolicies,
|
|
@@ -36,6 +36,7 @@ export class DocumentStorageServiceProxy implements IDocumentStorageService {
|
|
|
36
36
|
public async getSnapshotTree(
|
|
37
37
|
version?: IVersion,
|
|
38
38
|
scenarioName?: string,
|
|
39
|
+
// eslint-disable-next-line @rushstack/no-new-null
|
|
39
40
|
): Promise<ISnapshotTree | null> {
|
|
40
41
|
return this.internalStorageService.getSnapshotTree(version, scenarioName);
|
|
41
42
|
}
|
|
@@ -50,6 +51,7 @@ export class DocumentStorageServiceProxy implements IDocumentStorageService {
|
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
public async getVersions(
|
|
54
|
+
// eslint-disable-next-line @rushstack/no-new-null
|
|
53
55
|
versionId: string | null,
|
|
54
56
|
count: number,
|
|
55
57
|
scenarioName?: string,
|
package/src/error.ts
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
DriverErrorTypes,
|
|
8
|
-
IDriverErrorBase,
|
|
8
|
+
type IDriverErrorBase,
|
|
9
9
|
} from "@fluidframework/driver-definitions/internal";
|
|
10
|
-
import { IFluidErrorBase, LoggingError } from "@fluidframework/telemetry-utils/internal";
|
|
10
|
+
import { type IFluidErrorBase, LoggingError } from "@fluidframework/telemetry-utils/internal";
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Error indicating an API is being used improperly resulting in an invalid operation.
|
package/src/index.ts
CHANGED
|
@@ -18,7 +18,7 @@ export {
|
|
|
18
18
|
createGenericNetworkError,
|
|
19
19
|
createWriteError,
|
|
20
20
|
DeltaStreamConnectionForbiddenError,
|
|
21
|
-
DriverErrorTelemetryProps,
|
|
21
|
+
type DriverErrorTelemetryProps,
|
|
22
22
|
FluidInvalidSchemaError,
|
|
23
23
|
GenericNetworkError,
|
|
24
24
|
getRetryDelayFromError,
|
|
@@ -43,9 +43,9 @@ export {
|
|
|
43
43
|
export { PrefetchDocumentStorageService } from "./prefetchDocumentStorageService.js";
|
|
44
44
|
export { RateLimiter } from "./rateLimiter.js";
|
|
45
45
|
export { readAndParse } from "./readAndParse.js";
|
|
46
|
-
export { calculateMaxWaitTime, IProgress, runWithRetry } from "./runWithRetry.js";
|
|
46
|
+
export { calculateMaxWaitTime, type IProgress, runWithRetry } from "./runWithRetry.js";
|
|
47
47
|
export {
|
|
48
|
-
CombinedAppAndProtocolSummary,
|
|
48
|
+
type CombinedAppAndProtocolSummary,
|
|
49
49
|
getDocAttributesFromProtocolSummary,
|
|
50
50
|
getQuorumValuesFromProtocolSummary,
|
|
51
51
|
isCombinedAppAndProtocolSummary,
|
|
@@ -53,7 +53,7 @@ export {
|
|
|
53
53
|
export { convertSummaryTreeToSnapshotITree } from "./treeConversions.js";
|
|
54
54
|
export {
|
|
55
55
|
applyStorageCompression,
|
|
56
|
-
ICompressionStorageConfig,
|
|
56
|
+
type ICompressionStorageConfig,
|
|
57
57
|
SummaryCompressionAlgorithm,
|
|
58
58
|
blobHeadersBlobName,
|
|
59
59
|
} from "./adapters/index.js";
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { IRequest } from "@fluidframework/core-interfaces";
|
|
6
|
+
import type { IRequest } from "@fluidframework/core-interfaces";
|
|
7
7
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
8
8
|
import {
|
|
9
9
|
DriverHeader,
|
|
10
|
-
IResolvedUrl,
|
|
11
|
-
IUrlResolver,
|
|
10
|
+
type IResolvedUrl,
|
|
11
|
+
type IUrlResolver,
|
|
12
12
|
} from "@fluidframework/driver-definitions/internal";
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -51,11 +51,11 @@ export class InsecureUrlResolver implements IUrlResolver {
|
|
|
51
51
|
// If hosts match then we use the local tenant information. Otherwise we make a REST call out to the hosting
|
|
52
52
|
// service using our bearer token.
|
|
53
53
|
if (this.isForNodeTest) {
|
|
54
|
-
const [, documentId, tmpRelativePath] = parsedUrl.pathname.
|
|
54
|
+
const [, documentId, tmpRelativePath] = parsedUrl.pathname.slice(1).split("/");
|
|
55
55
|
const relativePath = tmpRelativePath ?? "";
|
|
56
56
|
return this.resolveHelper(documentId, relativePath, parsedUrl.search);
|
|
57
57
|
} else if (parsedUrl.host === window.location.host) {
|
|
58
|
-
const fullPath = parsedUrl.pathname.
|
|
58
|
+
const fullPath = parsedUrl.pathname.slice(1);
|
|
59
59
|
const documentId = fullPath.split("/")[0];
|
|
60
60
|
const documentRelativePath = fullPath.slice(documentId.length);
|
|
61
61
|
return this.resolveHelper(documentId, documentRelativePath);
|
|
@@ -142,13 +142,13 @@ export class InsecureUrlResolver implements IUrlResolver {
|
|
|
142
142
|
relativeUrl: string,
|
|
143
143
|
): Promise<string> {
|
|
144
144
|
const parsedUrl = new URL(resolvedUrl.url);
|
|
145
|
-
const
|
|
145
|
+
const documentId = (parsedUrl.pathname?.split("/") ?? [])[2];
|
|
146
146
|
|
|
147
147
|
assert(!!documentId, 0x273 /* "Invalid document id from parsed URL" */);
|
|
148
148
|
|
|
149
149
|
let url = relativeUrl;
|
|
150
150
|
if (url.startsWith("/")) {
|
|
151
|
-
url = url.
|
|
151
|
+
url = url.slice(1);
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
return `${this.hostUrl}/${encodeURIComponent(this.tenantId)}/${encodeURIComponent(
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
-
ISequencedDocumentMessage,
|
|
8
|
-
IDocumentMessage,
|
|
7
|
+
type ISequencedDocumentMessage,
|
|
8
|
+
type IDocumentMessage,
|
|
9
9
|
MessageType,
|
|
10
10
|
} from "@fluidframework/driver-definitions/internal";
|
|
11
11
|
|
|
@@ -20,6 +20,8 @@ export function isRuntimeMessage(message: { type: string }): boolean {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
+
* Whether the message can be coalesced by the relay service.
|
|
24
|
+
*
|
|
23
25
|
* @privateRemarks ADO #1385: To be moved to packages/protocol-base/src/protocol.ts
|
|
24
26
|
* @internal
|
|
25
27
|
*/
|
package/src/network.ts
CHANGED
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { ITelemetryBaseProperties } from "@fluidframework/core-interfaces";
|
|
6
|
+
import type { ITelemetryBaseProperties } from "@fluidframework/core-interfaces";
|
|
7
7
|
import {
|
|
8
|
-
IAuthorizationError,
|
|
9
|
-
ILocationRedirectionError,
|
|
10
|
-
IResolvedUrl,
|
|
11
|
-
IThrottlingWarning,
|
|
12
8
|
DriverErrorTypes,
|
|
13
|
-
|
|
9
|
+
type IAuthorizationError,
|
|
10
|
+
type ILocationRedirectionError,
|
|
11
|
+
type IResolvedUrl,
|
|
12
|
+
type IThrottlingWarning,
|
|
13
|
+
type IDriverErrorBase,
|
|
14
14
|
} from "@fluidframework/driver-definitions/internal";
|
|
15
|
-
import { IFluidErrorBase, LoggingError } from "@fluidframework/telemetry-utils/internal";
|
|
15
|
+
import { type IFluidErrorBase, LoggingError } from "@fluidframework/telemetry-utils/internal";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @internal
|
|
@@ -226,6 +226,8 @@ export class ThrottlingError
|
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
/**
|
|
229
|
+
* Creates a non-retryable write error.
|
|
230
|
+
*
|
|
229
231
|
* @internal
|
|
230
232
|
*/
|
|
231
233
|
export const createWriteError = (
|
|
@@ -235,6 +237,8 @@ export const createWriteError = (
|
|
|
235
237
|
new NonRetryableError(message, DriverErrorTypes.writeError, props);
|
|
236
238
|
|
|
237
239
|
/**
|
|
240
|
+
* Creates a generic network error, either throttling or non-throttling based on the provided retry information.
|
|
241
|
+
*
|
|
238
242
|
* @internal
|
|
239
243
|
*/
|
|
240
244
|
export function createGenericNetworkError(
|
|
@@ -254,18 +258,28 @@ export function createGenericNetworkError(
|
|
|
254
258
|
* @param error - The error to inspect for ability to retry
|
|
255
259
|
* @internal
|
|
256
260
|
*/
|
|
257
|
-
export const canRetryOnError = (error:
|
|
261
|
+
export const canRetryOnError = (error: unknown): boolean =>
|
|
262
|
+
typeof error === "object" &&
|
|
263
|
+
error !== null &&
|
|
264
|
+
(error as { canRetry?: boolean }).canRetry === true;
|
|
258
265
|
|
|
259
266
|
/**
|
|
260
267
|
* Check retryAfterSeconds property on error
|
|
261
268
|
* @internal
|
|
262
269
|
*/
|
|
263
|
-
export const getRetryDelaySecondsFromError = (error:
|
|
264
|
-
error
|
|
270
|
+
export const getRetryDelaySecondsFromError = (error: unknown): number | undefined => {
|
|
271
|
+
if (typeof error === "object" && error !== null) {
|
|
272
|
+
const retryAfterSeconds = (error as { retryAfterSeconds?: unknown }).retryAfterSeconds;
|
|
273
|
+
return typeof retryAfterSeconds === "number" ? retryAfterSeconds : undefined;
|
|
274
|
+
}
|
|
275
|
+
return undefined;
|
|
276
|
+
};
|
|
265
277
|
|
|
266
278
|
/**
|
|
267
279
|
* Check retryAfterSeconds property on error and convert to ms
|
|
268
280
|
* @internal
|
|
269
281
|
*/
|
|
270
|
-
export const getRetryDelayFromError = (error:
|
|
271
|
-
|
|
282
|
+
export const getRetryDelayFromError = (error: unknown): number | undefined => {
|
|
283
|
+
const retryAfterSeconds = getRetryDelaySecondsFromError(error);
|
|
284
|
+
return retryAfterSeconds === undefined ? undefined : retryAfterSeconds * 1000;
|
|
285
|
+
};
|
package/src/networkUtils.ts
CHANGED
|
@@ -3,29 +3,37 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type {
|
|
7
|
-
|
|
6
|
+
import type {
|
|
7
|
+
ITelemetryErrorEventExt,
|
|
8
|
+
ITelemetryLoggerExt,
|
|
9
|
+
} from "@fluidframework/telemetry-utils/internal";
|
|
8
10
|
|
|
9
11
|
import { OnlineStatus, canRetryOnError, isOnline } from "./network.js";
|
|
10
12
|
|
|
11
13
|
/**
|
|
14
|
+
* Logs a network failure with additional context about online status and retry capability for the provided event.
|
|
15
|
+
*
|
|
12
16
|
* @internal
|
|
13
17
|
*/
|
|
14
18
|
export function logNetworkFailure(
|
|
15
19
|
logger: ITelemetryLoggerExt,
|
|
16
20
|
event: ITelemetryErrorEventExt,
|
|
17
|
-
error?:
|
|
21
|
+
error?: unknown,
|
|
18
22
|
): void {
|
|
19
23
|
const newEvent = { ...event };
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
// TODO: better typing
|
|
26
|
+
const errorOnlineProp = (error as { online?: unknown })?.online;
|
|
22
27
|
newEvent.online =
|
|
23
28
|
typeof errorOnlineProp === "string" ? errorOnlineProp : OnlineStatus[isOnline()];
|
|
24
29
|
|
|
25
30
|
if (typeof navigator === "object" && navigator !== null) {
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any -- TODO: use a real type
|
|
26
32
|
const nav = navigator as any;
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
27
34
|
const connection = nav.connection ?? nav.mozConnection ?? nav.webkitConnection;
|
|
28
35
|
if (connection !== null && typeof connection === "object") {
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
29
37
|
newEvent.connectionType = connection.type;
|
|
30
38
|
}
|
|
31
39
|
}
|
package/src/packageVersion.ts
CHANGED
package/src/parallelRequests.ts
CHANGED
|
@@ -4,16 +4,16 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { performanceNow } from "@fluid-internal/client-utils";
|
|
7
|
-
import { ITelemetryBaseProperties } from "@fluidframework/core-interfaces";
|
|
7
|
+
import type { ITelemetryBaseProperties } from "@fluidframework/core-interfaces";
|
|
8
8
|
import { assert, Deferred } from "@fluidframework/core-utils/internal";
|
|
9
|
-
import {
|
|
9
|
+
import type {
|
|
10
10
|
IDeltasFetchResult,
|
|
11
11
|
IStream,
|
|
12
12
|
IStreamResult,
|
|
13
13
|
ISequencedDocumentMessage,
|
|
14
14
|
} from "@fluidframework/driver-definitions/internal";
|
|
15
15
|
import {
|
|
16
|
-
ITelemetryLoggerExt,
|
|
16
|
+
type ITelemetryLoggerExt,
|
|
17
17
|
PerformanceEvent,
|
|
18
18
|
} from "@fluidframework/telemetry-utils/internal";
|
|
19
19
|
|
|
@@ -164,10 +164,8 @@ export class ParallelRequests<T> {
|
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
const from = this.latestRequested;
|
|
167
|
-
if (this.to !== undefined) {
|
|
168
|
-
|
|
169
|
-
return undefined;
|
|
170
|
-
}
|
|
167
|
+
if (this.to !== undefined && this.to <= from) {
|
|
168
|
+
return undefined;
|
|
171
169
|
}
|
|
172
170
|
|
|
173
171
|
// this.latestRequested
|
|
@@ -237,7 +235,7 @@ export class ParallelRequests<T> {
|
|
|
237
235
|
// If it pops into our view a lot, we would need to reconsider how we approach it.
|
|
238
236
|
// Note that this is not visible to user other than potentially not hitting 100% of
|
|
239
237
|
// what we can in perf domain.
|
|
240
|
-
if (payload.length
|
|
238
|
+
if (payload.length > 0) {
|
|
241
239
|
this.logger.sendErrorEvent({
|
|
242
240
|
eventName: "ParallelRequests_GotExtra",
|
|
243
241
|
from,
|
|
@@ -255,7 +253,25 @@ export class ParallelRequests<T> {
|
|
|
255
253
|
const length = payload.length;
|
|
256
254
|
let fullChunk = requestedLength <= length; // we can possible get more than we asked.
|
|
257
255
|
|
|
258
|
-
if (length
|
|
256
|
+
if (length === 0) {
|
|
257
|
+
// 1. empty (partial) chunks should not be returned by various caching / adapter layers -
|
|
258
|
+
// they should fall back to next layer. This might be important invariant to hold to ensure
|
|
259
|
+
// that we are less likely have bugs where such layer would keep returning empty partial
|
|
260
|
+
// result on each call.
|
|
261
|
+
// 2. Current invariant is that callback does retries until it gets something,
|
|
262
|
+
// with the goal of failing if zero data is retrieved in given amount of time.
|
|
263
|
+
// This is very specific property of storage / ops, so this logic is not here, but given only
|
|
264
|
+
// one user of this class, we assert that to catch issues earlier.
|
|
265
|
+
// These invariant can be relaxed if needed.
|
|
266
|
+
assert(
|
|
267
|
+
!partial,
|
|
268
|
+
0x10f /* "empty/partial chunks should not be returned by caching" */,
|
|
269
|
+
);
|
|
270
|
+
assert(
|
|
271
|
+
!this.knewTo,
|
|
272
|
+
0x110 /* "callback should retry until valid fetch before it learns new boundary" */,
|
|
273
|
+
);
|
|
274
|
+
} else {
|
|
259
275
|
// We can get more than we asked for!
|
|
260
276
|
// This can screw up logic in dispatch!
|
|
261
277
|
// So push only batch size, and keep the rest for later - if conditions are favorable, we
|
|
@@ -274,24 +290,6 @@ export class ParallelRequests<T> {
|
|
|
274
290
|
const data = payload.splice(0, requestedLength);
|
|
275
291
|
this.results.set(from, data);
|
|
276
292
|
from += data.length;
|
|
277
|
-
} else {
|
|
278
|
-
// 1. empty (partial) chunks should not be returned by various caching / adapter layers -
|
|
279
|
-
// they should fall back to next layer. This might be important invariant to hold to ensure
|
|
280
|
-
// that we are less likely have bugs where such layer would keep returning empty partial
|
|
281
|
-
// result on each call.
|
|
282
|
-
// 2. Current invariant is that callback does retries until it gets something,
|
|
283
|
-
// with the goal of failing if zero data is retrieved in given amount of time.
|
|
284
|
-
// This is very specific property of storage / ops, so this logic is not here, but given only
|
|
285
|
-
// one user of this class, we assert that to catch issues earlier.
|
|
286
|
-
// These invariant can be relaxed if needed.
|
|
287
|
-
assert(
|
|
288
|
-
!partial,
|
|
289
|
-
0x10f /* "empty/partial chunks should not be returned by caching" */,
|
|
290
|
-
);
|
|
291
|
-
assert(
|
|
292
|
-
!this.knewTo,
|
|
293
|
-
0x110 /* "callback should retry until valid fetch before it learns new boundary" */,
|
|
294
|
-
);
|
|
295
293
|
}
|
|
296
294
|
|
|
297
295
|
if (!partial && !fullChunk) {
|
|
@@ -319,7 +317,7 @@ export class ParallelRequests<T> {
|
|
|
319
317
|
if (to === this.latestRequested) {
|
|
320
318
|
// we can go after full chunk at the end if we received partial chunk, or more than asked
|
|
321
319
|
// Also if we got more than we asked to, we can actually use those ops!
|
|
322
|
-
while (payload.length
|
|
320
|
+
while (payload.length > 0) {
|
|
323
321
|
const data = payload.splice(0, requestedLength);
|
|
324
322
|
this.results.set(from, data);
|
|
325
323
|
from += data.length;
|
|
@@ -358,7 +356,7 @@ export class Queue<T> implements IStream<T> {
|
|
|
358
356
|
this.pushCore(Promise.resolve({ done: false, value }));
|
|
359
357
|
}
|
|
360
358
|
|
|
361
|
-
public pushError(error:
|
|
359
|
+
public pushError(error: unknown): void {
|
|
362
360
|
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
|
|
363
361
|
this.pushCore(Promise.reject(error));
|
|
364
362
|
this.done = true;
|
|
@@ -445,7 +443,7 @@ async function getSingleOpBatch(
|
|
|
445
443
|
|
|
446
444
|
// If we got messages back, return them. Return regardless of whether we got messages back if we didn't
|
|
447
445
|
// specify a "to", since we don't have an expectation of how many to receive.
|
|
448
|
-
if (messages.length
|
|
446
|
+
if (messages.length > 0 || !strongTo) {
|
|
449
447
|
// Report this event if we waited to fetch ops due to being offline or throttling.
|
|
450
448
|
telemetryEvent?.end({
|
|
451
449
|
duration: totalRetryAfterTime,
|
|
@@ -670,6 +668,8 @@ export const emptyMessageStream: IStream<ISequencedDocumentMessage[]> = {
|
|
|
670
668
|
};
|
|
671
669
|
|
|
672
670
|
/**
|
|
671
|
+
* Creates a stream from the provided promise of messages.
|
|
672
|
+
*
|
|
673
673
|
* @internal
|
|
674
674
|
*/
|
|
675
675
|
export function streamFromMessages(
|
|
@@ -682,6 +682,7 @@ export function streamFromMessages(
|
|
|
682
682
|
return { done: true };
|
|
683
683
|
}
|
|
684
684
|
const value = await messages;
|
|
685
|
+
// eslint-disable-next-line require-atomic-updates
|
|
685
686
|
messages = undefined;
|
|
686
687
|
return value.length === 0 ? { done: true } : { done: false, value };
|
|
687
688
|
},
|
|
@@ -689,6 +690,8 @@ export function streamFromMessages(
|
|
|
689
690
|
}
|
|
690
691
|
|
|
691
692
|
/**
|
|
693
|
+
* Wraps the provided stream to observe values as they are read.
|
|
694
|
+
*
|
|
692
695
|
* @internal
|
|
693
696
|
*/
|
|
694
697
|
export function streamObserver<T>(
|