How to use Quenty's datastore system!

Hi developers!

Just wanted to let you guys know I’ve documented my datastore system, it’s currently in Nevermore, but several other people have been using it.

Let me know if you have any questions!

64 Likes

Definitely using this in my roblox game!

6 Likes

How would you say it is different from Kampfkarren’s own system?

5 Likes

Good question!

Features:

  • Minimize usage of the read and write datastore APIs so that API limits can be safely used
    • This means combining several datastore entries into one store. Instead of having 1 entry for gold, and 1 entry for money, this system combines the overall entries together into a table, while providing an API that is acceptable to use and acts as if you had entries for each one.
    • Furthermore, abstracting this API so that dependences aren’t required
  • Detect load failures and prevent further
  • Deal with the fundamental asyncronious component of DataStores
  • Abstract away a dependence upon faulty datastore API such that you can reasonable deal with errors
  • Ability to move from legacy system to this system
  • Proper merging on substores and systems (SUBSTORES!)
  • Proper write/change detection to minimize API calls
  • Granular control on exactly what happens, including load process

Summary:

  • Absolutely minimized read/write API uses (One on load, autosave time, 1 on leave)
  • Ability to utilize with existing save system or save systems (Datastore2 tends to require migration)
  • Substore API abstraction is clean
  • Promises (Good API)
  • Very granular control of behavior (more than datastore2)
  • Handles load failures in an elegant way.
7 Likes

As another note, I have a lot of respect for datastore2, but I evaluated it as a solution, and it didn’t meet my needs (legacy system, safety, control over feature, minimizing API usage), so I wrote this one.

5 Likes

This could actually work quite well for a lot of people (especially with your claim you’ve made migration easier). I tend to minimally rely on third-party code on Rōblox though.

3 Likes

I can recommend this. I switched my current project’s DataStore system to this (third time in a week) a few hours after he documented it, and it’s so much nicer. Doesn’t freeze up Studio for nearly as long as the previous system did and the API is just perfect and understandable.

2 Likes

You can drop freezing down to zero by calling the :DoNotSaveOnCloseInStudio() API when in studio. :smiley:

2 Likes

Going to migrate from Datastore2 to this just for the control, and the other bonuses are great too

(also the auto saving ValueObjects feature is epic)

2 Likes

Wow! This is really cool. I love the simplicity of the API compared to DataStore2. I can’t wait to use this in some upcoming projects I am working on! :smiley:

2 Likes

To Quenty, great work on the module as always!

Quenty nailed most of the pros of his system, just some notes from my point of view:

  • This system uses promises, something I regret not adding in the original version–they are excellent for this kind of work and I’ll be supporting them in the future with DataStore2 (because of backwards compatibility, they’ll be something like :GetAsync isntead of just :Get).
  • DataStore2 notoriously uses a very redundant system to store data. I haven’t been super public about this, but this is soon to change! DataStore2 will make it very easy to use standard data stores as opposed to the forced requirement to use the berezaa system. This will also help with not needing to migrate your data over.
  • I believe this is combined data stores by default, something that I regret very hard not doing and is one of the breaking changes in the coming major release of DataStore2.
  • This doesn’t appear to support serialization from my reading of the documentations, something DataStore2 has over it.

  • There doesn’t seem to be a backup system, unlike DataStore2’s one line backup API.

To Quenty:

I’m not sure what this means in the context of comparison to DataStore2, which doesn’t make any API calls once the data loads. It seems both do the same amount of calls when you describe it as:

9 Likes

Most of that is copied right from the documentation. He listed pros of his system in general, not all was in comparison to your system.

Both of you do fine jobs of handling API budget limits.

3 Likes

I have a quick question if I load a table and store it somewhere else will it be autosaved?

local data = {}

dataStore:Load("items", {sword = true, sword2 = true}):Then(function(items)
	data.items = items
end)

data.items.sword = nil

I’m assuming it does, but I’m asking to be safe

2 Likes

In this case, if you don’t write anything to the datastore, it won’t save it. So if you only load, the autosave won’t kick in. Also, if you request a flush to store, and nothing has changed, it won’t flush, or overwrite any data. So this helps with collisions on quick join/leave/rejoin.

Just to be clear, this was in relation to the berezza method. :stuck_out_tongue:

Uhh. It might in VERY certain situations, but, but don’t do this. This is a bad practice. I assume a general no-modification of data going out, although this was designed with my usecase in mind.

3 Likes

Edit

I’ve been experimenting and discovered why doing that wouldn’t work myself, I was just confused because I’m used to having a module that stores all PlayerData tables, but that isn’t necessary with this system

2 Likes

If I call dataStoreManager:GetDataStore(robloxPlayer) from multiple different scripts with the same player, will it return the same DataStore? Or would it return new instances of DataStore causing issues? Also, it seems that a DataStore has a self._maid on it. Can this maid be used in custom code? Or is this only for internal use?

2 Likes

Same datastore for the player datastore manager!

3 Likes

Thanks for the response. My only other question is how would I handle using the same maid for player data across multiple scripts? Is this possible?

Edit: Also as far as I can tell, all data is saved under the same key. Is there a way to detect load failure for the entire key without using :Catch on every single DataStore:Load() call?

Edit 2: Do I have to use the same PlayerDataStoreManager in all scripts somehow?

2 Likes

I see that this system doesn’t use the “berezaa method” of retrieving data from timestamps in OrderedDatastore. I’m really interested in migrating back to “standard” data stores because I dislike the double API calls and suspect it might be redudant. But I don’t want to risk the data losses. Any thoughts or feedback from other people using your system on the stability? Perhaps compared to the “berezaa method” and DataStore2?

There’s also no “retry” function in place when an API call fails. Most DataStore systems I’ve seen has this so I’m curious why that is? Does it happen so rarely that it’s not worth handling those cases?

2 Likes

I’ve had no issues with data loss using this, It’s very stable and easy to use. It autosaves at an interval of your choice and only saves data that has been stored. Meaning if for some reason your “Money” doesn’t load it will not attempt to save your Money causing some sort of overwrite. In other words if you don’t write something to the datastore then it won’t attempt to save it (as stated above). This uses Then/Catch promises to handle the API calls so if for some reason :Load() fails it will go to the “Catch” and you can handle the error however you please.

1 Like