Skip to content

Commit

Permalink
server: Add a TTL table attribute and set it on every update operation
Browse files Browse the repository at this point in the history
  • Loading branch information
armsnyder committed Nov 22, 2020
1 parent ee06c11 commit 1d2dfe1
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 8 deletions.
39 changes: 31 additions & 8 deletions pkg/server/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"os"
"strings"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
Expand All @@ -26,6 +27,7 @@ const (
attribOpponent = "Opponent"
attribGame = "Game"
attribConnections = "Connections"
attribTTL = "TTL"
)

const indexByOpponent = "ByOpponent"
Expand Down Expand Up @@ -78,8 +80,8 @@ func updateGame(ctx context.Context, args Args, host string, game game) error {
}

update := expression.Set(expression.Name(attribGame), expression.Value(gameBytes))
builder := expression.NewBuilder().WithUpdate(update)
_, err = updateItem(ctx, args, host, builder, false)

_, err = updateItem(ctx, args, host, update, false)
return err
}

Expand All @@ -94,8 +96,7 @@ func updateGameOpponentSetConnection(ctx context.Context, args Args, host string
Set(expression.Name(attribOpponent), expression.Value(opponent)).
Set(expression.Name(attribConnections), expression.Value(map[string]string{connName: connID}))

builder := expression.NewBuilder().WithUpdate(update)
_, err = updateItem(ctx, args, host, builder, false)
_, err = updateItem(ctx, args, host, update, false)
return err
}

Expand All @@ -104,8 +105,8 @@ func updateOpponentConnectionGetGame(ctx context.Context, args Args, host, oppon
Set(expression.Name(attribOpponent), expression.Value(opponent)).
Set(expression.Name(attribConnections+"."+connName), expression.Value(connID))
condition := expression.In(expression.Name(attribOpponent), expression.Value(expectedOpponents[0]), expression.Value(expectedOpponents[1]))
builder := expression.NewBuilder().WithUpdate(update).WithCondition(condition)
output, err := updateItem(ctx, args, host, builder, true)

output, err := updateItemWithCondition(ctx, args, host, update, condition, true)
if err != nil {
return game{}, err
}
Expand Down Expand Up @@ -140,7 +141,21 @@ func getHostsByOpponent(ctx context.Context, args Args, opponent string) ([]stri
}

// updateItem wraps dynamodb.UpdateItemWithContext.
func updateItem(ctx context.Context, args Args, host string, builder expression.Builder, returnOldValues bool) (*dynamodb.UpdateItemOutput, error) {
func updateItem(ctx context.Context, args Args, host string, update expression.UpdateBuilder, returnOldValues bool) (*dynamodb.UpdateItemOutput, error) {
update = update.Set(expression.Name(attribTTL), expression.Value(time.Now().Add(time.Hour).Unix()))
builder := expression.NewBuilder().WithUpdate(update)
return updateItemWithBuilder(ctx, args, host, builder, returnOldValues)
}

// updateItemWithCondition wraps dynamodb.UpdateItemWithContext.
func updateItemWithCondition(ctx context.Context, args Args, host string, update expression.UpdateBuilder, condition expression.ConditionBuilder, returnOldValues bool) (*dynamodb.UpdateItemOutput, error) {
update = update.Set(expression.Name(attribTTL), expression.Value(time.Now().Add(time.Hour).Unix()))
builder := expression.NewBuilder().WithUpdate(update).WithCondition(condition)
return updateItemWithBuilder(ctx, args, host, builder, returnOldValues)
}

// updateItemWithBuilder wraps dynamodb.UpdateItemWithContext.
func updateItemWithBuilder(ctx context.Context, args Args, host string, builder expression.Builder, returnOldValues bool) (*dynamodb.UpdateItemOutput, error) {
exp, err := builder.Build()
if err != nil {
return nil, err
Expand Down Expand Up @@ -204,7 +219,15 @@ func EnsureTable(ctx context.Context, db *dynamodb.DynamoDB, name string) error
return err
}

return nil
_, err = db.UpdateTimeToLiveWithContext(ctx, &dynamodb.UpdateTimeToLiveInput{
TableName: aws.String(name),
TimeToLiveSpecification: &dynamodb.TimeToLiveSpecification{
AttributeName: aws.String(attribTTL),
Enabled: aws.Bool(true),
},
})

return err
}

func defaultDB() *dynamodb.DynamoDB {
Expand Down
18 changes: 18 additions & 0 deletions pkg/server/server_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"log"
"net"
"net/http"
"strconv"
"testing"
"time"

Expand Down Expand Up @@ -181,6 +182,23 @@ var _ = Describe("Server", func() {
Expect(board).To(Equal(newGameBoard))
})

It("should have a TTL", func(done Done) {
output, err := LocalDB().Scan(&dynamodb.ScanInput{TableName: aws.String(testTableName())})
if err != nil {
panic(err)
}
Expect(output.Items).NotTo(BeEmpty())
now := time.Now().Unix()
for _, item := range output.Items {
ttl, err := strconv.ParseInt(*item["TTL"].N, 10, 64)
if err != nil {
panic(err)
}
Expect(ttl).To(BeNumerically(">", now))
}
close(done)
})

When("craig hosts a game", func() {
BeforeEach(func(done Done) {
craig.sendMessage(common.NewHostGameMessage("craig"))
Expand Down

0 comments on commit 1d2dfe1

Please sign in to comment.