Skip to content

Commit

Permalink
Differentiate between epoch 409 and coherency 409 errors (#4874)
Browse files Browse the repository at this point in the history
  • Loading branch information
jatgarg authored Jan 22, 2021
1 parent ca8bea2 commit 23c1d41
Showing 1 changed file with 32 additions and 17 deletions.
49 changes: 32 additions & 17 deletions packages/drivers/odsp-driver/src/epochTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { assert } from "@fluidframework/common-utils";
import { ITelemetryLogger } from "@fluidframework/common-definitions";
import { fluidEpochMismatchError, OdspErrorType } from "@fluidframework/odsp-doclib-utils";
import { ThrottlingError } from "@fluidframework/driver-utils";
import { fetchAndParseAsJSONHelper, fetchHelper, IOdspResponse } from "./odspUtils";
import { ICacheEntry, IFileEntry, LocalPersistentCacheAdapter } from "./odspCache";
import { RateLimiter } from "./rateLimiter";
Expand Down Expand Up @@ -159,12 +160,7 @@ export class EpochTracker {
fetchType: FetchType,
fromCache: boolean = false,
) {
// If epoch is undefined, then don't compare it because initially for createNew or TreesLatest
// initializes this value. Sometimes response does not contain epoch as it is still in
// implementation phase at server side. In that case also, don't compare it with our epoch value.
if (this.fluidEpoch && epochFromResponse && (this.fluidEpoch !== epochFromResponse)) {
throwOdspNetworkError("Epoch Mismatch", fluidEpochMismatchError);
}
this.checkForEpochErrorCore(epochFromResponse);
if (epochFromResponse) {
if (this._fluidEpoch === undefined) {
this.logger.sendTelemetryEvent(
Expand All @@ -187,17 +183,36 @@ export class EpochTracker {
fromCache: boolean = false,
) {
if (error.errorType === OdspErrorType.epochVersionMismatch) {
const err = {
...error,
fromCache,
clientEpoch: this.fluidEpoch,
serverEpoch: epochFromResponse ?? undefined,
fetchType,
};
this.logger.sendErrorEvent({ eventName: "EpochVersionMismatch" }, err);
assert(!!this.fileEntry, "File Entry should be set to clear the cached entries!!");
// If the epoch mismatches, then clear all entries for such file entry from cache.
await this.persistedCache.removeEntries(this.fileEntry);
try {
// This will only throw if it is an epoch error.
this.checkForEpochErrorCore(epochFromResponse, error.errorMessage);
} catch (epochError) {
const err = {
...epochError,
fromCache,
clientEpoch: this.fluidEpoch,
fetchType,
};
this.logger.sendErrorEvent({ eventName: "EpochVersionMismatch" }, err);
assert(!!this.fileEntry, "File Entry should be set to clear the cached entries!!");
// If the epoch mismatches, then clear all entries for such file entry from cache.
await this.persistedCache.removeEntries(this.fileEntry);
throw epochError;
}
// If it was categorised as epoch error but the epoch returned in response matches with the client epoch
// then it was coherency 409, so rethrow it as throttling error so that it can retried. Default throttling
// time is 1s.
this.logger.sendErrorEvent({ eventName: "Coherency409" }, error);
throw new ThrottlingError(error.errorMessage, 1000, 429);
}
}

private checkForEpochErrorCore(epochFromResponse: string | null | undefined, message?: string) {
// If epoch is undefined, then don't compare it because initially for createNew or TreesLatest
// initializes this value. Sometimes response does not contain epoch as it is still in
// implementation phase at server side. In that case also, don't compare it with our epoch value.
if (this.fluidEpoch && epochFromResponse && (this.fluidEpoch !== epochFromResponse)) {
throwOdspNetworkError(message ?? "Epoch Mismatch", fluidEpochMismatchError);
}
}
}
Expand Down

0 comments on commit 23c1d41

Please sign in to comment.