From c6f5d57b30ed9d43c7c4abdcf1d1725dfabdc9fa Mon Sep 17 00:00:00 2001 From: Michael-Georg Date: Fri, 21 Apr 2017 16:19:00 +0300 Subject: [PATCH] CompletableFutureBasic + CachingDataStorageImpl --- .../part2/cache/CachingDataStorageImpl.java | 27 +++++- .../exercise/CompletableFutureBasics.java | 83 ++++++++----------- 2 files changed, 59 insertions(+), 51 deletions(-) diff --git a/src/main/java/part2/cache/CachingDataStorageImpl.java b/src/main/java/part2/cache/CachingDataStorageImpl.java index a2ae460..ebbca1d 100755 --- a/src/main/java/part2/cache/CachingDataStorageImpl.java +++ b/src/main/java/part2/cache/CachingDataStorageImpl.java @@ -1,7 +1,6 @@ package part2.cache; import db.DataStorage; -import db.SlowCompletableFutureDb; import java.util.concurrent.*; @@ -32,12 +31,36 @@ public CachingDataStorageImpl(DataStorage db, int timeout, TimeUnit t @Override public OutdatableResult getOutdatable(String key) { + CompletableFuture result = new CompletableFuture<>(); + CompletableFuture outdated = new CompletableFuture<>(); + + OutdatableResult newResult = new OutdatableResult<>(result, outdated); + OutdatableResult cacheResult = cache.putIfAbsent(key, newResult); + + if (cacheResult != null) + return cacheResult; + + db.get(key).whenComplete((e, th) -> { + if (th != null) + result.completeExceptionally(th); + else { + result.complete(e); + } + scheduledExecutorService.schedule(() -> { + cache.remove(key, newResult); + outdated.complete(null); + }, + timeout, + timeoutUnits); + }); + + return newResult; + // TODO implement // TODO use ScheduledExecutorService to remove outdated result from cache - see SlowCompletableFutureDb implementation // TODO complete OutdatableResult::outdated after removing outdated result from cache // TODO don't use obtrudeException on result - just don't // TODO use remove(Object key, Object value) to remove target value // TODO Start timeout after receiving result in CompletableFuture, not after receiving CompletableFuture itself - throw new UnsupportedOperationException(); } } diff --git a/src/test/java/part1/exercise/CompletableFutureBasics.java b/src/test/java/part1/exercise/CompletableFutureBasics.java index cfd0861..e6859b6 100755 --- a/src/test/java/part1/exercise/CompletableFutureBasics.java +++ b/src/test/java/part1/exercise/CompletableFutureBasics.java @@ -60,21 +60,18 @@ public static void after() { public void createNonEmpty() throws ExecutionException, InterruptedException { final Person person = new Person("John", "Galt", 33); - // TODO Create non empty Optional - final Optional optPerson = null; + final Optional optPerson = Optional.of(person); assertTrue(optPerson.isPresent()); assertEquals(person, optPerson.get()); - // TODO Create stream with a single element - final Stream streamPerson = null; + final Stream streamPerson = Stream.of(person); final List persons = streamPerson.collect(toList()); assertThat(persons.size(), is(1)); assertEquals(person, persons.get(0)); - // TODO Create completed CompletableFuture - final CompletableFuture futurePerson = null; + final CompletableFuture futurePerson = CompletableFuture.completedFuture(person); assertTrue(futurePerson.isDone()); assertEquals(person, futurePerson.get()); @@ -82,20 +79,17 @@ public void createNonEmpty() throws ExecutionException, InterruptedException { @Test public void createEmpty() throws ExecutionException, InterruptedException { - // TODO Create empty Optional - final Optional optPerson = null; + final Optional optPerson = Optional.empty(); assertFalse(optPerson.isPresent()); - // TODO Create empty stream - final Stream streamPerson = null; + final Stream streamPerson = Stream.empty(); final List persons = streamPerson.collect(toList()); assertThat(persons.size(), is(0)); - // TODO Complete CompletableFuture with NoSuchElementException - final CompletableFuture futurePerson = null; - // futurePerson.??? + final CompletableFuture futurePerson = new CompletableFuture<>(); + futurePerson.completeExceptionally(new NoSuchElementException()); assertTrue(futurePerson.isCompletedExceptionally()); assertTrue(futurePerson @@ -107,28 +101,26 @@ public void createEmpty() throws ExecutionException, InterruptedException { public void forEach() throws ExecutionException, InterruptedException { final Person person = new Person("John", "Galt", 33); - // TODO Create non empty Optional - final Optional optPerson = null; + final Optional optPerson = Optional.of(person); final CompletableFuture result1 = new CompletableFuture<>(); - // TODO using optPerson.ifPresent complete result1 + optPerson.ifPresent(result1::complete); + assertEquals(person, result1.get()); - // TODO Create stream with a single element - final Stream streamPerson = null; + final Stream streamPerson = Stream.of(person); final CompletableFuture result2 = new CompletableFuture<>(); - // TODO Using streamPerson.forEach complete result2 + streamPerson.forEach(result2::complete); assertEquals(person, result2.get()); - // TODO Create completed CompletableFuture - final CompletableFuture futurePerson = null; + final CompletableFuture futurePerson = CompletableFuture.completedFuture(person); final CompletableFuture result3 = new CompletableFuture<>(); - // TODO Using futurePerson.thenAccept complete result3 + futurePerson.thenAccept(result3::complete); assertEquals(person, result3.get()); } @@ -136,27 +128,21 @@ public void forEach() throws ExecutionException, InterruptedException { public void map() throws ExecutionException, InterruptedException { final Person person = new Person("John", "Galt", 33); - // TODO Create non empty Optional - final Optional optPerson = null; + final Optional optPerson = Optional.of(person); - // TODO get Optional from optPerson - final Optional optFirstName = null; + final Optional optFirstName = Optional.of(person.getFirstName()); assertEquals(person.getFirstName(), optFirstName.get()); - // TODO Create stream with a single element - final Stream streamPerson = null; + final Stream streamPerson = Stream.of(person); - // TODO Get Stream from streamPerson - final Stream streamFirstName = null; + final Stream streamFirstName = streamPerson.map(Person::getFirstName); assertEquals(person.getFirstName(), streamFirstName.collect(toList()).get(0)); - // TODO Create completed CompletableFuture - final CompletableFuture futurePerson = null; + final CompletableFuture futurePerson = CompletableFuture.completedFuture(person); - // TODO Get CompletableFuture from futurePerson - final CompletableFuture futureFirstName = null; + final CompletableFuture futureFirstName = futurePerson.thenApply(Person::getFirstName); assertEquals(person.getFirstName(), futureFirstName.get()); } @@ -165,31 +151,30 @@ public void map() throws ExecutionException, InterruptedException { public void flatMap() throws ExecutionException, InterruptedException { final Person person = employeeDb.get(keys.get(0)).thenApply(Employee::getPerson).get(); - // TODO Create non empty Optional - final Optional optPerson = null; + final Optional optPerson = Optional.of(person); - // TODO Using flatMap and .getFirstName().codePoints().mapToObj(p -> p).findFirst() - // TODO get the first letter of first name if any - final Optional optFirstCodePointOfFirstName = - null; + final Optional optFirstCodePointOfFirstName = optPerson + .flatMap(person1 -> person1.getFirstName() + .codePoints() + .boxed() + .findFirst()); assertEquals(Integer.valueOf(65), optFirstCodePointOfFirstName.get()); - // TODO Create stream with a single element - final Stream streamPerson = null; + final Stream streamPerson = Stream.of(person); - // TODO Using flatMapToInt and .getFirstName().codePoints() get codepoints stream from streamPerson - final IntStream codePoints = null; + final IntStream codePoints = streamPerson + .flatMapToInt(person1 -> person1 + .getFirstName() + .codePoints()); final int[] codePointsArray = codePoints.toArray(); assertEquals(person.getFirstName(), new String(codePointsArray, 0, codePointsArray.length)); - // TODO Create completed CompletableFuture - final CompletableFuture futurePerson = null; + final CompletableFuture futurePerson = CompletableFuture.completedFuture(person); - // TODO Get CompletableFuture from futurePerson using getKeyByPerson and employeeDb - final CompletableFuture futureEmployee = null; + final CompletableFuture futureEmployee = employeeDb.get(getKeyByPerson(futurePerson.get())); assertEquals(person, futureEmployee.thenApply(Employee::getPerson).get()); } -} +} \ No newline at end of file