GwentAPI / gwentapi

The code for GwentAPI
https://gwentapi.com
BSD 3-Clause "New" or "Revised" License
47 stars 1 forks source link

Use human sanity-proof UUID #5

Closed Tri125 closed 7 years ago

Tri125 commented 7 years ago

v0/cards/ZDYyYWM4ODYtZjMwZi00OGIyLWI0MTctMWZlYzk5ZWJlMmU4

Is crazy long for no good reason. It's insanely long and that's without getting into the different resource available with cards. According to the db_setup script and the code, it's also stored as a string which takes a decent chunk of storage.

After a bit of research, it seems that some variant of a UUID with a minimum of 72 random bits should be:

  1. Sane
  2. Reasonable for our domain of application. We don't expect billions of cards with Gwent (Mtg have 16 505 cards so far). We can reduce the length and not mind about the collision probability.
Tri125 commented 7 years ago

With 72 bits without extra encoded information, that would give us the following base64 url safe result: /v0/cards/iRxRJ8RAbjKQ

cr0wst commented 7 years ago

Is there a specific reason you're using UUIDs for this? My understanding is they don't index well on relational databases and could impact lookup performance. I thought I read you were using MySQL but another issue reference MongoDB.

I don't have a lot of experience in no-sql databases, so maybe that's the reasoning. It seems like you'd almost want to keep a relational table with how your data is structured (just looking through your models) but that's a different issue entirely.

Tri125 commented 7 years ago

It used to be on MySQL but with Gwent constantly evolving it was difficult having to work again and again on the db design. MongoDB allows me to just drop in some json and then change the application code. It was also an importunity to learn MongoDB.

The data is a tiny bit relational but it only have 6 collections (tables) with the card collection having less than 300 entries so I believe the performance impact to be minimal.

The specific reason for using UUID is just to be able to uniquely identify a resource for the service. A previous version was using just the name like this: /cards/adrenaline_rush which is very fun to use but it have its flaws. The ID needs to be stable in order to not break any service (it's not very stable at the moment due to development but it's getting there once I rewrite the db script). A deck building website could use the API and store the ID in order to associate the card with the deck. What happens if a card is renamed? If a typo introduced itself and is later fix in a game patch? The ID would be invalid because it's tied to the name of the card.

To avoid that sort of things, I opted to use uuid (uuid4 to be specific) and I will gradually provide ways to query with different search criteria.

Due to an error #6 the UUID shown to the user is far longer than what it actually is. The actual stored value is 128 bits and the user should see the base64 representation of that. It's actually just stored as binary data, not as a mongoDB UUID. I think the only form of impact that it have is that it's stored at a random location because uuid4 is completely random (data locality problem). Something that is definitively worth looking at.

cr0wst commented 7 years ago

It makes sense to me that you're using something other than the name for an identifier. I guess I was under the assumption you were using MySQL and would have just suggested using incremented sequence numbers or index numbers.

Thanks for the clarification. I did find where you had mentioned being able to query via name. I had just got a basic Java wrapping library built, and that was the last piece I really needed. Looking forward to future updates!

Tri125 commented 7 years ago

Closing this as the initial issue was fixed.