| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- // @ts-check
- import minimist from 'minimist'
- import {
- db,
- ObjectId,
- READ_PREFERENCE_SECONDARY,
- } from '../app/src/infrastructure/mongodb.js'
- const OPTS = parseArgs()
- function parseArgs() {
- const args = minimist(process.argv.slice(2), {
- string: ['min-project-id', 'max-project-id'],
- boolean: ['help'],
- })
- if (args.help) {
- usage()
- process.exit(0)
- }
- return {
- minProjectId: args['min-project-id'] ?? null,
- maxProjectId: args['max-project-id'] ?? null,
- }
- }
- function usage() {
- console.log(`Usage: find_dangling_comments.mjs [OPTS]
- Options:
- --min-project-id Start scanning at this project id
- --max-project-id Stop scanning at this project id`)
- }
- async function main() {
- let projectsProcessed = 0
- let projectsFound = 0
- for await (const { projectId, threadIds } of fetchThreadIdsByProject()) {
- projectsProcessed += 1
- const danglingThreadIds = await findDanglingThreadIds(projectId, threadIds)
- if (danglingThreadIds.length > 0) {
- console.log(
- `Project ${projectId} has dangling threads: ${danglingThreadIds.join(', ')}`
- )
- projectsFound += 1
- }
- if (projectsProcessed % 100000 === 0) {
- console.log(
- `${projectsProcessed} projects processed - Last project: ${projectId}`
- )
- }
- }
- console.log(`${projectsFound} projects with dangling comments found`)
- }
- async function* fetchThreadIdsByProject() {
- const clauses = []
- clauses.push({
- deleted: { $ne: true },
- 'ranges.comments.0': { $exists: true },
- })
- if (OPTS.minProjectId != null) {
- clauses.push({ project_id: { $gte: new ObjectId(OPTS.minProjectId) } })
- }
- if (OPTS.maxProjectId != null) {
- clauses.push({ project_id: { $lte: new ObjectId(OPTS.maxProjectId) } })
- }
- const docs = db.docs.find(
- { $and: clauses },
- {
- sort: { project_id: 1 },
- projection: { project_id: 1, 'ranges.comments': 1 },
- readPreference: READ_PREFERENCE_SECONDARY,
- }
- )
- let projectId
- let threadIds = new Set()
- for await (const doc of docs) {
- if (projectId !== doc.project_id) {
- yield { projectId, threadIds }
- projectId = doc.project_id
- threadIds = new Set()
- }
- projectId = doc.project_id
- for (const comment of doc.ranges.comments) {
- threadIds.add(comment.op.t.toString())
- }
- }
- yield { projectId, threadIds }
- } /**
- * @param {string} projectId
- * @param {Set<string>} threadIds
- */
- async function findDanglingThreadIds(projectId, threadIds) {
- const rooms = await db.rooms.find(
- { project_id: projectId, thread_id: { $exists: true } },
- { readPreference: READ_PREFERENCE_SECONDARY }
- )
- const existingThreadIds = new Set()
- for await (const room of rooms) {
- existingThreadIds.add(room.thread_id.toString())
- }
- const danglingThreadIds = []
- for (const threadId of threadIds) {
- if (!existingThreadIds.has(threadId)) {
- danglingThreadIds.push(threadId)
- }
- }
- return danglingThreadIds
- }
- try {
- await main()
- process.exit(0)
- } catch (err) {
- console.error(err)
- process.exit(1)
- }
|