local I={GetAsync=Enum.DataStoreRequestType.GetAsync;SetAsync=Enum.DataStoreRequestType.SetIncrementAsync;RemoveAsync=Enum.DataStoreRequestType.SetIncrementAsync;OnUpdate=Enum.DataStoreRequestType.OnUpdate;IncrementAsync=Enum.DataStoreRequestType.SetIncrementAsync}local function b(b)return dataStoreService:GetRequestBudgetForRequestType(I[b])end function SafeDataStore.new(I,b)local V=setmetatable({DataStore=dataStoreService:GetDataStore(I,b)},SafeDataStore)V.Failed=V.Shared.Event.new()return V end function SafeDataStore.Try(h,I,V,p)local t=b(I)if t==0 then end local i=nil for b=1,MAX_ATTEMPTS,1 do local t,Z=pcall(function()return h.DataStore[I](h.DataStore,V,p)end)if t then i=Z break elseif b==MAX_ATTEMPTS then warn("\068\097\116\097\083\116\111\114\101 "..(I..(" \102\097\105\108\101\100\058 "..tostring(Z))))h.Failed:Fire(I,V,tostring(Z))else wait(ATTEMPT_INTERVAL)end end return i end function SafeDataStore.OnUpdate(V,I,b)return V.DataStore:OnUpdate(I,b)end function SafeDataStore.GetAsync(b,I)return b:Try("\071\101\116\065\115\121\110\099",I)end function SafeDataStore.IncrementAsync(V,I,b)return V:Try("\073\110\099\114\101\109\101\110\116\065\115\121\110\099",I,b)end function SafeDataStore.SetAsync(V,I,b)return V:Try("\083\101\116\065\115\121\110\099",I,b)end function SafeDataStore.RemoveAsync(b,I)return b:Try("\082\101\109\111\118\101\065\115\121\110\099",I)end function SafeDataStore.UpdateAsync(V,I,b)return V:Try("\085\112\100\097\116\101\065\115\121\110\099",I,b)end return SafeDataStore
-- Map DataStoreService methods to associated RequestTypes:
local requestTypes = {
	GetAsync = Enum.DataStoreRequestType.GetAsync,
	SetAsync = Enum.DataStoreRequestType.SetIncrementAsync,
	RemoveAsync = Enum.DataStoreRequestType.SetIncrementAsync,
	OnUpdate = Enum.DataStoreRequestType.OnUpdate,
	IncrementAsync = Enum.DataStoreRequestType.SetIncrementAsync,
}

local function GetBudget(method)
	return dataStoreService:GetRequestBudgetForRequestType(requestTypes[method])
end

function SafeDataStore.new(name, scope)
	local self = setmetatable({
		DataStore = dataStoreService:GetDataStore(name, scope),
	}, SafeDataStore)

	self.Failed = self.Shared.Event.new()

	return self
end

function SafeDataStore:Try(method, k, v)
	local budget = GetBudget(method)
	if budget == 0 then
		-- Do something in later implementation
	end
	local value = nil
	for i = 1, MAX_ATTEMPTS do
		local success, v = pcall(function()
			return self.DataStore[method](self.DataStore, k, v)
		end)
		if success then
			value = v
			break
		elseif i == MAX_ATTEMPTS then
			warn("DataStore " .. method .. " failed: " .. tostring(v))
			self.Failed:Fire(method, k, tostring(v))
		else
			wait(ATTEMPT_INTERVAL)
		end
	end
	return value
end

function SafeDataStore:OnUpdate(key, callback)
	return self.DataStore:OnUpdate(key, callback)
end

function SafeDataStore:GetAsync(key)
	return self:Try("GetAsync", key)
end

function SafeDataStore:IncrementAsync(key, delta)
	return self:Try("IncrementAsync", key, delta)
end

function SafeDataStore:SetAsync(key, value)
	return self:Try("SetAsync", key, value)
end

function SafeDataStore:RemoveAsync(key)
	return self:Try("RemoveAsync", key)
end

function SafeDataStore:UpdateAsync(key, transformFunction)
	return self:Try("UpdateAsync", key, transformFunction)
end

return SafeDataStore
