6

I have found some thread below which talk about this scenario.

However still struggling to find, if there are any recommended data structure design for this. I see a Multi-write library firebase-multi-write which says you probably don't need this in most cases.

But I think I do need this, my scenario is : 3 users

/users/A : {credit:20}

/users/B : {credit:3}

/users/C :  {credit:10}

And each user can steal credits from each other all at the same time.,

  • A steals from B credits look like {21, 2}
  • B steals from C credits look like {3, 9}
  • C steals from A credits look like {11, 20}

Now I need to update the credits for each user to maintain this consistency, so that each steal operation is atomic in nature.

What will be the best way to handle such scenario, while maintaining data integrity in Java?

Community
  • 1
  • 1
duskandawn
  • 646
  • 1
  • 10
  • 19
  • 1
    Your first linked thread talks about another approach (Event Sourcing - http://martinfowler.com/eaaDev/EventSourcing.html). You'd write a single event that captures all three stealing events and then when you needed to find the current credit balance you would load the initial state (probably 0 credits) and then playback the event history until you end up at the final state. Bonus points - you have a history of all "steals". Is there a reason this isn't acceptable? – Robert Horvick Jul 21 '15 at 13:17
  • Thanks, the scenario I mentioned was a simplified version of the workflow which I envision. This is a part of simple gaming app, where A steals form B, and at the next moment B steals it back, with the mix of C and D players. So its just too much calculations for a simple atomic update ?? – duskandawn Jul 21 '15 at 17:20
  • I don't know enough about your scenario to know if atomic operations will work or not - but what you are describing does not sound like an atomic operation to me. If A takes from B and then "at the next moment" B steals it back ... that's not atomic. That's two distinct operations that happened to occur near each other in time. – Robert Horvick Jul 22 '15 at 04:25
  • Indeed. These sound like distinct operations. Transactions would be sufficient for this use case. A [queue](https://github.com/firebase/firebase-queue) or event sourcing would handle atomic transactional changes best. Simple [multiple-path writes](https://www.firebase.com/blog/2015-09-24-atomic-writes-and-more.html) are now possible for simpler cases where the goal is simply to update all 3 paths at once. – Kato Dec 29 '15 at 22:57

1 Answers1

5

In setember/2015 firebase developers released new version.

With this release, you can now do this in a single atomic update to both locations:

Firebase ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
// Generate a new push ID for the new post

Firebase newPostRef = ref.child("posts").push();
String newPostKey = newPostRef.getKey();

// Create the data we want to update
Map newPost = new HashMap();
newPost.put("title", "New Post");
newPost.put("content", "Here is my new post!");

Map updatedUserData = new HashMap();
updatedUserData.put("users/posts/" + newPostKey, true);
updatedUserData.put("posts/" + newPostKey, newPost);

// Do a deep-path update
ref.updateChildren(updatedUserData, new Firebase.CompletionListener() {
   @Override
   public void onComplete(FirebaseError firebaseError, Firebase firebase) {
       if (firebaseError != null) {
           System.out.println("Error updating data: " + firebaseError.getMessage());
       }
   }
});
Diego Venâncio
  • 5,698
  • 2
  • 49
  • 68