Skip to content

Commit da4b316

Browse files
author
ntwigg
committed
First attempt.
1 parent 733fbfc commit da4b316

1 file changed

Lines changed: 83 additions & 7 deletions

File tree

src/main/java/com/diffplug/webtools/flywayjooq/SetupCleanupDockerFlyway.java

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.diffplug.common.base.Either;
44
import com.diffplug.common.base.Errors;
55
import com.diffplug.common.base.Throwables;
6+
import com.diffplug.common.base.Throwing;
67
import com.google.common.collect.ImmutableList;
78
import com.google.common.io.ByteStreams;
89
import com.google.common.io.Files;
@@ -18,7 +19,6 @@
1819
import org.gradle.api.GradleException;
1920
import org.postgresql.ds.PGSimpleDataSource;
2021
import webtools.Env;
21-
import webtools.SetupCleanup;
2222

2323
import java.io.*;
2424
import java.nio.charset.StandardCharsets;
@@ -58,7 +58,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
5858
return FileVisitResult.CONTINUE;
5959
}
6060
});
61-
new Impl().start(keyFile(projectDir), this);
61+
startImpl(keyFile(projectDir), this);
6262
} catch (Exception e) {
6363
var rootCause = Throwables.getRootCause(e);
6464
if (rootCause != null && rootCause.getMessage() != null) {
@@ -70,8 +70,43 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
7070
}
7171
}
7272

73+
private void startImpl(File keyFile, SetupCleanupDockerFlyway key) throws Exception {
74+
synchronized (key.getClass()) {
75+
byte[] required = toBytes(key);
76+
if (keyFile.exists()) {
77+
byte[] actual = java.nio.file.Files.readAllBytes(keyFile.toPath());
78+
if (java.util.Arrays.equals(actual, required)) {
79+
// short-circuit if our state is already setup
80+
return;
81+
} else {
82+
java.nio.file.Files.delete(keyFile.toPath());
83+
@SuppressWarnings("unchecked")
84+
SetupCleanupDockerFlyway lastKey = (SetupCleanupDockerFlyway) fromBytes(required);
85+
new Impl().doStop(lastKey);
86+
}
87+
}
88+
// write out the key
89+
new Impl().doStart(key);
90+
java.nio.file.Files.createDirectories(keyFile.toPath().getParent());
91+
java.nio.file.Files.write(keyFile.toPath(), required);
92+
}
93+
}
94+
7395
void forceStop(File projectDir) throws Exception {
74-
new Impl().forceStop(keyFile(projectDir), this);
96+
try {
97+
new Impl().doStop(this);
98+
} catch (Exception e) {
99+
if (Throwables.getStackTraceAsString(e).contains("Connection refused")) {
100+
// if we can't connect to docker, then we can't stop it
101+
// so we'll just ignore the error
102+
} else {
103+
e.printStackTrace();
104+
}
105+
}
106+
File kf = keyFile(projectDir);
107+
if (kf.exists()) {
108+
java.nio.file.Files.delete(kf.toPath());
109+
}
75110
}
76111

77112
PGSimpleDataSource getConnection() throws IOException {
@@ -105,6 +140,49 @@ private static File keyFile(File projectDir) {
105140
return new File(projectDir, "build/docker");
106141
}
107142

143+
private static final int TRY_SILENTLY_FOR = 10_000;
144+
private static final int TRY_LOUDLY_UNTIL = 12_000;
145+
private static final int WAIT_BETWEEN_TRIES = 100;
146+
147+
public static void keepTrying(Throwing.Runnable toAttempt) {
148+
long start = System.currentTimeMillis();
149+
while (true) {
150+
try {
151+
toAttempt.run();
152+
return;
153+
} catch (Throwable e) {
154+
long elapsed = System.currentTimeMillis() - start;
155+
if (elapsed < TRY_SILENTLY_FOR) {
156+
Errors.rethrow().run(() -> Thread.sleep(WAIT_BETWEEN_TRIES));
157+
} else if (elapsed < TRY_LOUDLY_UNTIL) {
158+
e.printStackTrace();
159+
Errors.rethrow().run(() -> Thread.sleep(WAIT_BETWEEN_TRIES));
160+
} else {
161+
throw Errors.asRuntime(e);
162+
}
163+
}
164+
}
165+
}
166+
167+
private static byte[] toBytes(Object key) {
168+
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
169+
try (ObjectOutputStream objectOutput = new ObjectOutputStream(bytes)) {
170+
objectOutput.writeObject(key);
171+
} catch (IOException e) {
172+
throw new RuntimeException(e);
173+
}
174+
return bytes.toByteArray();
175+
}
176+
177+
private static Object fromBytes(byte[] raw) throws ClassNotFoundException {
178+
ByteArrayInputStream bytes = new ByteArrayInputStream(raw);
179+
try (ObjectInputStream objectOutput = new ObjectInputStream(bytes)) {
180+
return objectOutput.readObject();
181+
} catch (IOException e) {
182+
throw new RuntimeException(e);
183+
}
184+
}
185+
108186
DockerComposeRule rule() {
109187
return DockerComposeRule.builder()
110188
.file(dockerComposeFile.getAbsolutePath())
@@ -117,8 +195,7 @@ DockerComposeRule rule() {
117195
.build();
118196
}
119197

120-
private static class Impl extends SetupCleanup<SetupCleanupDockerFlyway> {
121-
@Override
198+
private static class Impl {
122199
protected void doStart(SetupCleanupDockerFlyway key) throws IOException, InterruptedException {
123200
DockerComposeRule rule;
124201
String ip;
@@ -145,7 +222,7 @@ protected void doStart(SetupCleanupDockerFlyway key) throws IOException, Interru
145222

146223
// run flyway
147224
PGSimpleDataSource postgres = key.getConnection();
148-
SetupCleanup.keepTrying(() -> {
225+
keepTrying(() -> {
149226
Flyway.configure()
150227
.dataSource(postgres)
151228
.locations("filesystem:" + key.flywayMigrations.getAbsolutePath())
@@ -178,7 +255,6 @@ protected void doStart(SetupCleanupDockerFlyway key) throws IOException, Interru
178255
Files.write(schema, key.flywaySchemaDump, StandardCharsets.UTF_8);
179256
}
180257

181-
@Override
182258
protected void doStop(SetupCleanupDockerFlyway key) throws IOException, InterruptedException {
183259
if (!Env.isGitHubAction()) {
184260
DockerCompose compose = key.rule().dockerCompose();

0 commit comments

Comments
 (0)