| Index: go/src/infra/gae/epservice/example/service_cas.go
|
| diff --git a/go/src/infra/gae/epservice/example/service_cas.go b/go/src/infra/gae/epservice/example/service_cas.go
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f01804ec488218dcbfcd47732a3885d8319f929f
|
| --- /dev/null
|
| +++ b/go/src/infra/gae/epservice/example/service_cas.go
|
| @@ -0,0 +1,52 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package example
|
| +
|
| +import (
|
| + "golang.org/x/net/context"
|
| + "infra/gae/libs/wrapper"
|
| + "infra/gae/libs/wrapper/gae"
|
| +
|
| + "github.com/GoogleCloudPlatform/go-endpoints/endpoints"
|
| +)
|
| +
|
| +// CASReq is the input for the CAS RPC
|
| +type CASReq struct {
|
| + Name string `endpoints:"required"`
|
| +
|
| + OldVal int64 `json:",string"`
|
| + NewVal int64 `json:",string"`
|
| +}
|
| +
|
| +// CAS does an atomic compare-and-swap on a counter.
|
| +func (Example) CAS(c endpoints.Context, r *CASReq) (err error) {
|
| + success := false
|
| + ds := wrapper.GetDS(gae.Use(context.Background(), c))
|
| + err = ds.RunInTransaction(func(context.Context) error {
|
| + ctr := &Counter{ID: r.Name}
|
| + if err := ds.Get(ctr); err != nil {
|
| + return err
|
| + }
|
| + if ctr.Val == r.OldVal {
|
| + success = true
|
| + ctr.Val = r.NewVal
|
| + _, err := ds.Put(ctr)
|
| + return err
|
| + }
|
| + success = false
|
| + return nil
|
| + }, nil)
|
| + if err == nil && !success {
|
| + err = endpoints.ConflictError
|
| + }
|
| + return
|
| +}
|
| +
|
| +func init() {
|
| + mi["CAS"] = &endpoints.MethodInfo{
|
| + Path: "counter/{Name}/cas",
|
| + Desc: "Compare and swap a counter value",
|
| + }
|
| +}
|
|
|