veza/veza-backend-api/internal/elasticsearch/client.go
senke 171a154763 feat(v0.10.2): Recherche fulltext Elasticsearch - F361-F365
- Elasticsearch 8.x dans docker-compose.dev
- Package internal/elasticsearch: client, config, mappings, indices
- Sync PG→ES: reindex tracks/users/playlists, IndexTrack/DeleteTrack
- SearchService ES: multi_match + fuzziness (typo tolerance), highlighting
- Fallback gracieux: PostgreSQL si ELASTICSEARCH_URL absent
- Routes: GET /search, GET /search/suggestions, POST /admin/search/reindex
- Frontend: searchApi cursor/limit params (extensibilité)
- docs/ENV_VARIABLES: ELASTICSEARCH_URL, ELASTICSEARCH_INDEX, ELASTICSEARCH_AUTO_INDEX
- Roadmap v0.10.2 → DONE
2026-03-09 10:13:18 +01:00

50 lines
1.2 KiB
Go

package elasticsearch
import (
"context"
"fmt"
"github.com/elastic/go-elasticsearch/v8"
"go.uber.org/zap"
)
// Client wraps Elasticsearch client with health check (v0.10.2 F361)
type Client struct {
*elasticsearch.Client
Config Config
Logger *zap.Logger
}
// NewClient creates Elasticsearch client when ELASTICSEARCH_URL is set
func NewClient(cfg Config, logger *zap.Logger) (*Client, error) {
if !cfg.Enabled {
return nil, nil
}
es, err := elasticsearch.NewClient(elasticsearch.Config{
Addresses: []string{cfg.URL},
})
if err != nil {
return nil, fmt.Errorf("elasticsearch: create client: %w", err)
}
c := &Client{Client: es, Config: cfg, Logger: logger}
if err := c.Ping(context.Background()); err != nil {
return nil, fmt.Errorf("elasticsearch: ping: %w", err)
}
if logger != nil {
logger.Info("Elasticsearch client connected", zap.String("url", cfg.URL), zap.String("index", cfg.Index))
}
return c, nil
}
// Ping checks Elasticsearch cluster health
func (c *Client) Ping(ctx context.Context) error {
res, err := c.Info(c.Info.WithContext(ctx))
if err != nil {
return err
}
defer res.Body.Close()
if res.IsError() {
return fmt.Errorf("elasticsearch info failed: %s", res.String())
}
return nil
}