Skip to content

Commit

Permalink
Get rid of parameterized TContext
Browse files Browse the repository at this point in the history
  • Loading branch information
ejizba committed Aug 9, 2022
1 parent 8918f83 commit 48f2566
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 38 deletions.
4 changes: 2 additions & 2 deletions src/FunctionLoader.ts
Expand Up @@ -20,7 +20,7 @@ interface LoadedFunction {
thisArg: unknown;
}

export class FunctionLoader<TContext = unknown> {
export class FunctionLoader {
#loadedFunctions: { [k: string]: LoadedFunction | undefined } = {};

async load(functionId: string, metadata: rpc.IRpcFunctionMetadata, packageJson: PackageJson): Promise<void> {
Expand All @@ -38,7 +38,7 @@ export class FunctionLoader<TContext = unknown> {
return loadedFunction.metadata;
}

getCallback(functionId: string): FunctionCallback<TContext> {
getCallback(functionId: string): FunctionCallback {
const loadedFunction = this.#getLoadedFunction(functionId);
// `bind` is necessary to set the `this` arg, but it's also nice because it makes a clone of the function, preventing this invocation from affecting future invocations
return loadedFunction.callback.bind(loadedFunction.thisArg);
Expand Down
2 changes: 1 addition & 1 deletion src/WorkerChannel.ts
Expand Up @@ -27,7 +27,7 @@ export class WorkerChannel {
* this hook data is limited to the app-level scope and persisted only for app-level hooks
*/
appLevelOnlyHookData: HookData = {};
programmingModel?: ProgrammingModel<unknown>;
programmingModel?: ProgrammingModel;
#preInvocationHooks: HookCallback[] = [];
#postInvocationHooks: HookCallback[] = [];
#appStartHooks: HookCallback[] = [];
Expand Down
2 changes: 1 addition & 1 deletion src/eventHandlers/InvocationHandler.ts
Expand Up @@ -38,7 +38,7 @@ export class InvocationHandler extends EventHandler<'invocationRequest', 'invoca
// Log invocation details to ensure the invocation received by node worker
coreCtx.log(RpcLogLevel.Debug, RpcLogCategory.System, 'Received FunctionInvocationRequest');

const programmingModel: ProgrammingModel<unknown> = nonNullProp(channel, 'programmingModel');
const programmingModel: ProgrammingModel = nonNullProp(channel, 'programmingModel');
const invocModel = programmingModel.getInvocationModel(coreCtx);

const hookData: HookData = {};
Expand Down
2 changes: 1 addition & 1 deletion src/setupCoreModule.ts
Expand Up @@ -19,7 +19,7 @@ export function setupCoreModule(channel: WorkerChannel): void {
const coreApi = {
version: version,
registerHook: (hookName: string, callback: HookCallback) => channel.registerHook(hookName, callback),
setProgrammingModel: (programmingModel: ProgrammingModel<unknown>) => {
setProgrammingModel: (programmingModel: ProgrammingModel) => {
// Log when setting the programming model, except for the initial default one (partially because the grpc channels aren't fully setup at that time)
if (channel.programmingModel) {
channel.log({
Expand Down
17 changes: 12 additions & 5 deletions test/eventHandlers/InvocationHandler.test.ts
Expand Up @@ -321,15 +321,22 @@ namespace InputData {
};
}

type TestFunctionLoader = sinon.SinonStubbedInstance<
FunctionLoader & { getCallback(functionId: string): AzureFunction }
>;

describe('InvocationHandler', () => {
let stream: TestEventStream;
let loader: sinon.SinonStubbedInstance<FunctionLoader<Context>>;
let loader: TestFunctionLoader;
let channel: WorkerChannel;
let coreApi: typeof coreTypes;
let testDisposables: coreTypes.Disposable[] = [];

before(async () => {
({ stream, loader, channel } = beforeEventHandlerSuite());
const result = beforeEventHandlerSuite();
stream = result.stream;
loader = <TestFunctionLoader>result.loader;
channel = result.channel;
coreApi = await import('@azure/functions-core');
});

Expand Down Expand Up @@ -611,11 +618,11 @@ describe('InvocationHandler', () => {
loader.getRpcMetadata.returns(Binding.queue);

testDisposables.push(
coreApi.registerHook('preInvocation', (context: coreTypes.PreInvocationContext<Context>) => {
coreApi.registerHook('preInvocation', (context: coreTypes.PreInvocationContext) => {
expect(context.functionCallback).to.be.a('function');
context.functionCallback = async (invocContext: Context) => {
context.functionCallback = <coreTypes.FunctionCallback>(async (invocContext: Context) => {
invocContext.log('new function');
};
});
})
);

Expand Down
48 changes: 20 additions & 28 deletions types-core/index.d.ts
Expand Up @@ -14,22 +14,14 @@ declare module '@azure/functions-core' {
* Register a hook to interact with the lifecycle of Azure Functions.
* Hooks are executed in the order they were registered and will block execution if they throw an error
*/
function registerHook<TContext = unknown>(
hookName: 'preInvocation',
callback: PreInvocationCallback<TContext>
): Disposable;
function registerHook<TContext = unknown>(
hookName: 'postInvocation',
callback: PostInvocationCallback<TContext>
): Disposable;
function registerHook(hookName: 'preInvocation', callback: PreInvocationCallback): Disposable;
function registerHook(hookName: 'postInvocation', callback: PostInvocationCallback): Disposable;
function registerHook(hookName: 'appStart', callback: AppStartCallback): Disposable;
function registerHook(hookName: string, callback: HookCallback): Disposable;

type HookCallback = (context: HookContext) => void | Promise<void>;
type PreInvocationCallback<TContext = unknown> = (context: PreInvocationContext<TContext>) => void | Promise<void>;
type PostInvocationCallback<TContext = unknown> = (
context: PostInvocationContext<TContext>
) => void | Promise<void>;
type PreInvocationCallback = (context: PreInvocationContext) => void | Promise<void>;
type PostInvocationCallback = (context: PostInvocationContext) => void | Promise<void>;
type AppStartCallback = (context: AppStartContext) => void | Promise<void>;

type HookData = { [key: string]: any };
Expand All @@ -52,11 +44,11 @@ declare module '@azure/functions-core' {
* Context on a function that is about to be executed
* This object will be passed to all pre invocation hooks
*/
interface PreInvocationContext<TContext = unknown> extends HookContext {
interface PreInvocationContext extends HookContext {
/**
* The context object passed to the function
*/
invocationContext: TContext;
invocationContext: unknown;

/**
* The input values for this specific invocation. Changes to this array _will_ affect the inputs passed to your function
Expand All @@ -66,18 +58,18 @@ declare module '@azure/functions-core' {
/**
* The function callback for this specific invocation. Changes to this value _will_ affect the function itself
*/
functionCallback: FunctionCallback<TContext>;
functionCallback: FunctionCallback;
}

/**
* Context on a function that has just executed
* This object will be passed to all post invocation hooks
*/
interface PostInvocationContext<TContext = unknown> extends HookContext {
interface PostInvocationContext extends HookContext {
/**
* The context object passed to the function
*/
invocationContext: TContext;
invocationContext: unknown;

/**
* The input values for this specific invocation
Expand Down Expand Up @@ -141,19 +133,19 @@ declare module '@azure/functions-core' {
* Only one programming model can be set. The last programming model registered will be used
* If not explicitly set, a default programming model included with the worker will be used
*/
function setProgrammingModel<TContext>(programmingModel: ProgrammingModel<TContext>): void;
function setProgrammingModel(programmingModel: ProgrammingModel): void;

/**
* Returns the currently registered programming model
* If not explicitly set, a default programming model included with the worker will be used
*/
function getProgrammingModel<TContext>(): ProgrammingModel<TContext>;
function getProgrammingModel(): ProgrammingModel;

/**
* A set of information and methods that describe the model for handling a Node.js function app
* Currently, this is mainly focused on invocation
*/
interface ProgrammingModel<TContext> {
interface ProgrammingModel {
/**
* A name for this programming model, generally only used for tracking purposes
*/
Expand All @@ -167,7 +159,7 @@ declare module '@azure/functions-core' {
/**
* Returns a new instance of the invocation model for each invocation
*/
getInvocationModel(coreContext: CoreInvocationContext): InvocationModel<TContext>;
getInvocationModel(coreContext: CoreInvocationContext): InvocationModel;
}

/**
Expand Down Expand Up @@ -205,12 +197,12 @@ declare module '@azure/functions-core' {
/**
* A set of methods that describe the model for invoking a function
*/
interface InvocationModel<TContext> {
interface InvocationModel {
/**
* Returns the context object and inputs to be passed to all following invocation methods
* This is run before preInvocation hooks
*/
getArguments(): Promise<InvocationArguments<TContext>>;
getArguments(): Promise<InvocationArguments>;

/**
* The main method that executes the user's function callback
Expand All @@ -219,30 +211,30 @@ declare module '@azure/functions-core' {
* @param inputs The input array returned in `getArguments`, potentially modified by preInvocation hooks
* @param callback The function callback to be executed
*/
invokeFunction(context: TContext, inputs: unknown[], callback: FunctionCallback<TContext>): Promise<unknown>;
invokeFunction(context: unknown, inputs: unknown[], callback: FunctionCallback): Promise<unknown>;

/**
* Returns the invocation response to send back to the host
* This is run after postInvocation hooks
* @param context The context object created in `getArguments`
* @param result The result of the function callback, potentially modified by postInvocation hooks
*/
getResponse(context: TContext, result: unknown): Promise<RpcInvocationResponse>;
getResponse(context: unknown, result: unknown): Promise<RpcInvocationResponse>;
}

interface InvocationArguments<TContext> {
interface InvocationArguments {
/**
* This is usually the first argument passed to a function callback
*/
context: TContext;
context: unknown;

/**
* The remaining arguments passed to a function callback, generally describing the trigger/input bindings
*/
inputs: unknown[];
}

type FunctionCallback<TContext = unknown> = (context: TContext, ...inputs: unknown[]) => unknown;
type FunctionCallback = (context: unknown, ...inputs: unknown[]) => unknown;

// #region rpc types
interface RpcFunctionMetadata {
Expand Down

0 comments on commit 48f2566

Please sign in to comment.