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")
|
||||
|
||||
// =============================================================================
|
||||
// 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
|
||||
// =============================================================================
|
||||
|
||||
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()
|
||||
let cleanup: (() => void) | undefined
|
||||
|
||||
|
|
@ -213,15 +260,15 @@ async function runPlugin(ctx: any, options: any) {
|
|||
log("Plugin cleaning up...")
|
||||
eventController.abort()
|
||||
matrix.stop()
|
||||
releaseLock()
|
||||
}
|
||||
|
||||
return cleanup
|
||||
} catch (err) {
|
||||
fs.appendFileSync("/tmp/opencode-matrix-plugin/setup-error.log", `[${new Date().toISOString()}] ${String(err)}\n`)
|
||||
log(`Setup error: ${String(err)}`)
|
||||
return () => {
|
||||
cleanup?.()
|
||||
}
|
||||
releaseLock()
|
||||
return () => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue