Compare commits
No commits in common. '2df96026bb025e85709ed140b5b3cc3961b08d61' and '83fcb23e6794300c51e75a27d83ada71d5ba0bae' have entirely different histories.
2df96026bb
...
83fcb23e67
@ -1,9 +1,9 @@ |
|||||||
package me.bearns.fias.service; |
package me.bearns.fias.service; |
||||||
|
|
||||||
import java.io.File; |
import java.io.InputStream; |
||||||
import java.util.concurrent.CompletableFuture; |
import java.util.concurrent.Future; |
||||||
|
|
||||||
public interface Downloader { |
public interface Downloader { |
||||||
|
|
||||||
public CompletableFuture<File> download(String url); |
public Future<InputStream> download(String url); |
||||||
} |
} |
||||||
|
@ -1,65 +1,28 @@ |
|||||||
package me.bearns.fias.service; |
package me.bearns.fias.service; |
||||||
|
|
||||||
import org.springframework.stereotype.Component; |
import java.io.InputStream; |
||||||
|
import java.util.concurrent.CompletableFuture; |
||||||
|
import java.util.concurrent.ExecutorService; |
||||||
|
import java.util.concurrent.Executors; |
||||||
|
import java.util.concurrent.Future; |
||||||
|
|
||||||
import java.io.*; |
|
||||||
import java.net.URL; |
|
||||||
import java.nio.file.Files; |
|
||||||
import java.nio.file.Path; |
|
||||||
import java.nio.file.Paths; |
|
||||||
import java.nio.file.StandardCopyOption; |
|
||||||
import java.util.concurrent.*; |
|
||||||
|
|
||||||
@Component |
|
||||||
public class DownloaderImpl implements Downloader { |
public class DownloaderImpl implements Downloader { |
||||||
|
|
||||||
private static final ExecutorService pool = Executors.newCachedThreadPool(); |
private static final ExecutorService pool = Executors.newCachedThreadPool(); |
||||||
private static final String BASE_DIRECTORY = "/var/opt/fias"; |
|
||||||
private static final ConcurrentMap<String,CompletableFuture<File>> locks = new ConcurrentHashMap(); |
|
||||||
|
|
||||||
@Override |
@Override |
||||||
public CompletableFuture<File> download(String url) { |
public Future<InputStream> download(String url) { |
||||||
|
|
||||||
CompletableFuture<File> start = new CompletableFuture<>(); |
|
||||||
|
|
||||||
//syncronized
|
|
||||||
final CompletableFuture<File> feature = locks.putIfAbsent(url, start); |
|
||||||
|
|
||||||
//return earlier runned feature
|
CompletableFuture<InputStream> completableFuture |
||||||
if(feature != start) return feature; |
= new CompletableFuture<>(); |
||||||
|
|
||||||
pool.submit(() -> { |
pool.submit(() -> { |
||||||
|
InputStream is = null; |
||||||
//todo
|
//todo
|
||||||
|
|
||||||
final URL conn; |
completableFuture.complete(is); |
||||||
final Path path; |
|
||||||
|
|
||||||
try{ |
|
||||||
conn = new URL(url); |
|
||||||
path = Paths.get(BASE_DIRECTORY, conn.getFile()); |
|
||||||
|
|
||||||
} catch (IOException e) { |
|
||||||
feature.obtrudeException(e); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
final File file = path.toFile(); |
|
||||||
|
|
||||||
if(!file.exists()) { |
|
||||||
|
|
||||||
try (BufferedInputStream in = new BufferedInputStream(conn.openStream())) { |
|
||||||
|
|
||||||
Files.copy(in, path, StandardCopyOption.REPLACE_EXISTING); |
|
||||||
|
|
||||||
} catch (IOException e) { |
|
||||||
// handle exception
|
|
||||||
feature.obtrudeException(e); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
feature.complete(file); |
|
||||||
}); |
}); |
||||||
|
|
||||||
return feature; |
return completableFuture; |
||||||
} |
} |
||||||
} |
} |
||||||
|
@ -1,57 +0,0 @@ |
|||||||
package me.bearns.fias; |
|
||||||
|
|
||||||
|
|
||||||
import me.bearns.fias.service.Downloader; |
|
||||||
import org.junit.Test; |
|
||||||
import org.junit.runner.RunWith; |
|
||||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||||
import org.springframework.boot.test.context.SpringBootTest; |
|
||||||
|
|
||||||
import org.springframework.test.context.junit4.SpringRunner; |
|
||||||
|
|
||||||
import java.io.File; |
|
||||||
import java.util.Arrays; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Objects; |
|
||||||
import java.util.concurrent.CompletableFuture; |
|
||||||
import java.util.stream.Stream; |
|
||||||
|
|
||||||
@RunWith(SpringRunner.class) |
|
||||||
@SpringBootTest |
|
||||||
public class DownloaderTest { |
|
||||||
|
|
||||||
@Autowired |
|
||||||
private Downloader service; |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testDownload() { |
|
||||||
List<String> list = Arrays.asList( |
|
||||||
"http://fias-file.nalog.ru/DownloadUpdates?file=fias_delta_xml.zip&version=20200811", |
|
||||||
"http://fias-file.nalog.ru/DownloadUpdates?file=fias_delta_xml.zip&version=20200807", |
|
||||||
"http://fias-file.nalog.ru/DownloadUpdates?file=fias_delta_xml.zip&version=20200804", |
|
||||||
"http://fias-file.nalog.ru/DownloadUpdates?file=fias_delta_xml.zip&version=20200807" //repeat
|
|
||||||
); |
|
||||||
|
|
||||||
assert service != null; |
|
||||||
|
|
||||||
//start download
|
|
||||||
final Stream<CompletableFuture<File>> futureStream = list.parallelStream().map(service::download); |
|
||||||
|
|
||||||
Stream<File> fileStream = futureStream.map(fileCompletableFuture -> { |
|
||||||
try { |
|
||||||
return fileCompletableFuture.get(); |
|
||||||
} catch (Exception e) { |
|
||||||
return null; //on error
|
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
assert fileStream.allMatch(Objects::nonNull); |
|
||||||
|
|
||||||
assert fileStream.count() == 3; |
|
||||||
|
|
||||||
assert fileStream.allMatch(File::exists); |
|
||||||
|
|
||||||
assert fileStream.allMatch(file -> file.length() > 0); |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue