package model import ( "context" "encoding/json" "fmt" "github.com/go-redis/redis/v8" "github.com/golang-module/carbon/v2" "samba/pkg/log" "samba/pkg/servername" "samba/pkg/service" "samba/pkg/xtime" "samba/proto" "samba/util/rdbkey" "samba/util/routingKey" "samba/util/util" "time" ) // UserOnlineDuration 用户在线时长记录 type UserOnlineDuration struct { UID int64 `json:"uid"` // 上线时间 OnlineTime time.Time `json:"online_time"` // 下线时间 OffLineTime time.Time `json:"offline_time"` // 在线时长(s) Duration int64 `json:"duration"` // 记录时间 RecordTime time.Time `json:"record_time"` } func (u *UserOnlineDuration) Flush(srv service.IService) error { sql, err := util.Struct2InsertSql("user_online_duration", u) if err != nil { return err } req := proto.NtfClickHouseSql{Sql: sql} msg := util.MakeMessage(proto.NtfClickHouseSqlId, req, u.UID, 0) byteData, err := json.Marshal(msg) if err != nil { return err } err = srv.Publish(util.Direct(servername.ClickHouse), routingKey.ClickHouseKey(u.UID), byteData) if err != nil { return err } return err } var UserOnlineRepo = map[int64]carbon.Carbon{} func RecordUserOnline(uid int64) { UserOnlineRepo[uid] = xtime.Now() } func RecordUserOffline(uid int64, srv service.IService) { onlineTime, ok := UserOnlineRepo[uid] if !ok { return } delete(UserOnlineRepo, uid) now := xtime.Now() dur := UserOnlineDuration{ UID: uid, OnlineTime: onlineTime.StdTime(), OffLineTime: now.StdTime(), Duration: onlineTime.DiffInSeconds(now), RecordTime: now.StdTime(), } err := dur.Flush(srv) if err != nil { log.Error(fmt.Sprintf("failed to flush user uid=%d online duration %s", dur.UID, err)) } } type UserOnlineOp struct { rdb *redis.Client } func NewUserOnlineOp() *UserOnlineOp { return &UserOnlineOp{rdb: rdbGameLog} } func (op *UserOnlineOp) Current() (int64, error) { return op.rdb.Get(context.TODO(), rdbkey.CurrentOnlineUserKey()).Int64() } func (op *UserOnlineOp) SetCurrent(count int64) error { return op.rdb.Set(context.TODO(), rdbkey.CurrentOnlineUserKey(), count, 0).Err() }