I need help figuring out the best way to use firebase for my usecases. I'm making a twitter clone but unlike FireFeed my posts are mutable.
My database is structured like so:
Rooms, essentially a feed of posts you can subscribe to. Members of a room may write posts to that room:
- rooms/{roomId}/posts/{postId}/ -> a summary of a post with attributes like title, number of comments, likes, etc
- rooms/{roomId}/users/{userId}/ -> list of all the users subscribed to this room
- rooms/{roomId}/info/ -> room size, type, name, etc
Users, global list of all the users:
- users/{userId}/feed/{postId} -> an aggregate of all rooms/{roomId}/posts/ from all rooms a user is subscribed to
- users/{userId}/rooms/{roomId} -> list of all the rooms a user is subscribed to
Posts, global list of actual post content:
- posts/{postId}/comments/{commentId} -> nested comments
- posts/{postId}/users/{userId} -> users who want push notifications on this post
- posts/{postId}/info/ -> number of comments, likes, author, date posted, etc
- posts/{postId}/content/ -> actual content
Schools, lists of rooms:
- schools/{schoolId}/rooms/{roomName}/info -> list of of rooms in a school. Room names are unique within a school
- schools/{schoolId}/admins/{userId} -> list of admins that have different authorisation rules
Now, the first two use cases are fine. The confusion comes with how to go about making and editing references to posts. My use cases are:
Use case 0: User wants to create a room.
- Multi location update a room object to /rooms/ and appropriate room summary object to schools/{schoolId}/rooms/, and users/{userId}/rooms/.
Use case 1: User wants to subscribe to a room.
- Run a transaction on rooms/{roomId}/. Add {userId} to rooms/{roomId}/users/ and increment room size by 1.
- On transaction complete, take that snapshot and do a multi location update. Copy rooms/{roomId}/posts over to users/{userId}/feed, add {roomId} to user/{userId}/rooms/ and write new size to /schools/{schoolId}/rooms/{roomName}/info.
- If multiwrite fails then remove {userId} from rooms/{roomId}/users/.
Use case 2: User wants to make a post to a room.
- Retrieve list of users from rooms/{roomId}/users
- Multi location update all user feeds and global post table with post summaries and post object.
The problem with this is if another user joins this room right after our user retrieves the list of users, then he's not part of the multi-location update to receive this new post.
I face a similar conundrum when I'm trying to update the number of comments on a post. If a post has 15 comments, and 2 people add a new comment to this post simultaneously, the global post object will correctly update to 17 when done in a transaction, but depending on the order of the fan-outs after, everyone's post summary object might have 16 comments. The same is true for the size of a room when a user joins a room.
How should I go about this? Is there a way to better model my data, or is there a way to correctly do multi location updates during a transaction?