• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

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

90.24
/common/src/main/java/io/github/hyshmily/hotkey/autoconfigure/HotKeySchedulingConfiguration.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.autoconfigure;
17

18
import io.github.hyshmily.hotkey.Internal;
19
import io.github.hyshmily.hotkey.hotkeydetector.heavykeeper.Item;
20
import io.github.hyshmily.hotkey.hotkeydetector.heavykeeper.TopK;
21
import jakarta.annotation.PostConstruct;
22
import java.util.ArrayList;
23
import java.util.List;
24
import java.util.concurrent.ScheduledExecutorService;
25
import java.util.concurrent.TimeUnit;
26
import java.util.stream.Collectors;
27
import lombok.extern.slf4j.Slf4j;
28
import org.springframework.beans.factory.annotation.Qualifier;
29
import org.springframework.boot.autoconfigure.AutoConfiguration;
30
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
31
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
32

33
/**
34
 * Scheduled tasks for periodic TopK maintenance.
35
 *
36
 * <p>Handles decaying (fading) the HeavyKeeper counters and draining
37
 * expelled hot-key entries.  Uses {@link List List&#60;TopK&#62;} injection
38
 * to support both the app-side and Worker-side TopK instances when they
39
 * coexist in the same JVM.
40
 *
41
 * <p>Rather than relying on Spring's {@code @Scheduled} (which uses the
42
 * global single-threaded {@code taskScheduler}), tasks are submitted
43
 * directly to the shared {@code hotKeyScheduler} via {@link
44
 * ScheduledExecutorService#scheduleWithFixedDelay}.  This keeps HotKey's
45
 * maintenance tasks isolated from the host application's own scheduled
46
 * jobs.
47
 *
48
 * <p>Enabled by default; controlled via {@code hotkey.scheduling.enabled}.
49
 */
50
@Internal
51
@AutoConfiguration(after = HotKeyAutoConfiguration.class)
52
@ConditionalOnProperty(name = "hotkey.scheduling.enabled", havingValue = "true", matchIfMissing = true)
53
@ConditionalOnBean(TopK.class)
54
@Slf4j
4✔
55
public class HotKeySchedulingConfiguration {
56

57
  private final List<TopK> topKInstances;
58
  private final ScheduledExecutorService scheduler;
59

60
  public HotKeySchedulingConfiguration(
61
    List<TopK> topKInstances,
62
    @Qualifier("hotKeyScheduler") ScheduledExecutorService scheduler
63
  ) {
2✔
64
    this.topKInstances = topKInstances;
3✔
65
    this.scheduler = scheduler;
3✔
66
  }
1✔
67

68
  @PostConstruct
69
  void scheduleTasks() {
70
    scheduler.scheduleWithFixedDelay(this::cleanHotKeys, 20, 20, TimeUnit.SECONDS);
9✔
71
    scheduler.scheduleWithFixedDelay(this::drainExpelled, 10, 10, TimeUnit.SECONDS);
9✔
72
  }
1✔
73

74
  /**
75
   * Periodically decay the HeavyKeeper counters for all registered TopK instances.
76
   * Controlled by {@code hotkey.decay-period} (default 20 seconds).
77
   */
78
  void cleanHotKeys() {
79
    try {
80
      topKInstances.forEach(TopK::fading);
4✔
81
      log.debug("HeavyKeeper tick: decayed for {} TopK instance(s)", topKInstances.size());
7✔
82
    } catch (Exception e) {
×
83
      log.error("Scheduled cleanHotKeys failed", e);
×
84
    }
1✔
85
  }
1✔
86

87
  /**
88
   * Periodically drain expelled hot keys from all registered TopK instances.
89
   * Logs a truncated summary of up to 20 sample keys. Runs every 10 seconds.
90
   */
91
  void drainExpelled() {
92
    try {
93
      int totalDrained = 0;
2✔
94
      List<String> sampleKeys = new ArrayList<>();
4✔
95
      for (TopK topK : topKInstances) {
11✔
96
        List<Item> items = new ArrayList<>();
4✔
97
        topK.expelled().drainTo(items, 100_000);
6✔
98
        totalDrained += items.size();
5✔
99
        items.stream().map(Item::key).limit(20).forEach(sampleKeys::add);
12✔
100
      }
1✔
101
      if (totalDrained > 0) {
2✔
102
        String keys = sampleKeys.stream().limit(20).collect(Collectors.joining(","));
9✔
103
        boolean truncated = totalDrained > 20;
7✔
104
        log.info(
8✔
105
          "Drained {} expelled hot keys from {} TopK instance(s): {}{}",
106
          totalDrained,
6✔
107
          topKInstances.size(),
9✔
108
          keys,
109
          truncated ? "..." : ""
6✔
110
        );
111
      }
112
    } catch (Exception e) {
×
113
      log.error("Scheduled drainExpelled failed", e);
×
114
    }
1✔
115
  }
1✔
116
}
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