222 lines
5.4 KiB
Go
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) {}
|