Skip to content

Commit

Permalink
Use a Set rather than a List for putAll
Browse files Browse the repository at this point in the history
Dynamo won't accept a putAll with duplicate primary keys and the order which they're put isn't pertinent, so use a `Set`, rather than a `List`.
  • Loading branch information
Philip Wills committed Jul 14, 2016
1 parent ee5555d commit a4ececc
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 41 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ scala> def temptWithGum(child: LuckyWinner): LuckyWinner = child match {
scala> val luckyWinners = Table[LuckyWinner]("winners")
scala> val operations = for {
| _ <- luckyWinners.putAll(
| List(LuckyWinner("Violet", "human"), LuckyWinner("Augustus", "human"), LuckyWinner("Charlie", "human")))
| Set(LuckyWinner("Violet", "human"), LuckyWinner("Augustus", "human"), LuckyWinner("Charlie", "human")))
| winners <- luckyWinners.scan()
| winnerList = winners.flatMap(_.toOption).toList
| temptedWinners = winnerList.map(temptWithGum)
| _ <- luckyWinners.putAll(temptedWinners)
| _ <- luckyWinners.putAll(temptedWinners.toSet)
| results <- luckyWinners.getAll('name -> List("Charlie", "Violet"))
| } yield results

Expand All @@ -105,7 +105,7 @@ scala> val transportTableResult = LocalDynamoDB.createTable(client)("transports"
scala> case class Transport(mode: String, line: String)
scala> val transportTable = Table[Transport]("transports")
scala> val operations = for {
| _ <- transportTable.putAll(List(
| _ <- transportTable.putAll(Set(
| Transport("Underground", "Circle"),
| Transport("Underground", "Metropolitan"),
| Transport("Underground", "Central")
Expand Down Expand Up @@ -160,7 +160,7 @@ scala> val client = LocalDynamoDB.client()
scala> import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType._
scala> LocalDynamoDB.withTableWithSecondaryIndex(client)("transport", "colour-index")('mode -> S, 'line -> S)('colour -> S) {
| val operations = for {
| _ <- transport.putAll(List(
| _ <- transport.putAll(Set(
| Transport("Underground", "Circle", "Yellow"),
| Transport("Underground", "Metropolitan", "Maroon"),
| Transport("Underground", "Central", "Red")))
Expand Down Expand Up @@ -190,7 +190,7 @@ scala> case class Farm(animals: List[String])
scala> case class Farmer(name: String, age: Long, farm: Farm)
scala> val farmTable = Table[Farmer]("farm")
scala> val ops = for {
| _ <- farmTable.putAll(List(
| _ <- farmTable.putAll(Set(
| Farmer("Boggis", 43L, Farm(List("chicken"))),
| Farmer("Bunce", 52L, Farm(List("goose"))),
| Farmer("Bean", 55L, Farm(List("turkey")))
Expand Down
20 changes: 10 additions & 10 deletions src/main/scala/com/gu/scanamo/Scanamo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ object Scanamo {
* >>> import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType._
* >>> LocalDynamoDB.withTable(client)("rabbits")('name -> S) {
* ... Scanamo.putAll(client)("rabbits")((
* ... for { _ <- 0 until 100 } yield Rabbit(util.Random.nextString(500))).toList)
* ... for { _ <- 0 until 100 } yield Rabbit(util.Random.nextString(500))).toSet)
* ... Scanamo.scan[Rabbit](client)("rabbits").size
* ... }
* 100
* }}}
*/
def putAll[T: DynamoFormat](client: AmazonDynamoDB)(tableName: String)(items: List[T]): List[BatchWriteItemResult] =
def putAll[T: DynamoFormat](client: AmazonDynamoDB)(tableName: String)(items: Set[T]): List[BatchWriteItemResult] =
exec(client)(ScanamoFree.putAll(tableName)(items))

/**
Expand Down Expand Up @@ -109,7 +109,7 @@ object Scanamo {
*
* >>> import com.gu.scanamo.query._
* >>> LocalDynamoDB.withTable(client)("farmers")('name -> S) {
* ... Scanamo.putAll(client)("farmers")(List(
* ... Scanamo.putAll(client)("farmers")(Set(
* ... Farmer("Boggis", 43L, Farm(List("chicken"))), Farmer("Bunce", 52L, Farm(List("goose"))), Farmer("Bean", 55L, Farm(List("turkey")))
* ... ))
* ... Scanamo.getAll[Farmer](client)("farmers")(UniqueKeys(KeyList('name, List("Boggis", "Bean"))))
Expand All @@ -120,7 +120,7 @@ object Scanamo {
* {{{
* >>> import com.gu.scanamo.syntax._
* >>> LocalDynamoDB.withTable(client)("farmers")('name -> S) {
* ... Scanamo.putAll(client)("farmers")(List(
* ... Scanamo.putAll(client)("farmers")(Set(
* ... Farmer("Boggis", 43L, Farm(List("chicken"))), Farmer("Bunce", 52L, Farm(List("goose"))), Farmer("Bean", 55L, Farm(List("turkey")))
* ... ))
* ... Scanamo.getAll[Farmer](client)("farmers")('name -> List("Boggis", "Bean"))
Expand All @@ -132,7 +132,7 @@ object Scanamo {
* >>> case class Doctor(actor: String, regeneration: Int)
* >>> LocalDynamoDB.withTable(client)("doctors")('actor -> S, 'regeneration -> N) {
* ... Scanamo.putAll(client)("doctors")(
* ... List(Doctor("McCoy", 9), Doctor("Ecclestone", 10), Doctor("Ecclestone", 11)))
* ... Set(Doctor("McCoy", 9), Doctor("Ecclestone", 10), Doctor("Ecclestone", 11)))
* ... Scanamo.getAll[Doctor](client)("doctors")(('actor and 'regeneration) -> List("McCoy" -> 9, "Ecclestone" -> 11))
* ... }
* List(Right(Doctor(McCoy,9)), Right(Doctor(Ecclestone,11)))
Expand Down Expand Up @@ -212,7 +212,7 @@ object Scanamo {
*
* >>> LocalDynamoDB.withTable(client)("lemmings")('name -> S) {
* ... Scanamo.putAll(client)("lemmings")(
* ... (for { _ <- 0 until 100 } yield Lemming(util.Random.nextString(500), util.Random.nextString(5000))).toList
* ... (for { _ <- 0 until 100 } yield Lemming(util.Random.nextString(500), util.Random.nextString(5000))).toSet
* ... )
* ... Scanamo.scan[Lemming](client)("lemmings").size
* ... }
Expand Down Expand Up @@ -326,7 +326,7 @@ object Scanamo {
*
* >>> case class Transport(mode: String, line: String)
* >>> LocalDynamoDB.withTable(client)("transport")('mode -> S, 'line -> S) {
* ... Scanamo.putAll(client)("transport")(List(
* ... Scanamo.putAll(client)("transport")(Set(
* ... Transport("Underground", "Circle"),
* ... Transport("Underground", "Metropolitan"),
* ... Transport("Underground", "Central")))
Expand Down Expand Up @@ -357,7 +357,7 @@ object Scanamo {
*
* >>> case class Transport(mode: String, line: String)
* >>> LocalDynamoDB.withTable(client)("transport")('mode -> S, 'line -> S) {
* ... Scanamo.putAll(client)("transport")(List(
* ... Scanamo.putAll(client)("transport")(Set(
* ... Transport("Underground", "Circle"),
* ... Transport("Underground", "Metropolitan"),
* ... Transport("Underground", "Central")))
Expand All @@ -380,7 +380,7 @@ object Scanamo {
* >>> import com.gu.scanamo.syntax._
*
* >>> LocalDynamoDB.withTableWithSecondaryIndex(client)("transport", "colour-index")('mode -> S, 'line -> S)('colour -> S) {
* ... Scanamo.putAll(client)("transport")(List(
* ... Scanamo.putAll(client)("transport")(Set(
* ... Transport("Underground", "Circle", "Yellow"),
* ... Transport("Underground", "Metropolitan", "Magenta"),
* ... Transport("Underground", "Central", "Red")))
Expand All @@ -405,7 +405,7 @@ object Scanamo {
* >>> LocalDynamoDB.withTableWithSecondaryIndex(client)("transport", "colour-index")(
* ... 'mode -> S, 'line -> S)('mode -> S, 'colour -> S
* ... ) {
* ... Scanamo.putAll(client)("transport")(List(
* ... Scanamo.putAll(client)("transport")(Set(
* ... Transport("Underground", "Circle", "Yellow"),
* ... Transport("Underground", "Metropolitan", "Magenta"),
* ... Transport("Underground", "Central", "Red"),
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/com/gu/scanamo/ScanamoAsync.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ object ScanamoAsync {
(implicit ec: ExecutionContext): Future[PutItemResult] =
exec(client)(ScanamoFree.put(tableName)(item))

def putAll[T: DynamoFormat](client: AmazonDynamoDBAsync)(tableName: String)(items: List[T])
def putAll[T: DynamoFormat](client: AmazonDynamoDBAsync)(tableName: String)(items: Set[T])
(implicit ec: ExecutionContext): Future[List[BatchWriteItemResult]] =
exec(client)(ScanamoFree.putAll(tableName)(items))

Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/com/gu/scanamo/ScanamoFree.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ object ScanamoFree {
def put[T](tableName: String)(item: T)(implicit f: DynamoFormat[T]): ScanamoOps[PutItemResult] =
ScanamoOps.put(putRequest(tableName)(item))

def putAll[T: DynamoFormat](tableName: String)(items: List[T]): ScanamoOps[List[BatchWriteItemResult]] =
def putAll[T: DynamoFormat](tableName: String)(items: Set[T]): ScanamoOps[List[BatchWriteItemResult]] =
items.grouped(25).toList.traverseU(batch =>
ScanamoOps.batchWrite(batchPutRequest(tableName)(batch)))

Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/com/gu/scanamo/ScanamoRequest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ private object Requests {
def putRequest[T](tableName: String)(item: T)(implicit f: DynamoFormat[T]): ScanamoPutRequest =
ScanamoPutRequest(tableName, f.write(item).getM, None)

def batchPutRequest[T](tableName: String)(items: List[T])(implicit f: DynamoFormat[T]): BatchWriteItemRequest =
new BatchWriteItemRequest().withRequestItems(Map(tableName -> items.map(i =>
def batchPutRequest[T](tableName: String)(items: Set[T])(implicit f: DynamoFormat[T]): BatchWriteItemRequest =
new BatchWriteItemRequest().withRequestItems(Map(tableName -> items.toList.map(i =>
new WriteRequest().withPutRequest(new PutRequest().withItem(f.write(i).getM))
).asJava).asJava)

Expand Down
24 changes: 12 additions & 12 deletions src/main/scala/com/gu/scanamo/Table.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import com.gu.scanamo.update.UpdateExpression
* >>> LocalDynamoDB.withTable(client)("transport")('mode -> S, 'line -> S) {
* ... import com.gu.scanamo.syntax._
* ... val operations = for {
* ... _ <- transport.putAll(List(
* ... _ <- transport.putAll(Set(
* ... Transport("Underground", "Circle"),
* ... Transport("Underground", "Metropolitan"),
* ... Transport("Underground", "Central")))
Expand All @@ -33,7 +33,7 @@ import com.gu.scanamo.update.UpdateExpression
case class Table[V: DynamoFormat](name: String) {

def put(v: V) = ScanamoFree.put(name)(v)
def putAll(vs: List[V]) = ScanamoFree.putAll(name)(vs)
def putAll(vs: Set[V]) = ScanamoFree.putAll(name)(vs)
def get(key: UniqueKey[_]) = ScanamoFree.get[V](name)(key)
def getAll(keys: UniqueKeys[_]) = ScanamoFree.getAll[V](name)(keys)
def delete(key: UniqueKey[_]) = ScanamoFree.delete(name)(key)
Expand All @@ -51,7 +51,7 @@ case class Table[V: DynamoFormat](name: String) {
*
* >>> LocalDynamoDB.withTableWithSecondaryIndex(client)("transport", "colour-index")('mode -> S, 'line -> S)('colour -> S) {
* ... val operations = for {
* ... _ <- transport.putAll(List(
* ... _ <- transport.putAll(Set(
* ... Transport("Underground", "Circle", "Yellow"),
* ... Transport("Underground", "Metropolitan", "Magenta"),
* ... Transport("Underground", "Central", "Red")))
Expand Down Expand Up @@ -159,7 +159,7 @@ case class Table[V: DynamoFormat](name: String) {
* >>> LocalDynamoDB.withTable(client)("transport")('mode -> S, 'line -> S) {
* ... import com.gu.scanamo.syntax._
* ... val operations = for {
* ... _ <- transport.putAll(List(
* ... _ <- transport.putAll(Set(
* ... Transport("Underground", "Circle"),
* ... Transport("Underground", "Metropolitan"),
* ... Transport("Underground", "Central")))
Expand Down Expand Up @@ -200,7 +200,7 @@ case class Table[V: DynamoFormat](name: String) {
* >>> val lettersTable = Table[Letter]("letters")
* >>> LocalDynamoDB.withTable(client)("letters")('roman -> S) {
* ... val ops = for {
* ... _ <- lettersTable.putAll(List(Letter("a", "alpha"), Letter("b", "beta"), Letter("c", "gammon")))
* ... _ <- lettersTable.putAll(Set(Letter("a", "alpha"), Letter("b", "beta"), Letter("c", "gammon")))
* ... _ <- lettersTable.given('greek beginsWith "ale").put(Letter("a", "aleph"))
* ... _ <- lettersTable.given('greek beginsWith "gam").put(Letter("c", "gamma"))
* ... letters <- lettersTable.scan()
Expand All @@ -214,7 +214,7 @@ case class Table[V: DynamoFormat](name: String) {
* >>> val turnipsTable = Table[Turnip]("turnips")
* >>> LocalDynamoDB.withTable(client)("turnips")('size -> N) {
* ... val ops = for {
* ... _ <- turnipsTable.putAll(List(Turnip(1, None), Turnip(1000, None)))
* ... _ <- turnipsTable.putAll(Set(Turnip(1, None), Turnip(1000, None)))
* ... initialTurnips <- turnipsTable.scan()
* ... _ <- initialTurnips.flatMap(_.toOption).traverse(t =>
* ... turnipsTable.given('size > 500).put(t.copy(description = Some("Big turnip in the country."))))
Expand All @@ -232,7 +232,7 @@ case class Table[V: DynamoFormat](name: String) {
* >>> val thingTable = Table[Thing]("things")
* >>> LocalDynamoDB.withTable(client)("things")('a -> S) {
* ... val ops = for {
* ... _ <- thingTable.putAll(List(Thing("a", None), Thing("b", Some(1)), Thing("c", None)))
* ... _ <- thingTable.putAll(Set(Thing("a", None), Thing("b", Some(1)), Thing("c", None)))
* ... _ <- thingTable.given(attributeExists('maybe)).put(Thing("a", Some(2)))
* ... _ <- thingTable.given(attributeExists('maybe)).put(Thing("b", Some(3)))
* ... _ <- thingTable.given(Not(attributeExists('maybe))).put(Thing("c", Some(42)))
Expand All @@ -251,7 +251,7 @@ case class Table[V: DynamoFormat](name: String) {
* >>> val compoundTable = Table[Compound]("compounds")
* >>> LocalDynamoDB.withTable(client)("compounds")('a -> S) {
* ... val ops = for {
* ... _ <- compoundTable.putAll(List(Compound("alpha", None), Compound("beta", Some(1)), Compound("gamma", None)))
* ... _ <- compoundTable.putAll(Set(Compound("alpha", None), Compound("beta", Some(1)), Compound("gamma", None)))
* ... _ <- compoundTable.given(attributeExists('maybe) and 'a -> "alpha").put(Compound("alpha", Some(2)))
* ... _ <- compoundTable.given(attributeExists('maybe) and 'a -> "beta").put(Compound("beta", Some(3)))
* ... _ <- compoundTable.given(Condition('a -> "gamma") and attributeExists('maybe)).put(Compound("gamma", Some(42)))
Expand All @@ -269,7 +269,7 @@ case class Table[V: DynamoFormat](name: String) {
* >>> val choicesTable = Table[Choice]("choices")
* >>> LocalDynamoDB.withTable(client)("choices")('number -> N) {
* ... val ops = for {
* ... _ <- choicesTable.putAll(List(Choice(1, "cake"), Choice(2, "crumble"), Choice(3, "custard")))
* ... _ <- choicesTable.putAll(Set(Choice(1, "cake"), Choice(2, "crumble"), Choice(3, "custard")))
* ... _ <- choicesTable.given(Condition('description -> "cake") or 'description -> "death").put(Choice(1, "victoria sponge"))
* ... _ <- choicesTable.given(Condition('description -> "cake") or 'description -> "death").put(Choice(2, "victoria sponge"))
* ... choices <- choicesTable.scan()
Expand All @@ -286,7 +286,7 @@ case class Table[V: DynamoFormat](name: String) {
* >>> val gremlinsTable = Table[Gremlin]("gremlins")
* >>> LocalDynamoDB.withTable(client)("gremlins")('number -> N) {
* ... val ops = for {
* ... _ <- gremlinsTable.putAll(List(Gremlin(1, false, true), Gremlin(2, true, false)))
* ... _ <- gremlinsTable.putAll(Set(Gremlin(1, false, true), Gremlin(2, true, false)))
* ... _ <- gremlinsTable.given('wet -> true).delete('number -> 1)
* ... _ <- gremlinsTable.given('wet -> true).delete('number -> 2)
* ... remainingGremlins <- gremlinsTable.scan()
Expand All @@ -301,7 +301,7 @@ case class Table[V: DynamoFormat](name: String) {
* {{{
* >>> LocalDynamoDB.withTable(client)("gremlins")('number -> N) {
* ... val ops = for {
* ... _ <- gremlinsTable.putAll(List(Gremlin(1, false, true), Gremlin(2, true, true)))
* ... _ <- gremlinsTable.putAll(Set(Gremlin(1, false, true), Gremlin(2, true, true)))
* ... _ <- gremlinsTable.given('wet -> true).update('number -> 1, set('friendly -> false))
* ... _ <- gremlinsTable.given('wet -> true).update('number -> 2, set('friendly -> false))
* ... remainingGremlins <- gremlinsTable.scan()
Expand Down Expand Up @@ -329,7 +329,7 @@ private[scanamo] case class Index[V: DynamoFormat](tableName: String, indexName:
* ... 'mode -> S, 'line -> S)('mode -> S, 'colour -> S
* ... ) {
* ... val operations = for {
* ... _ <- transport.putAll(List(
* ... _ <- transport.putAll(Set(
* ... Transport("Underground", "Circle", "Yellow"),
* ... Transport("Underground", "Metropolitan", "Magenta"),
* ... Transport("Underground", "Central", "Red"),
Expand Down
Loading

0 comments on commit a4ececc

Please sign in to comment.