in kong/kong/db/declarative/init.lua [678:947]
function declarative.load_into_cache(entities, meta, hash)
local tags = {}
meta = meta or {}
local default_workspace = assert(find_default_ws(entities))
local fallback_workspace = default_workspace
assert(type(fallback_workspace) == "string")
if not hash or hash == "" then
hash = DECLARATIVE_EMPTY_CONFIG_HASH
end
local tags_by_name = {}
local db = kong.db
local t = txn.begin(128)
t:db_drop(false)
local transform = meta._transform == nil and true or meta._transform
for entity_name, items in pairs(entities) do
yield()
local dao = db[entity_name]
if not dao then
return nil, "unknown entity: " .. entity_name
end
local schema = dao.schema
local taggings = {}
local uniques = {}
local page_for = {}
local foreign_fields = {}
for fname, fdata in schema:each_field() do
if fdata.unique then
if fdata.type == "foreign" then
if #db[fdata.reference].schema.primary_key == 1 then
insert(uniques, fname)
end
else
insert(uniques, fname)
end
end
if fdata.type == "foreign" then
page_for[fdata.reference] = {}
foreign_fields[fname] = fdata.reference
end
end
local keys_by_ws = {
["*"] = {}
}
for id, item in pairs(items) do
yield(true)
assert(type(fallback_workspace) == "string")
local ws_id
if schema.workspaceable then
if item.ws_id == null or item.ws_id == nil then
item.ws_id = fallback_workspace
end
assert(type(item.ws_id) == "string")
ws_id = item.ws_id
else
ws_id = ""
end
assert(type(ws_id) == "string")
local cache_key = dao:cache_key(id, nil, nil, nil, nil, item.ws_id)
item = remove_nulls(item)
if transform then
local err
item, err = schema:transform(item)
if not item then
return nil, err
end
end
local item_marshalled, err = marshall(item)
if not item_marshalled then
return nil, err
end
t:set(cache_key, item_marshalled)
local global_query_cache_key = dao:cache_key(id, nil, nil, nil, nil, "*")
t:set(global_query_cache_key, item_marshalled)
insert(keys_by_ws["*"], cache_key)
if ws_id ~= "" then
keys_by_ws[ws_id] = keys_by_ws[ws_id] or {}
local keys = keys_by_ws[ws_id]
insert(keys, cache_key)
end
if schema.cache_key then
local cache_key = dao:cache_key(item)
t:set(cache_key, item_marshalled)
end
for i = 1, #uniques do
local unique = uniques[i]
if item[unique] then
local unique_key = item[unique]
if type(unique_key) == "table" then
local _
_, unique_key = next(unique_key)
end
local key = unique_field_key(entity_name, ws_id, unique, unique_key,
schema.fields[unique].unique_across_ws)
t:set(key, item_marshalled)
end
end
for fname, ref in pairs(foreign_fields) do
if item[fname] then
local fschema = db[ref].schema
local fid = declarative_config.pk_string(fschema, item[fname])
page_for[ref]["*"] = page_for[ref]["*"] or {}
page_for[ref]["*"][fid] = page_for[ref]["*"][fid] or {}
insert(page_for[ref]["*"][fid], cache_key)
page_for[ref][ws_id] = page_for[ref][ws_id] or {}
page_for[ref][ws_id][fid] = page_for[ref][ws_id][fid] or {}
insert(page_for[ref][ws_id][fid], cache_key)
end
end
local item_tags = item.tags
if item_tags then
local ws = schema.workspaceable and ws_id or ""
for i = 1, #item_tags do
local tag_name = item_tags[i]
insert(tags, tag_name .. "|" .. entity_name .. "|" .. id)
tags_by_name[tag_name] = tags_by_name[tag_name] or {}
insert(tags_by_name[tag_name], tag_name .. "|" .. entity_name .. "|" .. id)
taggings[tag_name] = taggings[tag_name] or {}
taggings[tag_name][ws] = taggings[tag_name][ws] or {}
taggings[tag_name][ws][cache_key] = true
end
end
end
for ws_id, keys in pairs(keys_by_ws) do
local entity_prefix = entity_name .. "|" .. (schema.workspaceable and ws_id or "")
local keys, err = marshall(keys)
if not keys then
return nil, err
end
t:set(entity_prefix .. "|@list", keys)
for ref, wss in pairs(page_for) do
local fids = wss[ws_id]
if fids then
for fid, entries in pairs(fids) do
local key = entity_prefix .. "|" .. ref .. "|" .. fid .. "|@list"
local entries, err = marshall(entries)
if not entries then
return nil, err
end
t:set(key, entries)
end
end
end
end
for tag_name, workspaces_dict in pairs(taggings) do
for ws_id, keys_dict in pairs(workspaces_dict) do
local key = "taggings:" .. tag_name .. "|" .. entity_name .. "|" .. ws_id .. "|@list"
local arr = {}
local len = 0
for id in pairs(keys_dict) do
len = len + 1
arr[len] = id
end
sort(arr)
local arr, err = marshall(arr)
if not arr then
return nil, err
end
t:set(key, arr)
end
end
end
for tag_name, tags in pairs(tags_by_name) do
yield(true)
local key = "tags:" .. tag_name .. "|@list"
local tags, err = marshall(tags)
if not tags then
return nil, err
end
t:set(key, tags)
end
local tags, err = marshall(tags)
if not tags then
return nil, err
end
t:set("tags||@list", tags)
t:set(DECLARATIVE_HASH_KEY, hash)
kong.default_workspace = default_workspace
local ok, err = t:commit()
if not ok then
return nil, err
end
kong.core_cache:purge()
kong.cache:purge()
yield()
return true, nil, default_workspace
end