wiki-plugin-allyabase 0.0.5 → 0.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.
@@ -112,11 +112,11 @@ setup_ecosystem() {
112
112
  declare -A service_ports=(
113
113
  [julia]=3000
114
114
  [continuebee]=2999
115
- [fount]=3002
115
+ [fount]=3006
116
116
  [bdo]=3003
117
117
  [joan]=3004
118
118
  [addie]=3005
119
- [pref]=3006
119
+ [pref]=3002
120
120
  [dolores]=3007
121
121
  [prof]=3008
122
122
  [covenant]=3011
@@ -168,9 +168,22 @@ main() {
168
168
  setup_ecosystem
169
169
 
170
170
  # Start with pm2 daemon (allows pm2 logs, pm2 status, etc.)
171
+ echo "Starting PM2 with ecosystem config..."
171
172
  ./node_modules/.bin/pm2 start ecosystem.config.js
172
173
 
173
- # Keep the script running so services stay up
174
- # This allows the wiki plugin to keep the process alive
175
- ./node_modules/.bin/pm2 logs
174
+ # Wait a moment for services to start
175
+ echo "Waiting for services to initialize..."
176
+ sleep 5
177
+
178
+ # Show PM2 status
179
+ ./node_modules/.bin/pm2 status
180
+
181
+ echo "✅ Allyabase services launched successfully"
182
+ echo "Services are running in PM2 daemon mode"
183
+ echo "Use 'pm2 status' to check service status"
184
+ echo "Use 'pm2 logs' to view logs"
185
+
186
+ # Don't block - exit cleanly so wiki plugin can track the setup script's PID
187
+ # PM2 daemon will keep services running in the background
188
+ exit 0
176
189
  }; main
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wiki-plugin-allyabase",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "Allyabase management plugin for the federated wiki",
5
5
  "keywords": [
6
6
  "wiki",
package/server/server.js CHANGED
@@ -1,5 +1,5 @@
1
1
  (function() {
2
- const { exec } = require('child_process');
2
+ const { exec, spawn } = require('child_process');
3
3
  const path = require('path');
4
4
  const http = require('http');
5
5
  const httpProxy = require('http-proxy');
@@ -26,12 +26,17 @@ const SERVICE_PORTS = {
26
26
  sanora: 7243
27
27
  };
28
28
 
29
+ // PID file for tracking PM2 process
30
+ const PM2_PID_FILE = path.join(__dirname, 'allyabase-pm2.pid');
31
+
29
32
  let baseStatus = {
30
33
  running: false,
31
34
  services: {},
32
35
  lastLaunch: null
33
36
  };
34
37
 
38
+ let allyabaseProcess = null;
39
+
35
40
  // Function to load wiki's owner.json for keypair and location emoji
36
41
  function loadWikiKeypair() {
37
42
  try {
@@ -55,6 +60,162 @@ function loadWikiKeypair() {
55
60
  }
56
61
  }
57
62
 
63
+ // Function to kill process by PID
64
+ function killProcessByPid(pid) {
65
+ try {
66
+ console.log(`[wiki-plugin-allyabase] Attempting to kill process ${pid}...`);
67
+ process.kill(pid, 'SIGTERM');
68
+
69
+ // Wait a bit, then force kill if still running
70
+ setTimeout(() => {
71
+ try {
72
+ process.kill(pid, 0); // Check if still alive
73
+ console.log(`[wiki-plugin-allyabase] Process ${pid} still running, sending SIGKILL...`);
74
+ process.kill(pid, 'SIGKILL');
75
+ } catch (err) {
76
+ // Process is dead, which is what we want
77
+ console.log(`[wiki-plugin-allyabase] ✅ Process ${pid} terminated successfully`);
78
+ }
79
+ }, 2000);
80
+
81
+ return true;
82
+ } catch (err) {
83
+ if (err.code === 'ESRCH') {
84
+ console.log(`[wiki-plugin-allyabase] Process ${pid} does not exist`);
85
+ } else {
86
+ console.error(`[wiki-plugin-allyabase] Error killing process ${pid}:`, err.message);
87
+ }
88
+ return false;
89
+ }
90
+ }
91
+
92
+ // Function to find and kill process using a specific port
93
+ function killProcessByPort(port) {
94
+ return new Promise((resolve) => {
95
+ // Use lsof to find process using the port
96
+ exec(`lsof -ti tcp:${port}`, (err, stdout, stderr) => {
97
+ if (err || !stdout.trim()) {
98
+ console.log(`[wiki-plugin-allyabase] No process found using port ${port}`);
99
+ resolve(false);
100
+ return;
101
+ }
102
+
103
+ const pid = parseInt(stdout.trim(), 10);
104
+ console.log(`[wiki-plugin-allyabase] Found process ${pid} using port ${port}`);
105
+
106
+ const killed = killProcessByPid(pid);
107
+ resolve(killed);
108
+ });
109
+ });
110
+ }
111
+
112
+ // Function to stop PM2 and all managed services
113
+ async function stopPM2() {
114
+ console.log('[wiki-plugin-allyabase] Stopping PM2 and all services...');
115
+
116
+ return new Promise((resolve) => {
117
+ // Try to stop PM2 gracefully using pm2 kill
118
+ exec('pm2 kill', (err, stdout, stderr) => {
119
+ if (err) {
120
+ console.log(`[wiki-plugin-allyabase] PM2 kill failed (might not be running): ${err.message}`);
121
+ } else {
122
+ console.log(`[wiki-plugin-allyabase] PM2 killed successfully`);
123
+ }
124
+
125
+ // Clean up PID file
126
+ cleanupPidFile();
127
+ resolve();
128
+ });
129
+ });
130
+ }
131
+
132
+ // Function to clean up orphaned processes from previous run
133
+ async function cleanupOrphanedProcesses() {
134
+ console.log('[wiki-plugin-allyabase] Checking for orphaned allyabase processes...');
135
+
136
+ // Check PID file for PM2 process
137
+ if (fs.existsSync(PM2_PID_FILE)) {
138
+ try {
139
+ const pidString = fs.readFileSync(PM2_PID_FILE, 'utf8').trim();
140
+ const pid = parseInt(pidString, 10);
141
+
142
+ console.log(`[wiki-plugin-allyabase] Found PID file with PID ${pid}`);
143
+ killProcessByPid(pid);
144
+
145
+ // Wait for process to die
146
+ await new Promise(resolve => setTimeout(resolve, 2500));
147
+
148
+ // Clean up PID file
149
+ fs.unlinkSync(PM2_PID_FILE);
150
+ console.log(`[wiki-plugin-allyabase] Cleaned up PID file`);
151
+ } catch (err) {
152
+ console.error(`[wiki-plugin-allyabase] Error reading PID file:`, err.message);
153
+ }
154
+ }
155
+
156
+ // Stop PM2 if it's running (cleans up all managed services)
157
+ await stopPM2();
158
+
159
+ // Fallback: kill any processes using our ports
160
+ console.log('[wiki-plugin-allyabase] Cleaning up any processes on service ports...');
161
+ for (const [service, port] of Object.entries(SERVICE_PORTS)) {
162
+ await killProcessByPort(port);
163
+ }
164
+
165
+ // Extra wait to ensure everything is dead
166
+ await new Promise(resolve => setTimeout(resolve, 2000));
167
+ console.log('[wiki-plugin-allyabase] Cleanup complete');
168
+ }
169
+
170
+ // Function to write PID file
171
+ function writePidFile(pid) {
172
+ try {
173
+ fs.writeFileSync(PM2_PID_FILE, pid.toString(), 'utf8');
174
+ console.log(`[wiki-plugin-allyabase] Wrote PID ${pid} to ${PM2_PID_FILE}`);
175
+ } catch (err) {
176
+ console.error(`[wiki-plugin-allyabase] Error writing PID file:`, err.message);
177
+ }
178
+ }
179
+
180
+ // Function to clean up PID file
181
+ function cleanupPidFile() {
182
+ try {
183
+ if (fs.existsSync(PM2_PID_FILE)) {
184
+ fs.unlinkSync(PM2_PID_FILE);
185
+ console.log(`[wiki-plugin-allyabase] Cleaned up PID file`);
186
+ }
187
+ } catch (err) {
188
+ console.error(`[wiki-plugin-allyabase] Error cleaning up PID file:`, err.message);
189
+ }
190
+ }
191
+
192
+ // Function to gracefully shutdown allyabase
193
+ async function shutdownAllyabase() {
194
+ console.log('[wiki-plugin-allyabase] Shutting down allyabase services...');
195
+
196
+ if (allyabaseProcess && !allyabaseProcess.killed) {
197
+ console.log(`[wiki-plugin-allyabase] Killing allyabase process ${allyabaseProcess.pid}...`);
198
+
199
+ try {
200
+ allyabaseProcess.kill('SIGTERM');
201
+
202
+ // Force kill after timeout
203
+ setTimeout(() => {
204
+ if (allyabaseProcess && !allyabaseProcess.killed) {
205
+ console.log(`[wiki-plugin-allyabase] Force killing allyabase process...`);
206
+ allyabaseProcess.kill('SIGKILL');
207
+ }
208
+ }, 2000);
209
+ } catch (err) {
210
+ console.error(`[wiki-plugin-allyabase] Error killing allyabase:`, err.message);
211
+ }
212
+ }
213
+
214
+ // Stop PM2
215
+ await stopPM2();
216
+ cleanupPidFile();
217
+ }
218
+
58
219
  // Function to check if a port is responding
59
220
  function checkPort(port) {
60
221
  return new Promise((resolve) => {
@@ -112,6 +273,11 @@ async function healthcheck() {
112
273
  async function startServer(params) {
113
274
  const app = params.app;
114
275
 
276
+ console.log('🔗 wiki-plugin-allyabase starting...');
277
+
278
+ // Clean up any orphaned allyabase/PM2 processes from previous run
279
+ await cleanupOrphanedProcesses();
280
+
115
281
  // Owner middleware to protect state-changing endpoints
116
282
  const owner = function (req, res, next) {
117
283
  if (!app.securityhandler.isAuthorized(req)) {
@@ -476,25 +642,50 @@ async function startServer(params) {
476
642
  console.log('Timestamp:', new Date().toISOString());
477
643
  console.log('-'.repeat(80));
478
644
 
479
- // Launch the setup script with spawn for better output streaming
480
- const { spawn } = require('child_process');
481
- const setupProcess = spawn('bash', [scriptPath], {
482
- stdio: 'inherit', // This will pipe stdout/stderr directly to the parent process
483
- env: process.env
645
+ // Launch the setup script with spawn
646
+ allyabaseProcess = spawn('bash', [scriptPath], {
647
+ stdio: ['ignore', 'pipe', 'pipe'], // Don't inherit stdio, capture it
648
+ env: process.env,
649
+ detached: false // Keep as child of this process
484
650
  });
485
651
 
486
- setupProcess.on('error', (error) => {
487
- console.error('❌ Error spawning allyabase process:', error);
652
+ // Write PID file immediately after spawning
653
+ writePidFile(allyabaseProcess.pid);
654
+
655
+ // Log stdout
656
+ allyabaseProcess.stdout.on('data', (data) => {
657
+ const lines = data.toString().split('\n').filter(line => line.trim());
658
+ lines.forEach(line => {
659
+ console.log(`[allyabase:${allyabaseProcess.pid}] ${line}`);
660
+ });
488
661
  });
489
662
 
490
- setupProcess.on('exit', (code, signal) => {
663
+ // Log stderr
664
+ allyabaseProcess.stderr.on('data', (data) => {
665
+ console.error(`[allyabase:${allyabaseProcess.pid}] ERROR: ${data.toString().trim()}`);
666
+ });
667
+
668
+ // Handle process exit
669
+ allyabaseProcess.on('exit', (code, signal) => {
491
670
  console.log('-'.repeat(80));
492
671
  if (code === 0) {
493
672
  console.log('✅ Allyabase setup completed successfully');
494
- } else {
495
- console.log(`⚠️ Allyabase setup exited with code: ${code}, signal: ${signal}`);
673
+ } else if (code) {
674
+ console.log(`⚠️ Allyabase setup exited with code: ${code}`);
675
+ } else if (signal) {
676
+ console.log(`⚠️ Allyabase setup killed by signal: ${signal}`);
496
677
  }
497
678
  console.log('='.repeat(80));
679
+
680
+ // Clean up PID file when process exits
681
+ cleanupPidFile();
682
+ allyabaseProcess = null;
683
+ });
684
+
685
+ allyabaseProcess.on('error', (error) => {
686
+ console.error('❌ Error spawning allyabase process:', error);
687
+ cleanupPidFile();
688
+ allyabaseProcess = null;
498
689
  });
499
690
 
500
691
  baseStatus.lastLaunch = new Date().toISOString();
@@ -503,7 +694,8 @@ async function startServer(params) {
503
694
  success: true,
504
695
  message: 'Allyabase launch initiated',
505
696
  timestamp: baseStatus.lastLaunch,
506
- scriptPath: scriptPath
697
+ scriptPath: scriptPath,
698
+ pid: allyabaseProcess.pid
507
699
  });
508
700
  } catch (err) {
509
701
  console.error('❌ Error launching allyabase:', err);
@@ -829,6 +1021,44 @@ async function startServer(params) {
829
1021
 
830
1022
  // Add deployment routes
831
1023
  deployment.addRoutes(params);
1024
+
1025
+ console.log('✅ wiki-plugin-allyabase ready!');
1026
+
1027
+ // Set up shutdown hooks to clean up allyabase/PM2 processes
1028
+ let isShuttingDown = false;
1029
+
1030
+ const handleShutdown = async (signal) => {
1031
+ if (isShuttingDown) {
1032
+ return; // Already shutting down
1033
+ }
1034
+ isShuttingDown = true;
1035
+
1036
+ console.log(`[wiki-plugin-allyabase] Received ${signal}, shutting down...`);
1037
+ await shutdownAllyabase();
1038
+
1039
+ // Give it a moment to clean up
1040
+ setTimeout(() => {
1041
+ console.log('[wiki-plugin-allyabase] Shutdown complete');
1042
+ // Don't call process.exit() here - let the parent process handle that
1043
+ }, 3000);
1044
+ };
1045
+
1046
+ // Register shutdown handlers (only once per process)
1047
+ if (!process.allyabaseShutdownRegistered) {
1048
+ process.allyabaseShutdownRegistered = true;
1049
+
1050
+ process.on('SIGINT', () => handleShutdown('SIGINT'));
1051
+ process.on('SIGTERM', () => handleShutdown('SIGTERM'));
1052
+ process.on('exit', () => {
1053
+ if (!isShuttingDown) {
1054
+ // Synchronous cleanup on exit
1055
+ console.log('[wiki-plugin-allyabase] Process exiting, cleaning up...');
1056
+ cleanupPidFile();
1057
+ }
1058
+ });
1059
+
1060
+ console.log('[wiki-plugin-allyabase] Shutdown handlers registered');
1061
+ }
832
1062
  }
833
1063
 
834
1064
  module.exports = { startServer };