refactor: api now uses it's own request type and handlers

will now handles the conversion of the request to the api request type
This commit is contained in:
Tigor Hutasuhut 2024-08-15 10:23:56 +07:00
parent 8bb8cb30ec
commit cf14079f1f
9 changed files with 187 additions and 133 deletions

View file

@ -5,11 +5,8 @@ import (
"sync"
"github.com/stephenafamo/bob"
"github.com/tigorlazuardi/bluemage/go/gen/converter"
)
var convert converter.DeviceConverterImpl
type API struct {
mu sync.Mutex
Executor bob.Executor
@ -21,3 +18,10 @@ func (api *API) lockf(f func()) {
defer api.mu.Unlock()
f()
}
type Sort string
const (
SortAsc Sort = "asc"
SortDesc Sort = "desc"
)

View file

@ -1,9 +1,6 @@
package api
import (
"strings"
device "github.com/tigorlazuardi/bluemage/go/gen/proto/device/v1"
"github.com/tigorlazuardi/bluemage/go/pkg/errs"
"golang.org/x/net/context"
@ -12,19 +9,30 @@ import (
. "github.com/tigorlazuardi/bluemage/go/gen/jet/table"
)
func listDevicesRequestSelectStatement(req *device.ListDevicesRequest) SelectStatement {
type ListDevicesRequest struct {
Search string
Disabled *bool
Limit int64
Offset int64
OrderBy string
Sort Sort
}
func (request ListDevicesRequest) Statement() SelectStatement {
cond := Bool(true)
switch req.Disabled {
case device.DisabledFilter_DISABLED_FILTER_TRUE:
if d := request.Disabled; d != nil {
disabled := *d
if disabled {
cond.AND(Devices.Disabled.EQ(Int(1)))
case device.DisabledFilter_DISABLED_FILTER_FALSE:
} else {
cond.AND(Devices.Disabled.EQ(Int(0)))
}
}
if req.Search != "" {
if request.Search != "" {
cond.AND(
Devices.Name.LIKE(String("%" + req.Search + "%")).
OR(Devices.Slug.LIKE(String("%" + req.Search + "%"))),
Devices.Name.LIKE(String("%" + request.Search + "%")).
OR(Devices.Slug.LIKE(String("%" + request.Search + "%"))),
)
}
@ -32,45 +40,35 @@ func listDevicesRequestSelectStatement(req *device.ListDevicesRequest) SelectSta
FROM(Devices).
WHERE(cond)
if req.Limit > 0 {
stmt.LIMIT(int64(req.Limit))
if request.Limit > 0 {
stmt.LIMIT(request.Limit)
}
if req.Offset > 0 {
stmt.OFFSET(int64(req.Offset))
if request.Offset > 0 {
stmt.OFFSET(request.Offset)
}
if req.OrderBy == device.OrderBy_ORDER_BY_UNSPECIFIED {
if request.OrderBy == "" {
return stmt.ORDER_BY(Devices.CreatedAt.DESC())
}
orderByField, _ := strings.CutPrefix(device.OrderBy_name[int32(req.OrderBy)], "ORDER_BY_")
orderByField = strings.ToLower(orderByField)
orderBy := StringColumn(orderByField)
if req.Sort == device.Sort_SORT_DESCENDING {
orderBy := StringColumn(request.OrderBy)
if request.Sort == SortDesc {
return stmt.ORDER_BY(orderBy.DESC())
} else {
return stmt.ORDER_BY(orderBy.ASC())
}
}
func (api *API) DevicesList(ctx context.Context, req *device.ListDevicesRequest) (resp *device.ListDevicesResponse, err error) {
func (api *API) DevicesList(ctx context.Context, req ListDevicesRequest) (resp []model.Devices, err error) {
ctx, span := tracer.Start(ctx, "DevicesList")
defer span.End()
resp = &device.ListDevicesResponse{}
stmt := listDevicesRequestSelectStatement(req)
var out []model.Devices
if err := stmt.QueryContext(ctx, api.DB, &out); err != nil {
stmt := req.Statement()
if err := stmt.QueryContext(ctx, api.DB, &resp); err != nil {
return resp, errs.Wrapw(err, "failed to list devices",
"request", req,
"query", stmt.DebugSql(),
)
}
for _, result := range out {
resp.Devices = append(resp.Devices, convert.JetModelDeviceToGetDeviceResponse(result))
}
return resp, err
}

View file

@ -1,7 +1,9 @@
package converts
import (
"github.com/aarondl/opt/omit"
"strings"
"github.com/tigorlazuardi/bluemage/go/api"
"github.com/tigorlazuardi/bluemage/go/gen/jet/model"
"github.com/tigorlazuardi/bluemage/go/gen/models"
device "github.com/tigorlazuardi/bluemage/go/gen/proto/device/v1"
@ -24,6 +26,9 @@ import (
// goverter:extend Int64ToOmitInt64
// goverter:extend Float64ToOmitFloat64
// goverter:extend StringToOmitString
// goverter:extend DeviceDisabledFilterToPtrBool
// goverter:extend DeviceOrderByToString
// goverter:extend DeviceSortToAPISort
type DeviceConverter interface {
// goverter:ignore CreatedAt UpdatedAt
// goverter:map Nsfw NSFW
@ -32,86 +37,41 @@ type DeviceConverter interface {
ModelsDeviceToCreateDeviceResponse(*models.Device) *device.CreateDeviceResponse
// goverter:ignore state sizeCache unknownFields
// goverter:useZeroValueOnPointerInconsistency
JetModelDeviceToGetDeviceResponse(model.Devices) *device.GetDeviceResponse
JetModelDeviceToProtoDevice(model.Devices) *device.Device
// goverter:useZeroValueOnPointerInconsistency
ListDevicesRequestToAPIListDevicesRequest(*device.ListDevicesRequest) api.ListDevicesRequest
// goverter:ignore Slug SingleFolderMode CreatedAt UpdatedAt
// goverter:map Nsfw NSFW
DeviceSetterProtoToModelsDeviceSetter(*device.DeviceSetter) *models.DeviceSetter
}
func BoolToInt8(b bool) int8 {
if b {
return 1
func DeviceDisabledFilterToPtrBool(f device.DisabledFilter) *bool {
switch f {
case device.DisabledFilter_DISABLED_FILTER_TRUE:
b := true
return &b
case device.DisabledFilter_DISABLED_FILTER_FALSE:
b := false
return &b
default:
return nil
}
return 0
}
func PtrBoolToOmitInt8(b *bool) omit.Val[int8] {
if b == nil {
return omit.Val[int8]{}
func DeviceOrderByToString(order device.OrderBy) string {
if order == device.OrderBy_ORDER_BY_UNSPECIFIED {
return ""
}
v := *b
if v {
return omit.From(int8(1))
field, _ := strings.CutPrefix(device.OrderBy_name[int32(order)], "ORDER_BY_")
field = strings.ToLower(field)
return field
}
func DeviceSortToAPISort(sort device.Sort) api.Sort {
if sort == device.Sort_SORT_DESCENDING {
return api.SortDesc
}
return omit.From(int8(0))
}
func PtrStringToOmitString(s *string) omit.Val[string] {
return omit.FromPtr(s)
}
func StringToOmitString(s string) omit.Val[string] {
return omit.From(s)
}
func PtrFloat64ToOmitFloat64(f *float64) omit.Val[float64] {
return omit.FromPtr(f)
}
func Float64ToOmitFloat64(f float64) omit.Val[float64] {
return omit.From(f)
}
func PtrIntToOmitInt(i *int) omit.Val[int] {
return omit.FromPtr(i)
}
func IntToOmitInt(i int) omit.Val[int] {
return omit.From(i)
}
func PtrInt8ToOmitInt8(i *int8) omit.Val[int8] {
return omit.FromPtr(i)
}
func Int8ToOmitInt8(i int8) omit.Val[int8] {
return omit.From(i)
}
func PtrInt32ToOmitInt32(i *int32) omit.Val[int32] {
return omit.FromPtr(i)
}
func Int32ToOmitInt32(i int32) omit.Val[int32] {
return omit.From(i)
}
func PtrInt64ToOmitInt64(i *int64) omit.Val[int64] {
return omit.FromPtr(i)
}
func Int64ToOmitInt64(i int64) omit.Val[int64] {
return omit.From(i)
}
func BoolToOmitInt8(b bool) omit.Val[int8] {
if b {
return omit.From(int8(1))
}
return omit.From(int8(0))
}
func Int8ToBool(i int8) bool {
return i > 0
return api.SortDesc
}

80
go/converts/utils.go Normal file
View file

@ -0,0 +1,80 @@
package converts
import "github.com/aarondl/opt/omit"
func BoolToInt8(b bool) int8 {
if b {
return 1
}
return 0
}
func PtrBoolToOmitInt8(b *bool) omit.Val[int8] {
if b == nil {
return omit.Val[int8]{}
}
v := *b
if v {
return omit.From(int8(1))
}
return omit.From(int8(0))
}
func PtrStringToOmitString(s *string) omit.Val[string] {
return omit.FromPtr(s)
}
func StringToOmitString(s string) omit.Val[string] {
return omit.From(s)
}
func PtrFloat64ToOmitFloat64(f *float64) omit.Val[float64] {
return omit.FromPtr(f)
}
func Float64ToOmitFloat64(f float64) omit.Val[float64] {
return omit.From(f)
}
func PtrIntToOmitInt(i *int) omit.Val[int] {
return omit.FromPtr(i)
}
func IntToOmitInt(i int) omit.Val[int] {
return omit.From(i)
}
func PtrInt8ToOmitInt8(i *int8) omit.Val[int8] {
return omit.FromPtr(i)
}
func Int8ToOmitInt8(i int8) omit.Val[int8] {
return omit.From(i)
}
func PtrInt32ToOmitInt32(i *int32) omit.Val[int32] {
return omit.FromPtr(i)
}
func Int32ToOmitInt32(i int32) omit.Val[int32] {
return omit.From(i)
}
func PtrInt64ToOmitInt64(i *int64) omit.Val[int64] {
return omit.FromPtr(i)
}
func Int64ToOmitInt64(i int64) omit.Val[int64] {
return omit.From(i)
}
func BoolToOmitInt8(b bool) omit.Val[int8] {
if b {
return omit.From(int8(1))
}
return omit.From(int8(0))
}
func Int8ToBool(i int8) bool {
return i > 0
}

View file

@ -39,16 +39,24 @@ func (d *DeviceHandler) GetDevice(ctx context.Context, request *connect.Request[
return nil, errs.IntoConnectError(err)
}
devResp := deviceConvert.JetModelDeviceToGetDeviceResponse(dev)
return connect.NewResponse(devResp), nil
data := deviceConvert.JetModelDeviceToProtoDevice(dev)
resp := &device.GetDeviceResponse{
Device: data,
}
return connect.NewResponse(resp), nil
}
// ListDevices implements v1connect.DeviceServiceHandler.
func (d *DeviceHandler) ListDevices(ctx context.Context, request *connect.Request[device.ListDevicesRequest]) (*connect.Response[device.ListDevicesResponse], error) {
resp, err := d.API.DevicesList(ctx, request.Msg)
listRequest := deviceConvert.ListDevicesRequestToAPIListDevicesRequest(request.Msg)
devices, err := d.API.DevicesList(ctx, listRequest)
if err != nil {
return nil, errs.IntoConnectError(err)
}
resp := &device.ListDevicesResponse{}
for _, device := range devices {
resp.Devices = append(resp.Devices, deviceConvert.JetModelDeviceToProtoDevice(device))
}
return connect.NewResponse(resp), nil
}

View file

@ -38,20 +38,3 @@ service DeviceService {
// CountDevices count the number of devices.
rpc CountDevices(CountDevicesRequest) returns (CountDevicesResponse) {}
}
message Device {
string slug = 1;
bool disabled = 2;
string name = 3;
double resolution_x = 4;
double resolution_y = 5;
double aspect_ratio_tolerance = 6;
int32 min_x = 7;
int32 min_y = 8;
int32 max_x = 9;
int32 max_y = 10;
bool nsfw = 11;
bool single_folder_mode = 12;
int64 created_at = 13;
int64 updated_at = 14;
}

View file

@ -3,7 +3,7 @@ syntax = "proto3";
package device.v1;
import "buf/validate/validate.proto";
import "device/v1/device.proto";
import "device/v1/types.proto";
option go_package = "github.com/tigorlazuardi/bluemage/go/gen/proto/device/v1";

View file

@ -2,8 +2,7 @@ syntax = "proto3";
package device.v1;
// import "buf/validate/validate.proto";
import "device/v1/get.proto";
import "device/v1/types.proto";
option go_package = "github.com/tigorlazuardi/bluemage/go/gen/proto/device/v1";
@ -28,12 +27,12 @@ message ListDevicesRequest {
// if value is 0 or not given, limit is set to 25.
//
// if limit is higher than 100, it is clamped to 100.
uint32 limit = 3;
int64 limit = 3;
// offset for the given data.
//
// If offset is 0 or not given, the query begins from start.
uint32 offset = 4;
int64 offset = 4;
// order_by is the field to order the devices by.
//
@ -47,7 +46,7 @@ message ListDevicesRequest {
}
message ListDevicesResponse {
repeated GetDeviceResponse devices = 1;
repeated Device devices = 1;
}
enum DisabledFilter {

View file

@ -0,0 +1,22 @@
syntax = "proto3";
package device.v1;
option go_package = "github.com/tigorlazuardi/bluemage/go/gen/proto/device/v1";
message Device {
string slug = 1;
bool disabled = 2;
string name = 3;
double resolution_x = 4;
double resolution_y = 5;
double aspect_ratio_tolerance = 6;
int32 min_x = 7;
int32 min_y = 8;
int32 max_x = 9;
int32 max_y = 10;
bool nsfw = 11;
bool single_folder_mode = 12;
int64 created_at = 13;
int64 updated_at = 14;
}