chore: auto-commit (5 archivos)
- handlers.go - handlers_test.go - main.go - datafactory_events.go - handlers_datafactory.go Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+57
-8
@@ -2,12 +2,15 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"fn-registry/apps/data_factory/datafactory"
|
||||
"fn-registry/functions/infra"
|
||||
)
|
||||
|
||||
@@ -18,14 +21,48 @@ type Server struct {
|
||||
pool *DBPool
|
||||
registryRoot string // raiz del fn_registry (para exec fn ...)
|
||||
hub *CallMonitorHub
|
||||
dfHub *DataFactoryHub
|
||||
|
||||
// data_factory.db (RW) is opened lazily on first request and reused.
|
||||
dfPath string
|
||||
dfMigrationsDir string
|
||||
dfMu sync.Mutex
|
||||
dfDB *sql.DB
|
||||
dfErr error // sticky if a previous open failed
|
||||
}
|
||||
|
||||
func NewServer(pool *DBPool, registryRoot string) *Server {
|
||||
return &Server{
|
||||
pool: pool,
|
||||
registryRoot: registryRoot,
|
||||
hub: NewCallMonitorHub(pool),
|
||||
func NewServer(pool *DBPool, registryRoot, dfPath, dfMigrationsDir string) *Server {
|
||||
s := &Server{
|
||||
pool: pool,
|
||||
registryRoot: registryRoot,
|
||||
hub: NewCallMonitorHub(pool),
|
||||
dfPath: dfPath,
|
||||
dfMigrationsDir: dfMigrationsDir,
|
||||
}
|
||||
s.dfHub = NewDataFactoryHub(s.dataFactoryDB)
|
||||
return s
|
||||
}
|
||||
|
||||
// dataFactoryDB returns a RW connection to data_factory.db, lazy-opened on
|
||||
// first call. Subsequent calls return the cached connection. If the open
|
||||
// fails it is cached as a sticky error to avoid retry storms; retry after
|
||||
// process restart.
|
||||
func (s *Server) dataFactoryDB() (*sql.DB, error) {
|
||||
s.dfMu.Lock()
|
||||
defer s.dfMu.Unlock()
|
||||
if s.dfDB != nil {
|
||||
return s.dfDB, nil
|
||||
}
|
||||
if s.dfErr != nil {
|
||||
return nil, s.dfErr
|
||||
}
|
||||
db, err := datafactory.Open(s.dfPath, s.dfMigrationsDir)
|
||||
if err != nil {
|
||||
s.dfErr = err
|
||||
return nil, err
|
||||
}
|
||||
s.dfDB = db
|
||||
return db, nil
|
||||
}
|
||||
|
||||
// Routes registers all API routes on the given mux.
|
||||
@@ -50,6 +87,13 @@ func (s *Server) Routes(mux *http.ServeMux) {
|
||||
// Issue 0086: WebSocket live stream de ops:call_monitor (calls table).
|
||||
// Hub global con ticker bajo demanda (solo corre con >=1 subscriber).
|
||||
mux.HandleFunc("GET /api/events/call_monitor", s.handleEvents(s.hub))
|
||||
|
||||
// Issue 0097: data_factory.db (nodes, runs, databases).
|
||||
// REST read-only + WS live stream sobre `runs`.
|
||||
mux.HandleFunc("GET /api/datafactory/nodes", s.handleDataFactoryNodes)
|
||||
mux.HandleFunc("GET /api/datafactory/runs", s.handleDataFactoryRuns)
|
||||
mux.HandleFunc("GET /api/datafactory/databases", s.handleDataFactoryDatabases)
|
||||
mux.HandleFunc("GET /api/ws/datafactory", s.handleDataFactoryEvents(s.dfHub))
|
||||
}
|
||||
|
||||
func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -62,9 +106,14 @@ func (s *Server) handleDatabases(w http.ResponseWriter, r *http.Request) {
|
||||
Alias string `json:"alias"`
|
||||
Kind string `json:"kind"`
|
||||
}
|
||||
out := make([]dbInfo, len(entries))
|
||||
for i, e := range entries {
|
||||
out[i] = dbInfo{Alias: e.Alias, Kind: e.Kind}
|
||||
out := make([]dbInfo, 0, len(entries)+1)
|
||||
for _, e := range entries {
|
||||
out = append(out, dbInfo{Alias: e.Alias, Kind: e.Kind})
|
||||
}
|
||||
// Surface data_factory.db too. It is opened RW outside the pool but
|
||||
// belongs in the discovery list so dashboards can see it.
|
||||
if s.dfPath != "" {
|
||||
out = append(out, dbInfo{Alias: "data_factory", Kind: "data_factory"})
|
||||
}
|
||||
writeJSON(w, http.StatusOK, out)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user