From ef51f9b3ed07fe1e24070a302e66faa13bad5ca1 Mon Sep 17 00:00:00 2001 From: Klagarge Date: Thu, 21 May 2026 12:23:12 +0200 Subject: [PATCH] refactor(db): map room and node on REST API Signed-off-by: Klagarge --- db/src/mapping.go | 11 +++++++++++ db/src/rest/rest.go | 43 +++++++++++++++++++++++++++++++++---------- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/db/src/mapping.go b/db/src/mapping.go index e295d08..b2f77c9 100644 --- a/db/src/mapping.go +++ b/db/src/mapping.go @@ -79,6 +79,17 @@ func (c *MappingConfig) GetRoom(nodeID string) (string, bool) { return room, ok } +// NodesForRoom returns the list of node IDs that belong to the given room. +func (c *MappingConfig) NodesForRoom(room string) []string { + var nodes []string + for nodeID, r := range c.nodeToRoom { + if r == room { + nodes = append(nodes, nodeID) + } + } + return nodes +} + // Rooms returns the list of all room names defined in the mapping. func (c *MappingConfig) Rooms() []string { seen := make(map[string]struct{}) diff --git a/db/src/rest/rest.go b/db/src/rest/rest.go index 568ebfa..3d22092 100644 --- a/db/src/rest/rest.go +++ b/db/src/rest/rest.go @@ -3,12 +3,12 @@ package rest import ( "context" "fmt" + _ "gateway/docs" "gateway/influx" "net/http" "regexp" "slices" - - _ "gateway/docs" + "strings" "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" @@ -16,21 +16,22 @@ import ( ginSwagger "github.com/swaggo/gin-swagger" ) -// RoomLister is an interface for getting the list of rooms from the mapping. -type RoomLister interface { +// RoomMapper is an interface for mapping node IDs to rooms and listing rooms. +type RoomMapper interface { Rooms() []string + NodesForRoom(room string) []string } type RestGateway struct { influxGateway *influx.InfluxGateway - mapping RoomLister + mapping RoomMapper engine *gin.Engine measurementName string username string password string } -func NewRestGateway(influxGateway *influx.InfluxGateway, mapping RoomLister, measurementName string, username, password string) *RestGateway { +func NewRestGateway(influxGateway *influx.InfluxGateway, mapping RoomMapper, measurementName string, username, password string) *RestGateway { g := &RestGateway{ influxGateway: influxGateway, mapping: mapping, @@ -75,6 +76,15 @@ func (g *RestGateway) setupRoutes() { g.engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) } +// buildNodeFilter builds a SQL WHERE clause fragment matching any of the given node IDs. +func buildNodeFilter(nodes []string) string { + parts := make([]string, len(nodes)) + for i, n := range nodes { + parts[i] = fmt.Sprintf(`"node" = '%s'`, n) + } + return "(" + strings.Join(parts, " OR ") + ")" +} + func (g *RestGateway) Run(addr string) error { return g.engine.Run(addr) } @@ -110,8 +120,15 @@ func (g *RestGateway) getRooms(c *gin.Context) { func (g *RestGateway) getRoomCurrent(c *gin.Context) { roomID := c.Param("room-id") - // Get the last record for the specific room - query := fmt.Sprintf(`SELECT * FROM "%s" WHERE "room" = '%s' AND time > now() - INTERVAL '1 days' ORDER BY time DESC LIMIT 1`, g.measurementName, roomID) + nodes := g.mapping.NodesForRoom(roomID) + if len(nodes) == 0 { + c.JSON(http.StatusNotFound, gin.H{"error": "Room not found in mapping"}) + return + } + nodeFilter := buildNodeFilter(nodes) + + // Get the last record for the specific room by matching node IDs + query := fmt.Sprintf(`SELECT * FROM "%s" WHERE %s AND time > now() - INTERVAL '1 days' ORDER BY time DESC LIMIT 1`, g.measurementName, nodeFilter) // Using context.Background() as seen in working snippet it, err := g.influxGateway.Query(context.Background(), query) @@ -149,8 +166,14 @@ func (g *RestGateway) getRoomHistory(c *gin.Context) { roomID := c.Param("room-id") window := c.DefaultQuery("window", "1 day") - query := fmt.Sprintf(` SELECT * FROM "%s" WHERE "room" = '%s' AND time > now() - INTERVAL '%s' ORDER BY time ASC -`, g.measurementName, roomID, window) + nodes := g.mapping.NodesForRoom(roomID) + if len(nodes) == 0 { + c.JSON(http.StatusNotFound, gin.H{"error": "Room not found in mapping"}) + return + } + nodeFilter := buildNodeFilter(nodes) + + query := fmt.Sprintf(`SELECT * FROM "%s" WHERE %s AND time > now() - INTERVAL '%s' ORDER BY time ASC`, g.measurementName, nodeFilter, window) // Using context.Background() as seen in working snippet it, err := g.influxGateway.Query(context.Background(), query)