Skip to content

Commit

Permalink
Update KV get/put and prepared batch examples.
Browse files Browse the repository at this point in the history
The basic key/value example has been updated to reflect the
current client and proto APIs.  The prepared batch example
has also been updated to query the correct number of rows.

Both examples were tested against a local cluster.
  • Loading branch information
jamesgraves committed Nov 19, 2014
1 parent 0e33783 commit ff0c6ed
Showing 1 changed file with 49 additions and 36 deletions.
85 changes: 49 additions & 36 deletions client/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,23 @@ The simplest way to use the client is through the Call method. Call
synchronously invokes the method and returns the reply and an
error. The example below shows a get and a put.
kv := client.NewKV("localhost:8080", tlsConfig)
getResp := &proto.GetResponse{}
if err := kv.Call(proto.Get, proto.GetArgs(proto.Key("a")), getResp); err != nil {
log.Fatal(err)
}
if _, err := kv.Call(proto.Put, proto.PutArgs(proto.Key("b"), getResp.Value.Bytes)) err != nil {
log.Fatal(err)
}
host := "localhost:8080"
sender := client.NewHTTPSender(host, &http.Transport{
TLSClientConfig: rpc.LoadInsecureTLSConfig().Config(),
})
kv := client.NewKV(sender, nil)
kv.User = storage.UserRoot
getResp := &proto.GetResponse{}
if err := kv.Call(proto.Get, proto.GetArgs(proto.Key("a")), getResp); err != nil {
log.Fatal(err)
}
value := getResp.Value.Bytes

This comment has been minimized.

Copy link
@jamesgraves

jamesgraves Nov 19, 2014

Author Contributor

We aren't doing any checking here if the key is not found. Not sure if that should be added to this example.

putResp := &proto.PutResponse{}
if err := kv.Call(proto.Put, proto.PutArgs(proto.Key("b"), value), putResp); err != nil {
log.Fatal(err)
}
The API is synchronous, but accommodates efficient parallel updates
and queries using the Prepare method. An arbitrary number of Prepare
Expand All @@ -50,33 +58,38 @@ transaction must be used to guarantee atomicity. A simple example of
using the API which does two scans in parallel and then sends a
sequence of puts in parallel:
kv := client.NewKV("localhost:8080", tlsConfig)
acResp, xzResp := &proto.ScanResponse{}, &proto.ScanResponse{}
kv.Prepare(proto.Scan, proto.ScanArgs(proto.Key("a"), proto.Key("c")), acResp)
kv.Prepare(proto.Scan, proto.ScanArgs(proto.Key("x"), proto.Key("z")), xzResp)
// Flush sends both scans in parallel and returns first error or nil.
if err := kv.Flush(); err != nil {
log.Fatal(err)
}
// Append maximum value from "a"-"c" to all values from "x"-"z".
max := []byte(nil)
for _, keyVal := range acResp.Rows {
if bytes.Compare(max, keyVal.Value.Bytes) < 0 {
max = keyVal.Value.Bytes
}
}
for keyVal := range xzResp.Rows {
putReq := proto.PutArgs(keyVal.Key, bytes.Join([][]byte{keyVal.Value.Bytes, max}, []byte(nil)))
kv.Prepare(proto.Put, putReq, &proto.PutReponse{})
}
// Flush all puts for parallel execution.
if _, err := kv.Flush(); err != nil {
log.Fatal(err)
}
host := "localhost:8080"
sender := client.NewHTTPSender(host, &http.Transport{
TLSClientConfig: rpc.LoadInsecureTLSConfig().Config(),
})
kv := client.NewKV(sender, nil)
kv.User = storage.UserRoot
acResp, xzResp := &proto.ScanResponse{}, &proto.ScanResponse{}
kv.Prepare(proto.Scan, proto.ScanArgs(proto.Key("a"), proto.Key("c").Next(), 3), acResp)
kv.Prepare(proto.Scan, proto.ScanArgs(proto.Key("x"), proto.Key("z").Next(), 3), xzResp)
// Flush sends both scans in parallel and returns first error or nil.
if err := kv.Flush(); err != nil {
log.Fatal(err)
}
// Append maximum value from "a"-"c" to all values from "x"-"z".
max := []byte(nil)
for _, keyVal := range acResp.Rows {
if bytes.Compare(max, keyVal.Value.Bytes) < 0 {
max = keyVal.Value.Bytes
}
}
for _, keyVal := range xzResp.Rows {
putReq := proto.PutArgs(keyVal.Key, bytes.Join([][]byte{keyVal.Value.Bytes, max}, []byte(nil)))
kv.Prepare(proto.Put, putReq, &proto.PutResponse{})
}
// Flush all puts for parallel execution.
if err := kv.Flush(); err != nil {
log.Fatal(err)
}
Transactions are supported through the RunTransaction() method, which
takes a retryable function, itself composed of the same simple mix of
Expand Down

5 comments on commit ff0c6ed

@spencerkimball
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is actual functional code now, let's move it into client/client_test.go using the "Example" test pattern: http://golang.org/pkg/testing/#hdr-Examples

Let's change the actual examples in the document to be very concise, mostly non-functional bits, as you'd find in the description for the RPC package: http://golang.org/pkg/net/rpc/

@jamesgraves
Copy link
Contributor Author

@jamesgraves jamesgraves commented on ff0c6ed Nov 19, 2014 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spencerkimball
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe don't go too crazy with the different examples. Just two would suffice. Do an ExampleCall and an ExamplePrepareFlush to contain the two examples you currently have in doc.go. Just create the test server from scratch in each Example so you don't worry about what order they're run in (although I think there is a guarantee that they're run in order in which they appear in the code (although output compares separately for each example).

@jamesgraves
Copy link
Contributor Author

@jamesgraves jamesgraves commented on ff0c6ed Nov 19, 2014 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spencerkimball
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, probably do want one for transactions. Forgot about that...

Please sign in to comment.