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

Hyshmily / hotkey / 28290463292

27 Jun 2026 01:22PM UTC coverage: 91.227% (-0.7%) from 91.882%
28290463292

push

github

Hyshmily
test: fix CI tests

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

1250 of 1427 branches covered (87.6%)

Branch coverage included in aggregate %.

3544 of 3828 relevant lines covered (92.58%)

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

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

55
  private final List<TopK> topKInstances;
56
  private final ScheduledExecutorService scheduler;
57

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

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

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

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