Skip to content

feat: improve API-driven standalone update reliability - #13904

Merged
bzp2010 merged 14 commits into
apache:masterfrom
bzp2010:bzp/feat-improve-a-s-sync-reliability
Sep 2, 2026
Merged

feat: improve API-driven standalone update reliability#13904
bzp2010 merged 14 commits into
apache:masterfrom
bzp2010:bzp/feat-improve-a-s-sync-reliability

Conversation

@bzp2010

@bzp2010 bzp2010 commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

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.

    • Technically, a worker reporting a digest simply indicates that the configuration has been loaded but does not necessarily reflect that the router has actually been rebuilt. The router is passively rebuilt based on differences in the conf_version value for each request; therefore, as long as conf_version has been updated, we can assume that the router has been rebuilt.
  • The PUT /apisix/admin/configs request now supports a wait parameter. 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.

    • This API now returns a 200 or 202. A 200 status code indicates that the configuration has been accepted and loaded on each worker, while a 202 status code indicates that the configuration has been accepted but its loading status is not guaranteed.
    • Configuration loading is expected to complete within 1 second, as each worker has a timer-driven loading mechanism. However, this may take longer under certain special circumstances (such as extreme CPU load).
  • Refactor the configuration loading from shdict to improve the configuration loading latency window for new workers (which may be restarted via reload). Configuration is now always loaded synchronously during init_worker and consumed immediately during core.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-based poll operations to avoid having to parse large JSON data every time.

    • Previously, the digest was stored within the JSON, requiring the JSON to be fully parsed each time—which could be as large as 10 MB—representing a significant overhead. Now that the digest is encoded outside the JSON, there is no longer a need to parse the JSON in advance.

All of the above changes are backward-compatible, and existing clients can work with them. Older clients do not send the wait parameter, so they will not trigger the new waiting behavior. The other changes are internal refactoring improvements that do not break compatibility.

Checklist

  • I have explained the need for this PR and the problem it solves
  • I have explained the changes or the new features added to this PR
  • I have added tests corresponding to this change
  • I have updated the documentation to reflect this change
  • I have verified that this change is backward compatible (If not, please discuss on the APISIX mailing list first)

@bzp2010 bzp2010 self-assigned this Sep 1, 2026
@bzp2010
bzp2010 marked this pull request as ready for review September 1, 2026 17:06
Comment thread apisix/admin/standalone.lua Outdated
Comment thread apisix/core/config_yaml.lua Outdated
nic-6443
nic-6443 previously approved these changes Sep 2, 2026

@nic-6443 nic-6443 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor suggestions have been submitted, and most of the code LGTM

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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 wait support 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.

Comment on lines +77 to +80
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"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...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"))  -- 1

Comment thread apisix/admin/standalone.lua Outdated
Comment thread apisix/admin/standalone.lua
Comment thread apisix/admin/standalone.lua
Comment thread apisix/core/config_local.lua Outdated
nic-6443
nic-6443 previously approved these changes Sep 2, 2026
AlinsRan
AlinsRan previously approved these changes Sep 2, 2026
@bzp2010
bzp2010 merged commit 15a4381 into apache:master Sep 2, 2026
25 checks passed
@bzp2010
bzp2010 deleted the bzp/feat-improve-a-s-sync-reliability branch September 2, 2026 09:41
@bzp2010
bzp2010 restored the bzp/feat-improve-a-s-sync-reliability branch September 2, 2026 09:41
AlinsRan added a commit to AlinsRan/apisix that referenced this pull request Sep 3, 2026
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.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C5GT6bj61RNzRFifGouLTm
AlinsRan added a commit to AlinsRan/apisix that referenced this pull request Sep 3, 2026
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants