Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add native support for warmup trigger #180

Merged
merged 8 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/addBindingName.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License.

export { InvocationContext } from './InvocationContext';
export { HttpRequest } from './http/HttpRequest';
export { HttpResponse } from './http/HttpResponse';
export { InvocationContext } from './InvocationContext';

const bindingCounts: Record<string, number> = {};
/**
* If the host spawns multiple workers, it expects the metadata (including binding name) to be the same accross workers
* If the host spawns multiple workers, it expects the metadata (including binding name) to be the same across workers.
* That means we need to generate binding names in a deterministic fashion, so we'll do that using a count
* There's a tiny risk users register bindings in a non-deterministic order (i.e. async race conditions), but it's okay considering the following:
* 1. We will track the count individually for each binding type. This makes the names more readable and reduces the chances a race condition will matter
Expand Down
5 changes: 5 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
StorageBlobFunctionOptions,
StorageQueueFunctionOptions,
TimerFunctionOptions,
WarmupFunctionOptions,
} from '@azure/functions';
import * as coreTypes from '@azure/functions-core';
import { CoreInvocationContext, FunctionCallback } from '@azure/functions-core';
Expand Down Expand Up @@ -145,6 +146,10 @@ export function cosmosDB(name: string, options: CosmosDBFunctionOptions): void {
generic(name, convertToGenericOptions(options, <any>trigger.cosmosDB));
}

export function warmup(name: string, options: WarmupFunctionOptions): void {
generic(name, convertToGenericOptions(options, trigger.warmup));
}

export function generic(name: string, options: GenericFunctionOptions): void {
if (!hasSetup) {
setup();
Expand Down
9 changes: 9 additions & 0 deletions src/trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import {
StorageQueueTriggerOptions,
TimerTrigger,
TimerTriggerOptions,
WarmupTrigger,
WarmupTriggerOptions,
} from '@azure/functions';
import { addBindingName } from './addBindingName';

Expand Down Expand Up @@ -90,6 +92,13 @@ export function cosmosDB(options: CosmosDBTriggerOptions): CosmosDBTrigger {
});
}

export function warmup(options: WarmupTriggerOptions): WarmupTrigger {
return addTriggerBindingName({
...options,
type: 'warmupTrigger',
});
}

export function generic(options: GenericTriggerOptions): FunctionTrigger {
return addTriggerBindingName(options);
}
Expand Down
13 changes: 13 additions & 0 deletions types/app.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { HttpFunctionOptions, HttpHandler, HttpMethodFunctionOptions } from './h
import { ServiceBusQueueFunctionOptions, ServiceBusTopicFunctionOptions } from './serviceBus';
import { StorageBlobFunctionOptions, StorageQueueFunctionOptions } from './storage';
import { TimerFunctionOptions } from './timer';
import { WarmupFunctionOptions } from './warmup';

/**
* Registers an http function in your app that will be triggered by making a request to the function url
Expand Down Expand Up @@ -143,6 +144,18 @@ export function eventGrid(name: string, options: EventGridFunctionOptions): void
*/
export function cosmosDB(name: string, options: CosmosDBFunctionOptions): void;

/**
castrodd marked this conversation as resolved.
Show resolved Hide resolved
* Registers a function in your app that will be triggered when an instance is added to scale a running function app.
* The warmup trigger is only called during scale-out operations, not during restarts or other non-scale startups.
* Make sure your logic can load all required dependencies without relying on the warmup trigger.
* Lazy loading is a good pattern to achieve this goal.
* The warmup trigger isn't available to apps running on the Consumption plan.
* For more information, please see the [Azure Functions warmup trigger documentation](https://learn.microsoft.com/azure/azure-functions/functions-bindings-warmup?tabs=isolated-process&pivots=programming-language-javascript).
* @param name The name of the function. The name must be unique within your app and will mostly be used for your own tracking purposes
castrodd marked this conversation as resolved.
Show resolved Hide resolved
* @param options Configuration options describing the inputs, outputs, and handler for this function
*/
export function warmup(name: string, options: WarmupFunctionOptions): void;

/**
* Registers a generic function in your app that will be triggered based on the type specified in `options.trigger.type`
* Use this method if your desired trigger type does not already have its own method
Expand Down
1 change: 1 addition & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export * from './storage';
export * from './table';
export * from './timer';
export * as trigger from './trigger';
export * from './warmup';

/**
* Void if no `return` output is registered
Expand Down
6 changes: 6 additions & 0 deletions types/trigger.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
StorageQueueTriggerOptions,
} from './storage';
import { TimerTrigger, TimerTriggerOptions } from './timer';
import { WarmupTrigger, WarmupTriggerOptions } from './warmup';

/**
* [Link to docs and examples](https://docs.microsoft.com/azure/azure-functions/functions-bindings-http-webhook-trigger?&pivots=programming-language-javascript)
Expand Down Expand Up @@ -66,6 +67,11 @@ export function eventGrid(options: EventGridTriggerOptions): EventGridTrigger;
*/
export function cosmosDB(options: CosmosDBTriggerOptions): CosmosDBTrigger;

/**
* [Link to docs and examples](https://learn.microsoft.com/azure/azure-functions/functions-bindings-warmup?tabs=isolated-process&pivots=programming-language-javascript)
*/
export function warmup(options: WarmupTriggerOptions): WarmupTrigger;

/**
* A generic option that can be used for any trigger type
* Use this method if your desired trigger type does not already have its own method
Expand Down
17 changes: 17 additions & 0 deletions types/warmup.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License.

import { FunctionOptions, FunctionResult, FunctionTrigger } from './index';
import { InvocationContext } from './InvocationContext';

export interface WarmupContextOptions {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Should be just WarmupContext without Options

export type WarmupHandler = (warmupContext: WarmupContextOptions, context: InvocationContext) => FunctionResult;

export interface WarmupFunctionOptions extends WarmupTriggerOptions, Partial<FunctionOptions> {
handler: WarmupHandler;

trigger?: WarmupTrigger;
}

export interface WarmupTriggerOptions {}
export type WarmupTrigger = FunctionTrigger & WarmupTriggerOptions;