Skip to content

fix: Fix scale rule cache entity inconsistency(#6623) - #6973

Merged
dengliming merged 10 commits into
apache:masterfrom
juicewcode:fix/6623-scale-rule-cache-entity-consistency
Sep 17, 2026
Merged

dengliming merged 10 commits into
apache:masterfrom
juicewcode:fix/6623-scale-rule-cache-entity-consistency

Conversation

@juicewcode

Copy link
Copy Markdown
Contributor

Fixes #6623

ScaleRuleServiceImpl#create and update build ScaleRuleDO twice.

For create operations without an ID, each call to buildScaleRuleDO generates a new UUID. Therefore, the entity stored
in the cache may have a different ID from the entity inserted into the database.
For update operations, rebuilding the entity can also produce a different dateUpdated timestamp.

Changes

  • Reuse the original ScaleRuleDO after a successful create.
  • Reuse the after entity after a successful update.

Make sure that:

  • You have read the contribution guidelines.
  • You submit test cases (unit or integration tests) that back your changes.
  • Your local test passed ./mvnw clean install -Dmaven.javadoc.skip=true.

  - Reuse the persisted entity after create.
  - Reuse the updated entity after update.

@Aias00 Aias00 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reusing after fixes the double-build inconsistency, but update still leaves a stale cache entry when metricName changes. ScaleRuleCache is keyed by metricName, and the update path only puts the updated rule under the new key; it never removes the old metric-name key for the same id. After renaming a rule, getAllRules() can therefore return both the old cached rule and the updated one until cache reload/restart. Could you load the existing rule before update and remove the old metric-name key when it differs from the new one before adding the updated rule?

@juicewcode

Copy link
Copy Markdown
Contributor Author

Reusing after fixes the double-build inconsistency, but update still leaves a stale cache entry when metricName changes. ScaleRuleCache is keyed by metricName, and the update path only puts the updated rule under the new key; it never removes the old metric-name key for the same id. After renaming a rule, getAllRules() can therefore return both the old cached rule and the updated one until cache reload/restart. Could you load the existing rule before update and remove the old metric-name key when it differs from the new one before adding the updated rule?

PR #6975 is based on this cache consistency fix and additionally removes the stale cache entry when a rule's metricName
changes. It also includes ID-based cache eviction for deletion and preserves the database id when caching newly created
rules.

This PR can be closed in favor of PR #6975.

juicewcode added a commit to juicewcode/shenyu that referenced this pull request Aug 27, 2026
  - Base the change on the cache consistency fix from pr apache#6973
  - Remove stale cache entries by database rule id during deletion
  - Remove the old metric-name cache key when a rule is renamed
  - Keep the persisted entity id when caching newly created rules

@Aias00 Aias00 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review: fix: Fix scale rule cache entity inconsistency (#6623)

Reviewed at head ce35b5f. The create-side change is good, but the update-path stale-key bug I flagged earlier is still present, so I'm requesting changes.

Fixed (good): create now caches the same scaleRuleDO instance it inserts (addOrUpdateRuleToCache(scaleRuleDO), line 10) instead of rebuilding a second ScaleRuleDO. This removes the double-build inconsistency where the cached object could differ from the persisted row.

Still broken — update leaves a stale metricName key: the update path (lines 15-20) is now addOrUpdateRuleToCache(after) where after = buildScaleRuleDO(scaleRuleDTO). ScaleRuleCache is keyed by rule.getMetricName() (ruleCache.put(rule.getMetricName(), rule), see ScaleRuleCache.addOrUpdateRuleToCache), and getAllRules() returns ruleCache.values(). When a rule's metricName changes, update only puts the rule under the new metricName key; the entry under the old metricName key is never removed. getAllRules() therefore returns both the old (stale) and the updated rule until a cache reload/restart — a correctness bug.

Requested fix: in update, load the existing rule before the update and remove the old metricName key when it differs, e.g.:

final ScaleRuleDO before = scaleRuleMapper.selectByPrimaryKey(scaleRuleDTO.getId());
final ScaleRuleDO after = ScaleRuleDO.buildScaleRuleDO(scaleRuleDTO);
int rows = scaleRuleMapper.updateByPrimaryKey(after);
if (rows > 0) {
    if (Objects.nonNull(before) && !Objects.equals(before.getMetricName(), after.getMetricName())) {
        scaleRuleCache.removeRulesFromCache(List.of(before.getMetricName()));
    }
    scaleRuleCache.addOrUpdateRuleToCache(after);
}

(Note: #6975 already contains exactly this removal; if you intend #6975 to always land together with this PR, please state the dependency explicitly so reviewers don't merge #6973 standalone — otherwise the stale-key bug ships on its own.)

Please add the old-key removal (or confirm #6975 will always precede this) and I'll approve.

@juicewcode

Copy link
Copy Markdown
Contributor Author

Review: fix: Fix scale rule cache entity inconsistency (#6623)

Reviewed at head ce35b5f. The create-side change is good, but the update-path stale-key bug I flagged earlier is still present, so I'm requesting changes.

Fixed (good): create now caches the same scaleRuleDO instance it inserts (addOrUpdateRuleToCache(scaleRuleDO), line 10) instead of rebuilding a second ScaleRuleDO. This removes the double-build inconsistency where the cached object could differ from the persisted row.

Still broken — update leaves a stale metricName key: the update path (lines 15-20) is now addOrUpdateRuleToCache(after) where after = buildScaleRuleDO(scaleRuleDTO). ScaleRuleCache is keyed by rule.getMetricName() (ruleCache.put(rule.getMetricName(), rule), see ScaleRuleCache.addOrUpdateRuleToCache), and getAllRules() returns ruleCache.values(). When a rule's metricName changes, update only puts the rule under the new metricName key; the entry under the old metricName key is never removed. getAllRules() therefore returns both the old (stale) and the updated rule until a cache reload/restart — a correctness bug.

Requested fix: in update, load the existing rule before the update and remove the old metricName key when it differs, e.g.:

final ScaleRuleDO before = scaleRuleMapper.selectByPrimaryKey(scaleRuleDTO.getId());
final ScaleRuleDO after = ScaleRuleDO.buildScaleRuleDO(scaleRuleDTO);
int rows = scaleRuleMapper.updateByPrimaryKey(after);
if (rows > 0) {
    if (Objects.nonNull(before) && !Objects.equals(before.getMetricName(), after.getMetricName())) {
        scaleRuleCache.removeRulesFromCache(List.of(before.getMetricName()));
    }
    scaleRuleCache.addOrUpdateRuleToCache(after);
}

(Note: #6975 already contains exactly this removal; if you intend #6975 to always land together with this PR, please state the dependency explicitly so reviewers don't merge #6973 standalone — otherwise the stale-key bug ships on its own.)

Please add the old-key removal (or confirm #6975 will always precede this) and I'll approve.

Thanks for the review.
I have added the requested fix in the update path. The existing scale rule is loaded before the update, and when its
metricName changes, the old metricName cache entry is removed before caching the updated rule.

Aias00
Aias00 previously approved these changes Sep 4, 2026

@Aias00 Aias00 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review: #6973 fix: Fix scale rule cache entity inconsistency (#6623)

Reviewed at head 995d908. The blocking issue from the prior REQUEST_CHANGES is now fixed — approving.

Previously flagged (now fixed): the update path left a stale metricName cache key when a rule's metric name changed. ScaleRuleCache is keyed by rule.getMetricName() and getAllRules() returns ruleCache.values(), so the old key would linger until a reload/restart.

Current fix (verified):

  • update() now selects before = scaleRuleMapper.selectByPrimaryKey(scaleRuleDTO.getId()), and when before.getMetricName() differs from after.getMetricName() it removes the stale key via scaleRuleCache.removeRulesFromCache(List.of(before.getMetricName())) before addOrUpdateRuleToCache(after).
  • create() now caches the same scaleRuleDO instance it inserts (with the generated id) instead of rebuilding a second DTO, removing the double-build inconsistency.

Verification:

  • ScaleRuleCache.removeRulesFromCache(List<String> metricNames) signature matches the call. The cache is keyed by metric name (getRuleByMetricName / removeRulesFromCache both take metric names), so the old-key removal is effective and getAllRules() will no longer return a stale rule after a metricName change.

Decision

APPROVE. The prior blocking concern is resolved and the change is consistent with the related #6975/#6974 scale-rule cache series.

@dengliming
dengliming merged commit ca9d008 into apache:master Sep 17, 2026
37 checks passed
Aias00 added a commit that referenced this pull request Sep 28, 2026
* fix: Fix scale rule cache eviction by using rule IDs.
  - Add cache eviction by database primary key.
  - Keep metric names as cache keys.
  - Add scale rule deletion to remove entries by rule ID.

* fix: Fix scale rule cache entity inconsistency.

  - Reuse the persisted entity after create.
  - Reuse the updated entity after update.

* fix: evict scale rule cache entries by rule id

  - Base the change on the cache consistency fix from pr #6973
  - Remove stale cache entries by database rule id during deletion
  - Remove the old metric-name cache key when a rule is renamed
  - Keep the persisted entity id when caching newly created rules

* fix: remove scale rule cache entries by ID

---------

Co-authored-by: aias00 <liuhongyu@apache.org>
eye-gu pushed a commit to eye-gu/shenyu that referenced this pull request Sep 30, 2026
* fix: Fix scale rule cache entity inconsistency.

  - Reuse the persisted entity after create.
  - Reuse the updated entity after update.

* fix: remove stale scale rule cache key on update

---------

Co-authored-by: aias00 <liuhongyu@apache.org>
Co-authored-by: Liming Deng <liming.d.pro@gmail.com>
eye-gu pushed a commit to eye-gu/shenyu that referenced this pull request Sep 30, 2026
…ache#6975)

* fix: Fix scale rule cache eviction by using rule IDs.
  - Add cache eviction by database primary key.
  - Keep metric names as cache keys.
  - Add scale rule deletion to remove entries by rule ID.

* fix: Fix scale rule cache entity inconsistency.

  - Reuse the persisted entity after create.
  - Reuse the updated entity after update.

* fix: evict scale rule cache entries by rule id

  - Base the change on the cache consistency fix from pr apache#6973
  - Remove stale cache entries by database rule id during deletion
  - Remove the old metric-name cache key when a rule is renamed
  - Keep the persisted entity id when caching newly created rules

* fix: remove scale rule cache entries by ID

---------

Co-authored-by: aias00 <liuhongyu@apache.org>
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.

[BUG] ScaleRuleServiceImpl.create caches a rule with a different ID than the one inserted (double UUID generation)

3 participants