added pagination

main
alex 2023-10-13 16:26:25 +02:00
parent 6f98311916
commit c8ea1f6ee9
12 changed files with 234 additions and 48 deletions

8
go.mod
View File

@ -3,11 +3,13 @@ module jannex/robot-control-manager
go 1.21.0 go 1.21.0
require ( require (
git.ex.umbach.dev/Alex/roese-utils v1.0.10 git.ex.umbach.dev/Alex/roese-utils v1.0.14
github.com/gofiber/fiber/v2 v2.49.2 github.com/gofiber/fiber/v2 v2.49.2
github.com/google/uuid v1.3.1
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
github.com/rs/zerolog v1.31.0
gorm.io/driver/mysql v1.5.1 gorm.io/driver/mysql v1.5.1
gorm.io/gorm v1.25.4 gorm.io/gorm v1.25.5
) )
require ( require (
@ -17,7 +19,6 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.15.5 // indirect github.com/go-playground/validator/v10 v10.15.5 // indirect
github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.17.0 // indirect github.com/klauspost/compress v1.17.0 // indirect
@ -26,7 +27,6 @@ require (
github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/rivo/uniseg v0.4.4 // indirect github.com/rivo/uniseg v0.4.4 // indirect
github.com/rs/zerolog v1.31.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.50.0 // indirect github.com/valyala/fasthttp v1.50.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect

18
go.sum
View File

@ -1,9 +1,11 @@
git.ex.umbach.dev/Alex/roese-utils v1.0.8 h1:ph18N52R9UsJ0AsJW95W6afa9qKlMDMh60xE4wlfFi8= git.ex.umbach.dev/Alex/roese-utils v1.0.11 h1:iPrVktpUG0WYLTexoI3iJqi/KojaB5Cs0hCF/GFs92c=
git.ex.umbach.dev/Alex/roese-utils v1.0.8/go.mod h1:tjq6m6lNFo0TzAvq8jHhlK48IGxi+SrlrQwf9WYg408= git.ex.umbach.dev/Alex/roese-utils v1.0.11/go.mod h1:mov3ZaoSu+GBQU1uXN/AfSK6MF3/3WxUk38Tb6IKxbI=
git.ex.umbach.dev/Alex/roese-utils v1.0.9 h1:MshCYgFc22t4h9KjfE4hvuHbUcrqkbzxC3J4nqGoyuk= git.ex.umbach.dev/Alex/roese-utils v1.0.12 h1:Sw9lJ2nZXpU3GIZVJ5SeUzcNQ+VJenvwQCSgJI5+Qvs=
git.ex.umbach.dev/Alex/roese-utils v1.0.9/go.mod h1:tjq6m6lNFo0TzAvq8jHhlK48IGxi+SrlrQwf9WYg408= git.ex.umbach.dev/Alex/roese-utils v1.0.12/go.mod h1:mov3ZaoSu+GBQU1uXN/AfSK6MF3/3WxUk38Tb6IKxbI=
git.ex.umbach.dev/Alex/roese-utils v1.0.10 h1:pAtvtWrDSuVKGyusKPG093+DsnNc2ek/6k/9Qgz7acE= git.ex.umbach.dev/Alex/roese-utils v1.0.13 h1:zPFUQda4ljskCFdGdV69jjAiblTdIMrubw70Hyrf254=
git.ex.umbach.dev/Alex/roese-utils v1.0.10/go.mod h1:tjq6m6lNFo0TzAvq8jHhlK48IGxi+SrlrQwf9WYg408= git.ex.umbach.dev/Alex/roese-utils v1.0.13/go.mod h1:mov3ZaoSu+GBQU1uXN/AfSK6MF3/3WxUk38Tb6IKxbI=
git.ex.umbach.dev/Alex/roese-utils v1.0.14 h1:OdV3RTXOsMZHntUgAl00g+zMux58gUqzRTPw/KNdTAg=
git.ex.umbach.dev/Alex/roese-utils v1.0.14/go.mod h1:mov3ZaoSu+GBQU1uXN/AfSK6MF3/3WxUk38Tb6IKxbI=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
@ -85,5 +87,5 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw= gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw=
gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o= gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o=
gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=

View File

@ -77,8 +77,6 @@ func main() {
robot.LoadRobotsFromDatabase() robot.LoadRobotsFromDatabase()
fmt.Println("loaded robots", cache.GetAllRobots())
go robot.RobotPingHandler() go robot.RobotPingHandler()
rcmlogger.AddSystemLog("Server started") rcmlogger.AddSystemLog("Server started")

View File

@ -2,7 +2,10 @@ package cache
import ( import (
"jannex/robot-control-manager/modules/structs" "jannex/robot-control-manager/modules/structs"
"jannex/robot-control-manager/modules/utils"
"sync" "sync"
"git.ex.umbach.dev/Alex/roese-utils/rspagination"
) )
var robots = make(map[string]*structs.Robot) var robots = make(map[string]*structs.Robot)
@ -31,7 +34,7 @@ func GetRobots() map[string]*structs.Robot {
return robots return robots
} }
func GetAllRobots() []structs.Robot { func GetAllRobots(query rspagination.PageQuery) structs.RobotsResponse {
rMu.RLock() rMu.RLock()
defer rMu.RUnlock() defer rMu.RUnlock()
@ -41,7 +44,12 @@ func GetAllRobots() []structs.Robot {
r = append(r, *v) r = append(r, *v)
} }
return r start, end := rspagination.GetPage(len(r), query.Page, utils.RobotsPageLimit)
return structs.RobotsResponse{
Robots: r[start:end],
TotalPages: rspagination.CalculateTotalPages(len(r), utils.RobotsPageLimit),
}
} }
func IsRobotInList(robotId string) bool { func IsRobotInList(robotId string) bool {

View File

@ -3,6 +3,8 @@ package cache
import ( import (
"jannex/robot-control-manager/modules/structs" "jannex/robot-control-manager/modules/structs"
"sync" "sync"
"git.ex.umbach.dev/Alex/roese-utils/rspagination"
) )
// list of robots that are connected for the first time // list of robots that are connected for the first time
@ -24,7 +26,7 @@ func GetUnauthorizedRobots() map[string]*structs.UnauthorizedRobot {
return unauthorizedRobots return unauthorizedRobots
} }
func GetAllUnauthorizedRobots() []structs.UnauthorizedRobot { func GetAllUnauthorizedRobots(query rspagination.PageQuery) structs.UnauthorizedRobotsResponse {
urMu.RLock() urMu.RLock()
defer urMu.RUnlock() defer urMu.RUnlock()
@ -34,7 +36,12 @@ func GetAllUnauthorizedRobots() []structs.UnauthorizedRobot {
r = append(r, *v) r = append(r, *v)
} }
return r start, end := rspagination.GetPage(len(r), query.Page, 10)
return structs.UnauthorizedRobotsResponse{
UnauthorizedRobots: r[start:end],
TotalPages: rspagination.CalculateTotalPages(len(r), 10),
}
} }
func IsUnauthorizedRobotInList(robotId string) bool { func IsUnauthorizedRobotInList(robotId string) bool {

View File

@ -31,7 +31,7 @@ func RobotPingHandler() {
logger.AddSystemLog("Robot %s marked as offline because %v attempts have already been made to reach it", robot.Name, utils.RobotPingRetries) logger.AddSystemLog("Robot %s marked as offline because %v attempts have already been made to reach it", robot.Name, utils.RobotPingRetries)
cache.RemoveRobotById(robot.Id) //cache.RemoveRobotById(robot.Id)
continue continue
} }

View File

@ -93,10 +93,16 @@ type StatusResponse struct {
Status string Status string
} }
// swagger:model GetRobotsResponse // swagger:model RobotsResponse
type GetRobotsResponse struct { type RobotsResponse struct {
Robots []Robot Robots []Robot
TotalPages int
}
// swagger:model UnauthorizedRobotsResponse
type UnauthorizedRobotsResponse struct {
UnauthorizedRobots []UnauthorizedRobot UnauthorizedRobots []UnauthorizedRobot
TotalPages int
} }
type RobotIdParams struct { type RobotIdParams struct {

View File

@ -3,6 +3,8 @@ package utils
const ( const (
RobotPingRetries = 3 RobotPingRetries = 3
RobotPingHandlerInterval = 5 // seconds RobotPingHandlerInterval = 5 // seconds
RobotsPageLimit = 10
UnauthorizedRobotsPageLimit = 10
) )
const ( const (

View File

@ -29,17 +29,54 @@
], ],
"summary": "Get all robots", "summary": "Get all robots",
"operationId": "getRobots", "operationId": "getRobots",
"parameters": [
{
"description": "Page number",
"name": "page",
"in": "query"
}
],
"responses": { "responses": {
"200": { "200": {
"description": "", "description": "",
"schema": { "schema": {
"$ref": "#/definitions/GetRobotsResponse" "$ref": "#/definitions/RobotsResponse"
} }
} }
} }
} }
}, },
"/control/0": { "/api/v1/urobots": {
"get": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"robots"
],
"summary": "Get all unauthorized robots",
"operationId": "getUnauthorizedRobots",
"parameters": [
{
"description": "Page number",
"name": "page",
"in": "query"
}
],
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/UnauthorizedRobotsResponse"
}
}
}
}
},
"/control/1": {
"post": { "post": {
"description": "This is used to control Rex.\n", "description": "This is used to control Rex.\n",
"consumes": [ "consumes": [
@ -67,6 +104,39 @@
"responses": { "responses": {
"200": { "200": {
"description": "Control Rex" "description": "Control Rex"
},
"400": {
"description": "Invalid request body"
},
"422": {
"description": "Robot not found"
}
}
}
},
"/control/1/finish": {
"post": {
"description": "This is used to finish control Rex.\n",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"control"
],
"summary": "Finish control Rex.",
"operationId": "finishControlRex",
"responses": {
"200": {
"description": "Finish control Rex"
},
"400": {
"description": "Invalid robot name"
},
"422": {
"description": "Robot not found"
} }
} }
} }
@ -97,6 +167,9 @@
"responses": { "responses": {
"200": { "200": {
"description": "Permit join set" "description": "Permit join set"
},
"400": {
"description": "Invalid request body"
} }
} }
} }
@ -132,6 +205,12 @@
"schema": { "schema": {
"$ref": "#/definitions/StatusResponse" "$ref": "#/definitions/StatusResponse"
} }
},
"400": {
"description": "Invalid request body"
},
"403": {
"description": "Permit join is enabled"
} }
} }
} }
@ -164,6 +243,9 @@
"200": { "200": {
"description": "Robot authorized" "description": "Robot authorized"
}, },
"400": {
"description": "Invalid robot id"
},
"422": { "422": {
"description": "Robot not found" "description": "Robot not found"
} }
@ -299,23 +381,11 @@
}, },
"x-go-package": "jannex/robot-control-manager/modules/structs" "x-go-package": "jannex/robot-control-manager/modules/structs"
}, },
"GetRobotsResponse": { "Mutex": {
"description": "A Mutex must not be copied after first use.\n\nIn the terminology of the Go memory model,\nthe n'th call to Unlock “synchronizes before” the m'th call to Lock\nfor any n \u003c m.\nA successful call to TryLock is equivalent to a call to Lock.\nA failed call to TryLock does not establish any “synchronizes before”\nrelation at all.",
"type": "object", "type": "object",
"properties": { "title": "A Mutex is a mutual exclusion lock.\nThe zero value for a Mutex is an unlocked mutex.",
"Robots": { "x-go-package": "sync"
"type": "array",
"items": {
"$ref": "#/definitions/Robot"
}
},
"UnauthorizedRobots": {
"type": "array",
"items": {
"$ref": "#/definitions/UnauthorizedRobot"
}
}
},
"x-go-package": "jannex/robot-control-manager/modules/structs"
}, },
"Robot": { "Robot": {
"type": "object", "type": "object",
@ -334,15 +404,36 @@
"CurrentJobId": { "CurrentJobId": {
"type": "string" "type": "string"
}, },
"CurrentTask": { "CurrentJobName": {
"type": "string" "type": "string"
}, },
"Id": { "Id": {
"type": "string" "type": "string"
}, },
"JobMutex": {
"$ref": "#/definitions/Mutex"
},
"JobsWaitingCount": {
"type": "integer",
"format": "int64"
},
"JobsWaitingNameList": {
"type": "array",
"items": {
"type": "string"
}
},
"LastTaskAt": {
"type": "string",
"format": "date-time"
},
"Name": { "Name": {
"type": "string" "type": "string"
}, },
"PingRetries": {
"type": "integer",
"format": "uint8"
},
"Status": { "Status": {
"type": "integer", "type": "integer",
"format": "uint8" "format": "uint8"
@ -354,6 +445,22 @@
}, },
"x-go-package": "jannex/robot-control-manager/modules/structs" "x-go-package": "jannex/robot-control-manager/modules/structs"
}, },
"RobotsResponse": {
"type": "object",
"properties": {
"Robots": {
"type": "array",
"items": {
"$ref": "#/definitions/Robot"
}
},
"TotalPages": {
"type": "integer",
"format": "int64"
}
},
"x-go-package": "jannex/robot-control-manager/modules/structs"
},
"StatusResponse": { "StatusResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -386,6 +493,22 @@
} }
}, },
"x-go-package": "jannex/robot-control-manager/modules/structs" "x-go-package": "jannex/robot-control-manager/modules/structs"
},
"UnauthorizedRobotsResponse": {
"type": "object",
"properties": {
"TotalPages": {
"type": "integer",
"format": "int64"
},
"UnauthorizedRobots": {
"type": "array",
"items": {
"$ref": "#/definitions/UnauthorizedRobot"
}
}
},
"x-go-package": "jannex/robot-control-manager/modules/structs"
} }
} }
} }

View File

@ -43,5 +43,7 @@ func SetPermitJoin(c *fiber.Ctx) error {
logger.AddSystemLog("Permit join enabled") logger.AddSystemLog("Permit join enabled")
} }
// TODO: sse
return c.SendStatus(fiber.StatusOK) return c.SendStatus(fiber.StatusOK)
} }

View File

@ -2,8 +2,9 @@ package robots
import ( import (
"jannex/robot-control-manager/modules/cache" "jannex/robot-control-manager/modules/cache"
"jannex/robot-control-manager/modules/structs"
"git.ex.umbach.dev/Alex/roese-utils/rspagination"
"git.ex.umbach.dev/Alex/roese-utils/rsutils"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
@ -15,12 +16,46 @@ func GetRobots(c *fiber.Ctx) error {
// - application/json // - application/json
// produces: // produces:
// - application/json // - application/json
// parameters:
// - name: page
// in: query
// description: Page number
// responses: // responses:
// "200": // "200":
// schema: // schema:
// "$ref": "#/definitions/GetRobotsResponse" // "$ref": "#/definitions/RobotsResponse"
return c.JSON(structs.GetRobotsResponse{ var query rspagination.PageQuery
Robots: cache.GetAllRobots(),
UnauthorizedRobots: cache.GetAllUnauthorizedRobots()}) if err := rsutils.QueryParserHelper(c, &query); err != nil {
return c.SendStatus(fiber.StatusBadRequest)
}
return c.JSON(cache.GetAllRobots(query))
}
func GetUnauthorizedRobots(c *fiber.Ctx) error {
// swagger:operation GET /api/v1/urobots robots getUnauthorizedRobots
// ---
// summary: Get all unauthorized robots
// consumes:
// - application/json
// produces:
// - application/json
// parameters:
// - name: page
// in: query
// description: Page number
// responses:
// "200":
// schema:
// "$ref": "#/definitions/UnauthorizedRobotsResponse"
var query rspagination.PageQuery
if err := rsutils.QueryParserHelper(c, &query); err != nil {
return c.SendStatus(fiber.StatusBadRequest)
}
return c.JSON(cache.GetAllUnauthorizedRobots(query))
} }

View File

@ -21,6 +21,9 @@ func SetupRoutes(app *fiber.App) {
rs := v1.Group("/robots") rs := v1.Group("/robots")
rs.Get("/", robots.GetRobots) rs.Get("/", robots.GetRobots)
rsu := v1.Group("/urobots")
rsu.Get("/", robots.GetUnauthorizedRobots)
c := v1.Group("/control") c := v1.Group("/control")
c.Post("/1", control.ControlRex) c.Post("/1", control.ControlRex)
c.Post("/1/finish", control.FinishControlRex) c.Post("/1/finish", control.FinishControlRex)