Proper Firebase host / amateur system design: should transactions be used?

I am working on an application that does something similar to the number of stars in the blog example given in the Firebase documentation, and I have a question about the design of the polling system and whether to use it.

In the example, the data for the message is as follows:

postid { // some data here about the post, author, id, etc, starCount : <an integer count of the stars>, stars : { <user who starred> : true, <user who starred> : true, // ... and so on, basically a list of all the users who starred the post } } 

Documents use a transaction to update the number of stars:

 private void onStarClicked(DatabaseReference postRef) { postRef.runTransaction(new Transaction.Handler() { @Override public Transaction.Result doTransaction(MutableData mutableData) { Post p = mutableData.getValue(Post.class); if (p == null) { return Transaction.success(mutableData); } if (p.stars.containsKey(getUid())) { // Unstar the post and remove self from stars p.starCount = p.starCount - 1; p.stars.remove(getUid()); } else { // Star the post and add self to stars p.starCount = p.starCount + 1; p.stars.put(getUid(), true); } // Set value and report transaction success mutableData.setValue(p); return Transaction.success(mutableData); } @Override public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) { // Transaction completed Log.d(TAG, "postTransaction:onComplete:" + databaseError); } }); } 

Due to the use of the transaction, both the starCount and stars tags seem to be part of the same object. What for? Because I want to use both transaction and self-confidence. Another option for providing automation is a multi-path update, but as noted here in the comments , you cannot use multi-path updates with transitions. You have access to mutableData (in this case post post) and what it is.

SO, if starCount and stars should be stored in the same place, I do not understand the point of starCount . Whenever you get a post object, it will include stars , a list of everyone who shot it. Why not remove starCount entirely and just get the size of the list of stars ? Is there anything not in this regard?

In this case, in the main / non- p.stars.put(getUid(), true); something will be something like p.stars.put(getUid(), true); and p.stars.remove(getUid()); . If I did this, I don’t see the need for a transaction, because I no longer have several users updating the counter object. I could use a transaction for the p.stars.put(getUid(), true); statement p.stars.put(getUid(), true); , but it seems unlikely to me that the same user who is trying to display / remove something from two different devices, and even if they did, it would not be a disaster as long as I can say.

So what am I missing here? Why use transactions here and what advantage does manual tracking of starCount add retain? I could see the performance benefits by storing the list of stars users elsewhere in the database, as shown in this example , but then the transaction would not work.

Any insight would be appreciated and thanks!

+5
source share
1 answer

In our efforts to create a single working example application with which to get documentation samples, we really could create an unreasonable (but functional) use for transactions.

I would recommend taking a look at my answer to this question for a more reasonable (but certainly complicated) way to make secure calculations using multi-window updates and server-side security rules.

In general, I would always recommend dividing the logic of voting into the logic of counting in such cases. Therefore, when a user votes for a message, you write a simple record to the database, which records their action:

 votesQueue <push id> <uid>: true 

And then you have a tiny script server (for example, a firebase queue employee ) that listens on this queue and aggregates the number of votes.

This approach is very common when using Firebase and makes things a lot easier. You can probably easily imagine how you would protect these two nodes ( votesQueue and voteTotals ), although I can assure you that the solution in the answer that I linked above gives me quite some maintenance headaches.

0
source

Source: https://habr.com/ru/post/1262319/


All Articles