@fluidframework/container-runtime 2.0.0-internal.1.0.0.82628 → 2.0.0-internal.1.0.0.84253
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/batchTracker.js +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +16 -16
- package/dist/blobManager.js.map +1 -1
- package/dist/containerRuntime.d.ts +1 -38
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +51 -105
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +2 -3
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStores.d.ts +1 -1
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +2 -2
- package/dist/dataStores.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/runningSummarizer.d.ts +14 -0
- package/dist/runningSummarizer.d.ts.map +1 -1
- package/dist/runningSummarizer.js +25 -0
- package/dist/runningSummarizer.js.map +1 -1
- package/dist/summarizer.d.ts.map +1 -1
- package/dist/summarizer.js +33 -3
- package/dist/summarizer.js.map +1 -1
- package/dist/summaryGenerator.js +1 -1
- package/dist/summaryGenerator.js.map +1 -1
- package/lib/batchTracker.js +1 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +16 -16
- package/lib/blobManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +1 -38
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +51 -105
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +2 -3
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStores.d.ts +1 -1
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +2 -2
- package/lib/dataStores.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/runningSummarizer.d.ts +14 -0
- package/lib/runningSummarizer.d.ts.map +1 -1
- package/lib/runningSummarizer.js +25 -0
- package/lib/runningSummarizer.js.map +1 -1
- package/lib/summarizer.d.ts.map +1 -1
- package/lib/summarizer.js +35 -5
- package/lib/summarizer.js.map +1 -1
- package/lib/summaryGenerator.js +1 -1
- package/lib/summaryGenerator.js.map +1 -1
- package/package.json +27 -18
- package/src/batchTracker.ts +1 -1
- package/src/blobManager.ts +20 -16
- package/src/containerRuntime.ts +71 -155
- package/src/dataStore.ts +1 -4
- package/src/dataStores.ts +13 -13
- package/src/packageVersion.ts +1 -1
- package/src/runningSummarizer.ts +33 -1
- package/src/summarizer.ts +46 -10
- package/src/summaryGenerator.ts +1 -1
package/src/dataStores.ts
CHANGED
|
@@ -29,11 +29,11 @@ import {
|
|
|
29
29
|
ITelemetryContext,
|
|
30
30
|
} from "@fluidframework/runtime-definitions";
|
|
31
31
|
import {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
convertSnapshotTreeToSummaryTree,
|
|
33
|
+
convertToSummaryTree,
|
|
34
|
+
create404Response,
|
|
35
|
+
responseToException,
|
|
36
|
+
SummaryTreeBuilder,
|
|
37
37
|
} from "@fluidframework/runtime-utils";
|
|
38
38
|
import { ChildLogger, LoggingError, TelemetryDataTag } from "@fluidframework/telemetry-utils";
|
|
39
39
|
import { AttachState } from "@fluidframework/container-definitions";
|
|
@@ -56,10 +56,10 @@ import { GCNodeType } from "./garbageCollection";
|
|
|
56
56
|
|
|
57
57
|
type PendingAliasResolve = (success: boolean) => void;
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
/**
|
|
60
|
+
* This class encapsulates data store handling. Currently it is only used by the container runtime,
|
|
61
|
+
* but eventually could be hosted on any channel once we formalize the channel api boundary.
|
|
62
|
+
*/
|
|
63
63
|
export class DataStores implements IDisposable {
|
|
64
64
|
// Stores tracked by the Domain
|
|
65
65
|
private readonly pendingAttach = new Map<string, IAttachMessage>();
|
|
@@ -202,7 +202,7 @@ export class DataStores implements IDisposable {
|
|
|
202
202
|
return;
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
|
|
205
|
+
// If a non-local operation then go and create the object, otherwise mark it as officially attached.
|
|
206
206
|
if (this.alreadyProcessed(attachMessage.id)) {
|
|
207
207
|
// TODO: dataStoreId may require a different tag from PackageData #7488
|
|
208
208
|
const error = new DataCorruptionError(
|
|
@@ -362,7 +362,7 @@ export class DataStores implements IDisposable {
|
|
|
362
362
|
return context;
|
|
363
363
|
}
|
|
364
364
|
|
|
365
|
-
public _createFluidDataStoreContext(pkg: string[], id: string,
|
|
365
|
+
public _createFluidDataStoreContext(pkg: string[], id: string, props?: any) {
|
|
366
366
|
assert(!id.includes("/"), 0x30d /* Id cannot contain slashes */);
|
|
367
367
|
const context = new LocalFluidDataStoreContext({
|
|
368
368
|
id,
|
|
@@ -376,7 +376,7 @@ export class DataStores implements IDisposable {
|
|
|
376
376
|
),
|
|
377
377
|
makeLocallyVisibleFn: () => this.makeDataStoreLocallyVisible(id),
|
|
378
378
|
snapshotTree: undefined,
|
|
379
|
-
isRootDataStore:
|
|
379
|
+
isRootDataStore: false,
|
|
380
380
|
writeGCDataAtRoot: this.writeGCDataAtRoot,
|
|
381
381
|
disableIsolatedChannels: this.runtime.disableIsolatedChannels,
|
|
382
382
|
createProps: props,
|
|
@@ -481,7 +481,7 @@ export class DataStores implements IDisposable {
|
|
|
481
481
|
} else {
|
|
482
482
|
eventName = "attached";
|
|
483
483
|
}
|
|
484
|
-
for (const [,context] of this.contexts) {
|
|
484
|
+
for (const [, context] of this.contexts) {
|
|
485
485
|
// Fire only for bounded stores.
|
|
486
486
|
if (!this.contexts.isNotBound(context.id)) {
|
|
487
487
|
context.emit(eventName);
|
package/src/packageVersion.ts
CHANGED
package/src/runningSummarizer.ts
CHANGED
|
@@ -106,10 +106,10 @@ export class RunningSummarizer implements IDisposable {
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
public get disposed() { return this._disposed; }
|
|
109
|
-
|
|
110
109
|
private stopping = false;
|
|
111
110
|
private _disposed = false;
|
|
112
111
|
private summarizingLock: Promise<void> | undefined;
|
|
112
|
+
private refreshSummaryAckLock: Promise<void> | undefined;
|
|
113
113
|
private tryWhileSummarizing = false;
|
|
114
114
|
private readonly pendingAckTimer: PromiseTimer;
|
|
115
115
|
private heuristicRunner?: ISummarizeHeuristicRunner;
|
|
@@ -329,6 +329,31 @@ export class RunningSummarizer implements IDisposable {
|
|
|
329
329
|
this.initialized = true;
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
+
/**
|
|
333
|
+
* Blocks a new summarizer from running in case RefreshSummaryAck is being processed.
|
|
334
|
+
* Assumes that caller checked upfront for lack of concurrent action (this.refreshSummaryAckLock)
|
|
335
|
+
* before calling this API. I.e. caller is responsible for either erroring out or waiting on this promise.
|
|
336
|
+
* Note: The refreshSummaryAckLock makes sure no summarizer gets enqueued or processed
|
|
337
|
+
* until the refresh has completed. One can't rely uniquely on the summarizingLock as the
|
|
338
|
+
* refreshLatestSummaryAck also happens during the time summarizingLock !== undefined.
|
|
339
|
+
* Ex. Summarizer submits a summay + op and then waits for the Summary Ack to proceed
|
|
340
|
+
* with the refreshLatestSummaryAck and complete the summary.
|
|
341
|
+
* @param action - action to perform.
|
|
342
|
+
* @returns - result of action.
|
|
343
|
+
*/
|
|
344
|
+
public async lockedRefreshSummaryAckAction<T>(action: () => Promise<T>) {
|
|
345
|
+
assert(this.refreshSummaryAckLock === undefined,
|
|
346
|
+
0x396 /* Refresh Summary Ack - Caller is responsible for checking lock */);
|
|
347
|
+
|
|
348
|
+
const refreshSummaryAckLock = new Deferred<void>();
|
|
349
|
+
this.refreshSummaryAckLock = refreshSummaryAckLock.promise;
|
|
350
|
+
|
|
351
|
+
return action().finally(() => {
|
|
352
|
+
refreshSummaryAckLock.resolve();
|
|
353
|
+
this.refreshSummaryAckLock = undefined;
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
|
|
332
357
|
/**
|
|
333
358
|
* Runs single summary action that prevents any other concurrent actions.
|
|
334
359
|
* Assumes that caller checked upfront for lack of concurrent action (this.summarizingLock)
|
|
@@ -343,6 +368,8 @@ export class RunningSummarizer implements IDisposable {
|
|
|
343
368
|
this.summarizingLock = summarizingLock.promise;
|
|
344
369
|
|
|
345
370
|
this.summarizeCount++;
|
|
371
|
+
// Make sure the RefreshLatestSummaryAck is not being executed.
|
|
372
|
+
await this.refreshSummaryAckLock;
|
|
346
373
|
|
|
347
374
|
return action().finally(() => {
|
|
348
375
|
summarizingLock.resolve();
|
|
@@ -446,6 +473,10 @@ export class RunningSummarizer implements IDisposable {
|
|
|
446
473
|
});
|
|
447
474
|
await delay(delaySeconds * 1000);
|
|
448
475
|
}
|
|
476
|
+
|
|
477
|
+
// Make sure the refresh Summary Ack is not being executed.
|
|
478
|
+
await this.refreshSummaryAckLock;
|
|
479
|
+
|
|
449
480
|
// Note: no need to account for cancellationToken.waitCancelled here, as
|
|
450
481
|
// this is accounted SummaryGenerator.summarizeCore that controls receivedSummaryAckOrNack.
|
|
451
482
|
const resultSummarize = this.generator.summarize(summarizeProps, options, cancellationToken);
|
|
@@ -494,6 +525,7 @@ export class RunningSummarizer implements IDisposable {
|
|
|
494
525
|
// The heuristics are blocking concurrent summarize attempts.
|
|
495
526
|
throw new UsageError("Attempted to run an already-running summarizer on demand");
|
|
496
527
|
}
|
|
528
|
+
|
|
497
529
|
const result = this.trySummarizeOnce(
|
|
498
530
|
{ reason: `onDemand/${reason}` },
|
|
499
531
|
options,
|
package/src/summarizer.ts
CHANGED
|
@@ -8,9 +8,15 @@ import { Deferred } from "@fluidframework/common-utils";
|
|
|
8
8
|
import { ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
9
9
|
import { ILoader, LoaderHeader } from "@fluidframework/container-definitions";
|
|
10
10
|
import { UsageError } from "@fluidframework/container-utils";
|
|
11
|
-
import { DriverHeader } from "@fluidframework/driver-definitions";
|
|
11
|
+
import { DriverErrorType, DriverHeader } from "@fluidframework/driver-definitions";
|
|
12
12
|
import { requestFluidObject } from "@fluidframework/runtime-utils";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
ChildLogger,
|
|
15
|
+
IFluidErrorBase,
|
|
16
|
+
isFluidError,
|
|
17
|
+
LoggingError,
|
|
18
|
+
wrapErrorAndLog,
|
|
19
|
+
} from "@fluidframework/telemetry-utils";
|
|
14
20
|
import {
|
|
15
21
|
FluidObject,
|
|
16
22
|
IFluidHandleContext,
|
|
@@ -20,7 +26,7 @@ import {
|
|
|
20
26
|
import { ISummaryConfiguration } from "./containerRuntime";
|
|
21
27
|
import { ICancellableSummarizerController } from "./runWhileConnectedCoordinator";
|
|
22
28
|
import { summarizerClientType } from "./summarizerClientElection";
|
|
23
|
-
import { SummaryCollection } from "./summaryCollection";
|
|
29
|
+
import { IAckedSummary, SummaryCollection } from "./summaryCollection";
|
|
24
30
|
import { SummarizerHandle } from "./summarizerHandle";
|
|
25
31
|
import { RunningSummarizer } from "./runningSummarizer";
|
|
26
32
|
import {
|
|
@@ -361,22 +367,52 @@ export class Summarizer extends EventEmitter implements ISummarizer {
|
|
|
361
367
|
|
|
362
368
|
private async handleSummaryAcks() {
|
|
363
369
|
let refSequenceNumber = this.runtime.deltaManager.initialSequenceNumber;
|
|
370
|
+
let ack: IAckedSummary | undefined;
|
|
364
371
|
while (this.runningSummarizer) {
|
|
365
372
|
const summaryLogger = this.runningSummarizer.tryGetCorrelatedLogger(refSequenceNumber) ?? this.logger;
|
|
366
373
|
try {
|
|
367
|
-
|
|
374
|
+
// Initialize ack with undefined if exception happens inside of waitSummaryAck on second iteration,
|
|
375
|
+
// we record undefined, not previous handles.
|
|
376
|
+
ack = undefined;
|
|
377
|
+
ack = await this.summaryCollection.waitSummaryAck(refSequenceNumber);
|
|
368
378
|
refSequenceNumber = ack.summaryOp.referenceSequenceNumber;
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
379
|
+
const summaryOpHandle = ack.summaryOp.contents.handle;
|
|
380
|
+
const summaryAckHandle = ack.summaryAck.contents.handle;
|
|
381
|
+
// Make sure we block any summarizer from being executed/enqueued while
|
|
382
|
+
// executing the refreshLatestSummaryAck.
|
|
383
|
+
// https://dev.azure.com/fluidframework/internal/_workitems/edit/779
|
|
384
|
+
await this.runningSummarizer.lockedRefreshSummaryAckAction(async () =>
|
|
385
|
+
this.internalsProvider.refreshLatestSummaryAck(
|
|
386
|
+
summaryOpHandle,
|
|
387
|
+
summaryAckHandle,
|
|
388
|
+
refSequenceNumber,
|
|
389
|
+
summaryLogger,
|
|
390
|
+
).catch(async (error) => {
|
|
391
|
+
// If the error is 404, so maybe the fetched version no longer exists on server. We just
|
|
392
|
+
// ignore this error in that case, as that means we will have another summaryAck for the
|
|
393
|
+
// latest version with which we will refresh the state. However in case of single commit
|
|
394
|
+
// summary, we might me missing a summary ack, so in that case we are still fine as the
|
|
395
|
+
// code in `submitSummary` function in container runtime, will refresh the latest state
|
|
396
|
+
// by calling `refreshLatestSummaryAckFromServer` and we will be fine.
|
|
397
|
+
if (isFluidError(error)
|
|
398
|
+
&& error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError) {
|
|
399
|
+
summaryLogger.sendTelemetryEvent({
|
|
400
|
+
eventName: "HandleSummaryAckErrorIgnored",
|
|
401
|
+
referenceSequenceNumber: refSequenceNumber,
|
|
402
|
+
proposalHandle: summaryOpHandle,
|
|
403
|
+
ackHandle: summaryAckHandle,
|
|
404
|
+
}, error);
|
|
405
|
+
} else {
|
|
406
|
+
throw error;
|
|
407
|
+
}
|
|
408
|
+
}),
|
|
375
409
|
);
|
|
376
410
|
} catch (error) {
|
|
377
411
|
summaryLogger.sendErrorEvent({
|
|
378
412
|
eventName: "HandleSummaryAckError",
|
|
379
413
|
referenceSequenceNumber: refSequenceNumber,
|
|
414
|
+
handle: ack?.summaryOp?.contents?.handle,
|
|
415
|
+
ackHandle: ack?.summaryAck?.contents?.handle,
|
|
380
416
|
}, error);
|
|
381
417
|
}
|
|
382
418
|
refSequenceNumber++;
|
package/src/summaryGenerator.ts
CHANGED
|
@@ -420,7 +420,7 @@ export class SummaryGenerator {
|
|
|
420
420
|
nonRuntimeOpsSinceLastSummary: this.heuristicData.numNonRuntimeOps,
|
|
421
421
|
};
|
|
422
422
|
|
|
423
|
-
default: assert(true,
|
|
423
|
+
default: assert(true, 0x397 /* Unexpected summary stage */);
|
|
424
424
|
}
|
|
425
425
|
|
|
426
426
|
return initialProps;
|