How to use DataStore2 - Data Store caching and data loss prevention

No it’s not. Requiring non-free modules by ID is going to be removed. Requiring free modules by ID will not. DataStore2 has always been a free module.

9 Likes

Apologies, misread the post.

5 Likes

Does this module have any methods to get data from all player keys? For example, to make a leaderboard showing highest score of all players who have played?

1 Like

No, you’d have to implement something like that as a wrapper.

3 Likes

OK. How would i index all the existing player keys? I guess i just dont understand the module well enough.

1 Like

You can’t. A wrapper would just use a separate ordered data store and set the values whenever DataStore2 updates.

5 Likes

Got it. I understand now. THANKS!

2 Likes

Received a PR that fixes :Update for combined data stores. I’ll be merging this soon. If you use :Update for combined data stores, make sure your code is ready before updating. If you require by ID, you’ll get this update as soon as I publish it.

5 Likes

Roblox has recently? made some changes to how DataStores work and I heard that theres is a better retry queue that helps avoid some for the problems that lead to the need for something like DataStore2.

Do you all feel that Roblox has addressed the issue? Do you all who use DataStore2 think you would keep using it anyway? What are your reasons?

Also to those who dont use DataStore2, do you feel like Roblox has addressed your concerns about data loss with their update?

3 Likes

The point of DataStore2 isn’t the saving mechanic, that wasn’t even in the original version. I use DataStore2 entirely because of caching, serde, and combining data stores.

That being said, are you sure there’s auto retry now? They announced that forever ago but it was never enabled, I don’t know if it is now.

2 Likes

I guess my friend and I were talking about it and I have seem some new messages in the output log while in Studio. However, I don’t have any source to that information.

I was of the understanding that the primary reason for DataStore2 (based on Berezaa’s method) was the prevention of data loss by never overwriting old keys and always making new ones. From my understanding that was why some folks started using it, out of frustration with player data being lost. Is this not the case?

I realize that DataStore2 has caching but there are other modules that so that. Not sure about combined datastores, I haven’t used those yet, but didn’t that feature come along a little later?

So I guess to re-frame my original question, is DataStore2 still a good idea to prevent player data being over written and lost, or is the problem not existing anymore?

Thanks

4 Likes

This seems to be a primary reason people use it, but that’s not the point of it. It’s just an addon.

I didn’t like their API. And yes, combined data stores came later, but they’re something unique to DataStore2 (as far as I know) and are good for avoiding throttles and better data guarantees (only one store has to load as opposed to multiple).

Automatic retries don’t offer the ability to restore old data from players, so no.

2 Likes

I was wondering why my code wasn’t working. I thought I was insane but I switch :Update() over to :Set() and it worked fine. Is there any reason for me to switch back to :Update()

1 Like

Only use Update if you actually are using the old value, otherwise I don’t see the point.

1 Like

I’m using rbx-datastore2 with combined data stores, and I have a BeforeSave callback for the level and xp stores. My question is, will this work as expected with setting new values for other stores in the BeforeSave callback? Here’s how I have it setup.

Code
DataStore2.Combine('PlayerData', 'rank', 'level', 'xp', 'coins')

Players.PlayerAdded.Connect((player) => {
  let rank = DataStore2<number>('rank', player)
  let level = DataStore2<number>('level', player)
  let xp = DataStore2<number>('xp', player)
  let coins = DataStore2<number>('coins', player)
  level.BeforeSave((currentLevel) => {
	  if (currentLevel > 1000) {
		  return 100
	  } else {
		  return currentLevel
	  }
  })
  xp.BeforeSave((currentXp) => {
    let currentLevel = level.Get(1)
    let maxXp = getMaxXpForLevel(currentLevel)
    if (currentXp >= maxXp) {
      let newXp = currentXp - maxXp
      level.Increment(1, 1)
      return newXp
    } else {
      return currentXp
    }
  })
})
2 Likes

That looks fine to me.

3 Likes

Are you going to switch from os.time() to incremental version numbers soon?

3 Likes

Yes.

7 Likes

Incremental key saving has been pushed to the prod script. Tell me if you have any issues.

2 Likes

For anyone dealing with GDPR, I believe this script I whipped up will work. Put this in your command bar then use clear(userId, name) (also in the command bar) to clear someone’s data.

If you use combined data stores, the name will be your master key. Otherwise, it’s your normal name.

local DataStoreService = game:GetService("DataStoreService")

function clear(userId, name)
	local orderedDataStore = DataStoreService:GetOrderedDataStore(name .. "/" .. userId)
	local dataStore = DataStoreService:GetDataStore(name .. "/" .. userId)

	while true do
		local pages = orderedDataStore:GetSortedAsync(false, 100)
		local data = pages:GetCurrentPage()
		for _, pair in pairs(data) do
			print(("key: %d"):format(pair.key))
			dataStore:RemoveAsync(pair.key)
			orderedDataStore:RemoveAsync(pair.key)
		end
		if pages.IsFinished then
			print(("finished (%d: %s)"):format(userId, name))
			return
		end
	end
end
97 Likes