Skip to content

Commit 5fd96d4

Browse files
Merge pull request #256 from Project-Env/feature/wait-for-other-process-download
Wait for archive to be downloaded by other process
2 parents 1b6950f + c987f4d commit 5fd96d4

File tree

1 file changed

+62
-6
lines changed
  • code/tool-support/tool-support-commons/src/main/java/io/projectenv/core/toolsupport/commons/commands

1 file changed

+62
-6
lines changed

code/tool-support/tool-support-commons/src/main/java/io/projectenv/core/toolsupport/commons/commands/ExtractArchiveStep.java

+62-6
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@
1414
import java.io.IOException;
1515
import java.net.URI;
1616
import java.nio.charset.StandardCharsets;
17-
import java.nio.file.Files;
18-
import java.nio.file.Path;
19-
import java.nio.file.Paths;
17+
import java.nio.file.*;
2018
import java.security.MessageDigest;
19+
import java.time.Duration;
20+
import java.time.Instant;
21+
import java.util.concurrent.TimeUnit;
22+
23+
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
2124

2225
public class ExtractArchiveStep implements LocalToolInstallationStep {
2326

27+
public static final Duration OTHER_PROCESS_ARCHIVE_DOWNLOAD_WAIT_LIMIT = Duration.ofMinutes(5);
2428
private final String rawArchiveUri;
2529

2630
public ExtractArchiveStep(String rawArchiveUri) {
@@ -52,18 +56,33 @@ private Path downloadArchive() throws LocalToolInstallationStepException {
5256
return archiveCachePath;
5357
}
5458

59+
Path archiveDownloadingPath = getArchiveDownloadingPath();
60+
if (Files.exists(archiveDownloadingPath)) {
61+
waitUntilArchiveHasBeenDownloadedByOtherProcess(archiveCachePath);
62+
ProcessOutput.writeDebugMessage("using cached archive from {0}", archiveCachePath);
63+
return archiveCachePath;
64+
}
65+
5566
ProcessOutput.writeDebugMessage("downloading archive from {0}", rawArchiveUri);
5667
try (var inputStream = URI.create(rawArchiveUri).toURL().openStream();
57-
var outputStream = new FileOutputStream(archiveCachePath.toFile())) {
68+
var outputStream = new FileOutputStream(archiveDownloadingPath.toFile())) {
5869

5970
IOUtils.copy(inputStream, outputStream);
71+
} catch (IOException e) {
72+
deleteIfExists(archiveDownloadingPath);
73+
throw new LocalToolInstallationStepException("failed to download archive from URI " + rawArchiveUri, e);
74+
}
6075

76+
try {
77+
Files.move(archiveDownloadingPath, archiveCachePath);
6178
ProcessOutput.writeDebugMessage("cached archive at {0}", archiveCachePath);
62-
return archiveCachePath;
6379
} catch (IOException e) {
80+
deleteIfExists(archiveDownloadingPath);
6481
deleteIfExists(archiveCachePath);
65-
throw new LocalToolInstallationStepException("failed to download archive from URI " + rawArchiveUri, e);
82+
throw new LocalToolInstallationStepException("failed to move downloaded archive from " + archiveDownloadingPath + " to " + archiveCachePath, e);
6683
}
84+
85+
return archiveCachePath;
6786
}
6887

6988
private Path getArchiveCachePath() throws LocalToolInstallationStepException {
@@ -82,6 +101,43 @@ private Path getCacheDirectory() throws IOException {
82101
});
83102
}
84103

104+
private Path getArchiveDownloadingPath() throws LocalToolInstallationStepException {
105+
Path archiveCachePath = getArchiveCachePath();
106+
return archiveCachePath.getParent().resolve(archiveCachePath.getFileName() + ".downloading");
107+
}
108+
109+
private void waitUntilArchiveHasBeenDownloadedByOtherProcess(Path archivePath) throws LocalToolInstallationStepException {
110+
try (WatchService watchService = createWatchServiceForArchive(archivePath)) {
111+
Instant startTime = Instant.now();
112+
while (!Files.exists(archivePath) && Duration.between(startTime, Instant.now()).compareTo(OTHER_PROCESS_ARCHIVE_DOWNLOAD_WAIT_LIMIT) <= 0) {
113+
waitForArchiveDownloadEvents(watchService);
114+
}
115+
} catch (Exception e) {
116+
ProcessOutput.writeDebugMessage("Got exception while waiting for archive to be downloaded by other process", e);
117+
}
118+
119+
if (!Files.exists(archivePath)) {
120+
throw new LocalToolInstallationStepException("failed to wait for archive to be downloaded");
121+
}
122+
}
123+
124+
private WatchService createWatchServiceForArchive(Path archiveDownloadingPath) throws IOException {
125+
WatchService watchService = FileSystems.getDefault().newWatchService();
126+
archiveDownloadingPath.getParent().register(watchService, ENTRY_CREATE);
127+
128+
return watchService;
129+
}
130+
131+
private void waitForArchiveDownloadEvents(WatchService watchService) throws Exception {
132+
WatchKey key = watchService.poll(OTHER_PROCESS_ARCHIVE_DOWNLOAD_WAIT_LIMIT.toMinutes(), TimeUnit.MINUTES);
133+
if (key != null) {
134+
key.pollEvents();
135+
if (!key.reset()) {
136+
throw new IOException("Watch key no more valid");
137+
}
138+
}
139+
}
140+
85141
private void extractArchive(Path localArchivePath, File installationRoot) throws LocalToolInstallationStepException {
86142
try {
87143
ArchiveExtractorFactory.createArchiveExtractor().extractArchive(localArchivePath.toFile(), installationRoot);

0 commit comments

Comments
 (0)