Skip to content

Commit

Permalink
Merge pull request #42 from bartelink/tryget
Browse files Browse the repository at this point in the history
Add TryGetItemAsync
  • Loading branch information
samritchie authored Mar 29, 2022
2 parents b63841a + 053c05d commit 3e1fadd
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 9 deletions.
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Moved Sync-over-Async versions of `TableContext` operations into `namespace FSharp.AWS.DynamoDB.Scripting`
* Added `?collector` parameter to each operation on `TableContext` to enable separated collection for concurrent requests
* Ensured metrics are reported even for failed requests
* Added `TryGetItemAsync` (same as `GetItemAsync`, but returns `None`, instead of throwing, if an item is not present)

### 0.9.3-beta
* Added `RequestMetrics` record type
Expand Down
32 changes: 23 additions & 9 deletions src/FSharp.AWS.DynamoDB/TableContext.fs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ type TableContext<'TRecord> internal
| Some sink -> ReturnConsumedCapacity.INDEXES, Some (reportMetrics sink)
| None -> ReturnConsumedCapacity.NONE, None

let getItemAsync (key : TableKey) (proj : ProjectionExpr.ProjectionExpr option) collector = async {
let tryGetItemAsync (key : TableKey) (proj : ProjectionExpr.ProjectionExpr option) collector = async {
let kav = template.ToAttributeValues(key)
let request = GetItemRequest(tableName, kav)
match proj with
Expand All @@ -80,11 +80,14 @@ type TableContext<'TRecord> internal
if response.HttpStatusCode <> HttpStatusCode.OK then
failwithf "GetItem request returned error %O" response.HttpStatusCode

if not response.IsItemSet then
let msg = sprintf "could not find item %O" key
raise <| ResourceNotFoundException(msg)
if response.IsItemSet then return Some response.Item
else return None
}

return response
let getItemAsync (key : TableKey) (proj : ProjectionExpr.ProjectionExpr option) collector = async {
match! tryGetItemAsync key proj collector with
| Some item -> return item
| None -> return raise <| ResourceNotFoundException(sprintf "could not find item %O" key)
}

let batchGetItemsAsync (keys : seq<TableKey>) (consistentRead : bool option)
Expand Down Expand Up @@ -421,6 +424,17 @@ type TableContext<'TRecord> internal
}


/// <summary>
/// Asynchronously attempts to fetch item with given key from table. Returns None if no item with that key is present.
/// </summary>
/// <param name="key">Key of item to be fetched.</param>
/// <param name="collector">Function to receive request metrics.</param>
member __.TryGetItemAsync(key : TableKey, ?collector) : Async<'TRecord option> = async {
let! response = tryGetItemAsync key None collector
return response |> Option.map template.OfAttributeValues
}


/// <summary>
/// Asynchronously checks whether item of supplied key exists in table.
/// </summary>
Expand All @@ -446,8 +460,8 @@ type TableContext<'TRecord> internal
/// <param name="key">Key of item to be fetched.</param>
/// <param name="collector">Function to receive request metrics.</param>
member __.GetItemAsync(key : TableKey, ?collector) : Async<'TRecord> = async {
let! response = getItemAsync key None collector
return template.OfAttributeValues response.Item
let! item = getItemAsync key None collector
return template.OfAttributeValues item
}


Expand All @@ -460,8 +474,8 @@ type TableContext<'TRecord> internal
/// <param name="projection">Projection expression to be applied to item.</param>
/// <param name="collector">Function to receive request metrics.</param>
member __.GetItemProjectedAsync(key : TableKey, projection : ProjectionExpression<'TRecord, 'TProjection>, ?collector) : Async<'TProjection> = async {
let! response = getItemAsync key (Some projection.ProjectionExpr) collector
return projection.UnPickle response.Item
let! item = getItemAsync key (Some projection.ProjectionExpr) collector
return projection.UnPickle item
}

/// <summary>
Expand Down
13 changes: 13 additions & 0 deletions tests/FSharp.AWS.DynamoDB.Tests/SimpleTableOperationTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,19 @@ type ``Simple Table Operation Tests`` (fixture : TableFixture) =
let _ = table.DeleteItem key
Expect.equal (table.ContainsKey key) false "ContainsKey should be false"

member this.``TryGet Operation`` () =
let value = mkItem()
let computedKey = table.Template.ExtractKey value
let get k = table.TryGetItemAsync k |> Async.RunSynchronously
let initialLoad = get computedKey
Expect.equal initialLoad None "TryGetItemAsync should yield None when not present"
let key = table.PutItem value
Expect.equal computedKey key "Local key computation should be same as Put result"
let loaded = get computedKey
Expect.equal (Some value) loaded "TryGetItemAsync should yield roundtripped value"
let _ = table.DeleteItem key
Expect.equal (get key |> Option.isSome) false "TryGetItemAsync should yield None"

member this.``Batch Put Operation`` () =
let values = set [ for i in 1L .. 20L -> mkItem() ]
let unprocessed = table.BatchPutItems values
Expand Down

0 comments on commit 3e1fadd

Please sign in to comment.