9️⃣

【Roblox】MemoryStore Queueについて

に公開

はじめに

今回は、MemoryStoreのデータ構造の一つである、Queueについて紹介します。

なお、MemoryStoreの概要については以下の記事をご覧ください。
https://zenn.dev/landho_roblox/articles/4d3fcbc648beb1

Roblox バージョン: 0.661.0.6610708

MemoryStoreQueueについて

MemoryStoreのデータ構造は、SortedMap、Queue、HashMapと3種類あります。
共通して、設定するデータには有効期限があり最大で45日です。

利用するにあたって各種制限などもありますが、これは概要編にて記載したので省きます。
詳しく知りたい方は、冒頭の「MemoryStoreの概要」リンクからご覧いただけます。

このデータ構造の一つであるQueueでは、MemoryStoreQueueインスタンスを利用してデータをQueueの構造で保持できます。
これは先入れ先出しの構造に加え優先度もつけることができます。

これらはサーバー間を跨いだマッチメイキングシステムなどに活用することができます。

MemoryStoreQueue

MemoryStoreでQueueを利用するには、MemoryStoreService:GetQueue() を実行しMemoryStoreQueueを取得する必要があります。

SampleScript
-- Service
local MemoryStoreService = game:GetService("MemoryStoreService")

local queue = MemoryStoreService:GetQueue("TestQueue", 30)

GetQueue function 名称 説明
引数 name string Queueの名前。
引数 invisibilityTimeout number Queueインスタンスを介した読み取り操作の非表示タイムアウト (秒単位)。 デフォルトでは30秒。
戻り値 MemoryStoreQueue MemoryStoreQueue 指定された名前のMemoryStoreQueueインスタンス。

MemoryStoreQueueを作成する上で重要なのは引数のinvisibilityTimeoutです。
これはMemoryStoreQueue:ReadAsync()で取得したアイテムを再度読み取るためにかかる秒数です。

MemoryStoreQueueはMemoryStoreQueue:ReadAsync()でアイテムと削除用のIdを読み取ります。
MemoryStoreQueueは複数サーバーから更新することができるため、読み取ったアイテムが他サーバーなどから更新されないように用意されているのがinvisibilityTimeoutです。

1度読み取られたアイテムはinvisibilityTimeoutで指定された秒数経過後に再度読み取り可能になります。

また削除用のIdを使用して読み取ったアイテムを削除する場合は、invisibilityTimeoutで指定された秒数内に削除しなければいけません。

マッチメイキングなどを実装する際はinvisibilityTimeoutで設定する秒数を正しく設定しなければ、次に読み取られるまで時間がかかる場合があるので注意しましょう。

アイテムの追加

MemoryStoreのQueueにアイテムを追加するには、MemoryStoreQueue:AddAsync() を呼び出します。

SampleScript
-- Service
local MemoryStoreService = game:GetService("MemoryStoreService")

local queue = MemoryStoreService:GetQueue("TestQueue", 30)

-- Queueにアイテムを追加する
function AddItem(item: string)

	local expiration = 60
	local priority = 1

	local success, errorMessage = pcall(function()
		queue:AddAsync(item, expiration, priority)
	end)

	if not success and errorMessage then
		warn(errorMessage)
	else
		print("Success AddAsync", item)
	end
end
AddAsync function 名称 説明
引数 value Variant Queueに追加するアイテム。
引数 expiration number 設定したアイテムの有効期限(秒単位)。有効期限が切れると、アイテムは自動的に削除される。最大有効期限は 45日間(3,888,000 秒)。
引数 priority number アイテムの優先度。優先度の高いアイテムは、優先度の低いアイテムよりも先にQueueから取得される。デフォルト値: 0
戻り値 - - なし

MemoryStoreのその他のデータ構造同様、引数には有効期限を秒数で指定します。
またアイテムごとに優先度を設定でき、優先度が高いアイテムは優先されてQueueから取得されます。

マッチメイキングシステムなどを実装した際は、長時間待機しているユーザーなどの優先度を高く設定するということもできます。

アイテムを読み取る

MemoryStoreのQueueからアイテムを読み取るには、MemoryStoreQueue:ReadAsync() を呼び出します。

SampleScript
-- Service
local MemoryStoreService = game:GetService("MemoryStoreService")

local queue = MemoryStoreService:GetQueue("TestQueue", 30)

-- Queueからアイテムを読み取る
function ReadItem()
	
	local count = 100
	local items = nil
	local removeId = nil
	local success, errorMessage
	
	success, errorMessage = pcall(function()
		items, removeId = queue:ReadAsync(count, false, 2)
	end)
	
	if not success and errorMessage then
		warn(errorMessage)	
	end

        return items
end
ReadAsync function 名称 説明
引数 count number Queueから読み取る個数。最大値は100。
引数 allOrNothing boolean Queueのアイテム数がcountより少ない場合のメソッドの動作を制御する。false に設定すると、メソッドは使用可能なすべてのアイテムを返す。true に設定すると、アイテムは返さない。デフォルト値: false
引数 waitTimeout number 必要な数のアイテムがすぐに利用できない場合にメソッドが待機する期間 (秒単位)。この期間中、読み取りは2秒ごとに試行される。このパラメータを0に設定した場合待機しない。このパラメータが指定されていないか-1に設定されている場合、メソッドは無期限に待機します。デフォルト値: -1
戻り値 items, id Tuple 取得したアイテムの配列とitemsをQueueから削除するために必要な文字列識別子。

引数のwaitTimeoutは注意が必要です。
Queue内のアイテムがすぐに利用できない場合はwaitTimeoutで指定された秒数待機しますが、この間2秒ごとに読み取りが試行されます。
この秒数を長期間に設定したり無期限に設定した場合、制限のあるAPIのリクエスト数を余計に消費する可能性があります。

制限については前述した「MemoryStoreの概要編」にて説明しています。

また前述にも合った通り、戻り値で取得できるitemsはinvisibilityTimeoutの制限がかかっていないアイテムです。

QueueにアイテムがあるがそのアイテムすべてはinvisibilityTimeoutの制限にかかっている場合、戻り値はnilになるので注意しましょう。

戻り値として取得するidは、削除する際に必要な文字列です。
idを利用することで取得したアイテムを全てQueueから削除することになるので、必要アイテム数のみ取得するようにしましょう。

アイテムの削除

MemoryStoreのQueueからアイテムを削除するには、MemoryStoreQueue:RemoveAsync() を呼び出します。
前述の「アイテムを読みとる」で使用したサンプルコードに追記します。

SampleScript
 -- Service
local MemoryStoreService = game:GetService("MemoryStoreService")

local queue = MemoryStoreService:GetQueue("TestQueue", 30)


 -- Queueからアイテムを読み取り削除する
function ReadItem()
	
	local count = 100
	local items = nil
	local removeId = nil
	local success, errorMessage
	
	success, errorMessage = pcall(function()
		items, removeId = queue:ReadAsync(count, false, 2)
	end)
	
	if not success and errorMessage then
		warn(errorMessage)	
	end
	
+	if #items > 0 then
+		
+		print("Success ReadAsync", items)
+		
+		success, errorMessage = pcall(function()
+			queue:RemoveAsync(removeId)
+		end)
+		
+		if not success and errorMessage then
+			warn(errorMessage)
+		end
+	end

        return items
end
RemoveAsync function 名称 説明
引数 id string MemoryStoreQueue:ReadAsync()で取得した文字列識別子。
戻り値 - - なし

前述にもありましたが、引数のidはMemoryStoreQueue:ReadAsync()で取得した文字列識別子です。
MemoryStoreQueue:RemoveAsync()を実行することで、idと同時に取得したアイテムすべてをQueueから削除します。

注意点としては、取得したidはQueueを作成する際に設定したinvisibilityTimeoutの秒数内に使用しなければいけません。
invisibilityTimeoutで指定した秒数経過後に取得していたidを用いてMemoryStoreQueue:RemoveAsync()を呼び出しても無効になります。

まとめ

  • MemoryStoreのデータ構造であるQueueは先入れ先出しの通常のQueueに加えアイテムごとに優先度をつけることができる。

  • MemoryStoreのQueueを使用するにはMemoryStoreQueueを使用する必要があり、これはMemoryStoreService:GetQueue()から取得できる。

  • MemoryStoreService:GetQueue()では引数にinvisibilityTimeoutを指定することができ、読み取ったアイテムはこのinvisibilityTimeoutで指定秒数間は他のサーバーなどから読み取ることができないようになっている。

  • MemoryStoreQueueにアイテムを追加するには、MemoryStoreQueue:AddAsync() を呼び出す。

  • MemoryStoreQueueのアイテムを読み取るには、MemoryStoreQueue:ReadAsync() を呼び出す。

  • MemoryStoreQueueのアイテムを削除するには、MemoryStoreQueue:ReadAync()で取得した文字列識別子をMemoryStoreQueue:RemoveAsync() の引数に設定して呼び出すことで削除できる。この時削除されるのは、同時に呼び出したアイテムとなる。

以上がMemoryStoreのQueueの紹介でした。
マッチメイキングシステムなどはRobloxではよく見かけると思います。
異なるサーバー間を通信する手段としてMessagingServiceなどが挙げられますが、MemoryStoreも使用することで幅が一気に広がると思います。

ぜひサーバー間をつなぐ通信が必要な際などに利用してみてください!!

参考

https://create.roblox.com/docs/cloud-services/memory-stores/queue
https://create.roblox.com/docs/reference/engine/classes/MemoryStoreService
https://create.roblox.com/docs/reference/engine/classes/MemoryStoreQueue

ランド・ホー Roblox開発チーム

Discussion