@ezetgalaxy/titan 26.7.0 → 26.7.2

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/README.md CHANGED
@@ -276,7 +276,7 @@ No exports wiring. No globals. No boilerplate.
276
276
 
277
277
  # 📦 Version
278
278
 
279
- **Titan v25 — Stable**
279
+ **Titan v26 — Stable**
280
280
 
281
281
  * Production-ready runtime
282
282
  * Safe JS execution
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ezetgalaxy/titan",
3
- "version": "26.7.0",
3
+ "version": "26.7.2",
4
4
  "description": "Titan Planet is a JavaScript-first backend framework that embeds JS actions into a Rust + Axum server and ships as a single native binary. Routes are compiled to static metadata; only actions run in the embedded JS runtime. No Node.js. No event loop in production.",
5
5
  "license": "ISC",
6
6
  "author": "ezetgalaxy",
@@ -10,10 +10,12 @@ const __filename = fileURLToPath(import.meta.url);
10
10
  const __dirname = path.dirname(__filename);
11
11
 
12
12
  let serverProcess = null;
13
+ let isKilling = false;
13
14
 
14
15
  async function killServer() {
15
16
  if (!serverProcess) return;
16
17
 
18
+ isKilling = true;
17
19
  const pid = serverProcess.pid;
18
20
  const killPromise = new Promise((resolve) => {
19
21
  if (serverProcess.exitCode !== null) return resolve();
@@ -34,28 +36,47 @@ async function killServer() {
34
36
  await killPromise;
35
37
  } catch (e) { }
36
38
  serverProcess = null;
39
+ isKilling = false;
37
40
  }
38
41
 
39
- async function startRustServer() {
42
+ async function startRustServer(retryCount = 0) {
43
+ // If we are retrying, give it more time (2s), otherwise standard 1s (increased from 500ms)
44
+ const waitTime = retryCount > 0 ? 2000 : 1000;
45
+
46
+ // Ensure any previous instance is killed
40
47
  await killServer();
41
48
 
42
49
  // Give the OS a moment to release file locks on the binary
43
- await new Promise(r => setTimeout(r, 500));
50
+ await new Promise(r => setTimeout(r, waitTime));
44
51
 
45
52
  const serverPath = path.join(process.cwd(), "server");
53
+ const startTime = Date.now();
54
+
55
+ if (retryCount > 0) {
56
+ console.log(`\x1b[33m[Titan] Retrying Rust server (Attempt ${retryCount})...\x1b[0m`);
57
+ }
46
58
 
47
- serverProcess = spawn("cargo", ["run"], {
59
+ // Windows often has file locking issues during concurrent linking/metadata generation
60
+ // We force 1 job and disable incremental compilation to be safe.
61
+ serverProcess = spawn("cargo", ["run", "--jobs", "1"], {
48
62
  cwd: serverPath,
49
63
  stdio: "inherit",
50
- shell: true
64
+ shell: true,
65
+ env: { ...process.env, CARGO_INCREMENTAL: "0" }
51
66
  });
52
67
 
53
- serverProcess.on("close", (code) => {
54
- if (code !== null && code !== 0 && code !== 1) {
55
- // 1 is often just 'terminated' on windows if forced, but also error.
56
- // We just log it.
57
- }
68
+ serverProcess.on("close", async (code) => {
69
+ if (isKilling) return;
70
+
58
71
  console.log(`[Titan] Rust server exited: ${code}`);
72
+
73
+ // If exited with error and it was a short run (< 10s), likely a start-up error/lock
74
+ // Retry up to 3 times
75
+ const runTime = Date.now() - startTime;
76
+ if (code !== 0 && code !== null && runTime < 10000 && retryCount < 3) {
77
+ console.log(`\x1b[31m[Titan] Server crash detected (possibly file lock). Retrying automatically...\x1b[0m`);
78
+ await startRustServer(retryCount + 1);
79
+ }
59
80
  });
60
81
  }
61
82
 
@@ -106,8 +127,18 @@ async function startDev() {
106
127
  console.log("\x1b[31m[Titan] Build failed -- waiting for changes...\x1b[0m");
107
128
  }
108
129
 
109
- }, 200);
130
+ }, 500);
110
131
  });
111
132
  }
112
133
 
134
+ // Handle graceful exit to release file locks
135
+ async function handleExit() {
136
+ console.log("\n[Titan] Stopping server...");
137
+ await killServer();
138
+ process.exit(0);
139
+ }
140
+
141
+ process.on("SIGINT", handleExit);
142
+ process.on("SIGTERM", handleExit);
143
+
113
144
  startDev();