From 254dbc116f2d9f876a7abe4d436737b8df28424d Mon Sep 17 00:00:00 2001 From: Ruben Bartelink Date: Fri, 29 Nov 2019 22:49:40 +0000 Subject: [PATCH] Add README --- README.md | 1 + equinox-fc/Domain/Location.fs | 1 + equinox-fc/Fc.sln | 5 +++++ equinox-fc/README.md | 26 ++++++++++++++++++++++++++ 4 files changed, 33 insertions(+) create mode 100644 equinox-fc/README.md diff --git a/README.md b/README.md index b72f5c877..8f6e477b7 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ This repo hosts the source for Jet's [`dotnet new`](https://docs.microsoft.com/e - [`eqxweb`](equinox-web/README.md) - Boilerplate for an ASP .NET Core 2 Web App, with an associated storage-independent Domain project using [Equinox](https://github.com/jet/equinox). - [`eqxwebcs`](equinox-web-csharp/README.md) - Boilerplate for an ASP .NET Core 2 Web App, with an associated storage-independent Domain project using [Equinox](https://github.com/jet/equinox), _ported to C#_. - [`eqxtestbed`](equinox-testbed/README.md) - Host that allows running back-to-back benchmarks when prototyping models using [Equinox](https://github.com/jet/equinox), using different stores and/or store configuration parameters. +- [`eqxfc`](equinox-fc/README.md) - Samples showcasing various modeling and testing techniques such as (FsCheck-based) unit tests and use of `MemoryStore` for integration tests. ## [Propulsion](https://github.com/jet/propulsion) related diff --git a/equinox-fc/Domain/Location.fs b/equinox-fc/Domain/Location.fs index 50511d8d3..ff6b6b133 100644 --- a/equinox-fc/Domain/Location.fs +++ b/equinox-fc/Domain/Location.fs @@ -34,6 +34,7 @@ type LocationService internal (zeroBalance, shouldClose, series : Series.Service [] module Helpers = + let create (zeroBalance, shouldClose) (series, epochs) = LocationService(zeroBalance, shouldClose, series, epochs) diff --git a/equinox-fc/Fc.sln b/equinox-fc/Fc.sln index 2bf47b4d9..bfb82d823 100644 --- a/equinox-fc/Fc.sln +++ b/equinox-fc/Fc.sln @@ -7,6 +7,11 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Domain", "Domain\Domain.fsp EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Domain.Tests", "Domain.Tests\Domain.Tests.fsproj", "{AA589DC7-D0B7-4F95-BC29-6B89AF4E9280}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".project", ".project", "{FEADBAC9-0CA2-440B-AF9B-184FED9B362E}" +ProjectSection(SolutionItems) = preProject + README.md = README.md +EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/equinox-fc/README.md b/equinox-fc/README.md new file mode 100644 index 000000000..39e27fd7c --- /dev/null +++ b/equinox-fc/README.md @@ -0,0 +1,26 @@ +# Equinox FC Sample + +This project was generated using: + + dotnet new -i Equinox.Templates # just once, to install in the local templates store + + dotnet new eqxfc # use --help to see options regarding storage subsystem configuration etc + +# `Location*` + +The `Location`* `module`s illustrates a way to approach the modelling of a long-running state by having writers adhere to a common protocol when writing: + +- the `LocationEpoch` category represents a span of time, which is guaranteed to have a `CarriedForward` event representing the opening balance, and/or the balance carried forward when the preceding epoch was marked `Closed` +- the `LocationSeries` category bears the verified active epoch (competing readers/writers read this optimistically on a cached basis; in the event that they're behind, they'll compete to log the successful commencement of a new epoch, which cannot happen before the `CarriedForward` event for the successor epoch has been committed) + +- `Domain.Tests` includes (`FsCheck`) Property-based unit tests, and an integration tests that demonstrates parallel writes (that trigger Optimistic Concurrency Control-based conflict resolution, including against `MemoryStore`) + +## Notes + +- Referencing an `Equinox.*` Store module from the `Domain` project is not mandatory; it's common to defer all wiring and configuration of the elements in `module Cosmos`, `module EventStore` etc. and instead maintain that alongside the Composition Root, outside of the `Domain` project + +- While using an `AccessStrategy` such as `Snapshotting` may in some cases be relevant too, in the general case, using the `Equinox.Cache`, combined with having a compact Fold `State` and a sufficiently constrained maximum number/size of events means the state can be established within a predictable latency range. + +- Representing a long-running state in this fashion is no panacea; in modeling a system, the ideal is to have streams that have a naturally constrained number of events over their lifetime. + +- [Original PR](https://github.com/jet/dotnet-templates/pull/40) \ No newline at end of file