Skip to content

Commit a8db0fa

Browse files
authored
Limit camara connection retries to 50Hz (#759)
1 parent cf07b78 commit a8db0fa

File tree

6 files changed

+43
-16
lines changed

6 files changed

+43
-16
lines changed

core/src/main/java/edu/wpi/grip/core/sources/CameraSource.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import edu.wpi.grip.core.sockets.SocketHints;
1010
import edu.wpi.grip.core.util.ExceptionWitness;
1111
import edu.wpi.grip.core.util.service.AutoRestartingService;
12+
import edu.wpi.grip.core.util.service.CooldownRestartPolicy;
1213
import edu.wpi.grip.core.util.service.LoggingListener;
1314
import edu.wpi.grip.core.util.service.RestartableService;
1415

@@ -185,7 +186,8 @@ public void copyNewMat(Mat matToCopy) {
185186
public void updatesComplete() {
186187
eventBus.post(new SourceHasPendingUpdateEvent(CameraSource.this));
187188
}
188-
}, getExceptionWitness()::clearException));
189+
}, getExceptionWitness()::clearException),
190+
new CooldownRestartPolicy(20, TimeUnit.MILLISECONDS)); // 50Hz retry rate
189191

190192
this.cameraService.addListener(new Listener() {
191193
@Override

core/src/main/java/edu/wpi/grip/core/util/service/AutoRestartingService.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import java.util.concurrent.TimeoutException;
1616
import java.util.concurrent.atomic.AtomicBoolean;
1717
import java.util.function.Supplier;
18+
import java.util.logging.Level;
19+
import java.util.logging.Logger;
1820

1921
import static com.google.common.base.Preconditions.checkNotNull;
2022

@@ -67,7 +69,7 @@ public AutoRestartingService(final Supplier<S> factory,
6769
* @param factory This should always supply a new instance of the service that can be restarted.
6870
*/
6971
public AutoRestartingService(final Supplier<S> factory) {
70-
this(factory, () -> true);
72+
this(factory, ServiceRestartPolicy.IMMEDIATE);
7173
}
7274

7375
/**
@@ -203,8 +205,18 @@ private final class RestartListener extends Listener {
203205

204206
@Override
205207
public void failed(final State from, final Throwable failure) {
206-
if (policy.shouldRestart()) {
208+
final long delay = policy.restartDelay();
209+
if (delay <= 0) {
207210
startAsync(false);
211+
} else {
212+
try {
213+
Thread.sleep(TimeUnit.NANOSECONDS.toMillis(delay));
214+
startAsync(false);
215+
} catch (InterruptedException e) {
216+
Logger.getLogger(AutoRestartingService.class.getName())
217+
.log(Level.SEVERE, "Could not sleep for " + delay + "ns", e);
218+
Thread.currentThread().interrupt();
219+
}
208220
}
209221
}
210222
}

core/src/main/java/edu/wpi/grip/core/util/service/CooldownRestartPolicy.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ public void notifyRestart() {
4646
}
4747

4848
@Override
49-
public boolean shouldRestart() {
50-
return stopwatch.elapsed(timeUnit) > interval;
49+
public long restartDelay() {
50+
return timeUnit.toNanos(interval) - stopwatch.elapsed(TimeUnit.NANOSECONDS);
5151
}
5252

5353
}

core/src/main/java/edu/wpi/grip/core/util/service/ServiceRestartPolicy.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,22 @@
66
@FunctionalInterface
77
public interface ServiceRestartPolicy {
88

9+
/**
10+
* A restart policy that has a service restart immediately.
11+
*/
12+
ServiceRestartPolicy IMMEDIATE = () -> 0L;
13+
914
/**
1015
* Policy might want to keep track of when the latest restarts have happened.
1116
*/
1217
default void notifyRestart() {
13-
/* no-op */
18+
/* no-op */
1419
}
1520

16-
boolean shouldRestart();
21+
/**
22+
* When the service should restart, in nanoseconds from the point when the service failed. A value
23+
* less than or equal to zero means an immediate restart.
24+
*/
25+
long restartDelay();
1726

1827
}

core/src/test/java/edu/wpi/grip/core/util/service/AutoRestartingServiceTest.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,10 @@ public void tearDown() {
7777

7878
@Test
7979
public void testStartStopMultipleTimes() throws InterruptedException {
80-
final RecordingSupplier recordingSupplier = new RecordingSupplier(WaitOnRunService::new);
80+
final RecordingSupplier<WaitOnRunService> recordingSupplier =
81+
new RecordingSupplier<>(WaitOnRunService::new);
8182
final AutoRestartingService<WaitOnRunService> restartingService =
82-
new AutoRestartingService<>(recordingSupplier, () -> false);
83+
new AutoRestartingService<>(recordingSupplier, ServiceRestartPolicy.IMMEDIATE);
8384

8485
assertFalse("Start should not have been called", restartingService.getDelegate().startUpCalled);
8586

@@ -117,9 +118,10 @@ public void testStartStopMultipleTimes() throws InterruptedException {
117118

118119
@Test
119120
public void testCallStartTwiceFails() throws InterruptedException {
120-
final RecordingSupplier recordingSupplier = new RecordingSupplier<>(WaitOnRunService::new);
121+
final RecordingSupplier<WaitOnRunService> recordingSupplier =
122+
new RecordingSupplier<>(WaitOnRunService::new);
121123
final AutoRestartingService<WaitOnRunService> restartingService =
122-
new AutoRestartingService<>(recordingSupplier, () -> false);
124+
new AutoRestartingService<>(recordingSupplier, ServiceRestartPolicy.IMMEDIATE);
123125

124126
restartingService.startAsync();
125127
try {
@@ -141,10 +143,10 @@ public void testCallStartTwiceFails() throws InterruptedException {
141143

142144
@Test
143145
public void testServiceStaysRunningIfThrowOnRunning() throws InterruptedException {
144-
final RecordingSupplier recordingSupplier =
146+
final RecordingSupplier<WaitThenThrowOnRunService> recordingSupplier =
145147
new RecordingSupplier<>(WaitThenThrowOnRunService::new);
146148
final AutoRestartingService<WaitThenThrowOnRunService> restartingService =
147-
new AutoRestartingService<>(recordingSupplier, () -> true);
149+
new AutoRestartingService<>(recordingSupplier, ServiceRestartPolicy.IMMEDIATE);
148150

149151
@SuppressWarnings("PMD.PrematureDeclaration")
150152
final Service initialDelegate = restartingService.getDelegate();
@@ -182,9 +184,10 @@ public void testServiceStaysRunningIfThrowOnRunning() throws InterruptedExceptio
182184

183185
@Test
184186
public void testListenerGetsAddedToRunningService() throws InterruptedException {
185-
final RecordingSupplier recordingSupplier = new RecordingSupplier(() -> new WaitOnRunService());
187+
final RecordingSupplier<WaitOnRunService> recordingSupplier =
188+
new RecordingSupplier<>(WaitOnRunService::new);
186189
final AutoRestartingService<WaitOnRunService> restartingService =
187-
new AutoRestartingService(recordingSupplier, () -> false);
190+
new AutoRestartingService<>(recordingSupplier, ServiceRestartPolicy.IMMEDIATE);
188191
final boolean[] startingListener = {false};
189192
final boolean[] stoppingListener = {false};
190193

ui/src/test/java/edu/wpi/grip/ui/components/StartStoppableButtonTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import edu.wpi.grip.core.util.service.AutoRestartingService;
44
import edu.wpi.grip.core.util.service.RestartableService;
5+
import edu.wpi.grip.core.util.service.ServiceRestartPolicy;
56

67
import com.google.common.util.concurrent.AbstractIdleService;
78

@@ -37,7 +38,7 @@ protected void startUp() {
3738
protected void shutDown() {
3839
/* no-op */
3940
}
40-
}, () -> false);
41+
}, ServiceRestartPolicy.IMMEDIATE);
4142
startStoppableButton = new StartStoppableButton(restartableService);
4243
Scene scene = new Scene(startStoppableButton, 800, 600);
4344
stage.setScene(scene);

0 commit comments

Comments
 (0)