4runr-os 2.10.9 → 2.10.13

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,192 @@
1
+ /**
2
+ * Watchdog process that monitors 4r and cleans up Docker containers on ANY exit
3
+ * Runs detached and polls the parent process, stopping containers when parent dies
4
+ */
5
+ import { execSync, spawn } from 'child_process';
6
+ import * as fs from 'fs';
7
+ import * as os from 'os';
8
+ import * as path from 'path';
9
+ const WATCHDOG_PID_FILE = '4runr-watchdog.pid';
10
+ const PARENT_PID_FILE = '4runr-parent.pid';
11
+ function getWatchdogPidPath() {
12
+ return path.join(os.tmpdir(), WATCHDOG_PID_FILE);
13
+ }
14
+ function getParentPidPath() {
15
+ return path.join(os.tmpdir(), PARENT_PID_FILE);
16
+ }
17
+ /**
18
+ * Check if a process is running
19
+ */
20
+ function isProcessRunning(pid) {
21
+ try {
22
+ process.kill(pid, 0); // Signal 0 just checks if process exists
23
+ return true;
24
+ }
25
+ catch {
26
+ return false;
27
+ }
28
+ }
29
+ /**
30
+ * Stop Docker containers (works even if Docker compose file unavailable)
31
+ */
32
+ function stopContainers() {
33
+ try {
34
+ if (process.platform === 'win32') {
35
+ execSync('docker stop 4runr-postgres 4runr-redis 2>nul', {
36
+ stdio: 'pipe',
37
+ timeout: 15000,
38
+ windowsHide: true,
39
+ });
40
+ }
41
+ else {
42
+ execSync('docker stop 4runr-postgres 4runr-redis 2>/dev/null || true', {
43
+ stdio: 'pipe',
44
+ timeout: 15000,
45
+ });
46
+ }
47
+ }
48
+ catch {
49
+ // Containers might not exist or Docker unavailable
50
+ }
51
+ }
52
+ /**
53
+ * Kill any autostarted Gateway process
54
+ */
55
+ function killGateway() {
56
+ const gatewayPidPath = path.join(os.tmpdir(), '4runr-os-local-gateway.pid');
57
+ try {
58
+ if (fs.existsSync(gatewayPidPath)) {
59
+ const pid = parseInt(fs.readFileSync(gatewayPidPath, 'utf-8').trim(), 10);
60
+ if (pid > 0 && isProcessRunning(pid)) {
61
+ try {
62
+ process.kill(pid, 'SIGTERM');
63
+ }
64
+ catch {
65
+ // ignore
66
+ }
67
+ }
68
+ fs.unlinkSync(gatewayPidPath);
69
+ }
70
+ }
71
+ catch {
72
+ // ignore
73
+ }
74
+ }
75
+ /**
76
+ * Start watchdog process (detached, survives parent exit)
77
+ */
78
+ export function startWatchdog(parentPid) {
79
+ // Kill any existing watchdog
80
+ const existingWatchdogPid = getWatchdogPidPath();
81
+ if (fs.existsSync(existingWatchdogPid)) {
82
+ try {
83
+ const pid = parseInt(fs.readFileSync(existingWatchdogPid, 'utf-8').trim(), 10);
84
+ if (pid > 0 && isProcessRunning(pid)) {
85
+ process.kill(pid, 'SIGTERM');
86
+ }
87
+ }
88
+ catch {
89
+ // ignore
90
+ }
91
+ }
92
+ // Write parent PID for watchdog to monitor
93
+ fs.writeFileSync(getParentPidPath(), String(parentPid), 'utf-8');
94
+ // Spawn detached watchdog process
95
+ const watchdogScript = `
96
+ const fs = require('fs');
97
+ const os = require('os');
98
+ const path = require('path');
99
+ const { execSync } = require('child_process');
100
+
101
+ const parentPidPath = path.join(os.tmpdir(), '${PARENT_PID_FILE}');
102
+ const watchdogPidPath = path.join(os.tmpdir(), '${WATCHDOG_PID_FILE}');
103
+
104
+ // Write our own PID
105
+ fs.writeFileSync(watchdogPidPath, String(process.pid), 'utf-8');
106
+
107
+ function isRunning(pid) {
108
+ try { process.kill(pid, 0); return true; } catch { return false; }
109
+ }
110
+
111
+ function cleanup() {
112
+ try {
113
+ // Kill Gateway
114
+ const gwPid = path.join(os.tmpdir(), '4runr-os-local-gateway.pid');
115
+ if (fs.existsSync(gwPid)) {
116
+ try {
117
+ const pid = parseInt(fs.readFileSync(gwPid, 'utf-8').trim(), 10);
118
+ if (pid > 0 && isRunning(pid)) process.kill(pid, 'SIGTERM');
119
+ } catch {}
120
+ try { fs.unlinkSync(gwPid); } catch {}
121
+ }
122
+
123
+ // Stop Docker containers
124
+ try {
125
+ if (process.platform === 'win32') {
126
+ execSync('docker stop 4runr-postgres 4runr-redis 2>nul', { stdio: 'pipe', timeout: 15000, windowsHide: true });
127
+ } else {
128
+ execSync('docker stop 4runr-postgres 4runr-redis 2>/dev/null || true', { stdio: 'pipe', timeout: 15000 });
129
+ }
130
+ } catch {}
131
+ } catch {}
132
+
133
+ // Cleanup PID files
134
+ try { fs.unlinkSync(parentPidPath); } catch {}
135
+ try { fs.unlinkSync(watchdogPidPath); } catch {}
136
+ process.exit(0);
137
+ }
138
+
139
+ // Monitor parent process
140
+ const parentPid = parseInt(fs.readFileSync(parentPidPath, 'utf-8').trim(), 10);
141
+ const interval = setInterval(() => {
142
+ if (!isRunning(parentPid)) {
143
+ clearInterval(interval);
144
+ cleanup();
145
+ }
146
+ }, 1000); // Check every second
147
+
148
+ // Cleanup on watchdog exit signals
149
+ process.on('SIGTERM', cleanup);
150
+ process.on('SIGINT', cleanup);
151
+ `;
152
+ const child = spawn(process.execPath, ['-e', watchdogScript], {
153
+ detached: true,
154
+ stdio: 'ignore',
155
+ windowsHide: true,
156
+ });
157
+ child.unref(); // Allow parent to exit independently
158
+ }
159
+ /**
160
+ * Stop watchdog and cleanup (called on graceful shutdown)
161
+ */
162
+ export function stopWatchdog() {
163
+ const watchdogPidPath = getWatchdogPidPath();
164
+ if (fs.existsSync(watchdogPidPath)) {
165
+ try {
166
+ const pid = parseInt(fs.readFileSync(watchdogPidPath, 'utf-8').trim(), 10);
167
+ if (pid > 0 && isProcessRunning(pid)) {
168
+ process.kill(pid, 'SIGTERM');
169
+ }
170
+ }
171
+ catch {
172
+ // ignore
173
+ }
174
+ }
175
+ // Manual cleanup since watchdog is being stopped gracefully
176
+ killGateway();
177
+ stopContainers();
178
+ // Cleanup PID files
179
+ try {
180
+ fs.unlinkSync(watchdogPidPath);
181
+ }
182
+ catch {
183
+ // ignore
184
+ }
185
+ try {
186
+ fs.unlinkSync(getParentPidPath());
187
+ }
188
+ catch {
189
+ // ignore
190
+ }
191
+ }
192
+ //# sourceMappingURL=watchdog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watchdog.js","sourceRoot":"","sources":["../src/watchdog.ts"],"names":[],"mappings":"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"}