-
Notifications
You must be signed in to change notification settings - Fork 2.2k
payments: kv-to-sql migration (tests + wiring) #10485
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: elle-payment-sql-series-new
Are you sure you want to change the base?
payments: kv-to-sql migration (tests + wiring) #10485
Conversation
Summary of ChangesHello @ziggie1984, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a significant architectural change by migrating the payments database from a Key-Value (KV) store to a native SQL schema. The primary goal is to enhance database robustness, query flexibility, and overall performance for payment-related operations. It includes the complete implementation of the migration logic, a new SQL-backed payment store, and a comprehensive suite of tests to ensure data integrity and correct functionality during and after the migration. This change also prepares the system for future database optimizations and features by leveraging the capabilities of a relational database. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a comprehensive migration for the payments database from a key-value store to SQL. The changes are well-structured, with the migration logic encapsulated in a new payments/db/migration1 package. This package includes a reader for the old KV store format, cleverly handling historical data quirks like duplicate payments by migrating them as HTLC attempts on the primary payment. The migration is correctly wired into the application startup, guarded by a new migration version and a tombstone mechanism to prevent accidental use of the old database post-migration. The testing strategy is particularly strong, featuring data integrity checks, property-based tests, and specific tests for various payment features, which provides high confidence in the correctness of this complex change. My review is positive, with only a couple of minor stylistic suggestions to improve readability.
| return fmt.Errorf("failed to migrate "+ | ||
| "payments to SQL: %w", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This string concatenation is not necessary as the resulting line is well within the 80-character limit. Combining it into a single string improves readability and adheres to the style guide's principle of minimizing lines for error messages where possible.
This applies to a few other places in this file as well:
- Line 1175:
d.logger.Debugf("Setting payments bucket tombstone") - Line 1308:
err = fmt.Errorf("unable to check payments bucket tombstone: %w", err) - Line 1315:
err = fmt.Errorf("payments bucket tombstoned, please switch back to native SQL")
return fmt.Errorf("failed to migrate payments to SQL: %w", err)References
- The style guide states to 'Minimize lines for log and error messages, while adhering to the 80-character limit.' The current code unnecessarily splits a short line, which goes against the 'minimize lines' principle. (link)
| return fmt.Errorf("non bucket element" + | ||
| "in duplicate bucket") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This string concatenation is unnecessary and can be combined into a single string to improve readability and adhere to the style guide's principle of minimizing lines for error messages.
return fmt.Errorf("non bucket element in duplicate bucket")References
- The style guide states to 'Minimize lines for log and error messages, while adhering to the 80-character limit.' The current code unnecessarily splits a short line, which goes against the 'minimize lines' principle. (link)
d8531d2 to
2930b37
Compare
2802da4 to
83bce46
Compare
2930b37 to
8c106c7
Compare
Add a migration specific query which allows to set the failure reason when inserting a payment into the db.
Older LND versions could create multiple payments for the same hash. We need to preserve those historical records during KV→SQL migration, but they don’t fit the normal payment schema because we enforce a unique payment hash constraint. Introduce a lean payment_duplicates table to store only the essential fields (identifier, amount, timestamps, settle/fail data). This keeps the primary payment records stable and makes the migration deterministic even when duplicate records lack attempt info. The table is intentionally minimal and can be dropped after migration if no duplicate payments exist. For now there is no logic in place which allows the noderunner to fetch duplicate payments after the migration.
622021b to
fc449ad
Compare
|
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces the migration logic for moving payment data from the key-value store to a SQL database. The changes are extensive, including a new payments/db/migration1 package that encapsulates the migration logic, new SQL schema definitions for duplicate payments, and the necessary wiring in the configuration builder to trigger the migration. The approach is solid, with good isolation of migration code and thorough validation checks to ensure data integrity. I've found a few minor issues related to code style and typos in error messages and comments, which I've detailed in the review comments.
| var err error | ||
| err = paymentsmig1.MigratePaymentsKVToSQL( | ||
| ctx, | ||
| dbs.ChanStateDB.Backend, | ||
| paymentsmig1sqlc.New(tx.GetTx()), | ||
| &paymentsmig1.SQLStoreConfig{ | ||
| QueryCfg: queryCfg, | ||
| }, | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The declaration of err on line 1163 is redundant. You can use a short variable declaration := on line 1164 to declare and initialize err in one step, which is more idiomatic Go.
err := paymentsmig1.MigratePaymentsKVToSQL(
ctx,
dbs.ChanStateDB.Backend,
paymentsmig1sqlc.New(tx.GetTx()),
&paymentsmig1.SQLStoreConfig{
QueryCfg: queryCfg,
},
)| return fmt.Errorf("payments bucket does not "+ | ||
| "exist: %w", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message "payments bucket does not exist" is confusing here, as this code block is executed when attempting to create the bucket. A more accurate message would be "failed to create payments bucket".
| return fmt.Errorf("payments bucket does not "+ | |
| "exist: %w", err) | |
| return fmt.Errorf("failed to create payments "+ | |
| "bucket: %w", err) |
| return fmt.Errorf("non bucket element" + | ||
| "in duplicate bucket") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| err = dup.ForEach(func(k, v []byte) error { | ||
| subBucket := dup.NestedReadBucket(k) | ||
| if subBucket == nil { | ||
| // We one bucket for each duplicate to be found. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| log.Warnf("Failed to decode extra TLV bytes for "+ | ||
| "failure message: %v", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a typo in the log message. A space is missing between "for" and "failure", which would result in "forfailure message".
| log.Warnf("Failed to decode extra TLV bytes for "+ | |
| "failure message: %v", err) | |
| log.Warnf("Failed to decode extra TLV bytes for "+ | |
| "failure message: %v", err) |
Copy the core payments/db helpers into payments/db/migration1 and add the required sqlc-generated types/queries from sqldb/sqlc. This effectively freezes the migration code so it stays robust against future query or schema changes in the main payments package.
Implement the KV→SQL payment migration and add an in-migration validation pass that deep-compares KV and SQL payment data in batches. Duplicate payments are migrated into the payment_duplicates table, and duplicates without attempt info or explicit resolution are marked failed to ensure terminal state. Validation checks those rows as well.
Add test helpers plus sql_migration_test coverage for KV→SQL migration: basic migration, sequence ordering, data integrity, and feature-specific cases (MPP/AMP, custom records, blinded routes, metadata, failure messages). Also cover duplicate payment migration to payment_duplicates, including missing attempt info to ensure terminal failure is recorded. This gives broad regression coverage for the migration path and its edge-cases.
Add a developer-facing migration_external_test that allows running the KV→SQL payments migration against a real channel.db/channel.sqlite (or a KV postgres backend) to debug migration failures on actual data. The accompanying testdata README documents how to supply a database file and configure the test, so users can validate their data and confirm the migration completes successfully. The test is skipped by default and meant for manual diagnostics.
Hook the payments KV→SQL migration into the SQL migration config and config builder, add logging for the migration path, and introduce tombstone protection to prevent re-running once migration completes.
fc449ad to
83a9946
Compare
Adds the KV db migration code to native SQL.
After merging this PR, the migration is still hidden behind
test_native_sql