pgserve 1.0.4 → 1.0.6
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/Makefile +5 -2
- package/README.md +2 -2
- package/bin/pglite-server.js +17 -12
- package/package.json +1 -1
- package/src/cluster.js +20 -6
- package/src/dashboard.js +2 -2
- package/src/router.js +1 -1
package/Makefile
CHANGED
|
@@ -111,10 +111,13 @@ check-npm: ## Check npm authentication
|
|
|
111
111
|
@echo "$(CYAN)🔍 Checking npm authentication...$(RESET)"
|
|
112
112
|
@if ! npm whoami >/dev/null 2>&1; then \
|
|
113
113
|
echo "$(RED)❌ Not logged in to npm!$(RESET)"; \
|
|
114
|
-
echo "$(YELLOW)Run: npm login$(RESET)"; \
|
|
114
|
+
echo "$(YELLOW)Run: npm login --auth-type=legacy$(RESET)"; \
|
|
115
115
|
exit 1; \
|
|
116
116
|
fi
|
|
117
117
|
@echo "$(GREEN)✅ Logged in as: $$(npm whoami)$(RESET)"
|
|
118
|
+
@if [ -z "$$NPM_TOKEN" ] && ! grep -q "_authToken" ~/.npmrc 2>/dev/null; then \
|
|
119
|
+
echo "$(YELLOW)⚠️ Consider using NPM_TOKEN or ~/.npmrc for non-interactive publish$(RESET)"; \
|
|
120
|
+
fi
|
|
118
121
|
|
|
119
122
|
check-version: ## Check if version tag exists
|
|
120
123
|
@echo "$(CYAN)🔍 Checking version $(VERSION)...$(RESET)"
|
|
@@ -178,7 +181,7 @@ publish: check-git check-npm check-files ## 🚀 Publish to npm (auto-bumps vers
|
|
|
178
181
|
fi; \
|
|
179
182
|
echo ""; \
|
|
180
183
|
echo "$(CYAN)📦 Publishing to npm...$(RESET)"; \
|
|
181
|
-
npm publish --access public; \
|
|
184
|
+
npm publish --access public || { echo "$(RED)❌ npm publish failed! Run manually: npm publish --access public$(RESET)"; exit 1; }; \
|
|
182
185
|
echo "$(GREEN)✅ Published to npm!$(RESET)"; \
|
|
183
186
|
echo ""; \
|
|
184
187
|
if command -v gh >/dev/null 2>&1; then \
|
package/README.md
CHANGED
|
@@ -99,7 +99,7 @@ npm install pgserve
|
|
|
99
99
|
pgserve [options]
|
|
100
100
|
|
|
101
101
|
Options:
|
|
102
|
-
--port <number> PostgreSQL port (default:
|
|
102
|
+
--port <number> PostgreSQL port (default: 8432)
|
|
103
103
|
--data <path> Data directory for persistence (default: in-memory)
|
|
104
104
|
--host <host> Host to bind to (default: 127.0.0.1)
|
|
105
105
|
--log <level> Log level: error, warn, info, debug (default: info)
|
|
@@ -139,7 +139,7 @@ pgserve --sync-to "postgresql://user:pass@db.example.com:5432/prod"
|
|
|
139
139
|
import { startMultiTenantServer } from 'pgserve';
|
|
140
140
|
|
|
141
141
|
const server = await startMultiTenantServer({
|
|
142
|
-
port:
|
|
142
|
+
port: 8432,
|
|
143
143
|
host: '127.0.0.1',
|
|
144
144
|
baseDir: null, // null = memory mode
|
|
145
145
|
logLevel: 'info',
|
package/bin/pglite-server.js
CHANGED
|
@@ -42,7 +42,7 @@ USAGE:
|
|
|
42
42
|
pgserve [options]
|
|
43
43
|
|
|
44
44
|
OPTIONS:
|
|
45
|
-
--port <number> PostgreSQL port (default:
|
|
45
|
+
--port <number> PostgreSQL port (default: 8432)
|
|
46
46
|
--data <path> Data directory for persistence (default: in-memory)
|
|
47
47
|
--host <host> Host to bind to (default: 127.0.0.1)
|
|
48
48
|
--log <level> Log level: error, warn, info, debug (default: info)
|
|
@@ -95,7 +95,7 @@ function parseArgs() {
|
|
|
95
95
|
const cpuCount = os.cpus().length;
|
|
96
96
|
|
|
97
97
|
const options = {
|
|
98
|
-
port:
|
|
98
|
+
port: 8432,
|
|
99
99
|
host: '127.0.0.1',
|
|
100
100
|
dataDir: null, // null = memory mode
|
|
101
101
|
logLevel: 'info',
|
|
@@ -179,10 +179,13 @@ async function main() {
|
|
|
179
179
|
const options = parseArgs();
|
|
180
180
|
const memoryMode = !options.dataDir;
|
|
181
181
|
|
|
182
|
-
|
|
182
|
+
// Only print header if not a cluster worker (workers get PGSERVE_WORKER env)
|
|
183
|
+
if (!process.env.PGSERVE_WORKER) {
|
|
184
|
+
console.log(`
|
|
183
185
|
pgserve - Embedded PostgreSQL Server
|
|
184
186
|
=====================================
|
|
185
187
|
`);
|
|
188
|
+
}
|
|
186
189
|
|
|
187
190
|
try {
|
|
188
191
|
let server;
|
|
@@ -254,16 +257,18 @@ Press Ctrl+C to stop
|
|
|
254
257
|
`);
|
|
255
258
|
}
|
|
256
259
|
|
|
257
|
-
// Graceful shutdown
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
260
|
+
// Graceful shutdown (only for primary/single-process, workers handle via IPC)
|
|
261
|
+
if (!process.env.PGSERVE_WORKER) {
|
|
262
|
+
const shutdown = async () => {
|
|
263
|
+
console.log('\nShutting down...');
|
|
264
|
+
await server.stop();
|
|
265
|
+
console.log('Server stopped.');
|
|
266
|
+
process.exit(0);
|
|
267
|
+
};
|
|
264
268
|
|
|
265
|
-
|
|
266
|
-
|
|
269
|
+
process.on('SIGINT', shutdown);
|
|
270
|
+
process.on('SIGTERM', shutdown);
|
|
271
|
+
}
|
|
267
272
|
|
|
268
273
|
// Keep process alive
|
|
269
274
|
await new Promise(() => {});
|
package/package.json
CHANGED
package/src/cluster.js
CHANGED
|
@@ -25,7 +25,7 @@ import { EventEmitter } from 'events';
|
|
|
25
25
|
class ClusterRouter extends EventEmitter {
|
|
26
26
|
constructor(options = {}) {
|
|
27
27
|
super();
|
|
28
|
-
this.port = options.port ||
|
|
28
|
+
this.port = options.port || 8432;
|
|
29
29
|
this.host = options.host || '127.0.0.1';
|
|
30
30
|
this.pgSocketPath = options.pgSocketPath; // From PRIMARY
|
|
31
31
|
this.pgPort = options.pgPort;
|
|
@@ -74,6 +74,8 @@ class ClusterRouter extends EventEmitter {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
this.adminClient = new pg.Client(connectionConfig);
|
|
77
|
+
// Suppress errors during shutdown (PostgreSQL terminating connections)
|
|
78
|
+
this.adminClient.on('error', () => {});
|
|
77
79
|
await this.adminClient.connect();
|
|
78
80
|
}
|
|
79
81
|
|
|
@@ -178,7 +180,11 @@ class ClusterRouter extends EventEmitter {
|
|
|
178
180
|
this.connections.clear();
|
|
179
181
|
|
|
180
182
|
if (this.adminClient) {
|
|
181
|
-
|
|
183
|
+
try {
|
|
184
|
+
await this.adminClient.end();
|
|
185
|
+
} catch {
|
|
186
|
+
// Ignore - connection may already be terminated
|
|
187
|
+
}
|
|
182
188
|
}
|
|
183
189
|
|
|
184
190
|
if (this.server) {
|
|
@@ -192,7 +198,7 @@ class ClusterRouter extends EventEmitter {
|
|
|
192
198
|
*/
|
|
193
199
|
export async function startClusterServer(options = {}) {
|
|
194
200
|
const numWorkers = options.workers || os.cpus().length;
|
|
195
|
-
const port = options.port ||
|
|
201
|
+
const port = options.port || 8432;
|
|
196
202
|
const host = options.host || '127.0.0.1';
|
|
197
203
|
const pgPort = options.pgPort || (port + 1000);
|
|
198
204
|
|
|
@@ -231,11 +237,18 @@ export async function startClusterServer(options = {}) {
|
|
|
231
237
|
workers.set(worker.id, worker);
|
|
232
238
|
}
|
|
233
239
|
|
|
234
|
-
//
|
|
240
|
+
// Track shutdown state to prevent worker restart during shutdown
|
|
241
|
+
let shuttingDown = false;
|
|
242
|
+
|
|
243
|
+
// Restart dead workers (unless shutting down)
|
|
235
244
|
cluster.on('exit', (worker, code, signal) => {
|
|
236
|
-
console.log(`[pgserve] Worker ${worker.id} died (${signal || code}), restarting...`);
|
|
237
245
|
workers.delete(worker.id);
|
|
238
246
|
|
|
247
|
+
if (shuttingDown) {
|
|
248
|
+
return; // Don't restart during shutdown
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
console.log(`[pgserve] Worker ${worker.id} died (${signal || code}), restarting...`);
|
|
239
252
|
const newWorker = cluster.fork({
|
|
240
253
|
PGSERVE_WORKER: 'true',
|
|
241
254
|
PGSERVE_PORT: String(port),
|
|
@@ -270,6 +283,7 @@ export async function startClusterServer(options = {}) {
|
|
|
270
283
|
pgSocketPath,
|
|
271
284
|
stop: async () => {
|
|
272
285
|
console.log('[pgserve] Stopping cluster...');
|
|
286
|
+
shuttingDown = true; // Prevent worker restart during shutdown
|
|
273
287
|
for (const worker of workers.values()) {
|
|
274
288
|
worker.send({ type: 'shutdown' });
|
|
275
289
|
}
|
|
@@ -292,7 +306,7 @@ export async function startClusterServer(options = {}) {
|
|
|
292
306
|
} else {
|
|
293
307
|
// WORKER: Only run TCP routing, connect to PRIMARY's PostgreSQL
|
|
294
308
|
const router = new ClusterRouter({
|
|
295
|
-
port: parseInt(process.env.PGSERVE_PORT) ||
|
|
309
|
+
port: parseInt(process.env.PGSERVE_PORT) || 8432,
|
|
296
310
|
host: process.env.PGSERVE_HOST || '127.0.0.1',
|
|
297
311
|
pgSocketPath: process.env.PGSERVE_PG_SOCKET || null,
|
|
298
312
|
pgPort: parseInt(process.env.PGSERVE_PG_PORT) || 6432,
|
package/src/dashboard.js
CHANGED
|
@@ -56,7 +56,7 @@ export class Dashboard {
|
|
|
56
56
|
*/
|
|
57
57
|
showHeader(config = {}) {
|
|
58
58
|
const mode = config.memoryMode ? 'In-memory' : 'Persistent';
|
|
59
|
-
const port = config.port ||
|
|
59
|
+
const port = config.port || 8432;
|
|
60
60
|
const host = config.host || '127.0.0.1';
|
|
61
61
|
const syncTo = config.syncTo ? ` → ${this._maskUrl(config.syncTo)}` : '';
|
|
62
62
|
|
|
@@ -169,7 +169,7 @@ export class Dashboard {
|
|
|
169
169
|
* Show final ready message
|
|
170
170
|
*/
|
|
171
171
|
showReady(config = {}) {
|
|
172
|
-
const port = config.port ||
|
|
172
|
+
const port = config.port || 8432;
|
|
173
173
|
const host = config.host || '127.0.0.1';
|
|
174
174
|
|
|
175
175
|
console.log('');
|
package/src/router.js
CHANGED
|
@@ -27,7 +27,7 @@ import pino from 'pino';
|
|
|
27
27
|
export class MultiTenantRouter extends EventEmitter {
|
|
28
28
|
constructor(options = {}) {
|
|
29
29
|
super();
|
|
30
|
-
this.port = options.port ||
|
|
30
|
+
this.port = options.port || 8432;
|
|
31
31
|
this.host = options.host || '127.0.0.1';
|
|
32
32
|
this.baseDir = options.baseDir || null; // null = memory mode
|
|
33
33
|
this.memoryMode = !options.baseDir;
|