-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add projection example for multiple aggregates #16
Conversation
@Fristi what do you think? can you spot anything that could be improved easily? |
libraryDependencies += "com.chuusai" %% "shapeless" % "2.2.5" | ||
|
||
resolvers += Resolver.sonatypeRepo("releases") | ||
|
||
addCompilerPlugin("org.spire-math" %% "kind-projector" % "0.6.3") | ||
|
||
wartremoverErrors ++= Warts.allBut(Wart.Any, Wart.Nothing, Wart.Throw, Wart.IsInstanceOf, Wart.AsInstanceOf, Wart.NoNeedForMonad) | ||
// wartremoverErrors ++= Warts.allBut(Wart.Any, Wart.Nothing, Wart.Throw, Wart.IsInstanceOf, Wart.AsInstanceOf, Wart.NoNeedForMonad) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: this is removed as there are lots of errors when using upickle. Options so far:
- investigate how to ignore specifically upickle errors
- swap upickle with an alternative lib
- disable wart remover :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Decouple encoding/decoding of events? So we let our users pick their own serialization lib
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, that should be already possible :)
I wonder if the wart remover was a good idea to have.. It works very well for the code in this repo but also limits the libraries we can use and a couldn't find a good way to disable it for implicit lookups from ext libs...
import InMemoryDb._ | ||
|
||
import scala.collection.immutable.TreeMap | ||
import DbAdapters.InMemoryDb._ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO, referencing the actual db adapter is still bad here - extract consumeEvents
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
solved
Hi @Fristi, any feedback on this version? currently the projection can be replayed from the start (events ordered by their creation) regardless of where in the process was it added. there are still some items to refactor, esp direct usage of the |
} | ||
} | ||
def emptyCounterProjection = Projection.empty[Data](TreeMap.empty, List( | ||
(Counter.tag, createEventDataConsumer( (d: Data, t: Tag, id: AggregateId, v: Int, e: Counter.Event) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: create intermediate type here
extract serialisation to a level above DB adapter operations and leave DB only for storing / retrieving strings?
final case class ReadAggregateExistence[E](id: AggregateId) extends EventDatabaseOp[E, Error Xor Boolean] | ||
final case class ReadAggregate[E](id: AggregateId, fromVersion: Int) extends EventDatabaseOp[E, Error Xor List[VersionedEvents[E]]] | ||
final case class AppendAggregateEvents[E](id: AggregateId, events: VersionedEvents[E]) extends EventDatabaseOp[E, Error Xor Unit] | ||
final case class ReadAggregateExistence[E](tag: Tag, id: AggregateId) extends EventDatabaseOp[E, Error Xor Boolean] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In akka-persistence events get a persistenceId
(which is a aggregateId
) and zero or more tags. In these cases you have to supply both. It would be nice to read events by a specific tag or a aggregateId. When writing you should write them along with one aggregatedId, but zero or more tags. Checking if a aggregate exists should only be done with a aggregateId
I think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The semantics of the tags in this PR are a bit different from akka - its more like aggregate class - eg all counters, or all doors. Checking if exists also needs it in this case - "is there a counter (by tag) identified by this id".
Projections tell what classes / tags of aggregates they are interested in and receive all aggregates within them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, makes abit sense. However, how would you read all events of a counter for example without knowing all the aggregateIds? case class ReadAggregate[E](tag: Tag, id: AggregateId, fromVersion: Int)
requires you to specify a AggregateId
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for this, there is currently a separate Database method as defined by the typeclass - https://github.com/svalaskevicius/eventflow/blob/multiEventsProjection/src/main/scala/Cqrs/Database.scala#L12
its not available in the aggregate actions as no aggregate should ever need that.. I think :)
Added some comments here and there. Overall I need to take a closer look what all constructs are doing conceptually. |
a0ae9bd
to
8592ee7
Compare
@@ -82,7 +80,12 @@ object Eventflow { | |||
fold(err => { println("Error occurred: " + err._2); err._1 }, r => { println("OK"); r._1 }) | |||
|
|||
@SuppressWarnings(Array("org.brianmckenna.wartremover.warts.OptionPartial", "org.brianmckenna.wartremover.warts.ExplicitImplicitTypes")) | |||
val _ = pprint.pprintln(db_, colors = pprint.Colors.Colored) | |||
val _ignore1 = pprint.pprintln(runner1, colors = pprint.Colors.Colored) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interesting that after some commit in this PR the pprint lost colours :/ (now its just showing toString result)
ok, looks a bit better now I hope :) @Fristi can you spot anything that has to be fixed before merging? |
libraryDependencies += "com.chuusai" %% "shapeless" % "2.2.5" | ||
|
||
resolvers += Resolver.sonatypeRepo("releases") | ||
|
||
addCompilerPlugin("org.spire-math" %% "kind-projector" % "0.6.3") | ||
|
||
wartremoverErrors ++= Warts.allBut(Wart.Any, Wart.Nothing, Wart.Throw, Wart.IsInstanceOf, Wart.AsInstanceOf, Wart.NoNeedForMonad) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No more wartremover? :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like wartremover.. when it works, but it seems to restrict libraries we can use conveniently at this point.. e.g. uPickle fails quite dramatically and I couldnt find a way to selectively disable it (as it fails when looking for implicits)..
do you have any ideas how can I restore it? (should I use another serialisation library?)
|
||
import scala.language.higherKinds | ||
|
||
object foldM { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this already in cats somewhere? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sadly no... there is an open PR for it - https://github.com/non/cats/pull/356 but its on hold
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah cool, let's address that later then!
Overall I think it's nice to get projections out there! There are some things we could improve here :) Sometimes I find it not easy to digest some of you code. How could we improve on that?
I can help you out with refactoring some parts! For now it would be good to merge this 👍 |
completely agree! :) in fact, I thought I am already doing most of those items :D apart from short names and no docs. happy to update the missed parts - in the end, I will have to read this as well even after I forget how it was implemented :) will have a skim over again and see what have I missed, thanks! |
add projection example for multiple aggregates
No description provided.