SuggestionCache
local Operator = require(game:GetService("ServerStorage").Operator)
local SuggestionCache = Operator.SuggestionCacheDebounces 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
SuggestionCache.new(): CacheMethods
:request
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.
local cache = SuggestionCache.new()
local cancel = cache:request(Types.Player, query, executor, function(suggestions)
render(suggestions)
end):clear
cache:clear(typeName: string?): ()Drops cached entries for one type, or all types when typeName is omitted.
:destroy
cache:destroy(): ()Tears everything down and suppresses pending callbacks.
Caching behaviour
The per-type SuggestionOptions drive this:
| Option | Default | Effect here |
|---|---|---|
ttl | 10 | how long an entry stays fresh |
debounce | 0.15 | quiet time before a miss issues a fetch |
timeout | 5 | when a pending fetch is abandoned |
queryDependent | false | whether 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.