mdbc/scope.go
2022-02-23 16:59:45 +08:00

222 lines
5.4 KiB
Go

package mdbc
import (
"context"
"time"
"github.com/go-redis/redis/v8"
)
type cacheConfig struct {
enable bool // 是否缓存
ttl time.Duration // 缓存时间
client redis.UniversalClient // 全局缓存redis句柄 [缓存、熔断器]
}
type breakerConfig struct {
ttl time.Duration // 熔断时间
reporter bool // 是否开启熔断告警 开启熔断告警 需要配置全局的redis 否则开启无效
}
// CacheObject 生成的缓存对象
type CacheObject struct {
// Key redis的key
Key string
// Value redis的value 请自行marshal对象value
// 如果value是一个对象 请将该对象实现 encoding.BinaryMarshaler
// 你可以参考 DefaultFindOneCacheFunc 其利用 json.Marshal 实现了对 value 的序列化
Value interface{}
}
// Scope 所有操作基于此结构 自定义结构体 将其匿名以继承其子scope
type Scope struct {
*Model // 模型
cache *cacheConfig // 缓存配置项
breaker *breakerConfig // 熔断配置项
execT time.Duration // 执行时间 后续debug和熔断告警用到
debug bool // 是否开启debug
debugWhenError bool // 当错误时才输出debug信息
}
type ctxWrap struct {
ctx context.Context // 上下文
cancel context.CancelFunc // 上下文取消
}
func (s *Scope) newDefaultCtxWrap() *ctxWrap {
return &ctxWrap{}
}
// SetDebug 是否开启执行语句的日志输出 目前仅支持终端输出
func (s *Scope) SetDebug(debug bool) *Scope {
s.debug = debug
return s
}
// SetDebugError 是否开启仅当错误时打印执行语句的日志 目前仅支持终端输出
func (s *Scope) SetDebugError(debug bool) *Scope {
s.debugWhenError = debug
return s
}
// SetBreaker 设置熔断时间 不配置默认5s熔断
// 此处建议在全局进行配置一次 否则会有覆盖后失效风险
func (s *Scope) SetBreaker(duration time.Duration) *Scope {
if s.breaker == nil {
s.breaker = &breakerConfig{}
}
s.breaker.ttl = duration
return s
}
// SetBreakerReporter 设置开启熔断告警
func (s *Scope) SetBreakerReporter(br bool) *Scope {
if s.breaker == nil {
s.breaker = &breakerConfig{}
}
s.breaker.reporter = br
return s
}
// SetCacheIdle 设置redis句柄 方便查询操作进行缓存
// 此处建议在全局进行配置一次 否则会有覆盖后失效风险
func (s *Scope) SetCacheIdle(cli redis.UniversalClient) *Scope {
if s.cache == nil {
s.cache = &cacheConfig{}
}
s.cache.client = cli
return s
}
// SetCacheExpiredAt 设置redis缓存过期时间 不设置 则不缓存 单位time.Duration
// 此处建议在全局进行配置一次 否则会有覆盖后失效风险
func (s *Scope) SetCacheExpiredAt(t time.Duration) *Scope {
if s.cache == nil {
s.cache = &cacheConfig{}
}
s.cache.ttl = t
s.cache.enable = true
return s
}
// SetCacheForever 设置key永不过期 true永不过期
// 此处建议在全局进行配置一次 否则会有覆盖后失效风险
func (s *Scope) SetCacheForever(b bool) *Scope {
if s.cache == nil {
s.cache = &cacheConfig{}
}
if b {
s.cache.ttl = -1
s.cache.enable = true
}
return s
}
// GetTableName 获取当前连接的表名
func (s *Scope) GetTableName() string {
return s.tableName
}
// check ctx检测和初始化
func (s *Scope) check() {
if s.breaker == nil {
s.breaker = &breakerConfig{}
}
// 设置默认熔断时间 5秒
if s.breaker.ttl == 0 {
s.breaker.ttl = 5 * time.Second
}
}
// RawConn 返回原始的mongoDB 操作资源句柄
func (s *Scope) RawConn() *Collection {
return db.Collection(s.tableName)
}
// Aggregate 聚合操作
func (s *Scope) Aggregate() *AggregateScope {
s.check()
as := &AggregateScope{cw: s.newDefaultCtxWrap(), scope: s}
return as
}
// Find 查询列表操作
func (s *Scope) Find() *FindScope {
s.check()
fs := &FindScope{cw: s.newDefaultCtxWrap(), scope: s}
return fs
}
// FindOne 查询一条操作
func (s *Scope) FindOne() *FindOneScope {
s.check()
fs := &FindOneScope{cw: s.newDefaultCtxWrap(), scope: s}
return fs
}
// Update 更新文档操作
func (s *Scope) Update() *UpdateScope {
s.check()
us := &UpdateScope{cw: s.newDefaultCtxWrap(), scope: s}
return us
}
// Delete 删除文档操作
func (s *Scope) Delete() *DeleteScope {
s.check()
ds := &DeleteScope{cw: s.newDefaultCtxWrap(), scope: s}
return ds
}
// Insert 插入文档操作
func (s *Scope) Insert() *InsertScope {
s.check()
is := &InsertScope{cw: s.newDefaultCtxWrap(), scope: s}
return is
}
// Distinct Distinct操作
func (s *Scope) Distinct() *DistinctScope {
s.check()
ds := &DistinctScope{cw: s.newDefaultCtxWrap(), scope: s}
return ds
}
// Index 索引操作
func (s *Scope) Index() *IndexScope {
s.check()
is := &IndexScope{cw: s.newDefaultCtxWrap(), scope: s}
return is
}
// BulkWrite 批量写操作
func (s *Scope) BulkWrite() *BulkWriteScope {
s.check()
bws := &BulkWriteScope{cw: s.newDefaultCtxWrap(), scope: s}
return bws
}
// Count 计数操作
func (s *Scope) Count() *CountScope {
s.check()
cs := &CountScope{cw: s.newDefaultCtxWrap(), scope: s}
return cs
}
// Drop 集合删除操作
func (s *Scope) Drop() *DropScope {
s.check()
ds := &DropScope{cw: s.newDefaultCtxWrap(), scope: s}
return ds
}
// Transaction 事务操作
func (s *Scope) Transaction() *TransactionScope {
s.check()
tx := &TransactionScope{cw: s.newDefaultCtxWrap(), scope: s}
return tx
}
// Retry mongo失败后的重试机制
func (s *Scope) Retry(since int64) {}