Skip to content

Commit 144a6c3

Browse files
committed
make Put version optional. increase if none supplied
1 parent b4bb854 commit 144a6c3

File tree

3 files changed

+72
-58
lines changed

3 files changed

+72
-58
lines changed

src/main/protobuf/fossildbapi.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ message GetReply {
2525
message PutRequest {
2626
required string collection = 1;
2727
required string key = 2;
28-
required uint64 version = 3;
28+
optional uint64 version = 3;
2929
required bytes value = 4;
3030
}
3131

src/main/scala/com/scalableminds/fossildb/FossilDBGrpcImpl.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ class FossilDBGrpcImpl(storeManager: StoreManager) extends FossilDBGrpc.FossilDB
3333

3434
override def put(req: PutRequest) = withExceptionHandler(req) {
3535
val store = storeManager.getStore(req.collection)
36-
require(req.version >= 0, "Version numbers must be non-negative")
37-
store.put(req.key, req.version, req.value.toByteArray)
36+
val version = req.version.getOrElse(store.get(req.key, None).map(_.version + 1).getOrElse(0L))
37+
require(version >= 0, "Version numbers must be non-negative")
38+
store.put(req.key, version, req.value.toByteArray)
3839
PutReply(true)
3940
} {errorMsg => PutReply(false, errorMsg)}
4041

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

Lines changed: 68 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -66,34 +66,47 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach {
6666
}
6767

6868
"Put" should "overwrite old value" in {
69-
client.put(PutRequest(collectionA, aKey, 0, testData1))
70-
client.put(PutRequest(collectionA, aKey, 0, testData2))
69+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
70+
client.put(PutRequest(collectionA, aKey, Some(0), testData2))
7171
val reply = client.get(GetRequest(collectionA, aKey, Some(0)))
7272
assert(testData2 == reply.value)
7373
}
7474

7575
it should "fail on non-existent collection" in {
76-
val reply = client.put(PutRequest("nonExistentCollection", aKey, 0, testData1))
76+
val reply = client.put(PutRequest("nonExistentCollection", aKey, Some(0), testData1))
7777
assert(!reply.success)
7878
}
7979

80+
it should "increment version if none is supplied" in {
81+
client.put(PutRequest(collectionA, aKey, Some(4), testData1))
82+
client.put(PutRequest(collectionA, aKey, None, testData1))
83+
val reply = client.get(GetRequest(collectionA, aKey))
84+
assert(reply.actualVersion == 5)
85+
}
86+
87+
it should "start at version 0 if none is supplied" in {
88+
client.put(PutRequest(collectionA, aKey, None, testData1))
89+
val reply = client.get(GetRequest(collectionA, aKey))
90+
assert(reply.actualVersion == 0)
91+
}
92+
8093
"Get" should "return matching value after matching Put" in {
81-
client.put(PutRequest(collectionA, aKey, 0, testData1))
94+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
8295
val reply = client.get(GetRequest(collectionA, aKey, Some(0)))
8396
assert(testData1 == reply.value)
8497
}
8598

8699
it should "return matching value after multiple versioned Puts" in {
87-
client.put(PutRequest(collectionA, aKey, 0, testData1))
88-
client.put(PutRequest(collectionA, aKey, 5, testData1))
89-
client.put(PutRequest(collectionA, aKey, 2, testData2))
100+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
101+
client.put(PutRequest(collectionA, aKey, Some(5), testData1))
102+
client.put(PutRequest(collectionA, aKey, Some(2), testData2))
90103
val reply = client.get(GetRequest(collectionA, aKey, Some(2)))
91104
assert(testData2 == reply.value)
92105
}
93106

94107
it should "return value of closest older version" in {
95-
client.put(PutRequest(collectionA, aKey, 2, testData1))
96-
client.put(PutRequest(collectionA, aKey, 5, testData2))
108+
client.put(PutRequest(collectionA, aKey, Some(2), testData1))
109+
client.put(PutRequest(collectionA, aKey, Some(5), testData2))
97110

98111
val reply = client.get(GetRequest(collectionA, aKey, Some(7)))
99112
assert(testData2 == reply.value)
@@ -105,41 +118,41 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach {
105118
}
106119

107120
it should "fail after Put with other key" in {
108-
client.put(PutRequest(collectionA, anotherKey, 0, testData1))
121+
client.put(PutRequest(collectionA, anotherKey, Some(0), testData1))
109122
val reply = client.get(GetRequest(collectionA, aKey))
110123
assert(!reply.success)
111124
}
112125

113126
it should "fail after Put with only newer version" in {
114-
client.put(PutRequest(collectionA, aKey, 5, testData1))
127+
client.put(PutRequest(collectionA, aKey, Some(5), testData1))
115128
val reply = client.get(GetRequest(collectionA, aKey, Some(3)))
116129
assert(!reply.success)
117130
}
118131

119132
"Delete" should "delete a value at specific version" in {
120-
client.put(PutRequest(collectionA, aKey, 0, testData1))
121-
client.put(PutRequest(collectionA, aKey, 1, testData2))
133+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
134+
client.put(PutRequest(collectionA, aKey, Some(1), testData2))
122135
client.delete(DeleteRequest(collectionA, aKey, 1))
123136
val reply = client.get(GetRequest(collectionA, aKey, Some(1)))
124137
assert(testData1 == reply.value)
125138
}
126139

127140
"ListKeys" should "list all keys of a collection" in {
128-
client.put(PutRequest(collectionA, aKey, 0, testData1))
129-
client.put(PutRequest(collectionA, aKey, 1, testData2))
130-
client.put(PutRequest(collectionA, anotherKey, 4, testData2))
131-
client.put(PutRequest(collectionB, aThirdKey, 1, testData1))
141+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
142+
client.put(PutRequest(collectionA, aKey, Some(1), testData2))
143+
client.put(PutRequest(collectionA, anotherKey, Some(4), testData2))
144+
client.put(PutRequest(collectionB, aThirdKey, Some(1), testData1))
132145
val reply = client.listKeys(ListKeysRequest(collectionA))
133146
assert(reply.keys.contains(aKey))
134147
assert(reply.keys.contains(anotherKey))
135148
assert(reply.keys.length == 2)
136149
}
137150

138151
it should "support pagination with startAfterKey" in {
139-
client.put(PutRequest(collectionA, aKey, 0, testData1))
140-
client.put(PutRequest(collectionA, aKey, 1, testData2))
141-
client.put(PutRequest(collectionA, anotherKey, 4, testData2))
142-
client.put(PutRequest(collectionB, aThirdKey, 1, testData1))
152+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
153+
client.put(PutRequest(collectionA, aKey, Some(1), testData2))
154+
client.put(PutRequest(collectionA, anotherKey, Some(4), testData2))
155+
client.put(PutRequest(collectionB, aThirdKey, Some(1), testData1))
143156
val reply = client.listKeys(ListKeysRequest(collectionA, Some(1)))
144157
assert(reply.keys.length == 1)
145158
assert(reply.keys.contains(aKey))
@@ -149,10 +162,10 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach {
149162
}
150163

151164
"GetMultipleVersions" should "return all versions in decending order if called without limits" in {
152-
client.put(PutRequest(collectionA, aKey, 0, testData1))
153-
client.put(PutRequest(collectionA, aKey, 1, testData2))
154-
client.put(PutRequest(collectionA, aKey, 2, testData3))
155-
client.put(PutRequest(collectionA, anotherKey, 0, testData1))
165+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
166+
client.put(PutRequest(collectionA, aKey, Some(1), testData2))
167+
client.put(PutRequest(collectionA, aKey, Some(2), testData3))
168+
client.put(PutRequest(collectionA, anotherKey, Some(0), testData1))
156169
val reply = client.getMultipleVersions(GetMultipleVersionsRequest(collectionA, aKey))
157170
assert(reply.versions(0) == 2)
158171
assert(reply.versions(1) == 1)
@@ -165,12 +178,12 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach {
165178
}
166179

167180
it should "return versions specified by bounds (inclusive)" in {
168-
client.put(PutRequest(collectionA, aKey, 0, testData1))
169-
client.put(PutRequest(collectionA, aKey, 1, testData2))
170-
client.put(PutRequest(collectionA, aKey, 3, testData3))
171-
client.put(PutRequest(collectionA, aKey, 4, testData1))
172-
client.put(PutRequest(collectionA, aKey, 5, testData1))
173-
client.put(PutRequest(collectionA, anotherKey, 0, testData1))
181+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
182+
client.put(PutRequest(collectionA, aKey, Some(1), testData2))
183+
client.put(PutRequest(collectionA, aKey, Some(3), testData3))
184+
client.put(PutRequest(collectionA, aKey, Some(4), testData1))
185+
client.put(PutRequest(collectionA, aKey, Some(5), testData1))
186+
client.put(PutRequest(collectionA, anotherKey, Some(0), testData1))
174187

175188
val reply = client.getMultipleVersions(GetMultipleVersionsRequest(collectionA, aKey, Some(4), Some(2)))
176189
assert(reply.versions(0) == 4)
@@ -182,9 +195,9 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach {
182195
}
183196

184197
"GetMultipleKeys" should "return keys starting with initial one (no prefix)" in {
185-
client.put(PutRequest(collectionA, aKey, 0, testData1))
186-
client.put(PutRequest(collectionA, anotherKey, 0, testData2))
187-
client.put(PutRequest(collectionA, aThirdKey, 0, testData3))
198+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
199+
client.put(PutRequest(collectionA, anotherKey, Some(0), testData2))
200+
client.put(PutRequest(collectionA, aThirdKey, Some(0), testData3))
188201
val reply = client.getMultipleKeys(GetMultipleKeysRequest(collectionA, aThirdKey))
189202
assert(reply.keys.length == 2)
190203
assert(reply.keys.contains(anotherKey))
@@ -195,37 +208,37 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach {
195208
}
196209

197210
it should "return keys of matching version (sorted alphabetically)" in {
198-
client.put(PutRequest(collectionA, aKey, 0, testData1))
199-
client.put(PutRequest(collectionA, anotherKey, 0, testData1))
200-
client.put(PutRequest(collectionA, aThirdKey, 0, testData1))
201-
client.put(PutRequest(collectionA, aKey, 1, testData2))
202-
client.put(PutRequest(collectionA, anotherKey, 1, testData2))
203-
client.put(PutRequest(collectionA, aThirdKey, 1, testData2))
204-
client.put(PutRequest(collectionA, aKey, 2, testData3))
205-
client.put(PutRequest(collectionA, anotherKey, 2, testData3))
206-
client.put(PutRequest(collectionA, aThirdKey, 2, testData3))
211+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
212+
client.put(PutRequest(collectionA, anotherKey, Some(0), testData1))
213+
client.put(PutRequest(collectionA, aThirdKey, Some(0), testData1))
214+
client.put(PutRequest(collectionA, aKey, Some(1), testData2))
215+
client.put(PutRequest(collectionA, anotherKey, Some(1), testData2))
216+
client.put(PutRequest(collectionA, aThirdKey, Some(1), testData2))
217+
client.put(PutRequest(collectionA, aKey, Some(2), testData3))
218+
client.put(PutRequest(collectionA, anotherKey, Some(2), testData3))
219+
client.put(PutRequest(collectionA, aThirdKey, Some(2), testData3))
207220
val reply = client.getMultipleKeys(GetMultipleKeysRequest(collectionA, aKey, None, Some(1)))
208221
assert(reply.keys.length == 3)
209222
assert(reply.values.contains(testData2))
210223
}
211224

212225
it should "return keys of matching version, matching prefix (sorted alphabetically)" in {
213-
client.put(PutRequest(collectionA, aKey, 0, testData1))
214-
client.put(PutRequest(collectionA, anotherKey, 0, testData1))
215-
client.put(PutRequest(collectionA, aThirdKey, 0, testData1))
216-
client.put(PutRequest(collectionA, aKey, 1, testData2))
217-
client.put(PutRequest(collectionA, anotherKey, 1, testData2))
218-
client.put(PutRequest(collectionA, aThirdKey, 1, testData2))
219-
client.put(PutRequest(collectionA, aKey, 2, testData3))
220-
client.put(PutRequest(collectionA, anotherKey, 2, testData3))
221-
client.put(PutRequest(collectionA, aThirdKey, 2, testData3))
226+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
227+
client.put(PutRequest(collectionA, anotherKey, Some(0), testData1))
228+
client.put(PutRequest(collectionA, aThirdKey, Some(0), testData1))
229+
client.put(PutRequest(collectionA, aKey, Some(1), testData2))
230+
client.put(PutRequest(collectionA, anotherKey, Some(1), testData2))
231+
client.put(PutRequest(collectionA, aThirdKey, Some(1), testData2))
232+
client.put(PutRequest(collectionA, aKey, Some(2), testData3))
233+
client.put(PutRequest(collectionA, anotherKey, Some(2), testData3))
234+
client.put(PutRequest(collectionA, aThirdKey, Some(2), testData3))
222235
val reply = client.getMultipleKeys(GetMultipleKeysRequest(collectionA, aKey, Some("aK"), Some(1)))
223236
assert(reply.keys.length == 1)
224237
assert(reply.values.contains(testData2))
225238
}
226239

227240
"Backup" should "create non-empty backup directory" in {
228-
client.put(PutRequest(collectionA, aKey, 0, testData1))
241+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
229242
client.backup(BackupRequest())
230243
val dir = new File(backupDir.toString)
231244
assert(dir.exists)
@@ -239,7 +252,7 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach {
239252
}
240253

241254
it should "restore old state after backup" in {
242-
client.put(PutRequest(collectionA, aKey, 0, testData1))
255+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
243256
client.backup(BackupRequest())
244257
client.delete(DeleteRequest(collectionA, aKey, 0))
245258
client.restoreFromBackup(RestoreFromBackupRequest())
@@ -248,7 +261,7 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach {
248261
}
249262

250263
it should "restore even after deletion of data dir" in {
251-
client.put(PutRequest(collectionA, aKey, 0, testData1))
264+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
252265
client.backup(BackupRequest())
253266
deleteRecursively(new File(dataDir.toString))
254267
client.restoreFromBackup(RestoreFromBackupRequest())

0 commit comments

Comments
 (0)