github.com/lingyao2333/mo-zero@v1.4.1/core/stores/monc/cachedmodel.go (about) 1 package monc 2 3 import ( 4 "context" 5 "log" 6 7 "github.com/lingyao2333/mo-zero/core/stores/cache" 8 "github.com/lingyao2333/mo-zero/core/stores/mon" 9 "github.com/lingyao2333/mo-zero/core/stores/redis" 10 "github.com/lingyao2333/mo-zero/core/syncx" 11 "go.mongodb.org/mongo-driver/mongo" 12 mopt "go.mongodb.org/mongo-driver/mongo/options" 13 ) 14 15 var ( 16 // ErrNotFound is an alias of mongo.ErrNoDocuments. 17 ErrNotFound = mongo.ErrNoDocuments 18 19 // can't use one SingleFlight per conn, because multiple conns may share the same cache key. 20 singleFlight = syncx.NewSingleFlight() 21 stats = cache.NewStat("monc") 22 ) 23 24 // A Model is a mongo model that built with cache capability. 25 type Model struct { 26 *mon.Model 27 cache cache.Cache 28 } 29 30 // MustNewModel returns a Model with a cache cluster, exists on errors. 31 func MustNewModel(uri, db, collection string, c cache.CacheConf, opts ...cache.Option) *Model { 32 model, err := NewModel(uri, db, collection, c, opts...) 33 if err != nil { 34 log.Fatal(err) 35 } 36 37 return model 38 } 39 40 // MustNewNodeModel returns a Model with a cache node, exists on errors. 41 func MustNewNodeModel(uri, db, collection string, rds *redis.Redis, opts ...cache.Option) *Model { 42 model, err := NewNodeModel(uri, db, collection, rds, opts...) 43 if err != nil { 44 log.Fatal(err) 45 } 46 47 return model 48 } 49 50 // NewModel returns a Model with a cache cluster. 51 func NewModel(uri, db, collection string, conf cache.CacheConf, opts ...cache.Option) (*Model, error) { 52 c := cache.New(conf, singleFlight, stats, mongo.ErrNoDocuments, opts...) 53 return NewModelWithCache(uri, db, collection, c) 54 } 55 56 // NewModelWithCache returns a Model with a custom cache. 57 func NewModelWithCache(uri, db, collection string, c cache.Cache) (*Model, error) { 58 return newModel(uri, db, collection, c) 59 } 60 61 // NewNodeModel returns a Model with a cache node. 62 func NewNodeModel(uri, db, collection string, rds *redis.Redis, opts ...cache.Option) (*Model, error) { 63 c := cache.NewNode(rds, singleFlight, stats, mongo.ErrNoDocuments, opts...) 64 return NewModelWithCache(uri, db, collection, c) 65 } 66 67 // newModel returns a Model with the given cache. 68 func newModel(uri, db, collection string, c cache.Cache) (*Model, error) { 69 model, err := mon.NewModel(uri, db, collection) 70 if err != nil { 71 return nil, err 72 } 73 74 return &Model{ 75 Model: model, 76 cache: c, 77 }, nil 78 } 79 80 // DelCache deletes the cache with given keys. 81 func (mm *Model) DelCache(ctx context.Context, keys ...string) error { 82 return mm.cache.DelCtx(ctx, keys...) 83 } 84 85 // DeleteOne deletes the document with given filter, and remove it from cache. 86 func (mm *Model) DeleteOne(ctx context.Context, key string, filter interface{}, 87 opts ...*mopt.DeleteOptions) (int64, error) { 88 val, err := mm.Model.DeleteOne(ctx, filter, opts...) 89 if err != nil { 90 return 0, err 91 } 92 93 if err := mm.DelCache(ctx, key); err != nil { 94 return 0, err 95 } 96 97 return val, nil 98 } 99 100 // DeleteOneNoCache deletes the document with given filter. 101 func (mm *Model) DeleteOneNoCache(ctx context.Context, filter interface{}, 102 opts ...*mopt.DeleteOptions) (int64, error) { 103 return mm.Model.DeleteOne(ctx, filter, opts...) 104 } 105 106 // FindOne unmarshals a record into v with given key and query. 107 func (mm *Model) FindOne(ctx context.Context, key string, v, filter interface{}, 108 opts ...*mopt.FindOneOptions) error { 109 return mm.cache.TakeCtx(ctx, v, key, func(v interface{}) error { 110 return mm.Model.FindOne(ctx, v, filter, opts...) 111 }) 112 } 113 114 // FindOneNoCache unmarshals a record into v with query, without cache. 115 func (mm *Model) FindOneNoCache(ctx context.Context, v, filter interface{}, 116 opts ...*mopt.FindOneOptions) error { 117 return mm.Model.FindOne(ctx, v, filter, opts...) 118 } 119 120 // FindOneAndDelete deletes the document with given filter, and unmarshals it into v. 121 func (mm *Model) FindOneAndDelete(ctx context.Context, key string, v, filter interface{}, 122 opts ...*mopt.FindOneAndDeleteOptions) error { 123 if err := mm.Model.FindOneAndDelete(ctx, v, filter, opts...); err != nil { 124 return err 125 } 126 127 return mm.DelCache(ctx, key) 128 } 129 130 // FindOneAndDeleteNoCache deletes the document with given filter, and unmarshals it into v. 131 func (mm *Model) FindOneAndDeleteNoCache(ctx context.Context, v, filter interface{}, 132 opts ...*mopt.FindOneAndDeleteOptions) error { 133 return mm.Model.FindOneAndDelete(ctx, v, filter, opts...) 134 } 135 136 // FindOneAndReplace replaces the document with given filter with replacement, and unmarshals it into v. 137 func (mm *Model) FindOneAndReplace(ctx context.Context, key string, v, filter interface{}, 138 replacement interface{}, opts ...*mopt.FindOneAndReplaceOptions) error { 139 if err := mm.Model.FindOneAndReplace(ctx, v, filter, replacement, opts...); err != nil { 140 return err 141 } 142 143 return mm.DelCache(ctx, key) 144 } 145 146 // FindOneAndReplaceNoCache replaces the document with given filter with replacement, and unmarshals it into v. 147 func (mm *Model) FindOneAndReplaceNoCache(ctx context.Context, v, filter interface{}, 148 replacement interface{}, opts ...*mopt.FindOneAndReplaceOptions) error { 149 return mm.Model.FindOneAndReplace(ctx, v, filter, replacement, opts...) 150 } 151 152 // FindOneAndUpdate updates the document with given filter with update, and unmarshals it into v. 153 func (mm *Model) FindOneAndUpdate(ctx context.Context, key string, v, filter interface{}, 154 update interface{}, opts ...*mopt.FindOneAndUpdateOptions) error { 155 if err := mm.Model.FindOneAndUpdate(ctx, v, filter, update, opts...); err != nil { 156 return err 157 } 158 159 return mm.DelCache(ctx, key) 160 } 161 162 // FindOneAndUpdateNoCache updates the document with given filter with update, and unmarshals it into v. 163 func (mm *Model) FindOneAndUpdateNoCache(ctx context.Context, v, filter interface{}, 164 update interface{}, opts ...*mopt.FindOneAndUpdateOptions) error { 165 return mm.Model.FindOneAndUpdate(ctx, v, filter, update, opts...) 166 } 167 168 // GetCache unmarshal the cache into v with given key. 169 func (mm *Model) GetCache(key string, v interface{}) error { 170 return mm.cache.Get(key, v) 171 } 172 173 // InsertOne inserts a single document into the collection, and remove the cache placeholder. 174 func (mm *Model) InsertOne(ctx context.Context, key string, document interface{}, 175 opts ...*mopt.InsertOneOptions) (*mongo.InsertOneResult, error) { 176 res, err := mm.Model.InsertOne(ctx, document, opts...) 177 if err != nil { 178 return nil, err 179 } 180 181 if err = mm.DelCache(ctx, key); err != nil { 182 return nil, err 183 } 184 185 return res, nil 186 } 187 188 // InsertOneNoCache inserts a single document into the collection. 189 func (mm *Model) InsertOneNoCache(ctx context.Context, document interface{}, 190 opts ...*mopt.InsertOneOptions) (*mongo.InsertOneResult, error) { 191 return mm.Model.InsertOne(ctx, document, opts...) 192 } 193 194 // ReplaceOne replaces a single document in the collection, and remove the cache. 195 func (mm *Model) ReplaceOne(ctx context.Context, key string, filter, replacement interface{}, 196 opts ...*mopt.ReplaceOptions) (*mongo.UpdateResult, error) { 197 res, err := mm.Model.ReplaceOne(ctx, filter, replacement, opts...) 198 if err != nil { 199 return nil, err 200 } 201 202 if err = mm.DelCache(ctx, key); err != nil { 203 return nil, err 204 } 205 206 return res, nil 207 } 208 209 // ReplaceOneNoCache replaces a single document in the collection. 210 func (mm *Model) ReplaceOneNoCache(ctx context.Context, filter, replacement interface{}, 211 opts ...*mopt.ReplaceOptions) (*mongo.UpdateResult, error) { 212 return mm.Model.ReplaceOne(ctx, filter, replacement, opts...) 213 } 214 215 // SetCache sets the cache with given key and value. 216 func (mm *Model) SetCache(key string, v interface{}) error { 217 return mm.cache.Set(key, v) 218 } 219 220 // UpdateByID updates the document with given id with update, and remove the cache. 221 func (mm *Model) UpdateByID(ctx context.Context, key string, id, update interface{}, 222 opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) { 223 res, err := mm.Model.UpdateByID(ctx, id, update, opts...) 224 if err != nil { 225 return nil, err 226 } 227 228 if err = mm.DelCache(ctx, key); err != nil { 229 return nil, err 230 } 231 232 return res, nil 233 } 234 235 // UpdateByIDNoCache updates the document with given id with update. 236 func (mm *Model) UpdateByIDNoCache(ctx context.Context, id, update interface{}, 237 opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) { 238 return mm.Model.UpdateByID(ctx, id, update, opts...) 239 } 240 241 // UpdateMany updates the documents that match filter with update, and remove the cache. 242 func (mm *Model) UpdateMany(ctx context.Context, keys []string, filter, update interface{}, 243 opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) { 244 res, err := mm.Model.UpdateMany(ctx, filter, update, opts...) 245 if err != nil { 246 return nil, err 247 } 248 249 if err = mm.DelCache(ctx, keys...); err != nil { 250 return nil, err 251 } 252 253 return res, nil 254 } 255 256 // UpdateManyNoCache updates the documents that match filter with update. 257 func (mm *Model) UpdateManyNoCache(ctx context.Context, filter, update interface{}, 258 opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) { 259 return mm.Model.UpdateMany(ctx, filter, update, opts...) 260 } 261 262 // UpdateOne updates the first document that matches filter with update, and remove the cache. 263 func (mm *Model) UpdateOne(ctx context.Context, key string, filter, update interface{}, 264 opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) { 265 res, err := mm.Model.UpdateOne(ctx, filter, update, opts...) 266 if err != nil { 267 return nil, err 268 } 269 270 if err = mm.DelCache(ctx, key); err != nil { 271 return nil, err 272 } 273 274 return res, nil 275 } 276 277 // UpdateOneNoCache updates the first document that matches filter with update. 278 func (mm *Model) UpdateOneNoCache(ctx context.Context, filter, update interface{}, 279 opts ...*mopt.UpdateOptions) (*mongo.UpdateResult, error) { 280 return mm.Model.UpdateOne(ctx, filter, update, opts...) 281 }