Skip to content

Commit f1970c5

Browse files
committed
Merge branch 'master' into java8-main
2 parents 5bab136 + d4bab8e commit f1970c5

File tree

7 files changed

+225
-4
lines changed

7 files changed

+225
-4
lines changed

metrics-ebean/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<parent>
44
<artifactId>avaje-metrics-parent</artifactId>
55
<groupId>io.avaje</groupId>
6-
<version>9.3-SNAPSHOT</version>
6+
<version>9.3-RC1</version>
77
</parent>
88
<modelVersion>4.0.0</modelVersion>
99

metrics-graphite/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<parent>
55
<artifactId>avaje-metrics-parent</artifactId>
66
<groupId>io.avaje</groupId>
7-
<version>9.3-SNAPSHOT</version>
7+
<version>9.3-RC1</version>
88
</parent>
99

1010
<artifactId>avaje-metrics-graphite</artifactId>

metrics/pom.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<parent>
44
<groupId>io.avaje</groupId>
55
<artifactId>avaje-metrics-parent</artifactId>
6-
<version>9.3-SNAPSHOT</version>
6+
<version>9.3-RC1</version>
77
</parent>
88

99
<artifactId>avaje-metrics</artifactId>
@@ -20,6 +20,12 @@
2020
<version>1.7.36</version>
2121
</dependency>
2222

23+
<dependency>
24+
<groupId>io.avaje</groupId>
25+
<artifactId>avaje-applog</artifactId>
26+
<version>1.0</version>
27+
</dependency>
28+
2329
<dependency>
2430
<groupId>io.avaje</groupId>
2531
<artifactId>junit</artifactId>
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package io.avaje.metrics;
2+
3+
import io.avaje.applog.AppLog;
4+
5+
import java.util.Objects;
6+
import java.util.concurrent.*;
7+
import java.util.concurrent.locks.ReentrantLock;
8+
9+
import static java.lang.System.Logger.Level.ERROR;
10+
11+
final class DScheduledTask implements ScheduledTask {
12+
13+
private static final System.Logger log = AppLog.getLogger(DScheduledTask.class);
14+
15+
static final class DBuilder implements Builder {
16+
private int initial = 60;
17+
private int delay = 60;
18+
private TimeUnit timeUnit = TimeUnit.SECONDS;
19+
20+
private Runnable task;
21+
22+
@Override
23+
public DBuilder schedule(int initial, int delay, TimeUnit timeUnit) {
24+
this.initial = initial;
25+
this.delay = delay;
26+
this.timeUnit = timeUnit;
27+
return this;
28+
}
29+
30+
@Override
31+
public DBuilder task(Runnable task) {
32+
this.task = task;
33+
return this;
34+
}
35+
36+
@Override
37+
public DScheduledTask build() {
38+
Objects.requireNonNull(task, "task is required");
39+
return new DScheduledTask(task, initial, delay, timeUnit);
40+
}
41+
}
42+
43+
44+
private final ReentrantLock activeLock = new ReentrantLock();
45+
private final Runnable task;
46+
private final int initial;
47+
private final int delay;
48+
private final TimeUnit timeUnit;
49+
50+
private final ScheduledExecutorService executor;
51+
private ScheduledFuture<?> backgroundTask;
52+
53+
DScheduledTask(Runnable task, int initial, int delay, TimeUnit timeUnit) {
54+
this.task = task;
55+
this.initial = initial;
56+
this.delay = delay;
57+
this.timeUnit = timeUnit;
58+
this.executor = Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory("schTask"));
59+
}
60+
61+
@Override
62+
public void start() {
63+
this.backgroundTask = executor.scheduleWithFixedDelay(this::runTask, initial, delay, timeUnit);
64+
}
65+
66+
@Override
67+
public boolean cancel(boolean mayInterruptIfRunning) {
68+
return this.backgroundTask.cancel(mayInterruptIfRunning);
69+
}
70+
71+
/**
72+
* Wait for the task to complete if it is actively running .
73+
*/
74+
@Override
75+
public void waitIfRunning(long timeout, TimeUnit timeUnit) {
76+
try {
77+
if (activeLock.tryLock(timeout, timeUnit)) {
78+
activeLock.unlock();
79+
}
80+
} catch (InterruptedException e) {
81+
Thread.currentThread().interrupt();
82+
log.log(ERROR, "interrupted while waiting for task to complete", e);
83+
}
84+
}
85+
86+
private void runTask() {
87+
activeLock.lock();
88+
try {
89+
task.run();
90+
} catch (Throwable e) {
91+
log.log(ERROR, "Error stopping task", e);
92+
} finally {
93+
activeLock.unlock();
94+
}
95+
}
96+
97+
private static final class DaemonThreadFactory implements ThreadFactory {
98+
99+
private final String name;
100+
101+
DaemonThreadFactory(String name) {
102+
this.name = name;
103+
}
104+
105+
@Override
106+
public Thread newThread(Runnable r) {
107+
Thread t = new Thread(r, name);
108+
t.setDaemon(true);
109+
return t;
110+
}
111+
}
112+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package io.avaje.metrics;
2+
3+
import java.util.concurrent.TimeUnit;
4+
5+
/**
6+
* A ScheduledTask that can run periodically, be cancelled, and
7+
* also aware of when its running (for use with Lambda).
8+
* <p>
9+
* The ScheduledTask will use a Daemon thread and expect to just
10+
* stop on JVM shutdown.
11+
*/
12+
public interface ScheduledTask {
13+
14+
/**
15+
* Return the Builder for a ScheduledTask.
16+
*/
17+
static Builder builder() {
18+
return new DScheduledTask.DBuilder();
19+
}
20+
21+
/**
22+
* Start the scheduled task.
23+
*/
24+
void start();
25+
26+
/**
27+
* Cancel the scheduled task.
28+
*/
29+
boolean cancel(boolean mayInterruptIfRunning);
30+
31+
/**
32+
* If the task is actively running wait for the task to complete.
33+
*/
34+
void waitIfRunning(long timeout, TimeUnit timeUnit);
35+
36+
/**
37+
* The builder for a ScheduledTask.
38+
*/
39+
interface Builder {
40+
41+
/**
42+
* Specify the schedule to run the task.
43+
* @param initial The initial delay
44+
* @param delay The delay between task execution
45+
* @param timeUnit The timeunit of the scheduled delay
46+
*/
47+
Builder schedule(int initial, int delay, TimeUnit timeUnit);
48+
49+
/**
50+
* Specify the task to execute periodically according to the schedule.
51+
*/
52+
Builder task(Runnable task);
53+
54+
/**
55+
* Build the scheduled task.
56+
*/
57+
ScheduledTask build();
58+
}
59+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package io.avaje.metrics;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import java.util.concurrent.TimeUnit;
6+
import java.util.concurrent.atomic.AtomicLong;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
10+
class ScheduledTaskTest {
11+
12+
@Test
13+
void runIt() throws InterruptedException {
14+
15+
ScheduledTask task = ScheduledTask.builder()
16+
.schedule(1, 1, TimeUnit.MILLISECONDS)
17+
.task(ScheduledTaskTest::hello)
18+
.build();
19+
20+
assertThat(counter.get()).isEqualTo(0);
21+
System.out.println("start...");
22+
task.start();
23+
Thread.sleep(5);
24+
assertThat(counter.get()).isGreaterThan(0);
25+
26+
task.waitIfRunning(10, TimeUnit.SECONDS);
27+
Thread.sleep(30);
28+
29+
System.out.println("cancel...");
30+
task.cancel(false);
31+
long after0 = counter.get();
32+
assertThat(after0).isGreaterThan(1);
33+
Thread.sleep(10);
34+
long after1 = counter.get();
35+
assertThat(after1).isEqualTo(after0);
36+
System.out.println("done");
37+
}
38+
39+
private static final AtomicLong counter = new AtomicLong();
40+
41+
private static void hello() {
42+
System.out.println("hi " + counter.incrementAndGet());
43+
}
44+
}

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
<groupId>io.avaje</groupId>
1111
<artifactId>avaje-metrics-parent</artifactId>
12-
<version>9.3-SNAPSHOT</version>
12+
<version>9.3-RC1</version>
1313
<packaging>pom</packaging>
1414

1515
<url>https://avaje-metrics.github.io</url>

0 commit comments

Comments
 (0)