This repository was archived by the owner on Sep 30, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Syntactic indexing: add database schema and dbworker #60055
Merged
Merged
Changes from 22 commits
Commits
Show all changes
48 commits
Select commit
Hold shift + click to select a range
107a75b
Move database code out of service entrypoint
keynmol 1e8cdcd
Worker scaffold
keynmol 8c0cc75
Name database connections
keynmol 147a8be
Add auto-incrementing sequence to the table
keynmol 0a87259
Add more services to the configuration
keynmol 69618c1
Merge branch 'main' into syntactic-worker-database
keynmol b991ac0
Correct broken merge and incorrect path to scip-syntax CLI
keynmol 4e17d9b
Add basic tests for the dbworker interface
keynmol 293ed01
Merge branch 'main' into syntactic-worker-database
keynmol 2fbb05a
Remove spurious check ins
keynmol 2616056
Clean up down migration
keynmol 530f30e
Clean up migration file
keynmol 43bb346
Run Gazelle
keynmol 6768573
Remove things I don't understand
keynmol 140ac04
Revert unrelated changes
keynmol 30d35d6
Restore code I don't fully understand
keynmol 26ead64
Amend comment to provide more detail
keynmol 94af832
Add requires network to tests
keynmol 9ef22fa
Regenerate squashed migration and description files
keynmol edde8a8
Make migration idempotent
keynmol 20961f4
Merge branch 'main' into syntactic-worker-database
keynmol a5a496a
Fix migration idempotency
keynmol af0874e
Use explicit env variables in config loading
keynmol 0fa10fb
Worker naming
keynmol fb73eb5
Remove outfile column and field
keynmol 8219c88
Fail fast assertions
keynmol 45aea83
compile-time interface conformance for syntactic index record
keynmol b9bad2a
Surface error from store initialisation
keynmol 72f95e3
Regenerate migration summary files
keynmol 05a7426
Use an enum for recordState
keynmol eb85a1f
Rename indexing worker config
keynmol d484a71
Fix tests
keynmol 43cb6a0
Rename table and view names for consistency
keynmol 35d9fe6
gofmt
keynmol d5eefae
Merge branch 'main' into syntactic-worker-database
keynmol 5c4d2e2
Clean up error handling in tests
keynmol 3fa7ea6
Add indexes to the table
keynmol 48d2295
Simplify call to SetProviders
keynmol 295bc95
Use Completed constant
keynmol 8c81264
Make migration idempotent
keynmol bac2a1f
Run gazelle
keynmol 512b133
Add a test for a case where there are no records to dequeue
keynmol daab1f3
Rearrange fields for clarity
keynmol 8b315b9
Add test for deleted repository
keynmol 82eb0f0
Make timestamp more readable
keynmol 81b7de4
Use bigserial for primary key
keynmol 928315a
Write squashed schema
keynmol cf1a70f
Merge branch 'main' into syntactic-worker-database
keynmol File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,55 @@ | ||
load("//dev:go_defs.bzl", "go_test") | ||
load("@io_bazel_rules_go//go:def.bzl", "go_library") | ||
|
||
go_library( | ||
name = "shared", | ||
srcs = [ | ||
"config.go", | ||
"indexing_worker.go", | ||
"service.go", | ||
"shared.go", | ||
"store.go", | ||
], | ||
importpath = "github.com/sourcegraph/sourcegraph/cmd/syntactic-code-intel-worker/shared", | ||
visibility = ["//visibility:public"], | ||
deps = [ | ||
"//internal/codeintel/shared/lsifuploadstore", | ||
"//internal/authz", | ||
"//internal/authz/providers", | ||
"//internal/conf", | ||
"//internal/conf/conftypes", | ||
"//internal/database", | ||
"//internal/database/basestore", | ||
"//internal/database/connections/live", | ||
"//internal/database/dbutil", | ||
"//internal/debugserver", | ||
"//internal/encryption/keyring", | ||
"//internal/env", | ||
"//internal/goroutine", | ||
"//internal/httpserver", | ||
"//internal/observation", | ||
"//internal/service", | ||
"//internal/workerutil", | ||
"//internal/workerutil/dbworker", | ||
"//internal/workerutil/dbworker/store", | ||
"//lib/errors", | ||
"@com_github_keegancsmith_sqlf//:sqlf", | ||
"@com_github_sourcegraph_log//:log", | ||
], | ||
) | ||
|
||
go_test( | ||
name = "shared_test", | ||
srcs = [ | ||
"store_helpers_test.go", | ||
"store_test.go", | ||
], | ||
embed = [":shared"], | ||
tags = ["requires-network"], | ||
deps = [ | ||
"//internal/database", | ||
"//internal/database/dbtest", | ||
"//internal/observation", | ||
"@com_github_keegancsmith_sqlf//:sqlf", | ||
"@com_github_stretchr_testify//assert", | ||
], | ||
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package shared | ||
|
||
import ( | ||
"context" | ||
"github.com/sourcegraph/log" | ||
"time" | ||
|
||
"github.com/sourcegraph/sourcegraph/internal/observation" | ||
"github.com/sourcegraph/sourcegraph/internal/workerutil" | ||
"github.com/sourcegraph/sourcegraph/internal/workerutil/dbworker" | ||
dbworkerstore "github.com/sourcegraph/sourcegraph/internal/workerutil/dbworker/store" | ||
) | ||
|
||
func NewIndexingWorker(ctx context.Context, observationCtx *observation.Context, workerStore dbworkerstore.Store[*SyntacticIndexRecord], config IndexingWorkerConfig) *workerutil.Worker[*SyntacticIndexRecord] { | ||
|
||
name := "syntactic_code_intel_indexer" | ||
keynmol marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return dbworker.NewWorker[*SyntacticIndexRecord](ctx, workerStore, &indexingHandler{}, workerutil.WorkerOptions{ | ||
Name: name, | ||
Interval: config.PollInterval, | ||
HeartbeatInterval: 10 * time.Second, | ||
Metrics: workerutil.NewMetrics(observationCtx, name), | ||
NumHandlers: config.Concurrency, | ||
MaximumRuntimePerJob: config.MaximumRuntimePerJob, | ||
}) | ||
|
||
} | ||
|
||
type indexingHandler struct{} | ||
|
||
var _ workerutil.Handler[*SyntacticIndexRecord] = &indexingHandler{} | ||
|
||
func (i indexingHandler) Handle(ctx context.Context, logger log.Logger, record *SyntacticIndexRecord) error { | ||
logger.Info("Stub indexing worker handling record", | ||
log.Int("id", record.ID), | ||
log.String("repository name", record.RepositoryName), | ||
log.String("commit", record.Commit)) | ||
return nil | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
package shared | ||
|
||
import ( | ||
"context" | ||
"database/sql" | ||
"strconv" | ||
"time" | ||
|
||
"github.com/keegancsmith/sqlf" | ||
"github.com/sourcegraph/log" | ||
"github.com/sourcegraph/sourcegraph/internal/authz" | ||
"github.com/sourcegraph/sourcegraph/internal/authz/providers" | ||
"github.com/sourcegraph/sourcegraph/internal/conf" | ||
"github.com/sourcegraph/sourcegraph/internal/conf/conftypes" | ||
"github.com/sourcegraph/sourcegraph/internal/database" | ||
"github.com/sourcegraph/sourcegraph/internal/database/basestore" | ||
connections "github.com/sourcegraph/sourcegraph/internal/database/connections/live" | ||
"github.com/sourcegraph/sourcegraph/internal/database/dbutil" | ||
"github.com/sourcegraph/sourcegraph/internal/observation" | ||
dbworkerstore "github.com/sourcegraph/sourcegraph/internal/workerutil/dbworker/store" | ||
) | ||
|
||
type SyntacticIndexRecord struct { | ||
ID int `json:"id"` | ||
Commit string `json:"commit"` | ||
QueuedAt time.Time `json:"queuedAt"` | ||
State string `json:"state"` | ||
FailureMessage *string `json:"failureMessage"` | ||
StartedAt *time.Time `json:"startedAt"` | ||
FinishedAt *time.Time `json:"finishedAt"` | ||
ProcessAfter *time.Time `json:"processAfter"` | ||
NumResets int `json:"numResets"` | ||
NumFailures int `json:"numFailures"` | ||
RepositoryID int `json:"repositoryId"` | ||
RepositoryName string `json:"repositoryName"` | ||
Outfile string `json:"outfile"` | ||
keynmol marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ShouldReindex bool `json:"shouldReindex"` | ||
EnqueuerUserID int32 `json:"enqueuerUserID"` | ||
varungandhi-src marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
func (i SyntacticIndexRecord) RecordID() int { | ||
return i.ID | ||
} | ||
keynmol marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
func (i SyntacticIndexRecord) RecordUID() string { | ||
return strconv.Itoa(i.ID) | ||
} | ||
|
||
func ScanSyntacticIndexRecord(s dbutil.Scanner) (*SyntacticIndexRecord, error) { | ||
var job SyntacticIndexRecord | ||
if err := scanSyntacticIndexRecord(&job, s); err != nil { | ||
return nil, err | ||
} | ||
return &job, nil | ||
} | ||
|
||
func scanSyntacticIndexRecord(job *SyntacticIndexRecord, s dbutil.Scanner) error { | ||
|
||
// Make sure this is in sync with columnExpressions below... | ||
if err := s.Scan( | ||
&job.ID, | ||
&job.Commit, | ||
&job.QueuedAt, | ||
&job.State, | ||
&job.FailureMessage, | ||
&job.StartedAt, | ||
&job.FinishedAt, | ||
&job.ProcessAfter, | ||
&job.NumResets, | ||
&job.NumFailures, | ||
&job.RepositoryID, | ||
&job.RepositoryName, | ||
&job.Outfile, | ||
&job.ShouldReindex, | ||
&job.EnqueuerUserID, | ||
); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func NewStore(observationCtx *observation.Context, db *sql.DB) (dbworkerstore.Store[*SyntacticIndexRecord], error) { | ||
|
||
// Make sure this is in sync with the columns of the | ||
// syntactic_scip_indexes_with_repository_name view | ||
var columnExpressions = []*sqlf.Query{ | ||
sqlf.Sprintf("u.id"), | ||
sqlf.Sprintf("u.commit"), | ||
sqlf.Sprintf("u.queued_at"), | ||
sqlf.Sprintf("u.state"), | ||
sqlf.Sprintf("u.failure_message"), | ||
sqlf.Sprintf("u.started_at"), | ||
sqlf.Sprintf("u.finished_at"), | ||
sqlf.Sprintf("u.process_after"), | ||
sqlf.Sprintf("u.num_resets"), | ||
sqlf.Sprintf("u.num_failures"), | ||
sqlf.Sprintf("u.repository_id"), | ||
sqlf.Sprintf("u.repository_name"), | ||
sqlf.Sprintf("u.outfile"), | ||
sqlf.Sprintf("u.should_reindex"), | ||
sqlf.Sprintf("u.enqueuer_user_id"), | ||
} | ||
|
||
storeOptions := dbworkerstore.Options[*SyntacticIndexRecord]{ | ||
Name: "syntactic_scip_index_store", | ||
TableName: "syntactic_scip_indexes", | ||
ViewName: "syntactic_scip_indexes_with_repository_name u", | ||
keynmol marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Using enqueuer_user_id prioritises manually scheduled indexing | ||
OrderByExpression: sqlf.Sprintf("(u.enqueuer_user_id > 0) DESC, u.queued_at, u.id"), | ||
ColumnExpressions: columnExpressions, | ||
Scan: dbworkerstore.BuildWorkerScan(ScanSyntacticIndexRecord), | ||
} | ||
|
||
handle := basestore.NewHandleWithDB(observationCtx.Logger, db, sql.TxOptions{}) | ||
return dbworkerstore.New(observationCtx, handle, storeOptions), nil | ||
} | ||
|
||
func mustInitializeDB(observationCtx *observation.Context, name string) *sql.DB { | ||
dsn := conf.GetServiceConnectionValueAndRestartOnChange(func(serviceConnections conftypes.ServiceConnections) string { | ||
return serviceConnections.PostgresDSN | ||
}) | ||
sqlDB, err := connections.EnsureNewFrontendDB(observationCtx, dsn, name) | ||
if err != nil { | ||
log.Scoped("init db ("+name+")").Fatal("Failed to connect to frontend database", log.Error(err)) | ||
} | ||
|
||
// This is an internal service, so we rely on the | ||
// frontend to do authz checks for user requests. | ||
// Authz checks are enforced by the DB layer | ||
// | ||
// This call to SetProviders is here so that calls to GetProviders don't block. | ||
// Relevant PR: https://github.com/sourcegraph/sourcegraph/pull/15755 | ||
// Relevant issue: https://github.com/sourcegraph/sourcegraph/issues/15962 | ||
|
||
ctx := context.Background() | ||
db := database.NewDB(observationCtx.Logger, sqlDB) | ||
go func() { | ||
for range time.NewTicker(providers.RefreshInterval()).C { | ||
allowAccessByDefault, authzProviders, _, _, _ := providers.ProvidersFromConfig(ctx, conf.Get(), db) | ||
authz.SetProviders(allowAccessByDefault, authzProviders) | ||
} | ||
}() | ||
keynmol marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return sqlDB | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.