gitee.com/h79/goutils@v1.22.10/dao/dao.go (about)

     1  package dao
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	commonoption "gitee.com/h79/goutils/common/option"
     8  	"gitee.com/h79/goutils/common/result"
     9  	"gitee.com/h79/goutils/common/stringutil"
    10  	"gitee.com/h79/goutils/dao/db"
    11  	"gitee.com/h79/goutils/dao/option"
    12  	"gitee.com/h79/goutils/dao/redis"
    13  	"gitee.com/h79/goutils/dao/util"
    14  	"gitee.com/h79/goutils/dao/wrapper"
    15  	"gitee.com/h79/goutils/perf"
    16  	goredis "github.com/go-redis/redis/v8"
    17  	"github.com/olivere/elastic/v7"
    18  	"gorm.io/gorm"
    19  	"time"
    20  )
    21  
    22  // Dao https://gorm.io/docs/query.html
    23  type Dao struct {
    24  	Sql     db.SqlDatabase
    25  	Redis   redis.Client
    26  	Elastic db.EsDatabase
    27  }
    28  
    29  var errZero = fmt.Errorf("length is zero")
    30  
    31  func (d *Dao) DBClient(opts ...commonoption.Option) (*gorm.DB, error) {
    32  	r, _, err := d.DBClientV2(opts...)
    33  	return r, err
    34  }
    35  
    36  func (d *Dao) DBClientV2(opts ...commonoption.Option) (*gorm.DB, string, error) {
    37  	if d.Sql == nil {
    38  		return nil, "", result.RErrNotSupport
    39  	}
    40  	var name, _ = option.NameKeyExist(opts...)
    41  	sql, err := d.Sql.Get(name)
    42  	if err != nil {
    43  		return nil, name, result.RErrNil
    44  	}
    45  	return sql.Db(), sql.Name(), nil
    46  }
    47  
    48  func (d *Dao) RedisClient(opts ...commonoption.Option) (*goredis.Client, error) {
    49  	r, _, err := d.RedisClientV2(opts...)
    50  	return r, err
    51  }
    52  
    53  func (d *Dao) RedisClientV2(opts ...commonoption.Option) (*goredis.Client, string, error) {
    54  	if d.Redis == nil {
    55  		return nil, "", result.RErrNotSupport
    56  	}
    57  	var name, _ = option.NameKeyExist(opts...)
    58  	rds, err := d.Redis.Get(name)
    59  	if err != nil {
    60  		return nil, name, err
    61  	}
    62  	return rds.Rds(), rds.Name(), nil
    63  }
    64  
    65  func (d *Dao) ClusterRedisClient(opts ...commonoption.Option) (*goredis.ClusterClient, error) {
    66  	r, _, err := d.ClusterRedisClientV2(opts...)
    67  	return r, err
    68  }
    69  
    70  func (d *Dao) ClusterRedisClientV2(opts ...commonoption.Option) (*goredis.ClusterClient, string, error) {
    71  	if d.Redis == nil {
    72  		return nil, "", result.RErrNotSupport
    73  	}
    74  	var name, _ = option.NameKeyExist(opts...)
    75  	rds, err := d.Redis.Get(name)
    76  	if err != nil {
    77  		return nil, name, err
    78  	}
    79  	return rds.Cluster(), rds.Name(), nil
    80  }
    81  
    82  func (d *Dao) SentinelRedisClient(opts ...commonoption.Option) (*goredis.SentinelClient, error) {
    83  	r, _, err := d.SentinelRedisClientV2(opts...)
    84  	return r, err
    85  }
    86  
    87  func (d *Dao) SentinelRedisClientV2(opts ...commonoption.Option) (*goredis.SentinelClient, string, error) {
    88  	if d.Redis == nil {
    89  		return nil, "", result.RErrNotSupport
    90  	}
    91  	var name, _ = option.NameKeyExist(opts...)
    92  	rds, err := d.Redis.Get(name)
    93  	if err != nil {
    94  		return nil, name, err
    95  	}
    96  	return rds.Sentinel(), rds.Name(), nil
    97  }
    98  
    99  func (d *Dao) ElasticClient(opts ...commonoption.Option) (*elastic.Client, error) {
   100  	r, _, err := d.ElasticClientV2(opts...)
   101  	return r, err
   102  }
   103  
   104  func (d *Dao) ElasticClientV2(opts ...commonoption.Option) (*elastic.Client, string, error) {
   105  	if d.Elastic == nil {
   106  		return nil, "", result.RErrNotSupport
   107  	}
   108  	var name, _ = option.NameKeyExist(opts...)
   109  	es, na, err := d.Elastic.Get(name)
   110  	return es, na, err
   111  }
   112  
   113  func (d *Dao) UseRedis(opts ...commonoption.Option) CurrentRedis {
   114  	client, name, _ := d.RedisClientV2(opts...)
   115  	t, _ := option.TimeOutExist(opts...)
   116  	w := option.AlarmExist(opts...)
   117  	return CurrentRedis{Client: client, Name: name, timeout: t, warn: w}
   118  }
   119  
   120  func (d *Dao) UseDB(opts ...commonoption.Option) CurrentDb {
   121  	client, name, _ := d.DBClientV2(opts...)
   122  	return CurrentDb{DB: client, Name: name}
   123  }
   124  
   125  func (d *Dao) UseElastic(opts ...commonoption.Option) CurrentElastic {
   126  	client, name, _ := d.ElasticClientV2(opts...)
   127  	return CurrentElastic{Client: client, Name: name}
   128  }
   129  
   130  func (d *Dao) Condition(ctx context.Context, data interface{}, call db.ConditionCallback, opts ...commonoption.Option) result.Result {
   131  
   132  	sql, err := d.DBClient(opts...)
   133  	if err != nil {
   134  		return result.Error(result.ErrDbInternal, fmt.Sprintf("the db non existed"))
   135  	}
   136  
   137  	tx := call(ctx, data, sql)
   138  
   139  	if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
   140  		return result.Error(result.ErrNotFound, tx.Error.Error())
   141  	}
   142  	if tx.Error != nil {
   143  		return result.Error(result.ErrDbInternal, tx.Error.Error())
   144  	}
   145  	return result.Succeed()
   146  }
   147  
   148  func (d *Dao) IsNotFound(db *gorm.DB) int {
   149  	return wrapper.IsNotFound(db)
   150  }
   151  
   152  type CurrentElastic struct {
   153  	*elastic.Client
   154  	Name string
   155  }
   156  
   157  func (d *CurrentElastic) OK() bool {
   158  	return d.Client != nil
   159  }
   160  
   161  type CurrentDb struct {
   162  	*gorm.DB
   163  	Name string
   164  }
   165  
   166  func (d *CurrentDb) OK() bool {
   167  	return d.DB != nil
   168  }
   169  
   170  type CurrentRedis struct {
   171  	*goredis.Client
   172  	Name    string
   173  	timeout int64
   174  	warn    bool
   175  }
   176  
   177  func (d *CurrentRedis) Warning(r *perf.RunTime, err error) {
   178  	dif := r.End()
   179  	if dif == 0 || !d.warn {
   180  		return
   181  	}
   182  	util.Alarm(result.ErrDbInternal, "Redis", fmt.Sprintf("run too time long=> %d,start=> %d", dif, r.Start()), err)
   183  }
   184  
   185  func (d *CurrentRedis) OK() bool {
   186  	return d.Client != nil
   187  }
   188  
   189  func (d *CurrentRedis) HSet(ctx context.Context, key, field string, value interface{}) (int64, error) {
   190  	if d.Client == nil {
   191  		return 0, result.RErrNil
   192  	}
   193  	if len(field) <= 0 {
   194  		return 0, errZero
   195  	}
   196  	var err error
   197  	var rt = perf.Begin(d.timeout)
   198  	defer d.Warning(rt, nil)
   199  	ret, err := d.Client.HSet(ctx, key, field, value).Result()
   200  	return ret, err
   201  }
   202  
   203  func (d *CurrentRedis) HSetNX(ctx context.Context, key, field string, value interface{}) (bool, error) {
   204  	if d.Client == nil {
   205  		return false, result.RErrNil
   206  	}
   207  	if len(field) <= 0 {
   208  		return false, errZero
   209  	}
   210  	var err error
   211  	var rt = perf.Begin(d.timeout)
   212  	defer d.Warning(rt, err)
   213  	ret, err := d.Client.HSetNX(ctx, key, field, value).Result()
   214  	return ret, err
   215  }
   216  
   217  func (d *CurrentRedis) HGet(ctx context.Context, key, field string) (string, error) {
   218  	if d.Client == nil {
   219  		return "", result.RErrNil
   220  	}
   221  	var err error
   222  	var rt = perf.Begin(d.timeout)
   223  	defer d.Warning(rt, err)
   224  	ret, err := d.Client.HGet(ctx, key, field).Result()
   225  	return ret, err
   226  }
   227  
   228  func (d *CurrentRedis) HGetAll(ctx context.Context, key string) (map[string]string, error) {
   229  	if d.Client == nil {
   230  		return nil, result.RErrNil
   231  	}
   232  	var err error
   233  	var rt = perf.Begin(d.timeout)
   234  	defer d.Warning(rt, err)
   235  	ret, err := d.Client.HGetAll(ctx, key).Result()
   236  	return ret, err
   237  }
   238  
   239  func (d *CurrentRedis) HGetInt(ctx context.Context, key, field string) (int, error) {
   240  	if d.Client == nil {
   241  		return 0, result.RErrNil
   242  	}
   243  	var err error
   244  	var rt = perf.Begin(d.timeout)
   245  	defer d.Warning(rt, err)
   246  	ret, err := d.Client.HGet(ctx, key, field).Result()
   247  	if err != nil {
   248  		return 0, err
   249  	}
   250  	return stringutil.StringToInt(ret), nil
   251  }
   252  
   253  func (d *CurrentRedis) HDel(ctx context.Context, key, field string) (int64, error) {
   254  	if d.Client == nil {
   255  		return 0, result.RErrNil
   256  	}
   257  	var err error
   258  	var rt = perf.Begin(d.timeout)
   259  	defer d.Warning(rt, err)
   260  	ret, err := d.Client.HDel(ctx, key, field).Result()
   261  	return ret, err
   262  }
   263  
   264  func (d *CurrentRedis) HInc(ctx context.Context, key, field string, value int64) (int64, error) {
   265  	if d.Client == nil {
   266  		return 0, result.RErrNil
   267  	}
   268  	if len(field) <= 0 {
   269  		return 0, errZero
   270  	}
   271  	var err error
   272  	var rt = perf.Begin(d.timeout)
   273  	defer d.Warning(rt, err)
   274  	ret, err := d.Client.HIncrBy(ctx, key, field, value).Result()
   275  	return ret, err
   276  }
   277  
   278  func (d *CurrentRedis) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) (string, error) {
   279  	if d.Client == nil {
   280  		return "", result.RErrNil
   281  	}
   282  	if len(key) <= 0 {
   283  		return "", errZero
   284  	}
   285  	var err error
   286  	var rt = perf.Begin(d.timeout)
   287  	defer d.Warning(rt, err)
   288  	ret, err := d.Client.Set(ctx, key, value, expiration).Result()
   289  	return ret, err
   290  }
   291  
   292  func (d *CurrentRedis) SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) (bool, error) {
   293  	if d.Client == nil {
   294  		return false, result.RErrNil
   295  	}
   296  	if len(key) <= 0 {
   297  		return false, errZero
   298  	}
   299  	var err error
   300  	var rt = perf.Begin(d.timeout)
   301  	defer d.Warning(rt, err)
   302  	ret, err := d.Client.SetNX(ctx, key, value, expiration).Result()
   303  	return ret, err
   304  }
   305  
   306  func (d *CurrentRedis) SetEX(ctx context.Context, key string, value interface{}, expiration time.Duration) (string, error) {
   307  	if d.Client == nil {
   308  		return "", result.RErrNil
   309  	}
   310  	if len(key) <= 0 {
   311  		return "", errZero
   312  	}
   313  	var err error
   314  	var rt = perf.Begin(d.timeout)
   315  	defer d.Warning(rt, err)
   316  	ret, err := d.Client.SetEX(ctx, key, value, expiration).Result()
   317  	return ret, err
   318  }
   319  
   320  func (d *CurrentRedis) Get(ctx context.Context, key string) (string, error) {
   321  	if d.Client == nil {
   322  		return "", result.RErrNil
   323  	}
   324  	var err error
   325  	var rt = perf.Begin(d.timeout)
   326  	defer d.Warning(rt, err)
   327  	ret, err := d.Client.Get(ctx, key).Result()
   328  	return ret, err
   329  }
   330  
   331  func (d *CurrentRedis) Inc(ctx context.Context, key string, value int64) (int64, error) {
   332  	if d.Client == nil {
   333  		return 0, result.RErrNil
   334  	}
   335  	if len(key) <= 0 {
   336  		return 0, errZero
   337  	}
   338  	var err error
   339  	var rt = perf.Begin(d.timeout)
   340  	defer d.Warning(rt, err)
   341  	ret, err := d.Client.IncrBy(ctx, key, value).Result()
   342  	return ret, err
   343  }
   344  
   345  func (d *CurrentRedis) GetInt(ctx context.Context, key string) (int, error) {
   346  	if d.Client == nil {
   347  		return 0, result.RErrNil
   348  	}
   349  	var err error
   350  	var rt = perf.Begin(d.timeout)
   351  	defer d.Warning(rt, err)
   352  	ret, err := d.Client.Get(ctx, key).Result()
   353  	if err != nil {
   354  		return 0, err
   355  	}
   356  	return stringutil.StringToInt(ret), nil
   357  }
   358  
   359  // ExpireAt 在某个时间点过期
   360  func (d *CurrentRedis) ExpireAt(ctx context.Context, key string, time time.Time) {
   361  	if d.Client == nil {
   362  		return
   363  	}
   364  	var err error
   365  	var rt = perf.Begin(d.timeout)
   366  	defer d.Warning(rt, err)
   367  	_, err = d.Client.ExpireAt(ctx, key, time).Result()
   368  }
   369  
   370  // Expire 过多久失效
   371  func (d *CurrentRedis) Expire(ctx context.Context, key string, time time.Duration) {
   372  	if d.Client == nil {
   373  		return
   374  	}
   375  	var err error
   376  	var rt = perf.Begin(d.timeout)
   377  	defer d.Warning(rt, err)
   378  	_, err = d.Client.Expire(ctx, key, time).Result()
   379  }