Skip to content

Commit 60d4fba

Browse files
committed
Clean up error naming (#624)
1 parent 0d8ca9a commit 60d4fba

19 files changed

+93
-88
lines changed

src/LegacyFunctionLoader.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33

44
import { FunctionCallback } from '@azure/functions-core';
55
import { AzureFunctionsRpcMessages as rpc } from '../azure-functions-language-worker-protobuf/src/rpc';
6+
import { AzFuncSystemError } from './errors';
67
import { loadScriptFile } from './loadScriptFile';
78
import { PackageJson } from './parsers/parsePackageJson';
8-
import { InternalException } from './utils/InternalException';
99
import { nonNullProp } from './utils/nonNull';
1010
import { RegisteredFunction } from './WorkerChannel';
1111

@@ -40,7 +40,7 @@ export class LegacyFunctionLoader implements ILegacyFunctionLoader {
4040
callback: loadedFunction.callback.bind(loadedFunction.thisArg),
4141
};
4242
} else {
43-
throw new InternalException(`Function code for '${functionId}' is not loaded and cannot be invoked.`);
43+
throw new AzFuncSystemError(`Function code for '${functionId}' is not loaded and cannot be invoked.`);
4444
}
4545
}
4646
}
@@ -72,9 +72,9 @@ function getEntryPoint(f: any, entryPoint?: string): [FunctionCallback, unknown]
7272
'If multiple functions are exported, ' +
7373
"you must indicate the entry point, either by naming it 'run' or 'index', or by naming it " +
7474
"explicitly via the 'entryPoint' metadata property.";
75-
throw new InternalException(msg);
75+
throw new AzFuncSystemError(msg);
7676
} else if (typeof f !== 'function') {
77-
throw new InternalException(
77+
throw new AzFuncSystemError(
7878
'The resolved entry point is not a function and cannot be invoked by the functions runtime. Make sure the function has been correctly exported.'
7979
);
8080
}

src/Worker.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22
// Licensed under the MIT License.
33

44
import * as parseArgs from 'minimist';
5+
import { AzFuncSystemError, ensureErrorType } from './errors';
56
import { CreateGrpcEventStream } from './GrpcClient';
67
import { LegacyFunctionLoader } from './LegacyFunctionLoader';
78
import { setupCoreModule } from './setupCoreModule';
89
import { setupEventStream } from './setupEventStream';
910
import { startBlockedMonitor } from './utils/blockedMonitor';
10-
import { ensureErrorType } from './utils/ensureErrorType';
11-
import { InternalException } from './utils/InternalException';
1211
import { systemError, systemLog } from './utils/Logger';
1312
import { isEnvironmentVariableSet } from './utils/util';
1413
import { WorkerChannel } from './WorkerChannel';
@@ -27,7 +26,7 @@ export function startNodeWorker(args) {
2726
if (!requestId) debugInfo.push(`'requestId' is ${requestId}`);
2827
if (!grpcMaxMessageLength) debugInfo.push(`'grpcMaxMessageLength' is ${grpcMaxMessageLength}`);
2928

30-
throw new InternalException(`gRPC client connection info is missing or incorrect (${debugInfo.join(', ')}).`);
29+
throw new AzFuncSystemError(`gRPC client connection info is missing or incorrect (${debugInfo.join(', ')}).`);
3130
}
3231

3332
const connection = `${host}:${port}`;
@@ -38,7 +37,7 @@ export function startNodeWorker(args) {
3837
eventStream = CreateGrpcEventStream(connection, parseInt(grpcMaxMessageLength));
3938
} catch (err) {
4039
const error = ensureErrorType(err);
41-
error.isAzureFunctionsInternalException = true;
40+
error.isAzureFunctionsSystemError = true;
4241
error.message = 'Error creating GRPC event stream: ' + error.message;
4342
throw error;
4443
}
@@ -57,7 +56,7 @@ export function startNodeWorker(args) {
5756
process.on('uncaughtException', (err: unknown) => {
5857
const error = ensureErrorType(err);
5958
let errorMessage: string;
60-
if (error.isAzureFunctionsInternalException) {
59+
if (error.isAzureFunctionsSystemError) {
6160
errorMessage = `Worker ${workerId} uncaught exception: ${error.stack || err}`;
6261
} else {
6362
errorMessage = `Worker ${workerId} uncaught exception (learn more: https://go.microsoft.com/fwlink/?linkid=2097909 ): ${

src/WorkerChannel.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
import { FunctionCallback, HookCallback, HookContext, HookData, ProgrammingModel } from '@azure/functions-core';
55
import { AzureFunctionsRpcMessages as rpc } from '../azure-functions-language-worker-protobuf/src/rpc';
66
import { Disposable } from './Disposable';
7+
import { AzFuncRangeError, AzFuncSystemError, ensureErrorType } from './errors';
78
import { IEventStream } from './GrpcClient';
89
import { ILegacyFunctionLoader } from './LegacyFunctionLoader';
910
import { PackageJson, parsePackageJson } from './parsers/parsePackageJson';
10-
import { ensureErrorType } from './utils/ensureErrorType';
1111
import LogLevel = rpc.RpcLog.Level;
1212
import LogCategory = rpc.RpcLog.RpcLogCategory;
1313

@@ -27,7 +27,7 @@ export class WorkerChannel {
2727

2828
get hostVersion(): string {
2929
if (!this._hostVersion) {
30-
throw new Error('Trying to access hostVersion before it is set.');
30+
throw new AzFuncSystemError('Cannot access hostVersion before worker init');
3131
} else {
3232
return this._hostVersion;
3333
}
@@ -116,7 +116,7 @@ export class WorkerChannel {
116116
case 'appTerminate':
117117
return this.#appTerminateHooks;
118118
default:
119-
throw new RangeError(`Unrecognized hook "${hookName}"`);
119+
throw new AzFuncRangeError(`Unrecognized hook "${hookName}"`);
120120
}
121121
}
122122

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the MIT License.
33

4+
import { AzFuncRangeError } from '../../errors';
5+
46
export function handleDefaultEnumCase(data: undefined | null | string, typeName: string): undefined | null {
57
switch (data) {
68
case undefined:
79
return undefined;
810
case null:
911
return null;
1012
default:
11-
throw new RangeError(`Unexpected value "${data}" for type "${typeName}"`);
13+
throw new AzFuncRangeError(`Unexpected value "${data}" for type "${typeName}"`);
1214
}
1315
}

src/coreApi/registerFunction.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { FunctionCallback, FunctionMetadata } from '@azure/functions-core';
55
import { v4 as uuid } from 'uuid';
66
import { AzureFunctionsRpcMessages as rpc } from '../../azure-functions-language-worker-protobuf/src/rpc';
77
import { Disposable } from '../Disposable';
8-
import { InternalException } from '../utils/InternalException';
8+
import { AzFuncSystemError } from '../errors';
99
import { WorkerChannel } from '../WorkerChannel';
1010
import { fromCoreFunctionMetadata } from './converters/fromCoreFunctionMetadata';
1111

@@ -15,7 +15,7 @@ export function registerFunction(
1515
callback: FunctionCallback
1616
): Disposable {
1717
if (channel.hasIndexedFunctions) {
18-
throw new InternalException('A function can only be registered during app startup.');
18+
throw new AzFuncSystemError('A function can only be registered during app startup.');
1919
}
2020
const functionId = uuid();
2121

@@ -33,7 +33,7 @@ export function registerFunction(
3333

3434
return new Disposable(() => {
3535
if (channel.hasIndexedFunctions) {
36-
throw new InternalException('A function can only be disposed during app startup.');
36+
throw new AzFuncSystemError('A function can only be disposed during app startup.');
3737
} else {
3838
delete channel.functions[functionId];
3939
}

src/errors.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
export interface AzFuncError {
5+
/**
6+
* System errors can be tracked in our telemetry
7+
* User errors cannot be tracked in our telemetry because they could have user information (users can still track it themselves in their app insights resource)
8+
*/
9+
isAzureFunctionsSystemError: boolean;
10+
}
11+
12+
export class AzFuncSystemError extends Error {
13+
isAzureFunctionsSystemError = true;
14+
}
15+
16+
export class AzFuncTypeError extends TypeError implements AzFuncError {
17+
isAzureFunctionsSystemError = true;
18+
}
19+
20+
export class AzFuncRangeError extends RangeError implements AzFuncError {
21+
isAzureFunctionsSystemError = true;
22+
}
23+
24+
export class ReadOnlyError extends AzFuncTypeError {
25+
constructor(propertyName: string) {
26+
super(`Cannot assign to read only property '${propertyName}'`);
27+
}
28+
}
29+
30+
export function ensureErrorType(err: unknown): Error & Partial<AzFuncError> {
31+
if (err instanceof Error) {
32+
return err;
33+
} else {
34+
let message: string;
35+
if (err === undefined || err === null) {
36+
message = 'Unknown error';
37+
} else if (typeof err === 'string') {
38+
message = err;
39+
} else if (typeof err === 'object') {
40+
message = JSON.stringify(err);
41+
} else {
42+
message = String(err);
43+
}
44+
return new Error(message);
45+
}
46+
}
47+
48+
/**
49+
* This is mostly for callbacks where `null` or `undefined` indicates there is no error
50+
* By contrast, anything thrown/caught is assumed to be an error regardless of what it is
51+
*/
52+
export function isError(err: unknown): boolean {
53+
return err !== null && err !== undefined;
54+
}

src/eventHandlers/FunctionLoadHandler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Licensed under the MIT License.
33

44
import { AzureFunctionsRpcMessages as rpc } from '../../azure-functions-language-worker-protobuf/src/rpc';
5-
import { ensureErrorType } from '../utils/ensureErrorType';
5+
import { ensureErrorType } from '../errors';
66
import { nonNullProp } from '../utils/nonNull';
77
import { WorkerChannel } from '../WorkerChannel';
88
import { EventHandler } from './EventHandler';
@@ -27,7 +27,7 @@ export class FunctionLoadHandler extends EventHandler<'functionLoadRequest', 'fu
2727
await channel.legacyFunctionLoader.load(functionId, metadata, channel.packageJson);
2828
} catch (err) {
2929
const error = ensureErrorType(err);
30-
error.isAzureFunctionsInternalException = true;
30+
error.isAzureFunctionsSystemError = true;
3131
error.message = `Worker was unable to load function ${metadata.name}: '${error.message}'`;
3232
throw error;
3333
}

src/eventHandlers/InvocationHandler.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ import { fromCoreInvocationResponse } from '../coreApi/converters/fromCoreInvoca
1818
import { fromCoreLogCategory, fromCoreLogLevel } from '../coreApi/converters/fromCoreStatusResult';
1919
import { toCoreFunctionMetadata } from '../coreApi/converters/toCoreFunctionMetadata';
2020
import { toCoreInvocationRequest } from '../coreApi/converters/toCoreInvocationRequest';
21-
import { isError } from '../utils/ensureErrorType';
21+
import { isError, ReadOnlyError } from '../errors';
2222
import { nonNullProp } from '../utils/nonNull';
23-
import { ReadOnlyError } from '../utils/ReadOnlyError';
2423
import { WorkerChannel } from '../WorkerChannel';
2524
import { EventHandler } from './EventHandler';
2625

src/eventHandlers/WorkerInitHandler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import { access, constants } from 'fs';
55
import * as path from 'path';
66
import { AzureFunctionsRpcMessages as rpc } from '../../azure-functions-language-worker-protobuf/src/rpc';
77
import { version as workerVersion } from '../constants';
8+
import { isError } from '../errors';
89
import { startApp } from '../startApp';
9-
import { isError } from '../utils/ensureErrorType';
1010
import { nonNullProp } from '../utils/nonNull';
1111
import { WorkerChannel } from '../WorkerChannel';
1212
import { EventHandler } from './EventHandler';

src/eventHandlers/terminateWorker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import { AppTerminateContext } from '@azure/functions-core';
55
import { AzureFunctionsRpcMessages as rpc } from '../../azure-functions-language-worker-protobuf/src/rpc';
6-
import { ReadOnlyError } from '../utils/ReadOnlyError';
6+
import { ReadOnlyError } from '../errors';
77
import { WorkerChannel } from '../WorkerChannel';
88
import LogCategory = rpc.RpcLog.RpcLogCategory;
99
import LogLevel = rpc.RpcLog.Level;

0 commit comments

Comments
 (0)