/**
* Deploy namespace apply handler for unified MetadataBase
*
* Extracted from lib/ci/deploy-apply.js
* Processes single deploy operations within the unified apply batch.
*
* Key schema (unified):
* server:{serverKey} → { serverKey, instanceUrl, hostname, status, registeredAt }
* deploy:{repoName} → { repoName, channel, commitHash, branch, deployedBy, deployedAt }
* deploy-log:{repoName}:{timestamp} → { repoName, serverKey, commitHash, branch, channel, timestamp }
*/
/**
* Apply a single deploy-namespace operation
*
* @param {object} op - Operation with { ns: 'deploy', type, ... }
* @param {object} batch - Hyperbee batch (caller flushes)
* @param {object} base - Autobase host (for addWriter/removeWriter)
*/
export async function applyDeployOp (op, batch, base) {
switch (op.type) {
case 'register-server': {
await batch.put(`server:${op.serverKey}`, {
serverKey: op.serverKey,
instanceUrl: op.instanceUrl || null,
hostname: op.hostname || null,
status: 'active',
registeredAt: op.timestamp || 0
})
break
}
case 'deploy-complete': {
// Update current deploy state (last-writer-wins via Autobase linearization)
await batch.put(`deploy:${op.repoName}`, {
repoName: op.repoName,
channel: op.channel || op.repoName,
commitHash: op.commitHash,
branch: op.branch,
deployedBy: op.serverKey || null,
deployedAt: op.timestamp || 0
})
// Append to deploy log (immutable history)
const ts = op.timestamp || 0
await batch.put(`deploy-log:${op.repoName}:${ts}`, {
repoName: op.repoName,
serverKey: op.serverKey || null,
commitHash: op.commitHash,
branch: op.branch,
channel: op.channel || op.repoName,
timestamp: ts
})
break
}
case 'ref-update': {
// Store latest ref value per repo+ref path.
// Autobase linearization ensures last-writer-wins semantics.
// Federation peers watch this key to know when to sync.
const refKey = `ref:${op.repoName}:${op.ref}`
const existing = await batch.get(refKey)
const existingVersion = existing?.value?.version || 0
// Only apply if version is higher (monotonic — prevents stale reverts)
if (op.version > existingVersion) {
await batch.put(refKey, {
repoName: op.repoName,
ref: op.ref,
sha: op.sha,
version: op.version,
serverKey: op.serverKey || null,
timestamp: op.timestamp || 0
})
}
break
}
case 'add-writer': {
if (op.writerKey) {
try {
await base.addWriter(Buffer.from(op.writerKey, 'hex'), { indexer: true })
} catch (err) {
console.error(`[Deploy:apply] add-writer failed for ${op.writerKey.slice(0, 16)}...: ${err.message}`)
}
}
break
}
}
}