This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

semble / src / modules / atproto / application / useCases / ProcessCollectionLinkRemovalFirehoseEventUseCase.ts
5.6 kB 150 lines
1import { Result, ok, err } from 'src/shared/core/Result'; 2import { UseCase } from 'src/shared/core/UseCase'; 3import { AppError } from 'src/shared/core/AppError'; 4import { IAtUriResolutionService } from '../../../cards/domain/services/IAtUriResolutionService'; 5import { ATUri } from '../../domain/ATUri'; 6import { Record as CollectionLinkRemovalRecord } from '../../infrastructure/lexicon/types/network/cosmik/collectionLinkRemoval'; 7import { 8 UpdateUrlCardAssociationsUseCase, 9 OperationContext, 10} from '../../../cards/application/useCases/commands/UpdateUrlCardAssociationsUseCase'; 11 12export interface ProcessCollectionLinkRemovalFirehoseEventDTO { 13 atUri: string; 14 cid: string | null; 15 eventType: 'create' | 'update' | 'delete'; 16 record?: CollectionLinkRemovalRecord; 17} 18 19const ENABLE_FIREHOSE_LOGGING = true; 20 21export class ProcessCollectionLinkRemovalFirehoseEventUseCase 22 implements UseCase<ProcessCollectionLinkRemovalFirehoseEventDTO, Result<void>> 23{ 24 constructor( 25 private atUriResolutionService: IAtUriResolutionService, 26 private updateUrlCardAssociationsUseCase: UpdateUrlCardAssociationsUseCase, 27 ) {} 28 29 async execute( 30 request: ProcessCollectionLinkRemovalFirehoseEventDTO, 31 ): Promise<Result<void>> { 32 try { 33 if (ENABLE_FIREHOSE_LOGGING) { 34 console.log( 35 `[FirehoseWorker] Processing collection link removal event: ${request.atUri} (${request.eventType})`, 36 ); 37 } 38 39 switch (request.eventType) { 40 case 'create': 41 return await this.handleCollectionLinkRemovalCreate(request); 42 case 'delete': 43 // For now, we don't handle deletion events for collectionLinkRemoval 44 if (ENABLE_FIREHOSE_LOGGING) { 45 console.log( 46 `[FirehoseWorker] Collection link removal delete event (not handled): ${request.atUri}`, 47 ); 48 } 49 break; 50 case 'update': 51 // Collection link removals don't typically have update operations 52 if (ENABLE_FIREHOSE_LOGGING) { 53 console.log( 54 `[FirehoseWorker] Collection link removal update event (unusual): ${request.atUri}`, 55 ); 56 } 57 break; 58 } 59 60 return ok(undefined); 61 } catch (error) { 62 return err(AppError.UnexpectedError.create(error)); 63 } 64 } 65 66 private async handleCollectionLinkRemovalCreate( 67 request: ProcessCollectionLinkRemovalFirehoseEventDTO, 68 ): Promise<Result<void>> { 69 if (!request.record || !request.cid) { 70 if (ENABLE_FIREHOSE_LOGGING) { 71 console.warn( 72 `[FirehoseWorker] Collection link removal create event missing record or cid, skipping: ${request.atUri}`, 73 ); 74 } 75 return ok(undefined); 76 } 77 78 try { 79 // Parse AT URI to extract curator DID (the person who published the removal) 80 const atUriResult = ATUri.create(request.atUri); 81 if (atUriResult.isErr()) { 82 if (ENABLE_FIREHOSE_LOGGING) { 83 console.warn( 84 `[FirehoseWorker] Invalid AT URI format: ${request.atUri} - ${atUriResult.error.message}`, 85 ); 86 } 87 return ok(undefined); 88 } 89 const removerDid = atUriResult.value.did.value; 90 91 // Resolve the collection link that's being removed 92 const collectionLinkUri = request.record.removedLink.uri; 93 const linkInfoResult = 94 await this.atUriResolutionService.resolveCollectionLinkId( 95 collectionLinkUri, 96 ); 97 98 if (linkInfoResult.isErr()) { 99 if (ENABLE_FIREHOSE_LOGGING) { 100 console.warn( 101 `[FirehoseWorker] Failed to resolve collection link - remover: ${removerDid}, collectionLinkUri: ${collectionLinkUri}, removalUri: ${request.atUri}`, 102 ); 103 } 104 return ok(undefined); 105 } 106 107 if (!linkInfoResult.value) { 108 if (ENABLE_FIREHOSE_LOGGING) { 109 console.log( 110 `[FirehoseWorker] Collection link not found in our system (may have already been removed) - remover: ${removerDid}, collectionLinkUri: ${collectionLinkUri}, removalUri: ${request.atUri}`, 111 ); 112 } 113 return ok(undefined); 114 } 115 116 const { cardId, collectionId } = linkInfoResult.value; 117 118 // Remove the card from the collection using the context flag to skip publishing 119 const result = await this.updateUrlCardAssociationsUseCase.execute({ 120 cardId: cardId.getStringValue(), 121 curatorId: removerDid, 122 removeFromCollections: [collectionId.getStringValue()], 123 context: OperationContext.FIREHOSE_EVENT, // This tells the use case to skip publishing 124 }); 125 126 if (result.isErr()) { 127 if (ENABLE_FIREHOSE_LOGGING) { 128 console.warn( 129 `[FirehoseWorker] Failed to remove card from collection - remover: ${removerDid}, cardId: ${cardId.getStringValue()}, collectionId: ${collectionId.getStringValue()}, removalUri: ${request.atUri}, error: ${result.error.message}`, 130 ); 131 } 132 return ok(undefined); 133 } 134 135 if (ENABLE_FIREHOSE_LOGGING) { 136 console.log( 137 `[FirehoseWorker] Successfully removed card from collection via removal record - remover: ${removerDid}, cardId: ${cardId.getStringValue()}, collectionId: ${collectionId.getStringValue()}, removalUri: ${request.atUri}`, 138 ); 139 } 140 return ok(undefined); 141 } catch (error) { 142 if (ENABLE_FIREHOSE_LOGGING) { 143 console.error( 144 `[FirehoseWorker] Error processing collection link removal create event - uri: ${request.atUri}, error: ${error}`, 145 ); 146 } 147 return ok(undefined); // Don't fail the firehose processing 148 } 149 } 150}