Expose new UsageError in DriverErrorType (#10950)
[AB#962](https://dev.azure.com/fluidframework/internal/_workitems/edit/962) For more information about how to contribute to this repo, visit [this page](https://github.com/microsoft/FluidFramework/blob/main/CONTRIBUTING.md). ## Description > We should not use strings, instead use values from one of the enums. Given that errors thrown is part of API contract (see such things are Container.close(), "closed" event), we need to ensure that clients can enumerate all known errorTypes different layers of our stack can throw. Anything unknown (i.e. not having shape of error our framework throws) is wrapped into generic error somewhere, so we maintain contract that client can enumerate all error types at complication time (assuming no dynamic code loading, of course). See https://github.com/microsoft/FluidFramework/pull/10692#discussion_r905243919 **Note**: This PR also makes simplifications around `DeltaStreamConnectionForbiddenError` and `container-utils>UsageError`
This commit is contained in:
Родитель
23c55c777e
Коммит
98f1ffa777
|
@ -11,6 +11,7 @@ import { ISequencedDocumentMessage } from '@fluidframework/protocol-definitions'
|
|||
import { ITelemetryLogger } from '@fluidframework/common-definitions';
|
||||
import { ITelemetryProperties } from '@fluidframework/common-definitions';
|
||||
import { IThrottlingWarning } from '@fluidframework/container-definitions';
|
||||
import { IUsageError } from '@fluidframework/container-definitions';
|
||||
import { LoggingError } from '@fluidframework/telemetry-utils';
|
||||
|
||||
// @public
|
||||
|
@ -70,10 +71,10 @@ export class ThrottlingWarning extends LoggingError implements IThrottlingWarnin
|
|||
}
|
||||
|
||||
// @public
|
||||
export class UsageError extends LoggingError implements IFluidErrorBase {
|
||||
export class UsageError extends LoggingError implements IUsageError, IFluidErrorBase {
|
||||
constructor(message: string);
|
||||
// (undocumented)
|
||||
readonly errorType = "usageError";
|
||||
readonly errorType = ContainerErrorType.usageError;
|
||||
}
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
|
|
|
@ -42,6 +42,7 @@ export enum DriverErrorType {
|
|||
throttlingError = "throttlingError",
|
||||
// (undocumented)
|
||||
unsupportedClientProtocolVersion = "unsupportedClientProtocolVersion",
|
||||
usageError = "usageError",
|
||||
writeError = "writeError"
|
||||
}
|
||||
|
||||
|
@ -181,7 +182,7 @@ export interface IDocumentStorageServicePolicies {
|
|||
// @public
|
||||
export interface IDriverBasicError extends IDriverErrorBase {
|
||||
// (undocumented)
|
||||
readonly errorType: DriverErrorType.genericError | DriverErrorType.fileNotFoundOrAccessDeniedError | DriverErrorType.offlineError | DriverErrorType.unsupportedClientProtocolVersion | DriverErrorType.writeError | DriverErrorType.fetchFailure | DriverErrorType.incorrectServerResponse | DriverErrorType.fileOverwrittenInStorage;
|
||||
readonly errorType: DriverErrorType.genericError | DriverErrorType.fileNotFoundOrAccessDeniedError | DriverErrorType.offlineError | DriverErrorType.unsupportedClientProtocolVersion | DriverErrorType.writeError | DriverErrorType.fetchFailure | DriverErrorType.incorrectServerResponse | DriverErrorType.fileOverwrittenInStorage | DriverErrorType.usageError;
|
||||
// (undocumented)
|
||||
readonly statusCode?: number;
|
||||
}
|
||||
|
|
|
@ -132,14 +132,14 @@ export function createGenericNetworkError(message: string, retryInfo: {
|
|||
export const createWriteError: (message: string, props: DriverErrorTelemetryProps) => NonRetryableError<DriverErrorType.writeError>;
|
||||
|
||||
// @public (undocumented)
|
||||
export class DeltaStreamConnectionForbiddenError extends LoggingError implements IFluidErrorBase {
|
||||
export class DeltaStreamConnectionForbiddenError extends LoggingError implements IDriverErrorBase, IFluidErrorBase {
|
||||
constructor(message: string, props: DriverErrorTelemetryProps);
|
||||
// (undocumented)
|
||||
readonly canRetry = false;
|
||||
// (undocumented)
|
||||
static readonly errorType: string;
|
||||
static readonly errorType = DriverErrorType.deltaStreamConnectionForbidden;
|
||||
// (undocumented)
|
||||
readonly errorType: string;
|
||||
readonly errorType = DriverErrorType.deltaStreamConnectionForbidden;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
|
@ -430,10 +430,12 @@ export class ThrottlingError extends LoggingError implements IThrottlingWarning,
|
|||
}
|
||||
|
||||
// @public
|
||||
export class UsageError extends LoggingError implements IFluidErrorBase {
|
||||
export class UsageError extends LoggingError implements IDriverErrorBase, IFluidErrorBase {
|
||||
constructor(message: string);
|
||||
// (undocumented)
|
||||
readonly errorType = "usageError";
|
||||
readonly canRetry = false;
|
||||
// (undocumented)
|
||||
readonly errorType = DriverErrorType.usageError;
|
||||
}
|
||||
|
||||
// @public
|
||||
|
|
|
@ -32,7 +32,7 @@ export enum ContainerErrorType {
|
|||
/**
|
||||
* Error indicating an API is being used improperly resulting in an invalid operation.
|
||||
*/
|
||||
usageError = "usageError",
|
||||
usageError = "usageError",
|
||||
|
||||
/**
|
||||
* Error indicating an client session has expired. Currently this only happens when GC is allowed on a document and
|
||||
|
@ -97,7 +97,7 @@ export interface IGenericError extends IErrorBase {
|
|||
/**
|
||||
* Error indicating an API is being used improperly resulting in an invalid operation.
|
||||
*/
|
||||
export interface IUsageError extends IErrorBase {
|
||||
export interface IUsageError extends IErrorBase {
|
||||
readonly errorType: ContainerErrorType.usageError;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,18 +71,24 @@ export enum DriverErrorType {
|
|||
* and storage / driver / loader detects such mismatch.
|
||||
* When it's hit, client needs to forget all the knowlege about this file and start over.
|
||||
*/
|
||||
fileOverwrittenInStorage = "fileOverwrittenInStorage",
|
||||
fileOverwrittenInStorage = "fileOverwrittenInStorage",
|
||||
|
||||
/**
|
||||
* The document is read-only and delta stream connection is forbidden.
|
||||
*/
|
||||
deltaStreamConnectionForbidden = "deltaStreamConnectionForbidden",
|
||||
/**
|
||||
* The document is read-only and delta stream connection is forbidden.
|
||||
*/
|
||||
deltaStreamConnectionForbidden = "deltaStreamConnectionForbidden",
|
||||
|
||||
/**
|
||||
* The location of file/container can change on server. So if the file location moves and we try to access the old
|
||||
* location, then this error is thrown to let the client know about the new location info.
|
||||
*/
|
||||
locationRedirection = "locationRedirection",
|
||||
|
||||
/**
|
||||
* Error indicating an API is being used improperly resulting in an invalid operation.
|
||||
* ! Should match the value of ContainerErrorType.usageError
|
||||
*/
|
||||
usageError = "usageError",
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,7 +142,8 @@ export interface IDriverBasicError extends IDriverErrorBase {
|
|||
| DriverErrorType.writeError
|
||||
| DriverErrorType.fetchFailure
|
||||
| DriverErrorType.incorrectServerResponse
|
||||
| DriverErrorType.fileOverwrittenInStorage;
|
||||
| DriverErrorType.fileOverwrittenInStorage
|
||||
| DriverErrorType.usageError;
|
||||
readonly statusCode?: number;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
"version": "2.0.0",
|
||||
"broken": {
|
||||
"TypeAliasDeclaration_OdspError": {
|
||||
"backCompat": false,
|
||||
"forwardCompat": false
|
||||
},
|
||||
"InterfaceDeclaration_IOdspError": {
|
||||
|
|
|
@ -397,6 +397,7 @@ declare function get_current_TypeAliasDeclaration_OdspError():
|
|||
declare function use_old_TypeAliasDeclaration_OdspError(
|
||||
use: TypeOnly<old.OdspError>);
|
||||
use_old_TypeAliasDeclaration_OdspError(
|
||||
// @ts-expect-error compatibility expected to be broken
|
||||
get_current_TypeAliasDeclaration_OdspError());
|
||||
|
||||
/*
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import fs from "fs";
|
||||
import { strict as assert } from "assert";
|
||||
import { IStream } from "@fluidframework/driver-definitions";
|
||||
import { DriverErrorType, IStream } from "@fluidframework/driver-definitions";
|
||||
import { IOdspResolvedUrl } from "@fluidframework/odsp-driver-definitions";
|
||||
import {
|
||||
IClient,
|
||||
|
@ -49,7 +49,7 @@ describe("Local Odsp driver", () => {
|
|||
);
|
||||
|
||||
async function assertThrowsUsageError(fn: () => Promise<any>) {
|
||||
await assert.rejects(fn, (e) => e.errorType === "usageError");
|
||||
await assert.rejects(fn, (e) => e.errorType === DriverErrorType.usageError);
|
||||
}
|
||||
|
||||
describe("Local Odsp document service factory", () => {
|
||||
|
|
|
@ -87,6 +87,10 @@
|
|||
},
|
||||
"typeValidation": {
|
||||
"version": "2.0.0",
|
||||
"broken": {}
|
||||
"broken": {
|
||||
"ClassDeclaration_UsageError": {
|
||||
"forwardCompat": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
IGenericError,
|
||||
IErrorBase,
|
||||
IThrottlingWarning,
|
||||
IUsageError,
|
||||
} from "@fluidframework/container-definitions";
|
||||
import {
|
||||
LoggingError,
|
||||
|
@ -72,9 +73,8 @@ export class ThrottlingWarning extends LoggingError implements IThrottlingWarnin
|
|||
}
|
||||
|
||||
/** Error indicating an API is being used improperly resulting in an invalid operation. */
|
||||
export class UsageError extends LoggingError implements IFluidErrorBase {
|
||||
// TODO: implement IUsageError once available
|
||||
readonly errorType = "usageError";
|
||||
export class UsageError extends LoggingError implements IUsageError, IFluidErrorBase {
|
||||
readonly errorType = ContainerErrorType.usageError;
|
||||
|
||||
constructor(
|
||||
message: string,
|
||||
|
|
|
@ -167,6 +167,7 @@ declare function get_old_ClassDeclaration_UsageError():
|
|||
declare function use_current_ClassDeclaration_UsageError(
|
||||
use: TypeOnly<current.UsageError>);
|
||||
use_current_ClassDeclaration_UsageError(
|
||||
// @ts-expect-error compatibility expected to be broken
|
||||
get_old_ClassDeclaration_UsageError());
|
||||
|
||||
/*
|
||||
|
|
|
@ -107,6 +107,21 @@
|
|||
"RemovedClassDeclaration_SummaryTreeAssembler": {
|
||||
"forwardCompat": false,
|
||||
"backCompat": false
|
||||
},
|
||||
"ClassDeclaration_ThrottlingError": {
|
||||
"backCompat": false
|
||||
},
|
||||
"ClassDeclaration_AuthorizationError": {
|
||||
"backCompat": false
|
||||
},
|
||||
"ClassDeclaration_GenericNetworkError": {
|
||||
"backCompat": false
|
||||
},
|
||||
"ClassDeclaration_DeltaStreamConnectionForbiddenError": {
|
||||
"forwardCompat": false
|
||||
},
|
||||
"ClassDeclaration_UsageError": {
|
||||
"forwardCompat": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
import { DriverErrorType, IDriverErrorBase } from "@fluidframework/driver-definitions";
|
||||
import { IFluidErrorBase, LoggingError } from "@fluidframework/telemetry-utils";
|
||||
|
||||
/** Error indicating an API is being used improperly resulting in an invalid operation. */
|
||||
export class UsageError extends LoggingError implements IFluidErrorBase {
|
||||
readonly errorType = "usageError";
|
||||
export class UsageError extends LoggingError implements IDriverErrorBase, IFluidErrorBase {
|
||||
readonly errorType = DriverErrorType.usageError;
|
||||
readonly canRetry = false;
|
||||
|
||||
constructor(
|
||||
message: string,
|
||||
|
|
|
@ -61,16 +61,9 @@ export class GenericNetworkError extends LoggingError implements IDriverErrorBas
|
|||
}
|
||||
}
|
||||
|
||||
// Todo GH #6214: Remove after next drive def bump. This is necessary as there is no
|
||||
// compatible way to augment an enum, as it can't be optional. So for now
|
||||
// we need to duplicate the value here. We likely need to rethink our
|
||||
// DriverErrorType strategy so that it supports extension with optional
|
||||
// value.
|
||||
const deltaStreamConnectionForbiddenStr = "deltaStreamConnectionForbidden";
|
||||
export class DeltaStreamConnectionForbiddenError extends LoggingError implements IFluidErrorBase {
|
||||
static readonly errorType: string =
|
||||
DriverErrorType[deltaStreamConnectionForbiddenStr] ?? deltaStreamConnectionForbiddenStr;
|
||||
readonly errorType: string = DeltaStreamConnectionForbiddenError.errorType;
|
||||
export class DeltaStreamConnectionForbiddenError extends LoggingError implements IDriverErrorBase, IFluidErrorBase {
|
||||
static readonly errorType = DriverErrorType.deltaStreamConnectionForbidden;
|
||||
readonly errorType = DeltaStreamConnectionForbiddenError.errorType;
|
||||
readonly canRetry = false;
|
||||
|
||||
constructor(message: string, props: DriverErrorTelemetryProps) {
|
||||
|
|
|
@ -35,6 +35,7 @@ declare function get_current_ClassDeclaration_AuthorizationError():
|
|||
declare function use_old_ClassDeclaration_AuthorizationError(
|
||||
use: TypeOnly<old.AuthorizationError>);
|
||||
use_old_ClassDeclaration_AuthorizationError(
|
||||
// @ts-expect-error compatibility expected to be broken
|
||||
get_current_ClassDeclaration_AuthorizationError());
|
||||
|
||||
/*
|
||||
|
@ -287,6 +288,7 @@ declare function get_old_ClassDeclaration_DeltaStreamConnectionForbiddenError():
|
|||
declare function use_current_ClassDeclaration_DeltaStreamConnectionForbiddenError(
|
||||
use: TypeOnly<current.DeltaStreamConnectionForbiddenError>);
|
||||
use_current_ClassDeclaration_DeltaStreamConnectionForbiddenError(
|
||||
// @ts-expect-error compatibility expected to be broken
|
||||
get_old_ClassDeclaration_DeltaStreamConnectionForbiddenError());
|
||||
|
||||
/*
|
||||
|
@ -443,6 +445,7 @@ declare function get_current_ClassDeclaration_GenericNetworkError():
|
|||
declare function use_old_ClassDeclaration_GenericNetworkError(
|
||||
use: TypeOnly<old.GenericNetworkError>);
|
||||
use_old_ClassDeclaration_GenericNetworkError(
|
||||
// @ts-expect-error compatibility expected to be broken
|
||||
get_current_ClassDeclaration_GenericNetworkError());
|
||||
|
||||
/*
|
||||
|
@ -1211,6 +1214,7 @@ declare function get_current_ClassDeclaration_ThrottlingError():
|
|||
declare function use_old_ClassDeclaration_ThrottlingError(
|
||||
use: TypeOnly<old.ThrottlingError>);
|
||||
use_old_ClassDeclaration_ThrottlingError(
|
||||
// @ts-expect-error compatibility expected to be broken
|
||||
get_current_ClassDeclaration_ThrottlingError());
|
||||
|
||||
/*
|
||||
|
@ -1223,6 +1227,7 @@ declare function get_old_ClassDeclaration_UsageError():
|
|||
declare function use_current_ClassDeclaration_UsageError(
|
||||
use: TypeOnly<current.UsageError>);
|
||||
use_current_ClassDeclaration_UsageError(
|
||||
// @ts-expect-error compatibility expected to be broken
|
||||
get_old_ClassDeclaration_UsageError());
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче