Files
web_sport/apps/api/src/modules/search/search-index.subscriber.ts
T

53 lines
1.8 KiB
TypeScript

import { Injectable, Logger, type OnModuleInit } from '@nestjs/common';
import { DOMAIN_EVENTS } from '@/infrastructure/events/domain-event';
import { EventBusService } from '@/infrastructure/events/event-bus.service';
import { SearchIndexerService } from './search-indexer.service';
/**
* Keeps the index in step with the catalog, by subscription rather than by call.
*
* This is the direction the dependency has to run: SearchModule knows about
* products, products knows nothing about search. When this module is extracted,
* this file is the only thing that changes — an in-process subscription becomes
* a queue consumer, and the producer never learns the difference.
*
* Failures are logged, not rethrown. A search index that missed one update is a
* degraded search; an exception escaping here would take down the write that
* triggered it, which is a far worse trade.
*/
@Injectable()
export class SearchIndexSubscriber implements OnModuleInit {
private readonly logger = new Logger(SearchIndexSubscriber.name);
constructor(
private readonly events: EventBusService,
private readonly indexer: SearchIndexerService,
) {}
onModuleInit(): void {
for (const event of [
DOMAIN_EVENTS.PRODUCT_UPDATED,
DOMAIN_EVENTS.PRODUCT_PUBLISHED,
DOMAIN_EVENTS.PRODUCT_ARCHIVED,
]) {
this.events.on<{ productId: string }>(event).subscribe((message) => {
void this.reindex(message.payload.productId, event);
});
}
}
private async reindex(productId: string, event: string): Promise<void> {
try {
await this.indexer.reindexProduct(productId);
} catch (error) {
this.logger.error(
`Reindex failed for ${productId} after ${event}: ${
error instanceof Error ? error.message : String(error)
}`,
);
}
}
}