Skip to content

Commit e928433

Browse files
committed
changelog, more tests, less logging
1 parent 3e27bff commit e928433

File tree

3 files changed

+29
-13
lines changed

3 files changed

+29
-13
lines changed

Changelog.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Changelog
2+
3+
## Breaking Changes
4+
5+
- The `GetMultipleKeys` call now takes a `startAfterKey` instead of a `key` for pagination. The returned list will only start *after* this key. [#38](https://github.com/scalableminds/fossildb/pull/38)
6+
7+
## Fixes
8+
9+
- Fixed a bug where the pagination for `GetMultipleKeys` could lead to an endless loop if some keys are prefixes of others. [#38](https://github.com/scalableminds/fossildb/pull/38)

src/main/scala/com/scalableminds/fossildb/db/VersionedKeyValueStore.scala

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ class VersionedKeyValueStore(underlying: RocksDBStore) {
128128
}
129129

130130
def getMultipleKeys(startAfterKey: Option[String], prefix: Option[String] = None, version: Option[Long] = None, limit: Option[Int]): (Seq[String], Seq[Array[Byte]], Seq[Long]) = {
131-
println(s"\ngetMultipleKeys! startAfterKey: $startAfterKey, prefix: $prefix, version: $version, limit: $limit")
132131
startAfterKey.foreach(requireValidKey)
133132
prefix.foreach{ p => requireValidKey(p)}
134133
val iterator: VersionFilterIterator = scanKeys(startAfterKey, prefix, version)
@@ -140,34 +139,24 @@ class VersionedKeyValueStore(underlying: RocksDBStore) {
140139
*/
141140
val firstItemOpt: Option[VersionedKeyValuePair[Array[Byte]]] = if (iterator.hasNext) {
142141
val firstItem = iterator.next()
143-
println(s"firstItem: ${firstItem.key}")
144142
if (startAfterKey.contains(firstItem.key)) {
145143
None
146144
} else {
147145
Some(firstItem)
148146
}
149147
} else None
150148

151-
if (firstItemOpt.isDefined) {
152-
println(s"including first item $firstItemOpt")
153-
} else {
154-
println(s"dropping first item (it equals startAfterKey)")
155-
}
156-
157149
val limitPadded = limit.map(_ + 1).getOrElse(Int.MaxValue)
158150
val asVector = iterator.take(limitPadded).toVector
159-
println(s"asVector: ${asVector.map{_.key}}")
160151
val asSequenceAdvancedIfNeeded = firstItemOpt.map(_ +: asVector).getOrElse(asVector).take(limit.getOrElse(Int.MaxValue))
161152
val keys = asSequenceAdvancedIfNeeded.map(_.key)
162-
println(s"Returning keys ${keys.toList}")
163153
val values = asSequenceAdvancedIfNeeded.map(_.value)
164154
val versions = asSequenceAdvancedIfNeeded.map(_.version)
165155
(keys, values, versions)
166156
}
167157

168158
private def scanKeys(startAfterKey: Option[String], prefix: Option[String] = None, version: Option[Long] = None): VersionFilterIterator = {
169159
val fullKey = startAfterKey.map(key => s"$key${VersionedKey.versionSeparator}").orElse(prefix).getOrElse("")
170-
println(s"Scanning to $fullKey")
171160
new VersionFilterIterator(underlying.scan(fullKey, prefix), version)
172161
}
173162

src/test/scala/com/scalableminds/fossildb/FossilDBSuite.scala

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach with TestHelpers wi
232232
assert(reply.values.contains(testData2))
233233
}
234234

235-
it should "return keys of matching version, matching prefix (sorted alphabetically)" in {
235+
it should "return keys of matching version, matching prefix" in {
236236
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
237237
client.put(PutRequest(collectionA, aNotherKey, Some(0), testData1))
238238
client.put(PutRequest(collectionA, aThirdKey, Some(0), testData1))
@@ -242,8 +242,26 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach with TestHelpers wi
242242
client.put(PutRequest(collectionA, aKey, Some(2), testData3))
243243
client.put(PutRequest(collectionA, aNotherKey, Some(2), testData3))
244244
client.put(PutRequest(collectionA, aThirdKey, Some(2), testData3))
245-
val reply = client.getMultipleKeys(GetMultipleKeysRequest(collectionA, None, Some("aK"), Some(1)))
245+
val reply = client.getMultipleKeys(GetMultipleKeysRequest(collectionA, None, Some("aN"), Some(1)))
246246
assert(reply.keys.length == 1)
247+
assert(reply.keys.contains(aNotherKey))
248+
assert(reply.values.contains(testData2))
249+
assert(reply.actualVersions.contains(1))
250+
}
251+
252+
it should "return keys of matching version, matching prefix even if it is exact match" in {
253+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
254+
client.put(PutRequest(collectionA, aNotherKey, Some(0), testData1))
255+
client.put(PutRequest(collectionA, aThirdKey, Some(0), testData1))
256+
client.put(PutRequest(collectionA, aKey, Some(1), testData2))
257+
client.put(PutRequest(collectionA, aNotherKey, Some(1), testData2))
258+
client.put(PutRequest(collectionA, aThirdKey, Some(1), testData2))
259+
client.put(PutRequest(collectionA, aKey, Some(2), testData3))
260+
client.put(PutRequest(collectionA, aNotherKey, Some(2), testData3))
261+
client.put(PutRequest(collectionA, aThirdKey, Some(2), testData3))
262+
val reply = client.getMultipleKeys(GetMultipleKeysRequest(collectionA, None, Some(aNotherKey), Some(1)))
263+
assert(reply.keys.length == 1)
264+
assert(reply.keys.contains(aNotherKey))
247265
assert(reply.values.contains(testData2))
248266
assert(reply.actualVersions.contains(1))
249267
}

0 commit comments

Comments
 (0)