@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.
@@ -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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"}
@@ -1,65 +1,157 @@
1
1
  "use strict";
2
- // npx vitest test ./src/cloudtask.spec.ts
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 CloudTaskConnector_1 = require("./CloudTaskConnector");
7
- class TestTask extends tasks_core_1.ShouldQueue {
8
- postUrl = `http://localhost/task/this/url`;
9
- taskName = 'this_is_the_task_name';
10
- async handle(taskBody) {
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
- (0, vitest_1.describe)('CloudTaskQueue', () => {
16
- let cloudTask;
17
- let task;
18
- (0, vitest_1.beforeAll)(() => {
19
- // Check if we have the required environment variable
20
- const serviceAccountBase64 = process.env.FIREBASE_SERVICE_ACCOUNT;
21
- if (!serviceAccountBase64) {
22
- console.warn('FIREBASE_SERVICE_ACCOUNT not found, skipping CloudTask tests');
23
- return;
24
- }
25
- try {
26
- // Decode and parse the service account
27
- const serviceAccountJson = Buffer.from(serviceAccountBase64, 'base64').toString('utf8');
28
- const gcpServiceAccount = JSON.parse(serviceAccountJson);
29
- cloudTask = new CloudTaskConnector_1.CloudTaskConnector({
30
- gcpServiceAccount,
31
- location: 'europe-west1',
32
- encryptionKey: 'some-encryption-key',
33
- gcpProject: 'gealium-develop'
34
- });
35
- task = new TestTask({
36
- connector: cloudTask
37
- });
38
- }
39
- catch (error) {
40
- console.error('Failed to parse FIREBASE_SERVICE_ACCOUNT:', error);
41
- throw new Error(`Invalid FIREBASE_SERVICE_ACCOUNT format: ${error.message}`);
42
- }
43
- });
44
- (0, vitest_1.it)('should create a task and run it', async () => {
45
- // Skip test if cloudTask wasn't initialized
46
- if (!cloudTask) {
47
- console.log('Skipping test: FIREBASE_SERVICE_ACCOUNT not available');
48
- return;
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 status = await task.queue({ text: 'Hello, World!' });
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('this_is_the_task_name');
56
- (0, vitest_1.expect)(status).not.toHaveProperty('payload');
57
- const getStatus = await task.getStatus(status.id);
58
- (0, vitest_1.expect)(getStatus).toHaveProperty('id', status.id);
59
- (0, vitest_1.expect)(getStatus).toHaveProperty('name', status.name);
60
- (0, vitest_1.expect)(getStatus).toHaveProperty('status', 'FAILED');
61
- (0, vitest_1.expect)(getStatus).toHaveProperty('payload');
62
- (0, vitest_1.expect)(getStatus.payload.text).toBe('Hello, World!');
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":"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"}
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 { CloudTaskConnector } from './CloudTaskConnector';
2
- export type { GCPServiceAccount } from './CloudTaskConnector.types';
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 CloudTaskConnector_1 = require("./CloudTaskConnector");
5
- Object.defineProperty(exports, "CloudTaskConnector", { enumerable: true, get: function () { return CloudTaskConnector_1.CloudTaskConnector; } });
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":";;;AAAA,2DAAyD;AAAhD,wHAAA,kBAAkB,OAAA"}
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"}