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  }