mirror of
https://github.com/ddworken/hishtory.git
synced 2025-02-08 22:50:44 +01:00
Refactor: Move UsageData and Device to the backend/server directory since they are purely server-side constructs
This commit is contained in:
parent
7272ca8448
commit
3a01e47701
@ -47,8 +47,8 @@ func OpenPostgres(dsn string, config *gorm.Config) (*DB, error) {
|
|||||||
func (db *DB) AddDatabaseTables() error {
|
func (db *DB) AddDatabaseTables() error {
|
||||||
models := []any{
|
models := []any{
|
||||||
&shared.EncHistoryEntry{},
|
&shared.EncHistoryEntry{},
|
||||||
&shared.Device{},
|
&Device{},
|
||||||
&shared.UsageData{},
|
&UsageData{},
|
||||||
&shared.DumpRequest{},
|
&shared.DumpRequest{},
|
||||||
&shared.DeletionRequest{},
|
&shared.DeletionRequest{},
|
||||||
&shared.Feedback{},
|
&shared.Feedback{},
|
||||||
@ -216,7 +216,7 @@ func (db *DB) UninstallDevice(ctx context.Context, userId, deviceId string) (int
|
|||||||
return 0, fmt.Errorf("UninstallDevice: failed to delete dump requests: %w", r3.Error)
|
return 0, fmt.Errorf("UninstallDevice: failed to delete dump requests: %w", r3.Error)
|
||||||
}
|
}
|
||||||
// Lastly, update the flag so that we know this device has been deleted
|
// Lastly, update the flag so that we know this device has been deleted
|
||||||
r := db.WithContext(ctx).Model(&shared.Device{}).Where("user_id = ? AND device_id = ?", userId, deviceId).Update("uninstall_date", time.Now().UTC())
|
r := db.WithContext(ctx).Model(&Device{}).Where("user_id = ? AND device_id = ?", userId, deviceId).Update("uninstall_date", time.Now().UTC())
|
||||||
if r.Error != nil {
|
if r.Error != nil {
|
||||||
return 0, fmt.Errorf("UnisntallDevice: failed to update uninstall_date: %w", r.Error)
|
return 0, fmt.Errorf("UnisntallDevice: failed to update uninstall_date: %w", r.Error)
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,27 @@ package database
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
"github.com/ddworken/hishtory/shared"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Device struct {
|
||||||
|
UserId string `json:"user_id"`
|
||||||
|
DeviceId string `json:"device_id"`
|
||||||
|
// The IP address that was used to register the device. Recorded so
|
||||||
|
// that I can count how many people are using hishtory and roughly
|
||||||
|
// from where. If you would like this deleted, please email me at
|
||||||
|
// david@daviddworken.com and I can clear it from your device entries.
|
||||||
|
RegistrationIp string `json:"registration_ip"`
|
||||||
|
RegistrationDate time.Time `json:"registration_date"`
|
||||||
|
// Test devices, that should be aggressively cleaned from the DB
|
||||||
|
IsIntegrationTestDevice bool `json:"is_integration_test_device"`
|
||||||
|
// Whether this device was uninstalled
|
||||||
|
UninstallDate time.Time `json:"uninstall_date"`
|
||||||
|
}
|
||||||
|
|
||||||
func (db *DB) CountAllDevices(ctx context.Context) (int64, error) {
|
func (db *DB) CountAllDevices(ctx context.Context) (int64, error) {
|
||||||
var numDevices int64 = 0
|
var numDevices int64 = 0
|
||||||
tx := db.WithContext(ctx).Model(&shared.Device{}).Count(&numDevices)
|
tx := db.WithContext(ctx).Model(&Device{}).Count(&numDevices)
|
||||||
if tx.Error != nil {
|
if tx.Error != nil {
|
||||||
return 0, fmt.Errorf("tx.Error: %w", tx.Error)
|
return 0, fmt.Errorf("tx.Error: %w", tx.Error)
|
||||||
}
|
}
|
||||||
@ -19,7 +33,7 @@ func (db *DB) CountAllDevices(ctx context.Context) (int64, error) {
|
|||||||
|
|
||||||
func (db *DB) CountDevicesForUser(ctx context.Context, userID string) (int64, error) {
|
func (db *DB) CountDevicesForUser(ctx context.Context, userID string) (int64, error) {
|
||||||
var existingDevicesCount int64
|
var existingDevicesCount int64
|
||||||
tx := db.WithContext(ctx).Model(&shared.Device{}).Where("user_id = ?", userID).Count(&existingDevicesCount)
|
tx := db.WithContext(ctx).Model(&Device{}).Where("user_id = ?", userID).Count(&existingDevicesCount)
|
||||||
if tx.Error != nil {
|
if tx.Error != nil {
|
||||||
return 0, fmt.Errorf("tx.Error: %w", tx.Error)
|
return 0, fmt.Errorf("tx.Error: %w", tx.Error)
|
||||||
}
|
}
|
||||||
@ -27,7 +41,7 @@ func (db *DB) CountDevicesForUser(ctx context.Context, userID string) (int64, er
|
|||||||
return existingDevicesCount, nil
|
return existingDevicesCount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) CreateDevice(ctx context.Context, device *shared.Device) error {
|
func (db *DB) CreateDevice(ctx context.Context, device *Device) error {
|
||||||
tx := db.WithContext(ctx).Create(device)
|
tx := db.WithContext(ctx).Create(device)
|
||||||
if tx.Error != nil {
|
if tx.Error != nil {
|
||||||
return fmt.Errorf("tx.Error: %w", tx.Error)
|
return fmt.Errorf("tx.Error: %w", tx.Error)
|
||||||
@ -36,8 +50,8 @@ func (db *DB) CreateDevice(ctx context.Context, device *shared.Device) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) DevicesForUser(ctx context.Context, userID string) ([]*shared.Device, error) {
|
func (db *DB) DevicesForUser(ctx context.Context, userID string) ([]*Device, error) {
|
||||||
var devices []*shared.Device
|
var devices []*Device
|
||||||
tx := db.WithContext(ctx).Where("user_id = ?", userID).Find(&devices)
|
tx := db.WithContext(ctx).Where("user_id = ?", userID).Find(&devices)
|
||||||
if tx.Error != nil {
|
if tx.Error != nil {
|
||||||
return nil, fmt.Errorf("tx.Error: %w", tx.Error)
|
return nil, fmt.Errorf("tx.Error: %w", tx.Error)
|
||||||
|
@ -52,7 +52,7 @@ func (db *DB) AddHistoryEntries(ctx context.Context, entries ...*shared.EncHisto
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) AddHistoryEntriesForAllDevices(ctx context.Context, devices []*shared.Device, entries []*shared.EncHistoryEntry) error {
|
func (db *DB) AddHistoryEntriesForAllDevices(ctx context.Context, devices []*Device, entries []*shared.EncHistoryEntry) error {
|
||||||
chunkSize := 1000
|
chunkSize := 1000
|
||||||
return db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
return db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||||
for _, device := range devices {
|
for _, device := range devices {
|
||||||
|
@ -4,12 +4,21 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ddworken/hishtory/shared"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (db *DB) UsageDataFindByUserAndDevice(ctx context.Context, userId, deviceId string) ([]shared.UsageData, error) {
|
type UsageData struct {
|
||||||
var usageData []shared.UsageData
|
UserId string `json:"user_id" gorm:"not null; uniqueIndex:usageDataUniqueIndex"`
|
||||||
|
DeviceId string `json:"device_id" gorm:"not null; uniqueIndex:usageDataUniqueIndex"`
|
||||||
|
LastUsed time.Time `json:"last_used"`
|
||||||
|
LastIp string `json:"last_ip"`
|
||||||
|
NumEntriesHandled int `json:"num_entries_handled"`
|
||||||
|
LastQueried time.Time `json:"last_queried"`
|
||||||
|
NumQueries int `json:"num_queries"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) UsageDataFindByUserAndDevice(ctx context.Context, userId, deviceId string) ([]UsageData, error) {
|
||||||
|
var usageData []UsageData
|
||||||
|
|
||||||
tx := db.DB.WithContext(ctx).Where("user_id = ? AND device_id = ?", userId, deviceId).Find(&usageData)
|
tx := db.DB.WithContext(ctx).Where("user_id = ? AND device_id = ?", userId, deviceId).Find(&usageData)
|
||||||
if tx.Error != nil {
|
if tx.Error != nil {
|
||||||
@ -23,7 +32,7 @@ func (db *DB) UsageDataFindByUserAndDevice(ctx context.Context, userId, deviceId
|
|||||||
return usageData, nil
|
return usageData, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) CreateUsageData(ctx context.Context, usageData *shared.UsageData) error {
|
func (db *DB) CreateUsageData(ctx context.Context, usageData *UsageData) error {
|
||||||
tx := db.DB.WithContext(ctx).Create(usageData)
|
tx := db.DB.WithContext(ctx).Create(usageData)
|
||||||
if tx.Error != nil {
|
if tx.Error != nil {
|
||||||
return fmt.Errorf("db.WithContext.Create: %w", tx.Error)
|
return fmt.Errorf("db.WithContext.Create: %w", tx.Error)
|
||||||
@ -34,7 +43,7 @@ func (db *DB) CreateUsageData(ctx context.Context, usageData *shared.UsageData)
|
|||||||
|
|
||||||
// UpdateUsageData updates the entry for a given userID/deviceID pair with the lastUsed and lastIP values
|
// UpdateUsageData updates the entry for a given userID/deviceID pair with the lastUsed and lastIP values
|
||||||
func (db *DB) UpdateUsageData(ctx context.Context, userId, deviceId string, lastUsed time.Time, lastIP string) error {
|
func (db *DB) UpdateUsageData(ctx context.Context, userId, deviceId string, lastUsed time.Time, lastIP string) error {
|
||||||
tx := db.DB.WithContext(ctx).Model(&shared.UsageData{}).
|
tx := db.DB.WithContext(ctx).Model(&UsageData{}).
|
||||||
Where("user_id = ? AND device_id = ?", userId, deviceId).
|
Where("user_id = ? AND device_id = ?", userId, deviceId).
|
||||||
Update("last_used", lastUsed).
|
Update("last_used", lastUsed).
|
||||||
Update("last_ip", lastIP)
|
Update("last_ip", lastIP)
|
||||||
@ -141,7 +150,7 @@ func (db *DB) UsageDataTotal(ctx context.Context) (int64, error) {
|
|||||||
}
|
}
|
||||||
nep := numEntriesProcessed{}
|
nep := numEntriesProcessed{}
|
||||||
|
|
||||||
tx := db.WithContext(ctx).Model(&shared.UsageData{}).Select("SUM(num_entries_handled) as total").Find(&nep)
|
tx := db.WithContext(ctx).Model(&UsageData{}).Select("SUM(num_entries_handled) as total").Find(&nep)
|
||||||
if tx.Error != nil {
|
if tx.Error != nil {
|
||||||
return 0, fmt.Errorf("tx.Error: %w", tx.Error)
|
return 0, fmt.Errorf("tx.Error: %w", tx.Error)
|
||||||
}
|
}
|
||||||
@ -151,7 +160,7 @@ func (db *DB) UsageDataTotal(ctx context.Context) (int64, error) {
|
|||||||
|
|
||||||
func (db *DB) CountActiveInstalls(ctx context.Context, since time.Duration) (int64, error) {
|
func (db *DB) CountActiveInstalls(ctx context.Context, since time.Duration) (int64, error) {
|
||||||
var activeInstalls int64
|
var activeInstalls int64
|
||||||
tx := db.WithContext(ctx).Model(&shared.UsageData{}).Where("last_used > ?", time.Now().Add(-since)).Count(&activeInstalls)
|
tx := db.WithContext(ctx).Model(&UsageData{}).Where("last_used > ?", time.Now().Add(-since)).Count(&activeInstalls)
|
||||||
if tx.Error != nil {
|
if tx.Error != nil {
|
||||||
return 0, fmt.Errorf("tx.Error: %w", tx.Error)
|
return 0, fmt.Errorf("tx.Error: %w", tx.Error)
|
||||||
}
|
}
|
||||||
@ -161,7 +170,7 @@ func (db *DB) CountActiveInstalls(ctx context.Context, since time.Duration) (int
|
|||||||
|
|
||||||
func (db *DB) CountQueryUsers(ctx context.Context, since time.Duration) (int64, error) {
|
func (db *DB) CountQueryUsers(ctx context.Context, since time.Duration) (int64, error) {
|
||||||
var activeQueryUsers int64
|
var activeQueryUsers int64
|
||||||
tx := db.WithContext(ctx).Model(&shared.UsageData{}).Where("last_queried > ?", time.Now().Add(-since)).Count(&activeQueryUsers)
|
tx := db.WithContext(ctx).Model(&UsageData{}).Where("last_queried > ?", time.Now().Add(-since)).Count(&activeQueryUsers)
|
||||||
if tx.Error != nil {
|
if tx.Error != nil {
|
||||||
return 0, fmt.Errorf("tx.Error: %w", tx.Error)
|
return 0, fmt.Errorf("tx.Error: %w", tx.Error)
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ddworken/hishtory/backend/server/internal/database"
|
||||||
"github.com/ddworken/hishtory/shared"
|
"github.com/ddworken/hishtory/shared"
|
||||||
"github.com/ddworken/hishtory/shared/ai"
|
"github.com/ddworken/hishtory/shared/ai"
|
||||||
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
|
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
|
||||||
@ -216,7 +217,7 @@ func (s *Server) apiRegisterHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
existingDevicesCount, err := s.db.CountDevicesForUser(r.Context(), userId)
|
existingDevicesCount, err := s.db.CountDevicesForUser(r.Context(), userId)
|
||||||
checkGormError(err)
|
checkGormError(err)
|
||||||
fmt.Printf("apiRegisterHandler: existingDevicesCount=%d\n", existingDevicesCount)
|
fmt.Printf("apiRegisterHandler: existingDevicesCount=%d\n", existingDevicesCount)
|
||||||
if err := s.db.CreateDevice(r.Context(), &shared.Device{UserId: userId, DeviceId: deviceId, RegistrationIp: getRemoteAddr(r), RegistrationDate: time.Now(), IsIntegrationTestDevice: isIntegrationTestDevice}); err != nil {
|
if err := s.db.CreateDevice(r.Context(), &database.Device{UserId: userId, DeviceId: deviceId, RegistrationIp: getRemoteAddr(r), RegistrationDate: time.Now(), IsIntegrationTestDevice: isIntegrationTestDevice}); err != nil {
|
||||||
checkGormError(err)
|
checkGormError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ func (s *Server) updateUsageData(ctx context.Context, version string, remoteAddr
|
|||||||
if !s.trackUsageData {
|
if !s.trackUsageData {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var usageData []shared.UsageData
|
var usageData []database.UsageData
|
||||||
usageData, err := s.db.UsageDataFindByUserAndDevice(ctx, userId, deviceId)
|
usageData, err := s.db.UsageDataFindByUserAndDevice(ctx, userId, deviceId)
|
||||||
if err != nil && !strings.Contains(err.Error(), "record not found") {
|
if err != nil && !strings.Contains(err.Error(), "record not found") {
|
||||||
return fmt.Errorf("db.UsageDataFindByUserAndDevice: %w", err)
|
return fmt.Errorf("db.UsageDataFindByUserAndDevice: %w", err)
|
||||||
@ -166,7 +166,7 @@ func (s *Server) updateUsageData(ctx context.Context, version string, remoteAddr
|
|||||||
if len(usageData) == 0 {
|
if len(usageData) == 0 {
|
||||||
err := s.db.CreateUsageData(
|
err := s.db.CreateUsageData(
|
||||||
ctx,
|
ctx,
|
||||||
&shared.UsageData{
|
&database.UsageData{
|
||||||
UserId: userId,
|
UserId: userId,
|
||||||
DeviceId: deviceId,
|
DeviceId: deviceId,
|
||||||
LastUsed: time.Now(),
|
LastUsed: time.Now(),
|
||||||
|
@ -90,8 +90,8 @@ func OpenDB() (*database.DB, error) {
|
|||||||
return nil, fmt.Errorf("failed to connect to the DB: %w", err)
|
return nil, fmt.Errorf("failed to connect to the DB: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println("AutoMigrating DB tables")
|
|
||||||
if !isProductionEnvironment() {
|
if !isProductionEnvironment() {
|
||||||
|
fmt.Println("AutoMigrating DB tables")
|
||||||
err := db.AddDatabaseTables()
|
err := db.AddDatabaseTables()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create underlying DB tables: %w", err)
|
return nil, fmt.Errorf("failed to create underlying DB tables: %w", err)
|
||||||
|
@ -21,22 +21,6 @@ type EncHistoryEntry struct {
|
|||||||
ReadCount int `json:"read_count"`
|
ReadCount int `json:"read_count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Move this struct to the backend directory
|
|
||||||
type Device struct {
|
|
||||||
UserId string `json:"user_id"`
|
|
||||||
DeviceId string `json:"device_id"`
|
|
||||||
// The IP address that was used to register the device. Recorded so
|
|
||||||
// that I can count how many people are using hishtory and roughly
|
|
||||||
// from where. If you would like this deleted, please email me at
|
|
||||||
// david@daviddworken.com and I can clear it from your device entries.
|
|
||||||
RegistrationIp string `json:"registration_ip"`
|
|
||||||
RegistrationDate time.Time `json:"registration_date"`
|
|
||||||
// Test devices, that should be aggressively cleaned from the DB
|
|
||||||
IsIntegrationTestDevice bool `json:"is_integration_test_device"`
|
|
||||||
// Whether this device was uninstalled
|
|
||||||
UninstallDate time.Time `json:"uninstall_date"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Represents a request to get all history entries from a given device. Used as part of bootstrapping
|
// Represents a request to get all history entries from a given device. Used as part of bootstrapping
|
||||||
// a new device.
|
// a new device.
|
||||||
type DumpRequest struct {
|
type DumpRequest struct {
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
package shared
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
type UsageData struct {
|
|
||||||
UserId string `json:"user_id" gorm:"not null; uniqueIndex:usageDataUniqueIndex"`
|
|
||||||
DeviceId string `json:"device_id" gorm:"not null; uniqueIndex:usageDataUniqueIndex"`
|
|
||||||
LastUsed time.Time `json:"last_used"`
|
|
||||||
LastIp string `json:"last_ip"`
|
|
||||||
NumEntriesHandled int `json:"num_entries_handled"`
|
|
||||||
LastQueried time.Time `json:"last_queried"`
|
|
||||||
NumQueries int `json:"num_queries"`
|
|
||||||
Version string `json:"version"`
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user