opencode-antigravity-auth-mf 1.3.0-2 → 1.3.1-4

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,490 @@
1
+ import { debugLogToFile } from './debug.js';
2
+ import { decryptData } from './crypto.js';
3
+ const FETCH_TIMEOUT_MS = 10000;
4
+ const DEFAULT_HEARTBEAT_RATIO = 0.5; // 50% of TTL
5
+ const DEFAULT_IDLE_TIMEOUT_MS = 20 * 60 * 1000; // 20 minutes
6
+ const IDLE_CHECK_INTERVAL_MS = 60 * 1000; // 1 minute
7
+ const DEFAULT_QUOTA_CHECK_INTERVAL_MS = 2 * 60 * 1000; // 5 minutes
8
+ const DEFAULT_LOW_QUOTA_THRESHOLD = 0.2; // 80%
9
+ const DEFAULT_MAX_RATE_LIMIT_WAIT_MS = 10 * 1000; // 10 seconds - switch faster
10
+ /**
11
+ * Generate a UUID v4
12
+ */
13
+ function generateUUID() {
14
+ // Use crypto if available, otherwise fallback to Math.random
15
+ if (typeof crypto !== 'undefined' && crypto.randomUUID) {
16
+ return crypto.randomUUID();
17
+ }
18
+ // Fallback UUID generation
19
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
20
+ const r = (Math.random() * 16) | 0;
21
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
22
+ return v.toString(16);
23
+ });
24
+ }
25
+ /**
26
+ * Fetch with timeout support
27
+ */
28
+ async function fetchWithTimeout(url, options, timeoutMs = FETCH_TIMEOUT_MS) {
29
+ const controller = new AbortController();
30
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
31
+ try {
32
+ return await fetch(url, { ...options, signal: controller.signal });
33
+ }
34
+ finally {
35
+ clearTimeout(timeout);
36
+ }
37
+ }
38
+ /**
39
+ * LeaseManager handles the lifecycle of account leases from the remote service.
40
+ *
41
+ * Features:
42
+ * - Acquire leases with automatic heartbeat renewal
43
+ * - Release leases with fire-and-forget pattern
44
+ * - Report issues and get a new account
45
+ * - Graceful error handling without blocking main flow
46
+ */
47
+ export class LeaseManager {
48
+ clientId;
49
+ apiEndpoint;
50
+ apiKey;
51
+ lease = null;
52
+ heartbeatTimer = null;
53
+ lastActivity = Date.now();
54
+ idleTimeoutMs;
55
+ idleCheckTimer = null;
56
+ quotaCheckIntervalMs;
57
+ lowQuotaThreshold;
58
+ lastQuotaCheck = 0;
59
+ maxRateLimitWaitMs;
60
+ onReleaseCallback = null;
61
+ constructor(config) {
62
+ this.clientId = generateUUID();
63
+ this.apiEndpoint = config.apiEndpoint;
64
+ this.apiKey = config.apiKey;
65
+ this.idleTimeoutMs = config.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
66
+ this.quotaCheckIntervalMs = config.quotaCheckIntervalMs ?? DEFAULT_QUOTA_CHECK_INTERVAL_MS;
67
+ this.lowQuotaThreshold = config.lowQuotaThreshold ?? DEFAULT_LOW_QUOTA_THRESHOLD;
68
+ this.maxRateLimitWaitMs = config.maxRateLimitWaitMs ?? DEFAULT_MAX_RATE_LIMIT_WAIT_MS;
69
+ debugLogToFile(`[lease-manager] Initialized with clientId=${this.clientId}`);
70
+ }
71
+ onRelease(callback) {
72
+ this.onReleaseCallback = callback;
73
+ }
74
+ /**
75
+ * Acquire a lease from the remote service.
76
+ * Starts heartbeat timer on success.
77
+ *
78
+ * @throws Error if acquire fails
79
+ */
80
+ async acquire() {
81
+ debugLogToFile(`[lease-manager] Acquiring lease...`);
82
+ try {
83
+ const response = await fetchWithTimeout(`${this.apiEndpoint}/api/lease/acquire`, {
84
+ method: 'POST',
85
+ headers: {
86
+ 'Content-Type': 'application/json',
87
+ 'X-API-Key': this.apiKey,
88
+ 'User-Agent': 'opencode-antigravity-auth',
89
+ },
90
+ body: JSON.stringify({ client_id: this.clientId }),
91
+ });
92
+ if (!response.ok) {
93
+ const errorText = await response.text().catch(() => '');
94
+ throw new Error(`Acquire failed: ${response.status} ${response.statusText} ${errorText}`);
95
+ }
96
+ const data = (await response.json());
97
+ const decrypted = decryptData(data.account, this.apiKey);
98
+ this.lease = {
99
+ leaseId: data.lease_id,
100
+ account: {
101
+ email: decrypted.account.email,
102
+ refreshToken: decrypted.account.refresh_token,
103
+ projectId: decrypted.account.project_id,
104
+ },
105
+ expiresAt: new Date(data.expires_at),
106
+ };
107
+ // Start heartbeat based on TTL
108
+ this.startHeartbeat(data.ttl_seconds);
109
+ this.updateActivity();
110
+ this.startIdleCheck();
111
+ debugLogToFile(`[lease-manager] Acquired lease ${data.lease_id} for ${decrypted.account.email}, expires at ${this.lease.expiresAt.toISOString()}`);
112
+ return this.lease;
113
+ }
114
+ catch (error) {
115
+ const message = error instanceof Error ? error.message : String(error);
116
+ debugLogToFile(`[lease-manager] Acquire error: ${message}`);
117
+ throw new Error(`Failed to acquire lease: ${message}`);
118
+ }
119
+ }
120
+ /**
121
+ * Release the current lease using fire-and-forget pattern.
122
+ * Does not block or throw on failure.
123
+ */
124
+ async release() {
125
+ // Stop heartbeat first
126
+ this.stopHeartbeat();
127
+ this.stopIdleCheck();
128
+ if (!this.lease) {
129
+ debugLogToFile(`[lease-manager] Release called but no active lease`);
130
+ return;
131
+ }
132
+ const leaseId = this.lease.leaseId;
133
+ this.lease = null;
134
+ debugLogToFile(`[lease-manager] Releasing lease ${leaseId}...`);
135
+ try {
136
+ const response = await fetch(`${this.apiEndpoint}/api/lease/release`, {
137
+ method: 'POST',
138
+ headers: {
139
+ 'Content-Type': 'application/json',
140
+ 'X-API-Key': this.apiKey,
141
+ 'User-Agent': 'opencode-antigravity-auth',
142
+ },
143
+ body: JSON.stringify({
144
+ lease_id: leaseId,
145
+ client_id: this.clientId,
146
+ }),
147
+ });
148
+ if (!response.ok) {
149
+ debugLogToFile(`[lease-manager] Release failed: ${response.status}`);
150
+ }
151
+ else {
152
+ debugLogToFile(`[lease-manager] Released lease ${leaseId}`);
153
+ }
154
+ }
155
+ catch (err) {
156
+ const message = err instanceof Error ? err.message : String(err);
157
+ debugLogToFile(`[lease-manager] Release error: ${message}`);
158
+ }
159
+ if (this.onReleaseCallback) {
160
+ this.onReleaseCallback();
161
+ }
162
+ }
163
+ /**
164
+ * Renew the current lease.
165
+ * Updates expiresAt on success.
166
+ *
167
+ * @throws Error if renew fails or no active lease
168
+ */
169
+ async renew() {
170
+ if (!this.lease) {
171
+ throw new Error('No active lease to renew');
172
+ }
173
+ debugLogToFile(`[lease-manager] Renewing lease ${this.lease.leaseId}...`);
174
+ try {
175
+ const response = await fetchWithTimeout(`${this.apiEndpoint}/api/lease/renew`, {
176
+ method: 'POST',
177
+ headers: {
178
+ 'Content-Type': 'application/json',
179
+ 'X-API-Key': this.apiKey,
180
+ 'User-Agent': 'opencode-antigravity-auth',
181
+ },
182
+ body: JSON.stringify({
183
+ lease_id: this.lease.leaseId,
184
+ client_id: this.clientId,
185
+ }),
186
+ });
187
+ if (!response.ok) {
188
+ const errorText = await response.text().catch(() => '');
189
+ throw new Error(`Renew failed: ${response.status} ${response.statusText} ${errorText}`);
190
+ }
191
+ const data = (await response.json());
192
+ this.lease.expiresAt = new Date(data.expires_at);
193
+ // Restart heartbeat with new TTL
194
+ this.stopHeartbeat();
195
+ this.startHeartbeat(data.ttl_seconds);
196
+ debugLogToFile(`[lease-manager] Renewed lease, new expiry: ${this.lease.expiresAt.toISOString()}`);
197
+ }
198
+ catch (error) {
199
+ const message = error instanceof Error ? error.message : String(error);
200
+ debugLogToFile(`[lease-manager] Renew error: ${message}`);
201
+ throw new Error(`Failed to renew lease: ${message}`);
202
+ }
203
+ }
204
+ /**
205
+ * Report an issue with the current account and get a new one.
206
+ *
207
+ * @param reason - Description of the issue
208
+ * @param resetTime - Optional quota reset time (ISO string)
209
+ * @returns New lease state with different account
210
+ * @throws Error if report fails or no active lease
211
+ */
212
+ async reportIssue(reason, resetTime) {
213
+ if (!this.lease) {
214
+ throw new Error('No active lease to report issue for');
215
+ }
216
+ debugLogToFile(`[lease-manager] Reporting issue for lease ${this.lease.leaseId}: ${reason}`);
217
+ try {
218
+ const response = await fetchWithTimeout(`${this.apiEndpoint}/api/lease/report-issue`, {
219
+ method: 'POST',
220
+ headers: {
221
+ 'Content-Type': 'application/json',
222
+ 'X-API-Key': this.apiKey,
223
+ 'User-Agent': 'opencode-antigravity-auth',
224
+ },
225
+ body: JSON.stringify({
226
+ lease_id: this.lease.leaseId,
227
+ client_id: this.clientId,
228
+ issue_type: reason,
229
+ ...(resetTime && { reset_time: resetTime }),
230
+ }),
231
+ });
232
+ if (!response.ok) {
233
+ const errorText = await response.text().catch(() => '');
234
+ throw new Error(`Report issue failed: ${response.status} ${response.statusText} ${errorText}`);
235
+ }
236
+ const rawData = (await response.json());
237
+ const data = 'new_lease' in rawData && rawData.new_lease ? rawData.new_lease : rawData;
238
+ if (!data.lease_id || !data.account) {
239
+ throw new Error('No new account available after reporting issue');
240
+ }
241
+ // Stop old heartbeat
242
+ this.stopHeartbeat();
243
+ const decrypted = decryptData(data.account, this.apiKey);
244
+ this.lease = {
245
+ leaseId: data.lease_id,
246
+ account: {
247
+ email: decrypted.account.email,
248
+ refreshToken: decrypted.account.refresh_token,
249
+ projectId: decrypted.account.project_id,
250
+ },
251
+ expiresAt: new Date(data.expires_at),
252
+ };
253
+ // Start new heartbeat
254
+ this.startHeartbeat(data.ttl_seconds);
255
+ this.updateActivity();
256
+ this.startIdleCheck();
257
+ debugLogToFile(`[lease-manager] Got new lease ${data.lease_id} for ${decrypted.account.email}`);
258
+ return this.lease;
259
+ }
260
+ catch (error) {
261
+ const message = error instanceof Error ? error.message : String(error);
262
+ debugLogToFile(`[lease-manager] Report issue error: ${message}`);
263
+ throw new Error(`Failed to report issue: ${message}`);
264
+ }
265
+ }
266
+ /**
267
+ * Get the current leased account.
268
+ *
269
+ * @returns Account info or null if no active lease
270
+ */
271
+ getAccount() {
272
+ return this.lease?.account ?? null;
273
+ }
274
+ /**
275
+ * Get the current lease state.
276
+ *
277
+ * @returns Lease state or null if no active lease
278
+ */
279
+ getLease() {
280
+ return this.lease;
281
+ }
282
+ updateActivity() {
283
+ this.lastActivity = Date.now();
284
+ }
285
+ getLastActivity() {
286
+ return this.lastActivity;
287
+ }
288
+ /**
289
+ * Get the client ID for this manager instance.
290
+ */
291
+ getClientId() {
292
+ return this.clientId;
293
+ }
294
+ /**
295
+ * Check if there's an active lease.
296
+ */
297
+ hasActiveLease() {
298
+ return this.lease !== null;
299
+ }
300
+ async handleRateLimit(waitMs, reason, quotaResetTime) {
301
+ this.updateActivity();
302
+ debugLogToFile(`[lease-manager] Rate limit: waitMs=${waitMs} reason=${reason || 'unknown'} quotaResetTime=${quotaResetTime || 'none'}`);
303
+ if (waitMs <= this.maxRateLimitWaitMs) {
304
+ debugLogToFile(`[lease-manager] Wait time ${waitMs}ms <= threshold ${this.maxRateLimitWaitMs}ms, recommending wait`);
305
+ return {
306
+ action: 'wait',
307
+ waitMs,
308
+ };
309
+ }
310
+ debugLogToFile(`[lease-manager] Wait time ${waitMs}ms > threshold ${this.maxRateLimitWaitMs}ms, switching account`);
311
+ try {
312
+ const resetTime = quotaResetTime || new Date(Date.now() + waitMs).toISOString();
313
+ const newLease = await this.reportIssue(`rate_limit:${reason || 'unknown'}`, resetTime);
314
+ return {
315
+ action: 'switch',
316
+ newAccount: newLease.account,
317
+ };
318
+ }
319
+ catch (err) {
320
+ debugLogToFile(`[lease-manager] Failed to switch account: ${err}`);
321
+ return {
322
+ action: 'wait',
323
+ waitMs,
324
+ };
325
+ }
326
+ }
327
+ shouldSwitchOnRateLimit(waitMs) {
328
+ return waitMs > this.maxRateLimitWaitMs;
329
+ }
330
+ getMaxRateLimitWaitMs() {
331
+ return this.maxRateLimitWaitMs;
332
+ }
333
+ async checkQuota() {
334
+ if (!this.lease) {
335
+ debugLogToFile('[lease-manager] No active lease, skipping quota check');
336
+ return null;
337
+ }
338
+ const now = Date.now();
339
+ if (now - this.lastQuotaCheck < this.quotaCheckIntervalMs) {
340
+ debugLogToFile('[lease-manager] Quota check rate limited');
341
+ return null;
342
+ }
343
+ this.lastQuotaCheck = now;
344
+ try {
345
+ const tokenResponse = await fetchWithTimeout('https://oauth2.googleapis.com/token', {
346
+ method: 'POST',
347
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
348
+ body: new URLSearchParams({
349
+ client_id: '1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com',
350
+ client_secret: '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',
351
+ refresh_token: this.lease.account.refreshToken,
352
+ grant_type: 'refresh_token',
353
+ }).toString(),
354
+ });
355
+ if (!tokenResponse.ok) {
356
+ debugLogToFile(`[lease-manager] Token refresh failed: ${tokenResponse.status}`);
357
+ return null;
358
+ }
359
+ const tokenData = (await tokenResponse.json());
360
+ const accessToken = tokenData.access_token;
361
+ const quotaResponse = await fetchWithTimeout('https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels', {
362
+ method: 'POST',
363
+ headers: {
364
+ 'Authorization': `Bearer ${accessToken}`,
365
+ 'Content-Type': 'application/json',
366
+ 'User-Agent': 'antigravity/1.11.3 Darwin/arm64',
367
+ },
368
+ body: JSON.stringify({ project: this.lease.account.projectId || '' }),
369
+ });
370
+ if (!quotaResponse.ok) {
371
+ debugLogToFile(`[lease-manager] Quota API failed: ${quotaResponse.status}`);
372
+ return null;
373
+ }
374
+ const quotaData = (await quotaResponse.json());
375
+ let minRemainingFraction = 1;
376
+ let earliestResetTime;
377
+ for (const info of Object.values(quotaData.models || {})) {
378
+ const fraction = info.quotaInfo?.remainingFraction ?? 1;
379
+ const resetTime = info.quotaInfo?.resetTime;
380
+ if (fraction < minRemainingFraction) {
381
+ minRemainingFraction = fraction;
382
+ earliestResetTime = resetTime;
383
+ }
384
+ }
385
+ const remaining = Math.round(minRemainingFraction * 100);
386
+ const total = 100;
387
+ const percentage = minRemainingFraction;
388
+ debugLogToFile(`[lease-manager] Quota: ${remaining}/${total} (${(percentage * 100).toFixed(1)}%) resetTime=${earliestResetTime || 'none'}`);
389
+ this.reportQuotaToServer(quotaData.models || {}).catch((err) => {
390
+ debugLogToFile(`[lease-manager] Failed to report quota to server: ${err}`);
391
+ });
392
+ if (percentage <= this.lowQuotaThreshold) {
393
+ debugLogToFile(`[lease-manager] Quota low (${(percentage * 100).toFixed(1)}%), disabling account and switching`);
394
+ try {
395
+ const resetTime = earliestResetTime || new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString();
396
+ await this.reportIssue('quota_exhausted', resetTime);
397
+ }
398
+ catch (err) {
399
+ debugLogToFile(`[lease-manager] Failed to disable and switch account on low quota: ${err}`);
400
+ }
401
+ }
402
+ return { remaining, total, percentage };
403
+ }
404
+ catch (err) {
405
+ debugLogToFile(`[lease-manager] Quota check error: ${err}`);
406
+ return null;
407
+ }
408
+ }
409
+ startHeartbeat(ttlSeconds) {
410
+ this.stopHeartbeat();
411
+ const intervalMs = Math.floor(ttlSeconds * DEFAULT_HEARTBEAT_RATIO * 1000);
412
+ debugLogToFile(`[lease-manager] Starting heartbeat with interval ${intervalMs}ms (TTL=${ttlSeconds}s)`);
413
+ this.heartbeatTimer = setInterval(() => {
414
+ this.renew()
415
+ .then(() => this.checkQuota())
416
+ .catch((err) => {
417
+ debugLogToFile(`[lease-manager] Heartbeat renew failed: ${err.message}`);
418
+ });
419
+ }, intervalMs);
420
+ // Prevent timer from blocking process exit
421
+ this.heartbeatTimer.unref();
422
+ }
423
+ /**
424
+ * Stop heartbeat timer.
425
+ */
426
+ stopHeartbeat() {
427
+ if (this.heartbeatTimer) {
428
+ clearInterval(this.heartbeatTimer);
429
+ this.heartbeatTimer = null;
430
+ debugLogToFile(`[lease-manager] Stopped heartbeat`);
431
+ }
432
+ }
433
+ startIdleCheck() {
434
+ this.stopIdleCheck();
435
+ this.idleCheckTimer = setInterval(() => {
436
+ const idleTime = Date.now() - this.lastActivity;
437
+ if (idleTime >= this.idleTimeoutMs && this.lease) {
438
+ debugLogToFile(`[lease-manager] Idle for ${Math.floor(idleTime / 1000)}s, releasing lease`);
439
+ this.release();
440
+ }
441
+ }, IDLE_CHECK_INTERVAL_MS);
442
+ this.idleCheckTimer.unref();
443
+ }
444
+ stopIdleCheck() {
445
+ if (this.idleCheckTimer) {
446
+ clearInterval(this.idleCheckTimer);
447
+ this.idleCheckTimer = null;
448
+ }
449
+ }
450
+ async reportQuotaToServer(models) {
451
+ if (!this.lease)
452
+ return;
453
+ const quotas = [];
454
+ for (const [modelName, info] of Object.entries(models)) {
455
+ const quotaInfo = info.quotaInfo || {};
456
+ quotas.push({
457
+ model_name: modelName,
458
+ percentage: Math.round((quotaInfo.remainingFraction || 0) * 100),
459
+ reset_time: quotaInfo.resetTime,
460
+ });
461
+ }
462
+ if (quotas.length === 0)
463
+ return;
464
+ try {
465
+ const response = await fetch(`${this.apiEndpoint}/api/quota/report`, {
466
+ method: 'POST',
467
+ headers: {
468
+ 'Content-Type': 'application/json',
469
+ 'X-API-Key': this.apiKey,
470
+ 'User-Agent': 'opencode-antigravity-auth',
471
+ },
472
+ body: JSON.stringify({
473
+ account_email: this.lease.account.email,
474
+ quotas,
475
+ }),
476
+ });
477
+ if (response.ok) {
478
+ debugLogToFile(`[lease-manager] Quota reported to server: ${quotas.length} models`);
479
+ }
480
+ else {
481
+ debugLogToFile(`[lease-manager] Quota report failed: ${response.status}`);
482
+ }
483
+ }
484
+ catch (err) {
485
+ const message = err instanceof Error ? err.message : String(err);
486
+ debugLogToFile(`[lease-manager] Quota report error: ${message}`);
487
+ }
488
+ }
489
+ }
490
+ //# sourceMappingURL=lease-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lease-manager.js","sourceRoot":"","sources":["../../../src/plugin/lease-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Lifecycle management for graceful shutdown.
3
+ *
4
+ * Handles SIGTERM/SIGINT/SIGHUP signals to release leases before exit.
5
+ * Features:
6
+ * - isShuttingDown flag prevents duplicate handling
7
+ * - Watchdog timeout (10s) prevents hanging
8
+ * - Does not call process.exit() to allow other cleanup handlers
9
+ */
10
+ import type { LeaseManager } from './lease-manager.js';
11
+ /**
12
+ * Initialize lifecycle management.
13
+ * Registers signal handlers for graceful shutdown.
14
+ */
15
+ export declare function initLifecycle(leaseManager: LeaseManager): void;
16
+ /**
17
+ * Handle shutdown signal.
18
+ * Releases lease with watchdog timeout protection.
19
+ */
20
+ declare function handleShutdown(signal: NodeJS.Signals): Promise<void>;
21
+ /**
22
+ * Check if shutdown is in progress.
23
+ */
24
+ export declare function isShuttingDownNow(): boolean;
25
+ /**
26
+ * Reset state for testing purposes only.
27
+ */
28
+ export declare function _resetForTesting(): void;
29
+ /**
30
+ * Export handleShutdown for testing purposes only.
31
+ */
32
+ export declare const _handleShutdownForTesting: typeof handleShutdown;
33
+ export {};
34
+ //# sourceMappingURL=lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../../src/plugin/lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAOvD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,CAqB9D;AAED;;;GAGG;AACH,iBAAe,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BnE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAMvC;AAED;;GAEG;AACH,eAAO,MAAM,yBAAyB,uBAAiB,CAAC"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Lifecycle management for graceful shutdown.
3
+ *
4
+ * Handles SIGTERM/SIGINT/SIGHUP signals to release leases before exit.
5
+ * Features:
6
+ * - isShuttingDown flag prevents duplicate handling
7
+ * - Watchdog timeout (10s) prevents hanging
8
+ * - Does not call process.exit() to allow other cleanup handlers
9
+ */
10
+ import { debugLogToFile } from './debug.js';
11
+ const WATCHDOG_TIMEOUT_MS = 10000;
12
+ let isShuttingDown = false;
13
+ let leaseManagerRef = null;
14
+ /**
15
+ * Initialize lifecycle management.
16
+ * Registers signal handlers for graceful shutdown.
17
+ */
18
+ export function initLifecycle(leaseManager) {
19
+ leaseManagerRef = leaseManager;
20
+ // Only register once
21
+ if (isShuttingDown)
22
+ return;
23
+ process.on('SIGTERM', handleShutdown);
24
+ process.on('SIGINT', handleShutdown);
25
+ process.on('SIGHUP', handleShutdown);
26
+ // Also handle beforeExit for cases where signals aren't received
27
+ process.on('beforeExit', async () => {
28
+ if (!isShuttingDown && leaseManagerRef) {
29
+ isShuttingDown = true;
30
+ try {
31
+ await leaseManagerRef.release();
32
+ }
33
+ catch { }
34
+ }
35
+ });
36
+ debugLogToFile(`[lifecycle] Initialized signal handlers`);
37
+ }
38
+ /**
39
+ * Handle shutdown signal.
40
+ * Releases lease with watchdog timeout protection.
41
+ */
42
+ async function handleShutdown(signal) {
43
+ if (isShuttingDown) {
44
+ debugLogToFile(`[lifecycle] Already shutting down, ignoring ${signal}`);
45
+ return;
46
+ }
47
+ isShuttingDown = true;
48
+ debugLogToFile(`[lifecycle] Received ${signal}, starting graceful shutdown...`);
49
+ // Watchdog: force exit after 10 seconds
50
+ const watchdog = setTimeout(() => {
51
+ debugLogToFile(`[lifecycle] Watchdog timeout, forcing exit`);
52
+ process.exit(1);
53
+ }, WATCHDOG_TIMEOUT_MS);
54
+ watchdog.unref();
55
+ try {
56
+ if (leaseManagerRef) {
57
+ await leaseManagerRef.release();
58
+ }
59
+ }
60
+ catch (error) {
61
+ const message = error instanceof Error ? error.message : String(error);
62
+ debugLogToFile(`[lifecycle] Release error during shutdown: ${message}`);
63
+ }
64
+ // Don't call process.exit() - let Node.js exit naturally
65
+ // This allows other cleanup handlers to run
66
+ clearTimeout(watchdog);
67
+ debugLogToFile(`[lifecycle] Graceful shutdown complete`);
68
+ }
69
+ /**
70
+ * Check if shutdown is in progress.
71
+ */
72
+ export function isShuttingDownNow() {
73
+ return isShuttingDown;
74
+ }
75
+ /**
76
+ * Reset state for testing purposes only.
77
+ */
78
+ export function _resetForTesting() {
79
+ isShuttingDown = false;
80
+ leaseManagerRef = null;
81
+ process.removeListener('SIGTERM', handleShutdown);
82
+ process.removeListener('SIGINT', handleShutdown);
83
+ process.removeListener('SIGHUP', handleShutdown);
84
+ }
85
+ /**
86
+ * Export handleShutdown for testing purposes only.
87
+ */
88
+ export const _handleShutdownForTesting = handleShutdown;
89
+ //# sourceMappingURL=lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../../src/plugin/lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAElC,IAAI,cAAc,GAAG,KAAK,CAAC;AAC3B,IAAI,eAAe,GAAwB,IAAI,CAAC;AAEhD;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,YAA0B;IACtD,eAAe,GAAG,YAAY,CAAC;IAE/B,qBAAqB;IACrB,IAAI,cAAc;QAAE,OAAO;IAE3B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IACtC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IAErC,iEAAiE;IACjE,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE;QAClC,IAAI,CAAC,cAAc,IAAI,eAAe,EAAE,CAAC;YACvC,cAAc,GAAG,IAAI,CAAC;YACtB,IAAI,CAAC;gBACH,MAAM,eAAe,CAAC,OAAO,EAAE,CAAC;YAClC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,cAAc,CAAC,yCAAyC,CAAC,CAAC;AAC5D,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,cAAc,CAAC,MAAsB;IAClD,IAAI,cAAc,EAAE,CAAC;QACnB,cAAc,CAAC,+CAA+C,MAAM,EAAE,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,cAAc,GAAG,IAAI,CAAC;IACtB,cAAc,CAAC,wBAAwB,MAAM,iCAAiC,CAAC,CAAC;IAEhF,wCAAwC;IACxC,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE;QAC/B,cAAc,CAAC,4CAA4C,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,EAAE,mBAAmB,CAAC,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,CAAC;IAEjB,IAAI,CAAC;QACH,IAAI,eAAe,EAAE,CAAC;YACpB,MAAM,eAAe,CAAC,OAAO,EAAE,CAAC;QAClC,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,cAAc,CAAC,8CAA8C,OAAO,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,yDAAyD;IACzD,4CAA4C;IAC5C,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvB,cAAc,CAAC,wCAAwC,CAAC,CAAC;AAC3D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,cAAc,GAAG,KAAK,CAAC;IACvB,eAAe,GAAG,IAAI,CAAC;IACvB,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IAClD,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IACjD,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;AACnD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,cAAc,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AA2CA,OAAO,KAAK,EAGV,aAAa,EACb,YAAY,EAGb,MAAM,gBAAgB,CAAC;AAylBxB;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,YAAY,MAAM,MACxD,uBAAuB,aAAa,KACnC,OAAO,CAAC,YAAY,CA02CtB,CAAC;AAEF,eAAO,MAAM,yBAAyB,0BA72Cb,aAAa,KACnC,OAAO,CAAC,YAAY,CA42CkE,CAAC;AAC1F,eAAO,MAAM,iBAAiB,0BA92CL,aAAa,KACnC,OAAO,CAAC,YAAY,CA62CmC,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AA6CA,OAAO,KAAK,EAGV,aAAa,EACb,YAAY,EAGb,MAAM,gBAAgB,CAAC;AAylBxB;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,YAAY,MAAM,MACxD,uBAAuB,aAAa,KACnC,OAAO,CAAC,YAAY,CA0hDtB,CAAC;AAEF,eAAO,MAAM,yBAAyB,0BA7hDb,aAAa,KACnC,OAAO,CAAC,YAAY,CA4hDkE,CAAC;AAC1F,eAAO,MAAM,iBAAiB,0BA9hDL,aAAa,KACnC,OAAO,CAAC,YAAY,CA6hDmC,CAAC"}