@goatlab/tasks-adapter-gcp 0.3.4 ā 0.4.0
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/dist/CloudTaskConnector.d.ts +118 -9
- package/dist/CloudTaskConnector.js +147 -9
- package/dist/CloudTaskConnector.js.map +1 -1
- package/dist/MockCloudTaskConnector.d.ts +49 -0
- package/dist/MockCloudTaskConnector.js +146 -0
- package/dist/MockCloudTaskConnector.js.map +1 -0
- package/dist/benchmark.d.ts +17 -0
- package/dist/benchmark.js +260 -0
- package/dist/benchmark.js.map +1 -0
- package/dist/cloudtask.spec.js +144 -52
- package/dist/cloudtask.spec.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* GCP Cloud Tasks Benchmark Script
|
|
4
|
+
*
|
|
5
|
+
* Run with: npx tsx src/benchmark.ts [mode]
|
|
6
|
+
*
|
|
7
|
+
* Modes:
|
|
8
|
+
* (default) - Run queue throughput benchmark
|
|
9
|
+
* payload - Compare different payload sizes
|
|
10
|
+
* batch - Compare different batch sizes
|
|
11
|
+
*
|
|
12
|
+
* Requires FIREBASE_SERVICE_ACCOUNT environment variable.
|
|
13
|
+
*
|
|
14
|
+
* Note: GCP Cloud Tasks is HTTP callback based, so we can only measure
|
|
15
|
+
* queue throughput (enqueue rate). E2E and latency tests would require
|
|
16
|
+
* a real HTTP endpoint to receive callbacks.
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
require("dotenv/config");
|
|
20
|
+
const tasks_core_1 = require("@goatlab/tasks-core");
|
|
21
|
+
const CloudTaskConnector_js_1 = require("./CloudTaskConnector.js");
|
|
22
|
+
// Configuration
|
|
23
|
+
const WARMUP_COUNT = 10;
|
|
24
|
+
const BENCHMARK_DURATION_MS = 10000; // 10 seconds (GCP has rate limits)
|
|
25
|
+
const DEFAULT_BATCH_SIZE = 10; // Smaller batches for GCP rate limits
|
|
26
|
+
// Parse service account
|
|
27
|
+
const serviceAccountBase64 = process.env.FIREBASE_SERVICE_ACCOUNT;
|
|
28
|
+
if (!serviceAccountBase64) {
|
|
29
|
+
console.error('ā FIREBASE_SERVICE_ACCOUNT environment variable is required');
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
const serviceAccountJson = Buffer.from(serviceAccountBase64, 'base64').toString('utf8');
|
|
33
|
+
const gcpServiceAccount = JSON.parse(serviceAccountJson);
|
|
34
|
+
class BenchmarkTask extends tasks_core_1.ShouldQueue {
|
|
35
|
+
postUrl;
|
|
36
|
+
taskName;
|
|
37
|
+
constructor(connector, name) {
|
|
38
|
+
super({ connector });
|
|
39
|
+
this.taskName = name;
|
|
40
|
+
// Use httpbin to accept the POST (though we won't wait for it)
|
|
41
|
+
this.postUrl = 'https://httpbin.org/post';
|
|
42
|
+
}
|
|
43
|
+
async handle() {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function runQueueBenchmark(_connector, task, batchSize = DEFAULT_BATCH_SIZE) {
|
|
48
|
+
console.log('\nš Queue Throughput (enqueue to GCP)');
|
|
49
|
+
console.log('='.repeat(50));
|
|
50
|
+
console.log(`Batch size: ${batchSize}`);
|
|
51
|
+
// Warmup
|
|
52
|
+
console.log(`Warming up (${WARMUP_COUNT} tasks)...`);
|
|
53
|
+
for (let i = 0; i < WARMUP_COUNT; i++) {
|
|
54
|
+
try {
|
|
55
|
+
await task.queue({ index: i });
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
console.log(`Warmup error: ${err.message}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
console.log(`Running for ${BENCHMARK_DURATION_MS / 1000}s...`);
|
|
62
|
+
let count = 0;
|
|
63
|
+
let errors = 0;
|
|
64
|
+
const startTime = Date.now();
|
|
65
|
+
const endTime = startTime + BENCHMARK_DURATION_MS;
|
|
66
|
+
while (Date.now() < endTime) {
|
|
67
|
+
const promises = [];
|
|
68
|
+
for (let i = 0; i < batchSize; i++) {
|
|
69
|
+
promises.push(task.queue({ index: count++ }).catch(_err => {
|
|
70
|
+
errors++;
|
|
71
|
+
return null;
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
await Promise.all(promises);
|
|
75
|
+
}
|
|
76
|
+
const elapsed = Date.now() - startTime;
|
|
77
|
+
const successful = count - errors;
|
|
78
|
+
const throughput = (successful / elapsed) * 1000;
|
|
79
|
+
console.log(`ā
Attempted: ${count.toLocaleString()} tasks`);
|
|
80
|
+
console.log(`ā
Successful: ${successful.toLocaleString()} tasks`);
|
|
81
|
+
console.log(`ā Errors: ${errors.toLocaleString()} tasks`);
|
|
82
|
+
console.log(`ā
Throughput: ${throughput.toFixed(1)} tasks/sec`);
|
|
83
|
+
return { throughput, successful, errors };
|
|
84
|
+
}
|
|
85
|
+
async function runSequentialBenchmark(_connector, task) {
|
|
86
|
+
console.log('\nš Sequential Queue (one at a time)');
|
|
87
|
+
console.log('='.repeat(50));
|
|
88
|
+
const count = 50;
|
|
89
|
+
const latencies = [];
|
|
90
|
+
for (let i = 0; i < count; i++) {
|
|
91
|
+
const start = Date.now();
|
|
92
|
+
try {
|
|
93
|
+
await task.queue({ index: i });
|
|
94
|
+
latencies.push(Date.now() - start);
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
console.log(`Error at ${i}: ${err.message}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (latencies.length === 0) {
|
|
101
|
+
console.log('ā No successful queues');
|
|
102
|
+
return { avg: 0, p50: 0, p95: 0, throughput: 0 };
|
|
103
|
+
}
|
|
104
|
+
latencies.sort((a, b) => a - b);
|
|
105
|
+
const avg = latencies.reduce((a, b) => a + b, 0) / latencies.length;
|
|
106
|
+
const p50 = latencies[Math.floor(latencies.length * 0.5)];
|
|
107
|
+
const p95 = latencies[Math.floor(latencies.length * 0.95)];
|
|
108
|
+
const throughput = 1000 / avg;
|
|
109
|
+
console.log(`ā
Samples: ${latencies.length}`);
|
|
110
|
+
console.log(`ā
Avg latency: ${avg.toFixed(0)}ms | P50: ${p50}ms | P95: ${p95}ms`);
|
|
111
|
+
console.log(`ā
Sequential throughput: ${throughput.toFixed(1)} tasks/sec`);
|
|
112
|
+
return { avg, p50, p95, throughput };
|
|
113
|
+
}
|
|
114
|
+
async function runPayloadComparison(connector) {
|
|
115
|
+
console.log('\nš Payload Size Comparison');
|
|
116
|
+
console.log('='.repeat(50));
|
|
117
|
+
const results = [];
|
|
118
|
+
const payloads = [
|
|
119
|
+
{ name: 'Tiny (100B)', data: 'x'.repeat(80) },
|
|
120
|
+
{ name: 'Small (1KB)', data: 'x'.repeat(900) },
|
|
121
|
+
{ name: 'Medium (10KB)', data: 'x'.repeat(10000) },
|
|
122
|
+
{ name: 'Large (50KB)', data: 'x'.repeat(50000) },
|
|
123
|
+
// GCP Cloud Tasks has a 100KB limit for task payload
|
|
124
|
+
{ name: 'Max (95KB)', data: 'x'.repeat(95000) }
|
|
125
|
+
];
|
|
126
|
+
for (const payload of payloads) {
|
|
127
|
+
const bytes = JSON.stringify({ index: 0, data: payload.data }).length;
|
|
128
|
+
console.log(`\nš Payload: ${payload.name} (~${(bytes / 1024).toFixed(1)}KB)`);
|
|
129
|
+
const task = new BenchmarkTask(connector, `bench_payload_${Date.now()}`);
|
|
130
|
+
task.postUrl = 'https://httpbin.org/post';
|
|
131
|
+
// Smaller test for payload comparison
|
|
132
|
+
const testDuration = 5000;
|
|
133
|
+
let count = 0;
|
|
134
|
+
let errors = 0;
|
|
135
|
+
const startTime = Date.now();
|
|
136
|
+
const endTime = startTime + testDuration;
|
|
137
|
+
while (Date.now() < endTime) {
|
|
138
|
+
try {
|
|
139
|
+
await task.queue({ index: count++, data: payload.data });
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
errors++;
|
|
143
|
+
if (errors === 1) {
|
|
144
|
+
console.log(`First error: ${err.message?.slice(0, 100)}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const elapsed = Date.now() - startTime;
|
|
149
|
+
const throughput = ((count - errors) / elapsed) * 1000;
|
|
150
|
+
console.log(`ā
Throughput: ${throughput.toFixed(1)} tasks/sec (${errors} errors)`);
|
|
151
|
+
results.push({ size: payload.name, bytes, throughput, errors });
|
|
152
|
+
}
|
|
153
|
+
// Summary
|
|
154
|
+
console.log(`\n${'='.repeat(50)}`);
|
|
155
|
+
console.log('š PAYLOAD SIZE COMPARISON');
|
|
156
|
+
console.log('='.repeat(50));
|
|
157
|
+
const maxThroughput = Math.max(...results.map(r => r.throughput));
|
|
158
|
+
for (const r of results) {
|
|
159
|
+
const pct = maxThroughput > 0 ? Math.round((r.throughput / maxThroughput) * 100) : 0;
|
|
160
|
+
console.log(`${r.size.padEnd(15)} ${r.throughput.toFixed(1).padStart(8)} tasks/sec (${pct.toString().padStart(3)}%) ${r.errors} errors`);
|
|
161
|
+
}
|
|
162
|
+
return results;
|
|
163
|
+
}
|
|
164
|
+
async function runBatchComparison(connector) {
|
|
165
|
+
console.log('\nš Batch Size Comparison');
|
|
166
|
+
console.log('='.repeat(50));
|
|
167
|
+
const results = [];
|
|
168
|
+
const batchSizes = [1, 5, 10, 20, 50];
|
|
169
|
+
for (const batchSize of batchSizes) {
|
|
170
|
+
console.log(`\nš Batch size: ${batchSize}`);
|
|
171
|
+
const task = new BenchmarkTask(connector, `bench_batch_${Date.now()}`);
|
|
172
|
+
const testDuration = 5000;
|
|
173
|
+
let count = 0;
|
|
174
|
+
let errors = 0;
|
|
175
|
+
const startTime = Date.now();
|
|
176
|
+
const endTime = startTime + testDuration;
|
|
177
|
+
while (Date.now() < endTime) {
|
|
178
|
+
const promises = [];
|
|
179
|
+
for (let i = 0; i < batchSize; i++) {
|
|
180
|
+
promises.push(task.queue({ index: count++ }).catch(() => {
|
|
181
|
+
errors++;
|
|
182
|
+
return null;
|
|
183
|
+
}));
|
|
184
|
+
}
|
|
185
|
+
await Promise.all(promises);
|
|
186
|
+
}
|
|
187
|
+
const elapsed = Date.now() - startTime;
|
|
188
|
+
const throughput = ((count - errors) / elapsed) * 1000;
|
|
189
|
+
console.log(`ā
Throughput: ${throughput.toFixed(1)} tasks/sec (${errors} errors)`);
|
|
190
|
+
results.push({ batchSize, throughput, errors });
|
|
191
|
+
}
|
|
192
|
+
// Summary
|
|
193
|
+
console.log(`\n${'='.repeat(50)}`);
|
|
194
|
+
console.log('š BATCH SIZE COMPARISON');
|
|
195
|
+
console.log('='.repeat(50));
|
|
196
|
+
const maxThroughput = Math.max(...results.map(r => r.throughput));
|
|
197
|
+
for (const r of results) {
|
|
198
|
+
const pct = maxThroughput > 0 ? Math.round((r.throughput / maxThroughput) * 100) : 0;
|
|
199
|
+
console.log(`Batch ${r.batchSize.toString().padStart(2)}: ${r.throughput.toFixed(1).padStart(8)} tasks/sec (${pct.toString().padStart(3)}%) ${r.errors} errors`);
|
|
200
|
+
}
|
|
201
|
+
return results;
|
|
202
|
+
}
|
|
203
|
+
async function main() {
|
|
204
|
+
console.log('š GCP Cloud Tasks Benchmark');
|
|
205
|
+
console.log('='.repeat(50));
|
|
206
|
+
console.log(`Project: ${gcpServiceAccount.project_id}`);
|
|
207
|
+
console.log(`Location: europe-west1`);
|
|
208
|
+
console.log(`Queue: default`);
|
|
209
|
+
console.log('');
|
|
210
|
+
console.log('ā ļø Note: GCP Cloud Tasks has rate limits.');
|
|
211
|
+
console.log(' Results may vary based on quota and network latency.');
|
|
212
|
+
console.log('');
|
|
213
|
+
const connector = new CloudTaskConnector_js_1.CloudTaskConnector({
|
|
214
|
+
gcpServiceAccount,
|
|
215
|
+
location: 'europe-west1',
|
|
216
|
+
encryptionKey: 'benchmark-encryption-key-32ch!',
|
|
217
|
+
gcpProject: gcpServiceAccount.project_id
|
|
218
|
+
});
|
|
219
|
+
// Queue throughput test
|
|
220
|
+
const task1 = new BenchmarkTask(connector, `bench_queue_${Date.now()}`);
|
|
221
|
+
const queueResult = await runQueueBenchmark(connector, task1, DEFAULT_BATCH_SIZE);
|
|
222
|
+
// Sequential test (measures single-request latency)
|
|
223
|
+
const task2 = new BenchmarkTask(connector, `bench_seq_${Date.now()}`);
|
|
224
|
+
const seqResult = await runSequentialBenchmark(connector, task2);
|
|
225
|
+
// Summary
|
|
226
|
+
console.log(`\n${'='.repeat(50)}`);
|
|
227
|
+
console.log('š GCP CLOUD TASKS SUMMARY');
|
|
228
|
+
console.log('='.repeat(50));
|
|
229
|
+
console.log(`Parallel throughput: ${queueResult.throughput.toFixed(1)} tasks/sec (batch=${DEFAULT_BATCH_SIZE})`);
|
|
230
|
+
console.log(`Sequential throughput: ${seqResult.throughput.toFixed(1)} tasks/sec`);
|
|
231
|
+
console.log(`Avg queue latency: ${seqResult.avg.toFixed(0)}ms`);
|
|
232
|
+
console.log(`P95 queue latency: ${seqResult.p95}ms`);
|
|
233
|
+
console.log('');
|
|
234
|
+
console.log('Note: E2E throughput cannot be measured without an HTTP endpoint');
|
|
235
|
+
console.log(' to receive GCP callbacks.');
|
|
236
|
+
}
|
|
237
|
+
// CLI
|
|
238
|
+
const mode = process.argv[2];
|
|
239
|
+
if (mode === 'payload') {
|
|
240
|
+
const connector = new CloudTaskConnector_js_1.CloudTaskConnector({
|
|
241
|
+
gcpServiceAccount,
|
|
242
|
+
location: 'europe-west1',
|
|
243
|
+
encryptionKey: 'benchmark-encryption-key-32ch!',
|
|
244
|
+
gcpProject: gcpServiceAccount.project_id
|
|
245
|
+
});
|
|
246
|
+
runPayloadComparison(connector).catch(console.error);
|
|
247
|
+
}
|
|
248
|
+
else if (mode === 'batch') {
|
|
249
|
+
const connector = new CloudTaskConnector_js_1.CloudTaskConnector({
|
|
250
|
+
gcpServiceAccount,
|
|
251
|
+
location: 'europe-west1',
|
|
252
|
+
encryptionKey: 'benchmark-encryption-key-32ch!',
|
|
253
|
+
gcpProject: gcpServiceAccount.project_id
|
|
254
|
+
});
|
|
255
|
+
runBatchComparison(connector).catch(console.error);
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
main().catch(console.error);
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=benchmark.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchmark.js","sourceRoot":"","sources":["../src/benchmark.ts"],"names":[],"mappings":"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"}
|
package/dist/cloudtask.spec.js
CHANGED
|
@@ -1,65 +1,157 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// npx vitest
|
|
2
|
+
// npx vitest run ./src/cloudtask.spec.ts
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
const tasks_core_1 = require("@goatlab/tasks-core");
|
|
5
|
+
const test_suite_1 = require("@goatlab/tasks-core/test-suite");
|
|
5
6
|
const vitest_1 = require("vitest");
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
console.log('Running task with body:', taskBody);
|
|
12
|
-
return undefined;
|
|
13
|
-
}
|
|
7
|
+
const CloudTaskConnector_js_1 = require("./CloudTaskConnector.js");
|
|
8
|
+
// Parse service account from env
|
|
9
|
+
const serviceAccountBase64 = process.env.FIREBASE_SERVICE_ACCOUNT;
|
|
10
|
+
if (!serviceAccountBase64) {
|
|
11
|
+
throw new Error('FIREBASE_SERVICE_ACCOUNT environment variable is required');
|
|
14
12
|
}
|
|
15
|
-
(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
13
|
+
const serviceAccountJson = Buffer.from(serviceAccountBase64, 'base64').toString('utf8');
|
|
14
|
+
const gcpServiceAccount = JSON.parse(serviceAccountJson);
|
|
15
|
+
// Create real GCP Cloud Tasks connector
|
|
16
|
+
const cloudTaskConnector = new CloudTaskConnector_js_1.CloudTaskConnector({
|
|
17
|
+
gcpServiceAccount,
|
|
18
|
+
location: 'europe-west1',
|
|
19
|
+
encryptionKey: 'test-encryption-key-32chars!!!!',
|
|
20
|
+
gcpProject: gcpServiceAccount.project_id,
|
|
21
|
+
// Enable payload cache for testing - GCP removes completed tasks immediately
|
|
22
|
+
enablePayloadCache: true
|
|
23
|
+
});
|
|
24
|
+
// Run the standardized test suite
|
|
25
|
+
// Note: GCP Cloud Tasks uses HTTP callbacks, not workers.
|
|
26
|
+
// For lifecycle tests, tasks will fail because there's no real HTTP endpoint.
|
|
27
|
+
// We skip lifecycle tests since GCP doesn't have a startWorker concept.
|
|
28
|
+
(0, test_suite_1.taskConnectorTestSuite)({ describe: vitest_1.describe, it: vitest_1.it, expect: vitest_1.expect, beforeAll: vitest_1.beforeAll, afterAll: vitest_1.afterAll, beforeEach: vitest_1.beforeEach, afterEach: vitest_1.afterEach }, () => cloudTaskConnector, {
|
|
29
|
+
taskCompletionTimeout: 30000,
|
|
30
|
+
statusCheckInterval: 2000,
|
|
31
|
+
// Skip lifecycle tests - GCP Cloud Tasks doesn't use workers,
|
|
32
|
+
// it uses HTTP callbacks. Without a real HTTP server, tasks will fail.
|
|
33
|
+
skipLifecycleTests: true,
|
|
34
|
+
// No startWorker for GCP - it's HTTP callback based
|
|
35
|
+
startWorker: undefined
|
|
36
|
+
});
|
|
37
|
+
// GCP-specific tests for the HTTP callback model
|
|
38
|
+
(0, vitest_1.describe)('CloudTaskConnector GCP-Specific Tests', () => {
|
|
39
|
+
(0, vitest_1.it)('should queue a task and get its status', async () => {
|
|
40
|
+
class TestTask extends tasks_core_1.ShouldQueue {
|
|
41
|
+
postUrl = 'https://httpbin.org/post';
|
|
42
|
+
taskName = 'gcp_test_task';
|
|
43
|
+
constructor() {
|
|
44
|
+
super({ connector: cloudTaskConnector });
|
|
45
|
+
}
|
|
46
|
+
async handle() {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
49
|
}
|
|
50
|
-
const
|
|
50
|
+
const task = new TestTask();
|
|
51
|
+
const status = await task.queue({ text: 'Hello GCP!' });
|
|
51
52
|
(0, vitest_1.expect)(status).toHaveProperty('id');
|
|
52
53
|
(0, vitest_1.expect)(status).toHaveProperty('name');
|
|
53
54
|
(0, vitest_1.expect)(status).toHaveProperty('status', 'QUEUED');
|
|
54
55
|
(0, vitest_1.expect)(status).toHaveProperty('attempts', 0);
|
|
55
|
-
(0, vitest_1.expect)(status.name).toContain('
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
(0, vitest_1.expect)(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
(0, vitest_1.expect)(status.name).toContain('gcp_test_task');
|
|
57
|
+
// Get status - task may have already been dispatched or completed
|
|
58
|
+
// GCP Cloud Tasks removes completed tasks, so payload may be empty if task completed quickly
|
|
59
|
+
const fullStatus = await task.getStatus(status.id);
|
|
60
|
+
(0, vitest_1.expect)(fullStatus).toHaveProperty('id');
|
|
61
|
+
// If task still exists, check payload; if completed/removed, payload will be empty
|
|
62
|
+
if (fullStatus.status !== 'COMPLETED' ||
|
|
63
|
+
Object.keys(fullStatus.payload).length > 0) {
|
|
64
|
+
(0, vitest_1.expect)(fullStatus.payload).toHaveProperty('text', 'Hello GCP!');
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
(0, vitest_1.it)('should queue task with valid but unreachable endpoint', async () => {
|
|
68
|
+
class UnreachableTask extends tasks_core_1.ShouldQueue {
|
|
69
|
+
// Use a valid URL that will timeout/fail when GCP tries to call it
|
|
70
|
+
postUrl = 'https://example.invalid/webhook';
|
|
71
|
+
taskName = 'gcp_unreachable_task';
|
|
72
|
+
constructor() {
|
|
73
|
+
super({ connector: cloudTaskConnector });
|
|
74
|
+
}
|
|
75
|
+
async handle() {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const task = new UnreachableTask();
|
|
80
|
+
const status = await task.queue({ text: 'This endpoint is unreachable' });
|
|
81
|
+
(0, vitest_1.expect)(status).toHaveProperty('id');
|
|
82
|
+
(0, vitest_1.expect)(status.status).toBe('QUEUED');
|
|
83
|
+
// The task will eventually fail since the endpoint is unreachable
|
|
84
|
+
// We just verify we can queue and get status
|
|
85
|
+
const fullStatus = await task.getStatus(status.id);
|
|
86
|
+
(0, vitest_1.expect)(fullStatus).toHaveProperty('payload');
|
|
87
|
+
});
|
|
88
|
+
(0, vitest_1.it)('should encrypt task body to base64 string', () => {
|
|
89
|
+
const original = { text: 'secret data', nested: { value: 123 } };
|
|
90
|
+
// encryptBody expects an object with 'content' key containing stringified data
|
|
91
|
+
const encrypted = cloudTaskConnector.encryptBody({
|
|
92
|
+
content: JSON.stringify(original)
|
|
93
|
+
});
|
|
94
|
+
(0, vitest_1.expect)(encrypted).toBeDefined();
|
|
95
|
+
(0, vitest_1.expect)(typeof encrypted === 'string').toBe(true);
|
|
96
|
+
// Should be base64 encoded
|
|
97
|
+
(0, vitest_1.expect)(() => Buffer.from(encrypted, 'base64')).not.toThrow();
|
|
98
|
+
});
|
|
99
|
+
(0, vitest_1.it)('should expose tenantId when set', () => {
|
|
100
|
+
const tenantConnector = new CloudTaskConnector_js_1.CloudTaskConnector({
|
|
101
|
+
gcpServiceAccount,
|
|
102
|
+
location: 'europe-west1',
|
|
103
|
+
encryptionKey: 'test-encryption-key-32chars!!!!',
|
|
104
|
+
gcpProject: gcpServiceAccount.project_id,
|
|
105
|
+
tenantId: 'test-tenant'
|
|
106
|
+
});
|
|
107
|
+
(0, vitest_1.expect)(tenantConnector.tenantId).toBe('test-tenant');
|
|
63
108
|
});
|
|
109
|
+
(0, vitest_1.it)('should have undefined tenantId when not set', () => {
|
|
110
|
+
(0, vitest_1.expect)(cloudTaskConnector.tenantId).toBeUndefined();
|
|
111
|
+
});
|
|
112
|
+
(0, vitest_1.it)('forTenant() should create a new connector with tenant prefix', () => {
|
|
113
|
+
const tenantConnector = cloudTaskConnector.forTenant('acme-corp');
|
|
114
|
+
(0, vitest_1.expect)(tenantConnector.tenantId).toBe('acme-corp');
|
|
115
|
+
// Original connector should be unchanged
|
|
116
|
+
(0, vitest_1.expect)(cloudTaskConnector.tenantId).toBeUndefined();
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
// Multi-tenant isolation tests using task name prefixes
|
|
120
|
+
// Note: GCP Cloud Tasks uses HTTP callbacks (push model), not workers (pull model).
|
|
121
|
+
// The multi-tenant tests verify task isolation and basic API operations.
|
|
122
|
+
const baseConnector = new CloudTaskConnector_js_1.CloudTaskConnector({
|
|
123
|
+
gcpServiceAccount,
|
|
124
|
+
location: 'europe-west1',
|
|
125
|
+
encryptionKey: 'test-encryption-key-32chars!!!!',
|
|
126
|
+
gcpProject: gcpServiceAccount.project_id,
|
|
127
|
+
// Enable payload cache for testing - GCP removes completed tasks immediately
|
|
128
|
+
enablePayloadCache: true
|
|
129
|
+
});
|
|
130
|
+
// Store tenant connectors for cleanup
|
|
131
|
+
const tenantConnectors = new Map();
|
|
132
|
+
(0, test_suite_1.multiTenantTestSuite)({ describe: vitest_1.describe, it: vitest_1.it, expect: vitest_1.expect, beforeAll: vitest_1.beforeAll, afterAll: vitest_1.afterAll, beforeEach: vitest_1.beforeEach, afterEach: vitest_1.afterEach }, {
|
|
133
|
+
createTenantConnector: tenantId => {
|
|
134
|
+
const tenantConnector = baseConnector.forTenant(tenantId);
|
|
135
|
+
tenantConnectors.set(tenantId, tenantConnector);
|
|
136
|
+
return tenantConnector;
|
|
137
|
+
},
|
|
138
|
+
// GCP Cloud Tasks uses HTTP callbacks, not workers.
|
|
139
|
+
// We provide a no-op startWorker since GCP pushes to the HTTP endpoint.
|
|
140
|
+
startTenantWorker: async (_tenantId, _tasks) => {
|
|
141
|
+
// GCP Cloud Tasks is push-based (HTTP callbacks), not pull-based (workers)
|
|
142
|
+
// The task completes when GCP receives a 2xx response from the endpoint
|
|
143
|
+
return async () => {
|
|
144
|
+
// No cleanup needed - GCP handles queue management
|
|
145
|
+
};
|
|
146
|
+
},
|
|
147
|
+
taskCompletionTimeout: 30000,
|
|
148
|
+
statusCheckInterval: 2000,
|
|
149
|
+
workerStartupDelay: 1000,
|
|
150
|
+
supportsForTenant: true,
|
|
151
|
+
// Use a real HTTP endpoint that GCP can reach and will return 200 OK
|
|
152
|
+
testPostUrl: 'https://httpbin.org/post',
|
|
153
|
+
// Skip data isolation tests - GCP tasks are identified by full path which
|
|
154
|
+
// includes the task name, so cross-tenant getStatus would require different logic
|
|
155
|
+
runIsolationTests: false
|
|
64
156
|
});
|
|
65
157
|
//# sourceMappingURL=cloudtask.spec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudtask.spec.js","sourceRoot":"","sources":["../src/cloudtask.spec.ts"],"names":[],"mappings":";AAAA,
|
|
1
|
+
{"version":3,"file":"cloudtask.spec.js","sourceRoot":"","sources":["../src/cloudtask.spec.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export
|
|
1
|
+
export type { CloudTaskConnectorConfig } from './CloudTaskConnector.js';
|
|
2
|
+
export { CloudTaskConnector } from './CloudTaskConnector.js';
|
|
3
|
+
export type { GCPServiceAccount } from './CloudTaskConnector.types.js';
|
|
4
|
+
export { MockCloudTaskConnector } from './MockCloudTaskConnector.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CloudTaskConnector = void 0;
|
|
4
|
-
var
|
|
5
|
-
Object.defineProperty(exports, "CloudTaskConnector", { enumerable: true, get: function () { return
|
|
3
|
+
exports.MockCloudTaskConnector = exports.CloudTaskConnector = void 0;
|
|
4
|
+
var CloudTaskConnector_js_1 = require("./CloudTaskConnector.js");
|
|
5
|
+
Object.defineProperty(exports, "CloudTaskConnector", { enumerable: true, get: function () { return CloudTaskConnector_js_1.CloudTaskConnector; } });
|
|
6
|
+
var MockCloudTaskConnector_js_1 = require("./MockCloudTaskConnector.js");
|
|
7
|
+
Object.defineProperty(exports, "MockCloudTaskConnector", { enumerable: true, get: function () { return MockCloudTaskConnector_js_1.MockCloudTaskConnector; } });
|
|
6
8
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,iEAA4D;AAAnD,2HAAA,kBAAkB,OAAA;AAE3B,yEAAoE;AAA3D,mIAAA,sBAAsB,OAAA"}
|