diff --git a/go.mod b/go.mod index ca26352..6072074 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,13 @@ module jannex/robot-control-manager go 1.21.0 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/google/uuid v1.3.1 github.com/joho/godotenv v1.5.1 + github.com/rs/zerolog v1.31.0 gorm.io/driver/mysql v1.5.1 - gorm.io/gorm v1.25.4 + gorm.io/gorm v1.25.5 ) require ( @@ -17,7 +19,6 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.15.5 // 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/now v1.1.5 // 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-runewidth v0.0.15 // 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/fasthttp v1.50.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect diff --git a/go.sum b/go.sum index 84f0d94..1abe275 100644 --- a/go.sum +++ b/go.sum @@ -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.8/go.mod h1:tjq6m6lNFo0TzAvq8jHhlK48IGxi+SrlrQwf9WYg408= -git.ex.umbach.dev/Alex/roese-utils v1.0.9 h1:MshCYgFc22t4h9KjfE4hvuHbUcrqkbzxC3J4nqGoyuk= -git.ex.umbach.dev/Alex/roese-utils v1.0.9/go.mod h1:tjq6m6lNFo0TzAvq8jHhlK48IGxi+SrlrQwf9WYg408= -git.ex.umbach.dev/Alex/roese-utils v1.0.10 h1:pAtvtWrDSuVKGyusKPG093+DsnNc2ek/6k/9Qgz7acE= -git.ex.umbach.dev/Alex/roese-utils v1.0.10/go.mod h1:tjq6m6lNFo0TzAvq8jHhlK48IGxi+SrlrQwf9WYg408= +git.ex.umbach.dev/Alex/roese-utils v1.0.11 h1:iPrVktpUG0WYLTexoI3iJqi/KojaB5Cs0hCF/GFs92c= +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.12 h1:Sw9lJ2nZXpU3GIZVJ5SeUzcNQ+VJenvwQCSgJI5+Qvs= +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.13 h1:zPFUQda4ljskCFdGdV69jjAiblTdIMrubw70Hyrf254= +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/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= 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/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o= 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.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= +gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= diff --git a/main.go b/main.go index 9ea161d..1dd86a8 100644 --- a/main.go +++ b/main.go @@ -77,8 +77,6 @@ func main() { robot.LoadRobotsFromDatabase() - fmt.Println("loaded robots", cache.GetAllRobots()) - go robot.RobotPingHandler() rcmlogger.AddSystemLog("Server started") diff --git a/modules/cache/robots.go b/modules/cache/robots.go index 18454b0..97ff6fc 100644 --- a/modules/cache/robots.go +++ b/modules/cache/robots.go @@ -2,7 +2,10 @@ package cache import ( "jannex/robot-control-manager/modules/structs" + "jannex/robot-control-manager/modules/utils" "sync" + + "git.ex.umbach.dev/Alex/roese-utils/rspagination" ) var robots = make(map[string]*structs.Robot) @@ -31,7 +34,7 @@ func GetRobots() map[string]*structs.Robot { return robots } -func GetAllRobots() []structs.Robot { +func GetAllRobots(query rspagination.PageQuery) structs.RobotsResponse { rMu.RLock() defer rMu.RUnlock() @@ -41,7 +44,12 @@ func GetAllRobots() []structs.Robot { 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 { diff --git a/modules/cache/unauthorizedrobots.go b/modules/cache/unauthorizedrobots.go index ee1c7a1..13ab3fb 100644 --- a/modules/cache/unauthorizedrobots.go +++ b/modules/cache/unauthorizedrobots.go @@ -3,6 +3,8 @@ package cache import ( "jannex/robot-control-manager/modules/structs" "sync" + + "git.ex.umbach.dev/Alex/roese-utils/rspagination" ) // list of robots that are connected for the first time @@ -24,7 +26,7 @@ func GetUnauthorizedRobots() map[string]*structs.UnauthorizedRobot { return unauthorizedRobots } -func GetAllUnauthorizedRobots() []structs.UnauthorizedRobot { +func GetAllUnauthorizedRobots(query rspagination.PageQuery) structs.UnauthorizedRobotsResponse { urMu.RLock() defer urMu.RUnlock() @@ -34,7 +36,12 @@ func GetAllUnauthorizedRobots() []structs.UnauthorizedRobot { 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 { diff --git a/modules/robot/robot.go b/modules/robot/robot.go index 64f7830..0606197 100644 --- a/modules/robot/robot.go +++ b/modules/robot/robot.go @@ -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) - cache.RemoveRobotById(robot.Id) + //cache.RemoveRobotById(robot.Id) continue } diff --git a/modules/structs/robot.go b/modules/structs/robot.go index 05e9545..873f7ea 100644 --- a/modules/structs/robot.go +++ b/modules/structs/robot.go @@ -93,10 +93,16 @@ type StatusResponse struct { Status string } -// swagger:model GetRobotsResponse -type GetRobotsResponse struct { - Robots []Robot +// swagger:model RobotsResponse +type RobotsResponse struct { + Robots []Robot + TotalPages int +} + +// swagger:model UnauthorizedRobotsResponse +type UnauthorizedRobotsResponse struct { UnauthorizedRobots []UnauthorizedRobot + TotalPages int } type RobotIdParams struct { diff --git a/modules/utils/globals.go b/modules/utils/globals.go index 21734fc..c6685e8 100644 --- a/modules/utils/globals.go +++ b/modules/utils/globals.go @@ -1,8 +1,10 @@ package utils const ( - RobotPingRetries = 3 - RobotPingHandlerInterval = 5 // seconds + RobotPingRetries = 3 + RobotPingHandlerInterval = 5 // seconds + RobotsPageLimit = 10 + UnauthorizedRobotsPageLimit = 10 ) const ( diff --git a/public/swagger/swagger.json b/public/swagger/swagger.json index d782d22..05efcfb 100644 --- a/public/swagger/swagger.json +++ b/public/swagger/swagger.json @@ -29,17 +29,54 @@ ], "summary": "Get all robots", "operationId": "getRobots", + "parameters": [ + { + "description": "Page number", + "name": "page", + "in": "query" + } + ], "responses": { "200": { "description": "", "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": { "description": "This is used to control Rex.\n", "consumes": [ @@ -67,6 +104,39 @@ "responses": { "200": { "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": { "200": { "description": "Permit join set" + }, + "400": { + "description": "Invalid request body" } } } @@ -132,6 +205,12 @@ "schema": { "$ref": "#/definitions/StatusResponse" } + }, + "400": { + "description": "Invalid request body" + }, + "403": { + "description": "Permit join is enabled" } } } @@ -164,6 +243,9 @@ "200": { "description": "Robot authorized" }, + "400": { + "description": "Invalid robot id" + }, "422": { "description": "Robot not found" } @@ -299,23 +381,11 @@ }, "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", - "properties": { - "Robots": { - "type": "array", - "items": { - "$ref": "#/definitions/Robot" - } - }, - "UnauthorizedRobots": { - "type": "array", - "items": { - "$ref": "#/definitions/UnauthorizedRobot" - } - } - }, - "x-go-package": "jannex/robot-control-manager/modules/structs" + "title": "A Mutex is a mutual exclusion lock.\nThe zero value for a Mutex is an unlocked mutex.", + "x-go-package": "sync" }, "Robot": { "type": "object", @@ -334,15 +404,36 @@ "CurrentJobId": { "type": "string" }, - "CurrentTask": { + "CurrentJobName": { "type": "string" }, "Id": { "type": "string" }, + "JobMutex": { + "$ref": "#/definitions/Mutex" + }, + "JobsWaitingCount": { + "type": "integer", + "format": "int64" + }, + "JobsWaitingNameList": { + "type": "array", + "items": { + "type": "string" + } + }, + "LastTaskAt": { + "type": "string", + "format": "date-time" + }, "Name": { "type": "string" }, + "PingRetries": { + "type": "integer", + "format": "uint8" + }, "Status": { "type": "integer", "format": "uint8" @@ -354,6 +445,22 @@ }, "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": { "type": "object", "properties": { @@ -386,6 +493,22 @@ } }, "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" } } } \ No newline at end of file diff --git a/routers/api/v1/permitjoin/permitjoin.go b/routers/api/v1/permitjoin/permitjoin.go index 70f5d61..2137baa 100644 --- a/routers/api/v1/permitjoin/permitjoin.go +++ b/routers/api/v1/permitjoin/permitjoin.go @@ -43,5 +43,7 @@ func SetPermitJoin(c *fiber.Ctx) error { logger.AddSystemLog("Permit join enabled") } + // TODO: sse + return c.SendStatus(fiber.StatusOK) } diff --git a/routers/api/v1/robots/robots.go b/routers/api/v1/robots/robots.go index 3e00ee5..7c5ca3c 100644 --- a/routers/api/v1/robots/robots.go +++ b/routers/api/v1/robots/robots.go @@ -2,8 +2,9 @@ package robots import ( "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" ) @@ -15,12 +16,46 @@ func GetRobots(c *fiber.Ctx) error { // - application/json // produces: // - application/json + // parameters: + // - name: page + // in: query + // description: Page number // responses: // "200": // schema: - // "$ref": "#/definitions/GetRobotsResponse" + // "$ref": "#/definitions/RobotsResponse" - return c.JSON(structs.GetRobotsResponse{ - Robots: cache.GetAllRobots(), - UnauthorizedRobots: cache.GetAllUnauthorizedRobots()}) + var query rspagination.PageQuery + + 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)) } diff --git a/routers/router/router.go b/routers/router/router.go index 8bfaed3..c6fe93c 100644 --- a/routers/router/router.go +++ b/routers/router/router.go @@ -21,6 +21,9 @@ func SetupRoutes(app *fiber.App) { rs := v1.Group("/robots") rs.Get("/", robots.GetRobots) + rsu := v1.Group("/urobots") + rsu.Get("/", robots.GetUnauthorizedRobots) + c := v1.Group("/control") c.Post("/1", control.ControlRex) c.Post("/1/finish", control.FinishControlRex)