monitor/core/modules/FxResources.ts
2025-04-16 22:30:27 +07:00

144 lines
3.7 KiB
TypeScript

const modulename = 'FxResources';
import consoleFactory from '@lib/console';
import { Stopwatch } from './FxMonitor/utils';
const console = consoleFactory(modulename);
type ResourceEventType = {
type: 'txAdminResourceEvent';
resource: string;
event: 'onResourceStarting'
| 'onResourceStart'
| 'onServerResourceStart'
| 'onResourceListRefresh'
| 'onResourceStop'
| 'onServerResourceStop';
};
type ResourceReportType = {
ts: Date,
resources: any[]
}
type ResPendingStartState = {
name: string;
time: Stopwatch;
}
type ResBootLogEntry = {
tsBooted: number;
resource: string;
duration: number;
};
/**
* Module responsible to track FXServer resource states.
* NOTE: currently it is not tracking the state during runtime, and it is just being used
* to assist with tracking the boot process.
*/
export default class FxResources {
public resourceReport?: ResourceReportType;
private resBooting: ResPendingStartState | null = null;
private resBootLog: ResBootLogEntry[] = [];
/**
* Reset boot state on server close
*/
handleServerClose() {
this.resBooting = null;
this.resBootLog = [];
}
/**
* Handler for all txAdminResourceEvent FD3 events
*/
handleServerEvents(payload: ResourceEventType, mutex: string) {
const { resource, event } = payload;
if (!resource || !event) {
console.verbose.error(`Invalid txAdminResourceEvent payload: ${JSON.stringify(payload)}`);
} else if (event === 'onResourceStarting') {
//Resource will start
this.resBooting = {
name: resource,
time: new Stopwatch(true),
}
} else if (event === 'onResourceStart') {
//Resource started
this.resBootLog.push({
resource,
duration: this.resBooting?.time.elapsed ?? 0,
tsBooted: Date.now(),
})
}
}
/**
* Returns the status of the resource boot process
*/
public get bootStatus() {
let elapsedSinceLast = null;
if (this.resBootLog.length > 0) {
const tsMs = this.resBootLog[this.resBootLog.length - 1].tsBooted;
elapsedSinceLast = Math.floor((Date.now() - tsMs) / 1000);
}
return {
current: this.resBooting,
elapsedSinceLast,
}
}
/**
* Handle resource report.
* NOTE: replace this when we start tracking resource states internally
*/
tmpUpdateResourceList(resources: any[]) {
this.resourceReport = {
ts: new Date(),
resources,
}
}
};
/*
NOTE Resource load scenarios knowledge base:
- resource lua error:
- `onResourceStarting` sourceRes
- print lua error
- `onResourceStart` sourceRes
- resource lua crash/hang:
- `onResourceStarting` sourceRes
- crash/hang
- dependency missing:
- `onResourceStarting` sourceRes
- does not get to `onResourceStart`
- dependency success:
- `onResourceStarting` sourceRes
- `onResourceStarting` dependency
- `onResourceStart` dependency
- `onResourceStart` sourceRes
- webpack/yarn fail:
- `onResourceStarting` sourceRes
- does not get to `onResourceStart`
- webpack/yarn success:
- `onResourceStarting` chat
- `onResourceStarting` yarn
- `onResourceStart` yarn
- `onResourceStarting` webpack
- `onResourceStart` webpack
- server first tick
- wait for build
- `onResourceStarting` chat
- `onResourceStart` chat
- ensure started resource:
- `onResourceStop` sourceRes
- `onResourceStarting` sourceRes
- `onResourceStart` sourceRes
- `onServerResourceStop` sourceRes
- `onServerResourceStart` sourceRes
*/