sliding-sync/sync2/devices_table.go

68 lines
2.0 KiB
Go
Raw Permalink Normal View History

2021-09-20 18:09:28 +01:00
package sync2
import (
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
2023-08-08 18:48:16 +01:00
"time"
2021-09-20 18:09:28 +01:00
)
type Device struct {
2023-04-28 13:24:22 +01:00
UserID string `db:"user_id"`
DeviceID string `db:"device_id"`
Since string `db:"since"`
2021-09-20 18:09:28 +01:00
}
2023-04-28 12:20:46 +01:00
// DevicesTable remembers syncv2 since positions per-device
2023-04-27 19:05:24 +01:00
type DevicesTable struct {
2021-09-20 18:09:28 +01:00
db *sqlx.DB
}
2023-04-28 16:10:43 +01:00
func NewDevicesTable(db *sqlx.DB) *DevicesTable {
2021-09-20 18:09:28 +01:00
db.MustExec(`
CREATE TABLE IF NOT EXISTS syncv3_sync2_devices (
2023-04-28 12:20:46 +01:00
user_id TEXT NOT NULL,
device_id TEXT NOT NULL,
PRIMARY KEY (user_id, device_id),
2021-09-20 18:09:28 +01:00
since TEXT NOT NULL
);`)
2023-04-27 19:05:24 +01:00
return &DevicesTable{
2023-04-28 12:20:46 +01:00
db: db,
2021-09-20 18:09:28 +01:00
}
}
2023-04-28 12:20:46 +01:00
// InsertDevice creates a new devices row with a blank since token if no such row
// exists. Otherwise, it does nothing.
func (t *DevicesTable) InsertDevice(txn *sqlx.Tx, userID, deviceID string) error {
_, err := txn.Exec(
2023-04-28 12:20:46 +01:00
` INSERT INTO syncv3_sync2_devices(user_id, device_id, since) VALUES($1,$2,$3)
ON CONFLICT (user_id, device_id) DO NOTHING`,
userID, deviceID, "",
)
return err
2021-09-20 18:09:28 +01:00
}
2023-04-28 16:10:43 +01:00
func (t *DevicesTable) UpdateDeviceSince(userID, deviceID, since string) error {
_, err := t.db.Exec(`UPDATE syncv3_sync2_devices SET since = $1 WHERE user_id = $2 AND device_id = $3`, since, userID, deviceID)
2021-09-20 18:09:28 +01:00
return err
}
2023-08-08 18:48:16 +01:00
// FindOldDevices fetches the user_id and device_id of all devices which haven't /synced
// for at least as long as the given inactivityPeriod. Such devices are returned in
// no particular order.
//
// This is determined using the syncv3_sync2_tokens.last_seen column, which is updated
2023-08-10 12:05:47 +01:00
// at most once per day to save DB throughtput (see TokensTable.MaybeUpdateLastSeen).
// The caller should therefore use an inactivityPeriod of at least two days to avoid
// considering a recently-used device as old.
2023-08-08 18:48:16 +01:00
func (t *DevicesTable) FindOldDevices(inactivityPeriod time.Duration) (devices []Device, err error) {
err = t.db.Select(&devices, `
SELECT user_id, device_id
FROM syncv3_sync2_devices JOIN syncv3_sync2_tokens USING(user_id, device_id)
GROUP BY (user_id, device_id)
HAVING MAX(last_seen) < $1
`, time.Now().Add(-inactivityPeriod),
)
return
}