Refactor active IP-server data handling in user traffic table
Publish telemt-api gateway Docker image / test (push) Successful in 25s
Publish telemt-api gateway Docker image / build-and-push (push) Successful in 2m30s

- Updated the data structure to store multiple servers associated with each user, enhancing the representation of active connections.
- Improved the logic for generating active IP-server rows, utilizing a map for better performance and organization.
- Modified the UI to display a list of servers for each user, improving clarity and usability in the user traffic table.
This commit is contained in:
Denozordec
2026-03-30 14:37:11 +07:00
parent bc15d4e2ca
commit f2683aab5e
+46 -30
View File
@@ -213,17 +213,19 @@
username: string;
ip: string;
country_code: string | null | undefined;
server: string;
servers: string[];
activeLabel: string;
};
let activeIpServerRows = $derived.by((): ActiveIpServerRow[] => {
const out: ActiveIpServerRow[] = [];
const seen = new Set<string>();
const map = new Map<
string,
{ row: Omit<ActiveIpServerRow, 'servers'>; serversSet: Set<string> }
>();
const maxUniqueIpRows = 80;
const maxOutRows = 2000;
for (const ur of uniqueIps?.slice(0, maxUniqueIpRows) ?? []) {
outer: for (const ur of uniqueIps?.slice(0, maxUniqueIpRows) ?? []) {
const username = ur.username ?? '';
if (!username) continue;
@@ -231,32 +233,41 @@
const ip = ipa.ip ?? '';
if (!ip) continue;
const servers = ipa.active_on_servers ?? [];
const servers = (ipa.active_on_servers ?? []).filter(Boolean);
if (servers.length === 0) continue;
const key = `${username}|${ip}`;
let item = map.get(key);
if (!item) {
if (map.size >= maxOutRows) break outer;
item = {
row: {
username,
ip,
country_code: ipa.country_code,
activeLabel: chipLabel(ipa)
},
serversSet: new Set<string>()
};
map.set(key, item);
}
for (const server of servers) {
if (!server) continue;
const key = `${username}|${ip}|${server}`;
if (seen.has(key)) continue;
seen.add(key);
out.push({
username,
ip,
country_code: ipa.country_code,
server,
activeLabel: chipLabel(ipa)
});
if (out.length >= maxOutRows) return out;
item.serversSet.add(server);
}
}
}
out.sort(
(a, b) =>
a.ip.localeCompare(b.ip) || a.server.localeCompare(b.server) || a.username.localeCompare(b.username)
);
const out: ActiveIpServerRow[] = [];
for (const { row, serversSet } of map.values()) {
out.push({
...row,
servers: [...serversSet].sort((a, b) => a.localeCompare(b))
});
}
out.sort((a, b) => a.ip.localeCompare(b.ip) || a.username.localeCompare(b.username));
return out;
});
</script>
@@ -443,7 +454,7 @@
<Table.Row>
<Table.Head>IP со страной</Table.Head>
<Table.Head>Клиент</Table.Head>
<Table.Head>Сервер</Table.Head>
<Table.Head>Серверы</Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
@@ -454,7 +465,7 @@
</Table.Cell>
</Table.Row>
{:else}
{#each activeIpServerRows as r (r.username + '|' + r.ip + '|' + r.server)}
{#each activeIpServerRows as r (r.username + '|' + r.ip)}
<Table.Row>
<Table.Cell class="font-mono text-sm">
{r.activeLabel}
@@ -468,12 +479,17 @@
</a>
</Table.Cell>
<Table.Cell>
<a
href="/servers/{encodeURIComponent(r.server)}"
class="text-primary hover:underline"
>
{r.server}
</a>
{#each r.servers as srv, idx (srv)}
<a
href="/servers/{encodeURIComponent(srv)}"
class="text-primary hover:underline"
>
{srv}
</a>
{#if idx < r.servers.length - 1}
<span class="text-muted-foreground">, </span>
{/if}
{/each}
</Table.Cell>
</Table.Row>
{/each}