Просмотр исходного кода

[document-updater] increase scanStream COUNT for project notifications (#33833)

* increase scanStream COUNT for project notifications
* fix Bull queue.add delay option being ignored
* parse timestamp to number before adding to notification queue
* fix outdated comments in project_notifications script

GitOrigin-RevId: 98bb638228550b2f6f2de90280a06c47e022cf96
Kristina 4 месяцев назад
Родитель
Сommit
88eb599d4e
1 измененных файлов с 19 добавлено и 11 удалено
  1. 19 11
      services/document-updater/scripts/project_notifications.mts

+ 19 - 11
services/document-updater/scripts/project_notifications.mts

@@ -21,13 +21,13 @@ const argv = minimist(process.argv.slice(2), {
 
 
 if (argv.help) {
 if (argv.help) {
   console.log(`
   console.log(`
-project_notifications.ts - Queue project update notifications
+project_notifications.mts - Queue project update notifications
 
 
 This script scans Redis for projects that have pending notification timestamps and queues
 This script scans Redis for projects that have pending notification timestamps and queues
 them for notification. It's used to notify project collaborators when changes have been
 them for notification. It's used to notify project collaborators when changes have been
 made to a project. Only projects with collaborators are processed.
 made to a project. Only projects with collaborators are processed.
 
 
-Usage: project_notifications.ts [options]
+Usage: node scripts/project_notifications.mts [options]
 
 
 Options:
 Options:
   -n, --dry-run    Show what would be done without making changes
   -n, --dry-run    Show what would be done without making changes
@@ -35,10 +35,10 @@ Options:
 
 
 Examples:
 Examples:
   # Dry run to see what would be notified
   # Dry run to see what would be notified
-  project_notifications.ts --dry-run
+  node scripts/project_notifications.mts --dry-run
 
 
   # Actually queue the notifications
   # Actually queue the notifications
-  project_notifications.ts
+  node scripts/project_notifications.mts
 `)
 `)
   process.exit(0)
   process.exit(0)
 }
 }
@@ -97,7 +97,7 @@ async function main() {
   if (dryRun) {
   if (dryRun) {
     console.log('\n[DRY RUN] Projects that would be queued:')
     console.log('\n[DRY RUN] Projects that would be queued:')
     for (const { projectId, timestamp } of projects) {
     for (const { projectId, timestamp } of projects) {
-      const date = new Date(parseInt(timestamp))
+      const date = new Date(parseInt(timestamp, 10))
       console.log(
       console.log(
         `  ${projectId}: ${timestamp} (${date.toISOString()}) - would be queued`
         `  ${projectId}: ${timestamp} (${date.toISOString()}) - would be queued`
       )
       )
@@ -110,13 +110,12 @@ async function main() {
   console.log('Queue is ready.')
   console.log('Queue is ready.')
 
 
   for (const { projectId, timestamp } of projects) {
   for (const { projectId, timestamp } of projects) {
+    const numericTimestamp = parseInt(timestamp, 10)
     try {
     try {
       await projectNotificationQueue.add(
       await projectNotificationQueue.add(
-        { projectId, timestamp },
+        { projectId, timestamp: numericTimestamp },
         {
         {
           jobId: projectId,
           jobId: projectId,
-        },
-        {
           delay: 1000,
           delay: 1000,
         }
         }
       )
       )
@@ -124,7 +123,7 @@ async function main() {
       // Delete the timestamp key after scheduling (only if it still matches)
       // Delete the timestamp key after scheduling (only if it still matches)
       await deleteProjectNotificationTimestamp(projectId, timestamp)
       await deleteProjectNotificationTimestamp(projectId, timestamp)
 
 
-      const date = new Date(parseInt(timestamp))
+      const date = new Date(numericTimestamp)
       console.log(
       console.log(
         `  ${projectId}: ${timestamp} (${date.toISOString()}) - queued`
         `  ${projectId}: ${timestamp} (${date.toISOString()}) - queued`
       )
       )
@@ -155,7 +154,7 @@ type ProjectNotification = {
 
 
 /**
 /**
  * Check if a project has any collaborators (excluding owner)
  * Check if a project has any collaborators (excluding owner)
- * Uses Redis caching with 1 hour expiration to avoid repeated MongoDB queries
+ * Uses Redis caching with 1-2 hour randomized expiration to avoid repeated MongoDB queries
  */
  */
 async function projectHasCollaborators(projectId: string): Promise<boolean> {
 async function projectHasCollaborators(projectId: string): Promise<boolean> {
   // Check Redis cache first
   // Check Redis cache first
@@ -185,7 +184,7 @@ async function projectHasCollaborators(projectId: string): Promise<boolean> {
   const randomTTL = 3600 + Math.floor(Math.random() * 3600)
   const randomTTL = 3600 + Math.floor(Math.random() * 3600)
 
 
   if (hasCollaborators === null) {
   if (hasCollaborators === null) {
-    // Cache false result for non-existent projects
+    // Cache negative result (no collaborators or project not found)
     await redisClient.setex(cacheKey, randomTTL, '0')
     await redisClient.setex(cacheKey, randomTTL, '0')
     return false
     return false
   }
   }
@@ -212,6 +211,7 @@ async function getProjectsToNotify(): Promise<ProjectNotification[]> {
     // Scan for all ProjectNotificationTimestamp keys
     // Scan for all ProjectNotificationTimestamp keys
     const stream = node.scanStream({
     const stream = node.scanStream({
       match: docUpdaterKeys.projectNotificationTimestamp({ project_id: '*' }),
       match: docUpdaterKeys.projectNotificationTimestamp({ project_id: '*' }),
+      count: 1000,
     })
     })
 
 
     for await (const keys of stream) {
     for await (const keys of stream) {
@@ -246,6 +246,14 @@ async function getProjectsToNotify(): Promise<ProjectNotification[]> {
           continue
           continue
         }
         }
 
 
+        const numericTimestamp = parseInt(timestamp, 10)
+        if (Number.isNaN(numericTimestamp)) {
+          console.log(
+            `Skipping project ${projectId} - non-numeric timestamp: ${timestamp}`
+          )
+          continue
+        }
+
         projects.push({ projectId, timestamp })
         projects.push({ projectId, timestamp })
       }
       }
     }
     }