Browse Source

add SaveMode for device which can be 0 (All) or a bitmask for what to save. It did not improve performance

feature-colorvalue2
Gisle Aune 3 years ago
parent
commit
0cd325e8db
  1. 8
      app/api/devices.go
  2. 2
      app/services/events.go
  3. 2
      app/services/synclights.go
  4. 91
      internal/mysql/devicerepo.go
  5. 14
      models/device.go

8
app/api/devices.go

@ -80,7 +80,7 @@ func Devices(r gin.IRoutes) {
go func() { go func() {
for _, device := range changed { for _, device := range changed {
err := config.DeviceRepository().Save(context.Background(), &device)
err := config.DeviceRepository().Save(context.Background(), &device, models.SMState)
if err != nil { if err != nil {
log.Println("Failed to save device for state:", err) log.Println("Failed to save device for state:", err)
continue continue
@ -109,7 +109,7 @@ func Devices(r gin.IRoutes) {
for i := range devices { for i := range devices {
devices[i].ApplyUpdate(update) devices[i].ApplyUpdate(update)
err := config.DeviceRepository().Save(context.Background(), &devices[i])
err := config.DeviceRepository().Save(context.Background(), &devices[i], models.SMProperties)
if err != nil { if err != nil {
log.Println("Failed to save device for state:", err) log.Println("Failed to save device for state:", err)
continue continue
@ -145,7 +145,7 @@ func Devices(r gin.IRoutes) {
go func() { go func() {
for _, device := range devices { for _, device := range devices {
err := config.DeviceRepository().Save(context.Background(), &device)
err := config.DeviceRepository().Save(context.Background(), &device, models.SMState)
if err != nil { if err != nil {
log.Println("Failed to save device for state:", err) log.Println("Failed to save device for state:", err)
continue continue
@ -204,7 +204,7 @@ func Devices(r gin.IRoutes) {
device.Tags = append(device.Tags[:index], device.Tags[index+1:]...) device.Tags = append(device.Tags[:index], device.Tags[index+1:]...)
} }
err = config.DeviceRepository().Save(ctxOf(c), device)
err = config.DeviceRepository().Save(ctxOf(c), device, models.SMTags)
if err != nil { if err != nil {
return nil, err return nil, err
} }

2
app/services/events.go

@ -157,7 +157,7 @@ func handleEvent(event models.Event) (responses []models.Event) {
wg.Add(1) wg.Add(1)
go func(device models.Device) { go func(device models.Device) {
err := config.DeviceRepository().Save(context.Background(), &device)
err := config.DeviceRepository().Save(context.Background(), &device, models.SMState)
if err != nil { if err != nil {
log.Println("Failed to save device for state:", err) log.Println("Failed to save device for state:", err)
} }

2
app/services/synclights.go

@ -66,7 +66,7 @@ func checkNewDevices() error {
log.Println("Saving new device", driverDevice.InternalID) log.Println("Saving new device", driverDevice.InternalID)
err := config.DeviceRepository().Save(ctx, &driverDevice)
err := config.DeviceRepository().Save(ctx, &driverDevice, models.SMState|models.SMProperties|models.SMTags)
if err != nil { if err != nil {
log.Println("Failed to save device:", err) log.Println("Failed to save device:", err)
continue continue

91
internal/mysql/devicerepo.go

@ -117,7 +117,7 @@ func (r *DeviceRepo) FetchByReference(ctx context.Context, kind models.Reference
return r.populate(ctx, records) return r.populate(ctx, records)
} }
func (r *DeviceRepo) Save(ctx context.Context, device *models.Device) error {
func (r *DeviceRepo) Save(ctx context.Context, device *models.Device, mode models.SaveMode) error {
tx, err := r.DBX.Beginx() tx, err := r.DBX.Beginx()
if err != nil { if err != nil {
return dbErr(err) return dbErr(err)
@ -149,13 +149,18 @@ func (r *DeviceRepo) Save(ctx context.Context, device *models.Device) error {
} }
// Let's just be lazy for now, optimize later if need be. // Let's just be lazy for now, optimize later if need be.
_, err = tx.ExecContext(ctx, "DELETE FROM device_tag WHERE device_id=?", record.ID)
if err != nil {
return dbErr(err)
if mode == 0 || mode&models.SMTags != 0 {
_, err = tx.ExecContext(ctx, "DELETE FROM device_tag WHERE device_id=?", record.ID)
if err != nil {
return dbErr(err)
}
} }
_, err = tx.ExecContext(ctx, "DELETE FROM device_property WHERE device_id=?", record.ID)
if err != nil {
return dbErr(err)
if mode == 0 || mode&models.SMProperties != 0 {
_, err = tx.ExecContext(ctx, "DELETE FROM device_property WHERE device_id=?", record.ID)
if err != nil {
return dbErr(err)
}
} }
} else { } else {
res, err := tx.NamedExecContext(ctx, ` res, err := tx.NamedExecContext(ctx, `
@ -175,51 +180,57 @@ func (r *DeviceRepo) Save(ctx context.Context, device *models.Device) error {
device.ID = int(lastID) device.ID = int(lastID)
} }
for _, tag := range device.Tags {
_, err := tx.ExecContext(ctx, "INSERT INTO device_tag (device_id, tag_name) VALUES (?, ?)", record.ID, tag)
if err != nil {
return dbErr(err)
if mode == 0 || mode&models.SMTags != 0 {
for _, tag := range device.Tags {
_, err := tx.ExecContext(ctx, "INSERT INTO device_tag (device_id, tag_name) VALUES (?, ?)", record.ID, tag)
if err != nil {
return dbErr(err)
}
} }
} }
for key, value := range device.UserProperties {
_, err := tx.ExecContext(ctx, "INSERT INTO device_property (device_id, prop_key, prop_value, is_user) VALUES (?, ?, ?, 1)",
record.ID, key, value,
)
if err != nil {
return dbErr(err)
if mode == 0 || mode&models.SMProperties != 0 {
for key, value := range device.UserProperties {
_, err := tx.ExecContext(ctx, "INSERT INTO device_property (device_id, prop_key, prop_value, is_user) VALUES (?, ?, ?, 1)",
record.ID, key, value,
)
if err != nil {
return dbErr(err)
}
} }
}
for key, value := range device.DriverProperties {
j, err := json.Marshal(value)
if err != nil {
// Eh, it'll get filled by the driver anyway
continue
}
for key, value := range device.DriverProperties {
j, err := json.Marshal(value)
if err != nil {
// Eh, it'll get filled by the driver anyway
continue
}
_, err = tx.ExecContext(ctx, "INSERT INTO device_property (device_id, prop_key, prop_value, is_user) VALUES (?, ?, ?, 0)",
record.ID, key, string(j),
)
if err != nil {
// Return err here anyway, it might put the tx in a bad state to ignore it.
return dbErr(err)
_, err = tx.ExecContext(ctx, "INSERT INTO device_property (device_id, prop_key, prop_value, is_user) VALUES (?, ?, ?, 0)",
record.ID, key, string(j),
)
if err != nil {
// Return err here anyway, it might put the tx in a bad state to ignore it.
return dbErr(err)
}
} }
} }
_, err = tx.NamedExecContext(ctx, `
if mode == 0 || mode&models.SMState != 0 {
_, err = tx.NamedExecContext(ctx, `
REPLACE INTO device_state(device_id, hue, saturation, kelvin, power, intensity) REPLACE INTO device_state(device_id, hue, saturation, kelvin, power, intensity)
VALUES (:device_id, :hue, :saturation, :kelvin, :power, :intensity) VALUES (:device_id, :hue, :saturation, :kelvin, :power, :intensity)
`, deviceStateRecord{ `, deviceStateRecord{
DeviceID: record.ID,
Hue: device.State.Color.Hue,
Saturation: device.State.Color.Saturation,
Kelvin: device.State.Color.Kelvin,
Power: device.State.Power,
Intensity: device.State.Intensity,
})
if err != nil {
return dbErr(err)
DeviceID: record.ID,
Hue: device.State.Color.Hue,
Saturation: device.State.Color.Saturation,
Kelvin: device.State.Color.Kelvin,
Power: device.State.Power,
Intensity: device.State.Intensity,
})
if err != nil {
return dbErr(err)
}
} }
return tx.Commit() return tx.Commit()

14
models/device.go

@ -20,8 +20,8 @@ type Device struct {
} }
type DeviceUpdate struct { type DeviceUpdate struct {
Icon *string `json:"icon"`
Name *string `json:"name"`
Icon *string `json:"icon"`
Name *string `json:"name"`
UserProperties map[string]*string `json:"userProperties"` UserProperties map[string]*string `json:"userProperties"`
} }
@ -46,10 +46,18 @@ type NewDeviceState struct {
type DeviceCapability string type DeviceCapability string
type SaveMode int
const (
SMState SaveMode = 1
SMProperties SaveMode = 2
SMTags SaveMode = 4
)
type DeviceRepository interface { type DeviceRepository interface {
Find(ctx context.Context, id int) (*Device, error) Find(ctx context.Context, id int) (*Device, error)
FetchByReference(ctx context.Context, kind ReferenceKind, value string) ([]Device, error) FetchByReference(ctx context.Context, kind ReferenceKind, value string) ([]Device, error)
Save(ctx context.Context, device *Device) error
Save(ctx context.Context, device *Device, mode SaveMode) error
Delete(ctx context.Context, device *Device) error Delete(ctx context.Context, device *Device) error
} }

Loading…
Cancel
Save