Commit Graph

149 Commits

Author SHA1 Message Date
Elle Mouton
eb67757a07 graph/db: gracefully handle duplicate channel policy announcements 2025-10-06 11:37:39 +02:00
Elle Mouton
abb9654856 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.
2025-10-06 11:28:33 +02:00
Olaoluwa Osuntokun
f3a8fd842d graph+discovery: update graph/db gossip backlog interfaces to use iter.Seq2
This lets us emit a rich error if things fail when first creating the
iterator, or if any of the yield attempts fail.
2025-09-26 17:01:11 -07:00
Olaoluwa Osuntokun
31ab2ae4b6 sqldb: implement iterator support for ChanUpdatesInHorizon
In this commit, we update the SQL store implementation to support the
new iterator-based API for ChanUpdatesInHorizon. This includes adding
SQL query pagination support and helper functions for efficient batch
processing.

The SQL implementation uses cursor-based pagination with configurable
batch sizes, allowing efficient iteration over large result sets without
loading everything into memory. The query is optimized to use indexes
effectively and minimize database round trips.

New SQL query GetChannelsByPolicyLastUpdateRange is updated to support:
- Cursor-based pagination using (max_update_time, id) compound cursor
- Configurable batch sizes via MaxResults parameter
- Efficient batch caching with updateChanCacheBatch helper
2025-09-26 16:58:11 -07:00
Olaoluwa Osuntokun
c69971c20b sqldb: implement iterator support for NodeUpdatesInHorizon
In this commit, we update the SQL store implementation to support the
new iterator-based API for NodeUpdatesInHorizon. This includes adding a
new SQL query that supports efficient pagination through result sets.

The SQL implementation uses cursor-based pagination with configurable
batch sizes, allowing efficient iteration over large result sets without
loading everything into memory. The query is optimized to use indexes
effectively and minimize database round trips.

New SQL query GetNodesByLastUpdateRange is updated to support:
  * Cursor-based pagination using (last_update, pub_key) compound cursor
  * Optional filtering for public nodes only
  * Configurable batch sizes via MaxResults parameter
2025-09-26 16:57:41 -07:00
Olaoluwa Osuntokun
069888b51a graph/db: convert ChanUpdatesInHorizon to use iterators
In this commit, we refactor the ChanUpdatesInHorizon method to return
an iterator instead of a slice. This change significantly reduces
memory usage when dealing with large result sets by allowing callers to
process items incrementally rather than loading everything into memory
at once.
2025-09-26 16:57:11 -07:00
Olaoluwa Osuntokun
1d6d54e5db graph/db: convert NodeUpdatesInHorizon to use iterators
In this commit, we refactor the NodeUpdatesInHorizon method to return
an iterator instead of a slice. This change significantly reduces
memory usage when dealing with large result sets by allowing callers to
process items incrementally rather than loading everything into memory
at once.

The new implementation uses Go 1.23's iter.Seq type to provide a
standard iterator interface. The method now supports configurable batch
sizes through functional options, allowing fine-tuned control over
memory usage and performance characteristics.

Rather than reading all the entries from disk into memory (before this
commit, we did consult the cache for most entries, skipping the disk
hits), we now expose a chunked iterator instead.

We also make the process of filtering out public nodes first class. This
saves many newly created db transactions later.
2025-09-26 16:56:41 -07:00
Elle
d9647f8b79 Merge pull request #10193 from ellemouton/fixSQLStrHelper
sqldb: fix SQLStr helper
2025-09-04 12:07:25 +02:00
Elle Mouton
40b279687f sqldb: add SQLStrValid helper
The SQL* helpers are meant to always set the `Valid` field of the
sql.Null* type to true. Otherwise they cannot be used to set a valid,
empty field. However, we dont want to break the behaviour of the
existing SQLStr helper and so this commit adds a new helper with the
desired functionality.
2025-09-03 15:46:11 +02:00
Elle Mouton
330f697937 graph: rename HasLightningNode
to HasNode
2025-09-03 10:14:35 +02:00
Elle Mouton
7a1b548e07 graph/db: rename DeleteLightningNode
to DeleteNode
2025-09-03 10:14:35 +02:00
Elle Mouton
cd3bd05810 multi: rename FetchLightningNode
to FetchNode
2025-09-03 10:14:35 +02:00
Elle Mouton
060219780b multi: rename AddLightningNode methods
to AddNode
2025-09-03 10:14:35 +02:00
Elle Mouton
c663a557c4 multi: rename models.LightningNode to models.Node 2025-09-03 10:14:35 +02:00
Elle Mouton
6ef80db746 graph/db+chanbackup: dns add encoding/decoding for persistence 2025-09-03 01:11:35 +00:00
Elle Mouton
f2ed5564ef graph/db+sqldb: improve performance of chan update sql migration
This commit simplifies insertChanEdgePolicyMig. Much of the logic can be
removed given that this method is only used in the context of the graph
SQL migration.

This should improve the performance of the migration quite a lot since
it removes the extra GetChannelAndNodesBySCID call.
2025-09-01 08:07:57 +02:00
Elle Mouton
22bf88e900 graph/db+sqldb: make policy migration idempotent
Finally, we make the channel-policy part of the SQL migration idempotent
by adding a migration-only policy insert query which will not error out
if the policy already exists and does not have a timestamp that is newer
than the existing records timestamp. To keep the commit simple, a
insertChanEdgePolicyMig function is added which is basically identical
to the updateChanEdgePolicy function except for the fact that it uses
the newly added query. In the next commit, it will be simplified even
more.
2025-09-01 08:06:12 +02:00
Elle Mouton
8736fcafa8 graph/db+sqldb: make channel SQL mig retry-safe
In this commit, we make the channel part of the graph SQL migration
idempotent (retry-safe!). We do this by adding a migration-only channel
insert query that will not error out if a the query is called and a
chanenl with the given scid&version already exists. We also ensure that
errors are not thrown if existing channel features & extra types are
re-added.
2025-09-01 08:05:21 +02:00
Elle Mouton
a291d6f1a6 graph/db+sqldb: improve efficiency of node migration
There is no need to use the "collect-then-update" pattern for node
insertion during the SQL migration since if we do have any previously
persisted data for the node and happen to re-run the insertion for that
node, the data will be exactly the same. So we can make use of "On
conflict, no nothing" here too.
2025-09-01 08:02:38 +02:00
Elle Mouton
ddea6d59ce graph/db+sqldb: make node migration idempotent
In this commit, the graph SQL migration is updated so that the node
migration step is retry-safe. This is done by using migration specific
logic & queries that do not use the same node-update-constraint as the
normal node upsert logic. For normal "run-time" logic, we always expect
a node update to have a newer timestamp than any previously stored one.
But for the migration, we will only ever be dealing with a single
announcement for a given node & to make things retry-safe, we dont want
the query to error if we re-insert the exact same node.
2025-09-01 07:56:34 +02:00
Elle Mouton
5b06474744 graph/db+sqldb: batch validation for zombie index migration
Finally, we update the migrateZombieIndex function to use batch
validation just like was done in the previous commits. Here, we
additionally make sure to validate the entire zombie index entry and not
just the SCID.
2025-08-14 08:00:07 +02:00
Elle Mouton
a490e03479 graph/db+sqldb: use batch validation for closed SCID migration
As was done in the previous commits for nodes & channels, we update the
migrateClosedSCIDIndex function here so that it validates migrated
entries in batches rather than one-by-one.
2025-08-14 08:00:06 +02:00
Elle Mouton
8554f17b3f graph/db+sqldb: validate prune log migration using batching
As was done in the previous commits for nodes & channels, we update the
migratePruneLog function here so that it validates migrated entries in
batches rather than one-by-one.
2025-08-14 08:00:06 +02:00
Elle Mouton
81c54611c1 graph/db+sqldb: use batch fetching during channel&policy migration
Restructue the `migrateChannelsAndPolicies` function so that it does the
validation of migrated channels and policies in batches. So instead of
fetching channel and its policies individually after migrating it, we
wait for a minimum batch size to be reached and then validate a batch of
them together. This lets us make way fewer DB round trips.
2025-08-14 08:00:06 +02:00
Elle Mouton
03ef2740a6 graph/db+sqldb: use batch validation for node migration
Restructue the `migrateNodes` function so that it does the validation of
migrated nodes in batches. So instead of fetching each node individually
after migrating it, we wait for a minimum batch size to be reached and
then validate a batch of nodes together. This lets us make way fewer DB
round trips.
2025-08-14 08:00:06 +02:00
Elle Mouton
218aa9eaa8 graph/db: move sanity check out of insertChannel
We do this so that this lookup is only done in the situation it is
actually needed. During a migration, we dont need to special case this
AlreadyExists error since we will terminate the transaction either way.
So there is no need for the extra lookup during the migration.

A timing analysis showed that this query was significantly impacting the
performance of the migration when run with a postgres backend.
2025-08-14 07:57:33 +02:00
Elle Mouton
b1deddec44 multi: remove DefaultQueryConfig
And always make use of either the new DefaultSQLiteConfig or
DefaultPostgresConfig.
2025-08-13 14:43:31 +02:00
Elle Mouton
8de33fa601 graph/db: batch fetching for FetchChanInfos 2025-08-07 08:12:40 +02:00
Elle Mouton
594c842aeb graph/db: batch loading for DisconnectBlockAtHeight 2025-08-07 08:12:40 +02:00
Elle Mouton
69bcf47dca graph/db: use batch loading for PruneGraph 2025-08-07 08:12:40 +02:00
Elle Mouton
556af8e221 graph/db: use batch fetching for DeleteChannelEdges 2025-08-07 08:12:40 +02:00
Elle Mouton
ebe6a8af9f graph/db: use batch loading for ChanUpdatesInHorizon
The following performance gains were measured using the new benchmark
test.

```
name                                      old time/op  new time/op  delta
ChanUpdatesInHorizon-native-sqlite-10     18.5s ± 3%    2.0s ± 5%  -89.11%  (p=0.000 n=9+9)
ChanUpdatesInHorizon-native-postgres-10   59.0s ± 3%    0.8s ±10%  -98.65%  (p=0.000 n=10+9)
```
2025-08-07 08:12:40 +02:00
Elle Mouton
ce3401ee5d graph/db: refactor buildNode to not take a pointer
Since the type returned from the DB is not a pointer. This will be
useful later on.
2025-08-07 08:04:20 +02:00
Elle Mouton
f51adaf31f graph/db: refactor makeZombiePubkeys
Let the helper method only take the params it needs so that we dont need
to construct an entire models.ChannelEdgeInfo object to pass to it. This
will be useful later on.
2025-08-07 08:04:20 +02:00
Elle Mouton
8aa8c7cc42 multi: remove the NodeRTx interface type 2025-08-06 09:56:21 +02:00
Elle Mouton
15e17e1270 graph/db: remove NodeRTx ForEachChannel method 2025-08-06 09:52:10 +02:00
Elle Mouton
5727bfa688 graph/db: let ForEachNodeCached maybe fetch node addresses
Here we adjust the ForEachNodeCached graph DB method to pass in a node's
addresses into the provided call-back if requested. This will allow us
to improve the performance of node/channel iteration in the autopilot
subserver.
2025-08-06 09:50:54 +02:00
Elle Mouton
ae566744c4 graph/db+autopilot: remove NodeRTx FetchNode method
In this commit, we remove the need for the NodeRTx interface to have the
FetchNode method on it.
2025-08-05 09:59:13 +02:00
Elle Mouton
0850bf4781 graph/db: batch fetch channel data in forEachNodeChannel
Update the forEachNodeChannel helper to batch fetch channel data.
2025-08-05 08:00:19 +02:00
Elle Mouton
dc6f9256bc graph/db: batch fetch channels in ForEachNodeCached
Previously, ForEachNodeCached would batch fetch node _feature_ data but
would still fetch the channel set of each node in a node-by-node fashion
which is not ideal. So this commit updates this method to make use of
the new sqldb.ExecuteCollectAndBatchWithSharedDataQuery helper. It lets
us batch load channel data for a range of node IDs.

This _greatly_ improves the performance of the method.
2025-08-05 08:00:19 +02:00
Elle Mouton
ada349dcf2 graph/db: batch collect node feature data
In this commit, we update the SQLStore's ForEachNodeCacheable and
ForEachNodeCached methods to use batch collection for node feature bits.

This results in the following performance gains:

```
name                                      old time/op  new time/op  delta

ForEachNodeCacheable-native-sqlite-10     184ms ± 2%   145ms ±10%  -21.45%  (p=0.000 n=10+10)
ForEachNodeCacheable-native-postgres-10   697ms ± 8%    51ms ± 4%  -92.68%  (p=0.000 n=9+10)
```
2025-08-05 08:00:19 +02:00
Elle Mouton
ae13158b68 graph/db: update ForEachChannel to use new sqldb helper
Refactor to let ForEachChannel make use of the new
sqldb.ExecuteCollectAndBatchWithSharedDataQuery helper.
2025-08-05 06:36:36 +02:00
Elle Mouton
1219cdb7f1 graph/db: use sqldb helper for ForEachNode
A pure refactor commit which updates the ForEachNode method to make use
of the new sqldb.ExecuteCollectAndBatchWithSharedDataQuery helper.
2025-08-05 06:36:34 +02:00
Elle Mouton
31978b99f4 graph/db: update forEachNodeCacheable to use sqldb helper
A pure refactor which updates forEachNodeCacheable to make use of the
new sqldb.ExecutePaginatedQuery helper.
2025-07-31 15:33:08 +02:00
Elle Mouton
2d09acfca2 graph/db: update ForEachChannelCacheable to use new helper
A pure refactor commit which updates ForEachChannelCacheable to make use
of the new sqldb.ExecutePaginatedQuery helper.
2025-07-31 15:33:08 +02:00
Elle Mouton
61299894e1 graph/db: add buildCachedChanPolicies helper
Here we just remove some code duplication by adding a
buildCachedChanPolicies helper.
2025-07-31 15:33:08 +02:00
Elle Mouton
0f7c0ae9e7 graph/db: refactor to use sqldb.QueryConfig value
This commit is a pure refactor. Here all we are doing is removing the
old `pageSize` constant used in the SQLStore code and instead using the
value provided in the QueryConfig struct.
2025-07-31 15:33:08 +02:00
Elle Mouton
a6248872cb sqldb: rename ExecutePagedQuery to ExecuteBatchQuery
We rename this helper along the config types & helper types for it
because the word "page" is used more often in the context of paging
through results using an offset and limit whereas this helper is
specifically used to split up the slice in queries of the form
"WHERE x in []slice". We do this rename so that there is mimimal
confusion in contexts where we use batching along with actual paging.

The config struct is also renamed to QueryConfig in preparation for it
holding more config options.
2025-07-31 15:32:53 +02:00
Elle Mouton
c1ba7a97a8 graph/db: increase default page size 2025-07-31 07:19:15 +02:00
Elle Mouton
a6b077064f graph/db: use batch loading for ForEachChannel 2025-07-31 07:19:15 +02:00