Reputation: 187
Context: My application currently allows users to create an account, with a username. Upon clicking confirm
- to create an account, a check is ran on the username to verify that it does not exist as a document within the usernames
collection i.e this allows for only unique usernames within the application.
The usernames were added to a map when the view was created - prior to the user pressing the confirm
button (I understand that this is the underlying issue)
public static void getAllNonAvailableUsernames() {
FirebaseFirestore.getInstance()
.collection("usernames")
.get().addOnCompleteListener(task -> {
List<DocumentSnapshot> snapshots = task.getResult().getDocuments();
for (DocumentSnapshot snap : snapshots) {
usedUsernames.put(snap.getId(), snap.get("owner"));
}
});
}
A Problem arises when two users happen to choose the same username to register with. The last request is processed and overrides the owner
field within the document, allowing both users to have the same username :
I'm unsure how to go about solving this issue, since the retrieval of all the documents within the usernames
collection might not finish before the validation is occurs.
Upvotes: 1
Views: 2333
Reputation: 7870
If you must have unique usernames for your users, the only way to do this correctly is with a transaction. Within your transaction, read the specific username you're trying to register then:
The transaction guarantees that both operations happen atomically.
Note that Firestore transactions only work while online. If you attempt to run a transaction without a network connection it will fail after a few attempts. In this case you'll need to prompt your user to register while they have a network connection.
Upvotes: 1