55 "encoding/json"
66 "fmt"
77 "reflect"
8+ "sync"
89 "time"
910
1011 "github.com/compozy/gograph/engine/core"
@@ -25,6 +26,9 @@ type Neo4jConfig struct {
2526 BatchSize int // Batch size for bulk operations
2627}
2728
29+ // Global mutex to prevent concurrent index creation across all repository instances
30+ var indexCreationMutex sync.Mutex
31+
2832// Neo4jRepository implements the graph.Repository interface
2933type Neo4jRepository struct {
3034 driver neo4j.DriverWithContext
@@ -131,7 +135,9 @@ func (r *Neo4jRepository) Close() error {
131135
132136// CreateNode creates a new node in the graph
133137func (r * Neo4jRepository ) CreateNode (ctx context.Context , node * core.Node ) error {
134- session := r .driver .NewSession (ctx , neo4j.SessionConfig {})
138+ session := r .driver .NewSession (ctx , neo4j.SessionConfig {
139+ DatabaseName : r .config .Database ,
140+ })
135141 defer session .Close (ctx )
136142
137143 // Build the query with dynamic properties
@@ -176,7 +182,9 @@ func (r *Neo4jRepository) CreateNodes(ctx context.Context, nodes []core.Node) er
176182 return nil
177183 }
178184
179- session := r .driver .NewSession (ctx , neo4j.SessionConfig {})
185+ session := r .driver .NewSession (ctx , neo4j.SessionConfig {
186+ DatabaseName : r .config .Database ,
187+ })
180188 defer session .Close (ctx )
181189
182190 // Determine batch size (default to 1000 if not configured)
@@ -251,7 +259,9 @@ func (r *Neo4jRepository) CreateNodes(ctx context.Context, nodes []core.Node) er
251259
252260// GetNode retrieves a node by ID
253261func (r * Neo4jRepository ) GetNode (ctx context.Context , id core.ID ) (* core.Node , error ) {
254- session := r .driver .NewSession (ctx , neo4j.SessionConfig {})
262+ session := r .driver .NewSession (ctx , neo4j.SessionConfig {
263+ DatabaseName : r .config .Database ,
264+ })
255265 defer session .Close (ctx )
256266
257267 query := `
@@ -290,7 +300,9 @@ func (r *Neo4jRepository) GetNode(ctx context.Context, id core.ID) (*core.Node,
290300
291301// UpdateNode updates an existing node
292302func (r * Neo4jRepository ) UpdateNode (ctx context.Context , node * core.Node ) error {
293- session := r .driver .NewSession (ctx , neo4j.SessionConfig {})
303+ session := r .driver .NewSession (ctx , neo4j.SessionConfig {
304+ DatabaseName : r .config .Database ,
305+ })
294306 defer session .Close (ctx )
295307
296308 query := `
@@ -320,7 +332,9 @@ func (r *Neo4jRepository) UpdateNode(ctx context.Context, node *core.Node) error
320332
321333// DeleteNode deletes a node by ID
322334func (r * Neo4jRepository ) DeleteNode (ctx context.Context , id core.ID ) error {
323- session := r .driver .NewSession (ctx , neo4j.SessionConfig {})
335+ session := r .driver .NewSession (ctx , neo4j.SessionConfig {
336+ DatabaseName : r .config .Database ,
337+ })
324338 defer session .Close (ctx )
325339
326340 query := `
@@ -347,7 +361,9 @@ func (r *Neo4jRepository) DeleteNode(ctx context.Context, id core.ID) error {
347361
348362// CreateRelationship creates a new relationship
349363func (r * Neo4jRepository ) CreateRelationship (ctx context.Context , rel * core.Relationship ) error {
350- session := r .driver .NewSession (ctx , neo4j.SessionConfig {})
364+ session := r .driver .NewSession (ctx , neo4j.SessionConfig {
365+ DatabaseName : r .config .Database ,
366+ })
351367 defer session .Close (ctx )
352368
353369 // Build the relationship properties map (excluding node matching properties)
@@ -395,7 +411,9 @@ func (r *Neo4jRepository) CreateRelationships(ctx context.Context, rels []core.R
395411 return nil
396412 }
397413
398- session := r .driver .NewSession (ctx , neo4j.SessionConfig {})
414+ session := r .driver .NewSession (ctx , neo4j.SessionConfig {
415+ DatabaseName : r .config .Database ,
416+ })
399417 defer session .Close (ctx )
400418
401419 // Determine batch size (default to 1000 if not configured)
@@ -476,7 +494,9 @@ func (r *Neo4jRepository) CreateRelationships(ctx context.Context, rels []core.R
476494
477495// GetRelationship retrieves a relationship by ID
478496func (r * Neo4jRepository ) GetRelationship (ctx context.Context , id core.ID ) (* core.Relationship , error ) {
479- session := r .driver .NewSession (ctx , neo4j.SessionConfig {})
497+ session := r .driver .NewSession (ctx , neo4j.SessionConfig {
498+ DatabaseName : r .config .Database ,
499+ })
480500 defer session .Close (ctx )
481501
482502 query := `
@@ -515,7 +535,9 @@ func (r *Neo4jRepository) GetRelationship(ctx context.Context, id core.ID) (*cor
515535
516536// DeleteRelationship deletes a relationship by ID
517537func (r * Neo4jRepository ) DeleteRelationship (ctx context.Context , id core.ID ) error {
518- session := r .driver .NewSession (ctx , neo4j.SessionConfig {})
538+ session := r .driver .NewSession (ctx , neo4j.SessionConfig {
539+ DatabaseName : r .config .Database ,
540+ })
519541 defer session .Close (ctx )
520542
521543 query := `
@@ -587,7 +609,9 @@ func (r *Neo4jRepository) ImportAnalysisResult(ctx context.Context, result *core
587609 }
588610
589611 // Use a single session for the entire import to ensure consistency
590- session := r .driver .NewSession (ctx , neo4j.SessionConfig {})
612+ session := r .driver .NewSession (ctx , neo4j.SessionConfig {
613+ DatabaseName : r .config .Database ,
614+ })
591615 defer session .Close (ctx )
592616
593617 // Execute the entire import in a single write transaction to ensure consistency
@@ -781,7 +805,13 @@ func (r *Neo4jRepository) createRelationshipsInTransaction(
781805
782806// ensureIndexes creates indexes for better query performance on large codebases
783807func (r * Neo4jRepository ) ensureIndexes (ctx context.Context ) error {
784- session := r .driver .NewSession (ctx , neo4j.SessionConfig {})
808+ // Use global mutex to prevent concurrent index creation across all instances
809+ indexCreationMutex .Lock ()
810+ defer indexCreationMutex .Unlock ()
811+
812+ session := r .driver .NewSession (ctx , neo4j.SessionConfig {
813+ DatabaseName : r .config .Database ,
814+ })
785815 defer session .Close (ctx )
786816
787817 // Create single-property indexes
@@ -946,7 +976,9 @@ func (r *Neo4jRepository) createConstraints(ctx context.Context, session neo4j.S
946976
947977// createProjectMetadata creates a metadata node for the project
948978func (r * Neo4jRepository ) createProjectMetadata (ctx context.Context , result * core.AnalysisResult ) error {
949- session := r .driver .NewSession (ctx , neo4j.SessionConfig {})
979+ session := r .driver .NewSession (ctx , neo4j.SessionConfig {
980+ DatabaseName : r .config .Database ,
981+ })
950982 defer session .Close (ctx )
951983
952984 query := `
@@ -981,7 +1013,9 @@ func (r *Neo4jRepository) createProjectMetadata(ctx context.Context, result *cor
9811013
9821014// ClearProject removes all nodes and relationships for a specific project
9831015func (r * Neo4jRepository ) ClearProject (ctx context.Context , projectID core.ID ) error {
984- session := r .driver .NewSession (ctx , neo4j.SessionConfig {})
1016+ session := r .driver .NewSession (ctx , neo4j.SessionConfig {
1017+ DatabaseName : r .config .Database ,
1018+ })
9851019 defer session .Close (ctx )
9861020
9871021 // Only delete nodes and relationships for the specified project_id
@@ -1014,7 +1048,9 @@ func (r *Neo4jRepository) FindNodesByType(
10141048 nodeType core.NodeType ,
10151049 projectID core.ID ,
10161050) ([]core.Node , error ) {
1017- session := r .driver .NewSession (ctx , neo4j.SessionConfig {})
1051+ session := r .driver .NewSession (ctx , neo4j.SessionConfig {
1052+ DatabaseName : r .config .Database ,
1053+ })
10181054 defer session .Close (ctx )
10191055
10201056 query := fmt .Sprintf (`
@@ -1062,7 +1098,9 @@ func (r *Neo4jRepository) FindNodesByName(
10621098 name string ,
10631099 projectID core.ID ,
10641100) ([]core.Node , error ) {
1065- session := r .driver .NewSession (ctx , neo4j.SessionConfig {})
1101+ session := r .driver .NewSession (ctx , neo4j.SessionConfig {
1102+ DatabaseName : r .config .Database ,
1103+ })
10661104 defer session .Close (ctx )
10671105
10681106 query := `
@@ -1111,7 +1149,9 @@ func (r *Neo4jRepository) FindRelationshipsByType(
11111149 relType core.RelationType ,
11121150 projectID core.ID ,
11131151) ([]core.Relationship , error ) {
1114- session := r .driver .NewSession (ctx , neo4j.SessionConfig {})
1152+ session := r .driver .NewSession (ctx , neo4j.SessionConfig {
1153+ DatabaseName : r .config .Database ,
1154+ })
11151155 defer session .Close (ctx )
11161156
11171157 query := fmt .Sprintf (`
0 commit comments