diff --git a/cmd/frontend/internal/cli/config.go b/cmd/frontend/internal/cli/config.go index 1cf8274db7e2..f9f9da8d4eb1 100644 --- a/cmd/frontend/internal/cli/config.go +++ b/cmd/frontend/internal/cli/config.go @@ -341,9 +341,10 @@ func serviceConnections() conftypes.ServiceConnections { } serviceConnectionsVal = conftypes.ServiceConnections{ - GitServers: gitServers(), - PostgresDSN: dbutil.PostgresDSN("", username, os.Getenv), - CodeIntelPostgresDSN: dbutil.PostgresDSN("codeintel", username, os.Getenv), + GitServers: gitServers(), + PostgresDSN: dbutil.PostgresDSN("", username, os.Getenv), + CodeIntelPostgresDSN: dbutil.PostgresDSN("codeintel", username, os.Getenv), + CodeInsightsTimescaleDSN: dbutil.PostgresDSN("codeinsights", username, os.Getenv), } // We set this envvar in development to disable the following check diff --git a/enterprise/internal/insights/insights.go b/enterprise/internal/insights/insights.go index 05422b7fdf20..b057410eccb8 100644 --- a/enterprise/internal/insights/insights.go +++ b/enterprise/internal/insights/insights.go @@ -2,13 +2,48 @@ package insights import ( "context" + "database/sql" + "fmt" + "log" "github.com/sourcegraph/sourcegraph/cmd/frontend/enterprise" "github.com/sourcegraph/sourcegraph/enterprise/internal/insights/resolvers" + "github.com/sourcegraph/sourcegraph/internal/conf" + "github.com/sourcegraph/sourcegraph/internal/database/dbconn" ) // Init initializes the given enterpriseServices to include the required resolvers for insights. func Init(ctx context.Context, enterpriseServices *enterprise.Services) error { + if !conf.IsDev(conf.DeployType()) { + // Code Insights is not yet deployed to non-dev/testing instances. We don't yet have + // TimescaleDB in those deployments. https://github.com/sourcegraph/sourcegraph/issues/17218 + return nil + } + _, err := initializeCodeInsightsDB() + if err != nil { + return err + } enterpriseServices.InsightsResolver = resolvers.New() return nil } + +// initializeCodeInsightsDB connects to and initializes the Code Insights Timescale DB, running +// database migrations before returning. +func initializeCodeInsightsDB() (*sql.DB, error) { + timescaleDSN := conf.Get().ServiceConnections.CodeInsightsTimescaleDSN + conf.Watch(func() { + if newDSN := conf.Get().ServiceConnections.CodeInsightsTimescaleDSN; timescaleDSN != newDSN { + log.Fatalf("Detected codeinsights database DSN change, restarting to take effect: %s", newDSN) + } + }) + + db, err := dbconn.New(timescaleDSN, "") + if err != nil { + return nil, fmt.Errorf("Failed to connect to codeinsights database: %s", err) + } + + if err := dbconn.MigrateDB(db, dbconn.CodeInsights); err != nil { + return nil, fmt.Errorf("Failed to perform codeinsights database migration: %s", err) + } + return db, nil +} diff --git a/internal/conf/conftypes/conftypes.go b/internal/conf/conftypes/conftypes.go index 5ffa44a5a02e..d0caad56e11f 100644 --- a/internal/conf/conftypes/conftypes.go +++ b/internal/conf/conftypes/conftypes.go @@ -19,6 +19,11 @@ type ServiceConnections struct { // code intel database. // eg: "postgres://sg@pgsql/sourcegraph_codeintel?sslmode=false" CodeIntelPostgresDSN string `json:"codeIntelPostgresDSN"` + + // CodeInsightsTimescaleDSN is the TimescaleDB data source name for the + // code insights database. + // eg: "postgres://sg@pgsql/sourcegraph_codeintel?sslmode=false" + CodeInsightsTimescaleDSN string `json:"codeinsightsTimescaleDSN"` } // RawUnified is the unparsed variant of conf.Unified.