QuickNetwork - A powerful hybrid alternative to ProfileService and DataStore2

QuickNetwork

QuickNetwork is an alternative, powerful and light wieght data store module to ProfileService and DataStore2. With features like SessionLocking, Backups and data combination, QuickNetwork provides an hybrid data store solution, also allowing you to control data saving and loading with easy flexibility.

Data loaded is auto saved automatically and managed efficiently with the least expensive of API calls, allowing you to use this module without worrying about data loss.

Documentation: Documentation
GitHub Source: GitHub Source
Roblox Model: Roblox Model

Benefits

  • Session Locking - Provides session locking, a powerful feature which prevents data duplication.

  • Robust Data Interface - Comes with its own data interface like DataStore2 except with no bloated methods, making it a hybrid combination of ProfileService and DataStore2.

  • Minimized DataStore API Calls - Proper data update detection and only sends an API request when needed, and takes precaution when working with API calls. Much securer than ProfileService and DataStore2.

  • Future Proof - Provides features for combining data from different keys or data stores all into 1, with the least expense of API calls. Also protects against throttling.

  • Light Weight - Doesn’t perform excessive API requests and conserves memory.

  • Flexibility - Easily handle data corruption and control how data is loaded / saved and other main aspects of this module, something which cannot be done when working with ProfileService or DataStore2. This allows for far more control, for advanced developers.

Want to get a new functionality recommended or issue a report? Head to Issues page in the repository and file one!

Example Usage

-- This is the template newly loaded datas' will default to
local DEFAULT_DATA_TEMPLATE = {
	Cash = 5,
}

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")

local QuickNetwork = require(ServerStorage.QuickNetwork)

local DataNetwork = QuickNetwork.GetDataNetwork("DataNetwork", DEFAULT_DATA_TEMPLATE)

-- Handle data corruption:
DataNetwork.DataCorruptionLoadSignal:Connect(function()
	 -- Load backup data:
     return "LoadBackup"
end)

-- Handle data load errors:
DataNetwork.DataErrorLoadSignal:Connect(function()
	-- Load backup data:
	return "LoadBackup"
end)

local function PlayerAdded(player)
	local data = DataNetwork:LoadDataAsync(player.UserId)
	
	-- Fill in any missing variables from the default data template:
	data:Reconcile()
	
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	
	local cash = Instance.new("IntValue")
	cash.Name = "Cash"
	cash.Value = data.Cash
	cash.Parent = leaderstats
	
	-- Listen to when the data updates
	data.ListenToUpdate:Connect(function(key, value)
		if leaderstats:FindFirstChild(key) then
			leaderstats[key].Value = value
		end
	end)

	leaderstats.Parent = player
	
	-- Increment cash:
	data:Set("Cash", data.Cash + 10)
end

local function PlayerRemoving(player)
	local data = DataNetwork:GetCachedData(player.UserId) 
	
	if data then
		data:Clear()
	end
end

-- Get new players:
Players.PlayerAdded:Connect(PlayerAdded) 

-- Get current players:
for _, player in ipairs(Players:GetPlayers()) do
	coroutine.wrap(PlayerAdded)(player)
end

-- Get leaving players:
Players.PlayerRemoving:Connect(PlayerRemoving)

68 Likes

This seems like a nice module, Might try it out someday. :wink:

2 Likes

Sounds good, I will download and take a look now.

1 Like

Why do you use UpdateAsync without anything? No comparing anything? I suggest using :SetAsync() instead if you’re not using UpdateAsync with no version comparing or anything.

Additionally, how are you handling backups? I can’t find any Ordered DataStore calls inside your modules, so I assume this is just a clone of the main version. Which doesn’t really come in as a hybrid from DataStore2 at all.

Some logging datastore calls later and I find out you’re using the same system as the :SetBackup() method from DS2, just a reminder those aren’t really backups but ok I guess.

Also, should have more info about the getting data thing, there’s nothing in the example you show, I thought it was some :Get() function or something. Only now I noticed it’s literally just do data.index

I also don’t know how to save data, it isn’t automatically saving so I’m not sure? :Save() doesn’t mean to wanna fire.

1 Like

The point of this module using UpdateAsync is not the old data, it respects incoming calls which is vital for session locking.

It fires, you can’t forcefully save data unnecessarily with this module to prevent it from sending another API call unnecessarily. And it won’t automatically save the data without any checks on which I encourage you to explore the source code.

If I ask, have you read the full source code properly? Whenever you call Save, it won’t forcefully save the data without any checks:

To forcefully save data, just pass an argument true.

What? Do you even know what backups are? QuickNetwork allows you to load backup data your self, it doesn’t load it automatically if data fails to load due to the flexibility nature.

DataStore2 these days is now inferior, the use of ordered data stores is extremely redundant and wastes resources, this module saves a backup of your data carefully. I think you have been under the mindset that ordered datastores are the way for backups, no.

Whenever you the data is saved, this module will first check if saving backup data is allowed, if so, it will save the current data to a backup data.

Upon loading data via LoadDataAsync, if that data couldn’t be loaded, an event DataErrorSignal will fire and you can do whatever you want, if you wish to load the backup data, return LoadBackup. Upon loading the backup data, it will be marked as a Backup so the module knows it’s a backup data and thus won’t be saved to the actual data store to prevent overriding the player’s actual data.

Same goes for when data loads but is corrupted, DataCorruptionSignal is fired and you can do whatever you want, if you wish to load the backup data, return LoadBackup but except this time, the backup data won’t be actually marked as Backup and will be saved to the actual data store.

I highly encourage you to read the documentation.

Read the documentation please.

5 Likes

How are you saving backups is my question.

Ordered Datastores pointing is fine for versioning, it is extremely expensive, but DataStore 1.1 is gonna release soon. (Q1 2021, so pretty soon) so it turns these solutions more useless anyhow.

My question is how do you handle backups, as: oh I save it in OrderedDataStores pointers, or oh I save it as a “insert method here”.

Honestly DS2 doesn’t have backups, it’s called versioning, it doesn’t keep backups, it keeps versions of data, so it depends on how you think of it. That’s why you don’t automatically get these backups while using DS2.

I didn’t go for a full walk through the entire thing, I’m asking you stuff to see if I would want to use it.

1 Like

How is this backup data store handled like, what key to do you set it to, etc? Knowing the methods you use to saving data is crucial.

I literally can’t find anything in documentation.

1 Like

The backup data is saved to the key you pass in as the first argument when calling LoadDataAsync in the backup data store.

The documentation is to help you how to use the methods, not explain everything about how this module saves and loads data.

2 Likes

Yeah that’s why I was asking ^^

1 Like

Can we get some examples of this?

1 Like

If you don’t want QuickNetwork to warn data store messages such as “Data Saved” or any error messages, you can set Logging to false.

Data:Save() -- will warn if data saves or errors

Settings.Logging = false 

Data:Save() -- will not warn if data saves or errors

No, I mean like the messages :sweat_smile:

Some of them are self explanatory and already explained, what one do you want an explanation for?

I recommend not using strings for setting things make it like profileservice where you can change it by path’s and its value like k,v

saying this

data:Set("key_to_set", 2) -- should be just instead data.key = 2

There is no proper way to detect when a table has changed and QuickNetwork always checks if data has updated before saving it, therefore it provides setter methods to update data.

2 Likes

People have annoyed me for that, but you can use userdatas (aka new proxy(true)), or alternatively really just an empty table that points to another table with NO issue.

Not possible with how QuickNetwork manages a data’s metatables.

Wdym by that? You can also just block certain indexes from being written to, like the indexes from your functions, and internal stuff. It is possible if you were to do it. Just wrap that into your already existing system. I can’t think why it wouldn’t be possible.

No, how data is loaded and managed will be completely broken and there’s no point anyways.

Looks cool, thanks for the module!