Skip to content

Commit ab1341d

Browse files
committed
Asynchronous stats support
1 parent a727122 commit ab1341d

File tree

5 files changed

+89
-45
lines changed

5 files changed

+89
-45
lines changed

src/build-uws-tracker.ts

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ type BuildServerParams = {
99
serverSettings: ServerItemSettings;
1010
websocketsAccess: Partial<WebSocketsAccessSettings> | undefined;
1111
indexHtml: Buffer | undefined;
12-
servers: UWebSocketsTracker[];
12+
getServersStats: () => Promise<unknown>;
1313
};
1414

1515
export function buildUwsTracker({
1616
tracker,
1717
serverSettings,
1818
websocketsAccess,
1919
indexHtml,
20-
servers,
20+
getServersStats,
2121
}: BuildServerParams): UWebSocketsTracker {
2222
if (!(serverSettings instanceof Object)) {
2323
throw Error(
@@ -41,39 +41,56 @@ export function buildUwsTracker({
4141
response.end(indexHtml);
4242
}
4343
})
44-
.get("/stats.json", (response: HttpResponse, request: HttpRequest) => {
45-
debugRequest(server, request);
44+
.get(
45+
"/stats.json",
46+
async (response: HttpResponse, request: HttpRequest) => {
47+
debugRequest(server, request);
4648

47-
const { swarms } = tracker;
48-
const peersCountPerInfoHash: Record<string, number> = {};
49+
response.onAborted(() => {
50+
response.aborted = true;
51+
});
4952

50-
let peersCount = 0;
51-
for (const [infoHash, swarm] of swarms) {
52-
peersCount += swarm.peers.length;
53+
const swarms = await tracker.getSwarms();
54+
const serversStats = await getServersStats();
5355

54-
const infoHashHex = Buffer.from(infoHash, "binary").toString("hex");
55-
peersCountPerInfoHash[infoHashHex] = swarm.peers.length;
56-
}
56+
if (!response.aborted) {
57+
const peersCountPerInfoHashPerTracker: Record<string, number>[] = [];
58+
let peersCount = 0;
5759

58-
const serversStats = [];
59-
for (const serverForStats of servers) {
60-
const { settings } = serverForStats;
61-
serversStats.push({
62-
server: `${settings.server.host}:${settings.server.port}`,
63-
webSocketsCount: serverForStats.stats.webSocketsCount,
64-
});
65-
}
60+
for (const trackerSwarms of swarms) {
61+
const peersCountPerInfoHash: Record<string, number> = {
62+
totalPeers: 0,
63+
};
6664

67-
response.writeHeader("Content-Type", "application/json").end(
68-
JSON.stringify({
69-
torrentsCount: swarms.size,
70-
peersCount,
71-
servers: serversStats,
72-
memory: process.memoryUsage(),
73-
peersCountPerInfoHash,
74-
}),
75-
);
76-
})
65+
for (const swarm of trackerSwarms) {
66+
peersCount += swarm.peersCount;
67+
68+
const infoHashHex = Buffer.from(
69+
swarm.infoHash,
70+
"binary",
71+
).toString("hex");
72+
73+
peersCountPerInfoHash[infoHashHex] = swarm.peersCount;
74+
peersCountPerInfoHash.totalPeers += swarm.peersCount;
75+
}
76+
77+
peersCountPerInfoHashPerTracker.push(peersCountPerInfoHash);
78+
}
79+
80+
response.cork(() => {
81+
response.writeHeader("Content-Type", "application/json").end(
82+
JSON.stringify({
83+
torrentsCount: swarms.length,
84+
peersCount,
85+
servers: serversStats,
86+
memory: process.memoryUsage(),
87+
peersCountPerInfoHashPerTracker,
88+
}),
89+
);
90+
});
91+
}
92+
},
93+
)
7794
.any("/*", (response: HttpResponse, request: HttpRequest) => {
7895
debugRequest(server, request);
7996

src/fast-tracker.ts

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { threadId } from "node:worker_threads";
1718
import Debug from "debug";
1819
import { Tracker, TrackerError } from "./tracker.js";
1920

20-
const debug = Debug("wt-tracker:fast-tracker");
21+
const debugSuffix = threadId ? `-${threadId}` : "";
22+
const debug = Debug(`wt-tracker:fast-tracker${debugSuffix}`);
2123
const debugEnabled = debug.enabled;
2224

2325
interface Swarm<ConnectionContext extends Record<string, unknown>> {
@@ -50,6 +52,19 @@ export class FastTracker<ConnectionContext extends Record<string, unknown>>
5052
return this.#swarms;
5153
}
5254

55+
public getSwarms() {
56+
const result = [];
57+
58+
for (const swarm of this.#swarms.values()) {
59+
result.push({
60+
infoHash: swarm.infoHash,
61+
peersCount: swarm.peers.length,
62+
});
63+
}
64+
65+
return Promise.resolve([result]);
66+
}
67+
5368
readonly #peers = new Map<string, PeerContext<ConnectionContext>>();
5469
public get peers() {
5570
return this.#peers;
@@ -390,10 +405,12 @@ export class FastTracker<ConnectionContext extends Record<string, unknown>>
390405
}
391406
}
392407

393-
debug(
394-
"announce: sent offers",
395-
countOffersToSend < 0 ? 0 : countOffersToSend,
396-
);
408+
if (debugEnabled) {
409+
debug(
410+
"announce: sent offers",
411+
countOffersToSend < 0 ? 0 : countOffersToSend,
412+
);
413+
}
397414
}
398415

399416
private processAnswer(json: UnknownObject): void {

src/socket-app.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,22 @@ export async function runSocketApp(
3838

3939
const servers: UWebSocketsTracker[] = [];
4040

41+
const getServersStats = async () => {
42+
return Promise.resolve(
43+
servers.map((server, index) => ({
44+
server: `${settings.servers[index].server?.host}:${settings.servers[index].server?.port}`,
45+
webSocketsCount: server.stats.webSocketsCount,
46+
})),
47+
);
48+
};
49+
4150
const serverPromises = settings.servers.map(async (serverSettings) => {
4251
const server = buildUwsTracker({
4352
tracker,
4453
serverSettings,
4554
websocketsAccess: settings.websocketsAccess,
4655
indexHtml,
47-
servers,
56+
getServersStats,
4857
});
4958
servers.push(server);
5059
await server.run();

src/tracker.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
*/
1616

1717
export interface Tracker<ConnectionContext> {
18-
readonly swarms: ReadonlyMap<string, { peers: readonly unknown[] }>;
19-
18+
getSwarms: () => Promise<{ infoHash: string; peersCount: number }[][]>;
2019
processMessage: (
2120
json: Record<string, unknown>,
2221
connection: ConnectionContext,

src/uws-tracker.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,17 @@ import {
3131
WebSocketsAccessSettings,
3232
WebSocketsSettings,
3333
} from "./settings.js";
34+
import { threadId } from "node:worker_threads";
3435

35-
const debugWebSockets = Debug("wt-tracker:uws-tracker");
36+
const debugSuffix = threadId ? `-${threadId}` : "";
37+
38+
const debugWebSockets = Debug(`wt-tracker:uws-tracker${debugSuffix}`);
3639
const debugWebSocketsEnabled = debugWebSockets.enabled;
3740

38-
const debugMessages = Debug("wt-tracker:uws-tracker-messages");
41+
const debugMessages = Debug(`wt-tracker:uws-tracker-messages${debugSuffix}`);
3942
const debugMessagesEnabled = debugMessages.enabled;
4043

41-
const debugRequests = Debug("wt-tracker:uws-tracker-requests");
44+
const debugRequests = Debug(`wt-tracker:uws-tracker-requests${debugSuffix}`);
4245
const debugRequestsEnabled = debugRequests.enabled;
4346

4447
const decoder = new StringDecoder();
@@ -61,7 +64,6 @@ export interface PartialUwsTrackerSettings {
6164

6265
export class UWebSocketsTracker {
6366
public readonly settings: UwsTrackerSettings;
64-
public readonly tracker: Readonly<Tracker<UwsConnectionContext>>;
6567

6668
private webSocketsCount = 0;
6769
private validateOrigin = false;
@@ -70,10 +72,9 @@ export class UWebSocketsTracker {
7072
readonly #app: TemplatedApp;
7173

7274
public constructor(
73-
tracker: Readonly<Tracker<UwsConnectionContext>>,
75+
public readonly tracker: Readonly<Tracker<UwsConnectionContext>>,
7476
settings: PartialUwsTrackerSettings,
7577
) {
76-
this.tracker = tracker;
7778
this.settings = {
7879
server: {
7980
port: 8000,
@@ -112,8 +113,9 @@ export class UWebSocketsTracker {
112113
return this.#app;
113114
}
114115

115-
public get stats(): { webSocketsCount: number } {
116+
public get stats() {
116117
return {
118+
threadId,
117119
webSocketsCount: this.webSocketsCount,
118120
};
119121
}

0 commit comments

Comments
 (0)