magector 2.1.2 → 2.1.3

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.
Files changed (2) hide show
  1. package/package.json +5 -5
  2. package/src/mcp-server.js +54 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "magector",
3
- "version": "2.1.2",
3
+ "version": "2.1.3",
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.1.2",
43
- "@magector/cli-linux-x64": "2.1.2",
44
- "@magector/cli-linux-arm64": "2.1.2",
45
- "@magector/cli-win32-x64": "2.1.2"
42
+ "@magector/cli-darwin-arm64": "2.1.3",
43
+ "@magector/cli-linux-x64": "2.1.3",
44
+ "@magector/cli-linux-arm64": "2.1.3",
45
+ "@magector/cli-win32-x64": "2.1.3"
46
46
  },
47
47
  "keywords": [
48
48
  "magento",
package/src/mcp-server.js CHANGED
@@ -141,6 +141,7 @@ function extractJson(stdout) {
141
141
  // Track the serve process PID to clean up orphans on restart.
142
142
 
143
143
  const PID_PATH = path.join(config.magentoRoot, '.magector', 'serve.pid');
144
+ const REINDEX_PID_PATH = path.join(config.magentoRoot, '.magector', 'reindex.pid');
144
145
 
145
146
  /**
146
147
  * Write the serve process PID to disk so future instances can clean up orphans.
@@ -153,6 +154,32 @@ function removePidFile() {
153
154
  try { if (existsSync(PID_PATH)) unlinkSync(PID_PATH); } catch {}
154
155
  }
155
156
 
157
+ function writeReindexPidFile(pid) {
158
+ try { writeFileSync(REINDEX_PID_PATH, String(pid)); } catch {}
159
+ }
160
+
161
+ function removeReindexPidFile() {
162
+ try { if (existsSync(REINDEX_PID_PATH)) unlinkSync(REINDEX_PID_PATH); } catch {}
163
+ }
164
+
165
+ /**
166
+ * Check if another reindex process is already running (from another MCP instance).
167
+ * Returns the PID if alive, null otherwise.
168
+ */
169
+ function getRunningReindexPid() {
170
+ try {
171
+ if (!existsSync(REINDEX_PID_PATH)) return null;
172
+ const pid = parseInt(readFileSync(REINDEX_PID_PATH, 'utf-8').trim(), 10);
173
+ if (!pid || isNaN(pid)) return null;
174
+ process.kill(pid, 0); // signal 0 = existence check
175
+ return pid;
176
+ } catch {
177
+ // Process doesn't exist or PID file unreadable — clean up
178
+ removeReindexPidFile();
179
+ return null;
180
+ }
181
+ }
182
+
156
183
  /**
157
184
  * Kill any stale serve process from a previous MCP server instance.
158
185
  * This handles the common case where the MCP server was killed without
@@ -229,6 +256,27 @@ function checkDbFormat() {
229
256
  */
230
257
  function startBackgroundReindex() {
231
258
  if (reindexInProgress) return;
259
+
260
+ // Check if another MCP instance is already running a reindex
261
+ const existingPid = getRunningReindexPid();
262
+ if (existingPid) {
263
+ logToFile('INFO', `Reindex already running in another process (PID ${existingPid}) — skipping`);
264
+ console.error(`Reindex already running (PID ${existingPid}) — skipping`);
265
+ reindexInProgress = true; // mark locally so tools know
266
+ // Poll the external process and react when it finishes
267
+ const pollInterval = setInterval(() => {
268
+ if (!getRunningReindexPid()) {
269
+ clearInterval(pollInterval);
270
+ reindexInProgress = false;
271
+ logToFile('INFO', 'External reindex finished. Restarting serve process.');
272
+ if (serveProcess) serveProcess.kill();
273
+ searchCache.clear();
274
+ startServeProcess();
275
+ }
276
+ }, 10000);
277
+ return;
278
+ }
279
+
232
280
  if (!config.magentoRoot || !existsSync(config.magentoRoot)) {
233
281
  const msg = 'Cannot auto-reindex: MAGENTO_ROOT not set or not found';
234
282
  console.error(msg);
@@ -269,6 +317,9 @@ function startBackgroundReindex() {
269
317
  env: rustEnv,
270
318
  });
271
319
 
320
+ // Write PID file so other MCP instances know a reindex is running
321
+ writeReindexPidFile(reindexProcess.pid);
322
+
272
323
  reindexProcess.stdout.on('data', (d) => {
273
324
  const text = d.toString().replace(/\x1b\[[0-9;]*m/g, '').trim();
274
325
  if (text) logToFile('INDEX', text);
@@ -281,6 +332,7 @@ function startBackgroundReindex() {
281
332
  reindexProcess.on('exit', (code) => {
282
333
  reindexInProgress = false;
283
334
  reindexProcess = null;
335
+ removeReindexPidFile();
284
336
  if (code === 0) {
285
337
  // Atomic swap: old → .bak, new → current
286
338
  try {
@@ -311,6 +363,7 @@ function startBackgroundReindex() {
311
363
  reindexProcess.on('error', (err) => {
312
364
  reindexInProgress = false;
313
365
  reindexProcess = null;
366
+ removeReindexPidFile();
314
367
  logToFile('ERR', `Background re-index error: ${err.message}`);
315
368
  console.error(`Background re-index error: ${err.message}`);
316
369
  });
@@ -3202,6 +3255,7 @@ function cleanup(reason) {
3202
3255
  reindexProcess = null;
3203
3256
  }
3204
3257
  removePidFile();
3258
+ removeReindexPidFile();
3205
3259
  }
3206
3260
 
3207
3261
  process.on('exit', () => cleanup('process exit'));