MemoryStoreQueue invisibility timeout issue

I’m currently making a cross-server block placement system using MemoryStoreQueues and MessagingService. Here’s how it should work:

  1. Place block
  2. Put it in the queue
  3. Check if the queue has x items (x = 5 for debugging)
  4. If item count reaches x, make a copy of the queue to be sent through MessagingService
  5. Clear the queue (only on the server the limit was reached on)
  6. Publish the queue to all servers using MessagingService
  7. Each server, upon the reception of the queue, loads the queue’s contents

Right now it seems like the queue does not clear consistently. I’m honestly pretty new to using MemoryStoreService so a lot of it has been trial and error. I’m assuming it’s something with the invisibility timeout, but I’m seriously lost as to what should be where, how much something should be etc. I just don’t want the duplicates to happen. I’ll paste the relevant code snippet along with a video that hopefully displays the issue as well as possible. Invisibility timeout is set to 30 seconds. Expiration for each item is set to 600 seconds.

Video (idk why it doesn’t embed):

External Media

Placing:

local brickInfo = {}

brickInfo.BrickPosition = {brick.Position.X, brick.Position.Y, brick.Position.Z}
brickInfo.ColorOfBrick = tostring(brick.BrickColor)
brickInfo.BrickOwner = brick:FindFirstChild("Owner").Value
brickInfo.BrickDate = brick:FindFirstChild("Date").Value
brickInfo.BrickID = brick.Name

local success, err = pcall(function()

	queue:AddAsync(brickInfo, EXPIRATION)
	print("Added brick to queue: " .. brick.Name)

	local succ, items = pcall(function()
		return queue:ReadAsync(5, true, 0)
	end)

	if not succ then
		warn("Failed to read queue:", items)
	else

		-- get items from queue and store them separately
		-- clear queue items
		-- send stored items to messagingservice

		if items then

			print("QUEUE FULL")

			local QEUEUE = items

			for _, it in pairs(items) do

				print(it)

				local removeSuccess, removeResult = pcall(function()
					return queue:RemoveAsync(it)
				end)

				if removeSuccess then
					print("Item successfully removed from the queue.")
				else
					warn("Failed to remove items from the queue:", removeResult)
				end

			end

			messagingService:PublishAsync("SyncRequest", QEUEUE)

		else
			print("QUEUE NOT FULL")
		end

	end
end)

if not success then
	warn("Failed to add brick to queue:", err)
end

Should I even be using queues for this anymore? I’ve tried hashmaps before, but I was very quickly hitting API request unit limits. What should I change? If something feels like it’s missing please let me know and I’ll answer back. Other than that I’d really appreciate any support here.

why does this queue have to use memorystoreservice instead of just being stored on local memory

Because local memory can’t be accessed by other servers. This is why I’m using MemoryStoreService. It’s cross-server block placement, which I specified at the beginning of the post.

EDIT: Although actually I could try copying the block table on every server instead of the one server that reached the 5-block limit. I’ll keep you updated

Okay so I’ve set up a very simple script to test this:

local MessagingService = game:GetService("MessagingService")
local MemoryStoreService = game:GetService("MemoryStoreService")
local queue = MemoryStoreService:GetQueue("TestQ")

for i = 1, 5 do
	queue:AddAsync("Item"..i, 60)
end

local readSuccess, readResult = pcall(function()
	return queue:ReadAsync(5, true, -1) -- up to 5 items from the queue, so it basically waits until those 5 items are available
end)

if readSuccess then

	for _, item in ipairs(readResult) do
		print(item)
	end

	-- remove from queue
	local removeSuccess, removeResult = pcall(function()
		return queue:RemoveAsync(readResult)
	end)

	if removeSuccess then
		print("Items removed from queue.")
	else
		warn("Failed to remove items from the queue:", removeResult)
	end
	
else
	warn("Failed to read items from queue:", readResult)
end

-- check if queue empty

task.wait(1)
local readSuccess2, readResult2 = pcall(function()
	return queue:ReadAsync(50, false, 0) -- reading up to 50 items just to be sure
end)

if readSuccess2 then
	print("Remaining items after removal:", readResult2)
else
	warn("Failed to read items from the queue:", readResult2)
end

At around 6:44 PM:


About 30 seconds later:

I need an explanation as if I were 5 because I’m getting a headache - why does this happen? What would I need to know about this that would be relevant to my project? I just want to clear the queue. :roll_eyes:

According to the docs, ReadAsync returns a tuple formatted as (value, identifier)
In your pcall your only taking the value and discarding the identifier
To remove a set of values, it requires the identifier
In your code it looks like your trying to remove from the queue using the returned values instead of the identifier.

To get the identifier, you can add a 3rd variable

local readSuccess, readResult, readIdentifier = pcall(function()
	return queue:ReadAsync(5, true, -1)
end)

From there you can use the identifier to remove from the queue

local removeSuccess, removeResult = pcall(function()
	return queue:RemoveAsync(readIdentifier)
end)

As a side note, you don’t need those extra function calls in each pcall

local readSuccess, readResult, readIdentifier = pcall(queue.ReadAsync, queue, 5, true, -1)
local removeSuccess = pcall(queue.RemoveAsync, queue, readIdentifier)