Search code examples
typescriptfirebasegoogle-cloud-firestoreangularfire

Deal with infinite loop when listeing to a collection and pushing changes to it


I'm using @angular/fire for this example but the question is valid for any firebase connection.

Getting the datas

 this.afs.collection<Message>('messages' , ref =>
            ref.where('chatId', '==', chatId)
 )
 .valueChanges()
 .subscribe(msgs => {

            this.removeUserFromUnseen(msgs)

      });

Appling changes to same collection from result

public removeUserFromUnseen(msgs: Message[]) {
    let batch = this.afs.firestore.batch();

    msgs.forEach(msg => {
        const mesagesRef = this.afs.collection<Message>('messages').doc(msg.id).ref;
        batch.update(mesagesRef , {notSeenBy : msg.notSeenBy.filter(userId => userId !== someId )});
    });

   return batch.commit();
}

Of course, this create an ifinite loop because I listen to changes on "messages" collection and then I apply changes to it. I dont want to .unsubscribe use .take or any similar so I dont think is a duplicated question.

How can I do this without creating this loop?

Can I subscribe only on new entries or changes on a specif property? Should I rethink desing of the database while it's still possible?

I'm using firestore


Solution

  • Don't use the results from Listeners to cause changes to the documents being watched! That is, by definition, an infinite loop.

    Firestore's Listeners are designed to support client applications: keeping the data displayed/available to the client current. It is assumed that changes are triggered by some form of user input - in which case, it's the user action that triggers the document change, not the update.

    IF what you're attempting to do is use browser compute power for generalized database processing...well... don't. That's what servers and cloud functions are for - and generally,listeners aren't useful for servers and cloud functions (Servers are more likely to use a listener, but still not likely a good idea. Cloud Functions are time-limited, so listeners are just not that useful).

    Finally, if you are storing data that needs to be updated in the same document as is being updated, re-think your architecture and separate into different documents or collections. If they must ("must") be in the same document, make the change in the same operation that was updating the documents in the first place.