Test atomic PUTs, and make them work.
Improve apiserver/logger.go's interface (it's pretty cool now). Improve apiserver's error reporting to clients. Improve client's handling of errors from apiserver. Make failed PUTs return 409 (conflict)-- http status codes are amazingly well defined for what we're doing!
This commit is contained in:
@@ -118,14 +118,8 @@ func (h *EtcdHelper) ExtractList(key string, slicePtr interface{}) error {
|
||||
// a zero object of the requested type, or an error, depending on ignoreNotFound. Treats
|
||||
// empty responses and nil response nodes exactly like a not found error.
|
||||
func (h *EtcdHelper) ExtractObj(key string, objPtr interface{}, ignoreNotFound bool) error {
|
||||
_, index, err := h.bodyAndExtractObj(key, objPtr, ignoreNotFound)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if jsonBase, err := api.FindJSONBase(objPtr); err == nil {
|
||||
jsonBase.ResourceVersion = index
|
||||
}
|
||||
return nil
|
||||
_, _, err := h.bodyAndExtractObj(key, objPtr, ignoreNotFound)
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *EtcdHelper) bodyAndExtractObj(key string, objPtr interface{}, ignoreNotFound bool) (body string, modifiedIndex uint64, err error) {
|
||||
@@ -145,20 +139,30 @@ func (h *EtcdHelper) bodyAndExtractObj(key string, objPtr interface{}, ignoreNot
|
||||
return "", 0, fmt.Errorf("key '%v' found no nodes field: %#v", key, response)
|
||||
}
|
||||
body = response.Node.Value
|
||||
return body, response.Node.ModifiedIndex, json.Unmarshal([]byte(body), objPtr)
|
||||
err = json.Unmarshal([]byte(body), objPtr)
|
||||
if jsonBase, err := api.FindJSONBase(objPtr); err == nil {
|
||||
jsonBase.ResourceVersion = response.Node.ModifiedIndex
|
||||
// Note that err shadows the err returned below, so we won't
|
||||
// return an error just because we failed to find a JSONBase.
|
||||
// This is intentional.
|
||||
}
|
||||
return body, response.Node.ModifiedIndex, err
|
||||
}
|
||||
|
||||
// SetObj marshals obj via json, and stores under key.
|
||||
// SetObj marshals obj via json, and stores under key. Will do an
|
||||
// atomic update if obj's ResourceVersion field is set.
|
||||
func (h *EtcdHelper) SetObj(key string, obj interface{}) error {
|
||||
data, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if jsonBase, err := api.FindJSONBase(obj); err == nil && jsonBase.ResourceVersion != 0 {
|
||||
if jsonBase, err := api.FindJSONBaseRO(obj); err == nil && jsonBase.ResourceVersion != 0 {
|
||||
_, err = h.Client.CompareAndSwap(key, string(data), 0, "", jsonBase.ResourceVersion)
|
||||
} else {
|
||||
_, err = h.Client.Set(key, string(data), 0)
|
||||
return err // err is shadowed!
|
||||
}
|
||||
|
||||
// TODO: when client supports atomic creation, integrate this with the above.
|
||||
_, err = h.Client.Set(key, string(data), 0)
|
||||
return err
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user