123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- package dao
- import (
- "context"
- "fmt"
- "io"
- "math"
- "strconv"
- "strings"
- "sync"
- "go-common/app/admin/main/member/model"
- "go-common/library/log"
- "go-common/library/sync/errgroup"
- xtime "go-common/library/time"
- "github.com/tsuna/gohbase/hrpc"
- )
- var (
- tableFaceByMidHistory = "account:user_face"
- tableFaceByOPHistory = "account:user_face_admin"
- )
- // reverse returns its argument string reversed rune-wise left to right.
- func reverse(s string) string {
- r := []rune(s)
- for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
- r[i], r[j] = r[j], r[i]
- }
- return string(r)
- }
- func rpad(s string, c string, l int) string {
- dt := l - len(s)
- if dt <= 0 {
- return s
- }
- return s + strings.Repeat(c, dt)
- }
- // func lpad(s string, c string, l int) string {
- // dt := l - len(s)
- // if dt <= 0 {
- // return s
- // }
- // return strings.Repeat(c, dt) + s
- // }
- func midKey(mid int64, time xtime.Time) string {
- suf := rpad(strconv.FormatInt(math.MaxInt64-int64(time), 10), "0", 10)
- return fmt.Sprintf("%s%s", rpad(reverse(strconv.FormatInt(mid, 10)), "0", 10), string(suf[len(suf)-10:]))
- }
- func operatorKey(operator string, time xtime.Time) string {
- suf := rpad(strconv.FormatInt(math.MaxInt64-int64(time), 10), "0", 10)
- return fmt.Sprintf("%s%s", rpad(operator, "-", 20), string(suf[len(suf)-10:]))
- }
- func scanTimes(tDuration xtime.Time) int {
- times := int(tDuration)/(60*60) + 5
- if times > 50 {
- times = 50
- }
- return times
- }
- // FaceHistoryByMid is.
- func (d *Dao) FaceHistoryByMid(ctx context.Context, arg *model.ArgFaceHistory) (model.FaceRecordList, error) {
- size := arg.ETime - arg.STime
- stimes := scanTimes(size)
- chunk := xtime.Time(size / xtime.Time(stimes))
- if chunk == 0 {
- chunk = size
- }
- rendKey, rstartKey := midKey(arg.Mid, arg.STime), midKey(arg.Mid, arg.ETime)
- eg := errgroup.Group{}
- lock := sync.RWMutex{}
- records := make(model.FaceRecordList, 0)
- for i := 0; i < stimes; i++ {
- times := i + 1
- stime := arg.STime + (chunk * xtime.Time(i))
- etime := arg.STime + (chunk * xtime.Time(i+1))
- eg.Go(func() error {
- endKey, startKey := midKey(arg.Mid, stime), midKey(arg.Mid, etime)
- log.Info("FaceHistoryByMid: range: start: %s end: %s with times: %d scaning key: start: %s end: %s",
- rstartKey, rendKey, times, startKey, endKey)
- scanner, err := d.fhbymidhbase.ScanRangeStr(ctx, tableFaceByMidHistory, startKey, endKey)
- if err != nil {
- log.Error("hbase.ScanRangeStr(%s,%+v) error(%v)", tableFaceByMidHistory, arg, err)
- return err
- }
- for {
- r, err := scanner.Next()
- if err != nil {
- if err != io.EOF {
- return err
- }
- break
- }
- lock.Lock()
- records = append(records, toMidFaceRecord(r))
- lock.Unlock()
- }
- return nil
- })
- if etime >= arg.ETime {
- break
- }
- }
- if err := eg.Wait(); err != nil {
- return nil, err
- }
- return records, nil
- }
- // FaceHistoryByOP is.
- func (d *Dao) FaceHistoryByOP(ctx context.Context, arg *model.ArgFaceHistory) (model.FaceRecordList, error) {
- size := arg.ETime - arg.STime
- stimes := scanTimes(size)
- chunk := xtime.Time(size / xtime.Time(stimes))
- if chunk == 0 {
- chunk = size
- }
- rendKey, rstartKey := operatorKey(arg.Operator, arg.STime), operatorKey(arg.Operator, arg.ETime)
- eg := errgroup.Group{}
- lock := sync.RWMutex{}
- records := make(model.FaceRecordList, 0)
- for i := 0; i < stimes; i++ {
- times := i + 1
- stime := arg.STime + (chunk * xtime.Time(i))
- etime := arg.STime + (chunk * xtime.Time(i+1))
- eg.Go(func() error {
- endKey, startKey := operatorKey(arg.Operator, stime), operatorKey(arg.Operator, etime)
- log.Info("FaceHistoryByOP: range: start: %s end: %s with times: %d scaning key: start: %s end: %s",
- rstartKey, rendKey, times, startKey, endKey)
- scanner, err := d.fhbyophbase.ScanRangeStr(ctx, tableFaceByOPHistory, startKey, endKey)
- if err != nil {
- log.Error("hbase.ScanRangeStr(%s,%+v) error(%v)", tableFaceByOPHistory, arg, err)
- return err
- }
- for {
- r, err := scanner.Next()
- if err != nil {
- if err != io.EOF {
- return err
- }
- break
- }
- lock.Lock()
- records = append(records, toOPFaceRecord(r))
- lock.Unlock()
- }
- return nil
- })
- if etime >= arg.ETime {
- break
- }
- }
- if err := eg.Wait(); err != nil {
- return nil, err
- }
- return records, nil
- }
- func toOPFaceRecord(res *hrpc.Result) *model.FaceRecord {
- l := &model.FaceRecord{}
- for _, c := range res.Cells {
- key := string(c.Row)
- qf := string(c.Qualifier)
- v := string(c.Value)
- log.Info("Retrieving op face record history: key(%s) qualifier(%s) value(%s)", key, qf, v)
- // fill fields
- switch qf {
- case "id":
- l.ID, _ = strconv.ParseInt(v, 10, 64)
- case "mid":
- l.Mid, _ = strconv.ParseInt(v, 10, 64)
- case "sta":
- l.Status = model.ParseStatus(v)
- case "op":
- l.Operator = v
- case "old":
- l.OldFace = v
- case "new":
- l.NewFace = v
- case "apply":
- l.ApplyTime = model.ParseApplyTime(v)
- case "mtm":
- l.ModifyTime, _ = model.ParseLogTime(v)
- }
- }
- return l
- }
- func toMidFaceRecord(res *hrpc.Result) *model.FaceRecord {
- l := &model.FaceRecord{}
- for _, c := range res.Cells {
- key := string(c.Row)
- qf := string(c.Qualifier)
- v := string(c.Value)
- log.Info("Retrieving mid face record history: key(%s) qualifier(%s) value(%s)", key, qf, v)
- // fill fields
- switch qf {
- // case "id":
- // l.ID, _ = strconv.ParseInt(v, 10, 64)
- case "mid":
- l.Mid, _ = strconv.ParseInt(v, 10, 64)
- case "s":
- l.Status = model.ParseStatus(v)
- case "op":
- l.Operator = v
- case "of":
- l.OldFace = v
- case "nf":
- l.NewFace = v
- case "at":
- l.ApplyTime = model.ParseApplyTime(v)
- case "mt":
- l.ModifyTime, _ = model.ParseLogTime(v)
- }
- }
- return l
- }
|