Skip to content

SuggestionCache

luau
local Operator = require(game:GetService("ServerStorage").Operator)
local SuggestionCache = Operator.SuggestionCache

Debounces and caches autocomplete requests so a type backed by a DataStore is not hammered on every keystroke. The built-in console uses one; a custom interface reaches it as Api.suggestions.

Functions

SuggestionCache.new

luau
SuggestionCache.new(): Cache

Methods

:request

luau
cache:request(
	argType: AnyArgType,
	query: string,
	executor: Player?,
	callback: (suggestions: { string }) -> ()
): () -> ()

Requests suggestions and returns a cancel function. Give it to a Maid, or call it when the query changes.

A cache hit calls back synchronously; a miss debounces first.

luau
local cache = SuggestionCache.new()

local cancel = cache:request(Types.Player, query, executor, function(suggestions)
	render(suggestions)
end)

:clear

luau
cache:clear(typeName: string?): ()

Drops cached entries for one type, or all types when typeName is omitted.

:destroy

luau
cache:destroy(): ()

Tears everything down and suppresses pending callbacks.

Caching behaviour

The per-type SuggestionOptions drive this:

OptionDefaultEffect here
ttl10how long an entry stays fresh
debounce0.15quiet time before a miss issues a fetch
timeout5when a pending fetch is abandoned
queryDependentfalsewhether entries key on the query

For a query-independent type the cache stores one entry per type and filters by prefix on the way out, so typing ten characters costs one fetch.

For a query-dependent type it keys on the query and passes results through unfiltered.

The cache is bounded

It holds at most 128 entries, evicting expired ones first and then those soonest to expire.

A query-dependent type is why that bound exists: it is keyed per query, so a player typing distinct prefixes adds an entry per keystroke, and expired entries would otherwise only be reclaimed when that exact key is requested again, which for a typed prefix is never.

Released under the MIT Licence.