import { reregisterEmailDomain } from '@documenso/ee/server-only/lib/reregister-email-domain'; import { verifyEmailDomain } from '@documenso/ee/server-only/lib/verify-email-domain'; import { prisma } from '@documenso/prisma'; import { DateTime } from 'luxon'; import type { JobRunIO } from '../../client/_internal/job'; import type { TSyncEmailDomainsJobDefinition } from './sync-email-domains'; const BATCH_SIZE = 10; const AUTO_REREGISTER_AFTER_HOURS = 48; export const run = async ({ io }: { payload: TSyncEmailDomainsJobDefinition; io: JobRunIO }) => { const pendingDomains = await prisma.emailDomain.findMany({ where: { status: 'PENDING', }, select: { id: true, domain: true, createdAt: true, lastVerifiedAt: true, }, orderBy: { lastVerifiedAt: { sort: 'asc', nulls: 'first' }, }, }); if (pendingDomains.length === 0) { io.logger.info('No pending email domains to sync'); return; } io.logger.info(`Found ${pendingDomains.length} pending email domains to sync`); let verifiedCount = 0; let reregisteredCount = 0; let errorCount = 0; const reregisterCutoff = DateTime.now().minus({ hours: AUTO_REREGISTER_AFTER_HOURS }).toJSDate(); for (let i = 0; i < pendingDomains.length; i += BATCH_SIZE) { const batch = pendingDomains.slice(i, i + BATCH_SIZE); const results = await Promise.allSettled( batch.map(async (domain) => { const shouldReregister = domain.createdAt < reregisterCutoff; const { isVerified } = await verifyEmailDomain(domain.id); if (isVerified) { io.logger.info(`Domain "${domain.domain}" is verified`); return 'verified' as const; } if (shouldReregister) { io.logger.info( `Domain "${domain.domain}" has been pending since ${domain.createdAt.toISOString()}, attempting re-registration`, ); await reregisterEmailDomain({ emailDomainId: domain.id }); return 'reregistered' as const; } return 'pending' as const; }), ); for (const result of results) { if (result.status === 'rejected') { errorCount++; io.logger.error(`Failed to process email domain: ${String(result.reason)}`); } else if (result.value === 'verified') { verifiedCount++; } else if (result.value === 'reregistered') { reregisteredCount++; } } // Small delay between batches to respect SES API rate limits. if (i + BATCH_SIZE < pendingDomains.length) { await new Promise((resolve) => { setTimeout(resolve, 1000); }); } } io.logger.info( `Sync complete: ${verifiedCount} verified, ${reregisteredCount} re-registered, ${errorCount} errors out of ${pendingDomains.length} pending domains`, ); };