Completed DynamoDB + DAX Benchmarker with a nice TUI to boot
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
package simulators
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/Dark-Alex-17/dynamodb-benchmarker/pkg/models"
|
||||
"github.com/aws/aws-dax-go/dax"
|
||||
"github.com/aws/aws-sdk-go/service/dynamodb"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func ReadItem(client *dax.Dax, tableName string, id dynamodb.AttributeValue, metrics *models.DynamoDbSimulationMetrics, recordMetrics bool) (dynamodb.GetItemOutput, error) {
|
||||
partitionKey := *id.S
|
||||
startTime := time.Now()
|
||||
response, err := client.GetItem(&dynamodb.GetItemInput{
|
||||
TableName: &tableName,
|
||||
Key: map[string]*dynamodb.AttributeValue{
|
||||
"id": {S: id.S},
|
||||
},
|
||||
})
|
||||
|
||||
if recordMetrics {
|
||||
duration := time.Since(startTime).Microseconds()
|
||||
millisecondDuration := float64(duration) / 1000
|
||||
metrics.ReadTime = &millisecondDuration
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Could not fetch item with partition key: %v. %v+", partitionKey, err)
|
||||
metrics.Successful = false
|
||||
return dynamodb.GetItemOutput{}, err
|
||||
}
|
||||
|
||||
if len(response.Item) == 0 {
|
||||
log.Infof("No items found with partition key: %v", partitionKey)
|
||||
return dynamodb.GetItemOutput{}, nil
|
||||
}
|
||||
|
||||
return *response, nil
|
||||
}
|
||||
|
||||
func UpdateItem(client *dax.Dax, tableName string, id dynamodb.AttributeValue, attributes int, metrics *models.DynamoDbSimulationMetrics) {
|
||||
updatedItem := models.NewBenchmarkingItem(attributes)
|
||||
updatedItem["id"] = &id
|
||||
partitionKey := *id.S
|
||||
startTime := time.Now()
|
||||
|
||||
_, err := client.PutItem(&dynamodb.PutItemInput{
|
||||
TableName: &tableName,
|
||||
Item: updatedItem,
|
||||
})
|
||||
|
||||
duration := time.Since(startTime).Microseconds()
|
||||
millisecondDuration := float64(duration) / 1000
|
||||
metrics.UpdateTime = &millisecondDuration
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Could not update item with partition key: %v. %v+", partitionKey, err)
|
||||
metrics.Successful = false
|
||||
} else {
|
||||
log.Infof("Successfully updated item with partition key: %v", partitionKey)
|
||||
}
|
||||
}
|
||||
|
||||
func PutItem(client *dax.Dax, tableName string, attributes int, metrics *models.DynamoDbSimulationMetrics) (models.BenchmarkingItem, error) {
|
||||
newItem := models.NewBenchmarkingItem(attributes)
|
||||
partitionKey := *newItem["id"].S
|
||||
startTime := time.Now()
|
||||
|
||||
_, err := client.PutItem(&dynamodb.PutItemInput{
|
||||
TableName: &tableName,
|
||||
Item: newItem,
|
||||
})
|
||||
|
||||
duration := time.Since(startTime).Microseconds()
|
||||
millisecondDuration := float64(duration) / 1000
|
||||
metrics.WriteTime = &millisecondDuration
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Could not put new item with partition key: %v. %v+", partitionKey, err)
|
||||
metrics.Successful = false
|
||||
return models.BenchmarkingItem{}, err
|
||||
}
|
||||
|
||||
log.Infof("Successfully put new item with partition key: %v", partitionKey)
|
||||
return newItem, nil
|
||||
}
|
||||
|
||||
func DeleteItem(client *dax.Dax, tableName string, id dynamodb.AttributeValue, metrics *models.DynamoDbSimulationMetrics) {
|
||||
partitionKey := *id.S
|
||||
startTime := time.Now()
|
||||
|
||||
_, err := client.DeleteItem(&dynamodb.DeleteItemInput{
|
||||
TableName: &tableName,
|
||||
Key: map[string]*dynamodb.AttributeValue{
|
||||
"charger_id": &id,
|
||||
},
|
||||
})
|
||||
|
||||
duration := time.Since(startTime).Microseconds()
|
||||
millisecondDuration := float64(duration) / 1000
|
||||
metrics.DeleteTime = &millisecondDuration
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Could not delete item with partition key: %v. %v+", partitionKey, err)
|
||||
metrics.Successful = false
|
||||
} else {
|
||||
log.Infof("Successfully deleted item with partition key: %v", partitionKey)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package simulators
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Dark-Alex-17/dynamodb-benchmarker/pkg/models"
|
||||
"github.com/aws/aws-dax-go/dax"
|
||||
"github.com/aws/aws-sdk-go/service/dynamodb"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func SimulateReadOperation(client *dax.Dax, tableName string, partitionKeys []string, metrics *models.DynamoDbSimulationMetrics) {
|
||||
log.Info("Performing READ operation...")
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
var partitionKey string
|
||||
for {
|
||||
partitionKey = partitionKeys[r.Intn(len(partitionKeys))]
|
||||
if len(strings.TrimSpace(partitionKey)) == 0 {
|
||||
log.Info("Parition key was empty. Trying again to choose a non-empty partition key")
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
id := dynamodb.AttributeValue{S: &partitionKey}
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
log.Infof("Attempt %d: Fetching existing item with partition key: %v", i, partitionKey)
|
||||
|
||||
response, _ := ReadItem(client, tableName, id, metrics, true)
|
||||
if response.Item["id"] != nil {
|
||||
log.Infof("Successfully read existing item with partition key: %v", partitionKey)
|
||||
break
|
||||
}
|
||||
|
||||
log.Errorf("Unable to find existing item with partition key: %v", partitionKey)
|
||||
if i == 9 {
|
||||
log.Errorf("All attempts to fetch the existing item with partition key: %v failed!", partitionKey)
|
||||
metrics.Successful = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func SimulateWriteOperation(client *dax.Dax, tableName string, attributes int, metrics *models.DynamoDbSimulationMetrics) {
|
||||
log.Info("Performing WRITE operation...")
|
||||
benchmarkingItem, err := PutItem(client, tableName, attributes, metrics)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to complete PUT simulation. %v+", err)
|
||||
metrics.Successful = false
|
||||
return
|
||||
}
|
||||
|
||||
id := *benchmarkingItem["id"]
|
||||
|
||||
AssertItemWasCreated(client, tableName, id, metrics)
|
||||
|
||||
DeleteItem(client, tableName, id, metrics)
|
||||
|
||||
AssertItemWasDeleted(client, tableName, id, metrics)
|
||||
}
|
||||
|
||||
func SimulateUpdateOperation(client *dax.Dax, tableName string, attributes int, metrics *models.DynamoDbSimulationMetrics) {
|
||||
log.Info("Performing UPDATE operation...")
|
||||
newItem, err := PutItem(client, tableName, attributes, metrics)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to complete UPDATE simulation. %v+", err)
|
||||
metrics.Successful = false
|
||||
return
|
||||
}
|
||||
|
||||
id := *newItem["id"]
|
||||
partitionKey := *id.S
|
||||
attemptsExhausted := false
|
||||
|
||||
AssertItemWasCreated(client, tableName, id, metrics)
|
||||
UpdateItem(client, tableName, id, attributes, metrics)
|
||||
|
||||
startTime := time.Now()
|
||||
for i := 0; i < 10; i++ {
|
||||
log.Infof("Attempt %d: Fetching updated item for partition key: %v...", i, partitionKey)
|
||||
|
||||
updatedItem, err := ReadItem(client, tableName, id, metrics, false)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to complete UPDATE simulation. %v+", err)
|
||||
metrics.Successful = false
|
||||
return
|
||||
}
|
||||
|
||||
if *newItem["1"].N != *updatedItem.Item["1"].N {
|
||||
log.Infof("Confirmed update for partition key: %v", partitionKey)
|
||||
break
|
||||
} else {
|
||||
log.Errorf("Update for partition key %v failed! Values are still equal!", partitionKey)
|
||||
if i == 9 {
|
||||
log.Error("Exhausted attempts to fetch updated item!")
|
||||
metrics.Successful = false
|
||||
attemptsExhausted = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !attemptsExhausted {
|
||||
duration := time.Since(startTime).Microseconds()
|
||||
millisecondDuration := float64(duration) / 1000
|
||||
metrics.UpdateItemConfirmationTime = &millisecondDuration
|
||||
}
|
||||
|
||||
DeleteItem(client, tableName, id, metrics)
|
||||
AssertItemWasDeleted(client, tableName, id, metrics)
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package simulators
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/Dark-Alex-17/dynamodb-benchmarker/pkg/models"
|
||||
"github.com/aws/aws-dax-go/dax"
|
||||
"github.com/aws/aws-sdk-go/service/dynamodb"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func AssertItemWasCreated(client *dax.Dax, tableName string, id dynamodb.AttributeValue, metrics *models.DynamoDbSimulationMetrics) {
|
||||
partitionKey := *id.S
|
||||
attemptsExhausted := false
|
||||
startTime := time.Now()
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
log.Infof("Attempt %d: Fetching newly added item with partition key: %v", i, partitionKey)
|
||||
|
||||
newItem, err := ReadItem(client, tableName, id, metrics, false)
|
||||
|
||||
if err != nil || newItem.Item["id"].S == nil {
|
||||
log.Errorf("Unable to find new item with partition key: %v", partitionKey)
|
||||
if i == 9 {
|
||||
log.Errorf("All attempts to fetch the newly added item with partition key: %v failed!", partitionKey)
|
||||
attemptsExhausted = true
|
||||
metrics.Successful = false
|
||||
}
|
||||
} else {
|
||||
log.Infof("Successfully read new item with partition key: %v", partitionKey)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !attemptsExhausted {
|
||||
duration := time.Since(startTime).Microseconds()
|
||||
millisecondDuration := float64(duration) / 1000
|
||||
metrics.WriteItemConfirmationTime = &millisecondDuration
|
||||
}
|
||||
}
|
||||
|
||||
func AssertItemWasDeleted(client *dax.Dax, tableName string, id dynamodb.AttributeValue, metrics *models.DynamoDbSimulationMetrics) {
|
||||
partitionKey := *id.S
|
||||
attemptsExhausted := false
|
||||
startTime := time.Now()
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
log.Infof("Attempt %d: Fetching deleted item with partition key: %v ...", i, partitionKey)
|
||||
|
||||
deletedItem, _ := ReadItem(client, tableName, id, metrics, false)
|
||||
if deletedItem.Item["id"].S == nil {
|
||||
log.Infof("Item with partition key: %v was successfully deleted.", partitionKey)
|
||||
break
|
||||
} else {
|
||||
log.Errorf("Item with partition key %v was not deleted as expected!", partitionKey)
|
||||
if i == 9 {
|
||||
log.Errorf("All attempts to receive an empty response to verify item with partition key: %v was deleted failed!", partitionKey)
|
||||
attemptsExhausted = true
|
||||
metrics.Successful = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !attemptsExhausted {
|
||||
duration := time.Since(startTime).Microseconds()
|
||||
millisecondDuration := float64(duration) / 1000
|
||||
metrics.DeleteItemConfirmationTime = &millisecondDuration
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user