DataSave+ - Discontinued look after v2

This module is discontinued, don’t use it as of the moment.

6 Likes

Some temporary documentation, didn’t edit the post because that’s gonna be in the github anyways.

DataSavePlus functions:

.GetProfileStore(profileStoreName, template)

This function will create a profileStore for you to use. This should only be called in a “main” script.


.WaitForProfileStore(profileStoreName)

This function will yield until a :GetProfileStore() is called. On which it will return the profile store requested. This is so that you have the same profile template on all scripts only changing it in one.


ProfileStore’ functions:

:Get(player)

This will get a profile from a datastore or caching for you. If you’re using multiple scripts and messing with the profile in multiple scripts, the next two functions are more appropriate. This one, should be only called once in the same server.


:WaitForProfile(player)

This will yield until a profile for the same player exists, or until a player has left. You still have to do “if profile then” here.


:FindFirstProfile(player)

This will return the profile to a player, if there’s one, if there isn’t, it will return nil. Does NOT yield.


Profile functions:

:Reconcile()

Reconcile unlike profileService, will REMOVE any remaining data from your profile. By default, it will auto-create the any data that isn’t there. For example, if the data in the datastore doesn’t have a Cash value, then it will make one for you, reconcile will remove any values that shoudn’t be there, ones that aren’t in the Template. Useful for converting data.


:Save()

This should be used for purchases for example. Where you wanna make sure the purchase details were saved. It returns success and error info as well.

Keep in mind you shouldn’t be doing auto-saving yourself. Session locking REQUIRES auto-saving to work anyway. :Save() should be only used in cases you wanna make sure certain data is saved.

:Save() will also delay the auto-saving.


A profile will also keep the data, of course, that you wanna save. In this case, it will be inside the profile, as Data, an example would be:

So wouldn’t that just render it the same as ProfileService? I don’t see the point in making another datastore module when there are already two very reliable ones and this will be made obsolete when Datastore 1.1 releases.

1 Like

Yeah, it was just my solution. It still works pretty well. One thing, it does require the player instance. Making it locked to a player. But, profileService was always more for player data anyway, so eh. It is EASIER to use than profile service since it has the profilestore wait for, functions, and the profiles are all inside the module anyway. You don’t need to create a profile service handler just to keep that data.

One thing, even though DataStore 1.1 will help with the backups thing, and will be preferred by some, the orderedBackups method keeps all backups. Meaning that if someone had data loss, older backups woudn’t be deleted. Right now, and probably forever, DataStore 1.1 will delete it’s backups after 30 days. Which for some developers isn’t enough. I had a talk to someone which said “They took 6 months to answer my data loss case.” and, so yeah.

I kind of just released it to see if anybody can help me look through code while improving it. Else I would have probably just stopped messing with this. I wanna make this better not only for myself.

So, if somebody is starting out with datastores and wants a reliable enough system with both these tecnics involved, this should help.

Can anybody test if Repro To Roblox works on this? I’m too poor right now to test it lol.

Right, but your backups are just second datastore scopes. Datastore 1.1’s backups are actually in Roblox’s internal database, which is ultimately preferable for preventing data loss. I don’t see how anyone could prefer this method with Roblox-endorsed backups being released.

Like I said mostly for the fact that the Roblox backups expire.

And no… It uses the DS2 method. Which consists of keeping indicators in OrderedDataStores and data inside a datastore.

Again, those are still datastores at the end of the day. They are still prone to data loss.

Yes…? Any data keeping system is prone to data loss anyway, what is your point here? Data loss is usually usually caused by datastores returning nil, on which I try my best to be sure that doesn’t happen here.

DS2 backups woudn’t be more or less prone to data loss than DataStore 1.1 backups. They actually work in a very similar matter.

My point is that no matter how secure your data is Roblox has the resources to store the backups in a better way because they have access to their internal database.

How do datastore 1.1 backups work? I haven’t heard anything about that.

They actually work very similarly to the berezaa method, consisting of keeping all the versions and always getting the newest one. You can list backups and such. But they just like DS2 won’t be automatically used. You’re supposed to use them if needed.

The good things about the internal handling of that is:

  1. Less requests, making it faster

  2. Can be both good and bad, but auto-deletes older backups. For developers that’s technically bad, but reasonable none the less.

  3. Unlike DS2 It allows you to get them through the actual API.

Right, but I’m sure they aren’t stored in a separate data scope and actually in an internal, read-only Roblox server that is more secure than a Datastore.

Eh, depends. Backups are well backups, backups aren’t mandatory, they’re BACK UPs, you use them when needed :)

Neither DataStore2 or DataStore 1.1 overwrite older backups. They keep their data intact, so you can’t SetAsync them or something. At least not internally, DS2 you can but it’s not part of DS2 so whatever.

Returning nil when the data is session locked and the session isn’t assumed dead is not a ideal solution:

This isn’t session locking, you are supposed to load the data until the session lock has expired or is assumed “dead” (depending on the load methods), not just return nil. Stop spreading false information regarding your module.

By reading the source code, this module doesn’t have session locking implemented carefully, everyone using this module would encounter a lot of bugs because of how session locking is implemented.

The way you save data is also really inefficient:

You aren’t waiting for the write cooldown to pass since you’re saving for the same key. This will throttle data stores really hard.

Why have you posted this module open sourced when it serves no purpose, not to mention the horrible code and inefficient practices that this module has.

8 Likes

You have made 3 datastore modules, why not just put them into 1?

6 Likes

I don’t like all of them, I only consider as if I made this one, which is DataStore+, this is just a wrapper I made to use DataStore+, I usually don’t make giant modules because of them being hard to read and modify afterwards. These “3” you’re talking about, they’re not related, they don’t do the same thing. It’s very likely that I’ll stop using DataStore+ as the backend once DataStore 1.1 is released. I can’t even support it early currently because if you’re in the beta, the data you save using 1.1 is gonna be deleted when it gets officially released.


I’m pretty sure that only counts if you write to it, if it didn’t sucessfully write to it, then no, it won’t throttle. UpdateAsync() only considers as a write if you save data to it. When a datastore errors, it won’t count as a Set request. Don’t worry about that :)

This isn’t re doing the same request all the time, it only retries if there was a error on the call. Which is rare to happen unless DataStoreServices are down.

I am not?

Like you said, it depends on the load method, I choose to do “Cancel” here. There’s nothing wrong to use cancel. I plan on adding the “usual” way later.

My plan with session locking was to not allow data corruption via innacurate data, “ForceLoad” can a lot of times throttle if a session is locked, and it will keep waiting until it gets something. Not really ideal for me personally.

I thought you would mention that os.time() is out of sync between servers. ProfileService deals with that by demanding that a profile is locked for more than 30 minutes. I need to fix that for now.

Because I want to. And also to find any of these “inefficient practices” and fix them.

Then why would you post it in #resources:community-resources? That belongs in #help-and-feedback:code-review.

I did so before and someone said it was not something to be on code review anyways. It’s only in case something happens.

You clearly don’t know how UpdateAsync works, you are clearly saving the data, as I showed you through the screenshot. When returning a value in the callback function of UpdateAsync, that value is saved.

That is my point, that’s isn’t useful session locking to the developer. There was no need to open source this module if you were being lazy to properly implement it, anyways, most of the developers don’t want to work with the “cancel” load method.

Don’t spread false information, ForceLoad doesn’t have the possibility to throttle since ProfileService specifically successive loads data every 10 seconds, ProfileService handles data corruption and error internally as well.

Not anymore, this has been fixed as the engineers at Roblox stated.

Data store errors aren’t rare, they occasionally happen and your entire point is incorrect, read up data store errors and limits to know more.

1 Like