@@ -94,40 +94,47 @@ export class WebhookController {
9494 axios . post ( new URL ( "blabsy" , process . env . ANCHR_URL ) . toString ( ) , req . body )
9595 }
9696
97- // Early duplicate check
98- if ( adapter . lockedIds . includes ( id ) ) {
97+ const mapping = Object . values ( adapter . mapping ) . find (
98+ ( m ) => m . schemaId === schemaId ,
99+ ) ;
100+ if ( ! mapping ) throw new Error ( ) ;
101+ const tableName = mapping . tableName + "s" ;
102+
103+ // For chats, skip the lock check and use timestamp comparison instead
104+ const isChatData = tableName === "chats" ;
105+
106+ if ( ! isChatData && adapter . lockedIds . includes ( id ) ) {
99107 console . log ( `Webhook skipped - ID ${ id } already locked` ) ;
100108 return res . status ( 200 ) . json ( { success : true , skipped : true } ) ;
101109 }
102110
103111 console . log ( `Processing webhook for ID: ${ id } ` ) ;
104-
105- // Lock the global ID immediately to prevent duplicates
106- adapter . addToLockedIds ( id ) ;
107112
108- const mapping = Object . values ( adapter . mapping ) . find (
109- ( m ) => m . schemaId === schemaId ,
110- ) ;
111- if ( ! mapping ) throw new Error ( ) ;
112- const tableName = mapping . tableName + "s" ;
113+ // Lock the global ID immediately to prevent duplicates (non-chat)
114+ if ( ! isChatData ) {
115+ adapter . addToLockedIds ( id ) ;
116+ }
113117
114118 const local = await adapter . fromGlobal ( { data, mapping } ) ;
115119
116- console . log ( "Webhook data received:" , {
117- globalId : id ,
118- tableName,
120+ console . log ( "Webhook data received:" , {
121+ globalId : id ,
122+ tableName,
119123 hasEname : ! ! local . data . ename ,
120- ename : local . data . ename
124+ ename : local . data . ename
121125 } ) ;
122-
126+
123127 // Get the local ID from the mapping database
124128 const localId = await adapter . mappingDb . getLocalId ( id ) ;
125129
126130 if ( localId ) {
127131 console . log ( `LOCAL, updating - ID: ${ id } , LocalID: ${ localId } ` ) ;
128- // Lock local ID early to prevent duplicate processing
129- adapter . addToLockedIds ( localId ) ;
130- await this . updateRecord ( tableName , localId , local . data ) ;
132+ if ( isChatData ) {
133+ await this . updateChatIfNewer ( localId , local . data ) ;
134+ } else {
135+ adapter . addToLockedIds ( localId ) ;
136+ await this . updateRecord ( tableName , localId , local . data ) ;
137+ }
131138 } else {
132139 console . log ( `NOT LOCAL, creating - ID: ${ id } ` ) ;
133140 await this . createRecord ( tableName , local . data , req . body . id ) ;
@@ -252,6 +259,33 @@ export class WebhookController {
252259 const mappedData = await this . mapDataToFirebase ( tableName , data ) ;
253260 await docRef . update ( mappedData ) ;
254261 }
262+
263+ private async updateChatIfNewer ( localId : string , data : any ) {
264+ const docRef = this . db . collection ( "chats" ) . doc ( localId ) ;
265+ const docSnapshot = await docRef . get ( ) ;
266+
267+ if ( ! docSnapshot . exists ) {
268+ console . warn ( `Chat document '${ localId } ' does not exist. Skipping update.` ) ;
269+ return ;
270+ }
271+
272+ const existing = docSnapshot . data ( ) ;
273+ const mappedData = this . mapChatData ( data , Timestamp . now ( ) ) ;
274+
275+ // Compare updatedAt timestamps - accept if incoming is more recent
276+ const existingUpdatedAt = existing ?. updatedAt ?. toMillis ?.( ) ?? 0 ;
277+ const incomingUpdatedAt = mappedData . updatedAt ?. toMillis ?.( ) ?? 0 ;
278+
279+ if ( incomingUpdatedAt < existingUpdatedAt ) {
280+ console . log ( `Chat ${ localId } webhook skipped - local data is more recent (local: ${ existingUpdatedAt } , incoming: ${ incomingUpdatedAt } )` ) ;
281+ return ;
282+ }
283+
284+ adapter . addToLockedIds ( localId ) ;
285+ await docRef . update ( mappedData ) ;
286+ console . log ( `Chat ${ localId } updated via webhook (timestamp check passed)` ) ;
287+ }
288+
255289 private mapDataToFirebase ( tableName : string , data : any ) : any {
256290 const now = Timestamp . now ( ) ;
257291 console . log ( "MAPPING DATA TO " , tableName ) ;
0 commit comments