@forge/events 0.0.0-experimental-e05f7a2 → 0.0.0-experimental-64caa5a
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 +154 -1
- package/README.md +1 -1
- package/out/__test__/jobProgress.test.d.ts +2 -0
- package/out/__test__/jobProgress.test.d.ts.map +1 -0
- package/out/__test__/jobProgress.test.js +110 -0
- package/out/__test__/queue.test.d.ts +2 -0
- package/out/__test__/queue.test.d.ts.map +1 -0
- package/out/__test__/queue.test.js +179 -0
- package/out/__test__/queueResponse.test.d.ts +2 -0
- package/out/__test__/queueResponse.test.d.ts.map +1 -0
- package/out/__test__/queueResponse.test.js +14 -0
- package/out/__test__/utils.d.ts +7 -0
- package/out/__test__/utils.d.ts.map +1 -0
- package/out/__test__/utils.js +37 -0
- package/out/errors.d.ts +9 -0
- package/out/errors.d.ts.map +1 -1
- package/out/errors.js +19 -1
- package/out/index.d.ts +3 -0
- package/out/index.d.ts.map +1 -1
- package/out/index.js +15 -0
- package/out/jobProgress.d.ts +9 -0
- package/out/jobProgress.d.ts.map +1 -0
- package/out/jobProgress.js +36 -0
- package/out/queries.d.ts +4 -2
- package/out/queries.d.ts.map +1 -1
- package/out/queries.js +13 -8
- package/out/queue.d.ts +4 -4
- package/out/queue.d.ts.map +1 -1
- package/out/queue.js +25 -25
- package/out/queueResponse.d.ts +5 -0
- package/out/queueResponse.d.ts.map +1 -0
- package/out/queueResponse.js +12 -0
- package/out/text.d.ts +14 -0
- package/out/text.d.ts.map +1 -0
- package/out/text.js +16 -0
- package/out/types.d.ts +11 -4
- package/out/types.d.ts.map +1 -1
- package/out/validators.d.ts +10 -4
- package/out/validators.d.ts.map +1 -1
- package/out/validators.js +69 -18
- package/package.json +7 -2
- package/src/__test__/jobProgress.test.ts +149 -0
- package/src/__test__/queue.test.ts +236 -0
- package/src/__test__/queueResponse.test.ts +14 -0
- package/src/__test__/utils.ts +47 -0
- package/src/errors.ts +18 -0
- package/src/index.ts +14 -0
- package/src/jobProgress.ts +48 -0
- package/src/queries.ts +15 -9
- package/src/queue.ts +28 -29
- package/src/queueResponse.ts +7 -0
- package/src/text.ts +15 -0
- package/src/types.ts +12 -4
- package/src/validators.ts +98 -31
- package/tsconfig.json +12 -9
- package/tsconfig.tsbuildinfo +107 -20
- package/out/__test__/index.test.d.ts +0 -2
- package/out/__test__/index.test.d.ts.map +0 -1
- package/out/__test__/index.test.js +0 -126
- package/src/__test__/index.test.ts +0 -168
package/CHANGELOG.md
CHANGED
|
@@ -1,15 +1,168 @@
|
|
|
1
1
|
# @forge/events
|
|
2
2
|
|
|
3
|
-
## 0.0.0-experimental-
|
|
3
|
+
## 0.0.0-experimental-64caa5a
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [8571c05]
|
|
8
|
+
- @forge/api@0.0.0-experimental-64caa5a
|
|
9
|
+
|
|
10
|
+
## 0.5.2-next.0
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies [8571c05]
|
|
15
|
+
- @forge/api@2.6.0-next.0
|
|
16
|
+
|
|
17
|
+
## 0.5.1
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- Updated dependencies [70e9c8c]
|
|
22
|
+
- Updated dependencies [32d11d1]
|
|
23
|
+
- @forge/api@2.5.0
|
|
24
|
+
|
|
25
|
+
## 0.5.1-next.0
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- Updated dependencies [df2cd2f]
|
|
30
|
+
- @forge/api@2.5.0-next.0
|
|
31
|
+
|
|
32
|
+
## 0.5.0
|
|
33
|
+
|
|
34
|
+
### Minor Changes
|
|
35
|
+
|
|
36
|
+
- 53e3fda: Create new API jobProgress.cancel() in forge-events package
|
|
37
|
+
|
|
38
|
+
### Patch Changes
|
|
39
|
+
|
|
40
|
+
- @forge/api@2.4.0
|
|
41
|
+
|
|
42
|
+
## 0.5.0-next.1
|
|
43
|
+
|
|
44
|
+
### Minor Changes
|
|
45
|
+
|
|
46
|
+
- 53e3fda: Create new API jobProgress.cancel() in forge-events package
|
|
47
|
+
|
|
48
|
+
## 0.4.1-next.0
|
|
49
|
+
|
|
50
|
+
### Patch Changes
|
|
51
|
+
|
|
52
|
+
- Updated dependencies [de02d45]
|
|
53
|
+
- @forge/api@2.4.0-next.0
|
|
54
|
+
|
|
55
|
+
## 0.4.0
|
|
56
|
+
|
|
57
|
+
### Minor Changes
|
|
58
|
+
|
|
59
|
+
- d32350b: allow sending up to 50 events per queue.push()
|
|
60
|
+
|
|
61
|
+
### Patch Changes
|
|
62
|
+
|
|
63
|
+
- 8a8dccc: Update error messages
|
|
64
|
+
|
|
65
|
+
## 0.4.0-next.1
|
|
66
|
+
|
|
67
|
+
### Minor Changes
|
|
68
|
+
|
|
69
|
+
- d32350b: allow sending up to 50 events per queue.push()
|
|
70
|
+
|
|
71
|
+
## 0.3.1-next.0
|
|
72
|
+
|
|
73
|
+
### Patch Changes
|
|
74
|
+
|
|
75
|
+
- 8a8dccc: Update error messages
|
|
76
|
+
|
|
77
|
+
## 0.3.0
|
|
78
|
+
|
|
79
|
+
### Minor Changes
|
|
80
|
+
|
|
81
|
+
- 9fe841c: Explicitly add uuid dependency and whitelist WHP getStats endpoint
|
|
82
|
+
- 66b6648: Add errors and validations
|
|
83
|
+
- 9051f1d: Add @forge/api as a dependency of @forge/events
|
|
84
|
+
- 6dbedd8: Add QueueResponse in forge-events package to allow retrying an async event.
|
|
85
|
+
|
|
86
|
+
### Patch Changes
|
|
87
|
+
|
|
88
|
+
- afa9ee0: Update the error messages
|
|
89
|
+
|
|
90
|
+
## 0.3.0-next.4
|
|
91
|
+
|
|
92
|
+
### Patch Changes
|
|
93
|
+
|
|
94
|
+
- afa9ee0: Update the error messages
|
|
95
|
+
|
|
96
|
+
## 0.3.0-next.3
|
|
97
|
+
|
|
98
|
+
### Minor Changes
|
|
99
|
+
|
|
100
|
+
- 9051f1d: Add @forge/api as a dependency of @forge/events
|
|
101
|
+
|
|
102
|
+
## 0.3.0-next.2
|
|
103
|
+
|
|
104
|
+
### Minor Changes
|
|
105
|
+
|
|
106
|
+
- 6dbedd8: Add QueueResponse in forge-events package to allow retrying an async event.
|
|
107
|
+
|
|
108
|
+
## 0.3.0-next.1
|
|
109
|
+
|
|
110
|
+
### Minor Changes
|
|
111
|
+
|
|
112
|
+
- 66b6648: Add errors and validations
|
|
113
|
+
|
|
114
|
+
## 0.3.0-next.0
|
|
115
|
+
|
|
116
|
+
### Minor Changes
|
|
117
|
+
|
|
118
|
+
- 767d40d: Explicitly add uuid dependency and whitelist WHP getStats endpoint
|
|
119
|
+
|
|
120
|
+
## 0.2.0
|
|
121
|
+
|
|
122
|
+
### Minor Changes
|
|
123
|
+
|
|
124
|
+
- a056b40: Add Queue.getStats()
|
|
125
|
+
- 8dca98b: New configurable settings for Queue push API
|
|
126
|
+
|
|
127
|
+
### Patch Changes
|
|
128
|
+
|
|
129
|
+
- ddce3eb: Update the error message for delayInSettings error in push settings
|
|
130
|
+
|
|
131
|
+
## 0.2.0-next.2
|
|
132
|
+
|
|
133
|
+
### Patch Changes
|
|
134
|
+
|
|
135
|
+
- ddce3eb: Update the error message for delayInSettings error in push settings
|
|
136
|
+
|
|
137
|
+
## 0.2.0-next.1
|
|
138
|
+
|
|
139
|
+
### Minor Changes
|
|
140
|
+
|
|
141
|
+
- a056b40: Add Queue.getStats()
|
|
142
|
+
|
|
143
|
+
## 0.2.0-next.0
|
|
144
|
+
|
|
145
|
+
### Minor Changes
|
|
146
|
+
|
|
147
|
+
- 8dca98b: New configurable settings for Queue push API
|
|
148
|
+
|
|
149
|
+
## 0.1.0
|
|
4
150
|
|
|
5
151
|
### Minor Changes
|
|
6
152
|
|
|
7
153
|
- bfc9f8c: update stargate allowlist and new middleware for updating runtime variables in path for requestAtlassian
|
|
154
|
+
- 0831a0a: export queue errors and rename queue param "queueName" to "key"
|
|
8
155
|
|
|
9
156
|
### Patch Changes
|
|
10
157
|
|
|
11
158
|
- c14df05: Add errors and validations
|
|
12
159
|
|
|
160
|
+
## 0.1.0-next.2
|
|
161
|
+
|
|
162
|
+
### Minor Changes
|
|
163
|
+
|
|
164
|
+
- 0831a0a: export queue errors and rename queue param "queueName" to "key"
|
|
165
|
+
|
|
13
166
|
## 0.1.0-next.1
|
|
14
167
|
|
|
15
168
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ async function apiClient(path: string, init: RequestInit): Promise<APIResponse>
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
async function demo() {
|
|
31
|
-
const queue = new Queue({
|
|
31
|
+
const queue = new Queue({key: "queue-name"}, apiClient);
|
|
32
32
|
const payloads = {
|
|
33
33
|
page: 1
|
|
34
34
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobProgress.test.d.ts","sourceRoot":"","sources":["../../src/__test__/jobProgress.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_1 = require("./utils");
|
|
4
|
+
const errors_1 = require("../errors");
|
|
5
|
+
const jobProgress_1 = require("../jobProgress");
|
|
6
|
+
const getJobProgress = (apiClientMock, jobId) => new jobProgress_1.JobProgress(jobId, apiClientMock);
|
|
7
|
+
describe('JobProgress methods', () => {
|
|
8
|
+
describe('getStats', () => {
|
|
9
|
+
it('should call the queue/stats endpoint', async () => {
|
|
10
|
+
const apiClientMock = utils_1.getApiClientMock({
|
|
11
|
+
success: 100,
|
|
12
|
+
inProgress: 50,
|
|
13
|
+
failed: 1
|
|
14
|
+
}, 200);
|
|
15
|
+
const jobProgress = getJobProgress(apiClientMock, 'test-queue-name#test-job-id');
|
|
16
|
+
const response = await jobProgress.getStats();
|
|
17
|
+
const { success, inProgress, failed } = await response.json();
|
|
18
|
+
utils_1.verifyApiClientCalledWith(apiClientMock, '/webhook/queue/stats/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
19
|
+
queueName: 'test-queue-name',
|
|
20
|
+
jobId: 'test-job-id'
|
|
21
|
+
});
|
|
22
|
+
expect(success).toEqual(100);
|
|
23
|
+
expect(inProgress).toEqual(50);
|
|
24
|
+
expect(failed).toEqual(1);
|
|
25
|
+
});
|
|
26
|
+
it('should throw JobDoesNotExistError', async () => {
|
|
27
|
+
const apiClientMock = utils_1.getApiClientMock({
|
|
28
|
+
message: 'Job Not Found',
|
|
29
|
+
code: 404
|
|
30
|
+
}, 404);
|
|
31
|
+
const jobProgress = getJobProgress(apiClientMock, 'test-queue-name#test-job-id');
|
|
32
|
+
await expect(jobProgress.getStats()).rejects.toThrow(new errors_1.JobDoesNotExistError(`The job test-job-id was not found for the queue test-queue-name.`));
|
|
33
|
+
utils_1.verifyApiClientCalledWith(apiClientMock, '/webhook/queue/stats/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
34
|
+
queueName: 'test-queue-name',
|
|
35
|
+
jobId: 'test-job-id'
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
it('should throw RateLimitError', async () => {
|
|
39
|
+
const apiClientMock = utils_1.getApiClientMock({}, 429);
|
|
40
|
+
const jobProgress = getJobProgress(apiClientMock, 'test-queue-name#test-job-id');
|
|
41
|
+
await expect(jobProgress.getStats()).rejects.toThrow(new errors_1.RateLimitError(`Too many requests.`));
|
|
42
|
+
utils_1.verifyApiClientCalledWith(apiClientMock, '/webhook/queue/stats/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
43
|
+
queueName: 'test-queue-name',
|
|
44
|
+
jobId: 'test-job-id'
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
it('should throw InternalServerError', async () => {
|
|
48
|
+
const apiClientMock = utils_1.getApiClientMock({
|
|
49
|
+
message: 'Service is not available',
|
|
50
|
+
code: 513,
|
|
51
|
+
details: 'The request processing has failed because of an unknown error, exception or failure'
|
|
52
|
+
}, 513);
|
|
53
|
+
const jobProgress = getJobProgress(apiClientMock, 'test-queue-name#test-job-id');
|
|
54
|
+
await expect(jobProgress.getStats()).rejects.toThrow(new errors_1.InternalServerError(`513 Status Text: Service is not available`, 513));
|
|
55
|
+
utils_1.verifyApiClientCalledWith(apiClientMock, '/webhook/queue/stats/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
56
|
+
queueName: 'test-queue-name',
|
|
57
|
+
jobId: 'test-job-id'
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe('cancel', () => {
|
|
62
|
+
it('should call the queue/cancel endpoint', async () => {
|
|
63
|
+
const apiClientMock = utils_1.getApiClientMock({}, 204);
|
|
64
|
+
const jobProgress = getJobProgress(apiClientMock, 'test-queue-name#test-job-id');
|
|
65
|
+
const response = await jobProgress.cancel();
|
|
66
|
+
utils_1.verifyApiClientCalledWith(apiClientMock, '/webhook/queue/cancel/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
67
|
+
queueName: 'test-queue-name',
|
|
68
|
+
jobId: 'test-job-id'
|
|
69
|
+
});
|
|
70
|
+
expect(response.status).toEqual(204);
|
|
71
|
+
});
|
|
72
|
+
it('should throw JobDoesNotExistError', async () => {
|
|
73
|
+
const apiClientMock = utils_1.getApiClientMock({
|
|
74
|
+
message: 'Job Not Found',
|
|
75
|
+
code: 404
|
|
76
|
+
}, 404);
|
|
77
|
+
const jobProgress = getJobProgress(apiClientMock, 'test-queue-name#test-job-id');
|
|
78
|
+
await expect(jobProgress.cancel()).rejects.toThrow(new errors_1.JobDoesNotExistError(`The job test-job-id was not found for the queue test-queue-name.`));
|
|
79
|
+
utils_1.verifyApiClientCalledWith(apiClientMock, '/webhook/queue/cancel/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
80
|
+
queueName: 'test-queue-name',
|
|
81
|
+
jobId: 'test-job-id'
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
it('should throw InternalServerError when WHP returns 422 response', async () => {
|
|
86
|
+
const apiClientMock = utils_1.getApiClientMock({
|
|
87
|
+
errors: ['jobId must not be null', 'queueName must not be null']
|
|
88
|
+
}, 422);
|
|
89
|
+
const jobProgress = getJobProgress(apiClientMock, 'test-queue-name#test-job-id');
|
|
90
|
+
await expect(jobProgress.getStats()).rejects.toThrow(new errors_1.InternalServerError(`422 Status Text: jobId must not be null, queueName must not be null`));
|
|
91
|
+
utils_1.verifyApiClientCalledWith(apiClientMock, '/webhook/queue/stats/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
92
|
+
queueName: 'test-queue-name',
|
|
93
|
+
jobId: 'test-job-id'
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
it('should throw errors when queueName or jobId is empty', async () => {
|
|
97
|
+
const apiClientMock = utils_1.getApiClientMock({
|
|
98
|
+
success: 100,
|
|
99
|
+
inProgress: 50,
|
|
100
|
+
failed: 1
|
|
101
|
+
}, 200);
|
|
102
|
+
const jobProgress1 = getJobProgress(apiClientMock, 'test-queue-name#');
|
|
103
|
+
await expect(jobProgress1.getStats()).rejects.toThrow(new errors_1.JobDoesNotExistError(`jobId cannot be empty.`));
|
|
104
|
+
const jobProgress2 = getJobProgress(apiClientMock, '#test-job-id');
|
|
105
|
+
await expect(jobProgress2.getStats()).rejects.toThrow(new errors_1.InvalidQueueNameError('Queue names can only contain alphanumeric characters, dashes and underscores.'));
|
|
106
|
+
const jobProgress3 = getJobProgress(apiClientMock, '');
|
|
107
|
+
await expect(jobProgress3.getStats()).rejects.toThrow(new errors_1.JobDoesNotExistError(`jobId cannot be empty.`));
|
|
108
|
+
expect(apiClientMock).toHaveBeenCalledTimes(0);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.test.d.ts","sourceRoot":"","sources":["../../src/__test__/queue.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const errors_1 = require("../errors");
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
const queue_1 = require("../queue");
|
|
6
|
+
const jobProgress_1 = require("../jobProgress");
|
|
7
|
+
const getQueue = (apiClientMock, queueName) => new queue_1.Queue({ key: queueName }, apiClientMock);
|
|
8
|
+
describe('Queue methods', () => {
|
|
9
|
+
describe('constructor', () => {
|
|
10
|
+
it('should throw InvalidQueueNameError', async () => {
|
|
11
|
+
const apiClientMock = utils_1.getApiClientMock();
|
|
12
|
+
expect(() => getQueue(apiClientMock, 'invalid name')).toThrowError(new errors_1.InvalidQueueNameError('Queue names can only contain alphanumeric characters, dashes and underscores.'));
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
describe('push', () => {
|
|
16
|
+
it('should call the queue/publish endpoint', async () => {
|
|
17
|
+
const apiClientMock = utils_1.getApiClientMock();
|
|
18
|
+
const queue = getQueue(apiClientMock, 'name');
|
|
19
|
+
const payload = {
|
|
20
|
+
page: 1
|
|
21
|
+
};
|
|
22
|
+
await queue.push([payload]);
|
|
23
|
+
utils_1.verifyApiClientCalledPushPathWith(apiClientMock, [payload], 'name');
|
|
24
|
+
});
|
|
25
|
+
it('should throw InvalidPushSettingsError for delay', async () => {
|
|
26
|
+
const apiClientMock = utils_1.getApiClientMock();
|
|
27
|
+
const queue = getQueue(apiClientMock, 'name');
|
|
28
|
+
await expect(queue.push(1, { delayInSeconds: 901 })).rejects.toThrow(new errors_1.InvalidPushSettingsError(`The delayInSeconds setting must be between 0 and 900.`));
|
|
29
|
+
expect(apiClientMock).toHaveBeenCalledTimes(0);
|
|
30
|
+
});
|
|
31
|
+
it('should throw NoEventsToPushError', async () => {
|
|
32
|
+
const apiClientMock = utils_1.getApiClientMock();
|
|
33
|
+
const queue = getQueue(apiClientMock, 'name');
|
|
34
|
+
await expect(queue.push([])).rejects.toThrow(new errors_1.NoEventsToPushError(`No events pushed.`));
|
|
35
|
+
expect(apiClientMock).toHaveBeenCalledTimes(0);
|
|
36
|
+
});
|
|
37
|
+
it('should throw TooManyEventsError', async () => {
|
|
38
|
+
const apiClientMock = utils_1.getApiClientMock();
|
|
39
|
+
const queue = getQueue(apiClientMock, 'name');
|
|
40
|
+
await expect(queue.push([...Array(51).keys()])).rejects.toThrow(new errors_1.TooManyEventsError(`This push contains more than the 50 events allowed.`));
|
|
41
|
+
expect(apiClientMock).toHaveBeenCalledTimes(0);
|
|
42
|
+
});
|
|
43
|
+
it('should throw PayloadTooBigError', async () => {
|
|
44
|
+
const apiClientMock = utils_1.getApiClientMock();
|
|
45
|
+
const queue = getQueue(apiClientMock, 'name');
|
|
46
|
+
await expect(queue.push('x'.repeat(201 * 1024))).rejects.toThrow(new errors_1.PayloadTooBigError(`The maximum payload size is 200KB.`));
|
|
47
|
+
expect(apiClientMock).toHaveBeenCalledTimes(0);
|
|
48
|
+
});
|
|
49
|
+
it('should throw RateLimitError', async () => {
|
|
50
|
+
const apiClientMock = utils_1.getApiClientMock({}, 429);
|
|
51
|
+
const queue = getQueue(apiClientMock, 'name');
|
|
52
|
+
const payload = [...Array(10).keys()];
|
|
53
|
+
await expect(queue.push(payload)).rejects.toThrow(new errors_1.RateLimitError(`Too many requests.`));
|
|
54
|
+
utils_1.verifyApiClientCalledPushPathWith(apiClientMock, payload, 'name');
|
|
55
|
+
});
|
|
56
|
+
it('should throw InvocationLimitReachedError', async () => {
|
|
57
|
+
const apiClientMock = utils_1.getApiClientMock({}, 405);
|
|
58
|
+
const queue = getQueue(apiClientMock, 'name');
|
|
59
|
+
const payload = [...Array(5).keys()];
|
|
60
|
+
await expect(queue.push(payload)).rejects.toThrow(new errors_1.InvocationLimitReachedError(`The limit on cyclic invocation has been reached.`));
|
|
61
|
+
utils_1.verifyApiClientCalledPushPathWith(apiClientMock, payload, 'name');
|
|
62
|
+
});
|
|
63
|
+
it('should throw PartialSuccessError when there are failed events', async () => {
|
|
64
|
+
const apiClientMock = utils_1.getApiClientMock({
|
|
65
|
+
failedEvents: [
|
|
66
|
+
{
|
|
67
|
+
index: '0',
|
|
68
|
+
errorMessage: 'failed-1'
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
index: 2,
|
|
72
|
+
errorMessage: 'failed-3'
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}, 202);
|
|
76
|
+
const queue = getQueue(apiClientMock, 'name');
|
|
77
|
+
const payload = [
|
|
78
|
+
{
|
|
79
|
+
content: 'payload-1'
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
content: 'payload-2'
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
content: 'payload-3'
|
|
86
|
+
}
|
|
87
|
+
];
|
|
88
|
+
await expect(queue.push(payload)).rejects.toThrow(new errors_1.PartialSuccessError(`Failed to process 2 event(s).`, [
|
|
89
|
+
{
|
|
90
|
+
errorMessage: 'failed-1',
|
|
91
|
+
payload: {
|
|
92
|
+
content: 'payload-1'
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
errorMessage: 'failed-3',
|
|
97
|
+
payload: {
|
|
98
|
+
content: 'payload-3'
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
]));
|
|
102
|
+
utils_1.verifyApiClientCalledPushPathWith(apiClientMock, payload, 'name');
|
|
103
|
+
});
|
|
104
|
+
it('should throw PartialSuccessError when backend failed to create job stats', async () => {
|
|
105
|
+
const apiClientMock = utils_1.getApiClientMock({
|
|
106
|
+
errorMessage: 'Failed to create stats for job name#12345'
|
|
107
|
+
}, 202);
|
|
108
|
+
const queue = getQueue(apiClientMock, 'name');
|
|
109
|
+
const payload = [
|
|
110
|
+
{
|
|
111
|
+
content: 'payload-1'
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
content: 'payload-2'
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
content: 'payload-3'
|
|
118
|
+
}
|
|
119
|
+
];
|
|
120
|
+
await expect(queue.push(payload)).rejects.toThrow(new errors_1.PartialSuccessError(`Failed to create stats for job name#12345`, []));
|
|
121
|
+
utils_1.verifyApiClientCalledPushPathWith(apiClientMock, payload, 'name');
|
|
122
|
+
});
|
|
123
|
+
it('should throw PartialSuccessError when there are failed events and backend failed to create job stats', async () => {
|
|
124
|
+
const apiClientMock = utils_1.getApiClientMock({
|
|
125
|
+
errorMessage: 'Failed to create stats for job name#12345',
|
|
126
|
+
failedEvents: [
|
|
127
|
+
{
|
|
128
|
+
index: '0',
|
|
129
|
+
errorMessage: 'failed-1'
|
|
130
|
+
}
|
|
131
|
+
]
|
|
132
|
+
}, 202);
|
|
133
|
+
const queue = getQueue(apiClientMock, 'name');
|
|
134
|
+
const payload = [
|
|
135
|
+
{
|
|
136
|
+
content: 'payload-1'
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
content: 'payload-2'
|
|
140
|
+
}
|
|
141
|
+
];
|
|
142
|
+
await expect(queue.push(payload)).rejects.toThrow(new errors_1.PartialSuccessError(`Failed to process 1 event(s). Failed to create stats for job name#12345`, [
|
|
143
|
+
{
|
|
144
|
+
errorMessage: 'failed-1',
|
|
145
|
+
payload: {
|
|
146
|
+
content: 'payload-1'
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
]));
|
|
150
|
+
utils_1.verifyApiClientCalledPushPathWith(apiClientMock, payload, 'name');
|
|
151
|
+
});
|
|
152
|
+
it('should throw InternalServerError', async () => {
|
|
153
|
+
const apiClientMock = utils_1.getApiClientMock({
|
|
154
|
+
message: 'AWS SQS timed out',
|
|
155
|
+
code: 500,
|
|
156
|
+
details: 'The request processing has failed because of an unknown error, exception or failure'
|
|
157
|
+
}, 500);
|
|
158
|
+
const queue = getQueue(apiClientMock, 'name');
|
|
159
|
+
const payload = [...Array(9).keys()];
|
|
160
|
+
await expect(queue.push(payload)).rejects.toThrow(new errors_1.InternalServerError(`500 Status Text: AWS SQS timed out`, 500, 'The request processing has failed because of an unknown error, exception or failure'));
|
|
161
|
+
utils_1.verifyApiClientCalledPushPathWith(apiClientMock, payload, 'name');
|
|
162
|
+
});
|
|
163
|
+
it('should throw InternalServerError for error response without response body', async () => {
|
|
164
|
+
const apiClientMock = utils_1.getApiClientMockWithoutResponseBody(504, 'Gateway Timeout');
|
|
165
|
+
const queue = getQueue(apiClientMock, 'name');
|
|
166
|
+
const payload = [1];
|
|
167
|
+
await expect(queue.push(1)).rejects.toThrow(new errors_1.InternalServerError(`504 Gateway Timeout`, 504));
|
|
168
|
+
utils_1.verifyApiClientCalledPushPathWith(apiClientMock, payload, 'name');
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
describe('getJob', () => {
|
|
172
|
+
it('should create a JobProgress by jobId', async () => {
|
|
173
|
+
const apiClientMock = utils_1.getApiClientMock();
|
|
174
|
+
const queue = getQueue(apiClientMock, 'name');
|
|
175
|
+
const jobProgress = queue.getJob('test-job-id');
|
|
176
|
+
expect(jobProgress).toEqual(new jobProgress_1.JobProgress('test-job-id', apiClientMock));
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queueResponse.test.d.ts","sourceRoot":"","sources":["../../src/__test__/queueResponse.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const queueResponse_1 = require("../queueResponse");
|
|
4
|
+
describe('QueueResponse', () => {
|
|
5
|
+
it('should contain property retry=false by default', async () => {
|
|
6
|
+
const res = new queueResponse_1.QueueResponse();
|
|
7
|
+
expect(JSON.stringify(res)).toEqual('{"_retry":false}');
|
|
8
|
+
});
|
|
9
|
+
it('doRetry() should change property retry=true', async () => {
|
|
10
|
+
const res = new queueResponse_1.QueueResponse();
|
|
11
|
+
res.retry();
|
|
12
|
+
expect(JSON.stringify(res)).toEqual('{"_retry":true}');
|
|
13
|
+
});
|
|
14
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/// <reference types="jest" />
|
|
2
|
+
import { Payload } from '../types';
|
|
3
|
+
export declare const getApiClientMock: (response?: any, statusCode?: number) => jest.Mock<any, any>;
|
|
4
|
+
export declare const getApiClientMockWithoutResponseBody: (statusCode: number, statusText: string) => jest.Mock<any, any>;
|
|
5
|
+
export declare const verifyApiClientCalledWith: (apiClientMock: jest.Mock, path: string, expectedBody: any) => void;
|
|
6
|
+
export declare const verifyApiClientCalledPushPathWith: (apiClientMock: jest.Mock, payloads: Payload | Payload[], name: string) => void;
|
|
7
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/__test__/utils.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,eAAO,MAAM,gBAAgB,cAAe,GAAG,6CAO9C,CAAC;AAEF,eAAO,MAAM,mCAAmC,eAAgB,MAAM,cAAc,MAAM,wBAMzF,CAAC;AAEF,eAAO,MAAM,yBAAyB,kBAAmB,IAAI,CAAC,IAAI,QAAQ,MAAM,gBAAgB,GAAG,SAclG,CAAC;AAEF,eAAO,MAAM,iCAAiC,kBAC7B,IAAI,CAAC,IAAI,YACd,OAAO,GAAG,OAAO,EAAE,QACvB,MAAM,SAQb,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.verifyApiClientCalledPushPathWith = exports.verifyApiClientCalledWith = exports.getApiClientMockWithoutResponseBody = exports.getApiClientMock = void 0;
|
|
4
|
+
exports.getApiClientMock = (response, statusCode = 201) => {
|
|
5
|
+
return jest.fn().mockReturnValue({
|
|
6
|
+
created: statusCode === 201,
|
|
7
|
+
status: statusCode,
|
|
8
|
+
statusText: 'Status Text',
|
|
9
|
+
json: jest.fn().mockResolvedValue(response)
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
exports.getApiClientMockWithoutResponseBody = (statusCode, statusText) => {
|
|
13
|
+
return jest.fn().mockReturnValue({
|
|
14
|
+
ok: statusCode === 200,
|
|
15
|
+
status: statusCode,
|
|
16
|
+
statusText: statusText
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
exports.verifyApiClientCalledWith = (apiClientMock, path, expectedBody) => {
|
|
20
|
+
expect(apiClientMock).toHaveBeenCalledWith(path, expect.objectContaining({
|
|
21
|
+
method: 'POST',
|
|
22
|
+
body: expect.any(String),
|
|
23
|
+
headers: {
|
|
24
|
+
'content-type': 'application/json'
|
|
25
|
+
}
|
|
26
|
+
}));
|
|
27
|
+
const [, { body }] = apiClientMock.mock.calls[0];
|
|
28
|
+
expect(JSON.parse(body)).toEqual(expect.objectContaining(expectedBody));
|
|
29
|
+
};
|
|
30
|
+
exports.verifyApiClientCalledPushPathWith = (apiClientMock, payloads, name) => {
|
|
31
|
+
exports.verifyApiClientCalledWith(apiClientMock, '/webhook/queue/publish/{cloudId}/{environmentId}/{appId}/{appVersion}', {
|
|
32
|
+
queueName: name,
|
|
33
|
+
schema: 'ari:cloud:ecosystem::forge/app-event',
|
|
34
|
+
type: 'avi:forge:app:event',
|
|
35
|
+
payload: payloads
|
|
36
|
+
});
|
|
37
|
+
};
|
package/out/errors.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { FailedEvent } from './types';
|
|
2
|
+
export declare class InvalidPushSettingsError extends Error {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
2
5
|
export declare class InvalidQueueNameError extends Error {
|
|
3
6
|
constructor(message: string);
|
|
4
7
|
}
|
|
@@ -23,4 +26,10 @@ export declare class InternalServerError extends Error {
|
|
|
23
26
|
errorCode?: number;
|
|
24
27
|
details?: string;
|
|
25
28
|
}
|
|
29
|
+
export declare class JobDoesNotExistError extends Error {
|
|
30
|
+
constructor(message: string);
|
|
31
|
+
}
|
|
32
|
+
export declare class InvocationLimitReachedError extends Error {
|
|
33
|
+
constructor(message: string);
|
|
34
|
+
}
|
|
26
35
|
//# sourceMappingURL=errors.d.ts.map
|
package/out/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE;IAKxD,YAAY,EAAE,WAAW,EAAE,CAAC;CAC7B;AAED,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;IAMjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE;IAKxD,YAAY,EAAE,WAAW,EAAE,CAAC;CAC7B;AAED,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;IAMjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,2BAA4B,SAAQ,KAAK;gBACxC,OAAO,EAAE,MAAM;CAG5B"}
|
package/out/errors.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.InternalServerError = exports.PartialSuccessError = exports.RateLimitError = exports.NoEventsToPushError = exports.PayloadTooBigError = exports.TooManyEventsError = exports.InvalidQueueNameError = void 0;
|
|
3
|
+
exports.InvocationLimitReachedError = exports.JobDoesNotExistError = exports.InternalServerError = exports.PartialSuccessError = exports.RateLimitError = exports.NoEventsToPushError = exports.PayloadTooBigError = exports.TooManyEventsError = exports.InvalidQueueNameError = exports.InvalidPushSettingsError = void 0;
|
|
4
|
+
class InvalidPushSettingsError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
exports.InvalidPushSettingsError = InvalidPushSettingsError;
|
|
4
10
|
class InvalidQueueNameError extends Error {
|
|
5
11
|
constructor(message) {
|
|
6
12
|
super(message);
|
|
@@ -46,3 +52,15 @@ class InternalServerError extends Error {
|
|
|
46
52
|
}
|
|
47
53
|
}
|
|
48
54
|
exports.InternalServerError = InternalServerError;
|
|
55
|
+
class JobDoesNotExistError extends Error {
|
|
56
|
+
constructor(message) {
|
|
57
|
+
super(message);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.JobDoesNotExistError = JobDoesNotExistError;
|
|
61
|
+
class InvocationLimitReachedError extends Error {
|
|
62
|
+
constructor(message) {
|
|
63
|
+
super(message);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.InvocationLimitReachedError = InvocationLimitReachedError;
|
package/out/index.d.ts
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
export { Queue } from './queue';
|
|
2
|
+
export { InvalidQueueNameError, TooManyEventsError, PayloadTooBigError, NoEventsToPushError, RateLimitError, PartialSuccessError, InternalServerError, JobDoesNotExistError, InvalidPushSettingsError, InvocationLimitReachedError } from './errors';
|
|
3
|
+
export { JobProgress } from './jobProgress';
|
|
4
|
+
export { QueueResponse } from './queueResponse';
|
|
2
5
|
//# sourceMappingURL=index.d.ts.map
|
package/out/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,wBAAwB,EACxB,2BAA2B,EAC5B,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
|
package/out/index.js
CHANGED
|
@@ -2,3 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
var queue_1 = require("./queue");
|
|
4
4
|
Object.defineProperty(exports, "Queue", { enumerable: true, get: function () { return queue_1.Queue; } });
|
|
5
|
+
var errors_1 = require("./errors");
|
|
6
|
+
Object.defineProperty(exports, "InvalidQueueNameError", { enumerable: true, get: function () { return errors_1.InvalidQueueNameError; } });
|
|
7
|
+
Object.defineProperty(exports, "TooManyEventsError", { enumerable: true, get: function () { return errors_1.TooManyEventsError; } });
|
|
8
|
+
Object.defineProperty(exports, "PayloadTooBigError", { enumerable: true, get: function () { return errors_1.PayloadTooBigError; } });
|
|
9
|
+
Object.defineProperty(exports, "NoEventsToPushError", { enumerable: true, get: function () { return errors_1.NoEventsToPushError; } });
|
|
10
|
+
Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return errors_1.RateLimitError; } });
|
|
11
|
+
Object.defineProperty(exports, "PartialSuccessError", { enumerable: true, get: function () { return errors_1.PartialSuccessError; } });
|
|
12
|
+
Object.defineProperty(exports, "InternalServerError", { enumerable: true, get: function () { return errors_1.InternalServerError; } });
|
|
13
|
+
Object.defineProperty(exports, "JobDoesNotExistError", { enumerable: true, get: function () { return errors_1.JobDoesNotExistError; } });
|
|
14
|
+
Object.defineProperty(exports, "InvalidPushSettingsError", { enumerable: true, get: function () { return errors_1.InvalidPushSettingsError; } });
|
|
15
|
+
Object.defineProperty(exports, "InvocationLimitReachedError", { enumerable: true, get: function () { return errors_1.InvocationLimitReachedError; } });
|
|
16
|
+
var jobProgress_1 = require("./jobProgress");
|
|
17
|
+
Object.defineProperty(exports, "JobProgress", { enumerable: true, get: function () { return jobProgress_1.JobProgress; } });
|
|
18
|
+
var queueResponse_1 = require("./queueResponse");
|
|
19
|
+
Object.defineProperty(exports, "QueueResponse", { enumerable: true, get: function () { return queueResponse_1.QueueResponse; } });
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { APIResponse, FetchMethod } from './types';
|
|
2
|
+
export declare class JobProgress {
|
|
3
|
+
private readonly apiClient;
|
|
4
|
+
private id;
|
|
5
|
+
constructor(id: string, apiClient?: FetchMethod);
|
|
6
|
+
getStats(): Promise<APIResponse>;
|
|
7
|
+
cancel(): Promise<APIResponse>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=jobProgress.d.ts.map
|
|
@@ -0,0 +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;AAEtF,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"}
|