From 87fb2c45a192a36a6e3ba8f080e896cc55ed11a0 Mon Sep 17 00:00:00 2001 From: Tigor Hutasuhut Date: Thu, 8 Aug 2024 16:13:30 +0700 Subject: [PATCH] server: implemented device update endpoint --- go/api/devices_exist.go | 21 ++++++++++++++++ go/api/devices_update.go | 46 ++++++++++++++++++++++++++++++++++++ go/server/device_handlers.go | 17 +++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 go/api/devices_exist.go create mode 100644 go/api/devices_update.go diff --git a/go/api/devices_exist.go b/go/api/devices_exist.go new file mode 100644 index 0000000..25cc255 --- /dev/null +++ b/go/api/devices_exist.go @@ -0,0 +1,21 @@ +package api + +import ( + "context" + + "github.com/tigorlazuardi/bluemage/go/gen/models" + "github.com/tigorlazuardi/bluemage/go/pkg/errs" + "github.com/tigorlazuardi/bluemage/go/pkg/log" +) + +func (api *API) DevicesExist(ctx context.Context, slug string) (exists bool, err error) { + ctx, coll := log.WithQueryCollector(ctx) + exists, err = models.DeviceExists(ctx, api.DB, slug) + if err != nil { + return exists, errs.Wrapw(err, "failed to check device existence", + "slug", slug, + "query", coll, + ) + } + return exists, nil +} diff --git a/go/api/devices_update.go b/go/api/devices_update.go new file mode 100644 index 0000000..b921e88 --- /dev/null +++ b/go/api/devices_update.go @@ -0,0 +1,46 @@ +package api + +import ( + "context" + "errors" + + "github.com/mattn/go-sqlite3" + "github.com/tigorlazuardi/bluemage/go/gen/models" + "github.com/tigorlazuardi/bluemage/go/pkg/errs" + "github.com/tigorlazuardi/bluemage/go/pkg/log" +) + +func (api *API) DevicesUpdate(ctx context.Context, slug string, update *models.DeviceSetter) (err error) { + exist, err := api.DevicesExist(ctx, slug) + if err != nil { + return err + } + + if !exist { + return errs.Failf("device with slug %q does not exist", slug) + } + + ctx, coll := log.WithQueryCollector(ctx) + + target := &models.Device{Slug: slug} + + api.lockf(func() { + err = models.Devices.Update(ctx, api.DB, update, target) + }) + if err != nil { + if sqlite3Err := new(sqlite3.Error); errors.As(err, &sqlite3Err) { + if sqlite3Err.Code == sqlite3.ErrConstraint { + return errs. + Wrapw( + err, "a device with the same slug already exists", + "slug", slug, + "update", update, + "query", coll, + ) + } + } + return errs.Wrapw(err, "failed to update device", "slug", slug, "update", update, "query", coll) + } + + return nil +} diff --git a/go/server/device_handlers.go b/go/server/device_handlers.go index 57f8d1e..ba9f651 100644 --- a/go/server/device_handlers.go +++ b/go/server/device_handlers.go @@ -64,3 +64,20 @@ func (d *DeviceHandler) ListDevices(ctx context.Context, request *connect.Reques } return connect.NewResponse(resp), nil } + +// UpdateDevice updates a device. +// Only fields that are set in the request will be updated. +func (de *DeviceHandler) UpdateDevice(ctx context.Context, request *connect.Request[device.UpdateDeviceRequest]) (*connect.Response[device.UpdateDeviceResponse], error) { + slug := request.Msg.Slug + set := convert.DeviceSetterProtoToModelsDeviceSetter(request.Msg.Set) + err := de.API.DevicesUpdate(ctx, slug, set) + if err != nil { + return nil, errs.IntoConnectError(err) + } + + resp := &device.UpdateDeviceResponse{ + Slug: slug, + } + + return connect.NewResponse(resp), nil +}