Skip to content

Commit 350739d

Browse files
committed
Default timescale of 10 seconds.
Now that we understand the nature of the MongoDB timeouts better, it has become clear that this timescale is only relevant when things are going wrong, and that happy-path performance is insensitive to this setting. In that case, a default of 1 second is unnecessarily short.
1 parent 03e41b7 commit 350739d

File tree

5 files changed

+43
-21
lines changed

5 files changed

+43
-21
lines changed

bosk-mongo/src/main/java/works/bosk/drivers/mongo/MongoDriverSettings.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ public class MongoDriverSettings {
2121
* are scaled accordingly.
2222
* Lower values recover more quickly, but will also give up sooner
2323
* and cause more network traffic;
24-
* higher values are more patient and efficient, but slower to recover.
24+
* higher values are more patient and efficient, and can tolerate
25+
* longer network disruptions, but are slower to recover.
2526
* <p>
2627
* Under normal circumstances, the system responds promptly
2728
* and efficiently regardless of this setting.
@@ -31,18 +32,20 @@ public class MongoDriverSettings {
3132
* <ul>
3233
* <li>
3334
* If you are exercising timeout conditions, set this to a low value
34-
* (say, 1/10 of its default) to make your tests run quickly;
35+
* (say, 10x the expected network round-trip delay)
36+
* to make your tests run quickly;
3537
* </li>
3638
* <li>
37-
* otherwise, set it to a high value (say, 10x its default)
38-
* to avoid spurious test failures.
39+
* otherwise, you can set it to a high value (say, 5x its default)
40+
* to avoid spurious test failures,
41+
* though the default should also be fine.
3942
* </li>
4043
* </ul>
4144
*
4245
* In Bosk's own tests, we use even more extreme values to ensure
4346
* this works across a wide range of values.
4447
*/
45-
@Default int timescaleMS = 1000;
48+
@Default int timescaleMS = 10_000;
4649

4750
/**
4851
* @see DatabaseFormat#SEQUOIA

bosk-mongo/src/main/java/works/bosk/drivers/mongo/internal/MainDriver.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,10 @@ public void onConnectionSucceeded() throws
522522
private void runInitialRootAction(FutureTask<R> initialRootAction) throws InterruptedException, TimeoutException, InitialRootActionException {
523523
initialRootAction.run();
524524
try {
525-
initialRootAction.get(initializeTimeout, MILLISECONDS);
525+
// You might think this ought to have a timeout,
526+
// but the underlying initialRootAction logic already has one,
527+
// so this already can't run forever.
528+
initialRootAction.get();
526529
LOGGER.debug("initialRoot action completed successfully");
527530
} catch (ExecutionException e) {
528531
LOGGER.debug("initialRoot action failed", e);

bosk-mongo/src/test/java/works/bosk/drivers/mongo/internal/MongoDriverRecoveryTest.java

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.bson.Document;
1414
import org.junit.jupiter.api.AfterEach;
1515
import org.junit.jupiter.api.BeforeEach;
16+
import org.junit.jupiter.api.Test;
1617
import org.junit.jupiter.params.ParameterizedClass;
1718
import org.junit.jupiter.params.provider.MethodSource;
1819
import org.slf4j.Logger;
@@ -26,7 +27,6 @@
2627
import works.bosk.drivers.mongo.PandoFormat;
2728
import works.bosk.exceptions.FlushFailureException;
2829
import works.bosk.exceptions.InvalidTypeException;
29-
import works.bosk.junit.InjectedTest;
3030
import works.bosk.testing.drivers.state.TestEntity;
3131
import works.bosk.testing.junit.Slow;
3232

@@ -102,7 +102,7 @@ enum FlushOrWait {
102102
}
103103

104104

105-
@InjectedTest
105+
@Test
106106
@DisruptsMongoProxy
107107
void initialOutage_recovers() throws InvalidTypeException, InterruptedException, IOException {
108108
LOGGER.debug("Set up the database contents to be different from initialRoot");
@@ -163,20 +163,25 @@ private void waitFor(BoskDriver driver) throws IOException, InterruptedException
163163
break;
164164
case WAIT:
165165
// The user really has no business expecting updates to occur promptly.
166-
// Because this is sometimes used when the bosk is (deliberately)
167-
// malfunctioning, we should wait much longer than the recovery time.
168166
//
169-
// Unfortunately, this makes these tests inevitably slow.
167+
// This is used in two circumstances:
168+
// 1. If the operation is expected to succeed, then the worst-case
169+
// delay is the delay time for the connection loop, plus the time
170+
// to detect and publish the new format driver,
171+
// plus the time to execute the operation itself.
172+
// 4*timescaleMS ought to be plenty for all that.
173+
// 2. If the operation is expected to fail, no amount of waiting
174+
// will make it succeed, so we can ignore this case.
170175
//
171-
long sleepTime = 12L * driverSettings.timescaleMS();
176+
long sleepTime = 4L * driverSettings.timescaleMS();
172177
LOGGER.debug("Waiting for {} ms", sleepTime);
173178
Thread.sleep(sleepTime);
174179
LOGGER.debug("...done waiting");
175180
break;
176181
}
177182
}
178183

179-
@InjectedTest
184+
@Test
180185
void databaseDropped_recovers() throws InterruptedException, IOException {
181186
testRecovery(() -> {
182187
LOGGER.debug("Drop database");
@@ -187,7 +192,7 @@ void databaseDropped_recovers() throws InterruptedException, IOException {
187192
}, (_) -> initializeDatabase("after drop"));
188193
}
189194

190-
@InjectedTest
195+
@Test
191196
void collectionDropped_recovers() throws InterruptedException, IOException {
192197
testRecovery(() -> {
193198
LOGGER.debug("Drop collection");
@@ -198,7 +203,7 @@ void collectionDropped_recovers() throws InterruptedException, IOException {
198203
}, (_) -> initializeDatabase("after drop"));
199204
}
200205

201-
@InjectedTest
206+
@Test
202207
void documentDeleted_recovers() throws InterruptedException, IOException {
203208
testRecovery(() -> {
204209
LOGGER.debug("Delete document");
@@ -209,7 +214,7 @@ void documentDeleted_recovers() throws InterruptedException, IOException {
209214
}, (_) -> initializeDatabase("after deletion"));
210215
}
211216

212-
@InjectedTest
217+
@Test
213218
void documentReappears_recovers() throws InterruptedException, IOException {
214219
MongoCollection<Document> collection = mongoService.client()
215220
.getDatabase(driverSettings.database())
@@ -236,7 +241,7 @@ void documentReappears_recovers() throws InterruptedException, IOException {
236241
});
237242
}
238243

239-
@InjectedTest
244+
@Test
240245
void revisionDeleted_recovers() throws InterruptedException, IOException {
241246
// It's not clear that this is a valid test. If this test is a burden to support,
242247
// we can consider removing it.
@@ -322,6 +327,12 @@ private void testRecovery(Runnable disruptiveAction, Function<TestEntity, TestEn
322327

323328
Bosk<TestEntity> bosk = new Bosk<>(boskName(getClass().getSimpleName()), TestEntity.class, AbstractMongoDriverTest::initialRoot, BoskConfig.<TestEntity>builder().driverFactory(driverFactory).build());
324329

330+
// With short timescales or slow networks, the bosk initial state
331+
// can time out trying to read the database and instead uses AbstractMongoDriverTest::initialRoot.
332+
// This is actually valid behaviour for a sufficiently impatient user.
333+
// Let's wait first to ensure we have the state from the database.
334+
waitFor(bosk.driver());
335+
325336
try (var _ = bosk.readContext()) {
326337
// Note: with very short timescales, this assertion can fail because the newly created bosk
327338
// times out trying to read the database contents and instead uses AbstractMongoDriverTest::initialRoot.

bosk-mongo/src/test/java/works/bosk/drivers/mongo/internal/TestParameters.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,20 @@ public class TestParameters {
1414

1515
/**
1616
* For tests that are expecting timeouts. A short value makes the tests run faster.
17-
* Too short, and the tests might not be testing the right thing.
17+
* <p>
18+
* Too short, and the tests might end up exhibiting fallback behaviour as though
19+
* there's a database outage. At initialization, it may proceed with the fallback
20+
* initial state from the downstream driver, and other operations may throw
21+
* {@link works.bosk.drivers.mongo.exceptions.DisconnectedException DisconnectException} or similar.
22+
* <p>
1823
* This should be much larger than the expected latency of MongoDB and the network.
1924
*/
2025
public static final int SHORT_TIMESCALE = 50;
2126

2227
/**
2328
* For tests that are not expecting timeouts. A nice long value makes spurious test failures unlikely.
2429
*/
25-
public static final int LONG_TIMESCALE = 90_000;
30+
public static final int LONG_TIMESCALE = 150_000;
2631

2732
@Value
2833
public static class ParameterSet {

lib-testing/src/main/resources/logback.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
<logger name="works.bosk.drivers.mongo" level="DEBUG"/>
2323
<logger name="works.bosk.drivers.mongo.internal.ChangeReceiver" level="DEBUG"/>
2424
<logger name="works.bosk.drivers.mongo.internal.MainDriver" level="DEBUG"/>
25-
<logger name="works.bosk.drivers.mongo.internal.PandoFormatDriver" level="TRACE"/>
26-
<logger name="works.bosk.drivers.mongo.internal.AbstractMongoDriverTest" level="INFO"/>
25+
<logger name="works.bosk.drivers.mongo.internal.PandoFormatDriver" level="DEBUG"/>
26+
<logger name="works.bosk.drivers.mongo.internal.AbstractMongoDriverTest" level="DEBUG"/>
2727
<logger name="works.bosk.logback.BoskLogFilter" level="DEBUG"/>
2828
-->
2929

0 commit comments

Comments
 (0)