-- stress_pagedata_ultra.lua
-- один URL (/api/v2/pagedata), быстрый равномерный перебор [i_min..i_max]

-- ===== tunables =====
local i_min      = tonumber(os.getenv("I_MIN") or "1")
local i_max      = tonumber(os.getenv("I_MAX") or "2500000")
local language   = os.getenv("LANGUAGE")   or "en"
local domain     = os.getenv("DOMAIN")     or "advcache.example.com"
local project_id = os.getenv("PROJECT_ID") or "285"

wrk.method  = "GET"
wrk.headers = {
  ["Host"]            = os.getenv("HOST")  or "0.0.0.0:8020",
  ["Accept-Encoding"] = os.getenv("AE")    or "gzip, deflate, br",
  ["Accept-Language"] = os.getenv("ALANG") or "en-US,en;q=0.9",
}

-- master VM: выдаём tid потокам
local THREADS = {}
function setup(thread)
  thread:set("tid", #THREADS)   -- 0..N-1
  table.insert(THREADS, thread)
end

-- per-thread state
local tid, basepath, space, i_cur, stride

-- обычный Евклид (без побитовых опов)
local function gcd(a, b)
  if a < 0 then a = -a end
  if b < 0 then b = -b end
  while b ~= 0 do
    a, b = b, a % b
  end
  return a
end

function init(args)
  tid = tonumber(wrk.thread:get("tid")) or 0

  basepath = "/api/v2/pagedata"
           .. "?project[id]=" .. project_id
           .. "&domain="      .. domain
           .. "&language="    .. language
           .. "&choice="

  space = i_max - i_min + 1
  if space < 1 then space = 1 end

  -- старт потока разнесём по диапазону
  i_cur = i_min + (tid % space)
  if i_cur > i_max then i_cur = i_min end

  -- шаг потока: нечётный, взаимно простой со space
  stride = 2 * tid + 1
  if stride <= 0 then stride = 1 end
  stride = stride % space
  if stride == 0 then stride = 1 end
  while gcd(stride, space) ~= 1 do
    stride = (stride + 2) % space
    if stride == 0 then stride = 1 end
  end
end

request = function()
  local path = basepath .. i_cur

  -- циклический инкремент
  i_cur = i_cur + stride
  if i_cur > i_max then
    i_cur = i_cur - space
  end

  return wrk.format(nil, path)
end
