()
| 922 | } |
| 923 | |
| 924 | async crawlCatalogDomains(): Promise<{ checked: number; found: number }> { |
| 925 | if (this.catalogCrawling || this.crawling) { |
| 926 | log.debug('Crawl already in progress, skipping catalog crawl'); |
| 927 | return { checked: 0, found: 0 }; |
| 928 | } |
| 929 | |
| 930 | this.catalogCrawling = true; |
| 931 | const BATCH_SIZE = 100; |
| 932 | const CONCURRENCY = 20; |
| 933 | |
| 934 | try { |
| 935 | // Pull domains from queue, oldest requests first, respecting backoff |
| 936 | const rows = await query<{ identifier_type: string; identifier_value: string }>( |
| 937 | `SELECT identifier_type, identifier_value |
| 938 | FROM catalog_crawl_queue |
| 939 | WHERE identifier_type = 'domain' |
| 940 | AND next_crawl_after <= NOW() |
| 941 | AND found_adagents = FALSE |
| 942 | ORDER BY crawl_requested_at ASC |
| 943 | LIMIT $1`, |
| 944 | [BATCH_SIZE] |
| 945 | ); |
| 946 | |
| 947 | if (rows.rows.length === 0) { |
| 948 | this.catalogCrawling = false; |
| 949 | return { checked: 0, found: 0 }; |
| 950 | } |
| 951 | |
| 952 | log.info({ count: rows.rows.length }, 'Catalog domain crawl batch'); |
| 953 | |
| 954 | let found = 0; |
| 955 | const domains = rows.rows.map(r => r.identifier_value); |
| 956 | |
| 957 | // Process with concurrency limit |
| 958 | const results = await this.processWithConcurrency( |
| 959 | domains, |
| 960 | CONCURRENCY, |
| 961 | async (domain) => { |
| 962 | try { |
| 963 | const validation = await this.adAgentsManager.validateDomain(domain); |
| 964 | return { domain, valid: validation.valid && !!validation.raw_data?.authorized_agents }; |
| 965 | } catch { |
| 966 | return { domain, valid: false }; |
| 967 | } |
| 968 | } |
| 969 | ); |
| 970 | |
| 971 | for (const { domain, valid } of results) { |
| 972 | if (valid) { |
| 973 | found++; |
| 974 | // Run full single-domain crawl to record agents/properties |
| 975 | try { |
| 976 | await this.crawlSingleDomainForCatalog(domain); |
| 977 | } catch (err) { |
| 978 | log.error({ domain, err }, 'Catalog domain crawl failed for domain'); |
| 979 | } |
| 980 | |
| 981 | // Mark as found in queue |
no test coverage detected