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

Rebase on Codec logic extracted into FsCodec.System.Text.Json #202

Merged
merged 3 commits into from
Mar 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions samples/Infrastructure/Services.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

open Domain
open FsCodec
open FsCodec.SystemTextJson.Serialization
open Microsoft.Extensions.DependencyInjection
open System
open System.Text.Json
Expand Down Expand Up @@ -49,24 +48,24 @@ type ServiceBuilder(storageConfig, handlerLog) =
let snapshot = Favorites.Fold.isOrigin,Favorites.Fold.snapshot

match storageConfig with
| Storage.StorageConfig.Cosmos _ -> Backend.Favorites.Service(handlerLog, resolver.ResolveWithJsonElementCodec(Favorites.Events.JsonElementCodec.codec JsonSerializer.defaultOptions, fold, initial, snapshot))
| _ -> Backend.Favorites.Service(handlerLog, resolver.ResolveWithUtf8ArrayCodec(Favorites.Events.Utf8ArrayCodec.codec, fold, initial, snapshot))
| Storage.StorageConfig.Cosmos _ -> Backend.Favorites.Service(handlerLog, resolver.ResolveWithJsonElementCodec(Favorites.Events.codecStj, fold, initial, snapshot))
| _ -> Backend.Favorites.Service(handlerLog, resolver.ResolveWithUtf8ArrayCodec(Favorites.Events.codecNewtonsoft, fold, initial, snapshot))

member __.CreateSaveForLaterService() =
let fold, initial = SavedForLater.Fold.fold, SavedForLater.Fold.initial
let snapshot = SavedForLater.Fold.isOrigin,SavedForLater.Fold.compact

match storageConfig with
| Storage.StorageConfig.Cosmos _ -> Backend.SavedForLater.Service(handlerLog, resolver.ResolveWithJsonElementCodec(SavedForLater.Events.JsonElementCodec.codec JsonSerializer.defaultOptions,fold,initial,snapshot), maxSavedItems=50)
| _ -> Backend.SavedForLater.Service(handlerLog, resolver.ResolveWithUtf8ArrayCodec(SavedForLater.Events.Utf8ArrayCodec.codec,fold,initial,snapshot), maxSavedItems=50)
| Storage.StorageConfig.Cosmos _ -> Backend.SavedForLater.Service(handlerLog, resolver.ResolveWithJsonElementCodec(SavedForLater.Events.codecStj,fold,initial,snapshot), maxSavedItems=50)
| _ -> Backend.SavedForLater.Service(handlerLog, resolver.ResolveWithUtf8ArrayCodec(SavedForLater.Events.codecNewtonsoft,fold,initial,snapshot), maxSavedItems=50)

member __.CreateTodosService() =
let fold, initial = TodoBackend.Fold.fold, TodoBackend.Fold.initial
let snapshot = TodoBackend.Fold.isOrigin, TodoBackend.Fold.snapshot

match storageConfig with
| Storage.StorageConfig.Cosmos _ -> TodoBackend.Service(handlerLog, resolver.ResolveWithJsonElementCodec(TodoBackend.Events.JsonElementCodec.codec JsonSerializer.defaultOptions,fold,initial,snapshot))
| _ -> TodoBackend.Service(handlerLog, resolver.ResolveWithUtf8ArrayCodec(TodoBackend.Events.Utf8ArrayCodec.codec,fold,initial,snapshot))
| Storage.StorageConfig.Cosmos _ -> TodoBackend.Service(handlerLog, resolver.ResolveWithJsonElementCodec(TodoBackend.Events.codecStj,fold,initial,snapshot))
| _ -> TodoBackend.Service(handlerLog, resolver.ResolveWithUtf8ArrayCodec(TodoBackend.Events.codecNewtonsoft,fold,initial,snapshot))

let register (services : IServiceCollection, storageConfig, handlerLog) =
let regF (factory : IServiceProvider -> 'T) = services.AddSingleton<'T>(fun (sp: IServiceProvider) -> factory sp) |> ignore
Expand Down
5 changes: 2 additions & 3 deletions samples/Store/Backend/Backend.fsproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<TargetFramework>netstandard2.1</TargetFramework>
<WarningLevel>5</WarningLevel>
<IsTestProject>false</IsTestProject>
<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
Expand All @@ -23,8 +23,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="FSharp.Core" Version="3.1.2.5" Condition=" '$(TargetFramework)' == 'net461' " />
<PackageReference Include="FSharp.Core" Version="4.3.4" Condition=" '$(TargetFramework)' == 'netstandard2.0' " />
<PackageReference Include="FSharp.Core" Version="4.3.4" />
</ItemGroup>

</Project>
31 changes: 3 additions & 28 deletions samples/Store/Domain/Cart.fs
Original file line number Diff line number Diff line change
Expand Up @@ -25,33 +25,8 @@ module Events =
| ItemWaiveReturnsChanged of ItemWaiveReturnsInfo
interface TypeShape.UnionContract.IUnionContract

module Utf8ArrayCodec =
let codec = FsCodec.NewtonsoftJson.Codec.Create<Event>()

module JsonElementCodec =
open FsCodec.SystemTextJson
open System.Text.Json

let private encode (options: JsonSerializerOptions) =
fun (evt: Event) ->
match evt with
| Snapshotted state -> "Snapshotted", JsonSerializer.SerializeToElement(state, options)
| ItemAdded addInfo -> "ItemAdded", JsonSerializer.SerializeToElement(addInfo, options)
| ItemRemoved removeInfo -> "ItemRemoved", JsonSerializer.SerializeToElement(removeInfo, options)
| ItemQuantityChanged changeInfo -> "ItemQuantityChanged", JsonSerializer.SerializeToElement(changeInfo, options)
| ItemWaiveReturnsChanged waiveInfo -> "ItemWaiveReturnsChanged", JsonSerializer.SerializeToElement(waiveInfo, options)

let private tryDecode (options: JsonSerializerOptions) =
fun (eventType, data: JsonElement) ->
match eventType with
| "Snapshotted" -> Some (Snapshotted <| JsonSerializer.DeserializeElement<Compaction.State>(data, options))
| "ItemAdded" -> Some (ItemAdded <| JsonSerializer.DeserializeElement<ItemAddInfo>(data, options))
| "ItemRemoved" -> Some (ItemRemoved <| JsonSerializer.DeserializeElement<ItemRemoveInfo>(data, options))
| "ItemQuantityChanged" -> Some (ItemQuantityChanged <| JsonSerializer.DeserializeElement<ItemQuantityChangeInfo>(data, options))
| "ItemWaiveReturnsChanged" -> Some (ItemWaiveReturnsChanged <| JsonSerializer.DeserializeElement<ItemWaiveReturnsInfo>(data, options))
| _ -> None

let codec options = FsCodec.Codec.Create<Event, JsonElement>(encode options, tryDecode options)
let codecNewtonsoft = FsCodec.NewtonsoftJson.Codec.Create<Event>()
let codecStj = FsCodec.SystemTextJson.Codec.Create<Event>()

module Fold =
type ItemInfo = { skuId: SkuId; quantity: int; returnsWaived: bool }
Expand Down Expand Up @@ -106,4 +81,4 @@ module Commands =
match waived with
| Some waived when itemExistsWithDifferentWaiveStatus skuId waived ->
yield Events.ItemWaiveReturnsChanged { context = c; skuId = skuId; waived = waived }
| _ -> () ]
| _ -> () ]
23 changes: 3 additions & 20 deletions samples/Store/Domain/ContactPreferences.fs
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,8 @@ module Events =
| [<System.Runtime.Serialization.DataMember(Name = "contactPreferencesChanged")>]Updated of Value
interface TypeShape.UnionContract.IUnionContract

module Utf8ArrayCodec =
let codec = FsCodec.NewtonsoftJson.Codec.Create<Event>()

module JsonElementCodec =
open FsCodec.SystemTextJson
open System.Text.Json

let private encode (options: JsonSerializerOptions) =
fun (evt: Event) ->
match evt with
| Updated value -> "contactPreferencesChanged", JsonSerializer.SerializeToElement(value, options)

let private tryDecode (options: JsonSerializerOptions) =
fun (eventType, data: JsonElement) ->
match eventType with
| "contactPreferencesChanged" -> Some (Updated <| JsonSerializer.DeserializeElement<Value>(data, options))
| _ -> None

let codec options = FsCodec.Codec.Create<Event, JsonElement>(encode options, tryDecode options)
let codecNewtonsoft = FsCodec.NewtonsoftJson.Codec.Create<Event>()
let codecStj = FsCodec.SystemTextJson.Codec.Create<Event>()

module Fold =

Expand All @@ -56,4 +39,4 @@ module Commands =
match command with
| Update ({ preferences = preferences } as value) ->
if state = preferences then [] else
[ Events.Updated value ]
[ Events.Updated value ]
7 changes: 4 additions & 3 deletions samples/Store/Domain/Domain.fsproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<TargetFrameworks>netstandard2.1</TargetFrameworks>
<WarningLevel>5</WarningLevel>
<IsTestProject>false</IsTestProject>
<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
Expand All @@ -19,9 +19,10 @@

<ItemGroup>
<PackageReference Include="FSharp.Core" Version="3.1.2.5" Condition=" '$(TargetFramework)' == 'net461' " />
<PackageReference Include="FSharp.Core" Version="4.3.4" Condition=" '$(TargetFramework)' == 'netstandard2.0' " />
<PackageReference Include="FSharp.Core" Version="4.3.4" Condition=" '$(TargetFramework)' == 'netstandard2.1' " />

<PackageReference Include="FsCodec.NewtonsoftJson" Version="2.0.1" />
<PackageReference Include="FsCodec.NewtonsoftJson" Version="2.0.2-alpha.0.6" />
<PackageReference Include="FsCodec.SystemTextJson" Version="2.0.2-alpha.0.6" />
</ItemGroup>

<ItemGroup>
Expand Down
23 changes: 2 additions & 21 deletions samples/Store/Domain/Favorites.fs
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,8 @@ module Events =
| Unfavorited of Unfavorited
interface TypeShape.UnionContract.IUnionContract

module Utf8ArrayCodec =
let codec = FsCodec.NewtonsoftJson.Codec.Create<Event>()

module JsonElementCodec =
open FsCodec.SystemTextJson
open System.Text.Json

let private encode (options: JsonSerializerOptions) = fun (evt: Event) ->
match evt with
| Snapshotted snapshotted -> "Snapshotted", JsonSerializer.SerializeToElement(snapshotted, options)
| Favorited favorited -> "Favorited", JsonSerializer.SerializeToElement(favorited, options)
| Unfavorited unfavorited -> "Unfavorited", JsonSerializer.SerializeToElement(unfavorited, options)

let private tryDecode (options: JsonSerializerOptions) = fun (eventType, data: JsonElement) ->
match eventType with
| "Snapshotted" -> Some (Snapshotted <| JsonSerializer.DeserializeElement<Snapshotted>(data, options))
| "Favorited" -> Some (Favorited <| JsonSerializer.DeserializeElement<Favorited>(data, options))
| "Unfavorited" -> Some (Unfavorited <| JsonSerializer.DeserializeElement<Unfavorited>(data, options))
| _ -> None

let codec options = FsCodec.Codec.Create<Event, JsonElement>(encode options, tryDecode options)
let codecNewtonsoft = FsCodec.NewtonsoftJson.Codec.Create<Event>()
let codecStj = FsCodec.SystemTextJson.Codec.Create<Event>()

module Fold =

Expand Down
29 changes: 3 additions & 26 deletions samples/Store/Domain/SavedForLater.fs
Original file line number Diff line number Diff line change
Expand Up @@ -30,31 +30,8 @@ module Events =
| Added of Added
interface TypeShape.UnionContract.IUnionContract

module Utf8ArrayCodec =
let codec = FsCodec.NewtonsoftJson.Codec.Create<Event>()

module JsonElementCodec =
open FsCodec.SystemTextJson
open System.Text.Json

let private encode (options: JsonSerializerOptions) =
fun (evt: Event) ->
match evt with
| Compacted compacted -> Compaction.EventType, JsonSerializer.SerializeToElement(compacted, options)
| Merged merged -> "Merged", JsonSerializer.SerializeToElement(merged, options)
| Removed removed -> "Removed", JsonSerializer.SerializeToElement(removed, options)
| Added added -> "Added", JsonSerializer.SerializeToElement(added, options)

let private tryDecode (options: JsonSerializerOptions) =
fun (eventType, data: JsonElement) ->
match eventType with
| Compaction.EventType -> Some (Compacted <| JsonSerializer.DeserializeElement<Compaction.Compacted>(data, options))
| "Merged" -> Some (Merged <| JsonSerializer.DeserializeElement<Merged>(data, options))
| "Removed" -> Some (Removed <| JsonSerializer.DeserializeElement<Removed>(data, options))
| "Added" -> Some (Added <| JsonSerializer.DeserializeElement<Added>(data, options))
| _ -> None

let codec options = FsCodec.Codec.Create<Event, JsonElement>(encode options, tryDecode options)
let codecNewtonsoft = FsCodec.NewtonsoftJson.Codec.Create<Event>()
let codecStj = FsCodec.SystemTextJson.Codec.Create<Event>()

module Fold =
open Events
Expand Down Expand Up @@ -129,4 +106,4 @@ module Commands =
let index = Index state
let net = skus |> Array.filter (index.DoesNotAlreadyContainSameOrMoreRecent dateSaved)
if Array.isEmpty net then true, []
else validateAgainstInvariants [ Events.Added { skus = net ; dateSaved = dateSaved } ]
else validateAgainstInvariants [ Events.Added { skus = net ; dateSaved = dateSaved } ]
7 changes: 3 additions & 4 deletions samples/Store/Integration/CartIntegration.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ open Equinox
open Equinox.Cosmos.Integration
open Equinox.EventStore
open Equinox.MemoryStore
open FsCodec.SystemTextJson.Serialization
open Swensen.Unquote

#nowarn "1182" // From hereon in, we may have some 'unused' privates (the tests)
Expand All @@ -16,15 +15,15 @@ let createMemoryStore () =
// we want to validate that the JSON UTF8 is working happily
VolatileStore<byte[]>()
let createServiceMemory log store =
Backend.Cart.Service(log, fun (id,opt) -> MemoryStore.Resolver(store, Domain.Cart.Events.Utf8ArrayCodec.codec, fold, initial).Resolve(id,?option=opt))
Backend.Cart.Service(log, fun (id,opt) -> MemoryStore.Resolver(store, Domain.Cart.Events.codecNewtonsoft, fold, initial).Resolve(id,?option=opt))

let eventStoreCodec = Domain.Cart.Events.Utf8ArrayCodec.codec
let eventStoreCodec = Domain.Cart.Events.codecNewtonsoft
let resolveGesStreamWithRollingSnapshots gateway =
fun (id,opt) -> EventStore.Resolver(gateway, eventStoreCodec, fold, initial, access = AccessStrategy.RollingSnapshots snapshot).Resolve(id,?option=opt)
let resolveGesStreamWithoutCustomAccessStrategy gateway =
fun (id,opt) -> EventStore.Resolver(gateway, eventStoreCodec, fold, initial).Resolve(id,?option=opt)

let cosmosCodec = Domain.Cart.Events.JsonElementCodec.codec JsonSerializer.defaultOptions
let cosmosCodec = Domain.Cart.Events.codecStj
let resolveCosmosStreamWithSnapshotStrategy gateway =
fun (id,opt) -> Cosmos.Resolver(gateway, cosmosCodec, fold, initial, Cosmos.CachingStrategy.NoCaching, Cosmos.AccessStrategy.Snapshot snapshot).Resolve(id,?option=opt)
let resolveCosmosStreamWithoutCustomAccessStrategy gateway =
Expand Down
10 changes: 4 additions & 6 deletions samples/Store/Integration/ContactPreferencesIntegration.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,24 @@

open Equinox
open Equinox.Cosmos.Integration
open FsCodec.SystemTextJson.Serialization
open Swensen.Unquote
open Xunit

#nowarn "1182" // From hereon in, we may have some 'unused' privates (the tests)

let fold, initial = Domain.ContactPreferences.Fold.fold, Domain.ContactPreferences.Fold.initial

let createMemoryStore () =
new MemoryStore.VolatileStore<_>()
MemoryStore.VolatileStore<_>()
let createServiceMemory log store =
Backend.ContactPreferences.Service(log, MemoryStore.Resolver(store, FsCodec.Box.Codec.Create(), fold, initial).Resolve)

let eventStoreCodec = Domain.ContactPreferences.Events.Utf8ArrayCodec.codec
let eventStoreCodec = Domain.ContactPreferences.Events.codecNewtonsoft
let resolveStreamGesWithOptimizedStorageSemantics gateway =
EventStore.Resolver(gateway 1, eventStoreCodec, fold, initial, access = EventStore.AccessStrategy.LatestKnownEvent).Resolve
let resolveStreamGesWithoutAccessStrategy gateway =
EventStore.Resolver(gateway defaultBatchSize, eventStoreCodec, fold, initial).Resolve

let cosmosCodec = Domain.ContactPreferences.Events.JsonElementCodec.codec JsonSerializer.defaultOptions
let cosmosCodec = Domain.ContactPreferences.Events.codecStj
let resolveStreamCosmosWithLatestKnownEventSemantics gateway =
Cosmos.Resolver(gateway 1, cosmosCodec, fold, initial, Cosmos.CachingStrategy.NoCaching, Cosmos.AccessStrategy.LatestKnownEvent).Resolve
let resolveStreamCosmosUnoptimized gateway =
Expand Down Expand Up @@ -76,7 +74,7 @@ type Tests(testOutputHelper) =
let! service = arrange connectToSpecifiedCosmosOrSimulator createCosmosContext resolveStreamCosmosWithLatestKnownEventSemantics
do! act service args
}

[<AutoData(SkipIfRequestedViaEnvironmentVariable="EQUINOX_INTEGRATION_SKIP_COSMOS")>]
let ``Can roundtrip against Cosmos, correctly folding the events with RollingUnfold semantics`` args = Async.RunSynchronously <| async {
let! service = arrange connectToSpecifiedCosmosOrSimulator createCosmosContext resolveStreamCosmosRollingUnfolds
Expand Down
7 changes: 3 additions & 4 deletions samples/Store/Integration/FavoritesIntegration.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

open Equinox
open Equinox.Cosmos.Integration
open FsCodec.SystemTextJson.Serialization
open Swensen.Unquote

#nowarn "1182" // From hereon in, we may have some 'unused' privates (the tests)
Expand All @@ -15,12 +14,12 @@ let createMemoryStore () =
let createServiceMemory log store =
Backend.Favorites.Service(log, MemoryStore.Resolver(store, FsCodec.Box.Codec.Create(), fold, initial).Resolve)

let eventStoreCodec = Domain.Favorites.Events.Utf8ArrayCodec.codec
let eventStoreCodec = Domain.Favorites.Events.codecNewtonsoft
let createServiceGes gateway log =
let resolve = EventStore.Resolver(gateway, eventStoreCodec, fold, initial, access = EventStore.AccessStrategy.RollingSnapshots snapshot).Resolve
Backend.Favorites.Service(log, resolve)

let cosmosCodec = Domain.Favorites.Events.JsonElementCodec.codec JsonSerializer.defaultOptions
let cosmosCodec = Domain.Favorites.Events.codecStj
let createServiceCosmos gateway log =
let resolve = Cosmos.Resolver(gateway, cosmosCodec, fold, initial, Cosmos.CachingStrategy.NoCaching, Cosmos.AccessStrategy.Snapshot snapshot).Resolve
Backend.Favorites.Service(log, resolve)
Expand Down Expand Up @@ -68,7 +67,7 @@ type Tests(testOutputHelper) =
let service = createServiceCosmos gateway log
do! act service args
}

[<AutoData(SkipIfRequestedViaEnvironmentVariable="EQUINOX_INTEGRATION_SKIP_COSMOS")>]
let ``Can roundtrip against Cosmos, correctly folding the events with rolling unfolds`` args = Async.RunSynchronously <| async {
let log = createLog ()
Expand Down
29 changes: 2 additions & 27 deletions samples/TodoBackend/Todo.fs
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,8 @@ module Events =
| Snapshotted of Snapshotted
interface TypeShape.UnionContract.IUnionContract

module Utf8ArrayCodec =
let codec = FsCodec.NewtonsoftJson.Codec.Create<Event>()

module JsonElementCodec =
open FsCodec.SystemTextJson
open System.Text.Json

let private encode (options: JsonSerializerOptions) =
fun (evt: Event) ->
match evt with
| Added todo -> "Added", JsonSerializer.SerializeToElement(todo, options)
| Updated todo -> "Updated", JsonSerializer.SerializeToElement(todo, options)
| Deleted deleted -> "Deleted", JsonSerializer.SerializeToElement(deleted, options)
| Cleared -> "Cleared", Unchecked.defaultof<JsonElement>
| Snapshotted snapshotted -> "Snapshotted", JsonSerializer.SerializeToElement(snapshotted, options)

let private tryDecode (options: JsonSerializerOptions) =
fun (eventType, data: JsonElement) ->
match eventType with
| "Added" -> Some (Added <| JsonSerializer.DeserializeElement<Todo>(data, options))
| "Updated" -> Some (Updated <| JsonSerializer.DeserializeElement<Todo>(data, options))
| "Deleted" -> Some (Deleted <| JsonSerializer.DeserializeElement<Deleted>(data, options))
| "Cleared" -> Some Cleared
| "Snapshotted" -> Some (Snapshotted <| JsonSerializer.DeserializeElement<Snapshotted>(data, options))
| _ -> None

let codec options = FsCodec.Codec.Create<Event, JsonElement>(encode options, tryDecode options)
let codecNewtonsoft = FsCodec.NewtonsoftJson.Codec.Create<Event>()
let codecStj = FsCodec.SystemTextJson.Codec.Create<Event>()

module Fold =
type State = { items : Events.Todo list; nextId : int }
Expand Down
Loading