Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create user and upload data on Firebase in one single transaction

I am making a web application which creates a user on Firebase using email and password firebase.auth().createUserUsingEmailAndPassowrd()

After the account is created, I immediately upload some data based on the forms values on the firebase database.

All works well, but sometimes, In worst case scenarios, the user is created but due to network issues the data is not uploaded. And the app is already redirected to a place where it needs that data and the whole app fails.

How can I make it certain that the user account is created only if the data I am trying to upload on database gets updated too.

Summary : Make sure that some data is uploaded along with user creation or the user doesn't get created at all.

like image 903
Prakhar Sharma Avatar asked Jan 05 '23 06:01

Prakhar Sharma


2 Answers

Because you're so afraid of worst case scenario (which is absolutely normal), here is one way to do it: Consider you have these fields: email, password, and address. The address field is the one you need to store in your database (with user uid, of course).

First you try to register the user, and like Faizy said, you use onCompleteListener like this

mAuth.createUserWithEmailAndPassword(email, password)
    .onCompleteListener(... {
        ... onComplete (... task) {
            if (task.isSuccessful()) {
                doInsertTheData();
            }
...

When task is successful, then you want to insert the data into database, which doInsertTheData() is created for

private void doInsertTheData() {
     // I believe you familiar with Firebase database inserting method, so I skip the long part
     FirebaseDatabase...setValue(address, new CompletionListener() {
         ... onComplete(FirebaseError firebaseError, ...) {
             if (firebaseError == null) {
                 // if your code reach here, its a happy ending
             } else {
                 // if it reach here, then you can remove the signed in user
                 // and tell the user that their registration is failed and should try again
                 FirebaseAuth.getInstance().getCurrentUser().delete();
             }

And there you go, as long as the database saving process failed, the user credential will be deleted

Note: I actually have another method in mind when I type this, but it's too complicated and I think this one is more easy to understand (I haven't try/use this though)

like image 130
koceeng Avatar answered Jan 13 '23 10:01

koceeng


firebaser here

There are no cross-feature transactions in Firebase at the moment. The common approach is to:

  • reduce the risk of cross-feature problems by carefully ordering your code
  • increase the resilience of your code against cross-feature failures

This means you decide which one if more important: that each existing user has a database node or that each database node points to an existing user. You seem to want to answer "both", but as said: that's not possible, you'll have to pick. In most scenarios I've seen developers will pick option 1: every Firebase Authentication user must have a node in the database.

In that case, you'll want to run the code that registers a user in the database before actually registering the user with Firebase Authentication. And since the user only gets their UID once they do register with Auth, you'll need some two-stepped process here. All quite nasty code that is bound to have problems. Which is why you'll see that most developers with an app in production care a lot less about this approach than you think.

Instead they rely on regular clean-up of their database. They run an administrative process every day or so that scans the database for users without a corresponding Firebase Authentication registration. This handles all kinds of edge cases with a fairly simple process, even edge cases not related to registration. You might even call this "eventual consistency": eventually the data in the database will match the registered users.

Final shout-out on your original question: you can drastically reduce the chance of a cross-feature failure by running the register-and-write-to-database code in a Cloud Function for Firebase. Using the Admin SDK in a Cloud Function makes this all nice and tidy. But while the chance of failures reduces a lot, it can still fail. So if you care about the cleanliness of your data, you'll still need the clean-up process.

like image 29
Frank van Puffelen Avatar answered Jan 13 '23 08:01

Frank van Puffelen