status-sharding
Version:
Welcome to Status Sharding! This package is designed to provide an efficient and flexible solution for sharding Discord bots, allowing you to scale your bot across multiple processes or workers.
59 lines (47 loc) • 2.2 kB
text/typescript
import { MessageTypes, Serializable, StoredPromise } from '../types';
import { BaseMessage, DataType } from '../other/message';
import { ClusterManager } from '../core/clusterManager';
import { ClusterClient } from '../core/clusterClient';
/** Handles promises by storing them in a map and resolving them when the response is received. */
export class PromiseHandler {
/** List of promises and their unique identifiers. */
nonces: Map<string, StoredPromise> = new Map();
/** Creates an instance of PromiseHandler. */
constructor(private instance: ClusterManager | ClusterClient) {}
/** Resolves the promise with the data received. */
public resolve<D extends DataType, A = Serializable, P extends object = object>(message: BaseMessage<D, A, P>): void {
const promise = this.nonces.get(message._nonce);
if (!promise) return this.instance._debug(`Received a message with an unknown nonce: ${message._nonce}`);
if (promise.timeout) clearTimeout(promise.timeout);
this.nonces.delete(message._nonce);
const errorTypes = [
MessageTypes.ClientEvalResponseError,
MessageTypes.ClientManagerEvalResponseError,
MessageTypes.ClientBroadcastResponseError,
];
if (!errorTypes.includes(message._type)) {
promise.resolve(message.data);
return;
}
const data = message.data as Partial<BaseMessage<'error'>['data']>;
const error = new Error([data.message, data.stack].filter(Boolean).join('\n') || 'Unknown IPC error');
if (data.script) error.cause = data.script;
if (data.stack) error.stack = data.stack;
if (data.name) error.name = data.name;
promise.reject(error);
console.error('An error occurred while resolving an IPC promise:', data);
}
/** Creates a promise and stores it in the map. */
public async create<T>(nonce: string, timeout?: number): Promise<T> {
return await new Promise<T>((resolve, reject) => {
if (timeout === undefined || timeout < 0) this.nonces.set(nonce, { resolve, reject });
else this.nonces.set(nonce, {
resolve, reject,
timeout: setTimeout(() => {
this.nonces.delete(nonce);
reject(new Error('Promise timed out.'));
}, timeout) as NodeJS.Timeout,
});
});
}
}