You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.8 KiB
112 lines
3.8 KiB
// orly-db-neo4j is a standalone gRPC database server using the Neo4j backend. |
|
package main |
|
|
|
import ( |
|
"context" |
|
"os" |
|
"time" |
|
|
|
"go-simpler.org/env" |
|
"lol.mleku.dev" |
|
"lol.mleku.dev/chk" |
|
"lol.mleku.dev/log" |
|
|
|
"next.orly.dev/pkg/database" |
|
"next.orly.dev/pkg/database/server" |
|
|
|
// Import neo4j to register the factory |
|
_ "next.orly.dev/pkg/neo4j" |
|
) |
|
|
|
// Config holds the database server configuration. |
|
type Config struct { |
|
// Listen is the gRPC server listen address |
|
Listen string `env:"ORLY_DB_LISTEN" default:"127.0.0.1:50051" usage:"gRPC server listen address"` |
|
|
|
// LogLevel is the logging level |
|
LogLevel string `env:"ORLY_DB_LOG_LEVEL" default:"info" usage:"log level (trace, debug, info, warn, error)"` |
|
|
|
// DataDir is required by the database layer for metadata storage |
|
DataDir string `env:"ORLY_DATA_DIR" default:"/tmp/orly-neo4j" usage:"data directory for metadata"` |
|
|
|
// Neo4j configuration |
|
Neo4jURI string `env:"ORLY_NEO4J_URI" default:"bolt://localhost:7687" usage:"Neo4j connection URI"` |
|
Neo4jUser string `env:"ORLY_NEO4J_USER" default:"neo4j" usage:"Neo4j username"` |
|
Neo4jPassword string `env:"ORLY_NEO4J_PASSWORD" usage:"Neo4j password"` |
|
|
|
// Neo4j driver tuning |
|
Neo4jMaxConnPoolSize int `env:"ORLY_NEO4J_MAX_CONN_POOL" default:"25" usage:"max connection pool size"` |
|
Neo4jFetchSize int `env:"ORLY_NEO4J_FETCH_SIZE" default:"1000" usage:"max records per fetch batch"` |
|
Neo4jMaxTxRetrySeconds int `env:"ORLY_NEO4J_MAX_TX_RETRY_SEC" default:"30" usage:"max transaction retry time"` |
|
Neo4jQueryResultLimit int `env:"ORLY_NEO4J_QUERY_RESULT_LIMIT" default:"10000" usage:"max results per query (0=unlimited)"` |
|
|
|
// Query cache configuration (for the gRPC server) |
|
QueryCacheSizeMB int `env:"ORLY_DB_QUERY_CACHE_SIZE_MB" default:"256" usage:"query cache size in MB"` |
|
QueryCacheMaxAge time.Duration `env:"ORLY_DB_QUERY_CACHE_MAX_AGE" default:"5m" usage:"query cache max age"` |
|
QueryCacheDisabled bool `env:"ORLY_DB_QUERY_CACHE_DISABLED" default:"false" usage:"disable query cache"` |
|
|
|
// gRPC server configuration |
|
StreamBatchSize int `env:"ORLY_DB_STREAM_BATCH_SIZE" default:"100" usage:"events per stream batch"` |
|
} |
|
|
|
func main() { |
|
cfg := loadConfig() |
|
|
|
// Set log level |
|
lol.SetLogLevel(cfg.LogLevel) |
|
log.I.F("orly-db-neo4j starting with log level: %s", cfg.LogLevel) |
|
|
|
ctx, cancel := context.WithCancel(context.Background()) |
|
defer cancel() |
|
|
|
// Create database configuration |
|
dbCfg := &database.DatabaseConfig{ |
|
DataDir: cfg.DataDir, |
|
LogLevel: cfg.LogLevel, |
|
Neo4jURI: cfg.Neo4jURI, |
|
Neo4jUser: cfg.Neo4jUser, |
|
Neo4jPassword: cfg.Neo4jPassword, |
|
Neo4jMaxConnPoolSize: cfg.Neo4jMaxConnPoolSize, |
|
Neo4jFetchSize: cfg.Neo4jFetchSize, |
|
Neo4jMaxTxRetrySeconds: cfg.Neo4jMaxTxRetrySeconds, |
|
Neo4jQueryResultLimit: cfg.Neo4jQueryResultLimit, |
|
QueryCacheSizeMB: cfg.QueryCacheSizeMB, |
|
QueryCacheMaxAge: cfg.QueryCacheMaxAge, |
|
QueryCacheDisabled: cfg.QueryCacheDisabled, |
|
} |
|
|
|
// Initialize Neo4j database via factory |
|
log.I.F("connecting to Neo4j at %s", cfg.Neo4jURI) |
|
db, err := database.NewDatabaseWithConfig(ctx, cancel, "neo4j", dbCfg) |
|
if chk.E(err) { |
|
log.E.F("failed to initialize Neo4j database: %v", err) |
|
os.Exit(1) |
|
} |
|
|
|
// Wait for database to be ready |
|
log.I.F("waiting for database to be ready...") |
|
<-db.Ready() |
|
log.I.F("database ready") |
|
|
|
// Create and start gRPC server |
|
serverCfg := &server.Config{ |
|
Listen: cfg.Listen, |
|
LogLevel: cfg.LogLevel, |
|
StreamBatchSize: cfg.StreamBatchSize, |
|
} |
|
|
|
srv := server.New(db, serverCfg) |
|
if err := srv.ListenAndServe(ctx, cancel); err != nil { |
|
log.E.F("gRPC server error: %v", err) |
|
} |
|
} |
|
|
|
func loadConfig() *Config { |
|
cfg := &Config{} |
|
if err := env.Load(cfg, nil); chk.E(err) { |
|
log.E.F("failed to load config: %v", err) |
|
os.Exit(1) |
|
} |
|
|
|
return cfg |
|
}
|
|
|