[SOLVED] How to detect whenever an item in a MemoryStoreSortedMap is expired?

Hello Everyone,

I am wondering how I am able to detect whenever a item in a MemoryStoreSortedMap expires. So if I set the date to expire 24 hours from the start time, it will expire without me able to detect in the code that it expired. I could loop through all of the keys in MemoryStoreSortedMap:GetRangeAsync() and see if any of the keys don’t exist anymore in the cache table, but this seems highly inefficient.

From,
Spencer “SpencerDevv”

usually you just have the data be stored as an integer which represents the time in seconds till it (relative to 1970 think) then just keep calling os.time(). You usually check when they want to purchase something (assuming thats what you are trying to do) or just every 30 seconds or so. Idk what are the band limits for memory stores though

1 Like

Hello @CoderHusk,

I see what your saying, but we can’t actually see how long until it expires, all that happens is you give the MSS the expiration time (seconds). Also I made a kind of event handler with my MSM (MemoryStoreManager) module, where it sends a message to all servers (through MessagingService) so I could limit the costs. We can’t check every 30 seconds because A, We can’t get all keys (Only top 100) as stated here, and here. And B, That would be heavy on costs.

Thanks For Helping,
Spencer “SpencerDevv”

Actually, now that I thought about it more, this may work

Hello Everyone,

I have made a custom solution for this problem.

DISCLAIMER: This is assuming you have figured out your way to communicate with all servers and a function for removing data from MSS (MemoryStoreService)

ANOTHER DISCLAIMER: This was made before there is an event handler or any way to detect if an item was expired

FINAL DISCLAIMER: There might be cleaner ways on doing this, but I made this in a way where it costs 0 extra costs to the MSS (except when initializing and removing)

What you have to do is put a variable called MSS_ExpireTimes and set it up as a table (can be any name, I’m just using this)

local MSS_ExpireTimes = {}

Then you need to create 2 functions (Again, these are the names I chose, you can change them)

function GetExpireTimeForKey(key, data)
end

function RunChecksForExpiration()
end

For the key naming convention, what I did is TimeOfExpire_Prefix_UID. So for example:
“1632769289.8_AuctionItem_A25004A0C34847AA849F2A62D414FC37”.

So for the GetExpireTimeForKey function, what we need to do is separate the TimeOfExpire and the rest of the string.

function GetExpireTimeForKey(key, data)
	local index = string.find(key, "_") 
	local str = string.sub(key, 1, (index - 1))
	local time = tonumber(str)

	-- whenever you are initializing a key, add the data argument so if
	-- there is a case where this is delayed by a tiny bit, it doesn't
	-- just lose data (in case you need data for a callback)
	if data then
		MSS_ExpireTimes[key] = data
	end

	return time
end

Now we are done with that function, so you want to call this with the data parameter whenever the item first gets created.

Now its time for the RunChecksForExpiration function!

function RunChecksForExpiration()
	coroutine.wrap(function()
		while true do
			for key, data in pairs(MSS_ExpireTimes) do
				local expireTime = GetExpireTimeForKey(key)
				local diffTime = os.difftime(expireTime, os.time())

				if diffTime <= 0 then
					MSS_ExpireTimes[key] = nil
					MSM.RemoveFromMSS(key, data)
				end
			end

			task.wait(1)
		end
	end)()
end

This was pretty much all you have to do, call RunChecksForExpiration() at the bottom of the script.

Example of when to call the GetExpireTimeForKey function (with the data parameter)
image

Example on when to call the RunChecksForExpiration function
image

Thanks for listening,
Spencer “SpencerDevv”

2 Likes