Última actividad 1705997430

TheRealToxicDev's Avatar TheRealToxicDev revisó este gist 1705997430. Ir a la revisión

1 file changed, 0 insertions, 0 deletions

gistfile1.txt renombrado a gistfile1.ts

Archivo renombrado sin cambios

TheRealToxicDev's Avatar TheRealToxicDev revisó este gist 1705997422. Ir a la revisión

1 file changed, 301 insertions

gistfile1.txt(archivo creado)

@@ -0,0 +1,301 @@
1 + import { Logger } from "../log.client";
2 + import * as DTypes from '../../types/db.types';
3 + import { IInstance, IInstanceClient, InstanceInfo } from "../../types/instance";
4 + import { InstanceErrors } from '../../types/err.types';
5 + import { CordXError } from "../error.client";
6 +
7 + export class InstanceClient implements IInstanceClient {
8 + private static instances: Map<string, InstanceClient> = new Map();
9 + private errors: typeof InstanceErrors = InstanceErrors;
10 + private idleTimeoutDuration: number = 1000 * 60 * 20;
11 + private warningInterval: number = 1000 * 60 * 5;
12 + public instance: IInstance;
13 +
14 + private constructor(instance: any, name: string) {
15 + this.instance = {
16 + ...instance,
17 + id: InstanceClient.generateId(),
18 + name: name,
19 + createdAt: new Date(),
20 + isActive: true,
21 + isIdle: false,
22 + lastUsed: new Date().toLocaleTimeString(),
23 + idleTimeout: null,
24 + idleStart: null,
25 + logs: Logger.getInstance(name, false),
26 + create: this.createInstance,
27 + destroy: this.destroyInstance
28 + }
29 + }
30 +
31 + private static generateId(): string {
32 + let id: string;
33 + do {
34 + id = Math.floor(Math.random() * 9 + 1).toString();
35 + for (let i = 0; i < 17; i++) {
36 + id += Math.floor(Math.random() * 10).toString();
37 + }
38 + } while (InstanceClient.instances.has(id));
39 + return id;
40 + }
41 +
42 + /**
43 + * @function setIdleState
44 + * @description Sets the instance to idle state.
45 + * @returns {void}
46 + * @memberof InstanceClient
47 + * @private internal use only
48 + * @memberof InstanceClient
49 + */
50 + private async setIdleState(): Promise<void> {
51 + this.instance.isActive = false;
52 + this.instance.isIdle = true;
53 + this.instance.idleStart = Date.now();
54 + await this.monitorState(this.instance.name);
55 +
56 + return this.instance.logs.trace(this.errors['INSTANCE_IDLE']({
57 + message: `Instance: ${this.instance.name}(${this.instance.id}) is now circulating in the idle pool.`,
58 + details: [
59 + `- This instance will be destroyed in ${this.idleTimeoutDuration / 1000 / 60} minutes.`,
60 + `- If you wish to keep this instance alive, please perform an operation on it to reset its active state.`
61 + ]
62 + }))
63 + }
64 +
65 + /**
66 + * @function setActiveState
67 + * @description Sets the instance to active state.
68 + * @returns {void}
69 + * @memberof InstanceClient
70 + * @private internal use only
71 + * @memberof InstanceClient
72 + */
73 + private setActiveState(): void {
74 + this.instance.isActive = true;
75 + this.instance.idleStart = null;
76 + this.instance.lastUsed = new Date();
77 + await this.monitorState(this.instance.name);
78 +
79 + if (this.instance.idleTimeout) {
80 + clearTimeout(this.instance.idleTimeout);
81 + this.instance.idleTimeout = null;
82 + this.instance.isIdle = false;
83 + this.instance.idleStart = null;
84 + }
85 + }
86 +
87 + private monitorState(): void {
88 +
89 + const instance = this.instance
90 +
91 + if (!instance) return;
92 +
93 + if (instance.idleTimeout) {
94 + clearInterval(instance.idleTimeout);
95 + instance.idleTimeout = null;
96 + instance.isIdle = false;
97 + instance.idleStart = null;
98 + }
99 +
100 + let count = 0;
101 + const max = instance.idleTimeoutDuration / instance.warningInterval;
102 +
103 + const logMessage = (idleDuration: number, fatal?: boolean = false) => {
104 + const method = fatal ? instance.logs.fatal : instance.logs.trace;
105 + method.call(instance.logs, this.errors['INSTANCE_MONITOR']({
106 + message: `Instance: ${instance.name}(${instance.id}) has been idle for ${idleDuration / 1000 / 60} minutes.`,
107 + details: fatal ? [
108 + `- This instance has been idle for way too long and will now be destroyed to prevent memory leaks/overloads.`
109 + ] : [
110 + `- This instance will be destroyed in ${instance.idleTimeoutDuration / 1000 / 60} minutes.`,
111 + `- If you wish to keep this instance alive, please perform an operation on it to reset its active state.`
112 + ]
113 + }))
114 + }
115 +
116 + const warnAndClose = () => {
117 + if (instance.lastUsed) {
118 + const currentTime = new Date().getTime();
119 + const lastUsedTime = instance.lastUsed ? instance.lastUsed.getTime() : currentTime;
120 + const idleDuration = currentTime - lastUsedTime;
121 + if (idleDuration < instance.idleTimeoutDuration) {
122 + logMessage(idleDuration);
123 + count++;
124 + if (count >= max) {
125 + logMessage(idleDuration, true);
126 + instance.destroy();
127 + }
128 + } else {
129 + logMessage(idleDuration, true);
130 + instance.destroy();
131 + }
132 + }
133 + }
134 +
135 + instance.idleTimeout = setInterval(warnAndClose, instance.warningInterval);
136 + }
137 +
138 +
139 + public createInstance(instance: InstanceClient, name: string): InstanceClient | CordXError {
140 + let exists = InstanceClient.instances.get(name);
141 +
142 + if (exists) return exists.instance.getInstance().catch((err: Error) => {
143 + let error = instance.errors['INSTANCE_CREATION_FAILED']({});
144 + let { status, message = err.stack } = error;
145 +
146 + throw this.instance.logs.fatal({ status, message });
147 + })
148 +
149 + exists = new InstanceClient(instance, name);
150 + InstanceClient.instances.set(name, exists);
151 +
152 + return exists;
153 + }
154 +
155 + public destroyInstance(): boolean {
156 + const instance = this.instance;
157 +
158 + if (instance) {
159 + try {
160 + if (instance.idleTimeout) {
161 + clearInterval(instance.idleTimeout);
162 + instance.idleTimeout = null;
163 + }
164 + InstanceClient.instances.delete(instance.name);
165 + instance.logs.fatal(this.errors['INSTANCE_DESTROYED']({
166 + message: `Instance: ${instance.name}(${instance.id}) has been destroyed.`,
167 + }))
168 + return true;
169 + } catch (error: Error) {
170 + if (error instanceof CordXError) {
171 + instance.logs.trace(this.errors['INSTANCE_DESTROY_FAILED']({
172 + message: `Failed to destroy instance: ${instance.name}(${instance.id}).`,
173 + details: [
174 + `- ${error.stack}`
175 + ]
176 +
177 + }));
178 + return false
179 + } else {
180 + instance.logs.trace(this.errors['INSTANCE_DESTROY_FAILED']({
181 + message: `Failed to destroy instance: ${instance.name}(${instance.id}).`,
182 + details: [
183 + `- ${error.stack}`
184 + ]
185 + }))
186 + return false;
187 + }
188 + }
189 + }
190 +
191 + this.errors['INSTANCE_NOT_FOUND']({
192 + message: `That instance does not exist, or has already been destroyed.`,
193 + })
194 +
195 + return false;
196 + }
197 +
198 + public static findInstance(name: string): any {
199 + const instance = InstanceClient.instances.get(name);
200 +
201 + if (!instance) return {
202 + success: false,
203 + message: `Instance: ${name} does not exist.`
204 + }
205 +
206 + return {
207 + success: true,
208 + instance: {
209 + id: instance.id,
210 + name: instance.name,
211 + created: instance.createdAt,
212 + active: instance.isActive,
213 + idle: instance.isIdle,
214 + }
215 + }
216 + }
217 +
218 + public static viewInstance(name: string): any {
219 + const instance = InstanceClient.instances.get(name);
220 +
221 + if (!instance) return {
222 + success: false,
223 + message: `Instance: ${name} does not exist.`
224 + }
225 +
226 + return {
227 + success: true,
228 + instance: {
229 + id: instance.id,
230 + name: instance.name,
231 + created: instance.createdAt,
232 + active: instance.isActive,
233 + idle: instance.isIdle,
234 + }
235 + }
236 + }
237 +
238 + /**
239 + * @function getInstance
240 + * @description Returns an instance of the specified name. If the instance does not exist, it will be created.
241 + * @param {InstanceClient} instance The instance to get/create. (usually a client or class).
242 + * @param {string} name The name of the instance to get/create (should be short and sweet).
243 + * @returns {InstanceClient | CordXError} Returns the instance of a client/class or errors out.
244 + * @memberof InstanceClient
245 + * @example
246 + * const instance = InstanceClient.getInstance(MongoClient, 'MongoDB');
247 + * if (instance instanceof CordXError) return console.error(instance.message);
248 + * console.log(instance);
249 + */
250 + private getInstance(): InstanceClient | CordXError {
251 + let exists = InstanceClient.instances.get(this.instance.name);
252 +
253 + if (!exists) exists = this.createInstance(this.instance, this.instance.name);
254 + if (!exists) return this.errors['INSTANCE_CREATION_FAILED']({
255 + details: [
256 + `- Failed to create instance: ${name}.`,
257 + `- Please check the logs for more information.`,
258 + `- If this issue persists, please contact Toxic Dev.`
259 + ]
260 + })
261 +
262 + return exists;
263 + }
264 +
265 + public static getAllInstances(): InstanceInfo[] {
266 + return Array.from(InstanceClient.instances.values()).map(i => ({
267 + id: i.instance.id,
268 + name: i.instance.name,
269 + created: i.instance.createdAt,
270 + active: i.instance.isActive,
271 + idle: i.instance.isIdle,
272 + }))
273 + }
274 +
275 + public static destroyAllInstances(): void {
276 + InstanceClient.instances.forEach((instance: InstanceClient) => {
277 + InstanceClient.destroyInstance(instance.name);
278 + })
279 + }
280 +
281 + public static getInstanceCount(): number {
282 + return InstanceClient.instances.size;
283 + }
284 +
285 + public performOperation(operation: string): void {
286 + const instance = InstanceClient.instances.get(this.instance.name);
287 +
288 + if (!instance) return this.errors.
289 +
290 + if(this.instance) {
291 + instance.lastUsed = Date.now();
292 + InstanceClient.monitorState(name);
293 + instance.logs.info(`Instance: ${instance.name}(${instance.id}) is performing operation: ${operation}`)
294 + if (instance.isIdle) {
295 + InstanceClient.setActiveState(name);
296 + } else {
297 + InstanceClient.setIdleState(name);
298 + }
299 + }
300 + }
301 + }
Siguiente Anterior