magector 2.2.2 → 2.2.4
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/package.json +5 -5
- package/src/mcp-server.js +31 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "magector",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.4",
|
|
4
4
|
"description": "Semantic code search for Magento 2 — index, search, MCP server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/mcp-server.js",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"ruvector": "^0.1.96"
|
|
40
40
|
},
|
|
41
41
|
"optionalDependencies": {
|
|
42
|
-
"@magector/cli-darwin-arm64": "2.2.
|
|
43
|
-
"@magector/cli-linux-x64": "2.2.
|
|
44
|
-
"@magector/cli-linux-arm64": "2.2.
|
|
45
|
-
"@magector/cli-win32-x64": "2.2.
|
|
42
|
+
"@magector/cli-darwin-arm64": "2.2.4",
|
|
43
|
+
"@magector/cli-linux-x64": "2.2.4",
|
|
44
|
+
"@magector/cli-linux-arm64": "2.2.4",
|
|
45
|
+
"@magector/cli-win32-x64": "2.2.4"
|
|
46
46
|
},
|
|
47
47
|
"keywords": [
|
|
48
48
|
"magento",
|
package/src/mcp-server.js
CHANGED
|
@@ -166,12 +166,19 @@ function tryAcquirePrimaryLock() {
|
|
|
166
166
|
return false; // another instance is alive and primary
|
|
167
167
|
}
|
|
168
168
|
} catch { /* holder is dead, take over */ }
|
|
169
|
-
// Stale lock — reclaim
|
|
169
|
+
// Stale lock — reclaim. Use random jitter to avoid thundering herd
|
|
170
|
+
// when multiple instances detect stale lock simultaneously.
|
|
171
|
+
const jitterMs = Math.floor(Math.random() * 200) + 50;
|
|
172
|
+
const start = Date.now();
|
|
173
|
+
while (Date.now() - start < jitterMs) { /* busy-wait for sub-second jitter */ }
|
|
170
174
|
try { unlinkSync(PRIMARY_LOCK_PATH); } catch {}
|
|
171
175
|
try {
|
|
172
176
|
const fd = openSync(PRIMARY_LOCK_PATH, fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL);
|
|
173
177
|
writeFileSync(fd, String(process.pid));
|
|
174
178
|
closeSync(fd);
|
|
179
|
+
// Double-check: re-read to confirm we actually own it (no TOCTOU race)
|
|
180
|
+
const check = readFileSync(PRIMARY_LOCK_PATH, 'utf-8').trim();
|
|
181
|
+
if (check !== String(process.pid)) return false;
|
|
175
182
|
return true;
|
|
176
183
|
} catch {
|
|
177
184
|
return false; // another instance beat us
|
|
@@ -566,6 +573,14 @@ let serveReadyPromise = null;
|
|
|
566
573
|
let serveReadyResolve = null;
|
|
567
574
|
|
|
568
575
|
function startServeProcess() {
|
|
576
|
+
// Guard: if a live serve process already exists (e.g. started by another
|
|
577
|
+
// instance that won the lock race), reuse it instead of spawning a duplicate.
|
|
578
|
+
const existingPid = getExistingServePid();
|
|
579
|
+
if (existingPid) {
|
|
580
|
+
logToFile('INFO', `Reusing existing serve process (PID ${existingPid}) — skipping spawn`);
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
|
|
569
584
|
serveReadyPromise = new Promise((resolve) => { serveReadyResolve = resolve; });
|
|
570
585
|
try {
|
|
571
586
|
const args = [
|
|
@@ -699,15 +714,23 @@ function tryConnectSocket() {
|
|
|
699
714
|
} catch {}
|
|
700
715
|
});
|
|
701
716
|
|
|
702
|
-
|
|
703
|
-
isSocketClient
|
|
704
|
-
serveReady = false;
|
|
705
|
-
logToFile('WARN', 'Socket connection lost — falling back to cold-start');
|
|
706
|
-
});
|
|
707
|
-
conn.on('close', () => {
|
|
717
|
+
function handleSocketLoss(reason) {
|
|
718
|
+
if (!isSocketClient) return; // already handled
|
|
708
719
|
isSocketClient = false;
|
|
709
720
|
serveReady = false;
|
|
710
|
-
|
|
721
|
+
globalServeQuery = null;
|
|
722
|
+
logToFile('WARN', `Socket ${reason} — cleared globalServeQuery, will use cold-start fallback`);
|
|
723
|
+
// Try to reconnect after a delay (primary may have restarted)
|
|
724
|
+
setTimeout(async () => {
|
|
725
|
+
if (globalServeQuery) return; // already reconnected
|
|
726
|
+
const reconnected = await tryConnectSocket();
|
|
727
|
+
if (reconnected) {
|
|
728
|
+
logToFile('INFO', 'Reconnected to serve socket after loss');
|
|
729
|
+
}
|
|
730
|
+
}, 5000);
|
|
731
|
+
}
|
|
732
|
+
conn.on('error', () => handleSocketLoss('error'));
|
|
733
|
+
conn.on('close', () => handleSocketLoss('closed'));
|
|
711
734
|
|
|
712
735
|
// Override serveQuery to route through socket
|
|
713
736
|
const socketQueryQueue = [];
|