Skip to content

Commit

Permalink
Remove Accumulator
Browse files Browse the repository at this point in the history
  • Loading branch information
bartelink committed Dec 15, 2023
1 parent 8441e79 commit 364b628
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 46 deletions.
6 changes: 2 additions & 4 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -1363,7 +1363,7 @@ which can then summarize the overall transaction.
### Idiomatic approach - composed method based on side-effect free functions

There's an example of such a case in the
[Cart's Domain Service](https://github.com/jet/equinox/blob/master/samples/Store/Domain/Cart.fs#L128):
[Cart's Domain Service](https://github.com/jet/equinox/blob/master/samples/Store/Domain/Cart.fs#L106):

```fsharp
let interpretMany fold interpreters (state: 'state): 'state * 'event[] =
Expand Down Expand Up @@ -1392,9 +1392,7 @@ _NOTE: This is an example of an alternate approach provided as a counterpoint -
there's no need to read it as the preceding approach is the recommended one is
advised as a default strategy to use_

As illustrated in [Cart's Domain
Service](https://github.com/jet/equinox/blob/master/samples/Store/Domain/Cart.fs#L99),
an alternate approach is to encapsulate the folding (Equinox in V1 exposed an
An alternate approach is to encapsulate the folding (Equinox in V1 exposed an
interface that encouraged such patterns; this was removed in two steps, as code
written using the idiomatic approach is [intrinsically simpler, even if it
seems not as Easy](https://www.infoq.com/presentations/Simple-Made-Easy/) at
Expand Down
42 changes: 0 additions & 42 deletions samples/Store/Domain/Cart.fs
Original file line number Diff line number Diff line change
Expand Up @@ -103,40 +103,6 @@ let interpret command (state: Fold.State) =
| SyncItem (Context c, skuId, None, w) ->
yield! maybePropChanges c skuId w |]

#if ACCUMULATOR
// This was once part of the core Equinox functionality, but was removed in https://github.com/jet/equinox/pull/184
// it remains here solely to serve as an example; the PR details the considerations leading to this conclusion

/// Maintains a rolling folded State while Accumulating Events pended as part of a decision flow
type Accumulator<'event, 'state>(fold: 'state -> 'event[] -> 'state, originState: 'state) =
let accumulated = ResizeArray<'event>()

/// The Events that have thus far been pended via the `decide` functions `Execute`/`Decide`d during the course of this flow
member _.Accumulated: 'event[] =
accumulated.ToArray()

/// The current folded State, based on the Stream's `originState` + any events that have been Accumulated during the the decision flow
member _.State: 'state =
accumulated |> fold originState

/// Invoke a decision function, gathering the events (if any) that it decides are necessary into the `Accumulated` sequence
member x.Transact(interpret: 'state -> 'event[]): unit =
interpret x.State |> accumulated.AddRange
/// Invoke an Async decision function, gathering the events (if any) that it decides are necessary into the `Accumulated` sequence
member x.Transact(interpret: 'state -> Async<'event[]>): Async<unit> = async {
let! events = interpret x.State
accumulated.AddRange events }
/// Invoke a decision function, while also propagating a result yielded as the fst of an (result, events) pair
member x.Transact(decide: 'state -> 'result * 'event[]): 'result =
let result, newEvents = decide x.State
accumulated.AddRange newEvents
result
/// Invoke a decision function, while also propagating a result yielded as the fst of an (result, events) pair
member x.Transact(decide: 'state -> Async<'result * 'event[]>): Async<'result> = async {
let! result, newEvents = decide x.State
accumulated.AddRange newEvents
return result }
#else
let interpretMany fold interpreters (state: 'state): 'state * 'event[] =
let mutable state = state
let events = [|
Expand All @@ -145,21 +111,13 @@ let interpretMany fold interpreters (state: 'state): 'state * 'event[] =
yield! events
state <- fold state events |]
state, events
#endif

type Service internal (resolve: CartId -> Equinox.Decider<Events.Event, Fold.State>) =

member _.Run(cartId, optimistic, commands: Command seq, ?prepare): Async<Fold.State> =
let interpret state = async {
match prepare with None -> () | Some prep -> do! prep
#if ACCUMULATOR
let acc = Accumulator(Fold.fold, state)
for cmd in commands do
acc.Transact(interpret cmd)
return acc.State, acc.Accumulated }
#else
return interpretMany Fold.fold (Seq.map interpret commands) state }
#endif
let decider = resolve cartId
let opt = if optimistic then Equinox.LoadOption.AnyCachedValue else Equinox.LoadOption.RequireLoad
decider.Transact(interpret, opt)
Expand Down

0 comments on commit 364b628

Please sign in to comment.