feat: improve API-driven standalone update reliability - #13904
Conversation
nic-6443
left a comment
There was a problem hiding this comment.
Minor suggestions have been submitted, and most of the code LGTM
There was a problem hiding this comment.
🟡 Changes recommended
Startup restoration is discarded, persisted-format upgrades are incompatible, and valid configurations can cause waits to time out permanently.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Improves API-driven standalone configuration reliability through worker-level application tracking, synchronous restoration, and efficient shared-memory polling.
Changes:
- Adds
waitsupport with worker/subsystem digest reporting. - Introduces prefixed digest/config storage and startup restoration.
- Adds HTTP/stream and reload coverage.
File summaries
| File | Description |
|---|---|
apisix/admin/standalone.lua |
Implements waiting, status checks, storage, and restoration. |
apisix/admin/config_validate.lua |
Classifies resources by subsystem. |
apisix/core/config_yaml.lua |
Reports applied digests. |
apisix/core/config_local.lua |
Detects stream enablement. |
apisix/init.lua |
Reorders stream initialization. |
apisix/cli/config.lua |
Configures status shared memory. |
apisix/cli/ngx_tpl.lua |
Emits the new shared dictionary. |
t/APISIX.pm |
Adds test shared-memory configuration. |
t/admin/standalone-wait.t |
Tests waiting and reload behavior. |
Review details
- Files reviewed: 9/9 changed files
- Comments generated: 6
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| local function decode_config(stored) | ||
| local idx = str_find(stored, CONFIG_DIGEST_LENGTH_SEPARATOR, 1, true) | ||
| if not idx then | ||
| return nil, nil, "missing digest length prefix" |
There was a problem hiding this comment.
That's complete bullshit.
There is no proper workflow that allows you to perform a hot update for Lua. This update will only be available in the next minor version; if you want to upgrade, you must perform a full restart, because there is no viable incremental path.
Therefore, there is absolutely no possibility of retaining shdict. Nor is there any possibility of running both old and new versions of Lua scripts simultaneously.
What you're assuming will never happen; you have absolutely no understanding of how this project works or its programming model. Stop that nonsense.
|
|
||
| local function parse_wait_ms(ctx) | ||
| local args = core.request.get_uri_args(ctx) | ||
| local wait = args and tonumber(args.wait) |
There was a problem hiding this comment.
...Do you really understand Lua, or are you just speaking based on that ridiculous LLM hallucinations?
print(tonumber(nil)) -- nil
print(tonumber(true)) -- nil
print(tonumber({a=1,b=2})) -- nil
print(tonumber("1")) -- 1apache#13904 moved the shared-dict startup load out of config_yaml.lua and into standalone.lua, and the move brought back the log line that writes the whole stored configuration; re-applied the size-only form there. The conflicting config_yaml.lua block is gone with the move, and standalone.lua's locals carry both sides. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C5GT6bj61RNzRFifGouLTm
apache#13904 moved the shared-dict startup load out of config_yaml.lua and into standalone.lua, and the move brought back the log line that writes the whole stored configuration; re-applied the size-only form there. The conflicting config_yaml.lua block is gone with the move, and standalone.lua's locals carry both sides.
Description
This PR aims to improve the reliability of configuration updates in API-driven standalone mode by implementing the following measures:
A new "standalone-status" reporting mechanism has been added. Now, each subsystem on every worker will report the digest of its loaded configuration, down to the level of each entity type (
worker:<id>:<subsystem>:<entity_type> = <digest>). This information will indicate whether the new configuration has taken effect on each worker (e.g., the router tree will be reset; the consumer lrucache will be flushed), and so on.conf_versionvalue for each request; therefore, as long asconf_versionhas been updated, we can assume that the router has been rebuilt.The
PUT /apisix/admin/configsrequest now supports awaitparameter. It allows you to specify a value in milliseconds; APISIX will collect if configuration applied status during this wait period and report it to the client. It is based on the report on "standalone-status" mentioned above.200or202. A200status code indicates that the configuration has been accepted and loaded on each worker, while a202status code indicates that the configuration has been accepted but its loading status is not guaranteed.Refactor the configuration loading from
shdictto improve the configuration loading latency window for new workers (which may be restarted viareload). Configuration is now always loaded synchronously duringinit_workerand consumed immediately duringcore.config.new.Refactor the storage format of configurations in shdict, they are now always encoded as
<digest_len>\n<digest><raw_json>, combining the digest and JSON using a fixed-length prefix. This ensures concurrency safety while allowing timer-basedpolloperations to avoid having to parse large JSON data every time.All of the above changes are backward-compatible, and existing clients can work with them. Older clients do not send the
waitparameter, so they will not trigger the new waiting behavior. The other changes are internal refactoring improvements that do not break compatibility.Checklist