|
- package accessstat
-
- import (
- "sync"
- "time"
-
- "gitlink.org.cn/cloudream/common/pkgs/async"
- "gitlink.org.cn/cloudream/common/pkgs/logger"
- "gitlink.org.cn/cloudream/jcs-pub/client/internal/db"
- jcstypes "gitlink.org.cn/cloudream/jcs-pub/common/types"
- )
-
- type AccessStatEventChan = async.UnboundChannel[AccessStatEvent]
-
- type AccessStatEvent interface {
- IsAccessStatEvent() bool
- }
-
- type ExitEvent struct {
- AccessStatEvent
- Err error
- }
-
- type AccessStat struct {
- cfg Config
- done chan any
- stats map[entryKey]float64
- lock sync.Mutex
- db *db.DB
- }
-
- type entryKey struct {
- objID jcstypes.ObjectID
- pkgID jcstypes.PackageID
- spaceID jcstypes.UserSpaceID
- }
-
- func NewAccessStat(cfg Config, db *db.DB) *AccessStat {
- return &AccessStat{
- cfg: cfg,
- done: make(chan any),
- stats: make(map[entryKey]float64),
- db: db,
- }
- }
-
- func (p *AccessStat) AddAccessCounter(objID jcstypes.ObjectID, pkgID jcstypes.PackageID, spaceID jcstypes.UserSpaceID, value float64) {
- p.lock.Lock()
- defer p.lock.Unlock()
-
- key := entryKey{
- objID: objID,
- pkgID: pkgID,
- spaceID: spaceID,
- }
- p.stats[key] += value
- }
-
- func (p *AccessStat) Start() *AccessStatEventChan {
- ch := async.NewUnboundChannel[AccessStatEvent]()
-
- go func() {
- ticker := time.NewTicker(p.cfg.ReportInterval)
- defer ticker.Stop()
-
- for {
- select {
- case <-ticker.C:
- case <-p.done:
- ch.Send(ExitEvent{})
- return
- }
-
- p.lock.Lock()
- st := p.stats
- p.stats = make(map[entryKey]float64)
- p.lock.Unlock()
-
- if len(st) == 0 {
- continue
- }
-
- var entries []db.AddAccessStatEntry
- for k, v := range st {
- entries = append(entries, db.AddAccessStatEntry{
- ObjectID: k.objID,
- PackageID: k.pkgID,
- UserSpaceID: k.spaceID,
- Counter: v,
- })
- }
- err := db.DoTx10(p.db, p.db.Package().BatchAddPackageAccessStat, entries)
-
- if err != nil {
- logger.Errorf("add all package access stat counter: %v", err)
-
- p.lock.Lock()
- for k, v := range st {
- p.stats[k] += v
- }
- p.lock.Unlock()
- continue
- }
- }
- }()
- return ch
- }
-
- func (p *AccessStat) Stop() {
- close(p.done)
- }
|