redis.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. package dao
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "strconv"
  7. "strings"
  8. artmdl "go-common/app/interface/openplatform/article/model"
  9. "go-common/app/job/openplatform/article/model"
  10. "go-common/library/cache/redis"
  11. "go-common/library/log"
  12. )
  13. const (
  14. // view
  15. _viewPrefix = "v_"
  16. // retry stat
  17. _retryStatKey = "retry_stat"
  18. // RetryUpdateStatCache .
  19. RetryUpdateStatCache = 1
  20. // RetryUpdateStatDB .
  21. RetryUpdateStatDB = 2
  22. // RetryStatCount is retry upper limit.
  23. RetryStatCount = 10
  24. // retry cache
  25. _retryArtCacheKey = "retry_art_cache"
  26. _retryGameCacheKey = "artj_retry_game_cache"
  27. _retryFlowCacheKey = "artj_retry_flow_cache"
  28. _retryDynamicCacheKey = "artj_retry_dynamic_cache"
  29. // RetryAddArtCache .
  30. RetryAddArtCache = 1
  31. // RetryUpdateArtCache .
  32. RetryUpdateArtCache = 2
  33. // RetryDeleteArtCache .
  34. RetryDeleteArtCache = 3
  35. // RetryDeleteArtRecCache .
  36. RetryDeleteArtRecCache = 4
  37. // retry reply
  38. _retryReplyKey = "retry_reply"
  39. // retry purge cdn
  40. _retryCDNKey = "retry_cdn"
  41. _recheckArtKey = "recheck_lock_%d"
  42. // reading start set
  43. _readPingSet = "art:readping"
  44. // reading during on some device for some article
  45. _prefixReadPing = "art:readping:%s:%d"
  46. )
  47. // StatRetry .
  48. type StatRetry struct {
  49. Action int `json:"action"`
  50. Count int `json:"count"`
  51. Data *artmdl.StatMsg `json:"data"`
  52. }
  53. func viewKey(aid, mid int64, ip string) (key string) {
  54. if ip == "" {
  55. // let it pass if ip is empty.
  56. return
  57. }
  58. key = _viewPrefix + strconv.FormatInt(aid, 10) + ip
  59. if mid != 0 {
  60. key += strconv.FormatInt(mid, 10)
  61. }
  62. return
  63. }
  64. func dupViewKey(aid, mid int64) (key string) {
  65. return fmt.Sprintf("dv_%v_%v", aid, mid)
  66. }
  67. func recheckKey(aid int64) (key string) {
  68. return fmt.Sprintf(_recheckArtKey, aid)
  69. }
  70. // pingRedis checks redis healthy.
  71. func (d *Dao) pingRedis(c context.Context) (err error) {
  72. conn := d.redis.Get(c)
  73. defer conn.Close()
  74. if _, err = conn.Do("SET", "PING", "PONG"); err != nil {
  75. PromError("redis:Ping")
  76. log.Error("redis: conn.Do(SET,PING,PONG) error(%+v)", err)
  77. }
  78. return
  79. }
  80. // Intercept intercepts illegal views.
  81. func (d *Dao) Intercept(c context.Context, aid, mid int64, ip string) (ban bool) {
  82. var (
  83. err error
  84. exist bool
  85. key = viewKey(aid, mid, ip)
  86. conn = d.redis.Get(c)
  87. )
  88. defer conn.Close()
  89. if key == "" {
  90. return
  91. }
  92. if exist, err = redis.Bool(conn.Do("EXISTS", key)); err != nil {
  93. log.Error("conn.Do(EXISTS, %s) error(%+v)", key, err)
  94. PromError("redis:EXISTS阅读数")
  95. return
  96. }
  97. if exist {
  98. ban = true
  99. return
  100. }
  101. if err = conn.Send("SET", key, "1"); err != nil {
  102. log.Error("conn.Send(EXPIRE, %s) error(%+v)", key, err)
  103. PromError("redis:SET阅读数")
  104. return
  105. }
  106. if err = conn.Send("EXPIRE", key, d.viewCacheTTL); err != nil {
  107. log.Error("conn.Send(EXPIRE, %s) error(%+v)", key, err)
  108. PromError("redis:EXPIRE阅读数")
  109. return
  110. }
  111. if err = conn.Flush(); err != nil {
  112. log.Error("conn.Flush error(%+v)", err)
  113. PromError("redis:阅读数缓存Flush")
  114. return
  115. }
  116. for i := 0; i < 2; i++ {
  117. if _, err = conn.Receive(); err != nil {
  118. log.Error("conn.Receive() error(%+v)", err)
  119. PromError("redis:阅读数缓存Receive")
  120. return
  121. }
  122. }
  123. return
  124. }
  125. // DupViewIntercept intercepts illegal views.
  126. func (d *Dao) DupViewIntercept(c context.Context, aid, mid int64) (ban bool) {
  127. if mid == 0 {
  128. return
  129. }
  130. var (
  131. err error
  132. exist bool
  133. key = dupViewKey(aid, mid)
  134. conn = d.redis.Get(c)
  135. )
  136. defer conn.Close()
  137. if exist, err = redis.Bool(conn.Do("EXISTS", key)); err != nil {
  138. log.Error("conn.Do(EXISTS, %s) error(%+v)", key, err)
  139. PromError("redis:EXISTS连续阅读数")
  140. return
  141. }
  142. if exist {
  143. ban = true
  144. return
  145. }
  146. if err = conn.Send("SET", key, "1"); err != nil {
  147. log.Error("conn.Send(EXPIRE, %s) error(%+v)", key, err)
  148. PromError("redis:SET连续阅读数")
  149. return
  150. }
  151. if err = conn.Send("EXPIRE", key, d.dupViewCacheTTL); err != nil {
  152. log.Error("conn.Send(EXPIRE, %s) error(%+v)", key, err)
  153. PromError("redis:EXPIRE连续阅读数")
  154. return
  155. }
  156. if err = conn.Flush(); err != nil {
  157. log.Error("conn.Flush error(%+v)", err)
  158. PromError("redis:连续阅读数缓存Flush")
  159. return
  160. }
  161. for i := 0; i < 2; i++ {
  162. if _, err = conn.Receive(); err != nil {
  163. log.Error("conn.Receive() error(%+v)", err)
  164. PromError("redis:连续阅读数缓存Receive")
  165. return
  166. }
  167. }
  168. return
  169. }
  170. // PushStat pushs failed item to redis.
  171. func (d *Dao) PushStat(c context.Context, retry *StatRetry) (err error) {
  172. var (
  173. length int64
  174. bs []byte
  175. conn = d.redis.Get(c)
  176. )
  177. defer conn.Close()
  178. if length, err = redis.Int64(conn.Do("LLEN", _retryStatKey)); err != nil {
  179. log.Error("conn.Do(%s) error(%+v)", _retryStatKey, err)
  180. PromError("redis:计数重试LLEN")
  181. return
  182. }
  183. cacheLen.State("redis:retry_stat_length", length)
  184. if bs, err = json.Marshal(retry); err != nil {
  185. log.Error("json.Marshal(%v) error(%+v)", retry, err)
  186. PromError("redis:计数重试消息Marshal")
  187. return
  188. }
  189. if _, err = conn.Do("RPUSH", _retryStatKey, bs); err != nil {
  190. log.Error("conn.Do(RPUSH, %s) error(%+v)", bs, err)
  191. PromError("redis:计数重试RPUSH")
  192. }
  193. return
  194. }
  195. // PopStat pops failed item from redis.
  196. func (d *Dao) PopStat(c context.Context) (bs []byte, err error) {
  197. var conn = d.redis.Get(c)
  198. defer conn.Close()
  199. if bs, err = redis.Bytes(conn.Do("LPOP", _retryStatKey)); err != nil {
  200. if err == redis.ErrNil {
  201. err = nil
  202. return
  203. }
  204. log.Error("redis.Bytes(conn.Do(LPOP, %s)) error(%+v)", _retryStatKey, err)
  205. PromError("redis:计数重试LPOP")
  206. }
  207. return
  208. }
  209. // PushReply opens article's reply.
  210. func (d *Dao) PushReply(c context.Context, aid, mid int64) (err error) {
  211. var (
  212. length int64
  213. conn = d.redis.Get(c)
  214. bs = []byte(strconv.FormatInt(aid, 10) + "_" + strconv.FormatInt(mid, 10))
  215. )
  216. defer conn.Close()
  217. if length, err = redis.Int64(conn.Do("LLEN", _retryReplyKey)); err != nil {
  218. log.Error("conn.Do(%s) error(%+v)", _retryReplyKey, err)
  219. PromError("redis:打开评论重试LLEN")
  220. return
  221. }
  222. cacheLen.State("redis:retry_reply_length", length)
  223. if _, err = conn.Do("RPUSH", _retryReplyKey, bs); err != nil {
  224. log.Error("conn.Do(RPUSH, %s) error(%+v)", bs, err)
  225. PromError("redis:打开评论重试RPUSH")
  226. }
  227. return
  228. }
  229. // PopReply consume reply's job.
  230. func (d *Dao) PopReply(c context.Context) (aid, mid int64, err error) {
  231. var (
  232. conn = d.redis.Get(c)
  233. bs []byte
  234. v string
  235. arr []string
  236. )
  237. defer conn.Close()
  238. if bs, err = redis.Bytes(conn.Do("LPOP", _retryReplyKey)); err != nil {
  239. if err == redis.ErrNil {
  240. err = nil
  241. return
  242. }
  243. log.Error("redis.Bytes(conn.Do(LPOP, %s)) error(%+v)", _retryReplyKey, err)
  244. PromError("redis:打开评论重试LPOP")
  245. return
  246. }
  247. if v = string(bs); v == "" {
  248. return
  249. }
  250. if arr = strings.Split(v, "_"); len(arr) < 2 {
  251. log.Error("reply retry param error (%s)", v)
  252. PromError("redis:打开评论重试消息内容错误")
  253. return
  254. }
  255. aid, _ = strconv.ParseInt(arr[0], 10, 64)
  256. mid, _ = strconv.ParseInt(arr[1], 10, 64)
  257. return
  258. }
  259. // PushCDN .
  260. func (d *Dao) PushCDN(c context.Context, file string) (err error) {
  261. var (
  262. length int64
  263. conn = d.redis.Get(c)
  264. bs = []byte(file)
  265. )
  266. defer conn.Close()
  267. if length, err = redis.Int64(conn.Do("LLEN", _retryCDNKey)); err != nil {
  268. log.Error("conn.Do(%s) error(%+v)", _retryCDNKey, err)
  269. PromError("redis:重试刷新CDN LLEN")
  270. return
  271. }
  272. cacheLen.State("redis:retry_cdn_length", length)
  273. if _, err = conn.Do("RPUSH", _retryCDNKey, bs); err != nil {
  274. log.Error("conn.Do(RPUSH, %s) error(%+v)", bs, err)
  275. PromError("redis:重试刷新CDN RPUSH")
  276. }
  277. return
  278. }
  279. // PopCDN .
  280. func (d *Dao) PopCDN(c context.Context) (file string, err error) {
  281. var (
  282. conn = d.redis.Get(c)
  283. bs []byte
  284. )
  285. defer conn.Close()
  286. if bs, err = redis.Bytes(conn.Do("LPOP", _retryCDNKey)); err != nil {
  287. if err == redis.ErrNil {
  288. err = nil
  289. return
  290. }
  291. log.Error("redis.Bytes(conn.Do(LPOP, %s)) error(%+v)", _retryCDNKey, err)
  292. PromError("redis:重试刷新CDN LPOP")
  293. return
  294. }
  295. file = string(bs)
  296. return
  297. }
  298. // CacheRetry struct of retry cache info.
  299. type CacheRetry struct {
  300. Action int `json:"action"`
  301. Aid int64 `json:"aid"`
  302. Mid int64 `json:"mid"`
  303. Cid int64 `json:"cid"`
  304. }
  305. // PushArtCache .
  306. func (d *Dao) PushArtCache(c context.Context, info *CacheRetry) (err error) {
  307. var (
  308. length int64
  309. bs []byte
  310. conn = d.redis.Get(c)
  311. )
  312. defer conn.Close()
  313. if length, err = redis.Int64(conn.Do("LLEN", _retryArtCacheKey)); err != nil {
  314. log.Error("conn.Do(%s) error(%+v)", _retryArtCacheKey, err)
  315. PromError("redis:重试文章缓存LLEN")
  316. return
  317. }
  318. cacheLen.State("redis:retry_art_cache_length", length)
  319. if bs, err = json.Marshal(info); err != nil {
  320. log.Error("json.Marshal(%v) error(%+v)", info, err)
  321. PromError("redis:重试文章缓存Marshal")
  322. return
  323. }
  324. if _, err = conn.Do("RPUSH", _retryArtCacheKey, bs); err != nil {
  325. log.Error("conn.Do(RPUSH, %s) error(%+v)", bs, err)
  326. PromError("redis:重试文章缓存RPUSH")
  327. }
  328. return
  329. }
  330. // PopArtCache .
  331. func (d *Dao) PopArtCache(c context.Context) (bs []byte, err error) {
  332. var conn = d.redis.Get(c)
  333. defer conn.Close()
  334. if bs, err = redis.Bytes(conn.Do("LPOP", _retryArtCacheKey)); err != nil {
  335. if err == redis.ErrNil {
  336. err = nil
  337. return
  338. }
  339. log.Error("redis.Bytes(conn.Do(LPOP, %s)) error(%+v)", _retryArtCacheKey, err)
  340. PromError("redis:重试文章缓存LPOP")
  341. }
  342. return
  343. }
  344. // PushGameCache .
  345. func (d *Dao) PushGameCache(c context.Context, info *model.GameCacheRetry) (err error) {
  346. var (
  347. length int64
  348. bs []byte
  349. conn = d.redis.Get(c)
  350. )
  351. defer conn.Close()
  352. if length, err = redis.Int64(conn.Do("LLEN", _retryGameCacheKey)); err != nil {
  353. log.Error("conn.Do(%s) error(%+v)", _retryGameCacheKey, err)
  354. PromError("redis:重试游戏缓存LLEN")
  355. return
  356. }
  357. cacheLen.State("redis:retry_game_cache_length", length)
  358. if bs, err = json.Marshal(info); err != nil {
  359. log.Error("json.Marshal(%v) error(%+v)", info, err)
  360. PromError("redis:重试游戏缓存Marshal")
  361. return
  362. }
  363. if _, err = conn.Do("RPUSH", _retryGameCacheKey, bs); err != nil {
  364. log.Error("conn.Do(RPUSH, %s) error(%+v)", bs, err)
  365. PromError("redis:重试游戏缓存RPUSH")
  366. }
  367. return
  368. }
  369. // PopGameCache .
  370. func (d *Dao) PopGameCache(c context.Context) (res *model.GameCacheRetry, err error) {
  371. var conn = d.redis.Get(c)
  372. defer conn.Close()
  373. var bs []byte
  374. if bs, err = redis.Bytes(conn.Do("LPOP", _retryGameCacheKey)); err != nil {
  375. if err == redis.ErrNil {
  376. err = nil
  377. return
  378. }
  379. log.Error("redis.Bytes(conn.Do(LPOP, %s)) error(%+v)", _retryGameCacheKey, err)
  380. PromError("redis:重试游戏缓存LPOP")
  381. return
  382. }
  383. res = new(model.GameCacheRetry)
  384. if err = json.Unmarshal(bs, res); err != nil {
  385. log.Error("redis.Unmarshal(%s) error(%+v)", bs, err)
  386. PromError("redis:解析游戏缓存")
  387. }
  388. return
  389. }
  390. // PushFlowCache .
  391. func (d *Dao) PushFlowCache(c context.Context, info *model.FlowCacheRetry) (err error) {
  392. var (
  393. length int64
  394. bs []byte
  395. conn = d.redis.Get(c)
  396. )
  397. defer conn.Close()
  398. if length, err = redis.Int64(conn.Do("LLEN", _retryFlowCacheKey)); err != nil {
  399. log.Error("conn.Do(%s) error(%+v)", _retryFlowCacheKey, err)
  400. PromError("redis:重试flow缓存LLEN")
  401. return
  402. }
  403. cacheLen.State("redis:retry_flow_cache_length", length)
  404. if bs, err = json.Marshal(info); err != nil {
  405. log.Error("json.Marshal(%v) error(%+v)", info, err)
  406. PromError("redis:重试flow缓存Marshal")
  407. return
  408. }
  409. if _, err = conn.Do("RPUSH", _retryFlowCacheKey, bs); err != nil {
  410. log.Error("conn.Do(RPUSH, %s) error(%+v)", bs, err)
  411. PromError("redis:重试flow缓存RPUSH")
  412. }
  413. return
  414. }
  415. // PopFlowCache .
  416. func (d *Dao) PopFlowCache(c context.Context) (res *model.FlowCacheRetry, err error) {
  417. var conn = d.redis.Get(c)
  418. defer conn.Close()
  419. var bs []byte
  420. if bs, err = redis.Bytes(conn.Do("LPOP", _retryFlowCacheKey)); err != nil {
  421. if err == redis.ErrNil {
  422. err = nil
  423. return
  424. }
  425. log.Error("redis.Bytes(conn.Do(LPOP, %s)) error(%+v)", _retryFlowCacheKey, err)
  426. PromError("redis:重试flow缓存LPOP")
  427. return
  428. }
  429. res = new(model.FlowCacheRetry)
  430. if err = json.Unmarshal(bs, res); err != nil {
  431. log.Error("redis.Unmarshal(%s) error(%+v)", bs, err)
  432. PromError("redis:解析flow缓存")
  433. }
  434. return
  435. }
  436. // PushDynamicCache put dynamic to redis
  437. func (d *Dao) PushDynamicCache(c context.Context, info *model.DynamicCacheRetry) (err error) {
  438. var (
  439. length int64
  440. bs []byte
  441. conn = d.redis.Get(c)
  442. )
  443. defer conn.Close()
  444. if length, err = redis.Int64(conn.Do("LLEN", _retryDynamicCacheKey)); err != nil {
  445. log.Error("conn.Do(%s) error(%+v)", _retryDynamicCacheKey, err)
  446. PromError("redis:重试dynamic缓存LLEN")
  447. return
  448. }
  449. cacheLen.State("redis:retry_dynamic_cache_length", length)
  450. if bs, err = json.Marshal(info); err != nil {
  451. log.Error("json.Marshal(%v) error(%+v)", info, err)
  452. PromError("redis:重试dynamic缓存Marshal")
  453. return
  454. }
  455. if _, err = conn.Do("RPUSH", _retryDynamicCacheKey, bs); err != nil {
  456. log.Error("conn.Do(RPUSH, %s) error(%+v)", bs, err)
  457. PromError("redis:重试dynamic缓存RPUSH")
  458. }
  459. return
  460. }
  461. // PopDynamicCache .
  462. func (d *Dao) PopDynamicCache(c context.Context) (res *model.DynamicCacheRetry, err error) {
  463. var conn = d.redis.Get(c)
  464. defer conn.Close()
  465. var bs []byte
  466. if bs, err = redis.Bytes(conn.Do("LPOP", _retryDynamicCacheKey)); err != nil {
  467. if err == redis.ErrNil {
  468. err = nil
  469. return
  470. }
  471. log.Error("redis.Bytes(conn.Do(LPOP, %s)) error(%+v)", _retryDynamicCacheKey, err)
  472. PromError("redis:重试dynamic缓存LPOP")
  473. return
  474. }
  475. res = new(model.DynamicCacheRetry)
  476. if err = json.Unmarshal(bs, res); err != nil {
  477. log.Error("redis.Unmarshal(%s) error(%+v)", bs, err)
  478. PromError("redis:解析dynamic缓存")
  479. }
  480. return
  481. }
  482. // GetRecheckCache get recheck info from redis
  483. func (d *Dao) GetRecheckCache(c context.Context, aid int64) (isRecheck bool, err error) {
  484. var conn = d.redis.Get(c)
  485. defer conn.Close()
  486. key := recheckKey(aid)
  487. if isRecheck, err = redis.Bool(conn.Do("GET", key)); err != nil {
  488. if err == redis.ErrNil {
  489. err = nil
  490. return
  491. }
  492. log.Error("redis.BOOL(conn.Do(GET, %s)) error(%+v)", key, err)
  493. PromError("redis:获取回查缓存")
  494. return
  495. }
  496. return
  497. }
  498. // SetRecheckCache set recheck info to redis
  499. func (d *Dao) SetRecheckCache(c context.Context, aid int64) (isRecheck bool, err error) {
  500. var conn = d.redis.Get(c)
  501. defer conn.Close()
  502. key := recheckKey(aid)
  503. if _, err = conn.Do("SETEX", key, 604800, true); err != nil {
  504. log.Error("redis.BOOL(conn.Do(SETEX, %s)) error(%+v)", key, err)
  505. PromError("redis:设置回查缓存")
  506. return
  507. }
  508. return
  509. }
  510. func readPingSetKey() string {
  511. return _readPingSet
  512. }
  513. func readPingKey(buvid string, aid int64) string {
  514. return fmt.Sprintf(_prefixReadPing, buvid, aid)
  515. }
  516. // ReadPingSet 获取所有阅读记录(不删除)
  517. func (d *Dao) ReadPingSet(c context.Context) (res []*model.Read, err error) {
  518. var (
  519. key = readPingSetKey()
  520. conn = d.artRedis.Get(c)
  521. tmpRes []string
  522. tmpArr []string
  523. )
  524. defer conn.Close()
  525. if err = conn.Send("SMEMBERS", key); err != nil {
  526. log.Error("conn.Send(SMEMBERS, %s) error(%+v)", key, err)
  527. return
  528. }
  529. if err = conn.Flush(); err != nil {
  530. log.Error("conn.Flush error(%+v)", err)
  531. return
  532. }
  533. if tmpRes, err = redis.Strings(conn.Receive()); err != nil {
  534. log.Error("conn.Receive error(%+v)", err)
  535. return
  536. }
  537. for _, tmp := range tmpRes {
  538. tmpArr = strings.Split(tmp, "|")
  539. if len(tmpArr) != 6 {
  540. log.Error("redis key(%s)存在脏数据(%s)", key, tmp)
  541. if _, err = conn.Do("SREM", key, tmp); err != nil {
  542. log.Error("d.Redis.SREM error(%+v), set(%s), key(%s)", err, key, tmp)
  543. }
  544. continue
  545. }
  546. read := &model.Read{
  547. Buvid: tmpArr[0],
  548. EndTime: 0,
  549. }
  550. read.Aid, _ = strconv.ParseInt(tmpArr[1], 10, 64)
  551. read.Mid, _ = strconv.ParseInt(tmpArr[2], 10, 64)
  552. read.IP = tmpArr[3]
  553. read.StartTime, _ = strconv.ParseInt(tmpArr[4], 10, 64)
  554. read.From = tmpArr[5]
  555. res = append(res, read)
  556. }
  557. return
  558. }
  559. // ReadPing 获取上次阅读心跳时间,不存在则返回0
  560. func (d *Dao) ReadPing(c context.Context, buvid string, aid int64) (last int64, err error) {
  561. var (
  562. key = readPingKey(buvid, aid)
  563. conn = d.artRedis.Get(c)
  564. )
  565. defer conn.Close()
  566. if last, err = redis.Int64(conn.Do("GET", key)); err != nil && err != redis.ErrNil {
  567. log.Error("conn.Do(GET, %s) error(%+v)", key, err)
  568. return
  569. }
  570. err = nil
  571. return
  572. }
  573. // DelReadPingSet 删除阅读记录缓存
  574. func (d *Dao) DelReadPingSet(c context.Context, read *model.Read) (err error) {
  575. if read == nil {
  576. return
  577. }
  578. var (
  579. elemKey = readPingKey(read.Buvid, read.Aid)
  580. setKey = readPingSetKey()
  581. value = fmt.Sprintf("%s|%d|%d|%s|%d|%s", read.Buvid, read.Aid, read.Mid, read.IP, read.StartTime, read.From)
  582. conn = d.artRedis.Get(c)
  583. )
  584. defer conn.Close()
  585. if _, err = conn.Do("DEL", elemKey); err != nil {
  586. log.Error("conn.Do(DEL, %s) error(%+v)", elemKey, err)
  587. return
  588. }
  589. if _, err = conn.Do("SREM", setKey, value); err != nil {
  590. log.Error("conn.Do(SREM, %s, %s) error(%+v)", setKey, value, err)
  591. return
  592. }
  593. return
  594. }