Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Commit d378d73

Browse files
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
1 parent 8b5eec2 commit d378d73

File tree

6 files changed

+122
-4
lines changed

6 files changed

+122
-4
lines changed

cmd/frontend/graphqlbackend/codeintel.codenav.graphql

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,13 @@ EXPERIMENTAL: This type may change in a backwards-incompatible way.
9898
TODO(issue: GRAPH-614): 'commit' field should have type GitCommit
9999
before stabilizing this API.
100100
"""
101-
type CodeGraphData {
101+
type CodeGraphData implements Node {
102+
"""
103+
ID of this object that can be used to identify the CodeGraphData
104+
for pagination in the codeGraphData field.
105+
"""
106+
id: ID!
107+
102108
"""
103109
Coarse description of the data source for this code graph data.
104110
"""

cmd/frontend/graphqlbackend/node.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,3 +381,8 @@ func (r *NodeResolver) ToSearchJob() (SearchJobResolver, bool) {
381381
n, ok := r.Node.(SearchJobResolver)
382382
return n, ok
383383
}
384+
385+
func (r *NodeResolver) ToCodeGraphData() (resolverstubs.CodeGraphDataResolver, bool) {
386+
n, ok := r.Node.(resolverstubs.CodeGraphDataResolver)
387+
return n, ok
388+
}

internal/codeintel/codenav/transport/graphql/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ go_library(
4343
"//lib/errors",
4444
"//lib/pointers",
4545
"@com_github_graph_gophers_graphql_go//:graphql-go",
46+
"@com_github_graph_gophers_graphql_go//relay",
4647
"@com_github_sourcegraph_go_lsp//:go-lsp",
4748
"@com_github_sourcegraph_log//:log",
4849
"@com_github_sourcegraph_scip//bindings/go/scip",

internal/codeintel/codenav/transport/graphql/root_resolver.go

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@ import (
55
"fmt"
66
"sync"
77

8+
"github.com/graph-gophers/graphql-go"
9+
"github.com/graph-gophers/graphql-go/relay"
810
orderedmap "github.com/wk8/go-ordered-map/v2"
911
"go.opentelemetry.io/otel/attribute"
1012

1113
"github.com/sourcegraph/scip/bindings/go/scip"
1214

15+
"github.com/sourcegraph/sourcegraph/internal/api"
1316
"github.com/sourcegraph/sourcegraph/internal/authz"
1417
"github.com/sourcegraph/sourcegraph/internal/codeintel/codenav"
1518
resolverstubs "github.com/sourcegraph/sourcegraph/internal/codeintel/resolvers"
@@ -159,6 +162,10 @@ func (r *rootResolver) CodeGraphData(ctx context.Context, opts *resolverstubs.Co
159162
return &[]resolverstubs.CodeGraphDataResolver{}, nil
160163
}
161164

165+
func (r *rootResolver) CodeGraphDataByID(ctx context.Context, id graphql.ID) (resolverstubs.CodeGraphDataResolver, error) {
166+
return newCodeGraphDataResolverFromID(ctx, r.repoStore, r.svc, r.operations, id)
167+
}
168+
162169
func preferUploadsWithLongestRoots(uploads []shared.CompletedUpload) []shared.CompletedUpload {
163170
// Use orderedmap instead of a map to preserve the order of the uploads
164171
// and to avoid introducing non-determinism.
@@ -317,14 +324,34 @@ type codeGraphDataResolver struct {
317324

318325
// Arguments
319326
svc CodeNavService
320-
upload shared.CompletedUpload
327+
upload UploadData
321328
opts *resolverstubs.CodeGraphDataOpts
322329
provenance resolverstubs.CodeGraphDataProvenance
323330

324331
// O11y
325332
operations *operations
326333
}
327334

335+
// UploadData represents the subset of information of shared.CompletedUpload
336+
// that we actually care about for the purposes of the GraphQL API.
337+
//
338+
// All fields are left public for JSON marshaling/unmarshaling.
339+
type UploadData struct {
340+
UploadID int
341+
Commit string
342+
Indexer string
343+
IndexerVersion string
344+
}
345+
346+
func NewUploadData(upload shared.CompletedUpload) UploadData {
347+
return UploadData{
348+
UploadID: upload.ID,
349+
Commit: upload.Commit,
350+
Indexer: upload.Indexer,
351+
IndexerVersion: upload.IndexerVersion,
352+
}
353+
}
354+
328355
func newCodeGraphDataResolver(
329356
svc CodeNavService,
330357
upload shared.CompletedUpload,
@@ -337,23 +364,81 @@ func newCodeGraphDataResolver(
337364
/*document*/ nil,
338365
/*documentRetrievalError*/ nil,
339366
svc,
340-
upload,
367+
NewUploadData(upload),
341368
opts,
342369
provenance,
343370
operations,
344371
}
345372
}
346373

374+
// CodeGraphDataID represents the serializable state needed to materialize
375+
// a CodeGraphData value from an opaque GraphQL ID.
376+
//
377+
// All fields are left public for JSON marshaling/unmarshaling.
378+
type CodeGraphDataID struct {
379+
UploadData
380+
Args *resolverstubs.CodeGraphDataArgs
381+
api.RepoID
382+
Commit api.CommitID
383+
Path string
384+
resolverstubs.CodeGraphDataProvenance
385+
}
386+
387+
func newCodeGraphDataResolverFromID(
388+
ctx context.Context,
389+
repoStore database.RepoStore,
390+
svc CodeNavService,
391+
operations *operations,
392+
rawID graphql.ID,
393+
) (resolverstubs.CodeGraphDataResolver, error) {
394+
var id CodeGraphDataID
395+
if err := relay.UnmarshalSpec(rawID, &id); err != nil {
396+
return nil, errors.Wrap(err, "malformed ID")
397+
}
398+
repos, err := repoStore.GetByIDs(ctx, id.RepoID)
399+
if err != nil {
400+
return nil, errors.Wrap(err, "repo for CodeGraphData value no longer exists")
401+
}
402+
opts := resolverstubs.CodeGraphDataOpts{
403+
Args: id.Args,
404+
Repo: repos[0],
405+
Commit: id.Commit,
406+
Path: id.Path,
407+
}
408+
return &codeGraphDataResolver{
409+
sync.Once{},
410+
/*document*/ nil,
411+
/*documentRetrievalError*/ nil,
412+
svc,
413+
id.UploadData,
414+
&opts,
415+
id.CodeGraphDataProvenance,
416+
operations,
417+
}, nil
418+
}
419+
347420
func (c *codeGraphDataResolver) tryRetrieveDocument(ctx context.Context) (*scip.Document, error) {
348421
// NOTE(id: scip-doc-optimization): In the case of pagination, if we retrieve the document ID
349422
// from the database, we can avoid performing a JOIN between codeintel_scip_document_lookup
350423
// and codeintel_scip_documents
351424
c.retrievedDocument.Do(func() {
352-
c.document, c.documentRetrievalError = c.svc.SCIPDocument(ctx, c.upload.ID, c.opts.Path)
425+
c.document, c.documentRetrievalError = c.svc.SCIPDocument(ctx, c.upload.UploadID, c.opts.Path)
353426
})
354427
return c.document, c.documentRetrievalError
355428
}
356429

430+
func (c *codeGraphDataResolver) ID() graphql.ID {
431+
dataID := CodeGraphDataID{
432+
c.upload,
433+
c.opts.Args,
434+
c.opts.Repo.ID,
435+
c.opts.Commit,
436+
c.opts.Path,
437+
c.provenance,
438+
}
439+
return relay.MarshalID(resolverstubs.CodeGraphDataIDKind, dataID)
440+
}
441+
357442
func (c *codeGraphDataResolver) Provenance(_ context.Context) (resolverstubs.CodeGraphDataProvenance, error) {
358443
return c.provenance, nil
359444
}

internal/codeintel/resolvers/codenav.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,13 @@ type CodeNavServiceResolver interface {
3131
// that it is not what is exactly provided as input from the GraphQL
3232
// client.
3333
CodeGraphData(ctx context.Context, opts *CodeGraphDataOpts) (*[]CodeGraphDataResolver, error)
34+
// CodeGraphDataByID materializes a CodeGraphDataResolver purely from a graphql.ID.
35+
CodeGraphDataByID(ctx context.Context, id graphql.ID) (CodeGraphDataResolver, error)
3436
UsagesForSymbol(ctx context.Context, args *UsagesForSymbolArgs) (UsageConnectionResolver, error)
3537
}
3638

39+
const CodeGraphDataIDKind = "CodeGraphData"
40+
3741
type GitBlobLSIFDataArgs struct {
3842
Repo *types.Repo
3943
Commit api.CommitID
@@ -161,13 +165,19 @@ type DiagnosticResolver interface {
161165
}
162166

163167
type CodeGraphDataResolver interface {
168+
// ID satisfies the Node interface.
169+
ID() graphql.ID
164170
Provenance(ctx context.Context) (CodeGraphDataProvenance, error)
165171
Commit(ctx context.Context) (string, error)
166172
ToolInfo(ctx context.Context) (*CodeGraphToolInfo, error)
167173
// Pre-condition: args are Normalized.
168174
Occurrences(ctx context.Context, args *OccurrencesArgs) (SCIPOccurrenceConnectionResolver, error)
169175
}
170176

177+
// CodeGraphDataProvenance corresponds to the matching type in the GraphQL API.
178+
//
179+
// Make sure this type maintains its marshaling/unmarshaling behavior in
180+
// case the type definition is changed.
171181
type CodeGraphDataProvenance string
172182

173183
const (
@@ -192,6 +202,10 @@ func (f *CodeGraphDataFilter) String() string {
192202
return ""
193203
}
194204

205+
// CodeGraphDataArgs represents the arguments to the codeGraphData(...)
206+
// field on GitBlob in the GraphQL API.
207+
//
208+
// All fields are left public for JSON marshaling/unmarshaling.
195209
type CodeGraphDataArgs struct {
196210
Filter *CodeGraphDataFilter
197211
}

internal/codeintel/resolvers/root_resolver.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ func (r *Resolver) NodeResolvers() map[string]NodeByIDFunc {
6363
"PreciseIndex": func(ctx context.Context, id graphql.ID) (Node, error) {
6464
return r.uploadsRootResolver.PreciseIndexByID(ctx, id)
6565
},
66+
CodeGraphDataIDKind: func(ctx context.Context, id graphql.ID) (Node, error) {
67+
return r.codenavResolver.CodeGraphDataByID(ctx, id)
68+
},
6669
}
6770
}
6871

@@ -129,6 +132,10 @@ func (r *Resolver) CodeGraphData(ctx context.Context, opts *CodeGraphDataOpts) (
129132
return r.codenavResolver.CodeGraphData(ctx, opts)
130133
}
131134

135+
func (r *Resolver) CodeGraphDataByID(ctx context.Context, id graphql.ID) (CodeGraphDataResolver, error) {
136+
return r.codenavResolver.CodeGraphDataByID(ctx, id)
137+
}
138+
132139
func (r *Resolver) UsagesForSymbol(ctx context.Context, args *UsagesForSymbolArgs) (UsageConnectionResolver, error) {
133140
return r.codenavResolver.UsagesForSymbol(ctx, args)
134141
}

0 commit comments

Comments
 (0)