Skip to content

Commit 5e28728

Browse files
authored
Restore failurePolicy (#760)
1 parent b751429 commit 5e28728

File tree

5 files changed

+107
-10
lines changed

5 files changed

+107
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Adds support for functions failure policies (#482)

spec/function-builder.spec.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,28 @@ describe('FunctionBuilder', () => {
8282
const fn = functions
8383
.runWith({
8484
timeoutSeconds: 90,
85+
failurePolicy: { retry: {} },
8586
memory: '256MB',
8687
})
8788
.auth.user()
8889
.onCreate((user) => user);
8990

9091
expect(fn.__trigger.availableMemoryMb).to.deep.equal(256);
9192
expect(fn.__trigger.timeout).to.deep.equal('90s');
93+
expect(fn.__trigger.failurePolicy).to.deep.equal({ retry: {} });
94+
});
95+
96+
it("should apply a default failure policy if it's aliased with `true`", () => {
97+
const fn = functions
98+
.runWith({
99+
failurePolicy: true,
100+
memory: '256MB',
101+
timeoutSeconds: 90,
102+
})
103+
.auth.user()
104+
.onCreate((user) => user);
105+
106+
expect(fn.__trigger.failurePolicy).to.deep.equal({ retry: {} });
92107
});
93108

94109
it('should allow both supported region and valid runtime options to be set', () => {
@@ -129,6 +144,22 @@ describe('FunctionBuilder', () => {
129144
}).to.throw(Error, 'TimeoutSeconds');
130145
});
131146

147+
it('should throw an error if user chooses a failurePolicy which is neither an object nor a boolean', () => {
148+
expect(() =>
149+
functions.runWith({
150+
failurePolicy: (1234 as unknown) as functions.RuntimeOptions['failurePolicy'],
151+
})
152+
).to.throw(Error, 'failurePolicy must be a boolean or an object');
153+
});
154+
155+
it('should throw an error if user chooses a failurePolicy.retry which is not an object', () => {
156+
expect(() =>
157+
functions.runWith({
158+
failurePolicy: { retry: (1234 as unknown) as object },
159+
})
160+
).to.throw(Error, 'failurePolicy.retry');
161+
});
162+
132163
it('should throw an error if user chooses an invalid memory allocation', () => {
133164
expect(() => {
134165
return functions.runWith({

src/cloud-functions.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,13 @@
2222

2323
import { Request, Response } from 'express';
2424
import * as _ from 'lodash';
25-
import { DeploymentOptions, Schedule } from './function-configuration';
2625
import { warn } from './logger';
26+
import {
27+
DEFAULT_FAILURE_POLICY,
28+
DeploymentOptions,
29+
FailurePolicy,
30+
Schedule,
31+
} from './function-configuration';
2732
export { Request, Response };
2833

2934
/** @hidden */
@@ -205,6 +210,7 @@ export namespace Change {
205210
if (json.fieldMask) {
206211
before = applyFieldMask(before, json.after, json.fieldMask);
207212
}
213+
208214
return Change.fromObjects(
209215
customizer(before || {}),
210216
customizer(json.after || {})
@@ -219,14 +225,16 @@ export namespace Change {
219225
) {
220226
const before = _.assign({}, after);
221227
const masks = fieldMask.split(',');
222-
_.forEach(masks, (mask) => {
228+
229+
masks.forEach((mask) => {
223230
const val = _.get(sparseBefore, mask);
224231
if (typeof val === 'undefined') {
225232
_.unset(before, mask);
226233
} else {
227234
_.set(before, mask, val);
228235
}
229236
});
237+
230238
return before;
231239
}
232240
}
@@ -256,6 +264,7 @@ export interface TriggerAnnotated {
256264
resource: string;
257265
service: string;
258266
};
267+
failurePolicy?: FailurePolicy;
259268
httpsTrigger?: {};
260269
labels?: { [key: string]: string };
261270
regions?: string[];
@@ -473,6 +482,18 @@ export function optionsToTrigger(options: DeploymentOptions) {
473482
if (options.regions) {
474483
trigger.regions = options.regions;
475484
}
485+
if (options.failurePolicy !== undefined) {
486+
switch (options.failurePolicy) {
487+
case false:
488+
trigger.failurePolicy = undefined;
489+
break;
490+
case true:
491+
trigger.failurePolicy = DEFAULT_FAILURE_POLICY;
492+
break;
493+
default:
494+
trigger.failurePolicy = options.failurePolicy;
495+
}
496+
}
476497
if (options.timeoutSeconds) {
477498
trigger.timeout = options.timeoutSeconds.toString() + 's';
478499
}

src/function-builder.ts

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,23 @@ function assertRuntimeOptionsValid(runtimeOptions: RuntimeOptions): boolean {
6666
`TimeoutSeconds must be between 0 and ${MAX_TIMEOUT_SECONDS}`
6767
);
6868
}
69+
if (runtimeOptions.failurePolicy !== undefined) {
70+
if (
71+
_.isBoolean(runtimeOptions.failurePolicy) === false &&
72+
_.isObjectLike(runtimeOptions.failurePolicy) === false
73+
) {
74+
throw new Error(`failurePolicy must be a boolean or an object.`);
75+
}
76+
77+
if (typeof runtimeOptions.failurePolicy === 'object') {
78+
if (
79+
_.isObjectLike(runtimeOptions.failurePolicy.retry) === false ||
80+
_.isEmpty(runtimeOptions.failurePolicy.retry) === false
81+
) {
82+
throw new Error('failurePolicy.retry must be an empty object.');
83+
}
84+
}
85+
}
6986
return true;
7087
}
7188

@@ -100,10 +117,14 @@ export function region(
100117
/**
101118
* Configure runtime options for the function.
102119
* @param runtimeOptions Object with three optional fields:
103-
* 1. memory: amount of memory to allocate to the function, possible values
104-
* are: '128MB', '256MB', '512MB', '1GB', and '2GB'.
105-
* 2. timeoutSeconds: timeout for the function in seconds, possible values are
106-
* 0 to 540.
120+
* 1. failurePolicy: failure policy of the function, with boolean `true` being
121+
* equivalent to providing an empty retry object.
122+
* 2. memory: amount of memory to allocate to the function, with possible
123+
* values being '128MB', '256MB', '512MB', '1GB', and '2GB'.
124+
* 3. timeoutSeconds: timeout for the function in seconds, with possible
125+
* values being 0 to 540.
126+
*
127+
* Value must not be null.
107128
*/
108129
export function runWith(runtimeOptions: RuntimeOptions): FunctionBuilder {
109130
if (assertRuntimeOptionsValid(runtimeOptions)) {
@@ -134,10 +155,14 @@ export class FunctionBuilder {
134155
/**
135156
* Configure runtime options for the function.
136157
* @param runtimeOptions Object with three optional fields:
137-
* 1. memory: amount of memory to allocate to the function, possible values
138-
* are: '128MB', '256MB', '512MB', '1GB', and '2GB'.
139-
* 2. timeoutSeconds: timeout for the function in seconds, possible values are
140-
* 0 to 540.
158+
* 1. failurePolicy: failure policy of the function, with boolean `true` being
159+
* equivalent to providing an empty retry object.
160+
* 2. memory: amount of memory to allocate to the function, with possible
161+
* values being '128MB', '256MB', '512MB', '1GB', and '2GB'.
162+
* 3. timeoutSeconds: timeout for the function in seconds, with possible
163+
* values being 0 to 540.
164+
*
165+
* Value must not be null.
141166
*/
142167
runWith(runtimeOptions: RuntimeOptions): FunctionBuilder {
143168
if (assertRuntimeOptionsValid(runtimeOptions)) {
@@ -147,6 +172,12 @@ export class FunctionBuilder {
147172
}
148173

149174
get https() {
175+
if (this.options.failurePolicy !== undefined) {
176+
console.warn(
177+
'RuntimeOptions.failurePolicy is not supported in https functions.'
178+
);
179+
}
180+
150181
return {
151182
/**
152183
* Handle HTTP requests.

src/function-configuration.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,20 @@ export interface Schedule {
6464
retryConfig?: ScheduleRetryConfig;
6565
}
6666

67+
export interface FailurePolicy {
68+
retry: {};
69+
}
70+
71+
export const DEFAULT_FAILURE_POLICY: FailurePolicy = {
72+
retry: {},
73+
};
74+
6775
export interface RuntimeOptions {
76+
/**
77+
* Failure policy of the function, with boolean `true` being equivalent to
78+
* providing an empty retry object.
79+
*/
80+
failurePolicy?: FailurePolicy | boolean;
6881
/**
6982
* Amount of memory to allocate to the function.
7083
*/

0 commit comments

Comments
 (0)