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

Hyshmily / hotkey / 28356107387

29 Jun 2026 07:35AM UTC coverage: 91.168% (-0.01%) from 91.178%
28356107387

push

github

Hyshmily
test : fix CI tests

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

1276 of 1461 branches covered (87.34%)

Branch coverage included in aggregate %.

10 of 10 new or added lines in 4 files covered. (100.0%)

117 existing lines in 15 files now uncovered.

3596 of 3883 relevant lines covered (92.61%)

4.24 hits per line

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

67.74
/common/src/main/java/io/github/hyshmily/hotkey/util/TimeSource.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.util;
17

18
import java.util.concurrent.atomic.AtomicBoolean;
19
import java.util.concurrent.atomic.AtomicInteger;
20
import lombok.extern.slf4j.Slf4j;
21

22
/**
23
 * Performance-optimized clock source that caches {@link System#currentTimeMillis()}
24
 * on a low-frequency background thread (every 5ms) to avoid the cost of a
25
 * {@code native} call on every read via {@link #currentTimeMillis()}.
26
 * <p>
27
 * The background daemon thread is started once via {@link #start()} and runs
28
 * for the lifetime of the JVM.  If the thread is interrupted it silently falls
29
 * back to calling {@link System#currentTimeMillis()} directly.
30
 * <p>
31
 * All time-sensitive components in the hot-path (expiry, rate limiting, circuit
32
 * breaker) use this source instead of {@code System.currentTimeMillis()}.
33
 */
34
@Slf4j
3✔
35
public final class TimeSource {
36

37
  private static volatile long currentMillis = System.currentTimeMillis();
2✔
38
  private static final AtomicBoolean threadRunning = new AtomicBoolean(false);
5✔
39
  private static final AtomicInteger threadTryCount = new AtomicInteger(0);
6✔
40
  private static final int THREAD_TRY_MAX = 3;
41

42
  /**
43
   * Start the background clock-cache thread.  Idempotent after the thread is
44
   * running.  If the thread dies unexpectedly it will be restarted up to
45
   * {@link #THREAD_TRY_MAX} times with a 1-second delay between attempts.
46
   * Called automatically during {@code HotKeyFacadeAutoConfiguration}
47
   * initialisation.
48
   */
49
  @SuppressWarnings("BusyWait")
50
  public static void start() {
51
    if (threadTryCount.incrementAndGet() <= THREAD_TRY_MAX && threadRunning.compareAndSet(false, true)) {
9✔
52
      Thread t = new HotKeyThreadFactory("TimeSource").newThread(() -> {
7✔
53
        while (threadRunning.get()) {
3!
54
          currentMillis = System.currentTimeMillis();
2✔
55
          try {
56
            Thread.sleep(5);
2✔
57
          } catch (InterruptedException ignored) {
×
58
            threadRunning.set(false);
×
59
          }
1✔
60
        }
61
      });
×
62
      t.setUncaughtExceptionHandler((th, ex) -> {
3✔
UNCOV
63
        log.error("TimeSource thread terminated unexpectedly, will restart after 1s.", ex);
×
UNCOV
64
        threadRunning.set(false);
×
65
        try {
UNCOV
66
          Thread.sleep(1000);
×
UNCOV
67
        } catch (InterruptedException ignored) {}
×
68
        start();
×
UNCOV
69
      });
×
70
      t.start();
2✔
71
    }
72
  }
1✔
73

74
  /**
75
   * Returns the current time in milliseconds since the epoch.
76
   * <p>
77
   * When the background thread is running, this returns the cached value
78
   * updated every 5ms — avoiding a {@code native} JNI call on every read.
79
   * Falls back to {@link System#currentTimeMillis()} if the thread has not
80
   * been started or was interrupted.
81
   *
82
   * @return current time in milliseconds (epoch-based)
83
   */
84
  public static long currentTimeMillis() {
85
    return threadRunning.get() ? currentMillis : System.currentTimeMillis();
7✔
86
  }
87

88
  private TimeSource() {}
89
}
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