Skip to content

Commit 521dc6f

Browse files
mehran-dabiMehran Dabestani
andauthored
add batch get items methods to repository for retrieving multiple items by keys; (#22)
* add batch get items methods to repository for retrieving multiple items by keys; --------- Co-authored-by: Mehran Dabestani <mehran.dabestani@adjoe.io>
1 parent 37fd839 commit 521dc6f

5 files changed

Lines changed: 660 additions & 0 deletions

dynamo_global_index_interface.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"context"
55
)
66

7+
//go:generate mockgen -source=dynamo_global_index_interface.go -destination=./mock/dynamo_global_index_interface.go -package=mock .
8+
79
type GlobalIndexInterface interface {
810
// GetItemWithContext get item from index; it accepts a key interface that is used to get the table name, hash key and range key if it exists;
911
// context which used to enable log with context; the output will be given in item

dynamo_repository.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,3 +585,65 @@ func (repository Repository) ScanIteratorWithContext(ctx context.Context, key Ke
585585

586586
return itr, nil
587587
}
588+
589+
// BatchGetItemsWithContext gets multiple items by their keys; all keys must refer to the same table.
590+
// out must be a pointer to a slice of your model type.
591+
// Returns (true, nil) if at least one item is found, (false, nil) if none found, or (false, err) on error.
592+
func (repository *Repository) BatchGetItemsWithContext(ctx context.Context, keys []KeyInterface, out interface{}) (bool, error) {
593+
if len(keys) == 0 {
594+
return false, nil
595+
}
596+
597+
// Validate keys and ensure they all point to the same table
598+
tableName := keys[0].TableName()
599+
for i := 0; i < len(keys); i++ {
600+
if err := isValidKey(keys[i]); err != nil {
601+
repository.log.error(ctx, keys[i].TableName(), err.Error())
602+
return false, err
603+
}
604+
if keys[i].TableName() != tableName {
605+
err := errors.New("BatchGetItemsWithContext: all keys must belong to the same table")
606+
repository.log.error(ctx, tableName, err.Error())
607+
return false, err
608+
}
609+
}
610+
611+
// by hash
612+
batch := repository.table(tableName).Batch(*keys[0].HashKeyName())
613+
// by hash & range
614+
if keys[0].RangeKeyName() != nil && keys[0].RangeKey() != nil {
615+
batch = repository.table(tableName).Batch(*keys[0].HashKeyName(), *keys[0].RangeKeyName())
616+
}
617+
618+
// Build dynamo keys
619+
dKeys := make([]dynamo.Keyed, len(keys))
620+
for i := 0; i < len(keys); i++ {
621+
dKeys[i] = dynamo.Keyed(keys[i])
622+
}
623+
624+
// Execute batch get
625+
err := batch.Get(dKeys...).AllWithContext(ctx, out)
626+
if err != nil {
627+
if errors.Is(err, dynamo.ErrNotFound) {
628+
repository.log.info(ctx, tableName, ErrNoItemFound.Error())
629+
return false, nil
630+
}
631+
632+
repository.log.error(ctx, tableName, err.Error())
633+
return false, err
634+
}
635+
636+
// Check if slice is empty
637+
val := reflect.ValueOf(out)
638+
if val.Kind() == reflect.Ptr {
639+
val = val.Elem()
640+
}
641+
642+
if val.Kind() == reflect.Array || val.Kind() == reflect.Slice {
643+
if val.Len() == 0 {
644+
return false, nil
645+
}
646+
}
647+
648+
return true, nil
649+
}

dynamo_repository_interface.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"context"
55
)
66

7+
//go:generate mockgen -source=dynamo_repository_interface.go -destination=./mock/dynamo_repository_interface.go -package=mock .
8+
79
// RepositoryInterface provides an interface to enable mocking the AWS dynamodb repository
810
// for testing your code.
911
type RepositoryInterface interface {
@@ -109,4 +111,9 @@ type RepositoryInterface interface {
109111

110112
//ConditionalUpdate updates an item if the passed expression and condition evaluates to true
111113
ConditionalUpdate(key KeyInterface, item interface{}, expression string, expressionArgs ...interface{}) (bool, error)
114+
115+
// BatchGetItemsWithContext gets multiple items by their keys; it accepts a slice of keys (all from the same table)
116+
// and fills out (pointer to a slice) with any found items.
117+
// returns true if at least one item is found, returns false and nil if no items found, returns false and error in case of error
118+
BatchGetItemsWithContext(ctx context.Context, keys []KeyInterface, out interface{}) (bool, error)
112119
}

mock/dynamo_global_index_interface.go

Lines changed: 139 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)