mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-11-30 16:10:01 +01:00
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.
This commit is contained in:
@@ -120,29 +120,6 @@ func (q *Queries) CreateChannel(ctx context.Context, arg CreateChannelParams) (i
|
||||
return id, err
|
||||
}
|
||||
|
||||
const createChannelExtraType = `-- name: CreateChannelExtraType :exec
|
||||
/* ─────────────────────────────────────────────
|
||||
graph_channel_extra_types table queries
|
||||
─────────────────────────────────────────────
|
||||
*/
|
||||
|
||||
INSERT INTO graph_channel_extra_types (
|
||||
channel_id, type, value
|
||||
)
|
||||
VALUES ($1, $2, $3)
|
||||
`
|
||||
|
||||
type CreateChannelExtraTypeParams struct {
|
||||
ChannelID int64
|
||||
Type int64
|
||||
Value []byte
|
||||
}
|
||||
|
||||
func (q *Queries) CreateChannelExtraType(ctx context.Context, arg CreateChannelExtraTypeParams) error {
|
||||
_, err := q.db.ExecContext(ctx, createChannelExtraType, arg.ChannelID, arg.Type, arg.Value)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteChannelPolicyExtraTypes = `-- name: DeleteChannelPolicyExtraTypes :exec
|
||||
DELETE FROM graph_channel_policy_extra_types
|
||||
WHERE channel_policy_id = $1
|
||||
@@ -2360,7 +2337,9 @@ INSERT INTO graph_channel_features (
|
||||
channel_id, feature_bit
|
||||
) VALUES (
|
||||
$1, $2
|
||||
)
|
||||
) ON CONFLICT (channel_id, feature_bit)
|
||||
-- Do nothing if the channel_id and feature_bit already exist.
|
||||
DO NOTHING
|
||||
`
|
||||
|
||||
type InsertChannelFeatureParams struct {
|
||||
@@ -2373,6 +2352,72 @@ func (q *Queries) InsertChannelFeature(ctx context.Context, arg InsertChannelFea
|
||||
return err
|
||||
}
|
||||
|
||||
const insertChannelMig = `-- name: InsertChannelMig :one
|
||||
INSERT INTO graph_channels (
|
||||
version, scid, node_id_1, node_id_2,
|
||||
outpoint, capacity, bitcoin_key_1, bitcoin_key_2,
|
||||
node_1_signature, node_2_signature, bitcoin_1_signature,
|
||||
bitcoin_2_signature
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12
|
||||
) ON CONFLICT (scid, version)
|
||||
-- If a conflict occurs, we have already migrated this channel. However, we
|
||||
-- still need to do an "UPDATE SET" here instead of "DO NOTHING" because
|
||||
-- otherwise, the "RETURNING id" part does not work.
|
||||
DO UPDATE SET
|
||||
node_id_1 = EXCLUDED.node_id_1,
|
||||
node_id_2 = EXCLUDED.node_id_2,
|
||||
outpoint = EXCLUDED.outpoint,
|
||||
capacity = EXCLUDED.capacity,
|
||||
bitcoin_key_1 = EXCLUDED.bitcoin_key_1,
|
||||
bitcoin_key_2 = EXCLUDED.bitcoin_key_2,
|
||||
node_1_signature = EXCLUDED.node_1_signature,
|
||||
node_2_signature = EXCLUDED.node_2_signature,
|
||||
bitcoin_1_signature = EXCLUDED.bitcoin_1_signature,
|
||||
bitcoin_2_signature = EXCLUDED.bitcoin_2_signature
|
||||
RETURNING id
|
||||
`
|
||||
|
||||
type InsertChannelMigParams struct {
|
||||
Version int16
|
||||
Scid []byte
|
||||
NodeID1 int64
|
||||
NodeID2 int64
|
||||
Outpoint string
|
||||
Capacity sql.NullInt64
|
||||
BitcoinKey1 []byte
|
||||
BitcoinKey2 []byte
|
||||
Node1Signature []byte
|
||||
Node2Signature []byte
|
||||
Bitcoin1Signature []byte
|
||||
Bitcoin2Signature []byte
|
||||
}
|
||||
|
||||
// NOTE: This query is only meant to be used by the graph SQL migration since
|
||||
// for that migration, in order to be retry-safe, we don't want to error out if
|
||||
// we re-insert the same channel again (which would error if the normal
|
||||
// CreateChannel query is used because of the uniqueness constraint on the scid
|
||||
// and version columns).
|
||||
func (q *Queries) InsertChannelMig(ctx context.Context, arg InsertChannelMigParams) (int64, error) {
|
||||
row := q.db.QueryRowContext(ctx, insertChannelMig,
|
||||
arg.Version,
|
||||
arg.Scid,
|
||||
arg.NodeID1,
|
||||
arg.NodeID2,
|
||||
arg.Outpoint,
|
||||
arg.Capacity,
|
||||
arg.BitcoinKey1,
|
||||
arg.BitcoinKey2,
|
||||
arg.Node1Signature,
|
||||
arg.Node2Signature,
|
||||
arg.Bitcoin1Signature,
|
||||
arg.Bitcoin2Signature,
|
||||
)
|
||||
var id int64
|
||||
err := row.Scan(&id)
|
||||
return id, err
|
||||
}
|
||||
|
||||
const insertClosedChannel = `-- name: InsertClosedChannel :exec
|
||||
/* ─────────────────────────────────────────────
|
||||
graph_closed_scid table queries
|
||||
@@ -3308,6 +3353,32 @@ func (q *Queries) ListNodesPaginated(ctx context.Context, arg ListNodesPaginated
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const upsertChannelExtraType = `-- name: UpsertChannelExtraType :exec
|
||||
/* ─────────────────────────────────────────────
|
||||
graph_channel_extra_types table queries
|
||||
─────────────────────────────────────────────
|
||||
*/
|
||||
|
||||
INSERT INTO graph_channel_extra_types (
|
||||
channel_id, type, value
|
||||
)
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT (channel_id, type)
|
||||
-- Update the value if a conflict occurs on channel_id and type.
|
||||
DO UPDATE SET value = EXCLUDED.value
|
||||
`
|
||||
|
||||
type UpsertChannelExtraTypeParams struct {
|
||||
ChannelID int64
|
||||
Type int64
|
||||
Value []byte
|
||||
}
|
||||
|
||||
func (q *Queries) UpsertChannelExtraType(ctx context.Context, arg UpsertChannelExtraTypeParams) error {
|
||||
_, err := q.db.ExecContext(ctx, upsertChannelExtraType, arg.ChannelID, arg.Type, arg.Value)
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertEdgePolicy = `-- name: UpsertEdgePolicy :one
|
||||
/* ─────────────────────────────────────────────
|
||||
graph_channel_policies table queries
|
||||
|
||||
@@ -16,7 +16,6 @@ type Querier interface {
|
||||
ClearKVInvoiceHashIndex(ctx context.Context) error
|
||||
CountZombieChannels(ctx context.Context, version int16) (int64, error)
|
||||
CreateChannel(ctx context.Context, arg CreateChannelParams) (int64, error)
|
||||
CreateChannelExtraType(ctx context.Context, arg CreateChannelExtraTypeParams) error
|
||||
DeleteCanceledInvoices(ctx context.Context) (sql.Result, error)
|
||||
DeleteChannelPolicyExtraTypes(ctx context.Context, channelPolicyID int64) error
|
||||
DeleteChannels(ctx context.Context, ids []int64) error
|
||||
@@ -90,6 +89,12 @@ type Querier interface {
|
||||
InsertAMPSubInvoiceHTLC(ctx context.Context, arg InsertAMPSubInvoiceHTLCParams) error
|
||||
InsertChanPolicyExtraType(ctx context.Context, arg InsertChanPolicyExtraTypeParams) error
|
||||
InsertChannelFeature(ctx context.Context, arg InsertChannelFeatureParams) error
|
||||
// NOTE: This query is only meant to be used by the graph SQL migration since
|
||||
// for that migration, in order to be retry-safe, we don't want to error out if
|
||||
// we re-insert the same channel again (which would error if the normal
|
||||
// CreateChannel query is used because of the uniqueness constraint on the scid
|
||||
// and version columns).
|
||||
InsertChannelMig(ctx context.Context, arg InsertChannelMigParams) (int64, error)
|
||||
InsertClosedChannel(ctx context.Context, scid []byte) error
|
||||
InsertInvoice(ctx context.Context, arg InsertInvoiceParams) (int64, error)
|
||||
InsertInvoiceFeature(ctx context.Context, arg InsertInvoiceFeatureParams) error
|
||||
@@ -130,6 +135,7 @@ type Querier interface {
|
||||
UpdateInvoiceHTLCs(ctx context.Context, arg UpdateInvoiceHTLCsParams) error
|
||||
UpdateInvoiceState(ctx context.Context, arg UpdateInvoiceStateParams) (sql.Result, error)
|
||||
UpsertAMPSubInvoice(ctx context.Context, arg UpsertAMPSubInvoiceParams) (sql.Result, error)
|
||||
UpsertChannelExtraType(ctx context.Context, arg UpsertChannelExtraTypeParams) error
|
||||
UpsertEdgePolicy(ctx context.Context, arg UpsertEdgePolicyParams) (int64, error)
|
||||
UpsertNode(ctx context.Context, arg UpsertNodeParams) (int64, error)
|
||||
UpsertNodeAddress(ctx context.Context, arg UpsertNodeAddressParams) error
|
||||
|
||||
@@ -738,7 +738,9 @@ INSERT INTO graph_channel_features (
|
||||
channel_id, feature_bit
|
||||
) VALUES (
|
||||
$1, $2
|
||||
);
|
||||
) ON CONFLICT (channel_id, feature_bit)
|
||||
-- Do nothing if the channel_id and feature_bit already exist.
|
||||
DO NOTHING;
|
||||
|
||||
-- name: GetChannelFeaturesBatch :many
|
||||
SELECT
|
||||
@@ -753,11 +755,14 @@ ORDER BY channel_id, feature_bit;
|
||||
─────────────────────────────────────────────
|
||||
*/
|
||||
|
||||
-- name: CreateChannelExtraType :exec
|
||||
-- name: UpsertChannelExtraType :exec
|
||||
INSERT INTO graph_channel_extra_types (
|
||||
channel_id, type, value
|
||||
)
|
||||
VALUES ($1, $2, $3);
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT (channel_id, type)
|
||||
-- Update the value if a conflict occurs on channel_id and type.
|
||||
DO UPDATE SET value = EXCLUDED.value;
|
||||
|
||||
-- name: GetChannelExtrasBatch :many
|
||||
SELECT
|
||||
@@ -1029,3 +1034,33 @@ ON CONFLICT (pub_key, version)
|
||||
color = EXCLUDED.color,
|
||||
signature = EXCLUDED.signature
|
||||
RETURNING id;
|
||||
|
||||
-- NOTE: This query is only meant to be used by the graph SQL migration since
|
||||
-- for that migration, in order to be retry-safe, we don't want to error out if
|
||||
-- we re-insert the same channel again (which would error if the normal
|
||||
-- CreateChannel query is used because of the uniqueness constraint on the scid
|
||||
-- and version columns).
|
||||
-- name: InsertChannelMig :one
|
||||
INSERT INTO graph_channels (
|
||||
version, scid, node_id_1, node_id_2,
|
||||
outpoint, capacity, bitcoin_key_1, bitcoin_key_2,
|
||||
node_1_signature, node_2_signature, bitcoin_1_signature,
|
||||
bitcoin_2_signature
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12
|
||||
) ON CONFLICT (scid, version)
|
||||
-- If a conflict occurs, we have already migrated this channel. However, we
|
||||
-- still need to do an "UPDATE SET" here instead of "DO NOTHING" because
|
||||
-- otherwise, the "RETURNING id" part does not work.
|
||||
DO UPDATE SET
|
||||
node_id_1 = EXCLUDED.node_id_1,
|
||||
node_id_2 = EXCLUDED.node_id_2,
|
||||
outpoint = EXCLUDED.outpoint,
|
||||
capacity = EXCLUDED.capacity,
|
||||
bitcoin_key_1 = EXCLUDED.bitcoin_key_1,
|
||||
bitcoin_key_2 = EXCLUDED.bitcoin_key_2,
|
||||
node_1_signature = EXCLUDED.node_1_signature,
|
||||
node_2_signature = EXCLUDED.node_2_signature,
|
||||
bitcoin_1_signature = EXCLUDED.bitcoin_1_signature,
|
||||
bitcoin_2_signature = EXCLUDED.bitcoin_2_signature
|
||||
RETURNING id;
|
||||
|
||||
Reference in New Issue
Block a user