sageserpent-open / plutonium

CQRS providing bitemporal object modelling for Java POJOs and Scala too.
MIT License
5 stars 0 forks source link

Plutonium - bitemporal CQRS for Plain Old Java Objects (and Scala too) Build Status

Pardon?

No, you are not about to be invited to purchase some fissile material of any isotopic constitution whatsover.

Plutonium is a software component that:-

It takes a CQRS approach to doing this, working off imperative events and furnishing a purely functional query API. It is intended for use by both Java and Scala projects.

Plutonium does not:-

Where?

It is published via Bintray to JCenter.

SBT

Add this to your build.sbt:

resolvers += Resolver.jcenterRepo

libraryDependencies += "com.sageserpent" %% "plutonium" % "1.3.0"

Gradle

Add this to your build.gradle:

repositories {
    jcenter()
}

dependencies {
    compile 'com.sageserpent:plutonium_2.12:1.3.0'
}

release history here

Show me...

jshell> /reload
|  Restarting and restoring state.
-: import com.sageserpent.americium.NegativeInfinity;
-: import com.sageserpent.americium.Unbounded;
-: import com.sageserpent.plutonium.World;
-: import com.sageserpent.plutonium.WorldReferenceImplementation;
-: import com.sageserpent.plutonium.javaApi.*;
-: import java.time.Instant;
-: World<Integer> world = new WorldReferenceImplementation<>();
-: NegativeInfinity<Instant> atTheBeginningOfTime = NegativeInfinity.apply();
-: {
       final Instant asOf = Instant.now();

       final int eventId = 0;

       world.revise(eventId, Change.forOneItem(atTheBeginningOfTime, "Fred", Account.class, accountItem -> {
           accountItem.setCash(5.0);
       }), asOf);

       final int followingRevision = world.nextRevision();

       final Scope scope = world.scopeFor(atTheBeginningOfTime, followingRevision);

       final Account account = scope.render(Bitemporal.withId("Fred", Account.class)).head();

       System.out.println(followingRevision);
       System.out.println(atTheBeginningOfTime);
       System.out.println(account.getCash());
   }
1
NegativeInfinity()
5.0

Revision Zero

-: Instant toStartWith = Instant.ofEpochSecond(0);
-: int rememberThisEventId = 1;
-: {
       final Instant asOf = Instant.now();

       world.revise(rememberThisEventId, Change.forOneItem(toStartWith, "Fred", Account.class, accountItem -> {
           accountItem.setCash(3.8);
       }), asOf);

       final int followingRevision = world.nextRevision();

       final Scope scope = world.scopeFor(toStartWith, followingRevision);

       final Account account = scope.render(Bitemporal.withId("Fred", Account.class)).head();

       System.out.println(followingRevision);
       System.out.println(toStartWith);
       System.out.println(account.getCash());
   }
2
1970-01-01T00:00:00Z
3.8

Revision One

-: Instant oneHourLater = toStartWith.plusSeconds(3600L);
-: {
       final Instant asOf = Instant.now();

       final int eventId = 2;

       world.revise(eventId, Change.forOneItem(oneHourLater, "Fred", Account.class, accountItem -> {
           accountItem.setCash(6.7);
       }), asOf);

       final int followingRevision = world.nextRevision();

       final Scope scope = world.scopeFor(oneHourLater, followingRevision);

       final Account account = scope.render(Bitemporal.withId("Fred", Account.class)).head();

       System.out.println(followingRevision);
       System.out.println(oneHourLater);
       System.out.println(account.getCash());
   }
3
1970-01-01T01:00:00Z
6.7

Revision Two

-: Instant twoHoursLater = oneHourLater.plusSeconds(3600L);
-: {
       final Instant asOf = Instant.now();

       final int eventId = 3;

       world.revise(eventId, Annihilation.apply(twoHoursLater, "Fred", Account.class), asOf);

       final int followingRevision = world.nextRevision();

       System.out.println(followingRevision);
       System.out.println(twoHoursLater);
   }
4
1970-01-01T02:00:00Z

Revision Three (annihilation)

-: {
       final Instant asOf = Instant.now();

       world.revise(rememberThisEventId, Change.forOneItem(toStartWith, "Fred", Account.class, accountItem -> {
           accountItem.setCash(3.0);
       }), asOf);

       final int followingRevision = world.nextRevision();

       System.out.println(followingRevision);
       System.out.println(toStartWith);
   }
5
1970-01-01T00:00:00Z

Revision Four (correct an event)

-: {
       final int followingRevision = 0;

       final Scope scope = world.scopeFor(twoHoursLater, followingRevision);

       System.out.println(followingRevision);
       System.out.println(twoHoursLater);
       System.out.println(scope.render(Bitemporal.withId("Fred", Account.class)).isEmpty());
   }
0
1970-01-01T02:00:00Z
true

Empty World

-: {
       int followingRevision = 1;

       final Scope scope = world.scopeFor(atTheBeginningOfTime, followingRevision);

       final Account account = scope.render(Bitemporal.withId("Fred", Account.class)).head();

       System.out.println(followingRevision);
       System.out.println(atTheBeginningOfTime);
       System.out.println(account.getCash());
   }
1
NegativeInfinity()
5.0

Revision Zero Revisited

-: {
       final int followingRevision = 2;

       final Scope scope = world.scopeFor(atTheBeginningOfTime, followingRevision);

       final Account account = scope.render(Bitemporal.withId("Fred", Account.class)).head();

       System.out.println(followingRevision);
       System.out.println(atTheBeginningOfTime);
       System.out.println(account.getCash());
   }
2
NegativeInfinity()
5.0

Revision One Revisited

-: {
       int followingRevision = 3;

       {
           final Scope scope = world.scopeFor(atTheBeginningOfTime, followingRevision);

           final Account account = scope.render(Bitemporal.withId("Fred", Account.class)).head();

           System.out.println(followingRevision);
           System.out.println(atTheBeginningOfTime);
           System.out.println(account.getCash());
       }

       {
           final Scope scope = world.scopeFor(twoHoursLater, followingRevision);

           final Account account = scope.render(Bitemporal.withId("Fred", Account.class)).head();

           System.out.println(followingRevision);
           System.out.println(twoHoursLater);
           System.out.println(account.getCash());
       }
   }
3
NegativeInfinity()
5.0
3
1970-01-01T02:00:00Z
6.7

Revision Two Revisited

-: {
       int followingRevision = 4;

       final Scope scope = world.scopeFor(twoHoursLater, followingRevision);

       final Iterable<Account> accountIterable = scope.renderAsIterable(Bitemporal.withId("Fred", Account.class));

       System.out.println(followingRevision);
       System.out.println(twoHoursLater);
       System.out.println(accountIterable.iterator().hasNext());
   }
4
1970-01-01T02:00:00Z
false

Revision Three Revisited

-: {
       final int followingRevision = 5;

       final Scope scope = world.scopeFor(toStartWith, followingRevision);

       final Account account = scope.render(Bitemporal.withId("Fred", Account.class)).head();

       System.out.println(followingRevision);
       System.out.println(toStartWith);
       System.out.println(account.getCash());
   }
5
1970-01-01T00:00:00Z
3.0

Revision Four Revisited

How?

See the example and following discussion here