Skip to content

Commit

Permalink
Tidy
Browse files Browse the repository at this point in the history
  • Loading branch information
bartelink committed Jan 24, 2022
1 parent 94f0aa1 commit 4611959
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 23 deletions.
23 changes: 12 additions & 11 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -703,9 +703,8 @@ elements you'll touch in a normal application are:
Transaction semantics that are central to Equinox and the overall `Decider` concept.
- [`type Decider`](https://github.com/jet/equinox/blob/master/src/Equinox/Decider.fs#L11) -
surface API one uses to `Transact` or `Query` against a specific stream's state
- [`type ResolveOption` Discriminated Union](https://github.com/jet/equinox/blob/master/src/Equinox/Decider.fs#L59) -
used to specify optimization overrides to be applied when
`resolve` hydrates a `Decider`
- [`type LoadOption` Discriminated Union](https://github.com/jet/equinox/blob/master/src/Equinox/Decider.fs#L59) -
used to specify optimization overrides to be applied when a `Decider`'s `Query` or `Transact` operations establishes the state of the stream

Its recommended to read the examples in conjunction with perusing the code in
order to see the relatively simple implementations that underlie the
Expand Down Expand Up @@ -1325,10 +1324,11 @@ let interpretMany fold interpreters (state : 'state) : 'state * 'event list =
type Service internal (resolve : CartId -> Equinox.Decider<Events.Event, Fold.State>) =
member __.Run(cartId, optimistic, commands : Command seq, ?prepare) : Async<Fold.State> =
let decider = resolve (cartId,if optimistic then Some Equinox.AllowStale else None)
decider.TransactAsync(fun state -> async {
let decider = resolve cartId
let opt = if optimistic then Equinox.AllowStale else Equinox.RequireLoad
decider.Transact(fun state -> async {
match prepare with None -> () | Some prep -> do! prep
return interpretMany Fold.fold (Seq.map interpret commands) state })
return interpretMany Fold.fold (Seq.map interpret commands) state }, opt)
```

<a name="accumulator"></a>
Expand Down Expand Up @@ -1368,7 +1368,7 @@ type Accumulator<'event, 'state>(fold : 'state -> 'event seq -> 'state, originSt
interpret __.State |> accumulated.AddRange
/// Invoke an Async decision function, gathering the events (if any) that
/// it decides are necessary into the `Accumulated` sequence
member __.TransactAsync(interpret : 'state -> Async<'event list>) : Async<unit> = async {
member __.Transact(interpret : 'state -> Async<'event list>) : Async<unit> = async {
let! events = interpret __.State
accumulated.AddRange events }
/// Invoke a decision function, while also propagating a result yielded as
Expand All @@ -1379,21 +1379,22 @@ type Accumulator<'event, 'state>(fold : 'state -> 'event seq -> 'state, originSt
result
/// Invoke a decision function, while also propagating a result yielded as
/// the fst of an (result, events) pair
member __.TransactAsync(decide : 'state -> Async<'result * 'event list>) : Async<'result> = async {
member __.Transact(decide : 'state -> Async<'result * 'event list>) : Async<'result> = async {
let! result, newEvents = decide __.State
accumulated.AddRange newEvents
return result }
type Service ... =
member __.Run(cartId, optimistic, commands : Command seq, ?prepare) : Async<Fold.State> =
let decider = resolve (cartId,if optimistic then Some Equinox.AllowStale else None)
decider.TransactAsync(fun state -> async {
let decider = resolve cartId
let opt = if optimistic then Some Equinox.AllowStale else Equinox.RequireLoad
decider.Transact(fun state -> async {
match prepare with None -> () | Some prep -> do! prep
let acc = Accumulator(Fold.fold, state)
for cmd in commands do
acc.Transact(interpret cmd)
return acc.State, acc.Accumulated
})
}, opt)
```

# Equinox Architectural Overview
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,7 @@ and Equinox will supply the _initial_ value for the `project` function to render

> Side note: the original question is for a read operation, but there's an interesting consideration if we are doing a `Transact`. Say,
> for instance, that there's a PUT API endpoint where the code would register a fresh customer order for the customer in its order list
> via the Decider's `Transact` operation. As an optimization, one can utilize the `AssumeEmpty` hint as the `Equinox.ResolveOption` to
> via the Decider's `Transact` operation. As an optimization, one can utilize the `AssumeEmpty` hint as the `Equinox.LoadOption` to
> hint that it's worth operating on the assumption that the stream is empty. When the internal sync operation attempts to perform the write,
> that assumption will be tested; every write is always version checked.
> In the scenario where we are dealing with a rerun of an attempt to create an order (lets say the call timed out, but the processing actually
Expand Down
9 changes: 5 additions & 4 deletions samples/Store/Domain/Cart.fs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ type Accumulator<'event, 'state>(fold : 'state -> 'event seq -> 'state, originSt
member __.Transact(interpret : 'state -> 'event list) : unit =
interpret __.State |> accumulated.AddRange
/// Invoke an Async decision function, gathering the events (if any) that it decides are necessary into the `Accumulated` sequence
member __.TransactAsync(interpret : 'state -> Async<'event list>) : Async<unit> = async {
member __.Transact(interpret : 'state -> Async<'event list>) : Async<unit> = async {
let! events = interpret __.State
accumulated.AddRange events }
/// Invoke a decision function, while also propagating a result yielded as the fst of an (result, events) pair
Expand All @@ -121,7 +121,7 @@ type Accumulator<'event, 'state>(fold : 'state -> 'event seq -> 'state, originSt
accumulated.AddRange newEvents
result
/// Invoke a decision function, while also propagating a result yielded as the fst of an (result, events) pair
member __.TransactAsync(decide : 'state -> Async<'result * 'event list>) : Async<'result> = async {
member __.Transact(decide : 'state -> Async<'result * 'event list>) : Async<'result> = async {
let! result, newEvents = decide __.State
accumulated.AddRange newEvents
return result }
Expand All @@ -142,13 +142,14 @@ type Service internal (resolve : CartId -> Equinox.Decider<Events.Event, Fold.St
#if ACCUMULATOR
let acc = Accumulator(Fold.fold, state)
for cmd in commands do
acc.Transact(interpret cmd, opt)
acc.Transact(interpret cmd)
return acc.State, acc.Accumulated }
#else
return interpretMany Fold.fold (Seq.map interpret commands) state }
#endif
let decider = resolve cartId
decider.Transact(interpret, (if optimistic then Equinox.AllowStale else Equinox.RequireLoad))
let opt = if optimistic then Equinox.AllowStale else Equinox.RequireLoad
decider.Transact(interpret, opt)

member __.ExecuteManyAsync(cartId, optimistic, commands : Command seq, ?prepare) : Async<unit> =
__.Run(cartId, optimistic, commands, ?prepare=prepare) |> Async.Ignore
Expand Down
6 changes: 3 additions & 3 deletions src/Equinox.CosmosStore/CosmosStore.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1380,14 +1380,14 @@ type CachingStrategy =
/// Retain a single 'state per streamName, together with the associated etag.
/// Each cache hit for a stream renews the retention period for the defined <c>window</c>.
/// Upon expiration of the defined <c>window</c> from the point at which the cache was entry was last used, a full reload is triggered.
/// Unless <c>ResolveOption.AllowStale</c> is used, each cache hit still incurs an etag-contingent Tip read (at a cost of a roundtrip with a 1RU charge if unmodified).
/// Unless <c>LoadOption.AllowStale</c> is used, each cache hit still incurs an etag-contingent Tip read (at a cost of a roundtrip with a 1RU charge if unmodified).
// NB while a strategy like EventStore.Caching.SlidingWindowPrefixed is obviously easy to implement, the recommended approach is to
// track all relevant data in the state, and/or have the `unfold` function ensure _all_ relevant events get held in the `u`nfolds in Tip
| SlidingWindow of ICache * window : TimeSpan
/// Retain a single 'state per streamName, together with the associated etag.
/// Upon expiration of the defined <c>period</c>, a full reload is triggered.
/// Typically combined with `Equinox.ResolveOption.AllowStale` to minimize loads.
/// Unless <c>ResolveOption.AllowStale</c> is used, each cache hit still incurs an etag-contingent Tip read (at a cost of a roundtrip with a 1RU charge if unmodified).
/// Typically combined with `Equinox.LoadOption.AllowStale` to minimize loads.
/// Unless <c>LoadOption.AllowStale</c> is used, each cache hit still incurs an etag-contingent Tip read (at a cost of a roundtrip with a 1RU charge if unmodified).
| FixedTimeSpan of ICache * period : TimeSpan

[<NoComparison; NoEquality; RequireQualifiedAccess>]
Expand Down
4 changes: 2 additions & 2 deletions src/Equinox.EventStore/EventStore.fs
Original file line number Diff line number Diff line change
Expand Up @@ -575,11 +575,11 @@ type CachingStrategy =
/// Retain a single 'state per streamName.
/// Each cache hit for a stream renews the retention period for the defined <c>window</c>.
/// Upon expiration of the defined <c>window</c> from the point at which the cache was entry was last used, a full reload is triggered.
/// Unless <c>ResolveOption.AllowStale</c> is used, each cache hit still incurs a roundtrip to load any subsequently-added events.
/// Unless <c>LoadOption.AllowStale</c> is used, each cache hit still incurs a roundtrip to load any subsequently-added events.
| SlidingWindow of ICache * window : TimeSpan
/// Retain a single 'state per streamName.
/// Upon expiration of the defined <c>period</c>, a full reload is triggered.
/// Unless <c>ResolveOption.AllowStale</c> is used, each cache hit still incurs a roundtrip to load any subsequently-added events.
/// Unless <c>LoadOption.AllowStale</c> is used, each cache hit still incurs a roundtrip to load any subsequently-added events.
| FixedTimeSpan of ICache * period : TimeSpan
/// Prefix is used to segregate multiple folds per stream when they are stored in the cache.
/// Semantics are identical to <c>SlidingWindow</c>.
Expand Down
4 changes: 2 additions & 2 deletions src/Equinox.SqlStreamStore/SqlStreamStore.fs
Original file line number Diff line number Diff line change
Expand Up @@ -534,11 +534,11 @@ type CachingStrategy =
/// Retain a single 'state per streamName.
/// Each cache hit for a stream renews the retention period for the defined <c>window</c>.
/// Upon expiration of the defined <c>window</c> from the point at which the cache was entry was last used, a full reload is triggered.
/// Unless <c>ResolveOption.AllowStale</c> is used, each cache hit still incurs a roundtrip to load any subsequently-added events.
/// Unless <c>LoadOption.AllowStale</c> is used, each cache hit still incurs a roundtrip to load any subsequently-added events.
| SlidingWindow of ICache * window : TimeSpan
/// Retain a single 'state per streamName
/// Upon expiration of the defined <c>period</c>, a full reload is triggered.
/// Unless <c>ResolveOption.AllowStale</c> is used, each cache hit still incurs a roundtrip to load any subsequently-added events.
/// Unless <c>LoadOption.AllowStale</c> is used, each cache hit still incurs a roundtrip to load any subsequently-added events.
| FixedTimeSpan of ICache * period : TimeSpan
/// Prefix is used to segregate multiple folds per stream when they are stored in the cache.
/// Semantics are identical to <c>SlidingWindow</c>.
Expand Down

0 comments on commit 4611959

Please sign in to comment.