Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Jarosław Ratajski
CSS Versicherung
DROP DATABASE
Jarek Ratajski
Developer, wizard, anarchitectDeveloper, wizard, anarchitect
Lives in LuzernLives in Luzern
Works in CSS In...
Multiversum
MULTIVERSUMMULTIVERSUM
Real life case
Galakpizza
10 000 Planets 3 Variants
3 Sizes
HAWAII
MARGHERITTA
VEGETARIAN
MEDIUM
LARGE
XL
Domain summary
MARGHERITTA MEDIUM
HAWAII LARGE
HAWAII LARGE
VEGERARIAN LARGE
HAWAII XL
MARGHERITTA XL
HAWAII LARGE
HAWAII LARGE
HAWAII LA...
10 000 Pizzas / s
I want to look at number
of queued orders 10000 times / s
My wife also!
Requirements
Alien development
(in 2 „parallel“ universes)
Normal universe Other universe
++
In Normal universe
https://github.com/airomem/galakpizza/tree/master/galakpizza_n
Normal domain
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
public final l...
Normal domain 2
public enum Size {
MEDIUM,
LARGE,
XL
}
public enum Variant {
HAWAII,
MARGHERITA,
VEGETARIAN
}
Normal Service
public interface GalakPizzaOrders {
long placeOrder(String planet, Variant variant, Size size);
}
Normal Service
public interface GalakPizzaOrders {
long placeOrder(String planet, Variant variant, Size size);
}
public in...
Normal Service
public interface GalakPizzaOrders {
long placeOrder(String planet, Variant variant, Size size);
}
public in...
Normal service implementation...
public class GalakPizzaCore implements GalakPizzaService, Serializable,
Storable<GalakPiz...
Normal service implementation...
public class GalakPizzaCore implements GalakPizzaService, Serializable,
Storable<GalakPiz...
Normal service implementation...
public class GalakPizzaCore implements GalakPizzaService, Serializable,
Storable<GalakPiz...
PlanetOrders - helper
class PlanetOrders implements Serializable {
final String name;
private List<Order> orders = new Arr...
PlanetOrders - helper
class PlanetOrders implements Serializable {
final String name;
private List<Order> orders = new Arr...
PlanetOrders - helper
class PlanetOrders implements Serializable {
final String name;
private List<Order> orders = new Arr...
Normal place order
public class GalakPizzaCore implements GalakPizzaService, Serializable,
Storable<GalakPizzaCore> {
priv...
Normal place order
public class GalakPizzaCore implements GalakPizzaService, Serializable,
Storable<GalakPizzaCore> {
priv...
Normal place order
public class GalakPizzaCore implements GalakPizzaService, Serializable,
Storable<GalakPizzaCore> {
priv...
Normal place order revisited
public class GalakPizzaCore { ...
private final Map<String, PlanetOrders> orders = new HashMa...
Normal place order revisited
public class GalakPizzaCore { ...
private final Map<String, PlanetOrders> orders = new HashMa...
Normal place order revisited
public class GalakPizzaCore { ...
private final Map<String, PlanetOrders> orders = new HashMa...
Wrapper... yeah
public static class Wrapper implements Comparable<Wrapper>,Serializable{
final PlanetOrders porders;
final...
PlanetOrders – take orders
class PlanetOrders implements Serializable {
final String name;
private List<Order> orders = ne...
PlanetOrders – take orders
class PlanetOrders implements Serializable {
final String name;
private List<Order> orders = ne...
Normal take orders
public class GalakPizzaCore implements GalakPizzaService, Serializable,
Storable<GalakPizzaCore> {
priv...
Normal take orders
public class GalakPizzaCore implements GalakPizzaService, Serializable,
Storable<GalakPizzaCore> {
priv...
Normal take orders
public class GalakPizzaCore implements GalakPizzaService, Serializable,
Storable<GalakPizzaCore> {
priv...
Normal count orders
private AtomicLong ordersTotal = new AtomicLong(0);
public long countStandingOrders() {
return this.or...
We have service - but do we deal with?
Concurrency
Persistence
Normal - Alien service wrapper
public class GalakPizza implements GalakPizzaService {
final PersistenceController<GalakPiz...
Done!
In alternative universe
https://github.com/airomem/galakpizza/tree/master/galakpizza_h
Other Domain
@Entity
@Table(name="T_ORDER")
@NamedQueries( {
@NamedQuery(name = "select best planet", query = "SELECT o.pl...
Other domain (same as above)
public enum Size {
MEDIUM,
LARGE,
XL
}
public enum Variant {
HAWAII,
MARGHERITA,
VEGETARIAN
}
It is in TABLE
so it exists
Other service (same)
public interface GalakPizzaOrders {
long placeOrder(String planet, Variant variant, Size size);
}
pub...
Select best blanet...
SELECT o.planet, count(o) FROM Order o
GROUP BY o.planet ORDER BY count(o) desc
Other Planet (but almost same story)
@Entity
@Table(name="T_PLANET",
indexes = {@Index(name="cnt_idx", columnList = "count...
Other service implementation
public class GalakPizza implements GalakPizzaService {
final SessionFactory sessionFactory;
p...
Other - Place order
public long placeOrder(String planet, Variant variant, Size size) {
return this.runInSession(session -...
Other - runInSession
private <T> T runInSession(Function<Session, T> dbCommand) {
final Session session = sessionFactory.o...
Other - Take orders
public List<Order> takeOrdersFromBestPlanet() {
return this.runInSession(session -> {
final Query best...
Other – count orders
@Override
public long countStandingOrders() {
return this.runInSession(session -> {
final Query order...
Other - others
Hibernate config, init
MySql config
After one day of coding...
In a real galaxy
That we can simulate as
Customers - 4 Threads doing in loop placeOrder (random planet
name, variant and size) – no pauses
...
Galaxy simulation
public static void main(String... args) {
runSimulation(5000);
System.gc();
sleep();
Result result = run...
?
Normal universe Other universe
~40 000 p/s ~600 p/s
Processed orders
Normal universe Other universe
~ 12 823 500 p/s ~6362 p/s
Peeping speed
Normal universe Other universe
Normal universe Other universe
GODS of SQL
HELP! ME
Normal universe Other universe
~60 000 p/s ~1000 p/s
After few days of operations...
Normal universe Other universe
Cool, that it runs on
laptop
Reality strickes back
I do not trust PizzaBoy
I want to know where exactly were pizzas delivered
Normal universe Other universe
Cool, we will not delete
orders any more,
only mark them
as deleted!
Cool, we will add a li...
Reality strickes back
I do not trust PizzaBoy
I want to know where were pizzas delivered
Yesterday!!!
Normal universe Other universe
Crap...
We will restart system
and commands
will be reprocessed
Yet another real world case
System evolves
I want to let people compose their pizza/
Like: more cheese on one half,
and no meat on the next half,
And ...
Normal universe Other universe
We will map it with only 20 tables
Or do we add TEXT field?
public Order(long id, String
pl...
Difference
+ Fast
+ Code in Java
+ „Strongly“ typed
+ Flexible
+ Testable
- Sophisticated java
- Terribly slow
- Code in S...
Why different ?
Long time ago
Sweet spot known as 90's
Computers had mostly one CPU Core
Memory (RAM) was expensive but more as 100MB
available in singl...
Around galactic year 2003
Normal universe
RAM is so cheap and huge
Computers have multiple cores
Alien developers start to use full power of hardwar...
Other universe
RAM is cheap and huge
Computers have multiple cores
But alien developers have never realised that
Other universe is a good place
Database vendors earn money and are happy
Application Servers vendors earn money and are ha...
DB / ORM vs Prevalence Problems
Problem Prevalent (Normal) ORMs (Other)
Detached objects Yes Yes
Transaction
isolation
Yes...
If you want to jump to normal universe...
Simple start
Prevayler
or
Airomem (Prevayler wrapper for Java 8 )
or
Nothing :-)
Airomem quick - maven
<dependency>
<groupId>pl.setblack</groupId>
<artifactId>airomem-core</artifactId>
<version>1.0.5</ve...
Airomem - init
PersistenceController<GalakPizzaCore,GalakPizzaCore> controller =
controller = PrevaylerBuilder
.newBuilder...
Airomem – commands
controller.executeAndQuery( core->core.placeOrder(planet, variant, size ));
----------------------
cont...
Commands are never executed concurrently
Query
controller.query( c->c.countStandingOrders());
Queries are executed concurrently - also with
one command!
Airomem – snapshots, events
jarek@ubuntu:~$ cd prevayler/
jarek@ubuntu:~/prevayler$ ls
pizza
jarek@ubuntu:~/prevayler$ cd ...
Problems?
RAM?
Data migration
Not big deal in fact
Java Serialization (sth to learn)
readResolve, writeReplace
XML export option
Transaction
This is always transactional!!!
public Long execute(GalakPizzaCore system) {
return system.placeOrder(planet,v...
Concurrency
Learn java.util.concurrent, synchronized or die!
Replication/ failover
Not in standard... but
Trivial to implement - send events to other machines, share
folder
Indices
Indices in memory do exists
CQEngine
Query<Car> query1 = or(endsWith(Car.NAME, "vic"),
lessThan(Car.CAR_ID, 2));
f...
Airomem summary
CQRS + ES simplified - one command one event→
With RAM projection
More enterprisy alternatives
Lagom!
Akka persistence
CQRS generally
Advice
Remember to add Thread.sleep(1000) often
Storing in Prevayler vs DB
model events vs model domain
store facts vs store state
Shared state is a cache vs shared state...
End
Try on something small first (not bigger then one planet)
Drop DB from core of your system
Drop your application serve...
Jdd 2016 DROP DATABASE
Upcoming SlideShare
Loading in …5
×

Jdd 2016 DROP DATABASE

578 views

Published on

JDD 2016 Krakow slides

Published in: Software
  • Be the first to comment

  • Be the first to like this

Jdd 2016 DROP DATABASE

  1. 1. Jarosław Ratajski CSS Versicherung DROP DATABASE
  2. 2. Jarek Ratajski Developer, wizard, anarchitectDeveloper, wizard, anarchitect Lives in LuzernLives in Luzern Works in CSS InsuranceWorks in CSS Insurance C64, 6502, 68000, 8086, C++, Java, JEE, Scala, Akka, JS,C64, 6502, 68000, 8086, C++, Java, JEE, Scala, Akka, JS, ScalaJS....ScalaJS.... jratajski@gmail.comjratajski@gmail.com @jarek000000@jarek000000
  3. 3. Multiversum
  4. 4. MULTIVERSUMMULTIVERSUM
  5. 5. Real life case
  6. 6. Galakpizza
  7. 7. 10 000 Planets 3 Variants 3 Sizes HAWAII MARGHERITTA VEGETARIAN MEDIUM LARGE XL Domain summary
  8. 8. MARGHERITTA MEDIUM HAWAII LARGE HAWAII LARGE VEGERARIAN LARGE HAWAII XL MARGHERITTA XL HAWAII LARGE HAWAII LARGE HAWAII LARGE HAWAII LARGE 33 33 11 11 Delivery model
  9. 9. 10 000 Pizzas / s I want to look at number of queued orders 10000 times / s My wife also! Requirements
  10. 10. Alien development (in 2 „parallel“ universes)
  11. 11. Normal universe Other universe ++
  12. 12. In Normal universe https://github.com/airomem/galakpizza/tree/master/galakpizza_n
  13. 13. Normal domain public class Order implements Serializable { private static final long serialVersionUID = 1L; public final long id; public final String planet; public final Variant variant; public final Size size; public Order(long id, String planet, Variant variant, Size size) { this.id = id; this.planet = planet; this.size = size; this.variant = variant; } }
  14. 14. Normal domain 2 public enum Size { MEDIUM, LARGE, XL } public enum Variant { HAWAII, MARGHERITA, VEGETARIAN }
  15. 15. Normal Service public interface GalakPizzaOrders { long placeOrder(String planet, Variant variant, Size size); }
  16. 16. Normal Service public interface GalakPizzaOrders { long placeOrder(String planet, Variant variant, Size size); } public interface GalakPizzaDelivery { List<Order> takeOrdersFromBestPlanet(); long countStandingOrders(); }
  17. 17. Normal Service public interface GalakPizzaOrders { long placeOrder(String planet, Variant variant, Size size); } public interface GalakPizzaDelivery { List<Order> takeOrdersFromBestPlanet(); long countStandingOrders(); } public interface GalakPizzaService extends GalakPizzaDelivery, GalakPizzaOrders{ }
  18. 18. Normal service implementation... public class GalakPizzaCore implements GalakPizzaService, Serializable, Storable<GalakPizzaCore> { public long placeOrder(String planet, Variant variant, Size size) { ... } public List<Order> takeOrdersFromBestPlanet() { ... } public long countStandingOrders() { ... } }
  19. 19. Normal service implementation... public class GalakPizzaCore implements GalakPizzaService, Serializable, Storable<GalakPizzaCore> { private finalprivate final Map<String, List<Order>>Map<String, List<Order>> ordersorders == newnew HashMap<>();HashMap<>(); public long placeOrder(String planet, Variant variant, Size size) { ... } public List<Order> takeOrdersFromBestPlanet() { ... } public long countStandingOrders() { ... } }
  20. 20. Normal service implementation... public class GalakPizzaCore implements GalakPizzaService, Serializable, Storable<GalakPizzaCore> { private finalprivate final Map<String, PlanetOrders>Map<String, PlanetOrders> ordersorders == newnew HashMap<>();HashMap<>(); public long placeOrder(String planet, Variant variant, Size size) { ... } public List<Order> takeOrdersFromBestPlanet() { ... } public long countStandingOrders() { ... } }
  21. 21. PlanetOrders - helper class PlanetOrders implements Serializable { final String name; private List<Order> orders = new ArrayList<>(); public PlanetOrders(String name) { this.name = name; } ... }
  22. 22. PlanetOrders - helper class PlanetOrders implements Serializable { final String name; private List<Order> orders = new ArrayList<>(); public PlanetOrders(String name) { this.name = name; } void assignOrder(final Order order) { this.orders.add(order); } ... }
  23. 23. PlanetOrders - helper class PlanetOrders implements Serializable { final String name; private List<Order> orders = new ArrayList<>(); public PlanetOrders(String name) { this.name = name; } void assignOrder(final Order order) { this.orders.add(order); } public boolean isEmpty() { return this.orders.isEmpty(); } ... }
  24. 24. Normal place order public class GalakPizzaCore implements GalakPizzaService, Serializable, Storable<GalakPizzaCore> { private final Map<String, PlanetOrders> orders = new HashMap<>(); private long orderSequence = 1; public long placeOrder(String planet, Variant variant, Size size) { final long id = orderSequence++; final Order order = new Order(id, planet, variant, size); assignOrderToPlanet(order); return id; }
  25. 25. Normal place order public class GalakPizzaCore implements GalakPizzaService, Serializable, Storable<GalakPizzaCore> { private final Map<String, PlanetOrders> orders = new HashMap<>(); private long orderSequence = 1; public long placeOrder(String planet, Variant variant, Size size) { final long id = orderSequence++; final Order order = new Order(id, planet, variant, size); assignOrderToPlanet(order); return id; } private void assignOrderToPlanet(Order order) { final PlanetOrders po = orders.computeIfAbsent(order.planet, planetName -> new PlanetOrders(planetName)); po.assignOrder(order); ...
  26. 26. Normal place order public class GalakPizzaCore implements GalakPizzaService, Serializable, Storable<GalakPizzaCore> { private final Map<String, PlanetOrders> orders = new HashMap<>(); private long orderSequence = 1; private AtomicLong ordersTotal = new AtomicLong(0); public long placeOrder(String planet, Variant variant, Size size) { final long id = orderSequence++; final Order order = new Order(id, planet, variant, size); assignOrderToPlanet(order); ordersTotal.incrementAndGet(); return id; } private void assignOrderToPlanet(Order order) { final PlanetOrders po = orders.computeIfAbsent(order.planet, planetName -> new PlanetOrders(planetName)); po.assignOrder(order); ...
  27. 27. Normal place order revisited public class GalakPizzaCore { ... private final Map<String, PlanetOrders> orders = new HashMap<>(); private PriorityQueue<PlanetOrders> bestPlanets = new PriorityQueue<>(256); private long orderSequence = 1; private AtomicLong ordersTotal = new AtomicLong(0); public long placeOrder(String planet, Variant variant, Size size) { final long id = orderSequence++; final Order order = new Order(id, planet, variant, size); assignOrderToPlanet(order); ordersTotal.incrementAndGet(); return id; } private void assignOrderToPlanet(Order order) { final PlanetOrders po = orders.computeIfAbsent(order.planet, planetName -> new PlanetOrders(planetName)); po.assignOrder(order); this.bestPlanets.offer(po); }
  28. 28. Normal place order revisited public class GalakPizzaCore { ... private final Map<String, PlanetOrders> orders = new HashMap<>(); private PriorityQueue<PlanetOrders> bestPlanets = new PriorityQueue<>(256); private long orderSequence = 1; private AtomicLong ordersTotal = new AtomicLong(0); public long placeOrder(String planet, Variant variant, Size size) { final long id = orderSequence++; final Order order = new Order(id, planet, variant, size); assignOrderToPlanet(order); ordersTotal.incrementAndGet(); return id; } private void assignOrderToPlanet(Order order) { final PlanetOrders po = orders.computeIfAbsent(order.planet, planetName -> new PlanetOrders(planetName)); po.assignOrder(order); this.bestPlanets.offer(po); BAD BAD BAD BAD }
  29. 29. Normal place order revisited public class GalakPizzaCore { ... private final Map<String, PlanetOrders> orders = new HashMap<>(); private PriorityQueue<PlanetOrders.Wrapper> bestPlanets = new PriorityQueue<>(256); private long orderSequence = 1; private AtomicLong ordersTotal = new AtomicLong(0); public long placeOrder(String planet, Variant variant, Size size) { final long id = orderSequence++; final Order order = new Order(id, planet, variant, size); assignOrderToPlanet(order); ordersTotal.incrementAndGet(); return id; } private void assignOrderToPlanet(Order order) { final PlanetOrders po = orders.computeIfAbsent(order.planet, planetName -> new PlanetOrders(planetName)); po.assignOrder(order); this.bestPlanets.offer(new PlanetOrders.Wrapper(po)); }
  30. 30. Wrapper... yeah public static class Wrapper implements Comparable<Wrapper>,Serializable{ final PlanetOrders porders; final int size; //just keep it final public Wrapper(PlanetOrders porders) { this.porders = porders; this.size = porders.orders.size(); } @Override public int compareTo(final Wrapper other) { return other.size - this.size; } }
  31. 31. PlanetOrders – take orders class PlanetOrders implements Serializable { final String name; private List<Order> orders = new ArrayList<>(); List<Order> takeOrders() { final List<Order> result = this.orders; this.orders = new ArrayList<>(); return result; } public boolean isEmpty() { return this.orders.isEmpty(); } }
  32. 32. PlanetOrders – take orders class PlanetOrders implements Serializable { final String name; private List<Order> orders = new ArrayList<>(); List<Order> takeOrders() { final List<Order> result = this.orders; this.orders = new ArrayList<>(); //yes we MUTATE! return result; } public boolean isEmpty() { return this.orders.isEmpty(); } }
  33. 33. Normal take orders public class GalakPizzaCore implements GalakPizzaService, Serializable, Storable<GalakPizzaCore> { privateprivate PriorityQueue<PlanetOrders.Wrapper>PriorityQueue<PlanetOrders.Wrapper> bestPlanetsbestPlanets == newnew PriorityQueue<>(PriorityQueue<>(256256);); private AtomicLong ordersTotal = new AtomicLong(0); public List<Order> takeOrdersFromBestPlanet() { final Optional<PlanetOrders> planetOpt = takeBestPlanet(); .... } private Optional<PlanetOrders> takeBestPlanet() { PlanetOrders.Wrapper planet = this.bestPlanets.poll(); while (planet != null && planet.porders.isEmpty()) { planet = this.bestPlanets.poll(); } return Optional.ofNullable(planet).map(p->p.porders); }
  34. 34. Normal take orders public class GalakPizzaCore implements GalakPizzaService, Serializable, Storable<GalakPizzaCore> { privateprivate PriorityQueue<PlanetOrders.Wrapper>PriorityQueue<PlanetOrders.Wrapper> bestPlanetsbestPlanets == newnew PriorityQueue<>(PriorityQueue<>(256256);); private AtomicLong ordersTotal = new AtomicLong(0); public List<Order> takeOrdersFromBestPlanet() { final Optional<PlanetOrders> planetOpt = takeBestPlanet(); if (planetOpt.isPresent()) { final PlanetOrders planet = planetOpt.get(); List<Order> orders = planet.takeOrders(); return orders; } return Collections.EMPTY_LIST; } private Optional<PlanetOrders> takeBestPlanet() { PlanetOrders.Wrapper planet = this.bestPlanets.poll(); while (planet != null && planet.porders.isEmpty()) { planet = this.bestPlanets.poll(); } return Optional.ofNullable(planet).map(p->p.porders); }
  35. 35. Normal take orders public class GalakPizzaCore implements GalakPizzaService, Serializable, Storable<GalakPizzaCore> { privateprivate PriorityQueue<PlanetOrders.Wrapper>PriorityQueue<PlanetOrders.Wrapper> bestPlanetsbestPlanets == newnew PriorityQueue<>(PriorityQueue<>(256256);); private AtomicLong ordersTotal = new AtomicLong(0); public List<Order> takeOrdersFromBestPlanet() { final Optional<PlanetOrders> planetOpt = takeBestPlanet(); if (planetOpt.isPresent()) { final PlanetOrders planet = planetOpt.get(); List<Order> orders = planet.takeOrders(); ordersTotal.addAndGet(-orders.size()); return orders; } return Collections.EMPTY_LIST; } private Optional<PlanetOrders> takeBestPlanet() { PlanetOrders.Wrapper planet = this.bestPlanets.poll(); while (planet != null && planet.porders.isEmpty()) { planet = this.bestPlanets.poll(); } return Optional.ofNullable(planet).map(p->p.porders); }
  36. 36. Normal count orders private AtomicLong ordersTotal = new AtomicLong(0); public long countStandingOrders() { return this.ordersTotal.get(); }
  37. 37. We have service - but do we deal with? Concurrency Persistence
  38. 38. Normal - Alien service wrapper public class GalakPizza implements GalakPizzaService { final PersistenceController<GalakPizzaCoreGalakPizzaCore,GalakPizzaCore> controller; public GalakPizza() { controller = PrevaylerBuilder.newBuilder() .withinUserFolder("pizza") .useSupplier( () -> new GalakPizzaCore()) .build(); } public long placeOrder(final String planet, final Variant variant, final Size size) { return controller.executeAndQuery( core -> core.placeOrder(planet,variant,size)core.placeOrder(planet,variant,size)); } public List<Order> takeOrdersFromBestPlanet() { return controller.executeAndQuery( core ->core.takeOrdersFromBestPlanet()core.takeOrdersFromBestPlanet()); } public long countStandingOrders() { return controller.query( c->c.countStandingOrders()c.countStandingOrders()); } ... }
  39. 39. Done!
  40. 40. In alternative universe https://github.com/airomem/galakpizza/tree/master/galakpizza_h
  41. 41. Other Domain @Entity @Table(name="T_ORDER") @NamedQueries( { @NamedQuery(name = "select best planet", query = "SELECT o.planet, count(o) FROM Order o " + " GROUP BY o.planet ORDER BY count(o) desc"), @NamedQuery(name = "select orders", query = "SELECT o FROM Order o WHERE o.planet = :planet"), @NamedQuery(name = "count orders", query = "SELECT count(o) FROM Order o ") }) public class Order { @Id @GeneratedValue(generator="increment") @GenericGenerator(name="increment", strategy = "increment") final long id; public final String planet; public final Variant variant; public final Size size; protected Order() { this("this is strange...", null, null); } public Order(String planet, Variant variant, Size size) { this.planet = planet; this.variant = variant; this.size = size; id = 0; } public long getId() { return id; } }
  42. 42. Other domain (same as above) public enum Size { MEDIUM, LARGE, XL } public enum Variant { HAWAII, MARGHERITA, VEGETARIAN }
  43. 43. It is in TABLE so it exists
  44. 44. Other service (same) public interface GalakPizzaOrders { long placeOrder(String planet, Variant variant, Size size); } public interface GalakPizzaDelivery { List<Order> takeOrdersFromBestPlanet(); long countStandingOrders(); } public interface GalakPizzaService extends GalakPizzaDelivery, GalakPizzaOrders{ }
  45. 45. Select best blanet... SELECT o.planet, count(o) FROM Order o GROUP BY o.planet ORDER BY count(o) desc
  46. 46. Other Planet (but almost same story) @Entity @Table(name="T_PLANET", indexes = {@Index(name="cnt_idx", columnList = "count", unique = false)} ) @NamedQueries( { @NamedQuery(name = "select best planet from table", query = "SELECT p FROM Planet p " + " ORDER BY p.count desc")}) public class Planet { @Id public final String name; private int count; protected Planet() { name = "default"; } public Planet(String name) { this.name = name; } public int getCount() { return this.count; } public void increment() { this.count++; } public void clear() { this.count = 0; } }
  47. 47. Other service implementation public class GalakPizza implements GalakPizzaService { final SessionFactory sessionFactory; public GalakPizza(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } public long placeOrder(String planet, Variant variant, Size size) { ... } public List<Order> takeOrdersFromBestPlanet() { ... } public long countStandingOrders() { ... } }
  48. 48. Other - Place order public long placeOrder(String planet, Variant variant, Size size) { return this.runInSession(session -> { final Order orderEntity = new Order(planet, variant, size); final Long key = (Long) session.save(orderEntity); incrementPlanetCounter(planet, session); return key; }); } private void incrementPlanetCounter(String planet, Session session) { Planet planetEntity = session.get(Planet.class, planet); if (planetEntity == null) { planetEntity = new Planet(planet); session.save(planetEntity); } planetEntity.increment(); } private <T> T runOnSession(Function<Session, T> dbCommand) { ...}
  49. 49. Other - runInSession private <T> T runInSession(Function<Session, T> dbCommand) { final Session session = sessionFactory.openSession(); session.beginTransaction(); try { final T result = dbCommand.apply(session); session.getTransaction().commit(); session.close(); return result; } catch (ConstraintViolationException cve) { session.getTransaction().rollback(); session.close(); return runInSession(dbCommand); } catch (Throwable t) { t.printStackTrace(); throw new RuntimeException(t); } } So easy
  50. 50. Other - Take orders public List<Order> takeOrdersFromBestPlanet() { return this.runInSession(session -> { final Query bestPlanetQuery = session.getNamedQuery("SELECT p FROM Planet p " + " ORDER BY p.count desc"); bestPlanetQuery.setMaxResults(1); final Iterator<Planet> bestPlanetsIterator = bestPlanetQuery.iterate(); if (bestPlanetsIterator.hasNext()) { final Planet bestOne = bestPlanetsIterator.next(); final Query ordersQuery = session.getNamedQuery("SELECT o FROM Order o WHERE o.planet = :planet"); ordersQuery.setParameter("planet", bestOne.name); final List<Order> orders = ordersQuery.list(); orders.forEach(o -> session.delete(o)); bestOne.clear(); return orders; } return Collections.EMPTY_LIST; }); }
  51. 51. Other – count orders @Override public long countStandingOrders() { return this.runInSession(session -> { final Query ordersCount = session.getNamedQuery("count orders"); final Long cnt = (Long) ordersCount.iterate().next(); return cnt; }); }
  52. 52. Other - others Hibernate config, init MySql config
  53. 53. After one day of coding...
  54. 54. In a real galaxy
  55. 55. That we can simulate as Customers - 4 Threads doing in loop placeOrder (random planet name, variant and size) – no pauses PizzBoy - 1 Thread doing in loop takeBestOrder – no pauses Owners – 2 Threads doing in loop – countStandingOrders
  56. 56. Galaxy simulation public static void main(String... args) { runSimulation(5000); System.gc(); sleep(); Result result = runSimulation(SECONDS_TOTAL*1000); System.out.println("Orders processed:" + result.processed); System.out.println("p/s:" + (double)result.processed/(double) SECONDS_TOTAL); System.out.println("Orders seen:" + result.seen); System.out.println("o/s:" + (double)result.seen/(double) SECONDS_TOTAL); }
  57. 57. ?
  58. 58. Normal universe Other universe ~40 000 p/s ~600 p/s Processed orders
  59. 59. Normal universe Other universe ~ 12 823 500 p/s ~6362 p/s Peeping speed
  60. 60. Normal universe Other universe
  61. 61. Normal universe Other universe GODS of SQL HELP! ME
  62. 62. Normal universe Other universe ~60 000 p/s ~1000 p/s
  63. 63. After few days of operations...
  64. 64. Normal universe Other universe
  65. 65. Cool, that it runs on laptop
  66. 66. Reality strickes back I do not trust PizzaBoy I want to know where exactly were pizzas delivered
  67. 67. Normal universe Other universe Cool, we will not delete orders any more, only mark them as deleted! Cool, we will add a list that will be processed during takeOrders, or maybe we will store data in DB Table (as archive)
  68. 68. Reality strickes back I do not trust PizzaBoy I want to know where were pizzas delivered Yesterday!!!
  69. 69. Normal universe Other universe Crap... We will restart system and commands will be reprocessed
  70. 70. Yet another real world case
  71. 71. System evolves I want to let people compose their pizza/ Like: more cheese on one half, and no meat on the next half, And onion on the third half.
  72. 72. Normal universe Other universe We will map it with only 20 tables Or do we add TEXT field? public Order(long id, String planet, Supplier<Variant> pizzaDescription, Size size) { public Order(long id, String planet, Variant variant, Size size) { We will use factory
  73. 73. Difference + Fast + Code in Java + „Strongly“ typed + Flexible + Testable - Sophisticated java - Terribly slow - Code in Strings and Annotations - Stringly typed - Limited domain - Testing expensive + Easy java
  74. 74. Why different ?
  75. 75. Long time ago
  76. 76. Sweet spot known as 90's Computers had mostly one CPU Core Memory (RAM) was expensive but more as 100MB available in single unit Disks were slow but huge (like 2Gb-20Gb) Time for JEE
  77. 77. Around galactic year 2003
  78. 78. Normal universe RAM is so cheap and huge Computers have multiple cores Alien developers start to use full power of hardware with Java No need to store data in databases anymore Because RAM is so cheap and huge
  79. 79. Other universe RAM is cheap and huge Computers have multiple cores But alien developers have never realised that
  80. 80. Other universe is a good place Database vendors earn money and are happy Application Servers vendors earn money and are happy Power plants are happy Hardware vendors are happy Only business complains – but they still pay Developers have a lot more work to do – they are happy.. Gfx By pressfoto / Freepik
  81. 81. DB / ORM vs Prevalence Problems Problem Prevalent (Normal) ORMs (Other) Detached objects Yes Yes Transaction isolation Yes in JAVA (concurrency) Yes in DB Testing Trivial Awful Cache It is all cache Lots of configs... Magic Contained Everywhere Mapping All serializable goes Limited
  82. 82. If you want to jump to normal universe...
  83. 83. Simple start Prevayler or Airomem (Prevayler wrapper for Java 8 ) or Nothing :-)
  84. 84. Airomem quick - maven <dependency> <groupId>pl.setblack</groupId> <artifactId>airomem-core</artifactId> <version>1.0.5</version> </dependency>
  85. 85. Airomem - init PersistenceController<GalakPizzaCore,GalakPizzaCore> controller = controller = PrevaylerBuilder .newBuilder() .withinUserFolder("pizza") .useSupplier( () -> new GalakPizzaCore()) .build(); GalakPizzaCore is main/plain object - Root aggregate! Must be Serializable! (how bad)
  86. 86. Airomem – commands controller.executeAndQuery( core->core.placeOrder(planet, variant, size )); ---------------------- controller.executeAndQuery( new PlaceOrderCommand(planet,variant,size)); private static final class PlaceOrderCommand implements Command<GalakPizzaCore, Long> { private final String planet; private final Variant variant; private final Size size; public PlaceOrderCommand(String planet, Variant variant, Size size){ this.planet = planet; this.variant = variant; this.size = size; } public Long execute(GalakPizzaCore system) { return system.placeOrder(planet,variant, size); } }
  87. 87. Commands are never executed concurrently
  88. 88. Query controller.query( c->c.countStandingOrders()); Queries are executed concurrently - also with one command!
  89. 89. Airomem – snapshots, events jarek@ubuntu:~$ cd prevayler/ jarek@ubuntu:~/prevayler$ ls pizza jarek@ubuntu:~/prevayler$ cd pizza/ jarek@ubuntu:~/prevayler/pizza$ ls -al total 188 drwxrwxr-x 2 jarek jarek 4096 May 6 14:46 . drwxrwxr-x 3 jarek jarek 4096 Apr 26 13:40 .. -rw-rw-r-- 1 jarek jarek 675 Apr 26 14:17 0000000000000000001.journal -rw-rw-r-- 1 jarek jarek 3375 Apr 26 14:18 0000000000000000002.journal -rw-rw-r-- 1 jarek jarek 3369 May 5 10:51 0000000000000000007.journal -rw-rw-r-- 1 jarek jarek 683 May 5 13:48 0000000000000000012.journal -rw-rw-r-- 1 jarek jarek 2048 May 5 14:12 0000000000000000012.snapshot -rw-rw-r-- 1 jarek jarek 497 May 5 14:12 0000000000000000013.journal -rw-rw-r-- 1 jarek jarek 1849 May 5 14:15 0000000000000000013.snapshot -rw-rw-r-- 1 jarek jarek 497 May 5 14:15 0000000000000000014.journal -rw-rw-r-- 1 jarek jarek 1685 May 5 14:17 0000000000000000014.snapshot -rw-rw-r-- 1 jarek jarek 8086 May 5 14:19 0000000000000000015.journal -rw-rw-r-- 1 jarek jarek 1084 May 6 13:25 0000000000000000028.snapshot -rw-rw-r-- 1 jarek jarek 57977 May 6 14:05 0000000000000000029.journal -rw-rw-r-- 1 jarek jarek 1228 May 6 14:46 0000000000000000132.snapshot -rw-rw-r-- 1 jarek jarek 59021 May 8 04:28 0000000000000000133.journal
  90. 90. Problems?
  91. 91. RAM?
  92. 92. Data migration Not big deal in fact Java Serialization (sth to learn) readResolve, writeReplace XML export option
  93. 93. Transaction This is always transactional!!! public Long execute(GalakPizzaCore system) { return system.placeOrder(planet,variant, size); }
  94. 94. Concurrency Learn java.util.concurrent, synchronized or die!
  95. 95. Replication/ failover Not in standard... but Trivial to implement - send events to other machines, share folder
  96. 96. Indices Indices in memory do exists CQEngine Query<Car> query1 = or(endsWith(Car.NAME, "vic"), lessThan(Car.CAR_ID, 2)); for (Car car : cars.retrieve(query1)) { System.out.println(car); }
  97. 97. Airomem summary CQRS + ES simplified - one command one event→ With RAM projection
  98. 98. More enterprisy alternatives Lagom! Akka persistence CQRS generally
  99. 99. Advice Remember to add Thread.sleep(1000) often
  100. 100. Storing in Prevayler vs DB model events vs model domain store facts vs store state Shared state is a cache vs shared state is a problem Domain with little magic vs domain polluted Clean architecture vs Maybe DDD can help...
  101. 101. End Try on something small first (not bigger then one planet) Drop DB from core of your system Drop your application servers Drop annotations Drop magic Learn Java and algorithms Feel the power of RAM and CPU alltogether!

×