Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create RealWorld data model in Redis #1

Open
james-s-tayler opened this issue Jul 15, 2021 · 1 comment
Open

Create RealWorld data model in Redis #1

james-s-tayler opened this issue Jul 15, 2021 · 1 comment

Comments

@james-s-tayler
Copy link
Owner

james-s-tayler commented Jul 15, 2021

This is RealWorld backend API spec: https://github.com/gothinkster/realworld/tree/master/api

Side quest: would be fun to write a Turbo frontend for this!
Side quest 2: would be really interesting to try a GraphQL backend https://leapgraph.com/graphql-with-redis

@james-s-tayler
Copy link
Owner Author

james-s-tayler commented Jul 15, 2021

User

"user": {
    "email": "[email protected]",
    "token": "jwt.token.here",
    "username": "jake",
    "bio": "I work at statefarm",
    "image": null
  }

I think can store two separate HASH keys for this:

{username}:user:credentials
{username}:user:profile
  • k, so after trying this it's not going to work. Reasons being LoginRequest object only has email and password, so I need to be able to perform a lookup based on email. Additionally, I want to have all data for a given user persisted to the same hashslot, so I need to use a hash tag that won't change. Both email, and username can change. It is possible to rename keys, but the implications are 1) doing so performs and implicit DEL operation, so latency can be high on keys with very large values, and 2) keys can only be renamed reliably when they reside in the same hashslot to begin with.
  • In light of the above I'm thinking that generating a stable user_id is necessary and that should be used as the hash tag. Then it needs to be possible to look up the user_id via email.
  • It might be an interesting idea to store a bidirectional mapping via a sorted set as outlined here https://stackoverflow.com/questions/25858310/how-to-create-a-bidirectional-hash-map-in-redis
  • Official docs delve into building secondary indexes https://redis.io/topics/indexes

since profile is public, wouldn't want the app to be getting back the credentials also when some user is just loading the publicly available profile info.

Profile

"profile": {
    "username": "jake",
    "bio": "I work at statefarm",
    "image": "https://static.productionready.io/images/smiley-cyrus.jpg",
    "following": false
  }

Profile seems to return user:{username}:profile data, in addition to if you're following that user or not.

List of followers/following can be recorded as a SET under
{username}:user:following
{username}:user:followed_by

You can then query for SET membership to figure out if you're already following a user or not

Article

"article": {
    "slug": "how-to-train-your-dragon",
    "title": "How to train your dragon",
    "description": "Ever wonder how?",
    "body": "It takes a Jacobian",
    "tagList": ["dragons", "training"],
    "createdAt": "2016-02-18T03:22:56.637Z",
    "updatedAt": "2016-02-18T03:48:35.824Z",
    "favorited": false,
    "favoritesCount": 0,
    "author": {
      "username": "jake",
      "bio": "I work at statefarm",
      "image": "https://i.stack.imgur.com/xHWG8.jpg",
      "following": false
}

I think article can be stored by the following keys:

{username}:article:[slug] - can store title, body, created at, updated at, favorites_count as a HASH
{username}:article:[slug]:tags - store a SET (or LIST?) of tags for the given article
{username}:user:favorite:articles - store a SET (or LIST?) of article keys the given user has favorited
global:article:tags:[tag] - store a SET (or LIST?) of each article key with the given tag
global:article:feed - store a LIST of article keys of each article published

Suppose you could write events too like ArticlePublishedEvent, and ArticleEditedEvent, and ArticleFavoritedEvent, and AuthorFollowedEvent etc that could then be processed to handle the logic of say incr the favorited count, and add the article to the favorites list etc in the case of ArticleFavoritedEvent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant