galactic.ts 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +45 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +45 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Connection, Server } from 'net-ipc';
|
|
2
|
-
import { GatewayIntentsString, Client } from 'discord.js';
|
|
2
|
+
import { GatewayIntentsString, Snowflake, Client } from 'discord.js';
|
|
3
3
|
import { ChildProcess } from 'child_process';
|
|
4
4
|
|
|
5
5
|
type EventPayload = {
|
|
@@ -32,6 +32,7 @@ declare class BridgeClientConnection {
|
|
|
32
32
|
readonly data: unknown;
|
|
33
33
|
connectionStatus: BridgeClientConnectionStatus;
|
|
34
34
|
readonly dev: boolean;
|
|
35
|
+
readonly establishedAt: number;
|
|
35
36
|
private _onMessage?;
|
|
36
37
|
private _onRequest?;
|
|
37
38
|
constructor(instanceID: number, connection: Connection, data: unknown, dev: boolean);
|
|
@@ -103,9 +104,10 @@ declare class Bridge {
|
|
|
103
104
|
private readonly intents;
|
|
104
105
|
private readonly shardsPerCluster;
|
|
105
106
|
private readonly clusterToStart;
|
|
107
|
+
private readonly reclusteringTimeoutInMs;
|
|
106
108
|
private readonly clusterCalculator;
|
|
107
109
|
private readonly eventMap;
|
|
108
|
-
constructor(port: number, token: string, intents: GatewayIntentsString[], shardsPerCluster: number, clusterToStart: number);
|
|
110
|
+
constructor(port: number, token: string, intents: GatewayIntentsString[], shardsPerCluster: number, clusterToStart: number, reclusteringTimeoutInMs: number);
|
|
109
111
|
start(): void;
|
|
110
112
|
private interval;
|
|
111
113
|
private checkRecluster;
|
|
@@ -121,6 +123,7 @@ declare class Bridge {
|
|
|
121
123
|
stopAllInstancesWithRestart(): Promise<void>;
|
|
122
124
|
moveCluster(instance: BridgeClientConnection, cluster: BridgeClientCluster): Promise<void>;
|
|
123
125
|
stopInstance(instance: BridgeClientConnection, recluster?: boolean): Promise<void>;
|
|
126
|
+
sendRequestToGuild(cluster: BridgeClientCluster, guildID: Snowflake, data: unknown, timeout?: number): Promise<unknown>;
|
|
124
127
|
}
|
|
125
128
|
type BridgeEventListeners = {
|
|
126
129
|
'CLUSTER_READY': ((cluster: BridgeClientCluster, guilds: number, members: number) => void) | undefined;
|
|
@@ -199,6 +202,7 @@ declare class Cluster<T extends Client> {
|
|
|
199
202
|
readonly intents: GatewayIntentsString[];
|
|
200
203
|
eventManager: EventManager;
|
|
201
204
|
client: T;
|
|
205
|
+
onSelfDestruct?: () => void;
|
|
202
206
|
private readonly eventMap;
|
|
203
207
|
constructor(instanceID: number, clusterID: number, shardList: number[], totalShards: number, token: string, intents: GatewayIntentsString[]);
|
|
204
208
|
static initial<T extends Client>(): Cluster<T>;
|
|
@@ -264,6 +268,7 @@ type BotInstanceEventListeners = {
|
|
|
264
268
|
'message': ((client: ClusterProcess, message: unknown) => void) | undefined;
|
|
265
269
|
'request': ((client: ClusterProcess, message: unknown, resolve: (data: unknown) => void, reject: (error: any) => void) => void) | undefined;
|
|
266
270
|
'PROCESS_KILLED': ((client: ClusterProcess, reason: string, processKilled: boolean) => void) | undefined;
|
|
271
|
+
'PROCESS_SELF_DESTRUCT_ERROR': ((client: ClusterProcess, reason: string, error: unknown) => void) | undefined;
|
|
267
272
|
'PROCESS_SPAWNED': ((client: ClusterProcess) => void) | undefined;
|
|
268
273
|
'PROCESS_ERROR': ((client: ClusterProcess, error: unknown) => void) | undefined;
|
|
269
274
|
'CLUSTER_READY': ((client: ClusterProcess) => void) | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Connection, Server } from 'net-ipc';
|
|
2
|
-
import { GatewayIntentsString, Client } from 'discord.js';
|
|
2
|
+
import { GatewayIntentsString, Snowflake, Client } from 'discord.js';
|
|
3
3
|
import { ChildProcess } from 'child_process';
|
|
4
4
|
|
|
5
5
|
type EventPayload = {
|
|
@@ -32,6 +32,7 @@ declare class BridgeClientConnection {
|
|
|
32
32
|
readonly data: unknown;
|
|
33
33
|
connectionStatus: BridgeClientConnectionStatus;
|
|
34
34
|
readonly dev: boolean;
|
|
35
|
+
readonly establishedAt: number;
|
|
35
36
|
private _onMessage?;
|
|
36
37
|
private _onRequest?;
|
|
37
38
|
constructor(instanceID: number, connection: Connection, data: unknown, dev: boolean);
|
|
@@ -103,9 +104,10 @@ declare class Bridge {
|
|
|
103
104
|
private readonly intents;
|
|
104
105
|
private readonly shardsPerCluster;
|
|
105
106
|
private readonly clusterToStart;
|
|
107
|
+
private readonly reclusteringTimeoutInMs;
|
|
106
108
|
private readonly clusterCalculator;
|
|
107
109
|
private readonly eventMap;
|
|
108
|
-
constructor(port: number, token: string, intents: GatewayIntentsString[], shardsPerCluster: number, clusterToStart: number);
|
|
110
|
+
constructor(port: number, token: string, intents: GatewayIntentsString[], shardsPerCluster: number, clusterToStart: number, reclusteringTimeoutInMs: number);
|
|
109
111
|
start(): void;
|
|
110
112
|
private interval;
|
|
111
113
|
private checkRecluster;
|
|
@@ -121,6 +123,7 @@ declare class Bridge {
|
|
|
121
123
|
stopAllInstancesWithRestart(): Promise<void>;
|
|
122
124
|
moveCluster(instance: BridgeClientConnection, cluster: BridgeClientCluster): Promise<void>;
|
|
123
125
|
stopInstance(instance: BridgeClientConnection, recluster?: boolean): Promise<void>;
|
|
126
|
+
sendRequestToGuild(cluster: BridgeClientCluster, guildID: Snowflake, data: unknown, timeout?: number): Promise<unknown>;
|
|
124
127
|
}
|
|
125
128
|
type BridgeEventListeners = {
|
|
126
129
|
'CLUSTER_READY': ((cluster: BridgeClientCluster, guilds: number, members: number) => void) | undefined;
|
|
@@ -199,6 +202,7 @@ declare class Cluster<T extends Client> {
|
|
|
199
202
|
readonly intents: GatewayIntentsString[];
|
|
200
203
|
eventManager: EventManager;
|
|
201
204
|
client: T;
|
|
205
|
+
onSelfDestruct?: () => void;
|
|
202
206
|
private readonly eventMap;
|
|
203
207
|
constructor(instanceID: number, clusterID: number, shardList: number[], totalShards: number, token: string, intents: GatewayIntentsString[]);
|
|
204
208
|
static initial<T extends Client>(): Cluster<T>;
|
|
@@ -264,6 +268,7 @@ type BotInstanceEventListeners = {
|
|
|
264
268
|
'message': ((client: ClusterProcess, message: unknown) => void) | undefined;
|
|
265
269
|
'request': ((client: ClusterProcess, message: unknown, resolve: (data: unknown) => void, reject: (error: any) => void) => void) | undefined;
|
|
266
270
|
'PROCESS_KILLED': ((client: ClusterProcess, reason: string, processKilled: boolean) => void) | undefined;
|
|
271
|
+
'PROCESS_SELF_DESTRUCT_ERROR': ((client: ClusterProcess, reason: string, error: unknown) => void) | undefined;
|
|
267
272
|
'PROCESS_SPAWNED': ((client: ClusterProcess) => void) | undefined;
|
|
268
273
|
'PROCESS_ERROR': ((client: ClusterProcess, error: unknown) => void) | undefined;
|
|
269
274
|
'CLUSTER_READY': ((client: ClusterProcess) => void) | undefined;
|
package/dist/index.js
CHANGED
|
@@ -244,6 +244,7 @@ var BridgeClientConnection = class {
|
|
|
244
244
|
data;
|
|
245
245
|
connectionStatus = "ready" /* READY */;
|
|
246
246
|
dev = false;
|
|
247
|
+
establishedAt = Date.now();
|
|
247
248
|
_onMessage;
|
|
248
249
|
_onRequest;
|
|
249
250
|
constructor(instanceID, connection, data, dev) {
|
|
@@ -437,6 +438,7 @@ var Bridge = class {
|
|
|
437
438
|
intents;
|
|
438
439
|
shardsPerCluster = 1;
|
|
439
440
|
clusterToStart = 1;
|
|
441
|
+
reclusteringTimeoutInMs;
|
|
440
442
|
clusterCalculator;
|
|
441
443
|
eventMap = {
|
|
442
444
|
CLUSTER_READY: void 0,
|
|
@@ -449,12 +451,13 @@ var Bridge = class {
|
|
|
449
451
|
ERROR: void 0,
|
|
450
452
|
CLIENT_STOP: void 0
|
|
451
453
|
};
|
|
452
|
-
constructor(port, token, intents, shardsPerCluster, clusterToStart) {
|
|
454
|
+
constructor(port, token, intents, shardsPerCluster, clusterToStart, reclusteringTimeoutInMs) {
|
|
453
455
|
this.port = port;
|
|
454
456
|
this.token = token;
|
|
455
457
|
this.intents = intents;
|
|
456
458
|
this.clusterToStart = clusterToStart;
|
|
457
459
|
this.shardsPerCluster = shardsPerCluster;
|
|
460
|
+
this.reclusteringTimeoutInMs = reclusteringTimeoutInMs;
|
|
458
461
|
this.clusterCalculator = new ClusterCalculator(this.clusterToStart, this.shardsPerCluster);
|
|
459
462
|
this.server = new import_net_ipc.Server({
|
|
460
463
|
port: this.port
|
|
@@ -478,7 +481,7 @@ var Bridge = class {
|
|
|
478
481
|
if (!up) {
|
|
479
482
|
return;
|
|
480
483
|
}
|
|
481
|
-
const connectedClients = this.connectedClients.values().filter((c) => c.connectionStatus == "ready" /* READY */
|
|
484
|
+
const connectedClients = this.connectedClients.values().filter((c) => c.connectionStatus == "ready" /* READY */).filter((c) => !c.dev).filter((c) => c.establishedAt + this.reclusteringTimeoutInMs < Date.now()).toArray();
|
|
482
485
|
const { most, least } = this.clusterCalculator.findMostAndLeastClustersForConnections(connectedClients);
|
|
483
486
|
if (most) {
|
|
484
487
|
const clusterToSteal = this.clusterCalculator.getClusterForConnection(most)[0] || void 0;
|
|
@@ -780,6 +783,17 @@ var Bridge = class {
|
|
|
780
783
|
await instance.connection.close("Instance stopped.", false);
|
|
781
784
|
}
|
|
782
785
|
}
|
|
786
|
+
sendRequestToGuild(cluster, guildID, data, timeout = 5e3) {
|
|
787
|
+
if (!cluster.connection) {
|
|
788
|
+
return Promise.reject(new Error("No connection defined for cluster " + cluster.clusterID));
|
|
789
|
+
}
|
|
790
|
+
return cluster.connection.eventManager.request({
|
|
791
|
+
type: "REDIRECT_REQUEST_TO_GUILD",
|
|
792
|
+
clusterID: cluster.clusterID,
|
|
793
|
+
guildID,
|
|
794
|
+
data
|
|
795
|
+
}, timeout);
|
|
796
|
+
}
|
|
783
797
|
};
|
|
784
798
|
|
|
785
799
|
// src/cluster/Cluster.ts
|
|
@@ -793,6 +807,7 @@ var Cluster = class _Cluster {
|
|
|
793
807
|
intents;
|
|
794
808
|
eventManager;
|
|
795
809
|
client;
|
|
810
|
+
onSelfDestruct;
|
|
796
811
|
eventMap = {
|
|
797
812
|
message: void 0,
|
|
798
813
|
request: void 0,
|
|
@@ -931,6 +946,10 @@ var Cluster = class _Cluster {
|
|
|
931
946
|
} else {
|
|
932
947
|
return result;
|
|
933
948
|
}
|
|
949
|
+
} else if (m.type == "SELF_DESTRUCT") {
|
|
950
|
+
if (this.onSelfDestruct) {
|
|
951
|
+
this.onSelfDestruct();
|
|
952
|
+
}
|
|
934
953
|
}
|
|
935
954
|
return void 0;
|
|
936
955
|
}
|
|
@@ -1064,6 +1083,7 @@ var BotInstance = class {
|
|
|
1064
1083
|
"message": void 0,
|
|
1065
1084
|
"request": void 0,
|
|
1066
1085
|
"PROCESS_KILLED": void 0,
|
|
1086
|
+
"PROCESS_SELF_DESTRUCT_ERROR": void 0,
|
|
1067
1087
|
"PROCESS_SPAWNED": void 0,
|
|
1068
1088
|
"ERROR": void 0,
|
|
1069
1089
|
"PROCESS_ERROR": void 0,
|
|
@@ -1093,7 +1113,8 @@ var BotInstance = class {
|
|
|
1093
1113
|
},
|
|
1094
1114
|
stdio: "inherit",
|
|
1095
1115
|
execArgv: this.execArgv,
|
|
1096
|
-
silent: false
|
|
1116
|
+
silent: false,
|
|
1117
|
+
detached: true
|
|
1097
1118
|
});
|
|
1098
1119
|
const client = new ClusterProcess(clusterID, child, shardList, totalShards);
|
|
1099
1120
|
child.stdout?.on("data", (data) => {
|
|
@@ -1128,18 +1149,29 @@ var BotInstance = class {
|
|
|
1128
1149
|
}
|
|
1129
1150
|
killProcess(client, reason) {
|
|
1130
1151
|
client.status = "stopped";
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1152
|
+
client.eventManager.request({
|
|
1153
|
+
type: "SELF_DESTRUCT",
|
|
1154
|
+
reason
|
|
1155
|
+
}, 5e3).catch(() => {
|
|
1156
|
+
if (this.eventMap.PROCESS_SELF_DESTRUCT_ERROR) this.eventMap.PROCESS_SELF_DESTRUCT_ERROR(client, reason, "Cluster didnt respond to shot-call.");
|
|
1157
|
+
}).finally(() => {
|
|
1158
|
+
if (client.child && client.child.pid) {
|
|
1159
|
+
if (client.child.kill("SIGKILL")) {
|
|
1160
|
+
if (this.eventMap.PROCESS_KILLED) this.eventMap.PROCESS_KILLED(client, reason, true);
|
|
1161
|
+
} else {
|
|
1162
|
+
if (this.eventMap.ERROR) this.eventMap.ERROR(`Failed to kill process for cluster ${client.id}`);
|
|
1163
|
+
client.child.kill("SIGKILL");
|
|
1164
|
+
}
|
|
1165
|
+
try {
|
|
1166
|
+
process.kill(-client.child.pid);
|
|
1167
|
+
} catch {
|
|
1168
|
+
}
|
|
1134
1169
|
} else {
|
|
1135
|
-
if (this.eventMap.
|
|
1136
|
-
client.child.kill("SIGKILL");
|
|
1170
|
+
if (this.eventMap.PROCESS_KILLED) this.eventMap.PROCESS_KILLED(client, reason, false);
|
|
1137
1171
|
}
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
}
|
|
1141
|
-
this.clients.delete(client.id);
|
|
1142
|
-
this.setClusterStopped(client, reason);
|
|
1172
|
+
this.clients.delete(client.id);
|
|
1173
|
+
this.setClusterStopped(client, reason);
|
|
1174
|
+
});
|
|
1143
1175
|
}
|
|
1144
1176
|
onMessage(client, message2) {
|
|
1145
1177
|
if (message2.type === "CLUSTER_READY") {
|