Skip to content

Commit eb01da4

Browse files
improve table verification logic
1 parent 1e4bdb0 commit eb01da4

File tree

2 files changed

+55
-28
lines changed

2 files changed

+55
-28
lines changed

src/FSharp.DynamoDB/TableContext.fs

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -548,37 +548,61 @@ type TableContext<'TRecord> internal (client : IAmazonDynamoDB, tableName : stri
548548
/// <param name="provisionedThroughput">Provisioned throughput for the table if newly created.</param>
549549
member __.VerifyTableAsync(?createIfNotExists : bool, ?provisionedThroughput : ProvisionedThroughput) : Async<unit> = async {
550550
let createIfNotExists = defaultArg createIfNotExists false
551-
try
552-
let dtr = new DescribeTableRequest(tableName)
551+
let rec verify retries = async {
552+
if retries = 0 then failwithf "failed to create table '%s'" tableName
553553
let! ct = Async.CancellationToken
554-
let! response = client.DescribeTableAsync(dtr, ct) |> Async.AwaitTaskCorrect
555-
let existingSchema = TableKeySchema.OfTableDescription response.Table
556-
if existingSchema <> template.KeySchema then
557-
sprintf "table '%s' exists with key schema %A, which is incompatible with record '%O'."
558-
tableName existingSchema typeof<'TRecord>
559-
|> invalidOp
560-
561-
with :? ResourceNotFoundException when createIfNotExists ->
562-
let provisionedThroughput =
563-
match provisionedThroughput with
564-
| None -> new ProvisionedThroughput(10L,10L)
565-
| Some pt -> pt
566-
567-
let ctr = template.KeySchema.CreateCreateTableRequest (tableName, provisionedThroughput)
568-
let! ct = Async.CancellationToken
569-
let! response = client.CreateTableAsync(ctr, ct) |> Async.AwaitTaskCorrect
570-
if response.HttpStatusCode <> HttpStatusCode.OK then
571-
failwithf "CreateTable request returned error %O" response.HttpStatusCode
572-
573-
let rec awaitReady retries = async {
574-
if retries = 0 then return failwithf "Failed to create table '%s'" tableName
575-
let! descr = client.DescribeTableAsync(tableName, ct) |> Async.AwaitTaskCorrect
576-
if descr.Table.TableStatus <> TableStatus.ACTIVE then
554+
let! response =
555+
client.DescribeTableAsync(tableName, ct)
556+
|> Async.AwaitTaskCorrect
557+
|> Async.Catch
558+
559+
let (|Conflict|_|) (e : exn) =
560+
match e with
561+
| :? AmazonDynamoDBException as e when e.StatusCode = HttpStatusCode.Conflict -> Some()
562+
| :? ResourceInUseException -> Some ()
563+
| _ -> None
564+
565+
match response with
566+
| Choice1Of2 td ->
567+
let existingSchema = TableKeySchema.OfTableDescription td.Table
568+
if existingSchema <> template.KeySchema then
569+
sprintf "table '%s' exists with key schema %A, which is incompatible with record '%O'."
570+
tableName existingSchema typeof<'TRecord>
571+
|> invalidOp
572+
573+
if td.Table.TableStatus <> TableStatus.ACTIVE then
574+
do! Async.Sleep 1000
575+
return! verify (retries - 1)
576+
577+
| Choice2Of2 (:? ResourceNotFoundException) when createIfNotExists ->
578+
let provisionedThroughput =
579+
match provisionedThroughput with
580+
| None -> new ProvisionedThroughput(10L,10L)
581+
| Some pt -> pt
582+
583+
let ctr = template.KeySchema.CreateCreateTableRequest (tableName, provisionedThroughput)
584+
let! ct = Async.CancellationToken
585+
let! response =
586+
client.CreateTableAsync(ctr, ct)
587+
|> Async.AwaitTaskCorrect
588+
|> Async.Catch
589+
590+
match response with
591+
| Choice1Of2 _ -> return! verify (retries - 1)
592+
| Choice2Of2 Conflict ->
577593
do! Async.Sleep 1000
578-
return! awaitReady (retries - 1)
579-
}
594+
return! verify (retries - 1)
595+
596+
| Choice2Of2 e -> do! Async.Raise e
597+
598+
| Choice2Of2 Conflict ->
599+
do! Async.Sleep 1000
600+
return! verify (retries - 1)
601+
602+
| Choice2Of2 e -> do! Async.Raise e
603+
}
580604

581-
do! awaitReady 30
605+
do! verify 30
582606
}
583607

584608
/// <summary>

src/FSharp.DynamoDB/Utils/Utils.fs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ module internal Utils =
204204
e :> exn
205205

206206
type Async with
207+
/// Raise an exception
208+
static member Raise e = Async.FromContinuations(fun (_,ec,_) -> ec e)
209+
207210
/// <summary>
208211
/// Gets the result of given task so that in the event of exception
209212
/// the actual user exception is raised as opposed to being wrapped

0 commit comments

Comments
 (0)