253 lines
3.7 KiB
TypeScript
253 lines
3.7 KiB
TypeScript
import { getLogger } from "./logger";
|
|
import { WrapperStatusMessage } from "server-manager-shared";
|
|
import { JsonFileStore } from "./persistence/jsonFileStore";
|
|
|
|
const logger = getLogger("WrapperRegistry");
|
|
|
|
export interface WrapperInfo {
|
|
|
|
id:string;
|
|
|
|
hostname:string;
|
|
|
|
commandQueue:string;
|
|
|
|
cpu:number;
|
|
|
|
ram:number;
|
|
|
|
|
|
ramFree:number;
|
|
|
|
|
|
online:boolean;
|
|
|
|
lastHeartbeat:number;
|
|
|
|
|
|
servers: WrapperStatusMessage["servers"];
|
|
|
|
}
|
|
|
|
interface WrapperRegistryState {
|
|
wrappers: Array<{
|
|
id:string;
|
|
hostname:string;
|
|
commandQueue:string;
|
|
cpu:number;
|
|
ram:number;
|
|
}>;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export class WrapperRegistry {
|
|
|
|
private wrappers =
|
|
new Map<string, WrapperInfo>();
|
|
|
|
private readonly persistence =
|
|
new JsonFileStore<WrapperRegistryState>(
|
|
"wrapperRegistry-state.json"
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
async init(): Promise<void> {
|
|
const state = await this.persistence.load();
|
|
|
|
if (!state)
|
|
return;
|
|
|
|
for (const wrapperData of state.wrappers) {
|
|
this.wrappers.set(
|
|
wrapperData.id,
|
|
{
|
|
id: wrapperData.id,
|
|
hostname: wrapperData.hostname,
|
|
commandQueue: wrapperData.commandQueue,
|
|
cpu: wrapperData.cpu,
|
|
ram: wrapperData.ram,
|
|
ramFree: wrapperData.ram,
|
|
online: false,
|
|
lastHeartbeat: 0,
|
|
servers: []
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
private toState(): WrapperRegistryState {
|
|
return {
|
|
wrappers: Array.from(this.wrappers.values()).map(
|
|
wrapper => ({
|
|
id: wrapper.id,
|
|
hostname: wrapper.hostname,
|
|
commandQueue: wrapper.commandQueue,
|
|
cpu: wrapper.cpu,
|
|
ram: wrapper.ram
|
|
})
|
|
)
|
|
};
|
|
}
|
|
|
|
private async saveState(): Promise<void> {
|
|
await this.persistence.save(
|
|
this.toState()
|
|
);
|
|
}
|
|
|
|
add(wrapper:WrapperInfo){
|
|
|
|
this.wrappers.set(
|
|
wrapper.id,
|
|
wrapper
|
|
);
|
|
|
|
logger.info(
|
|
"Wrapper added:",
|
|
wrapper.id
|
|
);
|
|
|
|
void this.saveState();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
get(id:string){
|
|
|
|
return this.wrappers.get(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
getAll(){
|
|
|
|
return Array.from(
|
|
this.wrappers.values()
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
updateHeartbeat(id:string){
|
|
|
|
|
|
const wrapper =
|
|
this.wrappers.get(id);
|
|
|
|
|
|
|
|
if(!wrapper)
|
|
return;
|
|
|
|
|
|
|
|
wrapper.lastHeartbeat =
|
|
Date.now();
|
|
|
|
|
|
wrapper.online =
|
|
true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
update(wrapper:WrapperInfo){
|
|
|
|
this.wrappers.set(
|
|
wrapper.id,
|
|
wrapper
|
|
);
|
|
|
|
void this.saveState();
|
|
}
|
|
|
|
|
|
checkOffline(timeout:number){
|
|
|
|
|
|
const now =
|
|
Date.now();
|
|
|
|
|
|
|
|
for(const wrapper of this.wrappers.values()){
|
|
|
|
|
|
if(
|
|
wrapper.online &&
|
|
now - wrapper.lastHeartbeat > timeout
|
|
){
|
|
|
|
|
|
wrapper.online = false;
|
|
|
|
|
|
logger.warn(
|
|
"Wrapper offline:",
|
|
wrapper.id
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
updateStatus(data: WrapperStatusMessage){
|
|
|
|
const wrapper =
|
|
this.wrappers.get(
|
|
data.wrapperId
|
|
);
|
|
|
|
|
|
|
|
if(!wrapper)
|
|
return;
|
|
|
|
|
|
|
|
wrapper.ramFree =
|
|
data.ramFree;
|
|
|
|
|
|
|
|
wrapper.servers =
|
|
data.servers;
|
|
|
|
|
|
|
|
wrapper.lastHeartbeat =
|
|
Date.now();
|
|
|
|
|
|
|
|
wrapper.online =
|
|
true;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|