package data import ( "context" "sort" "time" "go-common/app/interface/main/creative/model/data" "go-common/app/interface/main/creative/model/tag" "go-common/library/ecode" "go-common/library/log" ) func beginningOfDay(t time.Time) time.Time { d := time.Duration(-t.Hour()) * time.Hour return t.Truncate(time.Hour).Add(d) } func getTuesday(now time.Time) time.Time { t := beginningOfDay(now) weekday := int(t.Weekday()) if weekday == 0 { weekday = 7 } d := time.Duration(-weekday+2) * 24 * time.Hour return t.Truncate(time.Hour).Add(d) } func getSunday(now time.Time) time.Time { t := beginningOfDay(now) weekday := int(t.Weekday()) if weekday == 0 { return t } d := time.Duration(7-weekday) * 24 * time.Hour return t.Truncate(time.Hour).Add(d) } func getDate() (sd string) { t := time.Now() td := getTuesday(t).Add(12 * time.Hour) if t.Before(td) { //当前时间在本周二12点之前,则取上上周日的数据,否则取上周日的数据 sd = getSunday(t.AddDate(0, 0, -14)).Format("20060102") } else { sd = getSunday(t.AddDate(0, 0, -7)).Format("20060102") } log.Info("current time (%s) tuesday (%s) sunday (%s)", t.Format("2006-01-02 15:04:05"), td, sd) return } // NewStat get stat from hbase. func (s *Service) NewStat(c context.Context, mid int64, ip string) (r *data.Stat, err error) { hbaseDate1 := time.Now().AddDate(0, 0, -1).Add(-12 * time.Hour).Format("20060102") hbaseDate2 := time.Now().AddDate(0, 0, -2).Add(-12 * time.Hour).Format("20060102") var r1, r2 *data.UpBaseStat if r1, err = s.data.UpStat(c, mid, hbaseDate1); err != nil || r1 == nil { log.Error("s.data.NewStat error(%v) mid(%d) r1(%v) ip(%s)", err, mid, r1, ip) err = ecode.CreativeDataErr return } if r2, err = s.data.UpStat(c, mid, hbaseDate2); err != nil || r2 == nil { log.Error("s.data.NewStat error(%v) mid(%d) r2(%v) ip(%s)", err, mid, r2, ip) err = ecode.CreativeDataErr return } r = &data.Stat{} if r1 != nil { r.Play = r1.View r.Dm = r1.Dm r.Comment = r1.Reply r.Fan = r1.Fans r.Fav = r1.Fav r.Like = r1.Like r.Share = r1.Share r.Coin = r1.Coin r.Elec = r1.Elec } log.Info("s.data.UpStat hbaseDate1(%+v) mid(%d)", r1, mid) if r2 != nil { r.PlayLast = r2.View r.DmLast = r2.Dm r.CommentLast = r2.Reply r.FanLast = r2.Fans r.FavLast = r2.Fav r.LikeLast = r2.Like r.ShareLast = r2.Share r.CoinLast = r2.Coin r.ElecLast = r2.Elec } log.Info("s.data.UpStat hbaseDate2 (%+v) mid(%d)", r2, mid) pfl, err := s.acc.ProfileWithStat(c, mid) if err != nil { return } r.Fan = int64(pfl.Follower) return } // ViewerBase get up viewer base data. func (s *Service) ViewerBase(c context.Context, mid int64) (res map[string]*data.ViewerBase, err error) { dt := getDate() // try cache if res, _ = s.data.ViewerBaseCache(c, mid, dt); res != nil { s.pCacheHit.Incr("viewer_base_cache") return } // from data source if res, err = s.data.ViewerBase(c, mid, dt); len(res) != 0 { s.pCacheMiss.Incr("viewer_base_cache") s.data.AddCache(func() { s.data.AddViewerBaseCache(context.Background(), mid, dt, res) }) } return } // ViewerArea get up viewer area data. func (s *Service) ViewerArea(c context.Context, mid int64) (res map[string]map[string]int64, err error) { dt := getDate() // try cache if res, _ = s.data.ViewerAreaCache(c, mid, dt); res != nil { s.pCacheHit.Incr("viewer_area_cache") return } // from data source if res, err = s.data.ViewerArea(c, mid, dt); len(res) != 0 { s.pCacheMiss.Incr("viewer_area_cache") s.data.AddCache(func() { s.data.AddViewerAreaCache(context.Background(), mid, dt, res) }) } return } // CacheTrend get trend from mc. func (s *Service) CacheTrend(c context.Context, mid int64) (res map[string]*data.ViewerTrend, err error) { dt := getDate() // try cache if res, err = s.data.TrendCache(c, mid, dt); err != nil { log.Error("trend s.data.TrendCache err(%v)", err) return } if len(res) != 0 { s.pCacheHit.Incr("trend_cache") return } // from data source if res, err = s.viewerTrend(c, mid, dt); err != nil { return } s.pCacheMiss.Incr("trend_cache") if len(res) != 0 { s.data.AddCache(func() { s.data.AddTrendCache(context.Background(), mid, dt, res) }) } return } // ViewerTrend get up viewer trend data. func (s *Service) viewerTrend(c context.Context, mid int64, dt string) (res map[string]*data.ViewerTrend, err error) { ut, err := s.data.ViewerTrend(c, mid, dt) if err != nil || ut == nil { log.Error("trend s.data.ViewerTrend err(%v)", err) return } f := []string{"fan", "not_fan"} skeys := make([]int, 0) //for tag sort. tgs := make([]int64, 0) // for request tag name. res = make(map[string]*data.ViewerTrend) for _, fk := range f { td := ut[fk] vt := &data.ViewerTrend{} if td == nil { vt.Ty = nil vt.Tag = nil res[fk] = vt continue } tg := make(map[int]string) //return tag map to user. ty := make(map[string]int64) //return type map to user. //deal type for type name. if td.Ty != nil { for k, v := range td.Ty { ke := int16(k) if t, ok := s.p.TypeMapCache[ke]; ok { ty[t.Name] = v } } } else { ty = nil } // deal tag for tag name. if td.Tag != nil { for k, v := range td.Tag { tgs = append(tgs, v) skeys = append(skeys, k) } var tlist []*tag.Meta if tlist, err = s.dtag.TagList(c, tgs); err != nil { log.Error("trend s.dtag.TagList err(%v)", err) } tNameMap := make(map[int64]string) for _, v := range tlist { tNameMap[v.TagID] = v.TagName } for _, k := range skeys { if _, ok := tNameMap[td.Tag[k]]; ok { tg[k] = tNameMap[td.Tag[k]] } } } else { tg = nil } vt.Ty = ty vt.Tag = tg res[fk] = vt } return } // RelationFansDay get up viewer trend data. func (s *Service) RelationFansDay(c context.Context, mid int64) (res map[string]map[string]int, err error) { dt := time.Now().AddDate(0, 0, -1).Add(-12 * time.Hour).Format("20060102") // try cache if res, _ = s.data.RelationFansDayCache(c, mid, dt); res != nil { s.pCacheHit.Incr("relation_fans_day_cache") return } // from data source if res, err = s.data.RelationFansDay(c, mid); len(res) != 0 { s.pCacheMiss.Incr("relation_fans_day_cache") s.data.AddCache(func() { s.data.AddRelationFansDayCache(context.Background(), mid, dt, res) }) } return } // RelationFansHistory get relation history data by month. func (s *Service) RelationFansHistory(c context.Context, mid int64, month string) (res map[string]map[string]int, err error) { if res, err = s.data.RelationFansHistory(c, mid, month); err != nil { log.Error("s.data.RelationFansHistory err(%v)", err) } return } // RelationFansMonth get up viewer trend data. func (s *Service) RelationFansMonth(c context.Context, mid int64) (res map[string]map[string]int, err error) { dt := time.Now().AddDate(0, 0, -1).Add(-12 * time.Hour).Format("20060102") // try cache if res, _ = s.data.RelationFansMonthCache(c, mid, dt); res != nil { s.pCacheHit.Incr("relation_fans_month_cache") return } // from data source if res, err = s.data.RelationFansMonth(c, mid); len(res) != 0 { s.pCacheMiss.Incr("relation_fans_month_cache") s.data.AddCache(func() { s.data.AddRelationFansMonthCache(context.Background(), mid, dt, res) }) } return } // ViewerActionHour get up viewer action hour data. func (s *Service) ViewerActionHour(c context.Context, mid int64) (res map[string]*data.ViewerActionHour, err error) { dt := getDate() // try cache if res, _ = s.data.ViewerActionHourCache(c, mid, dt); res != nil { s.pCacheHit.Incr("viewer_action_hour_cache") return } // from data source if res, err = s.data.ViewerActionHour(c, mid, dt); len(res) != 0 { s.data.AddCache(func() { s.pCacheMiss.Incr("viewer_action_hour_cache") s.data.AddViewerActionHourCache(context.Background(), mid, dt, res) }) } return } // UpIncr for Play/Dm/Reply/Fav/Share/Elec/Coin incr. func (s *Service) UpIncr(c context.Context, mid int64, ty int8, ip string) (res map[string]*data.ViewerIncr, err error) { tyStr, _ := data.IncrTy(ty) res = make(map[string]*data.ViewerIncr) daytime := time.Now().AddDate(0, 0, -1).Add(-12 * time.Hour) datekey := daytime.Format("20060102") dt := daytime.Format("20060102") vic, _ := s.data.ViewerIncrCache(c, mid, tyStr, dt) if vic != nil { s.pCacheHit.Incr("viewer_incr_cache") res[datekey] = vic log.Info("s.data.ViewerIncrCache mid(%d) cache(%v) err(%v)", mid, vic, err) return } incr, _ := s.data.UpIncr(c, mid, ty, dt) if incr == nil { res[datekey] = nil log.Info("s.data.UpIncr mid(%d) incr(%v) err(%v)", incr, err) return } tyRank := make(map[string]int) //return type map to user. for k, v := range incr.Rank { ke := int16(k) if t, ok := s.p.TypeMapCache[ke]; ok { tyRank[t.Name] = v } } sortK := make([]int, 0, len(incr.TopAIDList)) aids := make([]int64, 0, len(incr.TopAIDList)) for k, v := range incr.TopAIDList { aids = append(aids, v) sortK = append(sortK, k) } avm, _ := s.p.BatchArchives(c, mid, aids, ip) if len(avm) == 0 { return } sort.Ints(sortK) arcs := make([]*data.ArcInc, 0, len(avm)) for _, k := range sortK { if aid, ok := incr.TopAIDList[k]; ok { if av, ok := avm[aid]; ok { al := &data.ArcInc{} al.AID = av.Archive.Aid al.PTime = av.Archive.PTime al.Title = av.Archive.Title al.DayTime = daytime.Unix() if _, ok := incr.TopIncrList[k]; ok { al.Incr = incr.TopIncrList[k] } arcs = append(arcs, al) } } } vi := &data.ViewerIncr{} vi.Arcs = arcs vi.TotalIncr = incr.Incr if len(tyRank) == 0 { vi.TyRank = nil } else { vi.TyRank = tyRank } res[datekey] = vi // insert cache. NOTE: sync reason? s.data.AddCache(func() { s.pCacheMiss.Incr("viewer_incr_cache") s.data.AddViewerIncrCache(context.Background(), mid, tyStr, dt, vi) }) return }