Перейти к содержимому

Key-Value хранилище

Быстрое key-value хранилище с поддержкой TTL. Идеально для кэширования, сессий и временного состояния.

Настройку хранилища см. в Store.

local store = require("store")

Получить ресурс хранилища по ID реестра:

local cache, err = store.get("app:cache")
if err then
return nil, err
end
cache:set("user:123", {name = "Alice"}, 3600)
local user = cache:get("user:123")
cache:release()
ПараметрТипОписание
idstringID ресурса хранилища

Возвращает: Store, error

Сохранить значение с опциональным TTL:

local cache = store.get("app:cache")
-- Простое сохранение
cache:set("user:123:name", "Alice")
-- Сохранение с TTL (истекает через 300 секунд)
cache:set("session:abc", {user_id = 123, role = "admin"}, 300)
ПараметрТипОписание
keystringКлюч
valueanyЗначение (таблицы, строки, числа, булевы)
ttlnumberTTL в секундах (опционально, 0 = без истечения)

Возвращает: boolean, error

Получить значение по ключу:

local user = cache:get("user:123")
if not user then
-- Ключ не найден или истёк
end
ПараметрТипОписание
keystringКлюч для получения

Возвращает: any, error

Возвращает nil если ключ не существует.

Проверить наличие ключа без получения значения:

if cache:has("lock:" .. resource_id) then
return nil, errors.new("CONFLICT", "Resource is locked")
end
ПараметрТипОписание
keystringКлюч для проверки

Возвращает: boolean, error

Удалить ключ из хранилища:

cache:delete("session:" .. session_id)
ПараметрТипОписание
keystringКлюч для удаления

Возвращает: boolean, error

Возвращает true если удалён, false если ключ не существовал.

entry возвращает значение вместе с его version — непрозрачной строкой, используемой для оптимистичной конкурентности:

local e, err = cache:entry("user:123")
if e then
print(e.key, e.value, e.version)
end
ПараметрТипОписание
keystringКлюч для чтения

Возвращает: Entry, error{key: string, value: any, version: string}

Перечислить записи в детерминированном порядке ключей с постраничной разбивкой:

local page, err = cache:list({ prefix = "session:", limit = 100 })
for _, e in ipairs(page.items) do
print(e.key, e.value)
end
-- следующая страница
if page.has_more then
page = cache:list({ prefix = "session:", after = page.cursor })
end
ОпцияТипОписание
prefixstringТолько ключи с этим префиксом
afterstringПродолжить после этого курсора (с предыдущей страницы)
limitintegerМаксимум элементов на странице

Возвращает: Page, error{items: Entry[], cursor: string, has_more: boolean}

put записывает значение и возвращает его новый Entry. Опции включают оптимистичную конкурентность:

-- создать только если ключ не существует
local e, err = cache:put("lock:job-1", owner, { only_if_absent = true })
if err and err:kind() == "ALREADY_EXISTS" then
-- ключ держит кто-то другой
end
-- compare-and-set: записать только если версия всё ещё совпадает
local cur = cache:entry("config")
local e2, err2 = cache:put("config", new_value, { if_version = cur.version })
if err2 and err2:kind() == "CONFLICT" then
-- конкурентный писатель изменил его; перечитать и повторить
end
ОпцияТипОписание
ttlnumberTTL в секундах
only_if_absentbooleanЗаписать только если ключ не существует
if_versionstringЗаписать только если текущая версия совпадает

only_if_absent и if_version взаимоисключающи.

Возвращает: Entry, error

Условные записи требуют хранилища, у которого info().conditional_put равно true (хранилища в памяти и store.kv.raft). На store.kv.crdt и store.sql они возвращают ошибку errors.INVALID — используйте store.kv.raft, когда нужны условные записи.

info сообщает о бэкенде и о том, что он поддерживает, чтобы код мог адаптироваться к привязанному хранилищу:

local info = cache:info()
-- info.backend -> одно из store.backend.* (напр. "kv.raft")
-- info.consistency -> одно из store.consistency.* (напр. "linearizable")
-- info.durable / info.list / info.versioned / info.conditional_put / info.ttl (булевы)

Возвращает: Info, error{id, backend, consistency, durable, list, versioned, conditional_put, ttl}

КонстантаЗначения
store.backendMEMORY, SQL, KV_RAFT, KV_CRDT, UNKNOWN
store.consistencyLINEARIZABLE, EVENTUAL, LOCAL, UNKNOWN
if cache:info().consistency == store.consistency.LINEARIZABLE then
-- безопасно использовать compare-and-set
end
МетодВозвращаетОписание
get(key)any, errorПолучить значение по ключу
entry(key)Entry, errorПолучить значение с метаданными версии
set(key, value, ttl?)boolean, errorСохранить значение с опциональным TTL
put(key, value, opts?)Entry, errorУсловная/версионированная запись, возвращает новую запись
list(opts?)Page, errorПостраничное перечисление в порядке ключей
has(key)boolean, errorПроверить существование ключа
delete(key)boolean, errorУдалить ключ
info()Info, errorБэкенд, согласованность и флаги возможностей
release()booleanВернуть хранилище в пул

Операции хранилища подчиняются вычислению политики безопасности.

ДействиеРесурсАтрибутыОписание
store.getID хранилища-Получить ресурс хранилища
store.key.getID хранилищаkeyПрочитать значение ключа
store.key.setID хранилищаkeyЗаписать значение ключа
store.key.deleteID хранилищаkeyУдалить ключ
store.key.hasID хранилищаkeyПроверить существование ключа

store.get() и все методы дескриптора хранилища (get, set, has, delete) возвращают структурированные ошибки (используйте err:kind()).

УсловиеKindПовторяемо
Пустой ID ресурсаerrors.INVALIDнет
Ресурс не найденerrors.NOT_FOUNDнет
Хранилище освобожденоerrors.INVALIDнет
Доступ запрещёнerrors.PERMISSION_DENIEDнет
only_if_absent и ключ существуетerrors.ALREADY_EXISTSнет
Несовпадение if_versionerrors.CONFLICTда
Условная запись на хранилище без поддержкиerrors.INVALIDнет

См. Обработка ошибок для работы с ошибками.