• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Build has been canceled!

Hyshmily / hotkey / 28637103998

03 Jul 2026 03:48AM UTC coverage: 90.399% (-0.2%) from 90.63%
28637103998

push

github

Hyshmily
fix: add packaging to gitignore, fix flaky jitter test, update docs references

Signed-off-by: Hyshmily <cxm8607@outlook.com>

1264 of 1461 branches covered (86.52%)

Branch coverage included in aggregate %.

3604 of 3924 relevant lines covered (91.85%)

4.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.0
/common/src/main/java/io/github/hyshmily/hotkey/sharding/RingManager.java
1
/*
2
 * Copyright 2026 Hyshmily. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package io.github.hyshmily.hotkey.sharding;
17

18
import io.github.hyshmily.hotkey.Internal;
19
import java.util.Set;
20
import java.util.function.IntConsumer;
21
import lombok.Getter;
22
import lombok.Setter;
23

24
/**
25
 * Manages the consistent-hash ring for Worker shard routing.
26
 *
27
 * <p>The ring is rebuilt automatically from the live Worker set reported
28
 * by {@link ClusterHealthView} on each reconciliation cycle.
29
 */
30
@Internal
31
public class RingManager {
32

33
  @Getter
34
  private final ConsistentHashRing ring;
35

36
  @Getter
37
  private final int virtualNodeCount;
38

39
  @Setter
40
  private IntConsumer onRingReconciled;
41

42
  /**
43
   * Creates a ring manager with the given virtual-node count.
44
   *
45
   * @param virtualNodeCount virtual copies per physical shard on the ring
46
   */
47
  public RingManager(int virtualNodeCount) {
2✔
48
    this.virtualNodeCount = virtualNodeCount;
3✔
49
    this.ring = new ConsistentHashRing(virtualNodeCount);
6✔
50
  }
1✔
51

52
  /**
53
   * Rebuild the ring from the current cluster health view.
54
   *
55
   * @param healthView the current cluster health view; must not be {@code null}
56
   * @throws NullPointerException if {@code healthView} is {@code null}
57
   */
58
  public synchronized void reconcileFromHealthView(ClusterHealthView healthView) {
59
    Set<String> alive = healthView.getAliveWorkerIds();
3✔
60
    if (!alive.equals(ring.getNodes())) {
6✔
61
      ring.rebuild(alive);
4✔
62
      if (onRingReconciled != null) {
3✔
63
        onRingReconciled.accept(alive.size());
5✔
64
      }
65
    }
66
  }
1✔
67

68
  /**
69
   * Return the current set of nodes on the ring.
70
   *
71
   * @return the set of live node identifiers
72
   */
73
  public Set<String> getCurrentNodes() {
74
    return ring.getNodes();
4✔
75
  }
76

77
  /**
78
   * Return the number of physical nodes currently on the ring.
79
   *
80
   * @return the node count
81
   */
82
  public int nodeCount() {
83
    return ring.nodeCount();
4✔
84
  }
85

86
  /**
87
   * Route a key to the responsible Worker node.
88
   *
89
   * @param key        the cache key to route; must not be {@code null}
90
   * @param healthView the current cluster health view; must not be {@code null}
91
   * @return the node identifier that owns the key, or {@code null} if no node is available
92
   * @throws NullPointerException if {@code key} or {@code healthView} is {@code null}
93
   */
94
  public String routeNode(String key, ClusterHealthView healthView) {
95
    Set<String> alive = healthView.getAliveWorkerIds();
3✔
96
    return ring.locateNode(key, alive::contains);
10✔
97
  }
98

99
  /**
100
   * Route a key to its target Worker node, using a pre-snapshotted alive-set
101
   * supplied by the caller. This avoids re-fetching {@link
102
   * ClusterHealthView#getAliveWorkerIds()} per key inside hot loops.
103
   *
104
   * @param key        the cache key to route
105
   * @param aliveNodes the already-snapshotted set of alive Worker ids; must not
106
   *                   be {@code null} or modified concurrently
107
   * @return the target Worker node id, or {@code null} if no alive nodes
108
   */
109
  public String routeNode(String key, Set<String> aliveNodes) {
110
    if (aliveNodes == null || aliveNodes.isEmpty()) {
5!
111
      return null;
×
112
    }
113
    return ring.locateNode(key, aliveNodes::contains);
10✔
114
  }
115
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc