After reading that, I have started to worry a bit, cuz I changed code partially to work normally, because I had needs to not only update items but also get data from Memory store, and I have used some GetAsync
to get item rolls data, aswell as SetAsync
to set item rolls data from master server.
code for all that changes:
local RS = game:GetService("ReplicatedStorage")
local SS = game:GetService("ServerStorage")
local Remotes = RS:WaitForChild("Remotes")
local Bindables = SS:WaitForChild("Bindables")
local MSS = game:GetService("MemoryStoreService")
local MemoryStore = MSS:GetHashMap("ItemShopRoll")
local HttpService = game:GetService("HttpService")
local RunService = game:GetService("RunService")
local Libraries = {
ItemPrice = require(RS.Libraries:WaitForChild("ItemPriceLibrary")),
ItemRoll = require(script:WaitForChild("ItemRollChance")),
}
local RefreshTime = 30 --10800
local LatencyTime = 5 --180
local Cleanup = false
local ModuleMeta = {}
ModuleMeta.__index = ModuleMeta
function ModuleMeta.Initialize()
local self = setmetatable({}, ModuleMeta)
self.Data = {}
self.Viewers = {}
if Cleanup then
local Retries = 10
local Success, Error
repeat
Success, Error = pcall(function()
return MemoryStore:SetAsync("MasterServer", "", 86400--[[3888000]])
end)
until Success or Retries <= 0
if not Success then
warn(Error)
end
Retries = 10
repeat
Success, Error = pcall(function()
return MemoryStore:SetAsync("Rolls", "", 86400--[[3888000]])
end)
until Success or Retries <= 0
if not Success then
warn(Error)
end
end
self:AssignMaster()
return self
end
function ModuleMeta:RefreshStock(Stock)
print(Stock)
self.Data = {}
for i = 1, #Stock, 1 do
local Item = Stock[i]
local Price, Currency = Libraries.ItemPrice.GetItemPrice(Item, "Buy")
if Price then
table.insert(self.Data, {Name = Item, Price = Price, Currency = Currency})
end
end
for i = 1, #self.Viewers, 1 do
Remotes.ShopEvent:FireClient(self.Viewers[i], "Refresh", self.Data)
end
end
function ModuleMeta:GenerateRolls()
local RollData
local Success, Error
local Retries = 10
repeat
Success, Error = pcall(function()
RollData = MemoryStore:GetAsync("Rolls")
end)
if Success then
local SelectedData
local Data = string.len(RollData) > 0 and HttpService:JSONDecode(RollData) or {}
for RollId = #Data, 1, -1 do
print(RollId)
local CurrentRoll = Data[RollId]
if CurrentRoll.Time <= os.time() - RefreshTime then
for i = 1, #Data, 1 do
table.remove(Data, 1)
end
warn("Generating all 3 rolls cuz they are all expired.")
for i = 1, 3, 1 do
local NewRoll = {}
while #NewRoll < 9 do
local SelectedItem = Libraries.ItemRoll.GetRandomItem()
if not table.find(NewRoll, SelectedItem) then
table.insert(NewRoll, SelectedItem)
end
end
local RollTime = math.floor(os.time() / RefreshTime + i-1) * RefreshTime
table.insert(Data, {Time = RollTime, Items = NewRoll})
end
SelectedData = Data[1]
MemoryStore:SetAsync("Rolls", HttpService:JSONEncode(Data), 86400)
break
elseif CurrentRoll.Time <= os.time() then
SelectedData = CurrentRoll
for i = 1, RollId-1, 1 do
table.remove(Data, 1)
end
warn("Generating " .. tostring(RollId-1) .. " rolls")
for i = 1, RollId-1, 1 do
local NewRoll = {}
while #NewRoll < 9 do
local SelectedItem = Libraries.ItemRoll.GetRandomItem()
if not table.find(NewRoll, SelectedItem) then
table.insert(NewRoll, SelectedItem)
end
end
local RollTime = math.floor(os.time() / RefreshTime + #Data) * RefreshTime
table.insert(Data, {Time = RollTime, Items = NewRoll})
end
MemoryStore:SetAsync("Rolls", HttpService:JSONEncode(Data), 86400)
break
end
end
if not SelectedData then
warn("Generating all 3 rolls cuz data not exists")
for i = 1, 3, 1 do
local NewRoll = {}
while #NewRoll < 9 do
local SelectedItem = Libraries.ItemRoll.GetRandomItem()
if not table.find(NewRoll, SelectedItem) then
table.insert(NewRoll, SelectedItem)
end
end
local RollTime = math.floor(os.time() / RefreshTime + i-1) * RefreshTime
table.insert(Data, {Time = RollTime, Items = NewRoll})
end
SelectedData = Data[1]
MemoryStore:SetAsync("Rolls", HttpService:JSONEncode(Data), 86400)
end
--self:RefreshStock(SelectedData.Items)
local TimeToUpdate = self:CheckRoll()
coroutine.wrap(function()
task.wait(TimeToUpdate)
if self.Closing then return end
self:GenerateRolls()
end)()
end
until Success or Retries <= 0
warn(Error)
end
function ModuleMeta:AssignMaster()
local Id = RunService:IsStudio() and "StudioTestServer" or game.JobId
warn(Id)
local Success, Error
local Retries = 10
local WasMaster = false
repeat
Success, Error = pcall(function()
return MemoryStore:UpdateAsync("MasterServer", function(OldData)
print("Master server: " .. tostring(OldData))
if OldData == nil or OldData == "" then
return Id
else
WasMaster = (Id == OldData)
return OldData
end
end, 86400--[[3888000]])
end)
if Success then
local IsMaster = Id == Error
print(WasMaster, IsMaster)
if IsMaster and WasMaster then
if not self.MasterDeath then
self.MasterDeath = game:BindToClose(function()
MemoryStore:RemoveAsync("MasterServer")
end)
end
local TimeToUpdate = self:CheckRoll()
coroutine.wrap(function()
task.wait(TimeToUpdate)
if self.Closing then return end
self:GenerateRolls()
end)()
elseif IsMaster then
if not self.MasterDeath then
self.MasterDeath = game:BindToClose(function()
MemoryStore:RemoveAsync("MasterServer")
end)
end
local TimeToUpdate = self:CheckRoll()
coroutine.wrap(function()
task.wait(TimeToUpdate)
if self.Closing then return end
self:AssignMaster()
end)()
else
local TimeToUpdate = self:CheckRoll()
coroutine.wrap(function()
task.wait(TimeToUpdate)
if self.Closing then return end
self:AssignMaster()
end)()
end
end
until Success or Retries <= 0
if not Success then
warn(Error)
end
return Id == Error, Error
end
function ModuleMeta:CheckRoll()
local RollData
local UpdateTime
local Success, Error
local Retries = 10
repeat
Success, Error = pcall(function()
RollData = MemoryStore:GetAsync("Rolls")
end)
if Success then
local SelectedData
local Data = string.len(RollData) > 0 and HttpService:JSONDecode(RollData) or {}
print(Data)
for RollId = #Data, 1, -1 do
local CurrentRoll = Data[RollId]
if CurrentRoll.Time <= os.time() then
SelectedData = CurrentRoll
UpdateTime = RefreshTime - (os.time() - CurrentRoll.Time)
UpdateTime = UpdateTime > LatencyTime and UpdateTime or UpdateTime + RefreshTime
break
end
end
if not SelectedData then
warn("FATAL ERROR: NO MATCHING ROLLS FOUND. USING OLD ONES")
SelectedData = {}
SelectedData.Items = self.Items or {}
end
self:RefreshStock(SelectedData.Items)
print(UpdateTime)
print(SelectedData.Time, os.time())
return UpdateTime
else
warn(Error)
end
Retries -= 1
until Success or Retries <= 0
return
end
return ModuleMeta
(Sorry if this code is mess)