| Index: filter/readonly/rds.go
|
| diff --git a/filter/readonly/rds.go b/filter/readonly/rds.go
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d4521a19af79ab20cd3383885f461300d6758977
|
| --- /dev/null
|
| +++ b/filter/readonly/rds.go
|
| @@ -0,0 +1,63 @@
|
| +// Copyright 2017 The LUCI Authors.
|
| +//
|
| +// Licensed under the Apache License, Version 2.0 (the "License");
|
| +// you may not use this file except in compliance with the License.
|
| +// You may obtain a copy of the License at
|
| +//
|
| +// http://www.apache.org/licenses/LICENSE-2.0
|
| +//
|
| +// Unless required by applicable law or agreed to in writing, software
|
| +// distributed under the License is distributed on an "AS IS" BASIS,
|
| +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| +// See the License for the specific language governing permissions and
|
| +// limitations under the License.
|
| +
|
| +// Package readonly implements a filter that enforces read-only accesses to
|
| +// datastore.
|
| +//
|
| +// This is useful in hybrid environments where one cluster wants to read from
|
| +// a cache-backed datastore, but cannot modify the cache, so reads are safe and
|
| +// direct, but writes would create a state where the cached values are invalid.
|
| +// This happens when mixing AppEngine datastore/memcache with Cloud Datastore
|
| +// readers.
|
| +package readonly
|
| +
|
| +import (
|
| + "golang.org/x/net/context"
|
| +
|
| + ds "github.com/luci/gae/service/datastore"
|
| +
|
| + "github.com/luci/luci-go/common/errors"
|
| +)
|
| +
|
| +// ErrReadOnly is an error returned in response to mutating datastore
|
| +// operations.
|
| +var ErrReadOnly = errors.New("readonly: datastore is read-only")
|
| +
|
| +// readOnlyDatastore is a datastore.RawInterface implementation that returns
|
| +// ErrReadOnly on mutating operations.
|
| +type readOnlyDatastore struct {
|
| + ds.RawInterface
|
| +}
|
| +
|
| +func (r *readOnlyDatastore) AllocateIDs(keys []*ds.Key, cb ds.NewKeyCB) error {
|
| + return ErrReadOnly
|
| +}
|
| +
|
| +func (r *readOnlyDatastore) DeleteMulti(keys []*ds.Key, cb ds.DeleteMultiCB) error {
|
| + return ErrReadOnly
|
| +}
|
| +
|
| +func (r *readOnlyDatastore) PutMulti(keys []*ds.Key, vals []ds.PropertyMap, cb ds.NewKeyCB) error {
|
| + return ErrReadOnly
|
| +}
|
| +
|
| +// FilterRDS installs a read-only datastore filter in the context.
|
| +//
|
| +// This enforces that all datastore operations which could mutate the datastore
|
| +// will return ErrReadOnly.
|
| +func FilterRDS(c context.Context) context.Context {
|
| + return ds.AddRawFilters(c, func(ic context.Context, inner ds.RawInterface) ds.RawInterface {
|
| + return &readOnlyDatastore{inner}
|
| + })
|
| +}
|
|
|