Save your player data with ProfileService! (DataStore Module)

The only time you should have issues is if Roblox accidentally gives you nil when there’s valid data stored somewhere. Many Roblox games experienced this issue a couple of years back for a day or so. That kind of thing is out of the control of anyone.

1 Like

It will yield indefinetly until a profile is loaded. nil is returned for other kinds of rare exceptions after which you should kick the player.

3 Likes

How do you use WipeProfileAsync?

So previously I wrote an interface to serialize/deserialize my data to Folders and ValueBases, and to update their keys in their respective tables in Profile.Data as the ValueBases are updated. Now I realize instead of trying to update Profile.Data as my ValueBases change, I can just serialize everything once when their profile is released like so:

profile:ListenToRelease(function()
	local data = leaderstatsToTable(player.PlayerData)
	profile.Data = data
	profileCache[player] = nil
	player:Kick()
end)

So my question is, serialization is a valid use of ListenToRelease, right? The first time I read this documentation:

After Profile:ListenToRelease() is triggered, it is too late to change Profile.Data for the final time. As long as the profile is active ( Profile:IsActive() == true ), you should store all profile related data immediately after it becomes available. An item trading operation between two profiles must happen without any yielding after it is confirmed that both profiles are active.

I was confused on whether I was allowed to modify Profile.Data in ListenToRelease.

Also, in the first line of ListenToRelease I printed Profile:IsActive() and it printed false. So, as per the IsActive documentation:

Returns true while the profile is session-locked and saving of changes to Profile.Data is guaranteed.

This worries me further that I’m doing something wrong. Am I allowed to serialize data in ListenToRelease?

2 Likes

You’re not allowed to - profile release can happen unexpectedly, issued by another server - that’s why :ListenToRelease can’t be used for final saving.

ProfileService forces you to keep your data saved in a form that, in case the server crashes or some other problem occurs, will protect player’s data with minimal data loss.

5 Likes

Presumably there are no issues with ProfileService in the event of an outage like DataStore2 experienced, where data became out of sync due to OrderDataStores not being affected by the recent issue?

When Roblox performs a rollback, is player data just reverted to whatever version they restored to?

https://devforum.roblox.com/t/datastores-incident-report/829962/1

Yup. ProfileService uses one key per profile, so it’s going to be compatible with Roblox’s own versioning systems.

1 Like

Didn’t get any reports so far for data loss with ProfileService.

6 Likes

hi, first off, I love your module! :grin: It is very intuitive and well made. Secondly, is there a way to detect changes to certain values such as a .Changed equivalent?

1 Like

Since ProfileService is not a change signal provider, you’ll either need to create your own get / set interface or simply update Profile.Data when your value object triggers .Changed

Wow! You’ve successfully sold this to me (thanks for making it Open Source by the way)! I’ve used DataStore2 for a while, and as it seems that Ordered Backups are soon no longer going to be necessary whenever the new API changes happen. This is part of my reasoning behind switching to ProfileService. Most of the things DataStore2 offers that ProfileService has I am fine writing by myself and would prefer to do that anyways (serialization, etc).

My only question is about detecting issues with Roblox’s datastores. DataStore2 has :IsBackup() which appears to work in most cases (but not in the last incident it seems). This just means that the current store is a temporary one and does not save at all to prevent issues. How does ProfileService specifically react to datastore saving issues like the recent one (does it return nil, etc), and is there anything else you would recommend for handling events like this (especially with regard to Robux purchases)?

Thanks!

1 Like

ProfileService basically IS the module that handles DataStore issues, given the developer has properly understood the documentation for the module.

Developer product purachase callbacks should be confirmed only when you know the player data has been saved - this can be done by utilizing Profile.MetaData.MetaTags and Profile.MetaData.MetaTagsLatest - see documentation for more info about them.

1 Like

Ah. Thanks for the specifics on MetaTags. From how I understand it, if the datastore itself fails to load, the profile will return nil. DataStore2 allows you to set a max number of tries and specifically informs you if it cannot load the data. From my understanding, ProfileService returns nil and to notify players of issues I should use the critical state signal.

If for some reason datastores are completely failing and ProfileService cannot access saved profile information, it would simply return nil. Please correct me if I am wrong.

However, you listed Kicking the player as the best option for when :LoadProfileAsync() returns nil. If datastores are down, wouldn’t the players automatically get kicked upon joining the server?

The specific case that I am seeking to answer is about notifying players that their data is having issues saving and loading, and notifying them when they join (and letting them join) instead of kicking them.

How would I go about doing this, and do I understand this fully or is there something I am missing?

P.S. Thanks for the quick reply on purchases. You have been very helpful.

EDIT: It seems that it will load indefinitely. I apologize for not seeing that you already answered my question. I will be building this eventuality into my handler. Thanks again for the module!

Quick question: does ProfileService encrypt data, and if not, would this be something worth doing myself? I saw something else do it a while back and am wondering if it would be something I would want to do.

Do you mean encrypting or encoding? Encrypting shouldn’t be necessary because you shouldn’t be storing confidential information about players in DataStores. Encoding also shouldn’t be necessary since the character limit is around 4 million now, and even a good building system would have trouble reaching that.

1 Like

I take it this only means stuff you wouldn’t be putting on Roblox anyway (real name, phone number etc)?

1 Like

Seems more efficient than DataStore2. Will ProfileService be getting any new functions? I’m planning it to use it for upcoming game.

ProfileService might receive rollback management in the near future

5 Likes

Nevermind! I figured out the issue.

The fact that DataStore2 is bound to the Player instance was a deal-breaker for me. Will be sure to use this once I start implementing saves.

3 Likes