@forge/events 0.0.0-experimental-416047f → 0.0.0-experimental-9b81865
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +143 -1
- package/out/__test__/invocationError.test.js +22 -7
- package/out/__test__/jobProgress.test.js +35 -26
- package/out/__test__/queue.test.js +46 -37
- package/out/__test__/utils.d.ts +1 -1
- package/out/__test__/utils.d.ts.map +1 -1
- package/out/__test__/utils.js +10 -6
- package/out/index.js +1 -2
- package/out/invocationError.d.ts +4 -0
- package/out/invocationError.d.ts.map +1 -1
- package/out/invocationError.js +11 -1
- package/out/invocationErrorCode.d.ts +6 -6
- package/out/invocationErrorCode.d.ts.map +1 -1
- package/out/invocationErrorCode.js +6 -6
- package/out/jobProgress.d.ts.map +1 -1
- package/out/jobProgress.js +8 -7
- package/out/queries.d.ts.map +1 -1
- package/out/queries.js +2 -1
- package/out/queue.d.ts.map +1 -1
- package/out/queue.js +8 -7
- package/out/retryOptions.d.ts +8 -5
- package/out/retryOptions.d.ts.map +1 -1
- package/out/retryOptions.js +6 -17
- package/out/validators.js +23 -14
- package/package.json +2 -2
- package/src/__test__/invocationError.test.ts +24 -7
- package/src/__test__/jobProgress.test.ts +31 -20
- package/src/__test__/queue.test.ts +40 -29
- package/src/__test__/utils.ts +1 -1
- package/src/invocationError.ts +16 -2
- package/src/invocationErrorCode.ts +6 -6
- package/src/jobProgress.ts +2 -1
- package/src/queue.ts +2 -1
- package/src/retryOptions.ts +9 -21
- package/tsconfig.tsbuildinfo +1 -1118
- package/out/__test__/retryOptions.test.d.ts +0 -2
- package/out/__test__/retryOptions.test.d.ts.map +0 -1
- package/out/__test__/retryOptions.test.js +0 -14
- package/src/__test__/retryOptions.test.ts +0 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invocationErrorCode.d.ts","sourceRoot":"","sources":["../src/invocationErrorCode.ts"],"names":[],"mappings":"AAAA,oBAAY,mBAAmB;IAC7B,sBAAsB,
|
|
1
|
+
{"version":3,"file":"invocationErrorCode.d.ts","sourceRoot":"","sources":["../src/invocationErrorCode.ts"],"names":[],"mappings":"AAAA,oBAAY,mBAAmB;IAC7B,sBAAsB,2BAA2B;IACjD,iBAAiB,sBAAsB;IACvC,+BAA+B,oCAAoC;IACnE,8BAA8B,mCAAmC;IACjE,8BAA8B,mCAAmC;IACjE,sBAAsB,2BAA2B;CAClD"}
|
|
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.InvocationErrorCode = void 0;
|
|
4
4
|
var InvocationErrorCode;
|
|
5
5
|
(function (InvocationErrorCode) {
|
|
6
|
-
InvocationErrorCode[
|
|
7
|
-
InvocationErrorCode[
|
|
8
|
-
InvocationErrorCode[
|
|
9
|
-
InvocationErrorCode[
|
|
10
|
-
InvocationErrorCode[
|
|
11
|
-
InvocationErrorCode[
|
|
6
|
+
InvocationErrorCode["FUNCTION_OUT_OF_MEMORY"] = "FUNCTION_OUT_OF_MEMORY";
|
|
7
|
+
InvocationErrorCode["FUNCTION_TIME_OUT"] = "FUNCTION_TIME_OUT";
|
|
8
|
+
InvocationErrorCode["FUNCTION_PLATFORM_UNKNOWN_ERROR"] = "FUNCTION_PLATFORM_UNKNOWN_ERROR";
|
|
9
|
+
InvocationErrorCode["FUNCTION_PLATFORM_RATE_LIMITED"] = "FUNCTION_PLATFORM_RATE_LIMITED";
|
|
10
|
+
InvocationErrorCode["FUNCTION_UPSTREAM_RATE_LIMITED"] = "FUNCTION_UPSTREAM_RATE_LIMITED";
|
|
11
|
+
InvocationErrorCode["FUNCTION_RETRY_REQUEST"] = "FUNCTION_RETRY_REQUEST";
|
|
12
12
|
})(InvocationErrorCode = exports.InvocationErrorCode || (exports.InvocationErrorCode = {}));
|
package/out/jobProgress.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jobProgress.d.ts","sourceRoot":"","sources":["../src/jobProgress.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,WAAW,EAAoB,WAAW,EAAmB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"jobProgress.d.ts","sourceRoot":"","sources":["../src/jobProgress.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,WAAW,EAAoB,WAAW,EAAmB,MAAM,SAAS,CAAC;AAGtF,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,EAAE,CAAS;gBAEP,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,WAAW;IAKzC,QAAQ,IAAI,OAAO,CAAC,WAAW,CAAC;IAehC,MAAM,IAAI,OAAO,CAAC,WAAW,CAAC;CAcrC"}
|
package/out/jobProgress.js
CHANGED
|
@@ -3,10 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.JobProgress = void 0;
|
|
4
4
|
const queries_1 = require("./queries");
|
|
5
5
|
const validators_1 = require("./validators");
|
|
6
|
+
const api_1 = require("@forge/api");
|
|
6
7
|
class JobProgress {
|
|
7
8
|
constructor(id, apiClient) {
|
|
8
9
|
this.id = id;
|
|
9
|
-
this.apiClient = apiClient ||
|
|
10
|
+
this.apiClient = apiClient || (0, api_1.createRequestStargateAsApp)();
|
|
10
11
|
}
|
|
11
12
|
async getStats() {
|
|
12
13
|
const [queueName, jobId] = this.id.split('#');
|
|
@@ -15,9 +16,9 @@ class JobProgress {
|
|
|
15
16
|
jobId: jobId,
|
|
16
17
|
time: new Date().toISOString()
|
|
17
18
|
};
|
|
18
|
-
validators_1.validateGetStatsPayload(getStatsRequest);
|
|
19
|
-
const response = await queries_1.post(queries_1.GET_STATS_PATH, getStatsRequest, this.apiClient);
|
|
20
|
-
await validators_1.validateGetStatsAPIResponse(response, getStatsRequest);
|
|
19
|
+
(0, validators_1.validateGetStatsPayload)(getStatsRequest);
|
|
20
|
+
const response = await (0, queries_1.post)(queries_1.GET_STATS_PATH, getStatsRequest, this.apiClient);
|
|
21
|
+
await (0, validators_1.validateGetStatsAPIResponse)(response, getStatsRequest);
|
|
21
22
|
return response;
|
|
22
23
|
}
|
|
23
24
|
async cancel() {
|
|
@@ -27,9 +28,9 @@ class JobProgress {
|
|
|
27
28
|
jobId: jobId,
|
|
28
29
|
time: new Date().toISOString()
|
|
29
30
|
};
|
|
30
|
-
validators_1.validateCancelJobRequest(cancelJobRequest);
|
|
31
|
-
const response = await queries_1.post(queries_1.CANCEL_JOB_PATH, cancelJobRequest, this.apiClient);
|
|
32
|
-
await validators_1.validateCancelJobAPIResponse(response, cancelJobRequest);
|
|
31
|
+
(0, validators_1.validateCancelJobRequest)(cancelJobRequest);
|
|
32
|
+
const response = await (0, queries_1.post)(queries_1.CANCEL_JOB_PATH, cancelJobRequest, this.apiClient);
|
|
33
|
+
await (0, validators_1.validateCancelJobAPIResponse)(response, cancelJobRequest);
|
|
33
34
|
return response;
|
|
34
35
|
}
|
|
35
36
|
}
|
package/out/queries.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE/D,eAAO,MAAM,SAAS,0EAA0E,CAAC;AACjG,eAAO,MAAM,cAAc,wEAAwE,CAAC;AACpG,eAAO,MAAM,eAAe,yEAAyE,CAAC;AAEtG,eAAO,MAAM,IAAI,aAAoB,MAAM,QAAQ,UAAU,aAAa,WAAW,KAAG,
|
|
1
|
+
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE/D,eAAO,MAAM,SAAS,0EAA0E,CAAC;AACjG,eAAO,MAAM,cAAc,wEAAwE,CAAC;AACpG,eAAO,MAAM,eAAe,yEAAyE,CAAC;AAEtG,eAAO,MAAM,IAAI,aAAoB,MAAM,QAAQ,UAAU,aAAa,WAAW,KAAG,QAAQ,WAAW,CAU1G,CAAC"}
|
package/out/queries.js
CHANGED
|
@@ -4,7 +4,7 @@ exports.post = exports.CANCEL_JOB_PATH = exports.GET_STATS_PATH = exports.PUSH_P
|
|
|
4
4
|
exports.PUSH_PATH = '/webhook/queue/publish/{cloudId}/{environmentId}/{appId}/{appVersion}';
|
|
5
5
|
exports.GET_STATS_PATH = '/webhook/queue/stats/{cloudId}/{environmentId}/{appId}/{appVersion}';
|
|
6
6
|
exports.CANCEL_JOB_PATH = '/webhook/queue/cancel/{cloudId}/{environmentId}/{appId}/{appVersion}';
|
|
7
|
-
|
|
7
|
+
const post = async (endpoint, body, apiClient) => {
|
|
8
8
|
const request = {
|
|
9
9
|
method: 'POST',
|
|
10
10
|
body: JSON.stringify(body),
|
|
@@ -14,3 +14,4 @@ exports.post = async (endpoint, body, apiClient) => {
|
|
|
14
14
|
};
|
|
15
15
|
return await apiClient(endpoint, request);
|
|
16
16
|
};
|
|
17
|
+
exports.post = post;
|
package/out/queue.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAe,MAAM,SAAS,CAAC;AAEvF,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAe,MAAM,SAAS,CAAC;AAEvF,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,qBAAa,KAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,WAAW,CAAc;gBAErB,WAAW,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,WAAW;IAMvD,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,EAAE,EAAE,YAAY,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IA0BvF,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW;CAGnC"}
|
package/out/queue.js
CHANGED
|
@@ -6,16 +6,17 @@ const queries_1 = require("./queries");
|
|
|
6
6
|
const validators_1 = require("./validators");
|
|
7
7
|
const v4_1 = tslib_1.__importDefault(require("uuid/v4"));
|
|
8
8
|
const jobProgress_1 = require("./jobProgress");
|
|
9
|
+
const api_1 = require("@forge/api");
|
|
9
10
|
class Queue {
|
|
10
11
|
constructor(queueParams, apiClient) {
|
|
11
|
-
validators_1.validateQueueKey(queueParams.key);
|
|
12
|
+
(0, validators_1.validateQueueKey)(queueParams.key);
|
|
12
13
|
this.queueParams = queueParams;
|
|
13
|
-
this.apiClient = apiClient ||
|
|
14
|
+
this.apiClient = apiClient || (0, api_1.createRequestStargateAsApp)();
|
|
14
15
|
}
|
|
15
16
|
async push(payloads, pushSettings) {
|
|
16
|
-
validators_1.validatePushPayloads(payloads);
|
|
17
|
+
(0, validators_1.validatePushPayloads)(payloads);
|
|
17
18
|
const queueName = this.queueParams.key;
|
|
18
|
-
const jobId = v4_1.default();
|
|
19
|
+
const jobId = (0, v4_1.default)();
|
|
19
20
|
const pushRequest = {
|
|
20
21
|
queueName: queueName,
|
|
21
22
|
jobId: jobId,
|
|
@@ -25,13 +26,13 @@ class Queue {
|
|
|
25
26
|
time: new Date().toISOString()
|
|
26
27
|
};
|
|
27
28
|
if (pushSettings) {
|
|
28
|
-
validators_1.validatePushSettings(pushSettings);
|
|
29
|
+
(0, validators_1.validatePushSettings)(pushSettings);
|
|
29
30
|
if (pushSettings.delayInSeconds) {
|
|
30
31
|
pushRequest.delayInSeconds = pushSettings.delayInSeconds;
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
|
-
const response = await queries_1.post(queries_1.PUSH_PATH, pushRequest, this.apiClient);
|
|
34
|
-
await validators_1.validatePushAPIResponse(response, pushRequest);
|
|
34
|
+
const response = await (0, queries_1.post)(queries_1.PUSH_PATH, pushRequest, this.apiClient);
|
|
35
|
+
await (0, validators_1.validatePushAPIResponse)(response, pushRequest);
|
|
35
36
|
return `${queueName}#${jobId}`;
|
|
36
37
|
}
|
|
37
38
|
getJob(jobId) {
|
package/out/retryOptions.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { InvocationErrorCode } from './invocationErrorCode';
|
|
2
|
-
export declare
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
export declare const MIN_RETRY_AFTER = 1;
|
|
3
|
+
export declare const DEFAULT_RETRY_OPTIONS: {
|
|
4
|
+
retryAfter: number;
|
|
5
5
|
retryReason: InvocationErrorCode;
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
};
|
|
7
|
+
export interface RetryOptions {
|
|
8
|
+
retryAfter: number;
|
|
9
|
+
retryReason: InvocationErrorCode;
|
|
10
|
+
retryData?: any;
|
|
8
11
|
}
|
|
9
12
|
//# sourceMappingURL=retryOptions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retryOptions.d.ts","sourceRoot":"","sources":["../src/retryOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,
|
|
1
|
+
{"version":3,"file":"retryOptions.d.ts","sourceRoot":"","sources":["../src/retryOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,eAAO,MAAM,qBAAqB;;;CAGjC,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,mBAAmB,CAAC;IACjC,SAAS,CAAC,EAAE,GAAG,CAAC;CACjB"}
|
package/out/retryOptions.js
CHANGED
|
@@ -1,20 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.DEFAULT_RETRY_OPTIONS = exports.MIN_RETRY_AFTER = void 0;
|
|
4
4
|
const invocationErrorCode_1 = require("./invocationErrorCode");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
set retryAfter(valueInSeconds) {
|
|
11
|
-
if (valueInSeconds >= RetryOptions.MIN_RETRY_AFTER) {
|
|
12
|
-
this._retryAfter = valueInSeconds;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
get retryAfter() {
|
|
16
|
-
return this._retryAfter;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
exports.RetryOptions = RetryOptions;
|
|
20
|
-
RetryOptions.MIN_RETRY_AFTER = 1;
|
|
5
|
+
exports.MIN_RETRY_AFTER = 1;
|
|
6
|
+
exports.DEFAULT_RETRY_OPTIONS = {
|
|
7
|
+
retryAfter: exports.MIN_RETRY_AFTER,
|
|
8
|
+
retryReason: invocationErrorCode_1.InvocationErrorCode.FUNCTION_RETRY_REQUEST
|
|
9
|
+
};
|
package/out/validators.js
CHANGED
|
@@ -6,17 +6,19 @@ const text_1 = require("./text");
|
|
|
6
6
|
const VALID_QUEUE_NAME_PATTERN = /^[a-zA-Z0-9-_]+$/;
|
|
7
7
|
const MAXIMUM_EVENTS = 50;
|
|
8
8
|
const MAXIMUM_PAYLOAD_SIZE_KB = 200;
|
|
9
|
-
|
|
9
|
+
const validateQueueKey = (queueName) => {
|
|
10
10
|
if (!queueName || !VALID_QUEUE_NAME_PATTERN.test(queueName)) {
|
|
11
11
|
throw new errors_1.InvalidQueueNameError(text_1.Text.error.invalidQueueName);
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
|
-
exports.
|
|
14
|
+
exports.validateQueueKey = validateQueueKey;
|
|
15
|
+
const validatePushSettings = (settings) => {
|
|
15
16
|
if ((settings.delayInSeconds && settings.delayInSeconds > 900) || settings.delayInSeconds < 0) {
|
|
16
17
|
throw new errors_1.InvalidPushSettingsError(text_1.Text.error.invalidDelayInSecondsSetting);
|
|
17
18
|
}
|
|
18
19
|
};
|
|
19
|
-
exports.
|
|
20
|
+
exports.validatePushSettings = validatePushSettings;
|
|
21
|
+
const validatePushPayloads = (payloads) => {
|
|
20
22
|
if (!payloads || (Array.isArray(payloads) && payloads.length === 0)) {
|
|
21
23
|
throw new errors_1.NoEventsToPushError(text_1.Text.error.noEventsPushed);
|
|
22
24
|
}
|
|
@@ -28,19 +30,22 @@ exports.validatePushPayloads = (payloads) => {
|
|
|
28
30
|
throw new errors_1.PayloadTooBigError(text_1.Text.error.maxPayloadAllowed(MAXIMUM_PAYLOAD_SIZE_KB));
|
|
29
31
|
}
|
|
30
32
|
};
|
|
31
|
-
exports.
|
|
33
|
+
exports.validatePushPayloads = validatePushPayloads;
|
|
34
|
+
const validateGetStatsPayload = (getStatsRequest) => {
|
|
32
35
|
if (!getStatsRequest.jobId) {
|
|
33
36
|
throw new errors_1.JobDoesNotExistError(text_1.Text.error.jobIdEmpty);
|
|
34
37
|
}
|
|
35
|
-
exports.validateQueueKey(getStatsRequest.queueName);
|
|
38
|
+
(0, exports.validateQueueKey)(getStatsRequest.queueName);
|
|
36
39
|
};
|
|
37
|
-
exports.
|
|
40
|
+
exports.validateGetStatsPayload = validateGetStatsPayload;
|
|
41
|
+
const validateCancelJobRequest = (cancelJobRequest) => {
|
|
38
42
|
if (!cancelJobRequest.jobId) {
|
|
39
43
|
throw new errors_1.JobDoesNotExistError(text_1.Text.error.jobIdEmpty);
|
|
40
44
|
}
|
|
41
|
-
exports.validateQueueKey(cancelJobRequest.queueName);
|
|
45
|
+
(0, exports.validateQueueKey)(cancelJobRequest.queueName);
|
|
42
46
|
};
|
|
43
|
-
exports.
|
|
47
|
+
exports.validateCancelJobRequest = validateCancelJobRequest;
|
|
48
|
+
const validateAPIResponse = async (response, expectedSuccessStatus) => {
|
|
44
49
|
if (response.status === 429) {
|
|
45
50
|
throw new errors_1.RateLimitError(text_1.Text.error.rateLimitError);
|
|
46
51
|
}
|
|
@@ -61,7 +66,8 @@ exports.validateAPIResponse = async (response, expectedSuccessStatus) => {
|
|
|
61
66
|
throw internalServerError;
|
|
62
67
|
}
|
|
63
68
|
};
|
|
64
|
-
exports.
|
|
69
|
+
exports.validateAPIResponse = validateAPIResponse;
|
|
70
|
+
const validatePushAPIResponse = async (response, requestBody) => {
|
|
65
71
|
if (response.status === 413) {
|
|
66
72
|
const responseBody = await response.json();
|
|
67
73
|
throw new errors_1.PayloadTooBigError(responseBody.errorMessage);
|
|
@@ -87,17 +93,20 @@ exports.validatePushAPIResponse = async (response, requestBody) => {
|
|
|
87
93
|
}
|
|
88
94
|
throw partialSuccessError;
|
|
89
95
|
}
|
|
90
|
-
await exports.validateAPIResponse(response, 201);
|
|
96
|
+
await (0, exports.validateAPIResponse)(response, 201);
|
|
91
97
|
};
|
|
92
|
-
exports.
|
|
98
|
+
exports.validatePushAPIResponse = validatePushAPIResponse;
|
|
99
|
+
const validateGetStatsAPIResponse = async (response, getStatsRequest) => {
|
|
93
100
|
if (response.status === 404) {
|
|
94
101
|
throw new errors_1.JobDoesNotExistError(text_1.Text.error.jobDoesNotExit(getStatsRequest.jobId, getStatsRequest.queueName));
|
|
95
102
|
}
|
|
96
|
-
await exports.validateAPIResponse(response, 200);
|
|
103
|
+
await (0, exports.validateAPIResponse)(response, 200);
|
|
97
104
|
};
|
|
98
|
-
exports.
|
|
105
|
+
exports.validateGetStatsAPIResponse = validateGetStatsAPIResponse;
|
|
106
|
+
const validateCancelJobAPIResponse = async (response, cancelJobRequest) => {
|
|
99
107
|
if (response.status === 404) {
|
|
100
108
|
throw new errors_1.JobDoesNotExistError(text_1.Text.error.jobDoesNotExit(cancelJobRequest.jobId, cancelJobRequest.queueName));
|
|
101
109
|
}
|
|
102
|
-
await exports.validateAPIResponse(response, 204);
|
|
110
|
+
await (0, exports.validateAPIResponse)(response, 204);
|
|
103
111
|
};
|
|
112
|
+
exports.validateCancelJobAPIResponse = validateCancelJobAPIResponse;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forge/events",
|
|
3
|
-
"version": "0.0.0-experimental-
|
|
3
|
+
"version": "0.0.0-experimental-9b81865",
|
|
4
4
|
"description": "Forge Async Event methods",
|
|
5
5
|
"author": "Atlassian",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"@types/uuid": "^3.4.7"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@forge/api": "^
|
|
19
|
+
"@forge/api": "^0.0.0-experimental-9b81865",
|
|
20
20
|
"uuid": "^3.4.0"
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -1,23 +1,40 @@
|
|
|
1
|
-
import { RetryOptions } from '../retryOptions';
|
|
2
1
|
import { InvocationError } from '../invocationError';
|
|
3
2
|
import { InvocationErrorCode } from '../invocationErrorCode';
|
|
3
|
+
import { DEFAULT_RETRY_OPTIONS, MIN_RETRY_AFTER, RetryOptions } from '../retryOptions';
|
|
4
4
|
|
|
5
5
|
describe('InvocationError tests', () => {
|
|
6
|
-
const defaultRetryOption = new RetryOptions();
|
|
7
6
|
let target = new InvocationError();
|
|
8
7
|
|
|
9
8
|
it('Populate invocationError with default retryOptions and expect default retry option', async () => {
|
|
10
|
-
expect(target.retryOptions.retryAfter).toEqual(
|
|
9
|
+
expect(target.retryOptions.retryAfter).toEqual(DEFAULT_RETRY_OPTIONS.retryAfter);
|
|
11
10
|
expect(target.retryOptions.retryReason).toEqual(InvocationErrorCode.FUNCTION_RETRY_REQUEST);
|
|
12
11
|
expect((target as any).hasOwnProperty('_retry')).toBe(true);
|
|
13
12
|
});
|
|
14
13
|
|
|
15
14
|
it('Populate InvocationError with custom RetryOptions and expect the custom value to set.', () => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
const retryOptions: RetryOptions = {
|
|
16
|
+
retryAfter: 10,
|
|
17
|
+
retryReason: InvocationErrorCode.FUNCTION_OUT_OF_MEMORY,
|
|
18
|
+
retryData: {
|
|
19
|
+
eventsToSplit: 5
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
target = new InvocationError(retryOptions);
|
|
19
23
|
|
|
20
|
-
expect(target.retryOptions).toEqual(
|
|
24
|
+
expect(target.retryOptions).toEqual(retryOptions);
|
|
25
|
+
expect((target as any).hasOwnProperty('_retry')).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('Use MIN_RETRY_AFTER when retryAfter <= 0', () => {
|
|
29
|
+
const retryOptions: RetryOptions = {
|
|
30
|
+
retryAfter: 0,
|
|
31
|
+
retryReason: InvocationErrorCode.FUNCTION_OUT_OF_MEMORY,
|
|
32
|
+
retryData: 'some string data'
|
|
33
|
+
};
|
|
34
|
+
target = new InvocationError(retryOptions);
|
|
35
|
+
|
|
36
|
+
expect(target.retryOptions.retryAfter).toEqual(MIN_RETRY_AFTER);
|
|
37
|
+
expect(target.retryOptions.retryData).toEqual('some string data');
|
|
21
38
|
expect((target as any).hasOwnProperty('_retry')).toBe(true);
|
|
22
39
|
});
|
|
23
40
|
});
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getMockFetchMethod, verifyApiClientCalledWith } from './utils';
|
|
2
2
|
import { InternalServerError, InvalidQueueNameError, JobDoesNotExistError, RateLimitError } from '../errors';
|
|
3
3
|
import { JobProgress } from '../jobProgress';
|
|
4
|
+
import { createRequestStargateAsApp } from '@forge/api';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
jest.mock('@forge/api', () => ({
|
|
7
|
+
createRequestStargateAsApp: jest.fn().mockReturnValue(getMockFetchMethod('done', 200))
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
const getJobProgress = (jobId: string, apiClientMock?: any) => new JobProgress(jobId, apiClientMock);
|
|
6
11
|
|
|
7
12
|
describe('JobProgress methods', () => {
|
|
8
13
|
describe('getStats', () => {
|
|
9
14
|
it('should call the queue/stats endpoint', async () => {
|
|
10
|
-
const apiClientMock =
|
|
15
|
+
const apiClientMock = getMockFetchMethod(
|
|
11
16
|
{
|
|
12
17
|
success: 100,
|
|
13
18
|
inProgress: 50,
|
|
@@ -15,7 +20,7 @@ describe('JobProgress methods', () => {
|
|
|
15
20
|
},
|
|
16
21
|
200
|
|
17
22
|
);
|
|
18
|
-
const jobProgress = getJobProgress(
|
|
23
|
+
const jobProgress = getJobProgress('test-queue-name#test-job-id', apiClientMock);
|
|
19
24
|
const response = await jobProgress.getStats();
|
|
20
25
|
const { success, inProgress, failed } = await response.json();
|
|
21
26
|
verifyApiClientCalledWith(apiClientMock, '/webhook/queue/stats/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
@@ -28,14 +33,14 @@ describe('JobProgress methods', () => {
|
|
|
28
33
|
});
|
|
29
34
|
|
|
30
35
|
it('should throw JobDoesNotExistError', async () => {
|
|
31
|
-
const apiClientMock =
|
|
36
|
+
const apiClientMock = getMockFetchMethod(
|
|
32
37
|
{
|
|
33
38
|
message: 'Job Not Found',
|
|
34
39
|
code: 404
|
|
35
40
|
},
|
|
36
41
|
404
|
|
37
42
|
);
|
|
38
|
-
const jobProgress = getJobProgress(
|
|
43
|
+
const jobProgress = getJobProgress('test-queue-name#test-job-id', apiClientMock);
|
|
39
44
|
await expect(jobProgress.getStats()).rejects.toThrow(
|
|
40
45
|
new JobDoesNotExistError(`The job test-job-id was not found for the queue test-queue-name.`)
|
|
41
46
|
);
|
|
@@ -46,8 +51,8 @@ describe('JobProgress methods', () => {
|
|
|
46
51
|
});
|
|
47
52
|
|
|
48
53
|
it('should throw RateLimitError', async () => {
|
|
49
|
-
const apiClientMock =
|
|
50
|
-
const jobProgress = getJobProgress(
|
|
54
|
+
const apiClientMock = getMockFetchMethod({}, 429);
|
|
55
|
+
const jobProgress = getJobProgress('test-queue-name#test-job-id', apiClientMock);
|
|
51
56
|
await expect(jobProgress.getStats()).rejects.toThrow(new RateLimitError(`Too many requests.`));
|
|
52
57
|
verifyApiClientCalledWith(apiClientMock, '/webhook/queue/stats/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
53
58
|
queueName: 'test-queue-name',
|
|
@@ -56,7 +61,7 @@ describe('JobProgress methods', () => {
|
|
|
56
61
|
});
|
|
57
62
|
|
|
58
63
|
it('should throw InternalServerError', async () => {
|
|
59
|
-
const apiClientMock =
|
|
64
|
+
const apiClientMock = getMockFetchMethod(
|
|
60
65
|
{
|
|
61
66
|
message: 'Service is not available',
|
|
62
67
|
code: 513,
|
|
@@ -64,7 +69,7 @@ describe('JobProgress methods', () => {
|
|
|
64
69
|
},
|
|
65
70
|
513
|
|
66
71
|
);
|
|
67
|
-
const jobProgress = getJobProgress(
|
|
72
|
+
const jobProgress = getJobProgress('test-queue-name#test-job-id', apiClientMock);
|
|
68
73
|
await expect(jobProgress.getStats()).rejects.toThrow(
|
|
69
74
|
new InternalServerError(`513 Status Text: Service is not available`, 513)
|
|
70
75
|
);
|
|
@@ -77,8 +82,8 @@ describe('JobProgress methods', () => {
|
|
|
77
82
|
|
|
78
83
|
describe('cancel', () => {
|
|
79
84
|
it('should call the queue/cancel endpoint', async () => {
|
|
80
|
-
const apiClientMock =
|
|
81
|
-
const jobProgress = getJobProgress(
|
|
85
|
+
const apiClientMock = getMockFetchMethod({}, 204);
|
|
86
|
+
const jobProgress = getJobProgress('test-queue-name#test-job-id', apiClientMock);
|
|
82
87
|
const response = await jobProgress.cancel();
|
|
83
88
|
verifyApiClientCalledWith(apiClientMock, '/webhook/queue/cancel/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
84
89
|
queueName: 'test-queue-name',
|
|
@@ -88,14 +93,14 @@ describe('JobProgress methods', () => {
|
|
|
88
93
|
});
|
|
89
94
|
|
|
90
95
|
it('should throw JobDoesNotExistError', async () => {
|
|
91
|
-
const apiClientMock =
|
|
96
|
+
const apiClientMock = getMockFetchMethod(
|
|
92
97
|
{
|
|
93
98
|
message: 'Job Not Found',
|
|
94
99
|
code: 404
|
|
95
100
|
},
|
|
96
101
|
404
|
|
97
102
|
);
|
|
98
|
-
const jobProgress = getJobProgress(
|
|
103
|
+
const jobProgress = getJobProgress('test-queue-name#test-job-id', apiClientMock);
|
|
99
104
|
await expect(jobProgress.cancel()).rejects.toThrow(
|
|
100
105
|
new JobDoesNotExistError(`The job test-job-id was not found for the queue test-queue-name.`)
|
|
101
106
|
);
|
|
@@ -107,13 +112,13 @@ describe('JobProgress methods', () => {
|
|
|
107
112
|
});
|
|
108
113
|
|
|
109
114
|
it('should throw InternalServerError when WHP returns 422 response', async () => {
|
|
110
|
-
const apiClientMock =
|
|
115
|
+
const apiClientMock = getMockFetchMethod(
|
|
111
116
|
{
|
|
112
117
|
errors: ['jobId must not be null', 'queueName must not be null']
|
|
113
118
|
},
|
|
114
119
|
422
|
|
115
120
|
);
|
|
116
|
-
const jobProgress = getJobProgress(
|
|
121
|
+
const jobProgress = getJobProgress('test-queue-name#test-job-id', apiClientMock);
|
|
117
122
|
await expect(jobProgress.getStats()).rejects.toThrow(
|
|
118
123
|
new InternalServerError(`422 Status Text: jobId must not be null, queueName must not be null`)
|
|
119
124
|
);
|
|
@@ -125,7 +130,7 @@ describe('JobProgress methods', () => {
|
|
|
125
130
|
});
|
|
126
131
|
|
|
127
132
|
it('should throw errors when queueName or jobId is empty', async () => {
|
|
128
|
-
const apiClientMock =
|
|
133
|
+
const apiClientMock = getMockFetchMethod(
|
|
129
134
|
{
|
|
130
135
|
success: 100,
|
|
131
136
|
inProgress: 50,
|
|
@@ -133,17 +138,23 @@ describe('JobProgress methods', () => {
|
|
|
133
138
|
},
|
|
134
139
|
200
|
|
135
140
|
);
|
|
136
|
-
const jobProgress1 = getJobProgress(
|
|
141
|
+
const jobProgress1 = getJobProgress('test-queue-name#', apiClientMock);
|
|
137
142
|
await expect(jobProgress1.getStats()).rejects.toThrow(new JobDoesNotExistError(`jobId cannot be empty.`));
|
|
138
143
|
|
|
139
|
-
const jobProgress2 = getJobProgress(
|
|
144
|
+
const jobProgress2 = getJobProgress('#test-job-id', apiClientMock);
|
|
140
145
|
await expect(jobProgress2.getStats()).rejects.toThrow(
|
|
141
146
|
new InvalidQueueNameError('Queue names can only contain alphanumeric characters, dashes and underscores.')
|
|
142
147
|
);
|
|
143
148
|
|
|
144
|
-
const jobProgress3 = getJobProgress(
|
|
149
|
+
const jobProgress3 = getJobProgress('', apiClientMock);
|
|
145
150
|
await expect(jobProgress3.getStats()).rejects.toThrow(new JobDoesNotExistError(`jobId cannot be empty.`));
|
|
146
151
|
|
|
147
152
|
expect(apiClientMock).toHaveBeenCalledTimes(0);
|
|
148
153
|
});
|
|
154
|
+
|
|
155
|
+
it('requests stargate if no api client is provided', async () => {
|
|
156
|
+
const jobProgress = getJobProgress('test-queue-name#job-id');
|
|
157
|
+
await jobProgress.getStats();
|
|
158
|
+
expect(createRequestStargateAsApp()).toBeCalledTimes(1);
|
|
159
|
+
});
|
|
149
160
|
});
|