(
preCrawlAgents: Map<string, { domains: Set<string> }>,
profiles: Map<string, ProfileUpsertInput>
)
| 683 | } |
| 684 | |
| 685 | private async produceEventsFromDiff( |
| 686 | preCrawlAgents: Map<string, { domains: Set<string> }>, |
| 687 | profiles: Map<string, ProfileUpsertInput> |
| 688 | ): Promise<void> { |
| 689 | if (!this.eventsDb) return; |
| 690 | |
| 691 | const events: WriteEventInput[] = []; |
| 692 | const postCrawlAgents = await this.snapshotAgentState(); |
| 693 | |
| 694 | // Detect new agents — include full profile in the event so RegistrySync |
| 695 | // clients get a complete agent without waiting for next bootstrap |
| 696 | for (const [url] of postCrawlAgents) { |
| 697 | if (!preCrawlAgents.has(url)) { |
| 698 | const profile = profiles.get(url); |
| 699 | events.push({ |
| 700 | event_type: 'agent.discovered', |
| 701 | entity_type: 'agent', |
| 702 | entity_id: url, |
| 703 | payload: { |
| 704 | agent_url: url, |
| 705 | ...(profile ? { |
| 706 | channels: profile.channels, |
| 707 | property_types: profile.property_types, |
| 708 | markets: profile.markets, |
| 709 | categories: profile.categories, |
| 710 | tags: profile.tags, |
| 711 | delivery_types: profile.delivery_types, |
| 712 | property_count: profile.property_count, |
| 713 | publisher_count: profile.publisher_count, |
| 714 | has_tmp: profile.has_tmp, |
| 715 | } : {}), |
| 716 | }, |
| 717 | actor: 'pipeline:crawler', |
| 718 | }); |
| 719 | } |
| 720 | } |
| 721 | |
| 722 | // Detect removed agents (global aggregation: gone from ALL publishers) |
| 723 | for (const [url] of preCrawlAgents) { |
| 724 | if (!postCrawlAgents.has(url)) { |
| 725 | events.push({ |
| 726 | event_type: 'agent.removed', |
| 727 | entity_type: 'agent', |
| 728 | entity_id: url, |
| 729 | payload: { agent_url: url }, |
| 730 | actor: 'pipeline:crawler', |
| 731 | }); |
| 732 | } |
| 733 | } |
| 734 | |
| 735 | // Detect authorization changes per agent |
| 736 | for (const [url, postState] of postCrawlAgents) { |
| 737 | const preState = preCrawlAgents.get(url); |
| 738 | const preDomains = preState?.domains ?? new Set<string>(); |
| 739 | |
| 740 | // New authorizations |
| 741 | for (const domain of postState.domains) { |
| 742 | if (!preDomains.has(domain)) { |
no test coverage detected