mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 17:11:49 +00:00
feat: Add id for CodeGraphData (#63337)
This allows locating a CodeGraphData object later so that the occurrences can be paginated over correctly. Fixes GRAPH-692
This commit is contained in:
parent
8b5eec2301
commit
d378d73d2b
@ -98,7 +98,13 @@ EXPERIMENTAL: This type may change in a backwards-incompatible way.
|
||||
TODO(issue: GRAPH-614): 'commit' field should have type GitCommit
|
||||
before stabilizing this API.
|
||||
"""
|
||||
type CodeGraphData {
|
||||
type CodeGraphData implements Node {
|
||||
"""
|
||||
ID of this object that can be used to identify the CodeGraphData
|
||||
for pagination in the codeGraphData field.
|
||||
"""
|
||||
id: ID!
|
||||
|
||||
"""
|
||||
Coarse description of the data source for this code graph data.
|
||||
"""
|
||||
|
||||
@ -381,3 +381,8 @@ func (r *NodeResolver) ToSearchJob() (SearchJobResolver, bool) {
|
||||
n, ok := r.Node.(SearchJobResolver)
|
||||
return n, ok
|
||||
}
|
||||
|
||||
func (r *NodeResolver) ToCodeGraphData() (resolverstubs.CodeGraphDataResolver, bool) {
|
||||
n, ok := r.Node.(resolverstubs.CodeGraphDataResolver)
|
||||
return n, ok
|
||||
}
|
||||
|
||||
@ -43,6 +43,7 @@ go_library(
|
||||
"//lib/errors",
|
||||
"//lib/pointers",
|
||||
"@com_github_graph_gophers_graphql_go//:graphql-go",
|
||||
"@com_github_graph_gophers_graphql_go//relay",
|
||||
"@com_github_sourcegraph_go_lsp//:go-lsp",
|
||||
"@com_github_sourcegraph_log//:log",
|
||||
"@com_github_sourcegraph_scip//bindings/go/scip",
|
||||
|
||||
@ -5,11 +5,14 @@ import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/graph-gophers/graphql-go"
|
||||
"github.com/graph-gophers/graphql-go/relay"
|
||||
orderedmap "github.com/wk8/go-ordered-map/v2"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
|
||||
"github.com/sourcegraph/scip/bindings/go/scip"
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/api"
|
||||
"github.com/sourcegraph/sourcegraph/internal/authz"
|
||||
"github.com/sourcegraph/sourcegraph/internal/codeintel/codenav"
|
||||
resolverstubs "github.com/sourcegraph/sourcegraph/internal/codeintel/resolvers"
|
||||
@ -159,6 +162,10 @@ func (r *rootResolver) CodeGraphData(ctx context.Context, opts *resolverstubs.Co
|
||||
return &[]resolverstubs.CodeGraphDataResolver{}, nil
|
||||
}
|
||||
|
||||
func (r *rootResolver) CodeGraphDataByID(ctx context.Context, id graphql.ID) (resolverstubs.CodeGraphDataResolver, error) {
|
||||
return newCodeGraphDataResolverFromID(ctx, r.repoStore, r.svc, r.operations, id)
|
||||
}
|
||||
|
||||
func preferUploadsWithLongestRoots(uploads []shared.CompletedUpload) []shared.CompletedUpload {
|
||||
// Use orderedmap instead of a map to preserve the order of the uploads
|
||||
// and to avoid introducing non-determinism.
|
||||
@ -317,7 +324,7 @@ type codeGraphDataResolver struct {
|
||||
|
||||
// Arguments
|
||||
svc CodeNavService
|
||||
upload shared.CompletedUpload
|
||||
upload UploadData
|
||||
opts *resolverstubs.CodeGraphDataOpts
|
||||
provenance resolverstubs.CodeGraphDataProvenance
|
||||
|
||||
@ -325,6 +332,26 @@ type codeGraphDataResolver struct {
|
||||
operations *operations
|
||||
}
|
||||
|
||||
// UploadData represents the subset of information of shared.CompletedUpload
|
||||
// that we actually care about for the purposes of the GraphQL API.
|
||||
//
|
||||
// All fields are left public for JSON marshaling/unmarshaling.
|
||||
type UploadData struct {
|
||||
UploadID int
|
||||
Commit string
|
||||
Indexer string
|
||||
IndexerVersion string
|
||||
}
|
||||
|
||||
func NewUploadData(upload shared.CompletedUpload) UploadData {
|
||||
return UploadData{
|
||||
UploadID: upload.ID,
|
||||
Commit: upload.Commit,
|
||||
Indexer: upload.Indexer,
|
||||
IndexerVersion: upload.IndexerVersion,
|
||||
}
|
||||
}
|
||||
|
||||
func newCodeGraphDataResolver(
|
||||
svc CodeNavService,
|
||||
upload shared.CompletedUpload,
|
||||
@ -337,23 +364,81 @@ func newCodeGraphDataResolver(
|
||||
/*document*/ nil,
|
||||
/*documentRetrievalError*/ nil,
|
||||
svc,
|
||||
upload,
|
||||
NewUploadData(upload),
|
||||
opts,
|
||||
provenance,
|
||||
operations,
|
||||
}
|
||||
}
|
||||
|
||||
// CodeGraphDataID represents the serializable state needed to materialize
|
||||
// a CodeGraphData value from an opaque GraphQL ID.
|
||||
//
|
||||
// All fields are left public for JSON marshaling/unmarshaling.
|
||||
type CodeGraphDataID struct {
|
||||
UploadData
|
||||
Args *resolverstubs.CodeGraphDataArgs
|
||||
api.RepoID
|
||||
Commit api.CommitID
|
||||
Path string
|
||||
resolverstubs.CodeGraphDataProvenance
|
||||
}
|
||||
|
||||
func newCodeGraphDataResolverFromID(
|
||||
ctx context.Context,
|
||||
repoStore database.RepoStore,
|
||||
svc CodeNavService,
|
||||
operations *operations,
|
||||
rawID graphql.ID,
|
||||
) (resolverstubs.CodeGraphDataResolver, error) {
|
||||
var id CodeGraphDataID
|
||||
if err := relay.UnmarshalSpec(rawID, &id); err != nil {
|
||||
return nil, errors.Wrap(err, "malformed ID")
|
||||
}
|
||||
repos, err := repoStore.GetByIDs(ctx, id.RepoID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "repo for CodeGraphData value no longer exists")
|
||||
}
|
||||
opts := resolverstubs.CodeGraphDataOpts{
|
||||
Args: id.Args,
|
||||
Repo: repos[0],
|
||||
Commit: id.Commit,
|
||||
Path: id.Path,
|
||||
}
|
||||
return &codeGraphDataResolver{
|
||||
sync.Once{},
|
||||
/*document*/ nil,
|
||||
/*documentRetrievalError*/ nil,
|
||||
svc,
|
||||
id.UploadData,
|
||||
&opts,
|
||||
id.CodeGraphDataProvenance,
|
||||
operations,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *codeGraphDataResolver) tryRetrieveDocument(ctx context.Context) (*scip.Document, error) {
|
||||
// NOTE(id: scip-doc-optimization): In the case of pagination, if we retrieve the document ID
|
||||
// from the database, we can avoid performing a JOIN between codeintel_scip_document_lookup
|
||||
// and codeintel_scip_documents
|
||||
c.retrievedDocument.Do(func() {
|
||||
c.document, c.documentRetrievalError = c.svc.SCIPDocument(ctx, c.upload.ID, c.opts.Path)
|
||||
c.document, c.documentRetrievalError = c.svc.SCIPDocument(ctx, c.upload.UploadID, c.opts.Path)
|
||||
})
|
||||
return c.document, c.documentRetrievalError
|
||||
}
|
||||
|
||||
func (c *codeGraphDataResolver) ID() graphql.ID {
|
||||
dataID := CodeGraphDataID{
|
||||
c.upload,
|
||||
c.opts.Args,
|
||||
c.opts.Repo.ID,
|
||||
c.opts.Commit,
|
||||
c.opts.Path,
|
||||
c.provenance,
|
||||
}
|
||||
return relay.MarshalID(resolverstubs.CodeGraphDataIDKind, dataID)
|
||||
}
|
||||
|
||||
func (c *codeGraphDataResolver) Provenance(_ context.Context) (resolverstubs.CodeGraphDataProvenance, error) {
|
||||
return c.provenance, nil
|
||||
}
|
||||
|
||||
@ -31,9 +31,13 @@ type CodeNavServiceResolver interface {
|
||||
// that it is not what is exactly provided as input from the GraphQL
|
||||
// client.
|
||||
CodeGraphData(ctx context.Context, opts *CodeGraphDataOpts) (*[]CodeGraphDataResolver, error)
|
||||
// CodeGraphDataByID materializes a CodeGraphDataResolver purely from a graphql.ID.
|
||||
CodeGraphDataByID(ctx context.Context, id graphql.ID) (CodeGraphDataResolver, error)
|
||||
UsagesForSymbol(ctx context.Context, args *UsagesForSymbolArgs) (UsageConnectionResolver, error)
|
||||
}
|
||||
|
||||
const CodeGraphDataIDKind = "CodeGraphData"
|
||||
|
||||
type GitBlobLSIFDataArgs struct {
|
||||
Repo *types.Repo
|
||||
Commit api.CommitID
|
||||
@ -161,6 +165,8 @@ type DiagnosticResolver interface {
|
||||
}
|
||||
|
||||
type CodeGraphDataResolver interface {
|
||||
// ID satisfies the Node interface.
|
||||
ID() graphql.ID
|
||||
Provenance(ctx context.Context) (CodeGraphDataProvenance, error)
|
||||
Commit(ctx context.Context) (string, error)
|
||||
ToolInfo(ctx context.Context) (*CodeGraphToolInfo, error)
|
||||
@ -168,6 +174,10 @@ type CodeGraphDataResolver interface {
|
||||
Occurrences(ctx context.Context, args *OccurrencesArgs) (SCIPOccurrenceConnectionResolver, error)
|
||||
}
|
||||
|
||||
// CodeGraphDataProvenance corresponds to the matching type in the GraphQL API.
|
||||
//
|
||||
// Make sure this type maintains its marshaling/unmarshaling behavior in
|
||||
// case the type definition is changed.
|
||||
type CodeGraphDataProvenance string
|
||||
|
||||
const (
|
||||
@ -192,6 +202,10 @@ func (f *CodeGraphDataFilter) String() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// CodeGraphDataArgs represents the arguments to the codeGraphData(...)
|
||||
// field on GitBlob in the GraphQL API.
|
||||
//
|
||||
// All fields are left public for JSON marshaling/unmarshaling.
|
||||
type CodeGraphDataArgs struct {
|
||||
Filter *CodeGraphDataFilter
|
||||
}
|
||||
|
||||
@ -63,6 +63,9 @@ func (r *Resolver) NodeResolvers() map[string]NodeByIDFunc {
|
||||
"PreciseIndex": func(ctx context.Context, id graphql.ID) (Node, error) {
|
||||
return r.uploadsRootResolver.PreciseIndexByID(ctx, id)
|
||||
},
|
||||
CodeGraphDataIDKind: func(ctx context.Context, id graphql.ID) (Node, error) {
|
||||
return r.codenavResolver.CodeGraphDataByID(ctx, id)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,6 +132,10 @@ func (r *Resolver) CodeGraphData(ctx context.Context, opts *CodeGraphDataOpts) (
|
||||
return r.codenavResolver.CodeGraphData(ctx, opts)
|
||||
}
|
||||
|
||||
func (r *Resolver) CodeGraphDataByID(ctx context.Context, id graphql.ID) (CodeGraphDataResolver, error) {
|
||||
return r.codenavResolver.CodeGraphDataByID(ctx, id)
|
||||
}
|
||||
|
||||
func (r *Resolver) UsagesForSymbol(ctx context.Context, args *UsagesForSymbolArgs) (UsageConnectionResolver, error) {
|
||||
return r.codenavResolver.UsagesForSymbol(ctx, args)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user