Synchronous Writes in Firebase

This post is focused on the Firebase Admin Java API which we use to build services to support our app.

Firebase Realtime Database is a lovely key-value tree-structured database. To write a value in Firebase, you can simply do:

FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("example");
ref.write("Hello World");

The entire database is a tree, so here we store “Hello World” into the “example” child of the root.

A few obvious questions:

  • does that write block until it succeeds?
  • what if the database write fails?

This write method does NOT block. It is handled asynchronously on a separate thread.

Aside from encouraging developers to ignore failed writes, this has a few other issues:

  • what if I want to set a timeout on writes?
  • what if I want to write to ref1 and then write to ref2 upon success?
  • what if I want to record how long it takes to do my writes?

Luckily, the crafty API developers provide the ability to add an optional CompletionListener argument (there’s also a Task object if you do not provide the argument, which they intend to deprecate in favor of com.google.api.core.ApiFuture).

If you want a synchronous write which properly throws on error, you can use a latch and a reference:

public void synchronousWrite(DatabaseReference ref, Object value) {
    CountDownLatch latch = new CountDownLatch(1);
    AtomicReference<DatabaseError> error = new AtomicReference<>();
    ref.write(
        value,
        (error, ref2) => {
    	    error.set(databaseError);
            latch.countDown();
        }
    );

    latch.await(TIMEOUT_DURATION, TimeUnit.SECONDS);

    if (error.get() != null) {
        throw IllegalStateException("sadness", error.get().toException());
    }
}

There are some gotchas if you aren’t careful though. See this post.

I actually wrapped Firebase behind a module which wraps the read, update, and delete properly as well. Leave a message if you’re interested in the wrapper library and I can upload to GitHub :P


Name:

Comment: