github.com/lingyao2333/mo-zero@v1.4.1/core/stores/mongoc/cachedmodel.go (about) 1 package mongoc 2 3 import ( 4 "log" 5 6 "github.com/globalsign/mgo" 7 "github.com/lingyao2333/mo-zero/core/stores/cache" 8 "github.com/lingyao2333/mo-zero/core/stores/mongo" 9 "github.com/lingyao2333/mo-zero/core/stores/redis" 10 ) 11 12 // A Model is a mongo model that built with cache capability. 13 type Model struct { 14 *mongo.Model 15 cache cache.Cache 16 generateCollection func(*mgo.Session) CachedCollection 17 } 18 19 // MustNewNodeModel returns a Model with a cache node, exists on errors. 20 func MustNewNodeModel(url, collection string, rds *redis.Redis, opts ...cache.Option) *Model { 21 model, err := NewNodeModel(url, collection, rds, opts...) 22 if err != nil { 23 log.Fatal(err) 24 } 25 26 return model 27 } 28 29 // MustNewModel returns a Model with a cache cluster, exists on errors. 30 func MustNewModel(url, collection string, c cache.CacheConf, opts ...cache.Option) *Model { 31 model, err := NewModel(url, collection, c, opts...) 32 if err != nil { 33 log.Fatal(err) 34 } 35 36 return model 37 } 38 39 // NewModel returns a Model with a cache cluster. 40 func NewModel(url, collection string, conf cache.CacheConf, opts ...cache.Option) (*Model, error) { 41 c := cache.New(conf, singleFlight, stats, mgo.ErrNotFound, opts...) 42 return NewModelWithCache(url, collection, c) 43 } 44 45 // NewModelWithCache returns a Model with a custom cache. 46 func NewModelWithCache(url, collection string, c cache.Cache) (*Model, error) { 47 return createModel(url, collection, c, func(collection mongo.Collection) CachedCollection { 48 return newCollection(collection, c) 49 }) 50 } 51 52 // NewNodeModel returns a Model with a cache node. 53 func NewNodeModel(url, collection string, rds *redis.Redis, opts ...cache.Option) (*Model, error) { 54 c := cache.NewNode(rds, singleFlight, stats, mgo.ErrNotFound, opts...) 55 return NewModelWithCache(url, collection, c) 56 } 57 58 // Count returns the count of given query. 59 func (mm *Model) Count(query interface{}) (int, error) { 60 return mm.executeInt(func(c CachedCollection) (int, error) { 61 return c.Count(query) 62 }) 63 } 64 65 // DelCache deletes the cache with given keys. 66 func (mm *Model) DelCache(keys ...string) error { 67 return mm.cache.Del(keys...) 68 } 69 70 // GetCache unmarshal the cache into v with given key. 71 func (mm *Model) GetCache(key string, v interface{}) error { 72 return mm.cache.Get(key, v) 73 } 74 75 // GetCollection returns a cache collection. 76 func (mm *Model) GetCollection(session *mgo.Session) CachedCollection { 77 return mm.generateCollection(session) 78 } 79 80 // FindAllNoCache finds all records without cache. 81 func (mm *Model) FindAllNoCache(v, query interface{}, opts ...QueryOption) error { 82 return mm.execute(func(c CachedCollection) error { 83 return c.FindAllNoCache(v, query, opts...) 84 }) 85 } 86 87 // FindOne unmarshals a record into v with given key and query. 88 func (mm *Model) FindOne(v interface{}, key string, query interface{}) error { 89 return mm.execute(func(c CachedCollection) error { 90 return c.FindOne(v, key, query) 91 }) 92 } 93 94 // FindOneNoCache unmarshals a record into v with query, without cache. 95 func (mm *Model) FindOneNoCache(v, query interface{}) error { 96 return mm.execute(func(c CachedCollection) error { 97 return c.FindOneNoCache(v, query) 98 }) 99 } 100 101 // FindOneId unmarshals a record into v with query. 102 func (mm *Model) FindOneId(v interface{}, key string, id interface{}) error { 103 return mm.execute(func(c CachedCollection) error { 104 return c.FindOneId(v, key, id) 105 }) 106 } 107 108 // FindOneIdNoCache unmarshals a record into v with query, without cache. 109 func (mm *Model) FindOneIdNoCache(v, id interface{}) error { 110 return mm.execute(func(c CachedCollection) error { 111 return c.FindOneIdNoCache(v, id) 112 }) 113 } 114 115 // Insert inserts docs. 116 func (mm *Model) Insert(docs ...interface{}) error { 117 return mm.execute(func(c CachedCollection) error { 118 return c.Insert(docs...) 119 }) 120 } 121 122 // Pipe returns a mongo pipe with given pipeline. 123 func (mm *Model) Pipe(pipeline interface{}) (mongo.Pipe, error) { 124 return mm.pipe(func(c CachedCollection) mongo.Pipe { 125 return c.Pipe(pipeline) 126 }) 127 } 128 129 // Remove removes a record with given selector, and remove it from cache with given keys. 130 func (mm *Model) Remove(selector interface{}, keys ...string) error { 131 return mm.execute(func(c CachedCollection) error { 132 return c.Remove(selector, keys...) 133 }) 134 } 135 136 // RemoveNoCache removes a record with given selector. 137 func (mm *Model) RemoveNoCache(selector interface{}) error { 138 return mm.execute(func(c CachedCollection) error { 139 return c.RemoveNoCache(selector) 140 }) 141 } 142 143 // RemoveAll removes all records with given selector, and removes cache with given keys. 144 func (mm *Model) RemoveAll(selector interface{}, keys ...string) (*mgo.ChangeInfo, error) { 145 return mm.change(func(c CachedCollection) (*mgo.ChangeInfo, error) { 146 return c.RemoveAll(selector, keys...) 147 }) 148 } 149 150 // RemoveAllNoCache removes all records with given selector, and returns a mgo.ChangeInfo. 151 func (mm *Model) RemoveAllNoCache(selector interface{}) (*mgo.ChangeInfo, error) { 152 return mm.change(func(c CachedCollection) (*mgo.ChangeInfo, error) { 153 return c.RemoveAllNoCache(selector) 154 }) 155 } 156 157 // RemoveId removes a record with given id, and removes cache with given keys. 158 func (mm *Model) RemoveId(id interface{}, keys ...string) error { 159 return mm.execute(func(c CachedCollection) error { 160 return c.RemoveId(id, keys...) 161 }) 162 } 163 164 // RemoveIdNoCache removes a record with given id. 165 func (mm *Model) RemoveIdNoCache(id interface{}) error { 166 return mm.execute(func(c CachedCollection) error { 167 return c.RemoveIdNoCache(id) 168 }) 169 } 170 171 // SetCache sets the cache with given key and value. 172 func (mm *Model) SetCache(key string, v interface{}) error { 173 return mm.cache.Set(key, v) 174 } 175 176 // Update updates the record with given selector, and delete cache with given keys. 177 func (mm *Model) Update(selector, update interface{}, keys ...string) error { 178 return mm.execute(func(c CachedCollection) error { 179 return c.Update(selector, update, keys...) 180 }) 181 } 182 183 // UpdateNoCache updates the record with given selector. 184 func (mm *Model) UpdateNoCache(selector, update interface{}) error { 185 return mm.execute(func(c CachedCollection) error { 186 return c.UpdateNoCache(selector, update) 187 }) 188 } 189 190 // UpdateId updates the record with given id, and delete cache with given keys. 191 func (mm *Model) UpdateId(id, update interface{}, keys ...string) error { 192 return mm.execute(func(c CachedCollection) error { 193 return c.UpdateId(id, update, keys...) 194 }) 195 } 196 197 // UpdateIdNoCache updates the record with given id. 198 func (mm *Model) UpdateIdNoCache(id, update interface{}) error { 199 return mm.execute(func(c CachedCollection) error { 200 return c.UpdateIdNoCache(id, update) 201 }) 202 } 203 204 // Upsert upserts a record with given selector, and delete cache with given keys. 205 func (mm *Model) Upsert(selector, update interface{}, keys ...string) (*mgo.ChangeInfo, error) { 206 return mm.change(func(c CachedCollection) (*mgo.ChangeInfo, error) { 207 return c.Upsert(selector, update, keys...) 208 }) 209 } 210 211 // UpsertNoCache upserts a record with given selector. 212 func (mm *Model) UpsertNoCache(selector, update interface{}) (*mgo.ChangeInfo, error) { 213 return mm.change(func(c CachedCollection) (*mgo.ChangeInfo, error) { 214 return c.UpsertNoCache(selector, update) 215 }) 216 } 217 218 func (mm *Model) change(fn func(c CachedCollection) (*mgo.ChangeInfo, error)) (*mgo.ChangeInfo, error) { 219 session, err := mm.TakeSession() 220 if err != nil { 221 return nil, err 222 } 223 defer mm.PutSession(session) 224 225 return fn(mm.GetCollection(session)) 226 } 227 228 func (mm *Model) execute(fn func(c CachedCollection) error) error { 229 session, err := mm.TakeSession() 230 if err != nil { 231 return err 232 } 233 defer mm.PutSession(session) 234 235 return fn(mm.GetCollection(session)) 236 } 237 238 func (mm *Model) executeInt(fn func(c CachedCollection) (int, error)) (int, error) { 239 session, err := mm.TakeSession() 240 if err != nil { 241 return 0, err 242 } 243 defer mm.PutSession(session) 244 245 return fn(mm.GetCollection(session)) 246 } 247 248 func (mm *Model) pipe(fn func(c CachedCollection) mongo.Pipe) (mongo.Pipe, error) { 249 session, err := mm.TakeSession() 250 if err != nil { 251 return nil, err 252 } 253 defer mm.PutSession(session) 254 255 return fn(mm.GetCollection(session)), nil 256 } 257 258 func createModel(url, collection string, c cache.Cache, 259 create func(mongo.Collection) CachedCollection) (*Model, error) { 260 model, err := mongo.NewModel(url, collection) 261 if err != nil { 262 return nil, err 263 } 264 265 return &Model{ 266 Model: model, 267 cache: c, 268 generateCollection: func(session *mgo.Session) CachedCollection { 269 collection := model.GetCollection(session) 270 return create(collection) 271 }, 272 }, nil 273 }