Skip to content
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

Support NEventStore #3

Open
bartelink opened this issue Jul 14, 2014 · 12 comments
Open

Support NEventStore #3

bartelink opened this issue Jul 14, 2014 · 12 comments

Comments

@bartelink
Copy link

With a small amount of work, the sample could also persist its events in NEventStore in a SQL database.

As I'll be developing a highly similar pair of readEvents / appendEvents, I could add it here, which would serve as a nice test bed (from my perspective).

However the obvious major risk is that adding yet another front end/store (esp if its in the same lib) is going to be the straw that changes the sample from an elegant communication tool to something that misses the point.

So my (obviously very debatable) proposal is for me to split the FsUno project into

  • FsUno.Domain (unchanged domain stuff)
  • FsUno.Persistence.EventStore (ref to EventStore nuget and GES specific code)
  • FsUno.Persistence.InMemory (off on its own)
  • FsUno.DemoExe

The major plus would be that FsUno would have a lot less files and the switchable stores becomes clearer

FsUno.Tests would only depend on FsUno.Domain and use NUnit

I'd then write a FsUno.Persistence.NEventStore which FsUno.DemoExe can also reference and then you just switch the store type ref in Main. The lib would:

  • have a NES Wireup with perhaps a connection string coming in but not much else as we are not generating a storage abstraction (and when you use NES for storage only, most of the Wireup pipeline is irrelevant)
  • have a helper to create the schema if it doesnt exist (NES exposes this and it fits with this being a demo) which one would call from FsUno.DemoExe

The likelihood is that Serialization.fs would be used for Persistence.NES and Persistence.GES. I'd propose to put the file in a FsUno.Persistence but just link to it from the 2x Persistence projects.

But why oh why do all this here?

  • I love FsUno.Domain and believe any sane person should def use the approach. But there should be a really good sample which is good enough to use as-is
  • I like NEventStore (I have code in prod and am starting a new project that will use it in prod - both on Azure PaaS).
  • I like GetEventStore (and will move to it eventually)
  • I will be using the DU Serialization you've implemented but don't want to maintain a fork (but would consider using a protobuf.net or FsPickler-based swappable impl if someone contributed that)

What could I do instead?

I could create a bartelink/FunDomain repo with

  • Samples/FunUno/Domain (stolen from FsUno)
  • Samples/FunUno/Tests (xUnit+Unquote)
  • Samples/FunUno/Demo (stolen from FsUno)
  • FunDomain.Persistence.NEventStore

The problem is that I can't imagine any traction and I'd just be sowing confusion by having a fork of your serialization (and/or your GES bindings)

I hope I've explained myself sufficiently for you to decide quickly which direction you'd like this to take - open to any subsets you consider reasonable and definitely will understand if you say "Don't go toppling my nice tidy sample please!"

@thinkbeforecoding
Copy link
Owner

Maybe I can start 2 versions of FsUno.. One being very lean to show the shortest way to functional event sourcing. One other presenting alternatives,and enhancements.
the second one would include:
Switchable stores
Load on call/in memory aggregates with agents
Snapshots or not...

@bartelink
Copy link
Author

@thinkbeforecoding Sounds good.

I assume the second/'serious' one would be async only ?

Main thing for me is having a fsproj with no common proj references per store. i.e if you have a XXX.Persistence.EventStore, I'd be able to throw in a matching XXX.Persistence.NEventStore (working on it in local repo - depending on when you have something up I'll either do a PR against yours or else a temp push elsewhere on a temporary basis until you've restructured).

@thinkbeforecoding
Copy link
Owner

Yes, I think so. Async only. No reason for making it sync.
And I would leave only the sync part in the first one.

I'll try to make the split shortly !

@bartelink
Copy link
Author

Thanks - think sync in Demo and async in Enterprise will split will help both.

I'm spiking in a local clone of https://github.com/bartelink/FunDomain

Depending on when you get to land your reorg I may push a preview there first.

@thinkbeforecoding
Copy link
Owner

How should we name the "production ready" implementation ?

@thinkbeforecoding
Copy link
Owner

Other question: Where would you put Command Handlers and projections ?

It has no direct dependency on infrastructure since readEvents and saveEvents are passed as parameters.. But it's not totally part of domain either...

@bartelink
Copy link
Author

Re naming

I guess if the repo is called FsUno, you could have

  • UnoComplete (Complet? Completo) Full Allonge ForReal
  • * Domain
  • * Persistence (folder with Serialization.fs only - I will use most of it for NEventStore. Of course this is highly debatable as it sends a bad message of there being a need to and/or a lot to share)
  • * Persistence.NEventStore
  • * Persistence.EventStore
  • * Persistence.Ram
  • UnoDemo (from FsUno) (Intro) Quickly Compact

Having the easy one sort to the top is a plus

@bartelink
Copy link
Author

I like the idea of having the core stuff in a Domain assembly so it can have low dependencies and/or be a PCL to optimize the unit test loop. (I know it doesnt need to go places PCLs need to go but I think its an important way to keep the focus on domain concerns)

The obvious issue with the rest is that it depends and you don't want to go too astronaut on it :)

The Command Handlers make sense to have in a FrontEnd layer as they'll invariably be involved in some dance with authorization and/or the composition root - be that a console app or a web project and there's nothing much you can do thats likely to be universally useful. I guess you need to pick the app type and that will inform the decision a lot ;)

If you get into splitting out projections, you also get forced into deciding whether the events get split out too (i.e. a separate assembly and/or file). I guess that points to leaving the projections in the front end.

Pehaps having a Handlers assembly with Command Handlers and Projections might make sense? In principle if both get passed functions, the only place a comment-in-out / reference change / addition needs to take place is in the composition root

For my FunDomain testbed, I will likely have Domain, Handlers, Persistence.NEventStore and Acceptance.NEventStore

The acceptance project will prob be the composition root and will wire up an NEventStore pointing at an empty SQL Server Local Db. The lib has a function to do the DDL.

At some stage, potentially I'll do an Agent to process Projections [driven from the Acceptance.NEventStore].

In my for real project, the default split will be a web project with Handlers and Projections subdirs in a web project. Maybe that might be an idea for a FsUno console app or web app?

(Thinking aloud) Any point in having the console app say whose turn it is and asking for a card to play (independent of shuffling/dealing) to make it 'more real'?

@bartelink
Copy link
Author

Have got an end to end with NEventStore [in memory, havce not actually run it into a SQL db but no reason it shouldnt]

I did some refactoring in the process which I'd appreciate comments on -- I've tried lots of things and would really like you to bat back some of them - esp unidiomatic and/or ugly to your sensibilities code.

I'm also thinking its time to implement Kickback and/or something else as its looking too small and boring with my succint syntax IMNSHO :)

Its at https://github.com/bartelink/FunDomain

@bartelink
Copy link
Author

@thinkbeforecoding Hi Jeremie, wondering whether you're sitting on a commit. I had a 2 week break en France which was v nice. Coming up relatively soon I'll be doing some [closed source] stuff on a Functional Event Sourcing stack.

I'm aiming to have it talk to NES over an async interface (NES is sync so that impl will do an async over sync wrapping) but also be able to be switchable to GES (or at a minimum not completely paint myself into a corner). Also will prob look at doing protobuf serialization as Acceptance.NES perf is pretty bad and I want to be able to rename fields without much messing.

Any thoughts on the structure of FunDomain ?

If you're planning to do for intro/for real splitting of the code base, I'd be happy to contribute.

If that doesnt fit your plan/availability.... Perfhaps if I renamed FunDomain to Fes (Functional Event Sourcing) and had

  • Fes.NEventStore (my code)
  • Fes.NEventStore.Acceptance (end to end including retrieval which my code doesnt do yet)
  • Fes.EventStore (either by you or by me, based on FsUno codebase but maybe reorder args a la my partial application stuff in FunDomain)
  • Samples/FunUno (xunit/unquote)

where would it live? I'd be happy with a separate org but equally so it you want to have it alongside/inside FsUno in order to avoid frameworkization.

@thinkbeforecoding
Copy link
Owner

Hehe, my weeks have been quite busy lately (kids vacations, work etc.), but I'm home alone this week, and I'll have time to put some more effort to all this. Tomorrow probably 😄

@bartelink
Copy link
Author

@thinkbeforecoding Cool; will hold off so. Playing with protobuf against DUs. Will likely make that a switchable aspect (perf for my NES acceptance test is pretty much unacceptable at moment).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants