memcache.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. package dao
  2. import (
  3. "context"
  4. "fmt"
  5. "go-common/app/service/main/favorite/model"
  6. "go-common/library/cache/memcache"
  7. "go-common/library/log"
  8. "go-common/library/xstr"
  9. "strconv"
  10. )
  11. const (
  12. _oldFolder = "f_%d_%d_%d" // key:f_{type}_{mid}_{fid},value:{*Fodler}.pb
  13. _folder = "f_%d_%d" // key:f_{mid%100}_{fid},value:{*Fodler}.pb
  14. _folderStat = "ft_%d_%d" // key:f_{mid%100}_{fid},value:{*FodlerStat}.pb
  15. _folderSort = "fst_%d_%d" // key:f_{type}_{mid},value:{fid,fid,fid...}.binary
  16. _relationFids = "rof_%d_%d_%d" // key:rof_{type}_{mid}_{oid},value:{[]int64}.pb
  17. _oidCount = "oc_%d_%d" // key:oc_{type}_{oid},value:int64
  18. _batchOids = "bo_%d_%d" // key:oc_{type}_{mid},value:{[]int64}.pb
  19. _recentOids = "rcto_%d_%d" // key:rcto_{type}_{mid},value:{[]int64}.pb
  20. _recentRes = "rctr_%d_%d" // key:rcto_{type}_{mid},value:{[]*Resource}.pb
  21. )
  22. func folderMcKey(mid, fid int64) string {
  23. return fmt.Sprintf(_folder, mid%100, fid)
  24. }
  25. func folderStatMcKey(mid, fid int64) string {
  26. return fmt.Sprintf(_folderStat, mid%100, fid)
  27. }
  28. func fsortMcKey(typ int8, mid int64) string {
  29. return fmt.Sprintf(_folderSort, typ, mid)
  30. }
  31. func relationFidsKey(typ int8, mid, oid int64) string {
  32. return fmt.Sprintf(_relationFids, typ, mid, oid)
  33. }
  34. func oidCountKey(typ int8, oid int64) string {
  35. return fmt.Sprintf(_oidCount, typ, oid)
  36. }
  37. func batchOidsKey(typ int8, mid int64) string {
  38. return fmt.Sprintf(_batchOids, typ, mid)
  39. }
  40. func recentOidsKey(typ int8, mid int64) string {
  41. return fmt.Sprintf(_recentOids, typ, mid)
  42. }
  43. func recentResKey(typ int8, mid int64) string {
  44. return fmt.Sprintf(_recentRes, typ, mid)
  45. }
  46. // pingMC ping mc is ok.
  47. func (d *Dao) pingMC(c context.Context) error {
  48. conn := d.mc.Get(c)
  49. defer conn.Close()
  50. item := memcache.Item{Key: "ping", Value: []byte{1}, Expiration: d.mcExpire}
  51. return conn.Set(&item)
  52. }
  53. // FolderStatsMc return folders stat by mid & fid from mc.
  54. func (d *Dao) FolderStatsMc(c context.Context, fvmids []*model.ArgFVmid) (fs map[int64]*model.Folder, missFvmids []*model.ArgFVmid, err error) {
  55. var (
  56. keys = make([]string, 0, len(fvmids))
  57. keysMap = make(map[string]*model.ArgFVmid, len(fvmids))
  58. )
  59. for _, v := range fvmids {
  60. key := folderStatMcKey(v.Vmid, v.Fid)
  61. keys = append(keys, key)
  62. keysMap[key] = v
  63. }
  64. conn := d.mc.Get(c)
  65. defer conn.Close()
  66. items, err := conn.GetMulti(keys)
  67. if err != nil {
  68. log.Error("conn.GetMulti(%v) error(%v)", keys, err)
  69. return
  70. }
  71. fs = make(map[int64]*model.Folder, len(items))
  72. for _, item := range items {
  73. stat := new(model.Folder)
  74. if err = conn.Scan(item, stat); err != nil {
  75. log.Error("conn.Scan(%s) error(%v)", item.Value, err)
  76. return
  77. }
  78. fs[keysMap[item.Key].MediaID()] = stat
  79. delete(keysMap, item.Key)
  80. }
  81. for _, v := range keysMap {
  82. missFvmids = append(missFvmids, v)
  83. }
  84. return
  85. }
  86. // SetFoldersMc add folders mc cache.
  87. func (d *Dao) SetFoldersMc(c context.Context, vs ...*model.Folder) (err error) {
  88. if len(vs) == 0 {
  89. return
  90. }
  91. conn := d.mc.Get(c)
  92. defer conn.Close()
  93. for _, v := range vs {
  94. if v == nil {
  95. continue
  96. }
  97. item := &memcache.Item{Key: folderMcKey(v.Mid, v.ID), Object: v, Flags: memcache.FlagProtobuf, Expiration: d.mcExpire}
  98. if err = conn.Set(item); err != nil {
  99. log.Error("conn.Set(%s) error(%v)", folderMcKey(v.Mid, v.ID), err)
  100. return
  101. }
  102. }
  103. return
  104. }
  105. // SetFolderStatsMc add folders mc cache.
  106. func (d *Dao) SetFolderStatsMc(c context.Context, stats map[int64]*model.Folder) (err error) {
  107. if len(stats) == 0 {
  108. return
  109. }
  110. conn := d.mc.Get(c)
  111. defer conn.Close()
  112. for k, v := range stats {
  113. if v == nil {
  114. continue
  115. }
  116. item := &memcache.Item{Key: folderStatMcKey(k%100, k/100), Object: v, Flags: memcache.FlagProtobuf, Expiration: d.mcExpire}
  117. if err = conn.Set(item); err != nil {
  118. log.Error("conn.Set(%s) error(%v)", folderStatMcKey(k%100, k/100), err)
  119. return
  120. }
  121. }
  122. return
  123. }
  124. // FoldersMc return folders by mid & fid from mc.
  125. func (d *Dao) FoldersMc(c context.Context, fvmids []*model.ArgFVmid) (fs map[string]*model.Folder, missFvmids []*model.ArgFVmid, err error) {
  126. var (
  127. keys = make([]string, 0, len(fvmids))
  128. keysMap = make(map[string]*model.ArgFVmid, len(fvmids))
  129. )
  130. for _, v := range fvmids {
  131. key := folderMcKey(v.Vmid, v.Fid)
  132. keys = append(keys, key)
  133. keysMap[key] = v
  134. }
  135. conn := d.mc.Get(c)
  136. defer conn.Close()
  137. items, err := conn.GetMulti(keys)
  138. if err != nil {
  139. log.Error("conn.GetMulti(%v) error(%v)", keys, err)
  140. return
  141. }
  142. fs = make(map[string]*model.Folder, len(items))
  143. for _, item := range items {
  144. folder := new(model.Folder)
  145. if err = conn.Scan(item, folder); err != nil {
  146. log.Error("conn.Scan(%s) error(%v)", item.Value, err)
  147. return
  148. }
  149. delete(keysMap, item.Key)
  150. fvmidStr := xstr.JoinInts([]int64{folder.ID, folder.Mid})
  151. fs[fvmidStr] = folder
  152. }
  153. for _, v := range keysMap {
  154. missFvmids = append(missFvmids, v)
  155. }
  156. return
  157. }
  158. // FolderMc return folder pb from mc.
  159. func (d *Dao) FolderMc(c context.Context, typ int8, mid, fid int64) (f *model.Folder, err error) {
  160. var (
  161. key = folderMcKey(mid, fid)
  162. item *memcache.Item
  163. conn = d.mc.Get(c)
  164. )
  165. defer conn.Close()
  166. if item, err = conn.Get(key); err != nil {
  167. if err == memcache.ErrNotFound {
  168. err = nil
  169. } else {
  170. log.Error("memcache.Get(%s) error(%v)", key, err)
  171. }
  172. return
  173. }
  174. f = new(model.Folder)
  175. if err = conn.Scan(item, f); err != nil {
  176. log.Error("conn.Scan(%s) error(%v)", item.Value, err)
  177. f = nil
  178. }
  179. return
  180. }
  181. // DelFolderMc delete folder mc cache.
  182. func (d *Dao) DelFolderMc(c context.Context, typ int8, mid, fid int64) (err error) {
  183. var (
  184. key = folderMcKey(mid, fid)
  185. conn = d.mc.Get(c)
  186. )
  187. defer conn.Close()
  188. if err = conn.Delete(key); err != nil {
  189. if err == memcache.ErrNotFound {
  190. err = nil
  191. } else {
  192. log.Error("conn.Delete(%s) error(%v)", key, err)
  193. }
  194. }
  195. return
  196. }
  197. // SetFolderSortMc set folder's sort binary data to mc.
  198. func (d *Dao) SetFolderSortMc(c context.Context, fst *model.FolderSort) (err error) {
  199. key := fsortMcKey(fst.Type, fst.Mid)
  200. conn := d.mc.Get(c)
  201. defer conn.Close()
  202. sortBin := fst.Index()
  203. item := &memcache.Item{
  204. Key: key,
  205. Value: sortBin,
  206. Expiration: d.mcExpire,
  207. }
  208. if err = conn.Set(item); err != nil {
  209. log.Error("conn.Set(%s) error(%v)", key, err)
  210. return
  211. }
  212. return
  213. }
  214. // FolderSortMc return folder sort binary from mc.
  215. func (d *Dao) FolderSortMc(c context.Context, typ int8, mid int64) (fst *model.FolderSort, err error) {
  216. var (
  217. key = fsortMcKey(typ, mid)
  218. item *memcache.Item
  219. b []byte
  220. conn = d.mc.Get(c)
  221. )
  222. defer conn.Close()
  223. if item, err = conn.Get(key); err != nil {
  224. if err == memcache.ErrNotFound {
  225. err = nil
  226. } else {
  227. log.Error("memcache.Get(%s) error(%v)", key, err)
  228. }
  229. return
  230. }
  231. if err = conn.Scan(item, &b); err != nil {
  232. log.Error("conn.Scan(%s) error(%v)", item.Value, err)
  233. fst = nil
  234. return
  235. }
  236. fst = &model.FolderSort{Type: typ, Mid: mid}
  237. if err = fst.SetIndex(b); err != nil {
  238. log.Error("fs.SetIndex(%v) error(%v)", b, err)
  239. err = nil
  240. fst = nil
  241. }
  242. return
  243. }
  244. // DelFolderSortMc delete folder's sort mc cache.
  245. func (d *Dao) DelFolderSortMc(c context.Context, typ int8, mid int64) (err error) {
  246. var (
  247. key = fsortMcKey(typ, mid)
  248. conn = d.mc.Get(c)
  249. )
  250. defer conn.Close()
  251. if err = conn.Delete(key); err != nil {
  252. if err == memcache.ErrNotFound {
  253. err = nil
  254. } else {
  255. log.Error("conn.Delete(%s) error(%v)", key, err)
  256. }
  257. }
  258. return
  259. }
  260. // SetRelaitonFidsMc set fids binary data to mc.
  261. func (d *Dao) SetRelaitonFidsMc(c context.Context, typ int8, mid, oid int64, fids []int64) (err error) {
  262. key := relationFidsKey(typ, mid, oid)
  263. conn := d.mc.Get(c)
  264. defer conn.Close()
  265. bytes := model.ToBytes(fids)
  266. item := &memcache.Item{Key: key, Value: bytes, Flags: memcache.FlagRAW, Expiration: d.mcExpire}
  267. if err = conn.Set(item); err != nil {
  268. log.Error("conn.Set(%s) error(%v)", key, err)
  269. return
  270. }
  271. return
  272. }
  273. // RelaitonFidsMc return fids from mc.
  274. func (d *Dao) RelaitonFidsMc(c context.Context, typ int8, mid, oid int64) (fids []int64, err error) {
  275. var (
  276. key = relationFidsKey(typ, mid, oid)
  277. item *memcache.Item
  278. conn = d.mc.Get(c)
  279. b []byte
  280. )
  281. defer conn.Close()
  282. if item, err = conn.Get(key); err != nil {
  283. if err == memcache.ErrNotFound {
  284. err = nil
  285. } else {
  286. log.Error("memcache.Get(%s) error(%v)", key, err)
  287. }
  288. return
  289. }
  290. if err = conn.Scan(item, &b); err != nil {
  291. log.Error("conn.Scan(%s) error(%v)", item.Value, err)
  292. fids = nil
  293. return
  294. }
  295. if fids, err = model.ToInt64s(b); err != nil {
  296. log.Error("fs.SetIndex(%v) error(%v)", b, err)
  297. err = nil
  298. fids = nil
  299. }
  300. return
  301. }
  302. // DelRelationFidsMc delete oid's fid mc cache.
  303. func (d *Dao) DelRelationFidsMc(c context.Context, typ int8, mid int64, oids ...int64) (err error) {
  304. conn := d.mc.Get(c)
  305. defer conn.Close()
  306. for _, oid := range oids {
  307. key := relationFidsKey(typ, mid, oid)
  308. if err = conn.Delete(key); err != nil {
  309. if err == memcache.ErrNotFound {
  310. err = nil
  311. } else {
  312. log.Error("conn.Delete(%s) error(%v)", key, err)
  313. }
  314. }
  315. }
  316. return
  317. }
  318. // SetOidCountMc set oid count to mc.
  319. func (d *Dao) SetOidCountMc(c context.Context, typ int8, oid, count int64) (err error) {
  320. var (
  321. key = oidCountKey(typ, oid)
  322. conn = d.mc.Get(c)
  323. )
  324. defer conn.Close()
  325. bs := []byte(strconv.FormatInt(int64(count), 10))
  326. item := &memcache.Item{Key: key, Value: bs, Flags: memcache.FlagRAW, Expiration: d.mcExpire}
  327. if err = conn.Set(item); err != nil {
  328. log.Error("conn.Set(%s) error(%v)", key, err)
  329. return
  330. }
  331. return
  332. }
  333. // OidCountMc return oid count from mc.
  334. func (d *Dao) OidCountMc(c context.Context, typ int8, oid int64) (count int64, err error) {
  335. var (
  336. key = oidCountKey(typ, oid)
  337. item *memcache.Item
  338. conn = d.mc.Get(c)
  339. )
  340. defer conn.Close()
  341. if item, err = conn.Get(key); err != nil {
  342. if err == memcache.ErrNotFound {
  343. err = nil
  344. } else {
  345. log.Error("memcache.Get(%s) error(%v)", key, err)
  346. }
  347. return
  348. }
  349. var v string
  350. if err = conn.Scan(item, &v); err != nil {
  351. log.Error("conn.Scan(%s) error(%v)", item.Value, err)
  352. return
  353. }
  354. count, err = strconv.ParseInt(v, 10, 64)
  355. return
  356. }
  357. // OidsCountMc return oids's count from mc.
  358. func (d *Dao) OidsCountMc(c context.Context, typ int8, oids []int64) (counts map[int64]int64, misOids []int64, err error) {
  359. var (
  360. keys = make([]string, 0, len(oids))
  361. keysMap = make(map[string]int64, len(oids))
  362. )
  363. for _, oid := range oids {
  364. key := oidCountKey(typ, oid)
  365. keys = append(keys, key)
  366. keysMap[key] = oid
  367. }
  368. conn := d.mc.Get(c)
  369. defer conn.Close()
  370. items, err := conn.GetMulti(keys)
  371. if err != nil {
  372. log.Error("conn.GetMulti(%v) error(%v)", keys, err)
  373. return
  374. }
  375. counts = make(map[int64]int64, len(items))
  376. for _, item := range items {
  377. var v string
  378. if err = conn.Scan(item, &v); err != nil {
  379. log.Error("conn.Scan(%s) error(%v)", item.Value, err)
  380. return
  381. }
  382. var cnt int64
  383. if cnt, err = strconv.ParseInt(v, 10, 64); err != nil {
  384. log.Error("strconv.ParseInt(%s) error(%v)", v, err)
  385. return
  386. }
  387. counts[keysMap[item.Key]] = cnt
  388. delete(keysMap, item.Key)
  389. }
  390. for _, v := range keysMap {
  391. misOids = append(misOids, v)
  392. }
  393. return
  394. }
  395. // SetOidsCountMc set oids count to mc.
  396. func (d *Dao) SetOidsCountMc(c context.Context, typ int8, cnts map[int64]int64) (err error) {
  397. conn := d.mc.Get(c)
  398. defer conn.Close()
  399. for oid, cnt := range cnts {
  400. bs := []byte(strconv.FormatInt(int64(cnt), 10))
  401. item := &memcache.Item{Key: oidCountKey(typ, oid), Object: bs, Flags: memcache.FlagRAW, Expiration: d.mcExpire}
  402. if err = conn.Set(item); err != nil {
  403. log.Error("conn.Set(%s) error(%v)", oidCountKey(typ, oid), err)
  404. return
  405. }
  406. }
  407. return
  408. }
  409. // BatchOidsMc return oids from mc.
  410. func (d *Dao) BatchOidsMc(c context.Context, typ int8, mid int64) (oids []int64, err error) {
  411. var (
  412. key = batchOidsKey(typ, mid)
  413. item *memcache.Item
  414. conn = d.mc.Get(c)
  415. b []byte
  416. )
  417. defer conn.Close()
  418. if item, err = conn.Get(key); err != nil {
  419. if err == memcache.ErrNotFound {
  420. err = nil
  421. } else {
  422. log.Error("memcache.Get(%s) error(%v)", key, err)
  423. }
  424. return
  425. }
  426. if err = conn.Scan(item, &b); err != nil {
  427. log.Error("conn.Scan(%s) error(%v)", item.Value, err)
  428. return
  429. }
  430. if oids, err = model.ToInt64s(b); err != nil {
  431. log.Error("fs.SetIndex(%v) error(%v)", b, err)
  432. }
  433. return
  434. }
  435. // SetBatchOidsMc set oids binary data to mc.
  436. func (d *Dao) SetBatchOidsMc(c context.Context, typ int8, mid int64, oids []int64) (err error) {
  437. key := batchOidsKey(typ, mid)
  438. conn := d.mc.Get(c)
  439. defer conn.Close()
  440. bytes := model.ToBytes(oids)
  441. item := &memcache.Item{Key: key, Value: bytes, Flags: memcache.FlagRAW, Expiration: d.mcExpire}
  442. if err = conn.Set(item); err != nil {
  443. log.Error("conn.Set(%s) error(%v)", key, err)
  444. return
  445. }
  446. return
  447. }
  448. // UserRecentOidsMc return oids from mc.
  449. func (d *Dao) UserRecentOidsMc(c context.Context, typ int8, mid int64) (oids []int64, err error) {
  450. var (
  451. key = recentOidsKey(typ, mid)
  452. item *memcache.Item
  453. conn = d.mc.Get(c)
  454. b []byte
  455. )
  456. defer conn.Close()
  457. if item, err = conn.Get(key); err != nil {
  458. if err == memcache.ErrNotFound {
  459. err = nil
  460. } else {
  461. log.Error("memcache.Get(%s) error(%v)", key, err)
  462. }
  463. return
  464. }
  465. if err = conn.Scan(item, &b); err != nil {
  466. log.Error("conn.Scan(%s) error(%v)", item.Value, err)
  467. return
  468. }
  469. if oids, err = model.ToInt64s(b); err != nil {
  470. log.Error("fs.SetIndex(%v) error(%v)", b, err)
  471. }
  472. return
  473. }
  474. // SetUserRecentOidsMc set oids binary data to mc.
  475. func (d *Dao) SetUserRecentOidsMc(c context.Context, typ int8, mid int64, oids []int64) (err error) {
  476. key := recentOidsKey(typ, mid)
  477. conn := d.mc.Get(c)
  478. defer conn.Close()
  479. bytes := model.ToBytes(oids)
  480. item := &memcache.Item{Key: key, Value: bytes, Flags: memcache.FlagRAW, Expiration: d.mcExpire}
  481. if err = conn.Set(item); err != nil {
  482. log.Error("conn.Set(%s) error(%v)", key, err)
  483. return
  484. }
  485. return
  486. }
  487. // SetUserRecentOidsMc set oids binary data to mc.
  488. func (d *Dao) SetUserRecentResourcesMc(c context.Context, typ int8, mid int64, recents []*model.Resource) (err error) {
  489. key := recentResKey(typ, mid)
  490. conn := d.mc.Get(c)
  491. defer conn.Close()
  492. item := &memcache.Item{Key: key, Object: recents, Flags: memcache.FlagJSON, Expiration: d.mcExpire}
  493. if err = conn.Set(item); err != nil {
  494. log.Error("conn.Set(%s) error(%v)", key, err)
  495. return
  496. }
  497. return
  498. }
  499. // UserRecentOidsMc return oids from mc.
  500. func (d *Dao) UserRecentResourcesMc(c context.Context, typ int8, mid int64) (recents []*model.Resource, err error) {
  501. var (
  502. key = recentResKey(typ, mid)
  503. item *memcache.Item
  504. conn = d.mc.Get(c)
  505. )
  506. defer conn.Close()
  507. if item, err = conn.Get(key); err != nil {
  508. if err == memcache.ErrNotFound {
  509. err = nil
  510. } else {
  511. log.Error("memcache.Get(%s) error(%v)", key, err)
  512. }
  513. return
  514. }
  515. recents = make([]*model.Resource, 0)
  516. if err = conn.Scan(item, &recents); err != nil {
  517. log.Error("conn.Scan(%s) error(%v)", item.Value, err)
  518. return
  519. }
  520. return
  521. }
  522. // DelRecentResMc delete recent oids mc cache.
  523. func (d *Dao) DelRecentResMc(c context.Context, typ int8, mid int64) (err error) {
  524. key := recentResKey(typ, mid)
  525. conn := d.mc.Get(c)
  526. defer conn.Close()
  527. if err = conn.Delete(key); err != nil {
  528. if err == memcache.ErrNotFound {
  529. err = nil
  530. } else {
  531. log.Error("conn.Delete(%s) error(%v)", key, err)
  532. }
  533. }
  534. return
  535. }
  536. // DelRecentOidsMc delete recent oids mc cache.
  537. func (d *Dao) DelRecentOidsMc(c context.Context, typ int8, mid int64) (err error) {
  538. key := recentOidsKey(typ, mid)
  539. conn := d.mc.Get(c)
  540. defer conn.Close()
  541. if err = conn.Delete(key); err != nil {
  542. if err == memcache.ErrNotFound {
  543. err = nil
  544. } else {
  545. log.Error("conn.Delete(%s) error(%v)", key, err)
  546. }
  547. }
  548. return
  549. }