@cocreate/server-mesh 1.1.0 → 1.2.1

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.
@@ -3,7 +3,7 @@ name: Automated Workflow
3
3
  on:
4
4
  push:
5
5
  branches:
6
- - master
6
+ - main
7
7
 
8
8
  jobs:
9
9
  about:
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [1.2.1](https://github.com/CoCreate-app/CoCreate-server-mesh/compare/v1.2.0...v1.2.1) (2026-07-19)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * set default branch to main ([50a0548](https://github.com/CoCreate-app/CoCreate-server-mesh/commit/50a054846d72ca79bb564aaf2546257c41f62051))
7
+
8
+ # [1.2.0](https://github.com/CoCreate-app/CoCreate-server-mesh/compare/v1.1.0...v1.2.0) (2026-07-18)
9
+
10
+
11
+ ### Features
12
+
13
+ * implement coordinated graceful shutdown and improve server instance eviction handling ([c667b53](https://github.com/CoCreate-app/CoCreate-server-mesh/commit/c667b53d1519c50bb7d4f0a9f78657fc6fefbd56))
14
+
1
15
  # [1.1.0](https://github.com/CoCreate-app/CoCreate-server-mesh/compare/v1.0.0...v1.1.0) (2026-07-17)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/server-mesh",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "Pluggable, event-driven WebSocket clustering and P2P mesh driver for CoCreate Server, enabling dynamic server-to-server state synchronization across multi-cloud and bare-metal environments.",
5
5
  "keywords": [
6
6
  "cocreate-socket",
package/release.config.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  dryRun: false,
3
- branches: ["master"],
3
+ branches: ["main"],
4
4
  plugins: [
5
5
  "@semantic-release/commit-analyzer",
6
6
  "@semantic-release/release-notes-generator",
package/src/index.js CHANGED
@@ -126,6 +126,14 @@ class ServerMesh extends EventEmitter {
126
126
  socketSend(uniqueSockets, payload);
127
127
  }
128
128
  }
129
+
130
+ /**
131
+ * Coordinates the graceful shutdown sequence. Called directly from the Master server class.
132
+ * @returns {Promise<void>} Resolves when all connections have dropped and port binds are freed
133
+ */
134
+ async close() {
135
+ return closeMesh();
136
+ }
129
137
  }
130
138
 
131
139
  const serverMeshInstance = new ServerMesh();
@@ -266,9 +274,6 @@ function removeSocketFromAllOrgServers(ws) {
266
274
  export async function init(server) {
267
275
  serverCtx = server;
268
276
 
269
- process.on('SIGINT', handleGracefulShutdown);
270
- process.on('SIGTERM', handleGracefulShutdown);
271
-
272
277
  const isPrimary = serverCtx.isPrimary;
273
278
 
274
279
  if (!isPrimary) {
@@ -445,17 +450,32 @@ export async function init(server) {
445
450
  wsPingInterval = setInterval(pingActiveWebsockets, 30000);
446
451
  }
447
452
 
448
-
449
453
  /**
450
454
  * Registers this server instance once on startup to allow discovery.
451
455
  */
452
456
  async function registerServer() {
453
457
  if (isGracefulExitRunning || !serverCtx?.crud) return;
458
+ const instanceId = serverCtx.infrastructure?.instanceId;
459
+ if (instanceId) {
460
+ try {
461
+ await serverCtx.crud.send({
462
+ method: 'object.delete',
463
+ array: 'servers',
464
+ $filter: {
465
+ query: { 'infrastructure.instanceId': instanceId },
466
+ limit: 0
467
+ },
468
+ organization_id: serverCtx.organization_id,
469
+ host: serverCtx.host
470
+ });
471
+ } catch (err) {
472
+ console.warn("[@cocreate/server-mesh] Startup instance-eviction run failed/skipped:", err.message);
473
+ }
474
+ }
454
475
 
455
476
  const registerPayload = {
456
- method: 'object.update',
477
+ method: 'object.create',
457
478
  array: 'servers',
458
- upsert: true,
459
479
  object: {
460
480
  _id: serverCtx.id,
461
481
  ip: serverCtx.ip,
@@ -501,12 +521,14 @@ function pingActiveWebsockets() {
501
521
 
502
522
  /**
503
523
  * Cleanly handles node evictions and releases network bindings.
524
+ * Rewritten to support fully coordinated async invocation from Primary Server controller without process.exit
525
+ * @returns {Promise<void>} Resolves when the HTTPS mesh server port is successfully released.
504
526
  */
505
- async function handleGracefulShutdown() {
527
+ async function closeMesh() {
506
528
  if (isGracefulExitRunning) return;
507
529
  isGracefulExitRunning = true;
508
530
 
509
- console.log(`\n[@cocreate/server-mesh] Graceful shutdown initiated. Cleaning up mesh state...`);
531
+ console.log(`[@cocreate/server-mesh] Coordinated secure mesh shutdown triggered. Evicting state...`);
510
532
 
511
533
  clearInterval(wsPingInterval);
512
534
 
@@ -542,19 +564,16 @@ async function handleGracefulShutdown() {
542
564
  try { meshWss.close(); } catch {}
543
565
  }
544
566
 
545
- if (secureMeshServer) {
546
- secureMeshServer.close(() => {
547
- console.log(`[@cocreate/server-mesh] Port ${MESH_PORT} successfully released.`);
548
- process.exit(0);
549
- });
550
- } else {
551
- process.exit(0);
552
- }
553
-
554
- setTimeout(() => {
555
- console.warn('[@cocreate/server-mesh] Force-exiting gracefully hung process.');
556
- process.exit(1);
557
- }, 3000).unref();
567
+ return new Promise((resolve) => {
568
+ if (secureMeshServer) {
569
+ secureMeshServer.close(() => {
570
+ console.log(`[@cocreate/server-mesh] Secure inter-node port ${MESH_PORT} successfully released.`);
571
+ resolve();
572
+ });
573
+ } else {
574
+ resolve();
575
+ }
576
+ });
558
577
  }
559
578
 
560
579
  /**
@@ -563,24 +582,6 @@ async function handleGracefulShutdown() {
563
582
  async function getServers() {
564
583
  if (isGracefulExitRunning || !serverCtx?.crud) return;
565
584
 
566
- const instanceId = serverCtx.infrastructure?.instanceId;
567
- if (instanceId) {
568
- try {
569
- await serverCtx.crud.send({
570
- method: 'object.delete',
571
- array: 'servers',
572
- $filter: {
573
- query: { 'infrastructure.instanceId': instanceId },
574
- limit: 0
575
- },
576
- organization_id: serverCtx.organization_id,
577
- host: serverCtx.host
578
- });
579
- } catch (err) {
580
- console.warn("[@cocreate/server-mesh] Startup instance-eviction run failed/skipped:", err.message);
581
- }
582
- }
583
-
584
585
  // Register profile once on boot
585
586
  await registerServer();
586
587