OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The LUCI Authors. |
| 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at |
| 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. |
| 14 |
| 15 // Package readonly implements a filter that enforces read-only accesses to |
| 16 // datastore. |
| 17 // |
| 18 // This is useful in hybrid environments where one cluster wants to read from |
| 19 // a cache-backed datastore, but cannot modify the cache, so reads are safe and |
| 20 // direct, but writes would create a state where the cached values are invalid. |
| 21 // This happens when mixing AppEngine datastore/memcache with Cloud Datastore |
| 22 // readers. |
| 23 package readonly |
| 24 |
| 25 import ( |
| 26 "golang.org/x/net/context" |
| 27 |
| 28 ds "github.com/luci/gae/service/datastore" |
| 29 |
| 30 "github.com/luci/luci-go/common/errors" |
| 31 ) |
| 32 |
| 33 // ErrReadOnly is an error returned in response to mutating datastore |
| 34 // operations. |
| 35 var ErrReadOnly = errors.New("readonly: datastore is read-only") |
| 36 |
| 37 // readOnlyDatastore is a datastore.RawInterface implementation that returns |
| 38 // ErrReadOnly on mutating operations. |
| 39 type readOnlyDatastore struct { |
| 40 ds.RawInterface |
| 41 } |
| 42 |
| 43 func (r *readOnlyDatastore) AllocateIDs(keys []*ds.Key, cb ds.NewKeyCB) error { |
| 44 return ErrReadOnly |
| 45 } |
| 46 |
| 47 func (r *readOnlyDatastore) DeleteMulti(keys []*ds.Key, cb ds.DeleteMultiCB) err
or { |
| 48 return ErrReadOnly |
| 49 } |
| 50 |
| 51 func (r *readOnlyDatastore) PutMulti(keys []*ds.Key, vals []ds.PropertyMap, cb d
s.NewKeyCB) error { |
| 52 return ErrReadOnly |
| 53 } |
| 54 |
| 55 // FilterRDS installs a read-only datastore filter in the context. |
| 56 // |
| 57 // This enforces that all datastore operations which could mutate the datastore |
| 58 // will return ErrReadOnly. |
| 59 func FilterRDS(c context.Context) context.Context { |
| 60 return ds.AddRawFilters(c, func(ic context.Context, inner ds.RawInterfac
e) ds.RawInterface { |
| 61 return &readOnlyDatastore{inner} |
| 62 }) |
| 63 } |
OLD | NEW |