Skip to content

Commit

Permalink
Remove Equinox.Core deps; add Equinox.Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
bartelink committed Aug 9, 2023
1 parent 8bdcf9d commit 4c1da33
Show file tree
Hide file tree
Showing 23 changed files with 96 additions and 54 deletions.
6 changes: 6 additions & 0 deletions Equinox.sln
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Equinox.MessageDb.Integrati
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Equinox.Core.Tests", "tests\Equinox.Core.Tests\Equinox.Core.Tests.fsproj", "{FB376808-7B32-4724-98BE-D9458EB0F68B}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Equinox.Tests", "src\Equinox.Tests\Equinox.Tests.fsproj", "{D8677ABB-1D7C-4FC3-ABF9-5A49AF377372}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -247,6 +249,10 @@ Global
{FB376808-7B32-4724-98BE-D9458EB0F68B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FB376808-7B32-4724-98BE-D9458EB0F68B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FB376808-7B32-4724-98BE-D9458EB0F68B}.Release|Any CPU.Build.0 = Release|Any CPU
{D8677ABB-1D7C-4FC3-ABF9-5A49AF377372}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D8677ABB-1D7C-4FC3-ABF9-5A49AF377372}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D8677ABB-1D7C-4FC3-ABF9-5A49AF377372}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D8677ABB-1D7C-4FC3-ABF9-5A49AF377372}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ The components within this repository are delivered as multi-targeted Nuget pack

## Core library

- `Equinox` [![NuGet](https://img.shields.io/nuget/v/Equinox.svg)](https://www.nuget.org/packages/Equinox/): Store-agnostic decision flow runner that manages the optimistic concurrency protocol and application-level API surface. ([depends](https://www.fuget.org/packages/Equinox) only on `FSharp.Core` v `6.0.7`, `FsCodec` v `3.0.0`, `Serilog` (but not specific Serilog sinks, i.e. you configure to emit to `NLog` etc)
- `Equinox` [![NuGet](https://img.shields.io/nuget/v/Equinox.svg)](https://www.nuget.org/packages/Equinox/): Store-agnostic decision flow runner that manages the optimistic concurrency protocol and application-level API surface, together with the default [`System.Runtime.Caching.MemoryCache`-based] `Cache` implementation. ([depends](https://www.fuget.org/packages/Equinox) only on `FSharp.Core` v `6.0.7`, `FsCodec` v `3.0.0`, `System.Runtime.Caching`, `Serilog` (but not specific Serilog sinks, i.e. you configure to emit to `NLog` etc)

## Serialization support

Expand All @@ -168,16 +168,16 @@ The components within this repository are delivered as multi-targeted Nuget pack

## Data Store libraries

- `Equinox.Core` [![NuGet](https://img.shields.io/nuget/v/Equinox.Core.svg)](https://www.nuget.org/packages/Equinox.Core/): Interfaces and helpers used in the concrete Store implementations, together with the default [`System.Runtime.Caching.MemoryCache`-based] `Cache` implementation. Hosts generic utility types frequently useful alongside Equinox: [`AsyncCacheCell`](https://github.com/jet/equinox/blob/master/src/Equinox.Core/AsyncCacheCell.fs#L36), [`Batcher`, `BatcherCache`, `BatcherDictionary`](https://github.com/jet/equinox/blob/master/src/Equinox.Core/Batching.fs#L44). ([depends](https://www.fuget.org/packages/Equinox.Core) on `Equinox`, `System.Runtime.Caching`)
- `Equinox.MemoryStore` [![MemoryStore NuGet](https://img.shields.io/nuget/v/Equinox.MemoryStore.svg)](https://www.nuget.org/packages/Equinox.MemoryStore/): In-memory store for integration testing/performance base-lining/providing out-of-the-box zero dependency storage for examples. ([depends](https://www.fuget.org/packages/Equinox.MemoryStore) on `Equinox`, `FsCodec`)
- `Equinox.CosmosStore` [![CosmosStore NuGet](https://img.shields.io/nuget/v/Equinox.CosmosStore.svg)](https://www.nuget.org/packages/Equinox.CosmosStore/): Azure CosmosDB Adapter with integrated 'unfolds' feature, facilitating optimal read performance in terms of latency and RU costs, instrumented to meet Jet's production monitoring requirements. ([depends](https://www.fuget.org/packages/Equinox.CosmosStore) on `Equinox.Core`, `Microsoft.Azure.Cosmos` >= `3.27`, `FsCodec`, `System.Text.Json`, `FSharp.Control.TaskSeq`)
- `Equinox.Core` [![NuGet](https://img.shields.io/nuget/v/Equinox.Core.svg)](https://www.nuget.org/packages/Equinox.Core/): Hosts generic utility types frequently useful alongside Equinox: [`AsyncCacheCell`](https://github.com/jet/equinox/blob/master/src/Equinox.Core/AsyncCacheCell.fs#L36), [`Batcher`, `BatcherCache`, `BatcherDictionary`](https://github.com/jet/equinox/blob/master/src/Equinox.Core/Batching.fs#L44). ([depends](https://www.fuget.org/packages/Equinox.Core) on `System.Runtime.Caching`)
- `Equinox.MemoryStore` [![MemoryStore NuGet](https://img.shields.io/nuget/v/Equinox.MemoryStore.svg)](https://www.nuget.org/packages/Equinox.MemoryStore/): In-memory store for integration testing/performance base-lining/providing out-of-the-box zero dependency storage for examples. ([depends](https://www.fuget.org/packages/Equinox.MemoryStore) on `Equinox`)
- `Equinox.CosmosStore` [![CosmosStore NuGet](https://img.shields.io/nuget/v/Equinox.CosmosStore.svg)](https://www.nuget.org/packages/Equinox.CosmosStore/): Azure CosmosDB Adapter with integrated 'unfolds' feature, facilitating optimal read performance in terms of latency and RU costs, instrumented to meet Jet's production monitoring requirements. ([depends](https://www.fuget.org/packages/Equinox.CosmosStore) on `Equinox`, `Equinox.Core`, `Microsoft.Azure.Cosmos` >= `3.27`, `System.Text.Json`, `FSharp.Control.TaskSeq`)
- `Equinox.CosmosStore.Prometheus` [![CosmosStore.Prometheus NuGet](https://img.shields.io/nuget/v/Equinox.CosmosStore.Prometheus.svg)](https://www.nuget.org/packages/Equinox.CosmosStore.Prometheus/): Integration package providing a `Serilog.Core.ILogEventSink` that extracts detailed metrics information attached to the `LogEvent`s and feeds them to the `prometheus-net`'s `Prometheus.Metrics` static instance. ([depends](https://www.fuget.org/packages/Equinox.CosmosStore.Prometheus) on `Equinox.CosmosStore`, `prometheus-net >= 3.6.0`)
- `Equinox.DynamoStore` [![DynamoStore NuGet](https://img.shields.io/nuget/v/Equinox.DynamoStore.svg)](https://www.nuget.org/packages/Equinox.DynamoStore/): Amazon DynamoDB Adapter with integrated 'unfolds' feature, facilitating optimal read performance in terms of latency and RC costs, patterned after `Equinox.CosmosStore`. ([depends](https://www.fuget.org/packages/Equinox.DynamoStore) on `Equinox`, `FSharp.AWS.DynamoDB` >= `0.11.2-beta`, `FsCodec`, `FSharp.Control.TaskSeq`)
- `Equinox.DynamoStore` [![DynamoStore NuGet](https://img.shields.io/nuget/v/Equinox.DynamoStore.svg)](https://www.nuget.org/packages/Equinox.DynamoStore/): Amazon DynamoDB Adapter with integrated 'unfolds' feature, facilitating optimal read performance in terms of latency and RC costs, patterned after `Equinox.CosmosStore`. ([depends](https://www.fuget.org/packages/Equinox.DynamoStore) on `Equinox`, `FSharp.AWS.DynamoDB` >= `0.11.2-beta`, `FSharp.Control.TaskSeq`)
- `Equinox.DynamoStore.Prometheus` [![DynamoStore.Prometheus NuGet](https://img.shields.io/nuget/v/Equinox.DynamoStore.Prometheus.svg)](https://www.nuget.org/packages/Equinox.DynamoStore.Prometheus/): Integration package providing a `Serilog.Core.ILogEventSink` that extracts detailed metrics information attached to the `LogEvent`s and feeds them to the `prometheus-net`'s `Prometheus.Metrics` static instance. ([depends](https://www.fuget.org/packages/Equinox.CosmosStore.Prometheus) on `Equinox.DynamoStore`, `prometheus-net >= 3.6.0`)
- `Equinox.EventStore` [![EventStore NuGet](https://img.shields.io/nuget/v/Equinox.EventStore.svg)](https://www.nuget.org/packages/Equinox.EventStore/): [EventStoreDB](https://eventstore.org/) Adapter designed to meet Jet's production monitoring requirements. ([depends](https://www.fuget.org/packages/Equinox.EventStore) on `Equinox`, `EventStore.Client >= 22.0.0-preview`, `FSharp.Control.TaskSeq`), EventStore Server version `21.10` or later). **NO NOT use for new projects - the TCP interface to EventStoreDB has long been deprecated, this package is only provided to ease migration scenarios and will be removed in due course**
- `Equinox.EventStoreDb` [![EventStoreDb NuGet](https://img.shields.io/nuget/v/Equinox.EventStoreDb.svg)](https://www.nuget.org/packages/Equinox.EventStoreDb/): Production-strength [EventStoreDB](https://eventstore.org/) Adapter. ([depends](https://www.fuget.org/packages/Equinox.EventStoreDb) on `Equinox`, `EventStore.Client.Grpc.Streams` >= `22.0.0`, `FSharp.Control.TaskSeq`, EventStore Server version `21.10` or later)
- `Equinox.MessageDb` [![MessageDb NuGet](https://img.shields.io/nuget/v/Equinox.MessageDb.svg)](https://www.nuget.org/packages/Equinox.MessageDb/): [MessageDb](http://docs.eventide-project.org/user-guide/message-db/) Adapter. ([depends](https://www.fuget.org/packages/Equinox.MessageDb) on `Equinox`, `Npgsql` >= `7.0.0`, `FSharp.Control.TaskSeq`))
- `Equinox.SqlStreamStore` [![SqlStreamStore NuGet](https://img.shields.io/nuget/v/Equinox.SqlStreamStore.svg)](https://www.nuget.org/packages/Equinox.SqlStreamStore/): [SqlStreamStore](https://github.com/SQLStreamStore/SQLStreamStore) Adapter derived from `Equinox.EventStore` - provides core facilities (but does not connect to a specific database; see sibling `SqlStreamStore`.* packages). ([depends](https://www.fuget.org/packages/Equinox.SqlStreamStore) on `Equinox.Core`, `FsCodec`, `SqlStreamStore >= 1.2.0-beta.8`, `FSharp.Control.TaskSeq`)
- `Equinox.SqlStreamStore` [![SqlStreamStore NuGet](https://img.shields.io/nuget/v/Equinox.SqlStreamStore.svg)](https://www.nuget.org/packages/Equinox.SqlStreamStore/): [SqlStreamStore](https://github.com/SQLStreamStore/SQLStreamStore) Adapter derived from `Equinox.EventStore` - provides core facilities (but does not connect to a specific database; see sibling `SqlStreamStore`.* packages). ([depends](https://www.fuget.org/packages/Equinox.SqlStreamStore) on `Equinox`, `SqlStreamStore >= 1.2.0-beta.8`, `FSharp.Control.TaskSeq`)
- `Equinox.SqlStreamStore.MsSql` [![MsSql NuGet](https://img.shields.io/nuget/v/Equinox.SqlStreamStore.MsSql.svg)](https://www.nuget.org/packages/Equinox.SqlStreamStore.MsSql/): [SqlStreamStore.MsSql](https://sqlstreamstore.readthedocs.io/en/latest/sqlserver) Sql Server `Connector` implementation for `Equinox.SqlStreamStore` package). ([depends](https://www.fuget.org/packages/Equinox.SqlStreamStore.MsSql) on `Equinox.SqlStreamStore`, `SqlStreamStore.MsSql >= 1.2.0-beta.8`)
- `Equinox.SqlStreamStore.MySql` [![MySql NuGet](https://img.shields.io/nuget/v/Equinox.SqlStreamStore.MySql.svg)](https://www.nuget.org/packages/Equinox.SqlStreamStore.MySql/): `SqlStreamStore.MySql` MySQL `Connector` implementation for `Equinox.SqlStreamStore` package). ([depends](https://www.fuget.org/packages/Equinox.SqlStreamStore.MySql) on `Equinox.SqlStreamStore`, `SqlStreamStore.MySql >= 1.2.0-beta.8`)
- `Equinox.SqlStreamStore.Postgres` [![Postgres NuGet](https://img.shields.io/nuget/v/Equinox.SqlStreamStore.Postgres.svg)](https://www.nuget.org/packages/Equinox.SqlStreamStore.Postgres/): [SqlStreamStore.Postgres](https://sqlstreamstore.readthedocs.io/en/latest/postgres) PostgreSQL `Connector` implementation for `Equinox.SqlStreamStore` package). ([depends](https://www.fuget.org/packages/Equinox.SqlStreamStore.Postgres) on `Equinox.SqlStreamStore`, `SqlStreamStore.Postgres >= 1.2.0-beta.8`)
Expand Down
8 changes: 7 additions & 1 deletion src/Equinox.Core/AsyncCacheCell.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ namespace Equinox.Core
/// Generic async lazy caching implementation that admits expiration/recomputation/retry on exception semantics.
/// If `workflow` fails, all readers entering while the load/refresh is in progress will share the failure
/// The first caller through the gate triggers a recomputation attempt if the previous attempt ended in failure
type AsyncCacheCell<'T>(startWorkflow : System.Func<CancellationToken, Task<'T>>, [<O; D null>]?isExpired: System.Func<'T, bool>) =
type
#if !EQUINOX_CORE
// NOT PUBLIC in Equinox.CosmosStore library - used internally to ensure the stored proc init is checked on first append once per container per process
// PUBLIC in Equinox.Core (it can also be used independent of Equinox)
internal
#endif
AsyncCacheCell<'T>(startWorkflow : System.Func<CancellationToken, Task<'T>>, [<O; D null>]?isExpired: System.Func<'T, bool>) =

let isValid = match isExpired with Some f -> not << f.Invoke | None -> fun _ -> true
let mutable cell = AsyncLazy<'T>.Empty
Expand Down
11 changes: 5 additions & 6 deletions src/Equinox.Core/Equinox.Core.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,23 @@

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<DefineConstants>EQUINOX_CORE</DefineConstants>
</PropertyGroup>

<ItemGroup>
<Compile Include="Infrastructure.fs" />
<Compile Include="..\Equinox\Infrastructure.fs" />
<Compile Include="..\Equinox\AsyncLazy.fs" />
<Compile Include="AsyncCacheCell.fs" />
<Compile Include="Retry.fs" />
<Compile Include="Batching.fs" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Equinox\Equinox.fsproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="MinVer" Version="4.2.0" PrivateAssets="All" />

<PackageReference Include="FSharp.Core" Version="6.0.7" ExcludeAssets="contentfiles" />


<PackageReference Include="System.Runtime.Caching" Version="6.0.0" />
</ItemGroup>

</Project>
6 changes: 4 additions & 2 deletions src/Equinox.CosmosStore/Equinox.CosmosStore.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="..\Equinox.Core\Infrastructure.fs" Link="Infrastructure.fs" />
<Compile Include="..\Equinox\Infrastructure.fs" />
<Compile Include="..\Equinox\AsyncLazy.fs" />
<Compile Include="..\Equinox.Core\AsyncCacheCell.fs" />
<Compile Include="..\Equinox.Core\Internal.fs" Link="Internal.fs" />
<Compile Include="CosmosStoreSerialization.fs" />
<Compile Include="CosmosStore.fs" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Equinox.Core\Equinox.Core.fsproj" />
<ProjectReference Include="..\Equinox\Equinox.fsproj" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/Equinox.DynamoStore/Equinox.DynamoStore.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="..\Equinox.Core\Infrastructure.fs" Link="Infrastructure.fs" />
<Compile Include="..\Equinox\Infrastructure.fs" />
<Compile Include="..\Equinox.Core\Internal.fs" Link="Internal.fs" />
<Compile Include="DynamoStore.fs" />
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/Equinox.EventStore/Equinox.EventStore.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="..\Equinox.Core\Infrastructure.fs" Link="Infrastructure.fs" />
<Compile Include="..\Equinox\Infrastructure.fs" />
<Compile Include="..\Equinox.Core\Internal.fs" Link="Internal.fs" />
<Compile Include="EventStore.fs" />
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/Equinox.EventStoreDb/Equinox.EventStoreDb.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="..\Equinox.Core\Infrastructure.fs" Link="Infrastructure.fs" />
<Compile Include="..\Equinox\Infrastructure.fs" />
<Compile Include="..\Equinox.Core\Internal.fs" Link="Internal.fs" />
<Compile Include="EventStoreDb.fs" />
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/Equinox.MemoryStore/Equinox.MemoryStore.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="..\Equinox.Core\Infrastructure.fs" Link="Infrastructure.fs" />
<Compile Include="..\Equinox\Infrastructure.fs" />
<Compile Include="MemoryStore.fs" />
</ItemGroup>

Expand Down
8 changes: 2 additions & 6 deletions src/Equinox.MessageDb/Equinox.MessageDb.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,8 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="..\Equinox.Core\Infrastructure.fs">
<Link>Infrastructure.fs</Link>
</Compile>
<Compile Include="..\Equinox.Core\Internal.fs">
<Link>Internal.fs</Link>
</Compile>
<Compile Include="..\Equinox\Infrastructure.fs" />
<Compile Include="..\Equinox.Core\Internal.fs" />
<Compile Include="MessageDbClient.fs" />
<Compile Include="Tracing.fs" />
<Compile Include="MessageDb.fs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="..\Equinox.Core\Infrastructure.fs" Link="Infrastructure.fs" />
<Compile Include="..\Equinox\Infrastructure.fs" />
<Compile Include="Connection.fs" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="..\Equinox.Core\Infrastructure.fs" Link="Infrastructure.fs" />
<Compile Include="..\Equinox\Infrastructure.fs" />
<Compile Include="Connection.fs" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="..\Equinox.Core\Infrastructure.fs" Link="Infrastructure.fs" />
<Compile Include="..\Equinox\Infrastructure.fs" />
<Compile Include="Connection.fs" />
</ItemGroup>

Expand Down
2 changes: 1 addition & 1 deletion src/Equinox.SqlStreamStore/Equinox.SqlStreamStore.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="..\Equinox.Core\Infrastructure.fs" Link="Infrastructure.fs" />
<Compile Include="..\Equinox\Infrastructure.fs" />
<Compile Include="..\Equinox.Core\Internal.fs" Link="Internal.fs" />
<Compile Include="SqlStreamStore.fs" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,6 @@ let write sn (sut: Equinox.Core.ICategory<_, _, _>) = task {
let wState' = trap <@ match wr with Equinox.Core.SyncResult.Written (_token, state') -> state' | _ -> failwith "unexpected" @>
test <@ expectedWriteState = wState' @> }

// Pinning the fact that the algorithm is not sensitive to the reuse of the initial value of a cache entry
let [<Fact>] ``AsyncLazy.Empty is a true singleton, does not allocate`` () =
let i1 = Equinox.Core.AsyncLazy<int>.Empty
let i2 = Equinox.Core.AsyncLazy<int>.Empty
test <@ obj.ReferenceEquals(i1, i2) @>

let [<Fact>] ``NoCaching strategy does no wrapping`` () =
let cat = SpyCategory()
let sut = Equinox.Core.Caching.apply isStale Equinox.CachingStrategy.NoCaching cat
Expand Down
25 changes: 25 additions & 0 deletions src/Equinox.Tests/Equinox.Tests.fsproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Compile Include="..\..\src\Equinox\Infrastructure.fs" />
<Compile Include="CachingTests.fs" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Equinox\Equinox.fsproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" />
<PackageReference Include="unquote" Version="6.1.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
9 changes: 7 additions & 2 deletions src/Equinox/AsyncLazy.fs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
namespace Equinox.Core

/// Asynchronous Lazy<'T> used to gate a workflow to ensure at most once execution of a computation.
type AsyncLazy<'T>(startTask: System.Func<Task<'T>>) =

type
#if !EQUINOX_CORE
// NOT PUBLIC in Equinox library - used internally in the impl of CacheEntry
// PUBLIC in Equinox.Core (which also uses it in the impl of AsyncCacheCell)
internal
#endif
AsyncLazy<'T>(startTask: System.Func<Task<'T>>) =
// NOTE due to `Lazy<T>` semantics, failed attempts will cache any exception; AsyncCacheCell compensates for this by rolling over to a new instance
let workflow = lazy startTask.Invoke()

Expand Down
2 changes: 1 addition & 1 deletion src/Equinox/Equinox.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="..\Equinox.Core\Infrastructure.fs" Link="Infrastructure.fs" />
<Compile Include="Infrastructure.fs" />
<Compile Include="StopwatchInterval.fs" />
<Compile Include="Tracing.fs" />
<Compile Include="Stream.fs" />
Expand Down
File renamed without changes.
11 changes: 0 additions & 11 deletions tests/Equinox.Core.Tests/AsyncCacheCellTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,6 @@ open Swensen.Unquote
open System
open Xunit

[<Fact>]
let ``AsyncLazy correctness`` () = async {
// ensure that the encapsulated computation fires only once
let mutable count = 0
let cell = AsyncLazy(fun () -> task { return Interlocked.Increment &count })
test <@ cell.TryCompleted() |> ValueOption.isNone @>
let! accessResult = [|1 .. 100|] |> Array.map (fun _ -> cell.Await() |> Async.AwaitTaskCorrect) |> Async.Parallel
test <@ cell.TryCompleted() |> ValueOption.isSome @>
test <@ accessResult |> Array.forall ((=) 1) @>
}

[<Fact>]
let ``AsyncCacheCell correctness`` () = async {
// ensure that the encapsulated computation fires only once and that expiry functions as expected
Expand Down
Loading

0 comments on commit 4c1da33

Please sign in to comment.