spark-server/internal/module/device/model/registry.go
2026-09-23 17:11:56 +08:00

79 lines
2.3 KiB
Go

package model
import (
"context"
"errors"
"time"
mysqldriver "github.com/go-sql-driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/clause"
devicelogic "spark-server/internal/module/device/logic"
"spark-server/internal/pkg/errs"
)
type DeviceRow struct {
DeviceID uint64 `gorm:"column:device_id;primaryKey;comment:JWT did"`
FingerprintHash string `gorm:"column:fingerprint_hash;uniqueIndex:uk_fingerprint;comment:物理指纹"`
DeviceType uint8 `gorm:"column:device_type;comment:device_type 枚举"`
DeviceName string `gorm:"column:device_name;comment:设备展示名"`
IDFV string `gorm:"column:idfv;comment:iOS IDFV"`
AndroidID string `gorm:"column:android_id;comment:Android ID"`
LastClientIP string `gorm:"column:last_client_ip;comment:最近 RealIP"`
CreatedAt time.Time `gorm:"column:created_at;comment:首次注册"`
UpdatedAt time.Time `gorm:"column:updated_at;comment:最近 touch"`
}
func (DeviceRow) TableName() string { return "t_devices" }
type RegistryRepo struct {
gdb *gorm.DB
}
func NewRegistryRepo(gdb *gorm.DB) *RegistryRepo {
return &RegistryRepo{gdb: gdb}
}
func (r *RegistryRepo) Upsert(ctx context.Context, row *devicelogic.RegistryRow) error {
if r == nil || r.gdb == nil || row == nil {
return errs.ErrAvailable
}
now := time.Now()
if row.UpdatedAt.IsZero() {
row.UpdatedAt = now
}
dr := DeviceRow{
DeviceID: row.DeviceID,
FingerprintHash: row.FingerprintHash,
DeviceType: uint8(row.DeviceType),
DeviceName: row.DeviceName,
IDFV: row.IDFV,
AndroidID: row.AndroidID,
LastClientIP: row.LastClientIP,
CreatedAt: now,
UpdatedAt: row.UpdatedAt,
}
err := r.gdb.WithContext(ctx).Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "fingerprint_hash"}},
DoUpdates: clause.AssignmentColumns([]string{
"device_name", "idfv", "android_id", "last_client_ip", "updated_at",
}),
}).Create(&dr).Error
return mapDBErr(err)
}
func mapDBErr(err error) error {
if err == nil {
return nil
}
if errors.Is(err, gorm.ErrRecordNotFound) {
return errs.ErrNotFound
}
var me *mysqldriver.MySQLError
if errors.As(err, &me) && me.Number == 1062 {
return errs.ErrDuplicate
}
return errs.ErrAvailable.WithError("device-db", err)
}