@@ -35,7 +35,7 @@ type KVService struct {
35
35
36
36
// commitSubs are the commit subscriptions currently active in this service.
37
37
// See the createCommitSubscription method for more details.
38
- commitSubs map [int ]chan raft. CommitEntry
38
+ commitSubs map [int ]chan Command
39
39
40
40
// ds is the underlying data store implementing the KV DB.
41
41
ds * DataStore
@@ -69,7 +69,7 @@ func New(id int, peerIds []int, storage raft.Storage, readyChan <-chan any) *KVS
69
69
rs : rs ,
70
70
commitChan : commitChan ,
71
71
ds : NewDataStore (),
72
- commitSubs : make (map [int ]chan raft. CommitEntry ),
72
+ commitSubs : make (map [int ]chan Command ),
73
73
httpResponsesEnabled : true ,
74
74
}
75
75
@@ -178,16 +178,15 @@ func (kvs *KVService) handlePut(w http.ResponseWriter, req *http.Request) {
178
178
// also select on the request context - if the request is canceled, this
179
179
// handler aborts without sending data back to the client.
180
180
select {
181
- case entry := <- sub :
181
+ case commitCmd := <- sub :
182
182
// If this is our command, all is good! If it's some other server's command,
183
183
// this means we lost leadership at some point and should return an error
184
184
// to the client.
185
- entryCmd := entry .Command .(Command )
186
- if entryCmd .Id == kvs .id {
185
+ if commitCmd .Id == kvs .id {
187
186
kvs .sendHTTPResponse (w , api.PutResponse {
188
187
RespStatus : api .StatusOK ,
189
- KeyFound : entryCmd .ResultFound ,
190
- PrevValue : entryCmd .ResultValue ,
188
+ KeyFound : commitCmd .ResultFound ,
189
+ PrevValue : commitCmd .ResultValue ,
191
190
})
192
191
} else {
193
192
kvs .sendHTTPResponse (w , api.PutResponse {RespStatus : api .StatusFailedCommit })
@@ -197,9 +196,9 @@ func (kvs *KVService) handlePut(w http.ResponseWriter, req *http.Request) {
197
196
}
198
197
}
199
198
199
+ // The details of these handlers are very similar to handlePut: refer to that
200
+ // function for detailed comments.
200
201
func (kvs * KVService ) handleGet (w http.ResponseWriter , req * http.Request ) {
201
- // The details of this handler are very similar to handleGet: refer to that
202
- // function for detailed comments.
203
202
gr := & api.GetRequest {}
204
203
if err := readRequestJSON (req , gr ); err != nil {
205
204
http .Error (w , err .Error (), http .StatusBadRequest )
@@ -213,31 +212,20 @@ func (kvs *KVService) handleGet(w http.ResponseWriter, req *http.Request) {
213
212
Id : kvs .id ,
214
213
}
215
214
logIndex := kvs .rs .Submit (cmd )
216
- // If we're not the Raft leader, send an appropriate status
217
215
if logIndex < 0 {
218
216
kvs .sendHTTPResponse (w , api.GetResponse {RespStatus : api .StatusNotLeader })
219
217
return
220
218
}
221
219
222
- // Subsribe for a commit update for our log index. Then wait for it to
223
- // be delivered.
224
220
sub := kvs .createCommitSubscription (logIndex )
225
221
226
- // Wait on the sub channel: the updater will deliver a value when the Raft
227
- // log has a commit at logIndex. To ensure clean shutdown of the service,
228
- // also select on the request context - if the request is canceled, this
229
- // handler aborts without sending data back to the client.
230
222
select {
231
- case entry := <- sub :
232
- // If this is our command, all is good! If it's some other server's command,
233
- // this means we lost leadership at some point and should return an error
234
- // to the client.
235
- entryCmd := entry .Command .(Command )
236
- if entryCmd .Id == kvs .id {
223
+ case commitCmd := <- sub :
224
+ if commitCmd .Id == kvs .id {
237
225
kvs .sendHTTPResponse (w , api.GetResponse {
238
226
RespStatus : api .StatusOK ,
239
- KeyFound : entryCmd .ResultFound ,
240
- Value : entryCmd .ResultValue ,
227
+ KeyFound : commitCmd .ResultFound ,
228
+ Value : commitCmd .ResultValue ,
241
229
})
242
230
} else {
243
231
kvs .sendHTTPResponse (w , api.GetResponse {RespStatus : api .StatusFailedCommit })
@@ -271,13 +259,12 @@ func (kvs *KVService) handleCAS(w http.ResponseWriter, req *http.Request) {
271
259
sub := kvs .createCommitSubscription (logIndex )
272
260
273
261
select {
274
- case entry := <- sub :
275
- entryCmd := entry .Command .(Command )
276
- if entryCmd .Id == kvs .id {
262
+ case commitCmd := <- sub :
263
+ if commitCmd .Id == kvs .id {
277
264
kvs .sendHTTPResponse (w , api.CASResponse {
278
265
RespStatus : api .StatusOK ,
279
- KeyFound : entryCmd .ResultFound ,
280
- PrevValue : entryCmd .ResultValue ,
266
+ KeyFound : commitCmd .ResultFound ,
267
+ PrevValue : commitCmd .ResultValue ,
281
268
})
282
269
} else {
283
270
kvs .sendHTTPResponse (w , api.CASResponse {RespStatus : api .StatusFailedCommit })
@@ -307,18 +294,10 @@ func (kvs *KVService) runUpdater() {
307
294
panic (fmt .Errorf ("unexpected command %v" , cmd ))
308
295
}
309
296
310
- // We're modifying the command to include results from the datastore,
311
- // so clone an entry with the update command for the subscribers.
312
- newEntry := raft.CommitEntry {
313
- Command : cmd ,
314
- Index : entry .Index ,
315
- Term : entry .Term ,
316
- }
317
-
318
297
// Forward this entry to the subscriber interested in its index, and
319
298
// close the subscription - it's single-use.
320
299
if sub := kvs .popCommitSubscription (entry .Index ); sub != nil {
321
- sub <- newEntry
300
+ sub <- cmd
322
301
close (sub )
323
302
}
324
303
}
@@ -331,20 +310,20 @@ func (kvs *KVService) runUpdater() {
331
310
// an entry is committed at this index in the Raft log". The entry is delivered
332
311
// on the returend (buffered) channel by the updater goroutine, after which
333
312
// the channel is closed and the subscription is automatically canceled.
334
- func (kvs * KVService ) createCommitSubscription (logIndex int ) chan raft. CommitEntry {
313
+ func (kvs * KVService ) createCommitSubscription (logIndex int ) chan Command {
335
314
kvs .Lock ()
336
315
defer kvs .Unlock ()
337
316
338
317
if _ , exists := kvs .commitSubs [logIndex ]; exists {
339
318
panic (fmt .Sprintf ("duplicate commit subscription for logIndex=%d" , logIndex ))
340
319
}
341
320
342
- ch := make (chan raft. CommitEntry , 1 )
321
+ ch := make (chan Command , 1 )
343
322
kvs .commitSubs [logIndex ] = ch
344
323
return ch
345
324
}
346
325
347
- func (kvs * KVService ) popCommitSubscription (logIndex int ) chan raft. CommitEntry {
326
+ func (kvs * KVService ) popCommitSubscription (logIndex int ) chan Command {
348
327
kvs .Lock ()
349
328
defer kvs .Unlock ()
350
329
0 commit comments