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

Changes for 0.12.0 release #70

Merged
merged 13 commits into from
Nov 29, 2023
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
2 changes: 1 addition & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"paket": {
"version": "7.2.1",
"version": "8.0.0",
"commands": [
"paket"
]
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
dotnet: ['6.0.x']
dotnet: ['8.0.x']
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
Expand All @@ -27,7 +27,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
dotnet: ['6.0.x']
dotnet: ['8.0.x']
runs-on: ${{ matrix.os }}

services:
Expand All @@ -37,7 +37,7 @@ jobs:
- 8000:8000

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
Expand Down
7 changes: 7 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
### 0.12.0-beta
* Added support for `Array.contains` and `List.contains` to compare an attribute against multiple values (thanks @faldor20)
* Added `AllowMultiple = true` for `GlobalSecondaryIndex*` Attributes to allow indices to share an attribute
* Modified index selection priority to better handle string `BeginsWith` queries on inverse GSIs (thanks @matti-avilabs)
* Added `ReturnValuesOnConditionCheckFailure.ALL_OLD` to include the item values in the `ConditionCheckFailedException` (thanks for the suggestion @bartelink)
* (breaking) Removed [obsolete](https://learn.microsoft.com/en-us/dotnet/core/compatibility/serialization/5.0/binaryformatter-serialization-obsolete) `BinaryFormatterAttribute`

### 0.11.2-beta
* Added optional `?consistentRead` parameter to Get requests (thanks @matti-avilabs)
* Fixed `TransactWriteItems`: updated validation to reflect [increased limit of 100 items in service](https://aws.amazon.com/about-aws/whats-new/2022/09/amazon-dynamodb-supports-100-actions-per-transaction/)
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "6.0.401",
"version": "8.0.100",
"rollForward": "latestMajor"
}
}
11 changes: 10 additions & 1 deletion paket.dependencies
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
source https://api.nuget.org/v3/index.json

storage: none
framework: net60, netstandard20, netstandard21
framework: net80, netstandard20, netstandard21

nuget Unquote ~> 6.1.0
nuget FSharp.Core >= 4.7.2 lowest_matching: true

nuget AWSSDK.DynamoDBv2 ~> 3.7.5
nuget DotNet.ReproducibleBuilds
github eiriktsarpalis/TypeShape:10.0.0 src/TypeShape/TypeShape.fs

group Test
source https://api.nuget.org/v3/index.json
framework: net80

nuget FsCheck
nuget Microsoft.NET.Test.Sdk
nuget xunit
nuget xunit.runner.visualstudio
92 changes: 67 additions & 25 deletions paket.lock
Original file line number Diff line number Diff line change
@@ -1,38 +1,80 @@
STORAGE: NONE
RESTRICTION: || (== net6.0) (== netstandard2.0) (== netstandard2.1)
RESTRICTION: || (== net8.0) (== netstandard2.0) (== netstandard2.1)
NUGET
remote: https://api.nuget.org/v3/index.json
AWSSDK.Core (3.7.107.10)
Microsoft.Bcl.AsyncInterfaces (>= 1.1) - restriction: || (&& (== net6.0) (< netcoreapp3.1)) (== netstandard2.0) (== netstandard2.1)
AWSSDK.DynamoDBv2 (3.7.105.1)
AWSSDK.Core (>= 3.7.107.10 < 4.0)
AWSSDK.Core (3.7.300.11)
Microsoft.Bcl.AsyncInterfaces (>= 1.1) - restriction: || (&& (== net8.0) (< netcoreapp3.1)) (== netstandard2.0) (== netstandard2.1)
AWSSDK.DynamoDBv2 (3.7.300.11)
AWSSDK.Core (>= 3.7.300.11 < 4.0)
DotNet.ReproducibleBuilds (1.1.1)
Microsoft.SourceLink.AzureRepos.Git (>= 1.1.1)
Microsoft.SourceLink.Bitbucket.Git (>= 1.1.1)
Microsoft.SourceLink.GitHub (>= 1.1.1)
Microsoft.SourceLink.GitLab (>= 1.1.1)
FSharp.Core (4.7.2)
Microsoft.Bcl.AsyncInterfaces (7.0) - restriction: || (&& (== net6.0) (< netcoreapp3.1)) (== netstandard2.0) (== netstandard2.1)
System.Threading.Tasks.Extensions (>= 4.5.4) - restriction: || (&& (== net6.0) (>= net462)) (&& (== net6.0) (< netstandard2.1)) (== netstandard2.0) (&& (== netstandard2.1) (>= net462))
Microsoft.Build.Tasks.Git (1.1.1)
Microsoft.SourceLink.AzureRepos.Git (1.1.1)
Microsoft.Build.Tasks.Git (>= 1.1.1)
Microsoft.SourceLink.Common (>= 1.1.1)
Microsoft.SourceLink.Bitbucket.Git (1.1.1)
Microsoft.Build.Tasks.Git (>= 1.1.1)
Microsoft.SourceLink.Common (>= 1.1.1)
Microsoft.SourceLink.Common (1.1.1)
Microsoft.SourceLink.GitHub (1.1.1)
Microsoft.Build.Tasks.Git (>= 1.1.1)
Microsoft.SourceLink.Common (>= 1.1.1)
Microsoft.SourceLink.GitLab (1.1.1)
Microsoft.Build.Tasks.Git (>= 1.1.1)
Microsoft.SourceLink.Common (>= 1.1.1)
System.Runtime.CompilerServices.Unsafe (6.0) - restriction: || (&& (== net6.0) (>= net461)) (&& (== net6.0) (>= net462)) (&& (== net6.0) (< netcoreapp2.1) (< netstandard2.1)) (&& (== net6.0) (< netstandard1.0)) (&& (== net6.0) (< netstandard2.0)) (&& (== net6.0) (>= wp8)) (== netstandard2.0) (&& (== netstandard2.1) (>= net462))
System.Threading.Tasks.Extensions (4.5.4) - restriction: || (&& (== net6.0) (>= net462)) (&& (== net6.0) (< netstandard2.1)) (== netstandard2.0) (&& (== netstandard2.1) (>= net462))
System.Runtime.CompilerServices.Unsafe (>= 4.5.3) - restriction: || (&& (== net6.0) (>= net461)) (&& (== net6.0) (< netcoreapp2.1)) (&& (== net6.0) (< netstandard1.0)) (&& (== net6.0) (< netstandard2.0)) (&& (== net6.0) (>= wp8)) (== netstandard2.0) (== netstandard2.1)
Microsoft.Bcl.AsyncInterfaces (8.0) - restriction: || (&& (== net8.0) (< netcoreapp3.1)) (== netstandard2.0) (== netstandard2.1)
System.Threading.Tasks.Extensions (>= 4.5.4) - restriction: || (&& (== net8.0) (>= net462)) (&& (== net8.0) (< netstandard2.1)) (== netstandard2.0) (&& (== netstandard2.1) (>= net462))
Microsoft.Build.Tasks.Git (8.0)
Microsoft.SourceLink.AzureRepos.Git (8.0)
Microsoft.Build.Tasks.Git (>= 8.0)
Microsoft.SourceLink.Common (>= 8.0)
Microsoft.SourceLink.Bitbucket.Git (8.0)
Microsoft.Build.Tasks.Git (>= 8.0)
Microsoft.SourceLink.Common (>= 8.0)
Microsoft.SourceLink.Common (8.0)
Microsoft.SourceLink.GitHub (8.0)
Microsoft.Build.Tasks.Git (>= 8.0)
Microsoft.SourceLink.Common (>= 8.0)
Microsoft.SourceLink.GitLab (8.0)
Microsoft.Build.Tasks.Git (>= 8.0)
Microsoft.SourceLink.Common (>= 8.0)
System.Runtime.CompilerServices.Unsafe (6.0) - restriction: || (&& (== net8.0) (>= net461)) (&& (== net8.0) (>= net462)) (&& (== net8.0) (< netcoreapp2.1) (< netstandard2.1)) (&& (== net8.0) (< netstandard1.0)) (&& (== net8.0) (< netstandard2.0)) (&& (== net8.0) (>= wp8)) (== netstandard2.0) (&& (== netstandard2.1) (>= net462))
System.Threading.Tasks.Extensions (4.5.4) - restriction: || (&& (== net8.0) (>= net462)) (&& (== net8.0) (< netstandard2.1)) (== netstandard2.0) (&& (== netstandard2.1) (>= net462))
System.Runtime.CompilerServices.Unsafe (>= 4.5.3) - restriction: || (&& (== net8.0) (>= net461)) (&& (== net8.0) (< netcoreapp2.1)) (&& (== net8.0) (< netstandard1.0)) (&& (== net8.0) (< netstandard2.0)) (&& (== net8.0) (>= wp8)) (== netstandard2.0) (== netstandard2.1)
Unquote (6.1)
FSharp.Core (>= 4.7.2)
GITHUB
remote: eiriktsarpalis/TypeShape
src/TypeShape/TypeShape.fs (6e7fe07c799de723de7e4b32d64a4fd6c1697c7f)
src/TypeShape/TypeShape.fs (6e7fe07c799de723de7e4b32d64a4fd6c1697c7f)
GROUP Test
RESTRICTION: == net8.0
NUGET
remote: https://api.nuget.org/v3/index.json
FsCheck (2.16.6)
FSharp.Core (>= 4.2.3)
FSharp.Core (8.0.100)
Microsoft.CodeCoverage (17.8)
Microsoft.NET.Test.Sdk (17.8)
Microsoft.CodeCoverage (>= 17.8)
Microsoft.TestPlatform.TestHost (>= 17.8)
Microsoft.NETCore.Platforms (7.0.4)
Microsoft.TestPlatform.ObjectModel (17.8)
NuGet.Frameworks (>= 6.5)
System.Reflection.Metadata (>= 1.6)
Microsoft.TestPlatform.TestHost (17.8)
Microsoft.TestPlatform.ObjectModel (>= 17.8)
Newtonsoft.Json (>= 13.0.1)
NETStandard.Library (2.0.3)
Microsoft.NETCore.Platforms (>= 1.1)
Newtonsoft.Json (13.0.3)
NuGet.Frameworks (6.8)
System.Collections.Immutable (8.0)
System.Reflection.Metadata (8.0)
System.Collections.Immutable (>= 8.0)
xunit (2.6.2)
xunit.analyzers (>= 1.6)
xunit.assert (>= 2.6.2)
xunit.core (2.6.2)
xunit.abstractions (2.0.3)
xunit.analyzers (1.6)
xunit.assert (2.6.2)
xunit.core (2.6.2)
xunit.extensibility.core (2.6.2)
xunit.extensibility.execution (2.6.2)
xunit.extensibility.core (2.6.2)
NETStandard.Library (>= 1.6.1)
xunit.abstractions (>= 2.0.3)
xunit.extensibility.execution (2.6.2)
NETStandard.Library (>= 1.6.1)
xunit.extensibility.core (2.6.2)
xunit.runner.visualstudio (2.5.4)
2 changes: 2 additions & 0 deletions src/FSharp.AWS.DynamoDB/Expression/ConditionalExpr.fs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ let extractKeyCondition (qExpr : QueryExpr) =
| Not _
| Or _ -> false
| And(l,r) -> isKeyCond l && isKeyCond r
| BeginsWith(attr,_) when attr.IsRangeKey ->
trySet rangeKeyRef attr
| BeginsWith(attr,_) when attr.IsHashKey -> false
| BeginsWith(attr,_) when attr.IsRangeKey ->
trySet rangeKeyRef attr
Expand Down
4 changes: 2 additions & 2 deletions src/FSharp.AWS.DynamoDB/Expression/UpdateExpr.fs
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ let extractUpdateOps (exprs : IntermediateUpdateExprs) =
exprs.Assignments
|> Seq.map (fun (rp,e) -> extractUpdateOp rp e)
|> Seq.append exprs.UpdateOps
|> Seq.filter (function Skip _ -> false | _ -> true)
|> Seq.filter (function Skip -> false | _ -> true)
|> Seq.map (fun uop ->
if uop.Attribute.IsHashKey && uop.Attribute.IsPrimaryKey then invalidArg "expr" "update expression cannot update hash key."
if uop.Attribute.IsRangeKey && uop.Attribute.IsPrimaryKey then invalidArg "expr" "update expression cannot update range key."
Expand Down Expand Up @@ -373,7 +373,7 @@ let applyParams (uops : UpdateOperations) (inputValues : obj[]) =

let applyUpdateOp uop =
match uop with
| Skip _ -> uop
| Skip -> uop
| Remove(attr) -> Remove (applyAttr attr)
| Set(attr, uv) -> UpdateOperation.ESet (applyAttr attr) (applyUpdateValue uv)
| Add(attr, op) -> UpdateOperation.EAdd (applyAttr attr) (applyOperand op)
Expand Down
11 changes: 4 additions & 7 deletions src/FSharp.AWS.DynamoDB/FSharp.AWS.DynamoDB.fsproj
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<TargetFramework>netstandard2.0</TargetFramework>
<OutputPath>..\..\bin\</OutputPath>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Description>A library that provides an idiomatic F# API for AWS DynamoDB.</Description>
<Description>An idiomatic F# wrapper for the AWS DynamoDB SDK.</Description>
<Authors>Eirik Tsarpalis</Authors>
<Company />
<Copyright>Copyright 2016</Copyright>
<Product />
<PackageLicense>MIT</PackageLicense>
<PackageLicenseUrl>https://github.com/fsprojects/FSharp.AWS.DynamoDB/blob/master/License.md</PackageLicenseUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/fsprojects/FSharp.AWS.DynamoDB</PackageProjectUrl>
<PackageIconUrl>https://avatars0.githubusercontent.com/u/6001315</PackageIconUrl>
<PackageTags>fsharp, f#, aws, amazon, dynamodb</PackageTags>
</PropertyGroup>
<ItemGroup>
<None Include="paket.references" />
<Compile Include="..\..\paket-files\eiriktsarpalis\TypeShape\src\TypeShape\TypeShape.fs">
<Paket>True</Paket>
<Link>TypeShape/TypeShape.fs</Link>
Expand All @@ -41,7 +39,6 @@
<Compile Include="TableContext.fs" />
<Compile Include="Extensions.fs" />
<None Include="Script.fsx" />
<None Include="paket.references" />
<None Include="paket.template" />
</ItemGroup>
<Import Project="..\..\.paket\Paket.Restore.targets" />
Expand Down
6 changes: 5 additions & 1 deletion src/FSharp.AWS.DynamoDB/TableContext.fs
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ type TableContext<'TRecord> internal
| Some pc ->
let writer = AttributeWriter(request.ExpressionAttributeNames, request.ExpressionAttributeValues)
request.ConditionExpression <- pc.Conditional.Write writer
request.ReturnValuesOnConditionCheckFailure <- ReturnValuesOnConditionCheckFailure.ALL_OLD
| _ -> ()

let! ct = Async.CancellationToken
Expand Down Expand Up @@ -592,7 +593,9 @@ type TableContext<'TRecord> internal
request.UpdateExpression <- updater.UpdateOps.Write(writer)

match precondition with
| Some pc -> request.ConditionExpression <- pc.Conditional.Write writer
| Some pc ->
request.ConditionExpression <- pc.Conditional.Write writer
request.ReturnValuesOnConditionCheckFailure <- ReturnValuesOnConditionCheckFailure.ALL_OLD
| _ -> ()

let! ct = Async.CancellationToken
Expand Down Expand Up @@ -735,6 +738,7 @@ type TableContext<'TRecord> internal
| Some pc ->
let writer = AttributeWriter(request.ExpressionAttributeNames, request.ExpressionAttributeValues)
request.ConditionExpression <- pc.Conditional.Write writer
request.ReturnValuesOnConditionCheckFailure <- ReturnValuesOnConditionCheckFailure.ALL_OLD
| None -> ()

let! ct = Async.CancellationToken
Expand Down
24 changes: 4 additions & 20 deletions src/FSharp.AWS.DynamoDB/Types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ type HashKeyAttribute() =
type RangeKeyAttribute() =
inherit Attribute()

/// Declares that the carrying property should contain the RangeKey
/// Declares that the carrying property should contain the HashKey
/// for a global secondary index.
[<Sealed; AttributeUsage(AttributeTargets.Property)>]
[<Sealed; AttributeUsage(AttributeTargets.Property, AllowMultiple = true)>]
type GlobalSecondaryHashKeyAttribute(indexName : string) =
inherit Attribute()
member _.IndexName = indexName

/// Declares that the carrying property should contain the HashKey
/// Declares that the carrying property should contain the RangeKey
/// for a global secondary index.
[<Sealed; AttributeUsage(AttributeTargets.Property)>]
[<Sealed; AttributeUsage(AttributeTargets.Property, AllowMultiple = true)>]
type GlobalSecondaryRangeKeyAttribute(indexName : string) =
inherit Attribute()
member _.IndexName = indexName
Expand Down Expand Up @@ -110,22 +110,6 @@ type PropertySerializerAttribute<'PickleType>() =
member x.Serialize value = x.Serialize value :> obj
member x.Deserialize pickle = x.Deserialize (pickle :?> 'PickleType)

/// Declares that the given property should be serialized using BinaryFormatter
[<AttributeUsage(AttributeTargets.Property, AllowMultiple = false)>]
type BinaryFormatterAttribute() =
inherit PropertySerializerAttribute<byte[]>()

override _.Serialize(value:'T) =
let bfs = BinaryFormatter()
use m = new MemoryStream()
bfs.Serialize(m, value)
m.ToArray()

override _.Deserialize(pickle : byte[]) =
let bfs = BinaryFormatter()
use m = new MemoryStream(pickle)
bfs.Deserialize(m) :?> 'T

/// Metadata on a table key attribute
type KeyAttributeSchema =
{
Expand Down
20 changes: 8 additions & 12 deletions tests/FSharp.AWS.DynamoDB.Tests/ConditionalExpressionTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@ module CondExprTypes =
Map : Map<string, int64>

Set : Set<int64>

[<BinaryFormatter>]
Serialized : int64 * string
}

type ``Conditional Expression Tests`` (fixture : TableFixture) =
Expand All @@ -85,7 +82,6 @@ type ``Conditional Expression Tests`` (fixture : TableFixture) =
List = [for _ in 0L .. rand() % 5L -> rand() ]
Array = [| for _ in 0L .. rand() % 5L -> rand() |]
Union = if rand() % 2L = 0L then UA (rand()) else UB(guid())
Serialized = rand(), guid()
}

let table = fixture.CreateEmpty<CondExprRecord>()
Expand All @@ -104,6 +100,14 @@ type ``Conditional Expression Tests`` (fixture : TableFixture) =
fun () -> table.PutItem(item, precondition = itemDoesNotExist)
|> shouldFailwith<_, ConditionalCheckFailedException>

let [<Fact(Skip = "Not sure if this should be working")>] ``Item not exists failure should add conflicting item data to the exception`` () =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks reasonable to me - don't have a prod env to hand so I guess that points the finget of blame at the simulators...

let item = mkItem()
let _key = table.PutItem(item, precondition = itemDoesNotExist)
try
table.PutItem(item, precondition = itemDoesNotExist) |> ignore
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@samritchie Hm, probably should assert that it does not just succeed
by replacing the try-with with a single raisesWith expression

with :? ConditionalCheckFailedException as e ->
test <@ e.Item.Count > 0 @>

let [<Fact>] ``String precondition`` () =
let item = mkItem()
let _key = table.PutItem item
Expand Down Expand Up @@ -376,13 +380,6 @@ type ``Conditional Expression Tests`` (fixture : TableFixture) =
fun () -> table.Template.PrecomputeConditionalExpr <@ fun r -> r.Bytes.Length = r.Bytes.Length @>
|> shouldFailwith<_, ArgumentException>


let [<Fact>] ``Serializable precondition`` () =
let item = mkItem()
let _key = table.PutItem item
fun () -> table.PutItem(item, <@ fun r -> r.Serialized = (0L,"") @>)
|> shouldFailwith<_, ArgumentException>

let [<Fact>] ``EXISTS precondition`` () =
let item = { mkItem() with List = [1L] }
let _key = table.PutItem item
Expand Down Expand Up @@ -466,7 +463,6 @@ type ``Conditional Expression Tests`` (fixture : TableFixture) =
test false <@ fun r -> r.Map > Map.empty @>
test false <@ fun r -> r.Set > Set.empty @>
test false <@ fun r -> r.Ref > ref "12" @>
test false <@ fun r -> r.Serialized <= (1L, "32") @>
test false <@ fun r -> r.Tuple <= (1L, 2L) @>
test false <@ fun r -> r.Nested <= r.Nested @>

Expand Down
Loading