bigdata.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. package dao
  2. import (
  3. "bytes"
  4. "crypto/md5"
  5. "encoding/hex"
  6. "net/url"
  7. "strconv"
  8. "time"
  9. "go-common/app/interface/main/creative/model/data"
  10. "go-common/app/interface/openplatform/article/model"
  11. "go-common/library/ecode"
  12. "go-common/library/log"
  13. "golang.org/x/net/context"
  14. )
  15. var (
  16. //HBaseArticleTable 文章作者概况
  17. HBaseArticleTable = "read_auth_stats_daily"
  18. )
  19. func hbaseMd5Key(aid int64) []byte {
  20. hasher := md5.New()
  21. hasher.Write([]byte(strconv.Itoa(int(aid))))
  22. return []byte(hex.EncodeToString(hasher.Sum(nil)))
  23. }
  24. // UpStat get the stat of article.
  25. func (d *Dao) UpStat(c context.Context, mid int64) (stat model.UpStat, err error) {
  26. var (
  27. tableName = HBaseArticleTable
  28. )
  29. result, err := d.hbase.Get(c, []byte(tableName), hbaseMd5Key(mid))
  30. if err != nil {
  31. log.Error("bigdata: d.hbase.Get BackupTable(%s, %d) error(%+v)", tableName, mid, err)
  32. PromError("bigdata:hbase")
  33. err = ecode.CreativeDataErr
  34. return
  35. }
  36. if result == nil {
  37. return
  38. }
  39. for _, c := range result.Cells {
  40. if c == nil {
  41. continue
  42. }
  43. v, _ := strconv.ParseInt(string(c.Value[:]), 10, 64)
  44. if !bytes.Equal(c.Family, []byte("r")) {
  45. continue
  46. }
  47. switch {
  48. case bytes.Equal(c.Qualifier, []byte("view1")):
  49. stat.View = v
  50. case bytes.Equal(c.Qualifier, []byte("reply1")):
  51. stat.Reply = v
  52. case bytes.Equal(c.Qualifier, []byte("coin1")):
  53. stat.Coin = v
  54. case bytes.Equal(c.Qualifier, []byte("like1")):
  55. stat.Like = v
  56. case bytes.Equal(c.Qualifier, []byte("fav1")):
  57. stat.Fav = v
  58. case bytes.Equal(c.Qualifier, []byte("share1")):
  59. stat.Share = v
  60. case bytes.Equal(c.Qualifier, []byte("view0")):
  61. stat.PreView = v
  62. case bytes.Equal(c.Qualifier, []byte("reply0")):
  63. stat.PreReply = v
  64. case bytes.Equal(c.Qualifier, []byte("coin0")):
  65. stat.PreCoin = v
  66. case bytes.Equal(c.Qualifier, []byte("like0")):
  67. stat.PreLike = v
  68. case bytes.Equal(c.Qualifier, []byte("fav0")):
  69. stat.PreFav = v
  70. case bytes.Equal(c.Qualifier, []byte("share0")):
  71. stat.PreShare = v
  72. }
  73. }
  74. stat.IncrView = stat.View - stat.PreView
  75. stat.IncrReply = stat.Reply - stat.PreReply
  76. stat.IncrCoin = stat.Coin - stat.PreCoin
  77. stat.IncrLike = stat.Like - stat.PreLike
  78. stat.IncrFav = stat.Fav - stat.PreFav
  79. stat.IncrShare = stat.Share - stat.PreShare
  80. d.AddCacheUpStatDaily(c, mid, &stat)
  81. return
  82. }
  83. // ThirtyDayArticle for Read/Reply/Like/Fav/Coin for article 30 days.
  84. func (d *Dao) ThirtyDayArticle(c context.Context, mid int64) (res []*model.ThirtyDayArticle, err error) {
  85. var (
  86. tableName = "read_auth_stats" //文章30天数据
  87. )
  88. result, err := d.hbase.Get(c, []byte(tableName), hbaseMd5Key(mid))
  89. if err != nil {
  90. log.Error("bigdata: d.hbase.Get tableName(%s) mid(%d) error(%+v)", tableName, mid, err)
  91. PromError("bigdata:30天数据")
  92. err = ecode.CreativeDataErr
  93. return
  94. }
  95. if result == nil || len(result.Cells) == 0 {
  96. log.Warn("bigdata: ThirtyDay article no data (%s, %d)", tableName, mid)
  97. PromError("bigdata:30天数据")
  98. return
  99. }
  100. res = make([]*model.ThirtyDayArticle, 0, 5)
  101. vtds := make([]*data.ThirtyDay, 0, 30)
  102. ptds := make([]*data.ThirtyDay, 0, 30)
  103. ltds := make([]*data.ThirtyDay, 0, 30)
  104. ftds := make([]*data.ThirtyDay, 0, 30)
  105. ctds := make([]*data.ThirtyDay, 0, 30)
  106. view := &model.ThirtyDayArticle{Category: "view"}
  107. reply := &model.ThirtyDayArticle{Category: "reply"}
  108. like := &model.ThirtyDayArticle{Category: "like"}
  109. fav := &model.ThirtyDayArticle{Category: "fav"}
  110. coin := &model.ThirtyDayArticle{Category: "coin"}
  111. for _, c := range result.Cells {
  112. if c == nil {
  113. continue
  114. }
  115. family := string(c.Family)
  116. qual := string(c.Qualifier[:])
  117. val := string(c.Value[:])
  118. switch family {
  119. case "v": //"阅读量"
  120. t, v, err := parseKeyValue(qual, val)
  121. if err != nil {
  122. break
  123. }
  124. td := &data.ThirtyDay{}
  125. td.DateKey = t
  126. td.TotalIncr = v
  127. vtds = append(vtds, td)
  128. view.ThirtyDay = vtds
  129. case "p": //"评论量"
  130. t, v, err := parseKeyValue(qual, val)
  131. if err != nil {
  132. break
  133. }
  134. td := &data.ThirtyDay{}
  135. td.DateKey = t
  136. td.TotalIncr = v
  137. ptds = append(ptds, td)
  138. reply.Category = "reply"
  139. reply.ThirtyDay = ptds
  140. case "l": //"点赞量"
  141. t, v, err := parseKeyValue(qual, val)
  142. if err != nil {
  143. break
  144. }
  145. td := &data.ThirtyDay{}
  146. td.DateKey = t
  147. td.TotalIncr = v
  148. ltds = append(ltds, td)
  149. like.Category = "like"
  150. like.ThirtyDay = ltds
  151. case "f": //"收藏量"
  152. t, v, err := parseKeyValue(qual, val)
  153. if err != nil {
  154. break
  155. }
  156. td := &data.ThirtyDay{}
  157. td.DateKey = t
  158. td.TotalIncr = v
  159. ftds = append(ftds, td)
  160. fav.Category = "fav"
  161. fav.ThirtyDay = ftds
  162. case "c": //"投币量"
  163. t, v, err := parseKeyValue(qual, val)
  164. if err != nil {
  165. break
  166. }
  167. td := &data.ThirtyDay{}
  168. td.DateKey = t
  169. td.TotalIncr = v
  170. ctds = append(ctds, td)
  171. coin.Category = "coin"
  172. coin.ThirtyDay = ctds
  173. }
  174. }
  175. res = append(res, view)
  176. res = append(res, reply)
  177. res = append(res, like)
  178. res = append(res, fav)
  179. res = append(res, coin)
  180. return
  181. }
  182. func parseKeyValue(k string, v string) (timestamp, value int64, err error) {
  183. tm, err := time.Parse("20060102", k)
  184. if err != nil {
  185. log.Error("time.Parse error(%+v)", err)
  186. return
  187. }
  188. timestamp = tm.Unix()
  189. value, err = strconv.ParseInt(v, 10, 64)
  190. if err != nil {
  191. log.Error("strconv.ParseInt error(%+v)", err)
  192. }
  193. return
  194. }
  195. // SkyHorse sky horse
  196. func (d *Dao) SkyHorse(c context.Context, mid int64, build int, buvid string, plat int8, ps int) (res *model.SkyHorseResp, err error) {
  197. if buvid == "" {
  198. err = ecode.NothingFound
  199. return
  200. }
  201. params := url.Values{}
  202. params.Set("cmd", "article")
  203. params.Set("mid", strconv.FormatInt(mid, 10))
  204. params.Set("buvid", buvid)
  205. params.Set("build", strconv.Itoa(build))
  206. params.Set("plat", strconv.FormatInt(int64(plat), 10))
  207. params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
  208. params.Set("request_cnt", strconv.Itoa(ps))
  209. params.Set("from", "8")
  210. res = &model.SkyHorseResp{}
  211. err = d.httpClient.Get(c, d.c.Article.SkyHorseURL, "", params, &res)
  212. if err != nil {
  213. PromError("bigdata:天马接口")
  214. log.Error("bigdata: d.client.Get(%s) error(%+v)", d.c.Article.SkyHorseURL+"?"+params.Encode(), err)
  215. return
  216. }
  217. // -3: 数量不足
  218. if res.Code != 0 && res.Code != -3 {
  219. PromError("bigdata:天马接口")
  220. log.Error("bigdata: url(%s) res: %+v", d.c.Article.SkyHorseURL+"?"+params.Encode(), res)
  221. err = ecode.Int(res.Code)
  222. return
  223. }
  224. if len(res.Data) == 0 {
  225. PromError("bigdata:天马返回空")
  226. log.Warn("bigdata: url(%s) res: %+v", d.c.Article.SkyHorseURL+"?"+params.Encode(), res)
  227. }
  228. return
  229. }