diff --git a/backend_go/Dockerfile b/backend_go/Dockerfile index 9754d25..f71fe82 100644 --- a/backend_go/Dockerfile +++ b/backend_go/Dockerfile @@ -1,4 +1,5 @@ -FROM golang:1.22-alpine AS builder +ARG GO_VERSION=1.24 +FROM golang:${GO_VERSION}-alpine AS builder WORKDIR /src diff --git a/backend_go/graph_export.go b/backend_go/graph_export.go index 2c676d9..4fc980f 100644 --- a/backend_go/graph_export.go +++ b/backend_go/graph_export.go @@ -15,10 +15,10 @@ func graphFromSparqlBindings( nodeLimit int, includeBNodes bool, ) (nodes []Node, edges []Edge) { - nodeIDByKey := map[termKey]int{} + nodeIDByKey := map[termKey]uint32{} nodeMeta := make([]termMeta, 0, min(nodeLimit, 4096)) - getOrAdd := func(term sparqlTerm) (int, bool) { + getOrAdd := func(term sparqlTerm) (uint32, bool) { if term.Type == "" || term.Value == "" { return 0, false } @@ -46,7 +46,7 @@ func graphFromSparqlBindings( if len(nodeMeta) >= nodeLimit { return 0, false } - nid := len(nodeMeta) + nid := uint32(len(nodeMeta)) nodeIDByKey[key] = nid nodeMeta = append(nodeMeta, meta) return nid, true @@ -78,7 +78,7 @@ func graphFromSparqlBindings( nodes = make([]Node, len(nodeMeta)) for i, m := range nodeMeta { nodes[i] = Node{ - ID: i, + ID: uint32(i), TermType: m.termType, IRI: m.iri, Label: nil, diff --git a/backend_go/graph_snapshot.go b/backend_go/graph_snapshot.go index 3048dfa..6f3b3f3 100644 --- a/backend_go/graph_snapshot.go +++ b/backend_go/graph_snapshot.go @@ -40,7 +40,7 @@ func fetchGraphSnapshot( // Layout: invert edges for hierarchy (target -> source). hierEdges := make([][2]int, 0, len(edges)) for _, e := range edges { - hierEdges = append(hierEdges, [2]int{e.Target, e.Source}) + hierEdges = append(hierEdges, [2]int{int(e.Target), int(e.Source)}) } layers, cycleErr := levelSynchronousKahnLayers(len(nodes), hierEdges) diff --git a/backend_go/models.go b/backend_go/models.go index 69ce343..2abd658 100644 --- a/backend_go/models.go +++ b/backend_go/models.go @@ -9,7 +9,7 @@ type HealthResponse struct { } type Node struct { - ID int `json:"id"` + ID uint32 `json:"id"` TermType string `json:"termType"` // "uri" | "bnode" IRI string `json:"iri"` Label *string `json:"label"` @@ -18,8 +18,8 @@ type Node struct { } type Edge struct { - Source int `json:"source"` - Target int `json:"target"` + Source uint32 `json:"source"` + Target uint32 `json:"target"` Predicate string `json:"predicate"` } @@ -55,27 +55,27 @@ type SparqlQueryRequest struct { } type NeighborsRequest struct { - SelectedIDs []int `json:"selected_ids"` - NodeLimit *int `json:"node_limit,omitempty"` - EdgeLimit *int `json:"edge_limit,omitempty"` - GraphQueryID *string `json:"graph_query_id,omitempty"` + SelectedIDs []uint32 `json:"selected_ids"` + NodeLimit *int `json:"node_limit,omitempty"` + EdgeLimit *int `json:"edge_limit,omitempty"` + GraphQueryID *string `json:"graph_query_id,omitempty"` } type NeighborsResponse struct { - SelectedIDs []int `json:"selected_ids"` - NeighborIDs []int `json:"neighbor_ids"` + SelectedIDs []uint32 `json:"selected_ids"` + NeighborIDs []uint32 `json:"neighbor_ids"` } type SelectionQueryRequest struct { - QueryID string `json:"query_id"` - SelectedIDs []int `json:"selected_ids"` - NodeLimit *int `json:"node_limit,omitempty"` - EdgeLimit *int `json:"edge_limit,omitempty"` - GraphQueryID *string `json:"graph_query_id,omitempty"` + QueryID string `json:"query_id"` + SelectedIDs []uint32 `json:"selected_ids"` + NodeLimit *int `json:"node_limit,omitempty"` + EdgeLimit *int `json:"edge_limit,omitempty"` + GraphQueryID *string `json:"graph_query_id,omitempty"` } type SelectionQueryResponse struct { - QueryID string `json:"query_id"` - SelectedIDs []int `json:"selected_ids"` - NeighborIDs []int `json:"neighbor_ids"` + QueryID string `json:"query_id"` + SelectedIDs []uint32 `json:"selected_ids"` + NeighborIDs []uint32 `json:"neighbor_ids"` } diff --git a/backend_go/selection_queries/helpers.go b/backend_go/selection_queries/helpers.go index 89916b3..4563cde 100644 --- a/backend_go/selection_queries/helpers.go +++ b/backend_go/selection_queries/helpers.go @@ -49,9 +49,9 @@ func termKeyFromSparqlTerm(term sparqlTerm, includeBNodes bool) (string, bool) { return "", false } -func selectedNodesFromIDs(idx Index, selectedIDs []int, includeBNodes bool) ([]NodeRef, map[int]struct{}) { +func selectedNodesFromIDs(idx Index, selectedIDs []uint32, includeBNodes bool) ([]NodeRef, map[uint32]struct{}) { out := make([]NodeRef, 0, len(selectedIDs)) - set := make(map[int]struct{}, len(selectedIDs)) + set := make(map[uint32]struct{}, len(selectedIDs)) for _, nid := range selectedIDs { n, ok := idx.IDToNode[nid] if !ok { @@ -66,13 +66,13 @@ func selectedNodesFromIDs(idx Index, selectedIDs []int, includeBNodes bool) ([]N return out, set } -func idsFromBindings(raw []byte, varName string, idx Index, selectedSet map[int]struct{}, includeBNodes bool) ([]int, error) { +func idsFromBindings(raw []byte, varName string, idx Index, selectedSet map[uint32]struct{}, includeBNodes bool) ([]uint32, error) { var res sparqlResponse if err := json.Unmarshal(raw, &res); err != nil { return nil, fmt.Errorf("failed to parse SPARQL JSON: %w", err) } - neighborSet := make(map[int]struct{}) + neighborSet := make(map[uint32]struct{}) for _, b := range res.Results.Bindings { term, ok := b[varName] if !ok { @@ -92,11 +92,10 @@ func idsFromBindings(raw []byte, varName string, idx Index, selectedSet map[int] neighborSet[nid] = struct{}{} } - ids := make([]int, 0, len(neighborSet)) + ids := make([]uint32, 0, len(neighborSet)) for nid := range neighborSet { ids = append(ids, nid) } - sort.Ints(ids) + sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] }) return ids, nil } - diff --git a/backend_go/selection_queries/neighbors.go b/backend_go/selection_queries/neighbors.go index 102f47c..60ccd91 100644 --- a/backend_go/selection_queries/neighbors.go +++ b/backend_go/selection_queries/neighbors.go @@ -62,10 +62,10 @@ WHERE { `, values, bnodeFilter) } -func runNeighbors(ctx context.Context, q Querier, idx Index, selectedIDs []int, includeBNodes bool) ([]int, error) { +func runNeighbors(ctx context.Context, q Querier, idx Index, selectedIDs []uint32, includeBNodes bool) ([]uint32, error) { selectedNodes, selectedSet := selectedNodesFromIDs(idx, selectedIDs, includeBNodes) if len(selectedNodes) == 0 { - return []int{}, nil + return []uint32{}, nil } raw, err := q.Query(ctx, neighborsQuery(selectedNodes, includeBNodes)) @@ -74,4 +74,3 @@ func runNeighbors(ctx context.Context, q Querier, idx Index, selectedIDs []int, } return idsFromBindings(raw, "nbr", idx, selectedSet, includeBNodes) } - diff --git a/backend_go/selection_queries/subclasses.go b/backend_go/selection_queries/subclasses.go index c14c4e1..9de4151 100644 --- a/backend_go/selection_queries/subclasses.go +++ b/backend_go/selection_queries/subclasses.go @@ -40,10 +40,10 @@ WHERE { `, values, bnodeFilter) } -func runSubclasses(ctx context.Context, q Querier, idx Index, selectedIDs []int, includeBNodes bool) ([]int, error) { +func runSubclasses(ctx context.Context, q Querier, idx Index, selectedIDs []uint32, includeBNodes bool) ([]uint32, error) { selectedNodes, selectedSet := selectedNodesFromIDs(idx, selectedIDs, includeBNodes) if len(selectedNodes) == 0 { - return []int{}, nil + return []uint32{}, nil } raw, err := q.Query(ctx, subclassesQuery(selectedNodes, includeBNodes)) @@ -52,4 +52,3 @@ func runSubclasses(ctx context.Context, q Querier, idx Index, selectedIDs []int, } return idsFromBindings(raw, "nbr", idx, selectedSet, includeBNodes) } - diff --git a/backend_go/selection_queries/superclasses.go b/backend_go/selection_queries/superclasses.go index 8d2542e..8841941 100644 --- a/backend_go/selection_queries/superclasses.go +++ b/backend_go/selection_queries/superclasses.go @@ -40,10 +40,10 @@ WHERE { `, values, bnodeFilter) } -func runSuperclasses(ctx context.Context, q Querier, idx Index, selectedIDs []int, includeBNodes bool) ([]int, error) { +func runSuperclasses(ctx context.Context, q Querier, idx Index, selectedIDs []uint32, includeBNodes bool) ([]uint32, error) { selectedNodes, selectedSet := selectedNodesFromIDs(idx, selectedIDs, includeBNodes) if len(selectedNodes) == 0 { - return []int{}, nil + return []uint32{}, nil } raw, err := q.Query(ctx, superclassesQuery(selectedNodes, includeBNodes)) @@ -52,4 +52,3 @@ func runSuperclasses(ctx context.Context, q Querier, idx Index, selectedIDs []in } return idsFromBindings(raw, "nbr", idx, selectedSet, includeBNodes) } - diff --git a/backend_go/selection_queries/types.go b/backend_go/selection_queries/types.go index ed800c7..62467bb 100644 --- a/backend_go/selection_queries/types.go +++ b/backend_go/selection_queries/types.go @@ -7,14 +7,14 @@ type Querier interface { } type NodeRef struct { - ID int + ID uint32 TermType string // "uri" | "bnode" IRI string } type Index struct { - IDToNode map[int]NodeRef - KeyToID map[string]int + IDToNode map[uint32]NodeRef + KeyToID map[string]uint32 } type Meta struct { @@ -24,6 +24,5 @@ type Meta struct { type Definition struct { Meta Meta - Run func(ctx context.Context, q Querier, idx Index, selectedIDs []int, includeBNodes bool) ([]int, error) + Run func(ctx context.Context, q Querier, idx Index, selectedIDs []uint32, includeBNodes bool) ([]uint32, error) } - diff --git a/backend_go/selection_query.go b/backend_go/selection_query.go index f8935cd..825296d 100644 --- a/backend_go/selection_query.go +++ b/backend_go/selection_query.go @@ -12,16 +12,16 @@ func runSelectionQuery( sparql *AnzoGraphClient, snapshot GraphResponse, queryID string, - selectedIDs []int, + selectedIDs []uint32, includeBNodes bool, -) ([]int, error) { +) ([]uint32, error) { def, ok := selectionqueries.Get(queryID) if !ok { return nil, fmt.Errorf("unknown query_id: %s", queryID) } - idToNode := make(map[int]selectionqueries.NodeRef, len(snapshot.Nodes)) - keyToID := make(map[string]int, len(snapshot.Nodes)) + idToNode := make(map[uint32]selectionqueries.NodeRef, len(snapshot.Nodes)) + keyToID := make(map[string]uint32, len(snapshot.Nodes)) for _, n := range snapshot.Nodes { nr := selectionqueries.NodeRef{ID: n.ID, TermType: n.TermType, IRI: n.IRI} idToNode[n.ID] = nr @@ -30,4 +30,3 @@ func runSelectionQuery( return def.Run(ctx, sparql, selectionqueries.Index{IDToNode: idToNode, KeyToID: keyToID}, selectedIDs, includeBNodes) } - diff --git a/backend_go/server.go b/backend_go/server.go index 18ea5d9..9a1da31 100644 --- a/backend_go/server.go +++ b/backend_go/server.go @@ -189,7 +189,7 @@ func (s *APIServer) handleSelectionQuery(w http.ResponseWriter, r *http.Request) writeJSON(w, http.StatusOK, SelectionQueryResponse{ QueryID: req.QueryID, SelectedIDs: req.SelectedIDs, - NeighborIDs: []int{}, + NeighborIDs: []uint32{}, }) return } @@ -247,7 +247,7 @@ func (s *APIServer) handleNeighbors(w http.ResponseWriter, r *http.Request) { return } if len(req.SelectedIDs) == 0 { - writeJSON(w, http.StatusOK, NeighborsResponse{SelectedIDs: req.SelectedIDs, NeighborIDs: []int{}}) + writeJSON(w, http.StatusOK, NeighborsResponse{SelectedIDs: req.SelectedIDs, NeighborIDs: []uint32{}}) return }