diff --git a/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfoUpdateService.java b/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfoUpdateService.java index 834b961..4b69399 100644 --- a/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfoUpdateService.java +++ b/java-spring/accounts-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfoUpdateService.java @@ -3,6 +3,7 @@ package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.ac import com.mongodb.WriteResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.dao.DuplicateKeyException; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; @@ -35,6 +36,9 @@ public class AccountInfoUpdateService { .set("version", version), AccountInfo.class); logger.info("Saved in mongo"); + + } catch (DuplicateKeyException t) { + logger.warn("When saving ", t); } catch (Throwable t) { logger.error("Error during saving: ", t); throw new RuntimeException(t); diff --git a/java-spring/accounts-query-side-backend/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfoUpdateServiceTest.java b/java-spring/accounts-query-side-backend/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfoUpdateServiceTest.java index fabe490..dd409e3 100644 --- a/java-spring/accounts-query-side-backend/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfoUpdateServiceTest.java +++ b/java-spring/accounts-query-side-backend/src/test/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/accounts/AccountInfoUpdateServiceTest.java @@ -93,4 +93,20 @@ public class AccountInfoUpdateServiceTest { assertEquals(ti, accountInfo.getTransactions().get(0)); } + @Test + public void shouldHandleDuplicateSaveAccountInfo() throws ExecutionException, InterruptedException { + IdGenerator x = new IdGeneratorImpl(); + String accountId = x.genId().asString(); + String customerId = x.genId().asString(); + String version = x.genId().asString(); + + String title = "Checking account"; + BigDecimal initialBalance = new BigDecimal("1345"); + String description = "Some account"; + + accountInfoUpdateService.create(accountId, customerId, title, initialBalance, description, version); + accountInfoUpdateService.create(accountId, customerId, title, initialBalance, description, version); + + + } } \ No newline at end of file diff --git a/java-spring/customers-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/customers/CustomerInfoUpdateService.java b/java-spring/customers-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/customers/CustomerInfoUpdateService.java index 53250ca..3964683 100644 --- a/java-spring/customers-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/customers/CustomerInfoUpdateService.java +++ b/java-spring/customers-query-side-backend/src/main/java/net/chrisrichardson/eventstore/javaexamples/banking/backend/queryside/customers/CustomerInfoUpdateService.java @@ -5,6 +5,7 @@ import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.Quer import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.ToAccountInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.dao.DuplicateKeyException; import java.util.Collections; @@ -15,15 +16,15 @@ public class CustomerInfoUpdateService { private Logger logger = LoggerFactory.getLogger(getClass()); - private QuerySideCustomerRepository accountInfoRepository; + private QuerySideCustomerRepository querySideCustomerRepository; - public CustomerInfoUpdateService(QuerySideCustomerRepository accountInfoRepository) { - this.accountInfoRepository = accountInfoRepository; + public CustomerInfoUpdateService(QuerySideCustomerRepository querySideCustomerRepository) { + this.querySideCustomerRepository = querySideCustomerRepository; } public void create(String id, CustomerInfo customerInfo) { try { - accountInfoRepository.save(new QuerySideCustomer(id, + querySideCustomerRepository.save(new QuerySideCustomer(id, customerInfo.getName(), customerInfo.getEmail(), customerInfo.getSsn(), @@ -33,6 +34,8 @@ public class CustomerInfoUpdateService { ) ); logger.info("Saved in mongo"); + } catch (DuplicateKeyException t) { + logger.warn("When saving ", t); } catch (Throwable t) { logger.error("Error during saving: ", t); throw new RuntimeException(t); @@ -40,9 +43,9 @@ public class CustomerInfoUpdateService { } public void addToAccount(String id, ToAccountInfo accountInfo) { - QuerySideCustomer customer = accountInfoRepository.findOne(id); + QuerySideCustomer customer = querySideCustomerRepository.findOne(id); customer.getToAccounts().put(accountInfo.getId(), accountInfo); - accountInfoRepository.save(customer); + querySideCustomerRepository.save(customer); } } diff --git a/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/TestUtil.java b/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/TestUtil.java index b8f8307..2c84554 100644 --- a/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/TestUtil.java +++ b/java-spring/testutil/src/main/java/net/chrisrichardson/eventstorestore/javaexamples/testutil/TestUtil.java @@ -54,51 +54,26 @@ public class TestUtil { } } - public static void eventually(final Producer producer, final Verifier verifier) { - final int n = 150; - Object possibleException = Observable.timer(0, 200, TimeUnit.MILLISECONDS).flatMap(new Func1>>() { - - @Override - public Observable> call(Long aLong) { - try { - return fromCompletableFuture(producer.produce()).map(new Func1>() { - @Override - public Outcome call(T t) { - return new Success(t); - } - }); - } catch (Exception e) { - Outcome value = new Failure(e); - return Observable.just(value); - } + public static void eventually(Producer producer, Verifier predicate) { + Throwable laste = null; + for (int i = 0; i < 30 ; i++) { + try { + T x = producer.produce().get(30, TimeUnit.SECONDS); + predicate.verify(x); + return; + } catch (Throwable t) { + laste = t; } - }).map(new Func1, Throwable>() { - @Override - public Throwable call(Outcome t) { - try { - if (t instanceof Success) { - verifier.verify(((Success) t).value); - return null; - } else - return ((Failure) t).t; - } catch (Throwable e) { - return e; - } + try { + TimeUnit.SECONDS.sleep(1); + } catch (InterruptedException e) { + throw new RuntimeException(e); } - }).take(n).zipWith(Observable.range(0, n), new Func2>() { - @Override - public Tuple2 call(Throwable e, Integer idx) { - return new Tuple2(e, idx); - } - }).skipWhile(new Func1, Boolean>() { - @Override - public Boolean call(Tuple2 tuple2) { - return tuple2.first != null && tuple2.second < n - 1; - } - }).first().toBlocking().getIterator().next().first; - - if (possibleException != null) - throw new RuntimeException((Throwable)possibleException); + } + if (laste != null) + throw new RuntimeException("Last exception was", laste); + else + throw new RuntimeException("predicate never satisfied"); } private static Observable fromCompletableFuture(CompletableFuture future) {