diff --git a/graph/db/graph_test.go b/graph/db/graph_test.go index 482c1aa18..08fa36f4e 100644 --- a/graph/db/graph_test.go +++ b/graph/db/graph_test.go @@ -125,6 +125,14 @@ func TestNodeInsertionAndDeletion(t *testing.T) { require.NoError(t, graph.AddNode(ctx, node)) assertNodeInCache(t, graph, node, testFeatures) + // Our AddNode implementation uses the batcher meaning that it is + // possible that two updates for the same node announcement may be + // processed in the same batch. So to avoid the conflict error (since we + // require at the DB level that the new timestamp is strictly + // greater than the previous one), we need to gracefully handle the + // case where the exact same node announcement is added twice. + require.NoError(t, graph.AddNode(ctx, node)) + // Next, fetch the node from the database to ensure everything was // serialized properly. dbNode, err := graph.FetchNode(ctx, testPub) diff --git a/graph/db/sql_store.go b/graph/db/sql_store.go index f13408765..a942405eb 100644 --- a/graph/db/sql_store.go +++ b/graph/db/sql_store.go @@ -255,6 +255,17 @@ func (s *SQLStore) AddNode(ctx context.Context, Opts: batch.NewSchedulerOptions(opts...), Do: func(queries SQLQueries) error { _, err := upsertNode(ctx, queries, node) + + // It is possible that two of the same node + // announcements are both being processed in the same + // batch. This may case the UpsertNode conflict to + // be hit since we require at the db layer that the + // new last_update is greater than the existing + // last_update. We need to gracefully handle this here. + if errors.Is(err, sql.ErrNoRows) { + return nil + } + return err }, }