You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

access_stat.go 2.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package accessstat
  2. import (
  3. "sync"
  4. "time"
  5. "gitlink.org.cn/cloudream/common/pkgs/async"
  6. "gitlink.org.cn/cloudream/common/pkgs/logger"
  7. "gitlink.org.cn/cloudream/jcs-pub/client/internal/db"
  8. clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types"
  9. )
  10. type AccessStatEventChan = async.UnboundChannel[AccessStatEvent]
  11. type AccessStatEvent interface {
  12. IsAccessStatEvent() bool
  13. }
  14. type ExitEvent struct {
  15. AccessStatEvent
  16. Err error
  17. }
  18. type AccessStat struct {
  19. cfg Config
  20. done chan any
  21. stats map[entryKey]float64
  22. lock sync.Mutex
  23. db *db.DB
  24. }
  25. type entryKey struct {
  26. objID clitypes.ObjectID
  27. pkgID clitypes.PackageID
  28. spaceID clitypes.UserSpaceID
  29. }
  30. func NewAccessStat(cfg Config, db *db.DB) *AccessStat {
  31. return &AccessStat{
  32. cfg: cfg,
  33. done: make(chan any),
  34. stats: make(map[entryKey]float64),
  35. db: db,
  36. }
  37. }
  38. func (p *AccessStat) AddAccessCounter(objID clitypes.ObjectID, pkgID clitypes.PackageID, spaceID clitypes.UserSpaceID, value float64) {
  39. p.lock.Lock()
  40. defer p.lock.Unlock()
  41. key := entryKey{
  42. objID: objID,
  43. pkgID: pkgID,
  44. spaceID: spaceID,
  45. }
  46. p.stats[key] += value
  47. }
  48. func (p *AccessStat) Start() *AccessStatEventChan {
  49. ch := async.NewUnboundChannel[AccessStatEvent]()
  50. go func() {
  51. ticker := time.NewTicker(p.cfg.ReportInterval)
  52. defer ticker.Stop()
  53. for {
  54. select {
  55. case <-ticker.C:
  56. case <-p.done:
  57. ch.Send(ExitEvent{})
  58. return
  59. }
  60. p.lock.Lock()
  61. st := p.stats
  62. p.stats = make(map[entryKey]float64)
  63. p.lock.Unlock()
  64. if len(st) == 0 {
  65. continue
  66. }
  67. var entries []db.AddAccessStatEntry
  68. for k, v := range st {
  69. entries = append(entries, db.AddAccessStatEntry{
  70. ObjectID: k.objID,
  71. PackageID: k.pkgID,
  72. UserSpaceID: k.spaceID,
  73. Counter: v,
  74. })
  75. }
  76. err := db.DoTx10(p.db, p.db.Package().BatchAddPackageAccessStat, entries)
  77. if err != nil {
  78. logger.Errorf("add all package access stat counter: %v", err)
  79. p.lock.Lock()
  80. for k, v := range st {
  81. p.stats[k] += v
  82. }
  83. p.lock.Unlock()
  84. continue
  85. }
  86. }
  87. }()
  88. return ch
  89. }
  90. func (p *AccessStat) Stop() {
  91. close(p.done)
  92. }

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。