function declarative.load_into_cache()

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