fix: prevent double Matrix bot startup (server + client)
OpenCode V2 loads plugins in both the background server and the client. Add a file-based mutex (/tmp/opencode-matrix-plugin.lock) so only the first instance (server) starts the Matrix bot. The second instance (client) detects the lock and returns a no-op cleanup.
This commit is contained in:
parent
51b98e02a5
commit
f981998ab8
53
index.ts
53
index.ts
|
|
@ -6,11 +6,58 @@ import { log } from "./logger.js"
|
||||||
|
|
||||||
log("Plugin module loaded")
|
log("Plugin module loaded")
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Global mutex — prevents double startup (server + client both load plugins)
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
const LOCK_FILE = "/tmp/opencode-matrix-plugin.lock"
|
||||||
|
|
||||||
|
function tryAcquireLock(): boolean {
|
||||||
|
try {
|
||||||
|
// Check if an existing lock is stale (process no longer running)
|
||||||
|
if (fs.existsSync(LOCK_FILE)) {
|
||||||
|
const existingPid = parseInt(fs.readFileSync(LOCK_FILE, "utf-8").trim(), 10)
|
||||||
|
if (existingPid && existingPid !== process.pid) {
|
||||||
|
try {
|
||||||
|
process.kill(existingPid, 0) // throws if process doesn't exist
|
||||||
|
} catch {
|
||||||
|
// Process dead, remove stale lock
|
||||||
|
fs.unlinkSync(LOCK_FILE)
|
||||||
|
}
|
||||||
|
} else if (existingPid === process.pid) {
|
||||||
|
// Same process re-entering (shouldn't happen, but be safe)
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return false // Valid lock held by another process
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fs.writeFileSync(LOCK_FILE, String(process.pid), { mode: 0o644 })
|
||||||
|
return true
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function releaseLock(): void {
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(LOCK_FILE)
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Plugin Setup
|
// Plugin Setup
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
async function runPlugin(ctx: any, options: any) {
|
async function runPlugin(ctx: any, options: any) {
|
||||||
|
// Acquire global lock — only one instance (server or client) starts the bot
|
||||||
|
const locked = tryAcquireLock()
|
||||||
|
if (!locked) {
|
||||||
|
log("Another instance already running (lock held), skipping bot startup")
|
||||||
|
return () => {}
|
||||||
|
}
|
||||||
|
|
||||||
const eventController = new AbortController()
|
const eventController = new AbortController()
|
||||||
let cleanup: (() => void) | undefined
|
let cleanup: (() => void) | undefined
|
||||||
|
|
||||||
|
|
@ -213,15 +260,15 @@ async function runPlugin(ctx: any, options: any) {
|
||||||
log("Plugin cleaning up...")
|
log("Plugin cleaning up...")
|
||||||
eventController.abort()
|
eventController.abort()
|
||||||
matrix.stop()
|
matrix.stop()
|
||||||
|
releaseLock()
|
||||||
}
|
}
|
||||||
|
|
||||||
return cleanup
|
return cleanup
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
fs.appendFileSync("/tmp/opencode-matrix-plugin/setup-error.log", `[${new Date().toISOString()}] ${String(err)}\n`)
|
fs.appendFileSync("/tmp/opencode-matrix-plugin/setup-error.log", `[${new Date().toISOString()}] ${String(err)}\n`)
|
||||||
log(`Setup error: ${String(err)}`)
|
log(`Setup error: ${String(err)}`)
|
||||||
return () => {
|
releaseLock()
|
||||||
cleanup?.()
|
return () => {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue