mirror of
https://github.com/DeBrosOfficial/network.git
synced 2026-01-30 23:03:03 +00:00
102 lines
2.4 KiB
Go
102 lines
2.4 KiB
Go
package rqlite
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"time"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// RQLiteClient is a simple HTTP client for RQLite
|
|
type RQLiteClient struct {
|
|
baseURL string
|
|
httpClient *http.Client
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// QueryResponse represents the RQLite query response
|
|
type QueryResponse struct {
|
|
Results []QueryResult `json:"results"`
|
|
}
|
|
|
|
// QueryResult represents a single query result
|
|
type QueryResult struct {
|
|
Columns []string `json:"columns"`
|
|
Types []string `json:"types"`
|
|
Values [][]interface{} `json:"values"`
|
|
Error string `json:"error"`
|
|
}
|
|
|
|
// NewRQLiteClient creates a new RQLite HTTP client
|
|
func NewRQLiteClient(dsn string, logger *zap.Logger) (*RQLiteClient, error) {
|
|
return &RQLiteClient{
|
|
baseURL: dsn,
|
|
httpClient: &http.Client{
|
|
Timeout: 10 * time.Second,
|
|
Transport: &http.Transport{
|
|
MaxIdleConns: 10,
|
|
MaxIdleConnsPerHost: 10,
|
|
IdleConnTimeout: 90 * time.Second,
|
|
},
|
|
},
|
|
logger: logger,
|
|
}, nil
|
|
}
|
|
|
|
// Query executes a SQL query and returns the results
|
|
func (c *RQLiteClient) Query(ctx context.Context, query string, args ...interface{}) ([][]interface{}, error) {
|
|
// Build parameterized query
|
|
queries := [][]interface{}{append([]interface{}{query}, args...)}
|
|
|
|
reqBody, err := json.Marshal(queries)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to marshal query: %w", err)
|
|
}
|
|
|
|
url := c.baseURL + "/db/query"
|
|
req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(reqBody))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create request: %w", err)
|
|
}
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("request failed: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
body, _ := io.ReadAll(resp.Body)
|
|
return nil, fmt.Errorf("query failed with status %d: %s", resp.StatusCode, string(body))
|
|
}
|
|
|
|
var queryResp QueryResponse
|
|
if err := json.NewDecoder(resp.Body).Decode(&queryResp); err != nil {
|
|
return nil, fmt.Errorf("failed to decode response: %w", err)
|
|
}
|
|
|
|
if len(queryResp.Results) == 0 {
|
|
return [][]interface{}{}, nil
|
|
}
|
|
|
|
result := queryResp.Results[0]
|
|
if result.Error != "" {
|
|
return nil, fmt.Errorf("query error: %s", result.Error)
|
|
}
|
|
|
|
return result.Values, nil
|
|
}
|
|
|
|
// Close closes the HTTP client
|
|
func (c *RQLiteClient) Close() error {
|
|
c.httpClient.CloseIdleConnections()
|
|
return nil
|
|
}
|