@@ -116,6 +116,7 @@ type recordingGraphStore struct {
116116 nextID uint
117117 nodesByFP map [string ][]graph.Node
118118 edges []graph.Edge
119+ upsertedNodeBatches [][]graph.Node
119120 upsertedEdges [][]graph.Edge
120121 fileSuffixLookupCalls int
121122 importFileNodeCalls int
@@ -137,6 +138,7 @@ func (r *recordingGraphStore) DeleteGraph(ctx context.Context) error {
137138
138139func (r * recordingGraphStore ) UpsertNodes (ctx context.Context , nodes []graph.Node ) error {
139140 r .record ("UpsertNodes" )
141+ r .upsertedNodeBatches = append (r .upsertedNodeBatches , append ([]graph.Node (nil ), nodes ... ))
140142 for i := range nodes {
141143 r .nextID ++
142144 nodes [i ].ID = r .nextID
@@ -207,6 +209,7 @@ func (r *recordingGraphStore) GetNodesByQualifiedNames(ctx context.Context, name
207209}
208210
209211func (r * recordingGraphStore ) GetNodesByFiles (ctx context.Context , filePaths []string ) (map [string ][]graph.Node , error ) {
212+ r .record ("GetNodesByFiles" )
210213 set := make (map [string ]bool , len (filePaths ))
211214 for _ , fp := range filePaths {
212215 set [fp ] = true
@@ -2334,7 +2337,7 @@ func Keep() {}
23342337 t .Fatalf ("Build: %v" , err )
23352338 }
23362339
2337- want := []string {"DeleteGraph" , "UpsertNodes" , "GetNodesByFile " , "UpsertAnnotation" , "UpsertEdges" }
2340+ want := []string {"DeleteGraph" , "UpsertNodes" , "GetNodesByFiles " , "UpsertAnnotation" , "UpsertEdges" }
23382341 for i , op := range want [:4 ] {
23392342 if len (fakeStore .ops ) <= i {
23402343 t .Fatalf ("ops too short: got %v" , fakeStore .ops )
@@ -2359,6 +2362,81 @@ func Keep() {}
23592362 }
23602363}
23612364
2365+ func TestFlushBuildBatch_BatchesNodesAndAnnotationLookups (t * testing.T ) {
2366+ fakeStore := newRecordingGraphStore (t )
2367+ released := 0
2368+ svc := & Service {
2369+ onBatchRelease : func ([]parsedBuildNodeBatch , int ) {
2370+ released ++
2371+ },
2372+ }
2373+ batch := buildPersistBatch {
2374+ files : 2 ,
2375+ nodeBatches : []parsedBuildNodeBatch {
2376+ {
2377+ relPath : "first.go" ,
2378+ nodes : []graph.Node {{
2379+ QualifiedName : "sample.First" ,
2380+ FilePath : "first.go" ,
2381+ Kind : graph .NodeKindFunction ,
2382+ StartLine : 2 ,
2383+ EndLine : 2 ,
2384+ }},
2385+ tsComments : []ingest.CommentBlock {{StartLine : 1 , EndLine : 1 , Text : "@intent first" }},
2386+ language : "go" ,
2387+ sourceLines : []string {"// @intent first" , "func First() {}" },
2388+ },
2389+ {
2390+ relPath : "second.go" ,
2391+ nodes : []graph.Node {{
2392+ QualifiedName : "sample.Second" ,
2393+ FilePath : "second.go" ,
2394+ Kind : graph .NodeKindFunction ,
2395+ StartLine : 2 ,
2396+ EndLine : 2 ,
2397+ }},
2398+ tsComments : []ingest.CommentBlock {{StartLine : 1 , EndLine : 1 , Text : "@intent second" }},
2399+ language : "go" ,
2400+ sourceLines : []string {"// @intent second" , "func Second() {}" },
2401+ },
2402+ },
2403+ }
2404+
2405+ if err := svc .flushBuildBatch (context .Background (), fakeStore , & batch ); err != nil {
2406+ t .Fatalf ("flushBuildBatch: %v" , err )
2407+ }
2408+ if got := len (fakeStore .upsertedNodeBatches ); got != 1 {
2409+ t .Fatalf ("node upsert calls = %d, want 1 (ops=%v)" , got , fakeStore .ops )
2410+ }
2411+ if got := len (fakeStore .upsertedNodeBatches [0 ]); got != 2 {
2412+ t .Fatalf ("batched node count = %d, want 2" , got )
2413+ }
2414+ countOperation := func (want string ) int {
2415+ count := 0
2416+ for _ , op := range fakeStore .ops {
2417+ if op == want {
2418+ count ++
2419+ }
2420+ }
2421+ return count
2422+ }
2423+ if got := countOperation ("GetNodesByFiles" ); got != 1 {
2424+ t .Fatalf ("bulk annotation node lookups = %d, want 1 (ops=%v)" , got , fakeStore .ops )
2425+ }
2426+ if got := countOperation ("GetNodesByFile" ); got != 0 {
2427+ t .Fatalf ("per-file annotation node lookups = %d, want 0 (ops=%v)" , got , fakeStore .ops )
2428+ }
2429+ if got := countOperation ("UpsertAnnotation" ); got != 2 {
2430+ t .Fatalf ("annotation upserts = %d, want 2 (ops=%v)" , got , fakeStore .ops )
2431+ }
2432+ if released != 2 {
2433+ t .Fatalf ("released batches = %d, want 2" , released )
2434+ }
2435+ if batch .files != 0 || len (batch .nodeBatches ) != 0 {
2436+ t .Fatalf ("batch was not reset: %+v" , batch )
2437+ }
2438+ }
2439+
23622440func TestBuild_FlushesLargeBuildInBoundedBatches (t * testing.T ) {
23632441 fakeStore := newRecordingGraphStore (t )
23642442 svc := & Service {
0 commit comments