graph/db: gracefully handle duplicate node announcements
It can happen that we are handling 2 of the same node announcements in the same batch transaction. In that case, our `UpsertNode` conflict assertion may fail. We need to handle this gracefully.
This commit is contained in:
2 files changed
+19
No files matched your search
@@ -125,6 +125,14 @@ func TestNodeInsertionAndDeletion(t *testing.T) {
|
|||||||
require.NoError(t, graph.AddNode(ctx, node))
|
require.NoError(t, graph.AddNode(ctx, node))
|
||||||
assertNodeInCache(t, graph, node, testFeatures)
|
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
|
// Next, fetch the node from the database to ensure everything was
|
||||||
// serialized properly.
|
// serialized properly.
|
||||||
dbNode, err := graph.FetchNode(ctx, testPub)
|
dbNode, err := graph.FetchNode(ctx, testPub)
|
||||||
|
|||||||
@@ -255,6 +255,17 @@ func (s *SQLStore) AddNode(ctx context.Context,
|
|||||||
Opts: batch.NewSchedulerOptions(opts...),
|
Opts: batch.NewSchedulerOptions(opts...),
|
||||||
Do: func(queries SQLQueries) error {
|
Do: func(queries SQLQueries) error {
|
||||||
_, err := upsertNode(ctx, queries, node)
|
_, 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
|
return err
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user