Skip to content

Commit 0f7654d

Browse files
committed
fix(scripts): fix docs mismatch and N+1 query in ban-spam-accounts
- Fix comment: default pattern is @vapu.xyz, not @sharebot.net - Replace per-user stats loop with a single aggregated JOIN query
1 parent 8d31698 commit 0f7654d

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

scripts/ban-spam-accounts.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Options:
88
* --dry-run List matching accounts without deleting (default behavior)
99
* --execute Actually delete the accounts
10-
* --pattern Email domain/pattern to match (default: @sharebot.net)
10+
* --pattern Email domain/pattern to match (default: @vapu.xyz)
1111
*/
1212

1313
import postgres from 'postgres'
@@ -47,13 +47,24 @@ async function main() {
4747

4848
console.log(`Found ${spamUsers.length} matching accounts:\n`)
4949

50-
// Show account details with their workflow/execution counts
50+
const userIds = spamUsers.map((u: { id: string }) => u.id)
51+
52+
// Fetch workflow/workspace counts for all matching users in one query
53+
const statRows = await sql`
54+
SELECT
55+
u.id,
56+
COUNT(DISTINCT ws.id) AS workspace_count,
57+
COUNT(DISTINCT wf.id) AS workflow_count
58+
FROM "user" u
59+
LEFT JOIN workspace ws ON ws.owner_id = u.id
60+
LEFT JOIN workflow wf ON wf.user_id = u.id
61+
WHERE u.id = ANY(${userIds}::text[])
62+
GROUP BY u.id
63+
`
64+
const statsById = Object.fromEntries(statRows.map((r: { id: string }) => [r.id, r]))
65+
5166
for (const user of spamUsers) {
52-
const [stats] = await sql`
53-
SELECT
54-
(SELECT COUNT(*) FROM workflow WHERE user_id = ${user.id}) as workflow_count,
55-
(SELECT COUNT(*) FROM workspace WHERE owner_id = ${user.id}) as workspace_count
56-
`
67+
const stats = statsById[user.id] ?? { workspace_count: 0, workflow_count: 0 }
5768
console.log(` ${user.email}`)
5869
console.log(` ID: ${user.id} | Created: ${user.created_at}`)
5970
console.log(` Workspaces: ${stats.workspace_count} | Workflows: ${stats.workflow_count}`)
@@ -69,8 +80,6 @@ async function main() {
6980
// Execute deletion
7081
console.log(`\n⚠️ Deleting ${spamUsers.length} accounts...`)
7182

72-
const userIds = spamUsers.map((u: { id: string }) => u.id)
73-
7483
// Delete workspaces first to handle the billedAccountUserId no-action FK
7584
const deletedWorkspaces = await sql`
7685
DELETE FROM workspace WHERE owner_id = ANY(${userIds}::text[])

0 commit comments

Comments
 (0)