diff --git a/kong/concurrency.lua b/kong/concurrency.lua index 82bc5ad75fb4..58077d0aeed5 100644 --- a/kong/concurrency.lua +++ b/kong/concurrency.lua @@ -1,5 +1,6 @@ local resty_lock = require "resty.lock" local ngx_semaphore = require "ngx.semaphore" +local in_yieldable_phase = require("kong.tools.utils").in_yieldable_phase local type = type @@ -7,9 +8,6 @@ local error = error local pcall = pcall -local get_phase = ngx.get_phase - - local concurrency = {} @@ -91,7 +89,7 @@ function concurrency.with_coroutine_mutex(opts, fn) error("invalid value for opts.on_timeout", 2) end - if get_phase() == "init_worker" then + if not in_yieldable_phase() then return fn() end diff --git a/kong/tools/utils.lua b/kong/tools/utils.lua index 8b9c3bb9347d..d95a5adcbc85 100644 --- a/kong/tools/utils.lua +++ b/kong/tools/utils.lua @@ -1648,26 +1648,45 @@ function _M.sort_by_handler_priority(a, b) return prio_a > prio_b end -do +--- +-- Check if the phase is yieldable. +-- @tparam string phase the phase to check, if not specified then +-- the default value will be the current phase +-- @treturn boolean true if the phase is yieldable, false otherwise +local in_yieldable_phase do local get_phase = ngx.get_phase - local ngx_sleep = _G.native_ngx_sleep or ngx.sleep - local SLEEP_PHASES = { + -- https://github.com/openresty/lua-nginx-module/blob/c89469e920713d17d703a5f3736c9335edac22bf/src/ngx_http_lua_util.h#L35C10-L35C10 + local LUA_CONTEXT_YIELDABLE_PHASE = { rewrite = true, + server_rewrite = true, access = true, content = true, timer = true, + ssl_client_hello = true, ssl_certificate = true, ssl_session_fetch = true, - ssl_client_hello = true, preread = true, } + in_yieldable_phase = function(phase) + if LUA_CONTEXT_YIELDABLE_PHASE[phase or get_phase()] == nil then + return false + end + return true + end +end + +_M.in_yieldable_phase = in_yieldable_phase + +do + local ngx_sleep = _G.native_ngx_sleep or ngx.sleep + local YIELD_ITERATIONS = 1000 local counter = YIELD_ITERATIONS function _M.yield(in_loop, phase) - if ngx.IS_CLI or SLEEP_PHASES[phase or get_phase()] == nil then + if ngx.IS_CLI or not in_yieldable_phase(phase) then return end if in_loop then diff --git a/spec/02-integration/13-vaults/03-mock_spec.lua b/spec/02-integration/13-vaults/03-mock_spec.lua index d8e2c896bfa6..77508422afea 100644 --- a/spec/02-integration/13-vaults/03-mock_spec.lua +++ b/spec/02-integration/13-vaults/03-mock_spec.lua @@ -145,4 +145,26 @@ for _, strategy in helpers.each_strategy() do end) end) end) + + if strategy == "postgres" then + describe("ENV Vault #" .. strategy, function () + describe("Kong Start", function () + it("can resolve reference in init_phase", function () + helpers.setenv("TEST_ENV_VAULT_LOGLEVEL", "debug") + + assert(helpers.start_kong { + database = strategy, + prefix = helpers.test_conf.prefix, + nginx_conf = "spec/fixtures/custom_nginx.template", + vaults = "env", + log_level = "{vault://env/TEST_ENV_VAULT_LOGLEVEL}" + }) + + finally(function () + assert(helpers.stop_kong()) + end) + end) + end) + end) + end end