mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-30 09:45:00 +03:00
perf(inbounds): batch client identities for stats enrichment (#6929)
backfillClientStats loaded every column of every client once per inbound, although enrichment only reads UUID, email and subscription ID. Each inbound list read (panel list, the master's node traffic poll, Xray config builds, bots) repeated that wide join per inbound. Identities now come from one narrow clients/client_inbounds projection per 400 inbounds, honouring the supplied transaction; stats output, sibling-traffic append order and the #6436 clients-table source of truth are unchanged. Closes #6926
This commit is contained in:
@@ -20,11 +20,9 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// setupScaleDB initializes the DB for a scale benchmark on either Postgres
|
||||
// (XUI_DB_TYPE=postgres + XUI_DB_DSN) or SQLite (XUI_SCALE_TEST=1, temp file;
|
||||
// XUI_SCALE_DB_PATH persists the DB for manual smoke runs), and registers
|
||||
// cleanup. Skips the test when neither backend is configured.
|
||||
func setupScaleDB(t *testing.T) {
|
||||
// setupScaleDB opens package-isolated PostgreSQL or opt-in SQLite (XUI_SCALE_TEST); otherwise it skips.
|
||||
// XUI_SCALE_DB_PATH preserves SQLite for manual smoke runs instead of temporary-file cleanup.
|
||||
func setupScaleDB(t testing.TB) {
|
||||
t.Helper()
|
||||
xuilogger.InitLogger(logging.ERROR)
|
||||
|
||||
@@ -82,11 +80,9 @@ type scaleDataset struct {
|
||||
perInbound [][]model.Client
|
||||
}
|
||||
|
||||
// seedScaleDataset seeds n healthy clients (future expiry, unfilled quota)
|
||||
// spread across numInbounds inbounds, writing inbounds, clients,
|
||||
// client_inbounds and client_traffics directly in one transaction — orders of
|
||||
// magnitude faster than SyncInbound and one fsync instead of thousands.
|
||||
func seedScaleDataset(t *testing.T, n, numInbounds int) scaleDataset {
|
||||
// seedScaleDataset writes healthy-client fixture tables directly in one transaction.
|
||||
// Skipping SyncInbound keeps per-client reconciliation out of benchmark setup.
|
||||
func seedScaleDataset(t testing.TB, n, numInbounds int) scaleDataset {
|
||||
t.Helper()
|
||||
db := database.GetDB()
|
||||
resetScaleTables(t, db, "inbounds", "clients", "client_inbounds", "client_traffics")
|
||||
@@ -187,10 +183,9 @@ func sampleEmails(emails []string, k int) []string {
|
||||
return out
|
||||
}
|
||||
|
||||
// resetScaleTables empties the given tables between sub-sizes. Postgres uses a
|
||||
// single TRUNCATE ... CASCADE; SQLite deletes per table and clears the
|
||||
// autoincrement counters so ids restart like RESTART IDENTITY.
|
||||
func resetScaleTables(t *testing.T, db *gorm.DB, tables ...string) {
|
||||
// resetScaleTables uses PostgreSQL TRUNCATE ... CASCADE with identity restart.
|
||||
// SQLite deletes table by table, then clears its autoincrement counters.
|
||||
func resetScaleTables(t testing.TB, db *gorm.DB, tables ...string) {
|
||||
t.Helper()
|
||||
if config.GetDBKind() == "postgres" {
|
||||
stmt := "TRUNCATE TABLE " + strings.Join(tables, ", ") + " RESTART IDENTITY CASCADE"
|
||||
|
||||
Reference in New Issue
Block a user