import { domainSites, sitesOwnedBy } from "./store"; import { clearDomainLapse, lapsedDomainAccounts, startUnpaidGraceClocks } from "../billing/domain-addon"; import { releaseSiteDomain } from "./site"; /** Matches the 72 h stale-claim window that lets another site take an unverified domain over. */ const UNVERIFIED_CLAIM_MS = 72 * 60 * 60 * 1000; const BATCH = 20; const ACCOUNT_DOMAINS_PAGE = 100; /** Never fully verified: no verification timestamp, and not currently active either. */ const NEVER_VERIFIED = "(domain_verified_at IS NULL AND (domain_status IS NULL OR domain_status NOT LIKE 'active%'))"; /** Cron: unverified custom domain claims older than the claim window lose their Cloudflare hostname. */ async function expireUnverifiedClaims(now: number): Promise { const cutoff = now - UNVERIFIED_CLAIM_MS; const sites = (await domainSites(`${NEVER_VERIFIED} AND COALESCE(domain_claimed_at, updated_at) < ?`, cutoff)).slice( 0, BATCH, ); for (const site of sites) await releaseSiteDomain(site); } /** Cron: once a lapsed add-on's grace period ends, every custom domain of the account is unmapped and deleted. */ async function releaseLapsedAddons(now: number): Promise { for (const accountId of await lapsedDomainAccounts(now)) { const sites = (await sitesOwnedBy(accountId)) .filter((site) => site.custom_domain !== null) .slice(0, ACCOUNT_DOMAINS_PAGE); for (const site of sites) await releaseSiteDomain(site); if (sites.length < ACCOUNT_DOMAINS_PAGE) await clearDomainLapse(accountId); } } export async function sweepCustomDomains(now = Date.now()): Promise { await expireUnverifiedClaims(now); await startUnpaidGraceClocks(now); await releaseLapsedAddons(now); }