139 lines
4.2 KiB
JavaScript
139 lines
4.2 KiB
JavaScript
// src/services/velocityClient.js
|
|
// Handles dynamic backend registration with the Velocity ZpackVelocityBridge plugin.
|
|
|
|
import fetch from "node-fetch";
|
|
import crypto from "crypto";
|
|
import dotenv from "dotenv";
|
|
|
|
dotenv.config();
|
|
|
|
const VELOCITY_URL = process.env.VELOCITY_URL || "http://10.70.0.241:8081";
|
|
const SHARED_SECRET = process.env.ZPACK_SECRET;
|
|
|
|
function getSecretHash() {
|
|
return crypto.createHash("sha256").update(SHARED_SECRET).digest("hex");
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
/* EXISTENCE CHECK */
|
|
/* -------------------------------------------------------------------------- */
|
|
export async function serverExists(name) {
|
|
try {
|
|
const res = await fetch(`${VELOCITY_URL}/zpack/list`);
|
|
if (!res.ok) return false;
|
|
const data = await res.json();
|
|
return Array.isArray(data.servers) && data.servers.some(s => s.name === name);
|
|
} catch (err) {
|
|
console.error(`[velocityClient] ⚠️ Server existence check failed: ${err.message}`);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// --- Internal deduplication cache ---
|
|
const registrationCache = new Map();
|
|
|
|
/**
|
|
* Register a backend server with Velocity dynamically.
|
|
* Adds deduplication to prevent duplicate registration attempts within 10 seconds.
|
|
*
|
|
* @param {Object} params
|
|
* @param {string} params.name - FQDN or short server name
|
|
* @param {string} params.address - IP address of the backend container
|
|
* @param {number} params.port - Listening port (e.g. 25565)
|
|
*/
|
|
export async function registerServer({ name, address, port }) {
|
|
const key = `${name}:${address}:${port}`;
|
|
const now = Date.now();
|
|
|
|
// Debounce repeated registrations for the same backend
|
|
if (registrationCache.has(key) && now - registrationCache.get(key) < 10000) {
|
|
console.log(`[velocityClient] Skipping duplicate registration for ${key}`);
|
|
return "duplicate-skip";
|
|
}
|
|
registrationCache.set(key, now);
|
|
|
|
const payload = { server_name: name, address, port };
|
|
const secretHash = getSecretHash();
|
|
|
|
console.log(`[velocityClient] Registering backend: ${name} -> ${address}:${port}`);
|
|
console.log(`[velocityClient] Using Velocity URL: ${VELOCITY_URL}`);
|
|
|
|
const res = await fetch(`${VELOCITY_URL}/zpack/register`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"X-Zpack-Secret": secretHash,
|
|
},
|
|
body: JSON.stringify(payload),
|
|
});
|
|
|
|
if (!res.ok) {
|
|
const text = await res.text();
|
|
throw new Error(`Velocity register failed (${res.status}): ${text}`);
|
|
}
|
|
|
|
const text = await res.text();
|
|
console.log(`[velocityClient] ✓ Velocity registered ${name} → ${address}:${port}`);
|
|
return text;
|
|
}
|
|
|
|
/**
|
|
* Unregister a backend server from Velocity dynamically.
|
|
* @param {string} name - Short hostname or FQDN
|
|
*/
|
|
export async function unregisterServer(name) {
|
|
// Convert short name → full FQDN if needed
|
|
let serverName = name;
|
|
const ZONE = process.env.CF_ZONE_NAME || "zerolaghub.quest";
|
|
if (!serverName.includes(".")) {
|
|
serverName = `${serverName}.${ZONE}`;
|
|
}
|
|
|
|
const payload = { server_name: serverName };
|
|
const secretHash = getSecretHash();
|
|
|
|
console.log(`[velocityClient] Unregistering backend: ${serverName}`);
|
|
|
|
let res;
|
|
try {
|
|
res = await fetch(`${VELOCITY_URL}/zpack/unregister`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"X-Zpack-Secret": secretHash,
|
|
},
|
|
body: JSON.stringify(payload),
|
|
});
|
|
} catch (err) {
|
|
console.error(`[velocityClient] ⚠️ Velocity unreachable: ${err.message}`);
|
|
return false;
|
|
}
|
|
|
|
const text = await res.text();
|
|
|
|
// ---------------------------
|
|
// Idempotent delete:
|
|
// Velocity returns 404 when the backend is already removed → this is SUCCESS
|
|
// ---------------------------
|
|
if (res.status === 404) {
|
|
console.log(
|
|
`[velocityClient] ✓ Backend already removed (idempotent): ${serverName}`
|
|
);
|
|
return true;
|
|
}
|
|
|
|
if (!res.ok) {
|
|
console.error(
|
|
`[velocityClient] ❌ Velocity unregister failed (${res.status}): ${text}`
|
|
);
|
|
return false;
|
|
}
|
|
|
|
console.log(`[velocityClient] ✓ Velocity unregistered ${serverName}`);
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
export default { registerServer, unregisterServer };
|