-
Notifications
You must be signed in to change notification settings - Fork 54
get intent by txid #884
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
get intent by txid #884
Conversation
WalkthroughAdds txid to Intent and propagates it across domain, constructors, repositories, SQLC, migrations and backfill; exposes GET /v1/intent (HTTP + gRPC) to fetch Intent by txid and adds INTENT_NOT_FOUND error. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant HTTP as HTTP/REST
participant GRPC as ArkServiceHandler
participant App as Service
participant RepoMgr as RepoManager
participant DB as Storage
Client->>HTTP: GET /v1/intent?txid=...
HTTP->>GRPC: Invoke GetIntent
GRPC->>App: GetIntentByTxid(ctx, txid)
App->>RepoMgr: Rounds().GetIntentByTxid(ctx, txid)
RepoMgr->>DB: query SelectIntentByTxid(txid) / index lookup
DB-->>RepoMgr: intent row or nil
RepoMgr-->>App: domain.Intent or nil
App-->>GRPC: GetIntentResponse or INTENT_NOT_FOUND
GRPC-->>HTTP: 200 or 404
HTTP-->>Client: response
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
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.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
internal/core/domain/round.go (1)
110-116: Silent error discard may hide malformed proofs.The error from
deriveTxidFromProofis discarded with_. If the proof is malformed and txid derivation fails,intent.Txidremains empty, which could cause lookup failures later. Consider logging the error or propagating it if txid derivation is required for valid intents.🐛 Suggested fix to handle derivation errors
for _, intent := range intents { - txid, _ := deriveTxidFromProof(intent.Proof) - intent.Txid = txid + txid, err := deriveTxidFromProof(intent.Proof) + if err != nil { + return nil, fmt.Errorf("failed to derive txid from proof for intent %s: %w", intent.Id, err) + } + intent.Txid = txid if err := intent.validate(false); err != nil { return nil, err } }internal/core/domain/intent.go (1)
20-32: Error fromderiveTxidFromProofis silently discarded, losing diagnostic context.Line 21 ignores the error returned by
deriveTxidFromProof. If the proof is malformed,txidwill be empty, and validation will fail with the generic "missing txid" error instead of the actual parsing error (e.g., "error deriving txid from proof: ...").This loses valuable diagnostic information about why the intent creation failed.
Proposed fix
func NewIntent(proof, message string, inputs []Vtxo) (*Intent, error) { - txid, _ := deriveTxidFromProof(proof) + txid, err := deriveTxidFromProof(proof) + if err != nil { + return nil, fmt.Errorf("failed to create intent: %w", err) + } intent := &Intent{ Id: uuid.New().String(), Inputs: inputs, Proof: proof, Message: message, Txid: txid, } if err := intent.validate(true); err != nil { return nil, err } return intent, nil }
🤖 Fix all issues with AI agents
In `@internal/infrastructure/db/postgres/intent_txid_migration.go`:
- Around line 270-279: The current SQL in the copyData constant in
intent_txid_migration.go uses an INNER JOIN between vtxo and intent which drops
vtxo rows with NULL or missing intent_id; change the join to a LEFT JOIN (FROM
vtxo AS v LEFT JOIN intent AS i ON i.id = v.intent_id) so you still select v.*
and i.id AS intent_id (which will be NULL when no intent exists) and preserve
all vtxo rows into vtxo_new.
- Around line 190-247: fixReceiverTableFK currently uses SQLite-specific PRAGMA
and table-recreation DDL which will fail on PostgreSQL; replace the SQLite steps
with PostgreSQL-compatible ALTER TABLE statements and remove PRAGMA usage.
Specifically, in fixReceiverTableFK: drop the `PRAGMA foreign_keys = OFF/ON`
ExecContext calls, stop creating/dropping receiver_new and copying data, and
instead execute PostgreSQL DDL such as ALTER TABLE receiver ADD CONSTRAINT ...
FOREIGN KEY (intent_id) REFERENCES intent(id) and, if you need the composite
primary key, add or replace the primary key with ALTER TABLE receiver ADD
CONSTRAINT <name> PRIMARY KEY (intent_id, pubkey, onchain_address) (dropping any
existing PK first). Keep the transaction logic (tx := db.BeginTx,
tx.Commit/Rollback) and use tx.ExecContext for the ALTER TABLE statements,
returning formatted errors from the same function (fixReceiverTableFK) as
currently done.
- Around line 249-318: fixVtxoTableFK is using SQLite-specific PRAGMA and
table-recreation logic; remove the `PRAGMA foreign_keys = OFF;` and `PRAGMA
foreign_keys = ON;` Execs and replace the SQL with PostgreSQL-compatible
statements: create `vtxo_new` with proper Postgres types and the FOREIGN KEY
(intent_id) REFERENCES intent(id) clause, copy rows using an INSERT ... SELECT
(use LEFT JOIN if intent_id can be NULL or to preserve unmatched rows), then
DROP TABLE vtxo and ALTER TABLE vtxo_new RENAME TO vtxo inside the same
transaction; keep existing transaction handling (tx.BeginTx/Commit/Rollback) but
do not rely on PRAGMA toggles. Ensure the `createNew` and `copyData` SQL use
Postgres syntax (no IF NOT EXISTS on columns/PRAGMA) so the migration runs on
PostgreSQL.
- Around line 78-82: The INSERT SQL in the insertIntent constant (named
"InsertIntent" :exec) uses SQLite-style `?` placeholders which will fail on
Postgres; update the VALUES placeholders to positional Postgres form `$1, $2,
$3, $4, $5` (keeping the same column order id, round_id, proof, message, txid)
so the query executes correctly with the Postgres driver.
- Around line 156-182: The code incorrectly uses SQLite PRAGMA statements in the
migration (calls to tx.ExecContext executing `PRAGMA foreign_keys = OFF/ON`
around the intent swap). Replace those PRAGMA calls with a PostgreSQL-safe
approach: before dropping/renaming tables, either set session_replication_role =
'replica' for the session (requires superuser) via tx.ExecContext, or
programmatically drop and later recreate any foreign key constraints that
reference the intent table (find constraints referencing "intent", drop them,
perform the DROP TABLE/ALTER TABLE on intent and intent_new, then re-add the
constraints). Update the calls around the intent backfill/rename (the functions
using tx.ExecContext and the intent/intent_new checks and DROP/ALTER steps) to
use one of these Postgres methods instead of PRAGMA.
In `@internal/infrastructure/db/service.go`:
- Around line 296-315: The Postgres migration path is missing the same stepwise
backfill used for SQLite, so adding a NOT NULL UNIQUE txid will fail on existing
rows; update the initialization logic in service.go to call the Postgres
backfill before enforcing the final migration version: detect current migration
version via m.Version(), run m.Migrate(intentTxidMigrationBegin) if needed, then
invoke postgresdb.BackfillIntentTxid(ctx, db) (same as
sqlitedb.BackfillIntentTxid) to populate txid for existing intent rows, and only
after successful backfill proceed to the final migration step (or ensure the
Postgres migration SQL initially creates a nullable txid column then enforces
NOT NULL after backfill).
In `@internal/infrastructure/db/sqlite/intent_txid_migration.go`:
- Around line 31-33: The backfillIntent call uses context.Background() which
prevents propagation of the caller's context (cancellation/deadlines/tracing);
replace context.Background() with the provided ctx variable at the call site
where backfillIntent(context.Background(), dbh) is invoked so
backfillIntent(ctx, dbh) uses the caller's context for proper cancellation and
tracing.
- Around line 197-208: The INSERT SELECT using an INNER JOIN on intent will drop
receiver rows whose intent_id has no matching intent; change the SELECT to use a
LEFT JOIN (or LEFT OUTER JOIN) and preserve the original receiver.intent_id
(e.g., SELECT r.pubkey, r.onchain_address, r.amount, r.intent_id AS intent_id)
or use COALESCE(i.id, r.intent_id) so unmatched receivers are copied into
receiver_new instead of being lost; update the SQL string referenced by copyData
accordingly.
- Around line 267-279: The migration SQL in copyData uses an INNER JOIN between
vtxo and intent, which drops vtxo rows with NULL or missing intent_id; change
the SELECT to use a LEFT JOIN (FROM vtxo AS v LEFT JOIN intent AS i ON i.id =
v.intent_id) and select i.id AS intent_id so orphaned vtxos preserve NULL
intent_id into vtxo_new, and add a post-copy validation (similar to swapIntent
count check) comparing row counts between vtxo and vtxo_new to detect unexpected
losses.
In `@internal/infrastructure/db/sqlite/sqlc/queries/query.sql.go`:
- Around line 350-365: The SQLite variant SelectIntentByTxid is using
sql.NullString for txid while Postgres uses string, causing an inconsistent API;
update the Queries.SelectIntentByTxid signature to accept a plain string (same
as Postgres), inside the function convert that string to sql.NullString (e.g.,
set Valid=false when empty) before calling q.db.QueryRowContext with
selectIntentByTxid, and keep SelectIntentByTxidRow and returned types unchanged
so callers see a unified method signature across backends; alternatively, if you
prefer nullable behavior, wrap this conversion in the repository layer so the
public API remains string-based and backend-specific null handling is internal.
🧹 Nitpick comments (9)
api-spec/protobuf/ark/v1/service.proto (1)
285-289: Inconsistent indentation in oneof block.The
string txidfield has extra leading spaces compared to other similar definitions in this file. Additionally, usingoneofwith a single field is unconventional but provides extensibility if you plan to add more filter options (e.g., by intent ID) in the future.Suggested fix for formatting
message GetIntentRequest { oneof filter { - string txid = 1; - } + string txid = 1; + } }internal/core/application/service.go (1)
4099-4111: Consider distinguishing "not found" from internal errors.The method wraps all repository errors as
INTERNAL_ERROR, but a "not found" case is semantically different from an internal failure. API consumers may need to distinguish between "intent doesn't exist" vs "something went wrong internally."♻️ Suggested improvement
func (s *service) GetIntentByTxid( ctx context.Context, txid string, ) (domain.Intent, errors.Error) { intent, err := s.repoManager.Rounds().GetIntentByTxid(ctx, txid) if err != nil { + if strings.Contains(err.Error(), "not found") { + return domain.Intent{}, errors.TX_NOT_FOUND.New( + "intent with txid %s not found", txid, + ) + } return domain.Intent{}, errors.INTERNAL_ERROR.New( "failed to get intent by txid %s: %w", txid, err, ) } return intent, nil }internal/infrastructure/db/badger/ark_repo.go (1)
256-269: Use structured logging instead of fmt.Printf.The error is logged using
fmt.Printfwhich bypasses the application's logging infrastructure. This makes it harder to correlate errors and filter logs in production.♻️ Suggested fix
+import log "github.com/sirupsen/logrus" + // derive txids from intent proofs and add to each intents for k, v := range round.Intents { if v.Txid != "" { continue } txid, err := application.DeriveTxidFromProof(v.Proof) if err != nil { - fmt.Printf("error deriving txid from proof: %s\n", err.Error()) + log.WithError(err).Warnf("failed to derive txid from proof for intent %s", k) continue } updatedIntent := v updatedIntent.Txid = txid round.Intents[k] = updatedIntent }internal/infrastructure/db/sqlite/round_repo.go (2)
167-178: Redundant txid derivation whenintent.Txidmay already be populated.The
Intentstruct now has aTxidfield that's populated duringNewIntent(). Here,application.DeriveTxidFromProofis called again to derive the txid, even thoughintent.Txidmay already contain this value.Additionally, there's code duplication between
domain.deriveTxidFromProofandapplication.DeriveTxidFromProof.Proposed fix: Use the existing intent.Txid field
for _, intent := range round.Intents { - txid, err := application.DeriveTxidFromProof(intent.Proof) - if err != nil { - return fmt.Errorf("failed to derive txid from proof: %w", err) + txid := intent.Txid + if txid == "" { + // Fallback for legacy intents without pre-populated Txid + var err error + txid, err = application.DeriveTxidFromProof(intent.Proof) + if err != nil { + return fmt.Errorf("failed to derive txid from proof: %w", err) + } } if err := querierWithTx.UpsertIntent( ctx, queries.UpsertIntentParams{ ID: sql.NullString{String: intent.Id, Valid: true}, RoundID: sql.NullString{String: round.Id, Valid: true}, Proof: sql.NullString{String: intent.Proof, Valid: true}, Message: sql.NullString{String: intent.Message, Valid: true}, Txid: sql.NullString{String: txid, Valid: true}, },
462-475: ReturnedIntentis only partially populated.The method returns a
domain.Intentwith onlyProofandMessagefields populated. TheId,Txid,Inputs, andReceiversfields are left as zero values. While this may suffice for the current API use case, returning partially populated domain objects can lead to subtle bugs if callers assume full initialization.Consider either:
- Populating all available fields from the query result, or
- Returning a dedicated DTO instead of the domain object
api-spec/openapi/swagger/ark/v1/service.openapi.json (1)
371-409: Missing operation description andtxidparameter should be required.The new
/v1/intentendpoint lacks adescriptionfield, unlike other operations in the spec. Additionally, thetxidquery parameter is not marked as required. If notxidis provided, the gRPC handler will returnInvalidArgumentwith "unknown intent filter provided", which may be confusing to API consumers.Suggested improvements
"/v1/intent": { "get": { "tags": [ "ArkService" ], + "description": "GetIntent retrieves an intent by its transaction ID.", "operationId": "ArkService_GetIntent", "parameters": [ { "name": "txid", "in": "query", + "required": true, "schema": { "type": "string" } } ],internal/infrastructure/db/postgres/round_repo.go (1)
431-444: Incomplete domain.Intent population in GetIntentByTxid.The returned
domain.Intentonly populatesProofandMessagefields, omittingId,Inputs,Receivers, andTxid. If callers need the full intent data, this will cause issues.Verify whether this minimal return is intentional for the use case (e.g., just returning the proof for verification) or if additional fields should be populated.
♻️ Suggested fix to include all available fields
func (r *roundRepository) GetIntentByTxid( ctx context.Context, txid string, ) (domain.Intent, error) { intent, err := r.querier.SelectIntentByTxid(ctx, txid) if err != nil { return domain.Intent{}, fmt.Errorf("failed to get intents by txid: %w", err) } return domain.Intent{ + Txid: txid, Proof: intent.Proof.String, Message: intent.Message.String, }, nil }internal/infrastructure/db/sqlite/intent_txid_migration.go (1)
134-140: Duplicate deriveTxidFromProof implementation.This function is duplicated in both SQLite and PostgreSQL migration files. Consider extracting it to a shared utility (e.g.,
application.DeriveTxidFromProofwhich already exists per the context).♻️ Suggested refactor to use existing utility
+import "github.com/arkade-os/arkd/internal/core/application" + -func deriveTxidFromProof(proof string) (string, error) { - tx, err := psbt.NewFromRawBytes(strings.NewReader(proof), true) - if err != nil { - return "", fmt.Errorf("psbt parse: %w", err) - } - return tx.UnsignedTx.TxID(), nil -} +// Use application.DeriveTxidFromProof insteadThen replace calls to
deriveTxidFromProof(proof)withapplication.DeriveTxidFromProof(proof).internal/infrastructure/db/postgres/intent_txid_migration.go (1)
137-143: Duplicate deriveTxidFromProof - same as SQLite migration.This is the third copy of
deriveTxidFromProof. The utility already exists ininternal/core/application/utils.goasDeriveTxidFromProof. Consider using that instead.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (4)
api-spec/protobuf/gen/ark/v1/indexer.pb.rgw.gois excluded by!**/gen/**api-spec/protobuf/gen/ark/v1/service.pb.gois excluded by!**/*.pb.go,!**/gen/**api-spec/protobuf/gen/ark/v1/service.pb.rgw.gois excluded by!**/gen/**api-spec/protobuf/gen/ark/v1/service_grpc.pb.gois excluded by!**/*.pb.go,!**/gen/**
📒 Files selected for processing (31)
api-spec/openapi/swagger/ark/v1/service.openapi.jsonapi-spec/protobuf/ark/v1/service.protointernal/core/application/service.gointernal/core/application/types.gointernal/core/application/utils.gointernal/core/domain/intent.gointernal/core/domain/intent_test.gointernal/core/domain/round.gointernal/core/domain/round_repo.gointernal/core/domain/round_test.gointernal/infrastructure/db/badger/ark_repo.gointernal/infrastructure/db/badger/intent_fees_repo.gointernal/infrastructure/db/postgres/intent_txid_migration.gointernal/infrastructure/db/postgres/migration/20260114000000_add_intent_txid.down.sqlinternal/infrastructure/db/postgres/migration/20260114000000_add_intent_txid.up.sqlinternal/infrastructure/db/postgres/round_repo.gointernal/infrastructure/db/postgres/sqlc/queries/models.gointernal/infrastructure/db/postgres/sqlc/queries/query.sql.gointernal/infrastructure/db/postgres/sqlc/query.sqlinternal/infrastructure/db/service.gointernal/infrastructure/db/service_test.gointernal/infrastructure/db/sqlite/intent_txid_migration.gointernal/infrastructure/db/sqlite/migration/20260114000000_add_intent_txid.down.sqlinternal/infrastructure/db/sqlite/migration/20260114000000_add_intent_txid.up.sqlinternal/infrastructure/db/sqlite/round_repo.gointernal/infrastructure/db/sqlite/sqlc/queries/models.gointernal/infrastructure/db/sqlite/sqlc/queries/query.sql.gointernal/infrastructure/db/sqlite/sqlc/query.sqlinternal/interface/grpc/handlers/arkservice.gointernal/interface/grpc/permissions/permissions.gopkg/errors/errors.go
💤 Files with no reviewable changes (1)
- internal/infrastructure/db/badger/intent_fees_repo.go
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-29T14:33:52.871Z
Learnt from: louisinger
Repo: arkade-os/arkd PR: 722
File: pkg/ark-lib/intent/proof.go:52-58
Timestamp: 2025-09-29T14:33:52.871Z
Learning: In btcsuite/btcd's psbt package, the NewFromRawBytes function's boolean parameter (b64) automatically handles base64 decoding when set to true, so passing a base64 string via strings.NewReader with b64=true is the correct usage pattern.
Applied to files:
internal/core/domain/intent.go
📚 Learning: 2025-09-29T14:33:52.871Z
Learnt from: louisinger
Repo: arkade-os/arkd PR: 722
File: pkg/ark-lib/intent/proof.go:52-58
Timestamp: 2025-09-29T14:33:52.871Z
Learning: In btcsuite/btcd's psbt package, the NewFromRawBytes function's boolean parameter (b64) automatically handles base64 decoding when set to true, so passing a base64 string via strings.NewReader with b64=true is the correct usage pattern. A common bug is manually base64-decoding the string and then passing b64=true, which causes a double-decode error.
Applied to files:
internal/core/domain/intent.go
🧬 Code graph analysis (14)
internal/core/domain/round_repo.go (3)
internal/core/domain/intent.go (1)
Intent(11-18)internal/infrastructure/db/postgres/sqlc/queries/models.go (1)
Intent(33-39)internal/infrastructure/db/sqlite/sqlc/queries/models.go (1)
Intent(31-37)
internal/core/domain/round.go (1)
pkg/ark-lib/intent/proof.go (1)
Proof(39-41)
internal/interface/grpc/permissions/permissions.go (1)
api-spec/protobuf/gen/ark/v1/service_grpc.pb.go (1)
ArkService_ServiceDesc(650-716)
internal/infrastructure/db/service_test.go (2)
pkg/ark-lib/intent/proof.go (1)
Proof(39-41)internal/core/application/utils.go (1)
DeriveTxidFromProof(468-474)
internal/core/application/types.go (4)
internal/core/domain/intent.go (1)
Intent(11-18)internal/infrastructure/db/postgres/sqlc/queries/models.go (1)
Intent(33-39)internal/infrastructure/db/sqlite/sqlc/queries/models.go (1)
Intent(31-37)pkg/errors/errors.go (1)
Error(39-46)
internal/core/domain/intent.go (3)
internal/infrastructure/db/postgres/sqlc/queries/models.go (2)
Vtxo(197-213)Intent(33-39)internal/infrastructure/db/sqlite/sqlc/queries/models.go (2)
Vtxo(184-200)Intent(31-37)pkg/ark-lib/intent/proof.go (1)
Proof(39-41)
internal/infrastructure/db/badger/ark_repo.go (3)
internal/core/domain/intent.go (2)
Intents(106-106)Intent(11-18)internal/core/application/utils.go (1)
DeriveTxidFromProof(468-474)pkg/ark-lib/intent/proof.go (1)
Proof(39-41)
internal/infrastructure/db/sqlite/intent_txid_migration.go (1)
internal/infrastructure/db/postgres/intent_txid_migration.go (1)
BackfillIntentTxid(15-53)
internal/infrastructure/db/postgres/intent_txid_migration.go (1)
internal/infrastructure/db/sqlite/intent_txid_migration.go (1)
BackfillIntentTxid(13-50)
internal/infrastructure/db/service.go (2)
internal/infrastructure/db/postgres/intent_txid_migration.go (1)
BackfillIntentTxid(15-53)internal/infrastructure/db/sqlite/intent_txid_migration.go (1)
BackfillIntentTxid(13-50)
internal/infrastructure/db/postgres/round_repo.go (5)
internal/core/application/utils.go (1)
DeriveTxidFromProof(468-474)internal/infrastructure/db/postgres/sqlc/queries/query.sql.go (1)
UpsertIntentParams(1737-1743)internal/core/domain/intent.go (1)
Intent(11-18)internal/infrastructure/db/postgres/sqlc/queries/models.go (1)
Intent(33-39)internal/infrastructure/db/sqlite/sqlc/queries/models.go (1)
Intent(31-37)
internal/infrastructure/db/sqlite/sqlc/queries/query.sql.go (2)
pkg/ark-lib/intent/proof.go (1)
Proof(39-41)internal/infrastructure/db/postgres/sqlc/queries/query.sql.go (1)
SelectIntentByTxidRow(357-360)
internal/infrastructure/db/sqlite/round_repo.go (4)
internal/core/application/utils.go (1)
DeriveTxidFromProof(468-474)internal/infrastructure/db/sqlite/sqlc/queries/query.sql.go (1)
UpsertIntentParams(1801-1807)internal/core/domain/intent.go (1)
Intent(11-18)internal/infrastructure/db/sqlite/sqlc/queries/models.go (1)
Intent(31-37)
internal/infrastructure/db/postgres/sqlc/queries/query.sql.go (4)
pkg/ark-lib/intent/proof.go (1)
Proof(39-41)internal/infrastructure/db/postgres/sqlc/queries/db.go (1)
Queries(23-25)internal/infrastructure/db/sqlite/sqlc/queries/db.go (1)
Queries(23-25)internal/infrastructure/db/sqlite/sqlc/queries/query.sql.go (1)
SelectIntentByTxidRow(355-358)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: unit tests
- GitHub Check: integration tests
🔇 Additional comments (30)
internal/infrastructure/db/postgres/migration/20260114000000_add_intent_txid.down.sql (1)
1-2: LGTM!The down migration correctly reverses the up migration by dropping the index first (with safe
IF EXISTS), then removing the column.internal/core/domain/round_repo.go (1)
27-27: LGTM!The new
GetIntentByTxidmethod appropriately extends the repository interface to support the new lookup capability. The signature aligns with the domain model whereIntentnow includes aTxidfield.pkg/errors/errors.go (1)
336-337: LGTM!The new
INTENT_NOT_FOUNDerror code follows established patterns, uses the appropriategrpccodes.NotFoundfor the gRPC mapping, and maintains sequential code numbering.internal/infrastructure/db/postgres/sqlc/query.sql (2)
32-38: LGTM!The
UpsertIntentquery correctly includestxidin both the INSERT values and the ON CONFLICT update clause, ensuring the transaction ID is persisted and updated appropriately.
418-420: The lightweight design returning onlyproofandmessageis intentional and sufficient.Verification confirms that
GetIntentByTxidis used exclusively by the gRPC handler to return anIntentresponse containing only these two fields. The otherIntentstruct fields (Id, Inputs, Receivers) are not needed for this lookup operation. No callers attempt to access these fields from the result, confirming the design is appropriate for its use case.internal/infrastructure/db/postgres/migration/20260114000000_add_intent_txid.up.sql (1)
1-6: The explicit index on line 6 is redundant since theUNIQUEconstraint already creates a unique index in PostgreSQL.However, the primary concern in the original comment about adding a NOT NULL column without a DEFAULT is addressed by the accompanying application-level migration handler (
internal/infrastructure/db/postgres/intent_txid_migration.go), which:
- Creates a new table with the txid column
- Backfills existing intents by deriving txid values from their proof data
- Swaps the old and new tables
This migration strategy safely handles existing data, making the SQL file safe to execute as part of the full migration flow.
internal/infrastructure/db/sqlite/sqlc/query.sql (2)
32-38: LGTM!The UpsertIntent statement correctly includes
txidin both the INSERT and ON CONFLICT clauses, ensuring the transaction ID is persisted and updated on conflict.
420-424: LGTM!The new
SelectIntentByTxidquery correctly retrieves the proof and message for a given transaction ID, which aligns with the GetIntent API requirements.internal/core/application/types.go (1)
60-64: LGTM!The new
GetIntentByTxidmethod follows the established interface patterns, using the customerrors.Errorreturn type and returning the domain entity.api-spec/protobuf/ark/v1/service.proto (1)
152-157: LGTM!The new
GetIntentRPC is well-defined with an appropriate HTTP GET mapping. The endpoint aligns with the service's RESTful API patterns.internal/infrastructure/db/postgres/sqlc/queries/models.go (1)
33-39: Type difference is properly abstracted in the repository layer.The
Txidfield is indeedstring(non-nullable) in Postgres andsql.NullString(nullable) in SQLite, but this difference is correctly handled. BothGetIntentByTxidimplementations expose the same interface (txid string), and the SQLite implementation properly wraps the value insql.NullString{String: txid, Valid: true}when calling the generated querier. No action needed.internal/infrastructure/db/sqlite/migration/20260114000000_add_intent_txid.up.sql (1)
1-6: Fix comment typos; SQL migration is incomplete by design due to application-level backfill.The comment contains typos ("make int unique and and not null" should be "make it unique and not null"), which should be corrected. However, the missing constraints are intentional: this SQL migration file is step one of a two-phase strategy. The application code in
BackfillIntentTxid()creates a newintenttable withtxid TEXT UNIQUE NOT NULLconstraints, backfills all existing intents with derived txids from their proofs, and swaps the old and new tables. This pattern avoids SQLite's limitation on adding NOT NULL constraints to existing columns without defaults.The current SQL migration is correct as-is; only fix the comment typos for clarity.
Likely an incorrect or invalid review comment.
internal/core/domain/intent_test.go (1)
14-14: LGTM!The proof constant is correctly updated to a valid base64-encoded PSBT string, which is required for the new
deriveTxidFromProoffunctionality that extracts transaction IDs from PSBT proofs during intent creation.internal/interface/grpc/permissions/permissions.go (1)
143-146: LGTM!The
GetIntentendpoint is correctly added to the whitelist withEntityArkand"read"action, consistent with other read-only Ark service endpoints likeGetInfo,GetPendingTx, andEstimateIntentFee.internal/infrastructure/db/sqlite/sqlc/queries/models.go (1)
31-37: LGTM!The
Txidfield addition to theIntentstruct is correctly generated by sqlc, usingsql.NullStringto handle the nullable column appropriately for backward compatibility with existing intents.internal/core/domain/round_test.go (1)
12-76: LGTM!The test fixtures are correctly updated with valid base64-encoded PSBT strings for the
Prooffields. Using distinct proof strings for each intent (Id "0" and Id "1") ensures proper test coverage for the newderiveTxidFromProoffunctionality.internal/core/application/utils.go (1)
467-474: LGTM!The function is a clean utility that correctly parses a PSBT proof and extracts the transaction ID. Error handling appropriately wraps the underlying parse error with context.
internal/infrastructure/db/service_test.go (2)
41-42: LGTM!The test data uses valid PSBT strings that can be parsed to derive transaction IDs, enabling proper testing of the
GetIntentByTxidfunctionality.
508-521: LGTM!Good test coverage for the new
GetIntentByTxidfunctionality. The tests properly verify that:
- Transaction IDs can be derived from proofs
- Intents can be retrieved by their derived txid
- The retrieved intent contains the expected Proof and Message values
internal/infrastructure/db/service.go (1)
306-315: LGTM!The stepwise migration logic for SQLite is well-structured: it checks if the current version is below the intent txid migration threshold, runs migrations up to that point, performs the backfill, and then continues with any remaining migrations. Error handling is comprehensive.
internal/core/domain/intent.go (2)
75-77: LGTM!The validation for a non-empty
Txidis appropriate. SinceTxidis derived from the proof, validating it alongside the other core fields ensures data integrity.
133-139: LGTM!The
deriveTxidFromProoffunction correctly usespsbt.NewFromRawByteswithb64=truefor base64-encoded PSBT parsing. Based on learnings, this is the correct usage pattern for btcsuite's psbt package.internal/interface/grpc/handlers/arkservice.go (1)
593-614: LGTM!The
GetIntenthandler is well-implemented:
- Uses a type switch for extensibility when adding more filter types
- Returns appropriate
InvalidArgumentstatus for unknown filters- Correctly maps the domain
Intentto the protobuf responseapi-spec/openapi/swagger/ark/v1/service.openapi.json (1)
853-870: LGTM!The
GetIntentRequestandGetIntentResponseschemas are properly defined and consistent with the existing schema patterns in the specification.internal/infrastructure/db/postgres/round_repo.go (1)
169-180: LGTM - Txid derivation from proof during intent upsert.The logic correctly derives the txid from the intent's proof using
application.DeriveTxidFromProofand passes it to the upsert operation. Error handling is appropriate.internal/infrastructure/db/sqlite/intent_txid_migration.go (1)
75-82: SQL placeholders use?which is correct for SQLite.The prepared statement syntax with
?placeholders is appropriate for SQLite. This differs from the PostgreSQL version which should use$1, $2...placeholders.internal/infrastructure/db/postgres/sqlc/queries/query.sql.go (2)
352-367: LGTM - SQLC-generated query for SelectIntentByTxid.The generated code correctly implements the query to fetch proof and message by txid. The parameter type
string(non-nullable) is consistent with the Postgres model whereTxidis a plain string.
1729-1751: LGTM - UpsertIntent updated to include txid.The generated code correctly adds the
Txidfield toUpsertIntentParamsand passes it to the SQL executor. The SQL includestxidin both INSERT and ON CONFLICT DO UPDATE SET clauses.internal/infrastructure/db/sqlite/sqlc/queries/query.sql.go (1)
1793-1815: LGTM - UpsertIntent updated for SQLite with txid.The generated code correctly adds the
Txidfield. Note thatTxidissql.NullStringhere (matching SQLite's nullable model), which differs from Postgres's non-nullablestring.internal/infrastructure/db/postgres/intent_txid_migration.go (1)
33-35: Inconsistent context usage.Same issue as SQLite migration - uses
context.Background()instead of the passedctx.🐛 Proposed fix
- if err := backfillIntent(context.Background(), dbh); err != nil { + if err := backfillIntent(ctx, dbh); err != nil { return fmt.Errorf("failed to backfill txids: %s", err) }⛔ Skipped due to learnings
Learnt from: louisinger Repo: arkade-os/arkd PR: 686 File: internal/core/application/fraud.go:47-61 Timestamp: 2025-08-28T08:21:01.170Z Learning: In reactToFraud function in internal/core/application/fraud.go, the goroutine that waits for confirmation and schedules checkpoint sweep should use context.Background() instead of the request context, as this is intentional design to decouple the checkpoint sweep scheduling from the request lifetime.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
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.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@internal/infrastructure/db/postgres/intent_txid_migration.go`:
- Around line 30-33: The call to backfillIntent uses context.Background() which
discards the passed ctx and any cancellation/deadline; change the call to pass
the existing ctx (i.e., backfillIntent(ctx, dbh)) and ensure the surrounding
function signature provides that ctx into this call so cancellation/timeout is
respected by backfillIntent and any callers.
♻️ Duplicate comments (5)
internal/infrastructure/db/postgres/intent_txid_migration.go (4)
72-135: LGTM! Previous placeholder issue has been addressed.The function now correctly uses PostgreSQL positional placeholders (
$1, $2, $3, $4, $5) and properly handles transaction lifecycle, prepared statements, and row iteration errors.
145-232: LGTM! Previous PRAGMA issues have been addressed.The function now uses PostgreSQL-compatible
ALTER TABLE DROP CONSTRAINTstatements instead of SQLite PRAGMA, properly handles dependent views, and validates row counts before the swap.
234-284: LGTM! Previous PRAGMA issues have been addressed.The function uses PostgreSQL-compatible DDL without PRAGMA statements and correctly uses
LEFT JOINto preserve receiver records.
307-316: LEFT JOIN preserves vtxos with missing intents - verify this is intentional.The query uses
LEFT JOIN intent AS i ON i.id = v.intent_idand selectsi.id AS intent_id. This means vtxos whoseintent_idreferences a non-existent intent will have theirintent_idset to NULL in the new table. This addresses the data loss concern from previous reviews, but verify this orphan cleanup behavior is desired.internal/infrastructure/db/sqlite/sqlc/queries/query.sql.go (1)
351-366: Parameter type inconsistency between SQLite and PostgreSQL backends.The SQLite
SelectIntentByTxidacceptssql.NullStringwhile the PostgreSQL version acceptsstring. This creates an API inconsistency that the repository layer must abstract. Ensure the calling code (e.g.,round_repo.go) handles this difference appropriately.
🧹 Nitpick comments (3)
internal/infrastructure/db/service_test.go (1)
508-521: Consider adding a negative test case for non-existent txid.The test correctly validates successful retrieval for both intents. Consider adding a test case for a non-existent txid to verify proper error handling.
💡 Optional: Add negative test case
// Test non-existent txid _, err = svc.Rounds().GetIntentByTxid(ctx, "nonexistent_txid_0000000000000000") require.Error(t, err)internal/infrastructure/db/badger/ark_repo.go (1)
262-275: Consider using structured logging instead of fmt.Printf.The error is logged using
fmt.Printf, which won't integrate with the application's logging infrastructure. Consider using a logger if available, or returning/accumulating errors for visibility.♻️ Suggested improvement
If a logger is available in the repository context, use it instead:
- fmt.Printf("error deriving txid from proof: %s\n", err.Error()) + // Consider using structured logging or returning errors + // log.Warnf("error deriving txid from proof: %v", err)Alternatively, if silent failure is acceptable during migration, consider at minimum using
log.Printffrom the standard library for consistent output formatting.internal/infrastructure/db/postgres/intent_txid_migration.go (1)
349-357: Consider using parameterized query to avoid potential SQL injection.The function uses
fmt.Sprintfto interpolatetableNameandcolumnNamedirectly into the SQL string. While currently called with hardcoded values, this pattern is risky if reused. PostgreSQL'sinformation_schemadoesn't support parameterized identifiers directly, but consider adding input validation or documenting this limitation.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
internal/core/application/utils.gointernal/infrastructure/db/badger/ark_repo.gointernal/infrastructure/db/postgres/intent_txid_migration.gointernal/infrastructure/db/postgres/migration/20260114000000_add_intent_txid.up.sqlinternal/infrastructure/db/postgres/sqlc/queries/models.gointernal/infrastructure/db/postgres/sqlc/queries/query.sql.gointernal/infrastructure/db/postgres/sqlc/query.sqlinternal/infrastructure/db/service.gointernal/infrastructure/db/service_test.gointernal/infrastructure/db/sqlite/intent_txid_migration.gointernal/infrastructure/db/sqlite/sqlc/queries/models.gointernal/infrastructure/db/sqlite/sqlc/queries/query.sql.gointernal/infrastructure/db/sqlite/sqlc/query.sql
🚧 Files skipped from review as they are similar to previous changes (5)
- internal/infrastructure/db/postgres/sqlc/queries/models.go
- internal/core/application/utils.go
- internal/infrastructure/db/sqlite/intent_txid_migration.go
- internal/infrastructure/db/service.go
- internal/infrastructure/db/postgres/migration/20260114000000_add_intent_txid.up.sql
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-28T08:21:01.170Z
Learnt from: louisinger
Repo: arkade-os/arkd PR: 686
File: internal/core/application/fraud.go:47-61
Timestamp: 2025-08-28T08:21:01.170Z
Learning: In reactToFraud function in internal/core/application/fraud.go, the goroutine that waits for confirmation and schedules checkpoint sweep should use context.Background() instead of the request context, as this is intentional design to decouple the checkpoint sweep scheduling from the request lifetime.
Applied to files:
internal/infrastructure/db/postgres/intent_txid_migration.go
🧬 Code graph analysis (4)
internal/infrastructure/db/sqlite/sqlc/queries/query.sql.go (3)
pkg/ark-lib/intent/proof.go (1)
Proof(39-41)internal/infrastructure/db/sqlite/sqlc/queries/db.go (1)
Queries(23-25)internal/infrastructure/db/postgres/sqlc/queries/query.sql.go (1)
SelectIntentByTxidRow(358-361)
internal/infrastructure/db/postgres/intent_txid_migration.go (1)
internal/infrastructure/db/sqlite/intent_txid_migration.go (1)
BackfillIntentTxid(13-50)
internal/infrastructure/db/service_test.go (2)
pkg/ark-lib/intent/proof.go (1)
Proof(39-41)internal/core/application/utils.go (1)
DeriveTxidFromProof(468-474)
internal/infrastructure/db/badger/ark_repo.go (5)
internal/core/domain/intent.go (2)
Intents(106-106)Intent(11-18)internal/core/application/utils.go (1)
DeriveTxidFromProof(468-474)pkg/ark-lib/intent/proof.go (1)
Proof(39-41)internal/infrastructure/db/postgres/sqlc/queries/models.go (1)
Intent(33-39)internal/infrastructure/db/sqlite/sqlc/queries/models.go (1)
Intent(31-37)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: integration tests
- GitHub Check: unit tests
🔇 Additional comments (16)
internal/infrastructure/db/service_test.go (4)
15-15: LGTM!The import of the
applicationpackage is necessary to accessDeriveTxidFromProoffor deriving transaction IDs from proofs in the test.
41-42: LGTM!The proof constants are valid base64-encoded PSBTs that will produce distinct transaction IDs when decoded, enabling proper testing of the
GetIntentByTxidfunctionality.
436-437: LGTM!Using the defined
proof1constant ensures the intent has a valid PSBT proof from which a txid can be derived for the subsequentGetIntentByTxidtest.
456-457: LGTM!Using
proof2for the second intent ensures distinct txids for each intent, enabling comprehensive testing of the lookup functionality.internal/infrastructure/db/sqlite/sqlc/query.sql (2)
33-38: LGTM!The
UpsertIntentstatement correctly includestxidin both the INSERT and the ON CONFLICT UPDATE clauses, ensuring the transaction ID is properly persisted and updated.
427-429: Index onintent.txidalready exists. The indexidx_intent_txidwas created in migration20260114000000_add_intent_txid.up.sqlto optimize lookups on this column. No action needed.Likely an incorrect or invalid review comment.
internal/infrastructure/db/badger/ark_repo.go (3)
28-32: LGTM!The
IntentIndexstruct provides an efficient secondary index mapping txid to round and intent IDs, enabling O(1) lookups instead of scanning all rounds.
561-580: LGTM - Addresses the performance concern from previous review.This implementation uses the
IntentIndexfor O(1) lookup by txid, then fetches the round and iterates only through its intents. This is much more efficient than the previous approach of scanning all rounds.
582-613: No collision risk with BadgerHold's type-aware storage.BadgerHold (timshannon/badgerhold) stores type information alongside values, allowing the same key to safely store different types. Since
TxandIntentIndexare distinct types, they can coexist with the same txid key without collision. Retrieval operations are type-specific (e.g.,r.store.Get(txid, &idx)specifies the target type), ensuring correct type handling.Likely an incorrect or invalid review comment.
internal/infrastructure/db/postgres/sqlc/queries/query.sql.go (2)
353-368: LGTM - Generated code correctly implements SelectIntentByTxid.The query and function are correctly generated to fetch intent proof and message by txid. The return type uses
sql.NullStringappropriately for nullable columns.
1756-1782: No changes needed — txid handling is consistent across backends.The typing difference (
stringvssql.NullString) is intentional and correct. SQLite's generated code wraps all parameters insql.NullStringper its driver requirements, while PostgreSQL uses appropriate Go types. Both implementations handle txid derivation identically: they callDeriveTxidFromProof(), immediately check for errors, and only pass a non-empty txid toUpsertIntentby returning early on failure. Empty txid values are not a concern here.internal/infrastructure/db/postgres/sqlc/query.sql (2)
33-38: LGTM!The
UpsertIntentstatement correctly includestxidin both INSERT and ON CONFLICT UPDATE clauses, consistent with the SQLite implementation.
424-426: An indexidx_intent_txidalready exists on theintent.txidcolumn, created specifically for this purpose in migration20260114000000_add_intent_txid.up.sql. The query already benefits from efficient lookups.Likely an incorrect or invalid review comment.
internal/infrastructure/db/postgres/intent_txid_migration.go (1)
53-70: LGTM!The
ensureIntentNewfunction correctly creates the new table with PostgreSQL-compatible syntax and appropriate column definitions.internal/infrastructure/db/sqlite/sqlc/queries/models.go (1)
31-37: LGTM!The
Txidfield addition to theIntentstruct is consistent with the schema migration adding the txid column. This is a generated file matching the updated schema.internal/infrastructure/db/sqlite/sqlc/queries/query.sql.go (1)
1823-1849: LGTM!The
UpsertIntentquery and params struct correctly include the newtxidfield, with proper INSERT and ON CONFLICT UPDATE handling.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
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.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@internal/infrastructure/db/badger/ark_repo.go`:
- Around line 316-323: The call to r.upsertIntentIndex(ctx, it.Txid, rnd.Id,
it.Id) in the loop over rnd.Intents returns an error that is currently ignored;
update the loop to explicitly handle the returned error by capturing it and
either discarding with _ = r.upsertIntentIndex(...) or, preferably, logging the
error for observability (e.g., err := r.upsertIntentIndex(...); if err != nil {
r.logger.Warnf("upsertIntentIndex failed txid=%s rnd=%s intent=%s: %v", it.Txid,
rnd.Id, it.Id, err) } ), keeping the existing behavior of not failing the whole
round.
In `@internal/infrastructure/db/postgres/intent_txid_migration.go`:
- Around line 53-70: The create statement in ensureIntentNew currently defines
txid as "txid TEXT" but must match SQLite by being "txid TEXT UNIQUE NOT NULL";
update the SQL in ensureIntentNew (the createIntentNew string) to declare txid
with UNIQUE NOT NULL, and if necessary adjust any upstream inserts or migration
logic to handle existing NULL/duplicate txid rows before applying the constraint
to avoid migration failures.
- Around line 234-252: fixReceiverTableFK defines receiver_new with intent_id
TEXT NOT NULL but copyData uses a LEFT JOIN that can bring orphan receiver rows
with NULL intent_id, causing the INSERT to fail; either make intent_id nullable
in the receiver_new CREATE statement to match the SQLite behavior (remove NOT
NULL on intent_id in the createNew constant) or change the copyData SELECT to
only include matched intents (use an INNER JOIN or add WHERE i.id IS NOT NULL)
so no NULL intent_id rows are inserted; update the constants createNew and/or
copyData in fixReceiverTableFK accordingly.
In `@internal/infrastructure/db/sqlite/intent_txid_migration.go`:
- Around line 171-185: The ALTER TABLE ... DROP CONSTRAINT statements using
tx.ExecContext are PostgreSQL-specific and not supported by SQLite; remove the
four EXECUTE calls that run `ALTER TABLE ... DROP CONSTRAINT IF EXISTS ...` (the
ones affecting receiver and vtxo) because you already disable foreign keys with
`PRAGMA foreign_keys = OFF` and the migration uses the table-recreation helpers;
if you need to remove or reapply constraints, rely on the existing
fixReceiverTableFK and fixVtxoTableFK functions (or the recreate-table pattern
they implement) instead of these unsupported DROP CONSTRAINT statements.
🧹 Nitpick comments (4)
internal/infrastructure/db/badger/ark_repo.go (2)
268-270: Consider using a proper logger instead offmt.Printf.Using
fmt.Printffor error logging writes to stdout and may interfere with structured logging. Consider using the logger pattern consistent with the rest of the codebase, or at minimumlog.Printfwhich writes to stderr.♻️ Suggested improvement
- fmt.Printf("error deriving txid from proof: %s\n", err.Error()) + // If a logger is available in the repository, use it: + // r.logger.Warnf("error deriving txid from proof: %s", err.Error()) + // Otherwise, at minimum use log package: + log.Printf("error deriving txid from proof: %s", err.Error())
560-579: Consider using pointer receiver for consistency.The method uses a value receiver (
r arkRepository) while other methods in this file use pointer receivers (r *arkRepository). For consistency and to avoid unnecessary copying, consider using a pointer receiver.♻️ Suggested change
-func (r arkRepository) GetIntentByTxid(ctx context.Context, txid string) (domain.Intent, error) { +func (r *arkRepository) GetIntentByTxid(ctx context.Context, txid string) (domain.Intent, error) {internal/infrastructure/db/postgres/intent_txid_migration.go (2)
137-143: Consider extracting sharedderiveTxidFromProofto a common utility.This function is duplicated identically in both SQLite and PostgreSQL migrations. The AI summary mentions
DeriveTxidFromProofexists ininternal/core/application/utils.go. Consider reusing that implementation to avoid duplication.
198-225: View column order differs between PostgreSQL and SQLite migrations.The
intent_with_receivers_vwview has different column ordering:
- PostgreSQL (line 210):
SELECT receiver.*, intent.*- SQLite (line 216):
SELECT intent.*, receiver.*While this may not cause functional issues if columns are accessed by name, it could cause problems if code relies on positional column access. Consider aligning the column order for consistency.
♻️ Proposed fix: Align column order with SQLite
if _, err = tx.ExecContext(ctx, ` CREATE VIEW intent_with_receivers_vw AS - SELECT receiver.*, intent.* + SELECT intent.*, receiver.* FROM intent LEFT OUTER JOIN receiver ON intent.id = receiver.intent_id; `); err != nil {
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
internal/infrastructure/db/badger/ark_repo.gointernal/infrastructure/db/postgres/intent_txid_migration.gointernal/infrastructure/db/sqlite/intent_txid_migration.go
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-28T08:21:01.170Z
Learnt from: louisinger
Repo: arkade-os/arkd PR: 686
File: internal/core/application/fraud.go:47-61
Timestamp: 2025-08-28T08:21:01.170Z
Learning: In reactToFraud function in internal/core/application/fraud.go, the goroutine that waits for confirmation and schedules checkpoint sweep should use context.Background() instead of the request context, as this is intentional design to decouple the checkpoint sweep scheduling from the request lifetime.
Applied to files:
internal/infrastructure/db/postgres/intent_txid_migration.gointernal/infrastructure/db/sqlite/intent_txid_migration.go
🧬 Code graph analysis (3)
internal/infrastructure/db/badger/ark_repo.go (4)
internal/core/domain/intent.go (2)
Intents(106-106)Intent(11-18)pkg/ark-lib/intent/proof.go (1)
Proof(39-41)internal/infrastructure/db/postgres/sqlc/queries/models.go (1)
Intent(33-39)internal/infrastructure/db/sqlite/sqlc/queries/models.go (1)
Intent(31-37)
internal/infrastructure/db/postgres/intent_txid_migration.go (1)
internal/infrastructure/db/sqlite/intent_txid_migration.go (1)
BackfillIntentTxid(13-50)
internal/infrastructure/db/sqlite/intent_txid_migration.go (1)
internal/infrastructure/db/postgres/intent_txid_migration.go (1)
BackfillIntentTxid(13-51)
🪛 GitHub Actions: ci_unit
internal/infrastructure/db/badger/ark_repo.go
[error] 322-322: Error return value of r.upsertIntentIndex is not checked (errcheck).
🪛 GitHub Check: unit tests
internal/infrastructure/db/badger/ark_repo.go
[failure] 322-322:
Error return value of r.upsertIntentIndex is not checked (errcheck)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Build and Scan
- GitHub Check: integration tests
🔇 Additional comments (17)
internal/infrastructure/db/badger/ark_repo.go (4)
10-10: LGTM!Import correctly added to support the
DeriveTxidFromProoffunction usage.
28-32: LGTM!The
IntentIndexstruct provides a clean secondary index structure to enable efficient intent lookups by txid, addressing the previous O(n) full table scan concern.
581-591: LGTM!The helper follows the established pattern for transactional/non-transactional upserts in this repository.
593-612: LGTM!Correct implementation with proper error handling for not-found cases.
internal/infrastructure/db/sqlite/intent_txid_migration.go (8)
1-11: LGTM!Package declaration and imports are appropriate for the SQLite migration functionality.
13-50: LGTM!The orchestration function correctly checks for existing migration, creates the new table, backfills data, swaps tables, and fixes foreign keys. Context is properly propagated throughout.
52-69: LGTM!The
intent_newtable schema is well-defined with appropriate constraints including theUNIQUE NOT NULLconstraint ontxid.
71-134: LGTM!The backfill logic correctly iterates through existing intents, derives txids from proofs, and inserts into the new table within a transaction. Good use of prepared statements and proper error handling with
rows.Err()check.
136-142: LGTM!Clean implementation of PSBT parsing to derive the transaction ID.
244-301: LGTM!The receiver table FK fix correctly uses SQLite's table recreation pattern with
PRAGMA foreign_keysand aLEFT JOINto preserve all receiver rows.
303-372: LGTM!The vtxo table FK fix correctly implements the table recreation pattern with
LEFT JOINto preserve all vtxo rows, including those with NULL intent_id.
374-380: LGTM!The
existsQueryfunction correctly uses SQLite'spragma_table_infoto check for column existence.internal/infrastructure/db/postgres/intent_txid_migration.go (5)
1-11: LGTM!Package declaration and imports are appropriate for the PostgreSQL migration functionality.
13-51: LGTM!The orchestration function correctly propagates context throughout all migration steps.
72-135: LGTM!The backfill logic correctly uses PostgreSQL positional placeholders (
$1, $2, $3, $4, $5) and properly handles transactions with error checking.
286-347: LGTM!The vtxo table FK fix correctly uses PostgreSQL DDL without PRAGMA statements and preserves all vtxo rows using
LEFT JOIN.
349-357: LGTM!The
existsQueryfunction correctly uses PostgreSQL'sinformation_schema.columnsto check for column existence.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
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.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@internal/infrastructure/db/badger/ark_repo.go`:
- Line 561: GetIntentByTxid currently uses a value receiver (`r arkRepository`)
while other methods use pointer receivers; change its receiver to a pointer (`r
*arkRepository`) so the method signature matches the rest of the type, update
any internal references if necessary, and run tests/compile to ensure no
interface or call-site mismatches arise.
In `@internal/infrastructure/db/postgres/intent_txid_migration.go`:
- Around line 307-316: The INSERT...SELECT in the copyData SQL uses "i.id AS
intent_id" which will null-out orphaned vtxo.intent_id values; update the SQL in
the copyData constant so the selected intent_id comes from the original row
("v.intent_id") instead of the joined "i.id" (keep the LEFT JOIN to preserve
intent metadata if needed but ensure the SELECT uses v.intent_id for the
intent_id column when inserting into vtxo_new).
♻️ Duplicate comments (3)
internal/infrastructure/db/badger/ark_repo.go (1)
316-324: Acknowledged:nolint:errcheckaddresses CI, but consider logging.The
nolint:errcheckdirective resolves the pipeline failure. For better observability, consider logging the error (as suggested in the previous review) rather than silently discarding it.internal/infrastructure/db/sqlite/intent_txid_migration.go (2)
171-177: SQLite does not supportALTER TABLE ... DROP CONSTRAINTsyntax.These statements use PostgreSQL-specific DDL that will fail on SQLite. SQLite's
ALTER TABLEonly supportsRENAME TABLE,RENAME COLUMN,ADD COLUMN, andDROP COLUMN. Since foreign keys are already disabled viaPRAGMA foreign_keys = OFF(line 156), these constraint-drop operations are redundant and should be removed.🐛 Proposed fix: Remove unsupported statements
if oldCT != newCT { return fmt.Errorf("backfill mismatch: intent=%d intent_new=%d", oldCT, newCT) } - // drop dependent foreign keys - if _, err = tx.ExecContext(ctx, `ALTER TABLE IF EXISTS receiver DROP CONSTRAINT IF EXISTS receiver_intent_id_fkey;`); err != nil { - return fmt.Errorf("drop receiver FK: %w", err) - } - if _, err = tx.ExecContext(ctx, `ALTER TABLE IF EXISTS vtxo DROP CONSTRAINT IF EXISTS vtxo_intent_id_fkey;`); err != nil { - return fmt.Errorf("drop vtxo FK: %w", err) - } - // drop views that depend on intent before dropping the intent table
316-325: Data corruption risk:i.id AS intent_idmay silently null-out orphaned vtxo references.The copyData query uses
i.id AS intent_idfrom the LEFT JOIN, which will be NULL if no matching intent exists. This differs fromfixReceiverTableFKwhich correctly usesr.intent_idto preserve original values. If any vtxo has an intent_id that doesn't exist in the intent table, it will be silently changed to NULL.🐛 Proposed fix: Use v.intent_id to preserve original values
const copyData = ` INSERT INTO vtxo_new ( txid, vout, pubkey, amount, expires_at, created_at, commitment_txid, spent_by, spent, unrolled, swept, preconfirmed, settled_by, ark_txid, intent_id ) SELECT v.txid, v.vout, v.pubkey, v.amount, v.expires_at, v.created_at, v.commitment_txid, v.spent_by, v.spent, v.unrolled, v.swept, v.preconfirmed, v.settled_by, v.ark_txid, - i.id AS intent_id - FROM vtxo AS v - LEFT JOIN intent AS i - ON i.id = v.intent_id;` + v.intent_id + FROM vtxo AS v;`
🧹 Nitpick comments (5)
internal/infrastructure/db/badger/ark_repo.go (2)
267-270: Replacefmt.Printfwith structured logging.Using
fmt.Printffor error logging bypasses the application's logging infrastructure, making it harder to correlate errors in production. Consider using a structured logger consistent with the rest of the codebase.♻️ Suggested approach
If a logger is available on the repository (or can be injected), replace:
- fmt.Printf("error deriving txid from proof: %s\n", err.Error()) + // Use structured logger, e.g.: + // log.Warnf("failed to derive txid from proof for intent %s: %v", v.Id, err)Alternatively, consider returning a multi-error or logging via a passed-in logger interface.
10-10: This dependency pattern is consistent across the codebase.Multiple infrastructure packages (postgres, sqlite, badger, and tests) already import
application.DeriveTxidFromProoffrominternal/core/application/utils.go. This appears to be an intentional architectural pattern rather than an isolated violation.If cleaner architectural separation is desired, consider moving
DeriveTxidFromProofto thedomainpackage as a utility function; however, the current design is established and consistent across all DB implementations.internal/infrastructure/db/sqlite/intent_txid_migration.go (2)
13-50: Orchestration logic is sound, but clean up the TODO-style comments.The function correctly checks for idempotency, propagates context, and sequences the migration steps properly. However, lines 40 and 44 contain uncertainty comments (
// do we even need since we keep the intent id unchanged?). If the FK fixes are needed, remove the comments; if they're not needed, remove the function calls.
52-69: Consider adding a UNIQUE constraint ontxidcolumn.If
txidwill be used for lookups (as suggested by the PR objective "get intent by txid"), adding aUNIQUEconstraint would improve query performance and prevent duplicate entries.♻️ Proposed schema change
createIntentNew := ` CREATE TABLE IF NOT EXISTS intent_new ( id TEXT PRIMARY KEY, round_id TEXT NOT NULL, proof TEXT NOT NULL, message TEXT NOT NULL, - txid TEXT, + txid TEXT UNIQUE, FOREIGN KEY (round_id) REFERENCES round(id) ); `internal/infrastructure/db/postgres/intent_txid_migration.go (1)
53-70: Schema is consistent with SQLite version.Same suggestion applies: consider adding
UNIQUEconstraint ontxidfor query performance.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
internal/infrastructure/db/badger/ark_repo.gointernal/infrastructure/db/postgres/intent_txid_migration.gointernal/infrastructure/db/sqlite/intent_txid_migration.go
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-28T08:21:01.170Z
Learnt from: louisinger
Repo: arkade-os/arkd PR: 686
File: internal/core/application/fraud.go:47-61
Timestamp: 2025-08-28T08:21:01.170Z
Learning: In reactToFraud function in internal/core/application/fraud.go, the goroutine that waits for confirmation and schedules checkpoint sweep should use context.Background() instead of the request context, as this is intentional design to decouple the checkpoint sweep scheduling from the request lifetime.
Applied to files:
internal/infrastructure/db/badger/ark_repo.gointernal/infrastructure/db/sqlite/intent_txid_migration.gointernal/infrastructure/db/postgres/intent_txid_migration.go
🧬 Code graph analysis (2)
internal/infrastructure/db/sqlite/intent_txid_migration.go (1)
internal/infrastructure/db/postgres/intent_txid_migration.go (1)
BackfillIntentTxid(13-51)
internal/infrastructure/db/postgres/intent_txid_migration.go (1)
internal/infrastructure/db/sqlite/intent_txid_migration.go (1)
BackfillIntentTxid(13-50)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: unit tests
- GitHub Check: integration tests
🔇 Additional comments (15)
internal/infrastructure/db/badger/ark_repo.go (2)
28-32: LGTM!The
IntentIndexstruct is well-designed for the secondary index pattern, enabling efficient lookup by txid without full table scans.
582-613: LGTM!The
upsertIntentIndexandgetIntentIndexByTxidhelper methods follow the established patterns in this file for transaction-aware persistence operations. Error handling forErrNotFoundis appropriate.internal/infrastructure/db/sqlite/intent_txid_migration.go (6)
1-11: Imports and package setup look correct.The imports appropriately include
github.com/btcsuite/btcd/btcutil/psbtfor PSBT parsing and logrus for debug logging. Usingstrings.NewReaderfor PSBT parsing is appropriate.
71-134: Well-structured backfill with proper transaction handling.Good use of prepared statements for batch inserts, proper transaction rollback on error, and iteration error checking with
rows.Err().
136-142: LGTM!Clean implementation for deriving txid from PSBT proof.
179-234: View handling and table swap logic is correct.The view drop/recreate pattern, row count validation, and FK pragma handling are appropriate for SQLite migrations.
236-293: Receiver table migration correctly preserves original intent_id values.Using
r.intent_idin the SELECT (rather thani.id) correctly preserves the original foreign key values during migration.
366-372: LGTM!Correctly uses SQLite's
pragma_table_infoto check for column existence.internal/infrastructure/db/postgres/intent_txid_migration.go (7)
1-11: Imports are appropriate for PostgreSQL migration.
13-51: Orchestration is correct; same cleanup suggestion as SQLite version.Context is properly propagated. Consider removing the uncertainty comments on lines 40 and 44.
72-135: PostgreSQL placeholder syntax is correct; backfill logic is sound.The
$1, $2...positional placeholders are appropriate for PostgreSQL.
137-143: LGTM!
145-232: PostgreSQL-appropriate table swap with proper constraint and view handling.The
ALTER TABLE ... DROP CONSTRAINT IF EXISTSsyntax is valid PostgreSQL DDL, and the view handling withCASCADEis appropriate.
234-284: Receiver table recreation is PostgreSQL-appropriate.The use of
BIGINTfor amount (vs SQLite'sINTEGER) and removal of PRAGMA statements are correct for PostgreSQL. Ther.intent_idselection preserves original values.
349-357: LGTM!Correctly uses PostgreSQL's
information_schema.columnsto check for column existence.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
| if err != nil { | ||
| return nil, 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.
can be moved outside the switch
internal/core/application/types.go
Outdated
| GetIntentByTxid( | ||
| ctx context.Context, | ||
| txid string, | ||
| ) (domain.Intent, errors.Error) |
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.
| ) (domain.Intent, errors.Error) | |
| ) (*domain.Intent, errors.Error) |
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.
Actionable comments posted: 6
🤖 Fix all issues with AI agents
In `@internal/core/domain/intent_test.go`:
- Line 31: The test is missing a declaration for txid used when calling
domain.NewIntent and elsewhere; add txid to the top var block in the test (same
block that contains other test fixtures) as a suitable test value (e.g., var
txid = "test-txid" or similar) so NewIntent(txid, proof, message, inputs) and
other uses compile; ensure the symbol name is exactly txid to match existing
references in the file.
In `@internal/infrastructure/db/postgres/intent_txid_migration_test.go`:
- Around line 3-45: Gate the TestIntentTxidMigration so it only runs when a
Postgres DSN is provided via an env var (e.g. POSTGRES_TEST_DSN) and skip with
t.Skip if unset; read the DSN from that env var instead of hardcoding it. In
TestIntentTxidMigration ensure deterministic cleanup by either creating table
names with a unique suffix (or using a dedicated temporary schema) and adding
defer cleanup that drops those tables (or the schema) and closes the DB, or run
the test work inside a transaction and roll it back at the end; update calls to
setupRoundTable, setupOldIntentTable, insertTestRoundRows, insertTestIntentRows,
modifyIntentTable and BackfillIntentTxid to accept the dynamic table/schema
names or transaction handle so cleanup works reliably. Ensure defer db.Close()
remains and that any created tables are dropped in a deferred cleanup to make
the test safe for local `go test ./...`.
In `@internal/infrastructure/db/postgres/intent_txid_migration.go`:
- Around line 103-118: The doc comment for function columnExists is inaccurate
(mentions "PRAGMA table_info" / SQLite) while the implementation queries
PostgreSQL's information_schema.columns; update the comment to describe that
columnExists checks for a column using information_schema.columns (PostgreSQL)
and mention the parameters/context (ctx, db, tableName, columnName) to match the
implementation in columnExists.
- Around line 31-83: The backfillIntent function must use a named error return
(err error) and avoid shadowing so the deferred rollback can see failures:
change the signature to func backfillIntent(ctx context.Context, db *sql.DB)
(err error), replace any short-declared errors (e.g., the rows.Scan, rows.Err,
rows.Close, tx.QueryContext and tx.ExecContext checks) so they assign to the
outer err (use = not :=), and when DeriveTxidFromProof returns derr assign it to
err before returning; additionally track commit success (e.g., set committed :=
false, set committed = true after tx.Commit() succeeds) or simply defer a
rollback that runs unless the function returns nil by setting defer func(){ if
err != nil { _ = tx.Rollback() } }() so all error paths (including tx.Commit
failure) trigger rollback correctly.
In `@internal/infrastructure/db/service.go`:
- Around line 234-256: The migration currently advances to
intentTxidMigrationBegin before running BackfillIntentTxid so a failing backfill
leaves the DB version at the threshold and prevents retries; modify the flow in
the init sequence (the block using m.Version(), intentTxidMigrationBegin,
m.Migrate, and BackfillIntentTxid) to ensure backfill is retried: either run
BackfillIntentTxid before committing the version bump or, if you must call
m.Migrate first, add logic to detect version == intentTxidMigrationBegin and
re-run BackfillIntentTxid when NULL/empty intent txid rows remain (i.e., query
for missing txids) and only consider the migration fully complete when
BackfillIntentTxid succeeds; ensure errors from BackfillIntentTxid propagate so
startup can retry and do not leave the schema version marked as completed if
backfill failed.
In `@internal/infrastructure/db/sqlite/round_repo.go`:
- Around line 457-472: GetIntentByTxid currently constructs domain.Intent with
only Proof and Message, leaving Id and Txid empty; update the return to populate
domain.Intent.Id and domain.Intent.Txid from the DB row (the local variable
intent returned by r.querier.SelectIntentByTxid) and handle the SQL null
wrappers (e.g., sql.NullString/NullInt64) appropriately so Id and Txid are set
when present; change the construction inside GetIntentByTxid to map intent.Id
and intent.Txid into the domain.Intent fields alongside Proof and Message.
♻️ Duplicate comments (3)
internal/infrastructure/db/badger/ark_repo.go (2)
542-542: Use pointer receiver for consistency.
GetIntentByTxiduses a value receiver while all other methods in this file use pointer receivers. This inconsistency should be fixed.♻️ Proposed fix
-func (r arkRepository) GetIntentByTxid(ctx context.Context, txid string) (*domain.Intent, error) { +func (r *arkRepository) GetIntentByTxid(ctx context.Context, txid string) (*domain.Intent, error) {
543-546: Verify not-found error handling matches interface contract.A past review comment requested returning
(nil, nil)when the intent is not found, allowing the interface layer to map this toINTENT_NOT_FOUND. Currently,getIntentIndexByTxidreturns an error on not-found (line 588), which propagates here. Confirm this aligns with the final agreed-upon contract.#!/bin/bash # Check how other GetIntentByTxid implementations handle not-found rg -nA 10 "func.*GetIntentByTxid" --type=go internal/infrastructure/db/internal/infrastructure/db/postgres/round_repo.go (1)
426-442: Populate Id/Txid in GetIntentByTxid result.Same issue as SQLite: the returned intent lacks Id/Txid, which can lead to incomplete API responses.
🛠️ Suggested fix
- return &domain.Intent{ - Proof: intent.Proof.String, - Message: intent.Message.String, - }, nil + return &domain.Intent{ + Id: intent.ID.String, + Txid: intent.Txid.String, + Proof: intent.Proof.String, + Message: intent.Message.String, + }, nil
🧹 Nitpick comments (2)
internal/infrastructure/db/badger/ark_repo.go (1)
300-305: Consider logging the suppressed error for observability.While
nolint:errchecksilences the linter, failures in intent index upserts will be silently dropped. Logging would aid debugging without failing the round upsert.♻️ Suggested improvement
// upsert intent index for each intent with a txid for _, it := range rnd.Intents { // do not fail the whole round upsert if intent index upsert fails - // nolint:errcheck - r.upsertIntentIndex(ctx, it.Txid, rnd.Id, it.Id) + if err := r.upsertIntentIndex(ctx, it.Txid, rnd.Id, it.Id); err != nil { + // Log but don't fail the round upsert + fmt.Printf("failed to upsert intent index for txid %s: %v\n", it.Txid, err) + } }internal/infrastructure/db/postgres/intent_txid_migration.go (1)
86-92: Avoid duplicating txid derivation helpers across layers.
A similarDeriveTxidFromProofexists ininternal/core/application/utils.goand SQLite migration; consider consolidating into a shared helper to prevent drift in error semantics.
| return nil | ||
| } | ||
|
|
||
| func DeriveTxidFromProof(proof string) (string, error) { |
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.
no need to be exported
| func DeriveTxidFromProof(proof string) (string, error) { | |
| func deriveTxidFromProof(proof string) (string, error) { |
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.
handled in: 27c13e0
| @@ -0,0 +1,141 @@ | |||
| package pgdb | |||
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 convention is to declare this a test package (and this is the only reason why the backfill function is exported)
| package pgdb | |
| package pgdb_test |
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.
handled in: 27c13e0
| return &domain.Intent{ | ||
| Proof: intent.Proof.String, | ||
| Message: intent.Message.String, | ||
| }, nil |
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.
| return &domain.Intent{ | |
| Proof: intent.Proof.String, | |
| Message: intent.Message.String, | |
| }, nil | |
| return &domain.Intent{ | |
| Txid: intent.Txid.String, | |
| Proof: intent.Proof.String, | |
| Message: intent.Message.String, | |
| }, nil |
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.
coderabbitai suggested this as well: #884 (comment)
I will modify the query so we can populate txid here
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.
handled in: 27c13e0
| intentTxidMigrationBegin := uint(20260114000000) | ||
| version, dirty, verr := m.Version() | ||
| if verr != nil && !errors.Is(verr, migrate.ErrNilVersion) { | ||
| return nil, fmt.Errorf("failed to read migration version: %w", verr) | ||
| } | ||
| if dirty { | ||
| return nil, fmt.Errorf( | ||
| "database is in a dirty migration state; manual intervention required", | ||
| ) | ||
| } | ||
|
|
||
| if version < intentTxidMigrationBegin { | ||
| if err := m.Migrate(intentTxidMigrationBegin); err != nil && | ||
| !errors.Is(err, migrate.ErrNoChange) { | ||
| return nil, fmt.Errorf("failed to run migrations: %s", err) | ||
| } | ||
|
|
||
| err = pgdb.BackfillIntentTxid(context.Background(), db) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to backfill intent txid field: %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.
seems like this code is duplicated and can be moved to a util function handleIntentIdMigration (or smtn lke that)?
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.
handled in: 27c13e0
| @@ -0,0 +1,135 @@ | |||
| package sqlitedb | |||
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.
| package sqlitedb | |
| package sqlitedb_test |
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.
handled in: 27c13e0
| return &domain.Intent{ | ||
| Proof: intent.Proof.String, | ||
| Message: intent.Message.String, | ||
| }, nil |
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.
| return &domain.Intent{ | |
| Proof: intent.Proof.String, | |
| Message: intent.Message.String, | |
| }, nil | |
| return &domain.Intent{ | |
| Txid: intent.Txid.String, | |
| Proof: intent.Proof.String, | |
| Message: intent.Message.String, | |
| }, nil |
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.
also added in the id field: 27c13e0
…ndling, package naming, returned intents to include id and txid
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.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@internal/infrastructure/db/postgres/intent_txid_migration_test.go`:
- Around line 83-86: Move the error check for psbt.NewFromRawBytes before
dereferencing the returned packet: call psbt.NewFromRawBytes(r.Proof...),
immediately assert require.NoError(t, err), and only then access
pkt.UnsignedTx.TxID() to compute txidFromProof and compare with require.Equal;
this fixes the potential panic when NewFromRawBytes returns an error (symbols:
psbt.NewFromRawBytes, pkt, pkt.UnsignedTx.TxID, require.NoError, require.Equal).
🧹 Nitpick comments (4)
internal/infrastructure/db/badger/ark_repo.go (2)
542-570: Fix receiver inconsistency: use pointer receiver.
GetIntentByTxiduses a value receiver (r arkRepository) while all other methods in this file use pointer receivers (r *arkRepository). This inconsistency should be fixed for consistency and to avoid potential issues if the method needs to access mutable state in the future.♻️ Proposed fix
-func (r arkRepository) GetIntentByTxid(ctx context.Context, txid string) (*domain.Intent, error) { +func (r *arkRepository) GetIntentByTxid(ctx context.Context, txid string) (*domain.Intent, error) {
27-31: Consider unexporting IntentIndex.
IntentIndexis only used internally within this package for badgerhold storage. Unless it needs to be accessed externally, it could be unexported tointentIndexto reduce the public API surface.internal/infrastructure/db/postgres/intent_txid_migration.go (1)
90-96: Note: deriveTxidFromProof is duplicated in SQLite migration.The
deriveTxidFromProoffunction exists in both Postgres and SQLite migration files with identical implementation. This duplication is acceptable for migration code isolation, but if the logic needs to change, remember to update both locations.internal/infrastructure/db/service.go (1)
623-658: LGTM! Consolidated migration handler addresses duplication concern.The
HandleIntentTxidMigrationfunction properly:
- Consolidates the stepwise migration logic (addressing the past review comment about duplication)
- Handles dirty migration state detection
- Calls the appropriate backfill function based on db type
One minor improvement: consider accepting a
context.Contextparameter instead of usingcontext.Background()on lines 645 and 649, to allow callers to pass cancellation context during shutdown.♻️ Optional: Accept context parameter
-func HandleIntentTxidMigration(m *migrate.Migrate, db *sql.DB, dbType string) error { +func HandleIntentTxidMigration(ctx context.Context, m *migrate.Migrate, db *sql.DB, dbType string) error { intentTxidMigrationBegin := uint(20260114000000) // ... switch dbType { case "postgres": - if err := pgdb.BackfillIntentTxid(context.Background(), db); err != nil { + if err := pgdb.BackfillIntentTxid(ctx, db); err != nil { return fmt.Errorf("failed to backfill intent txid field: %w", err) } case "sqlite": - if err := sqlitedb.BackfillIntentTxid(context.Background(), db); err != nil { + if err := sqlitedb.BackfillIntentTxid(ctx, db); err != nil { return fmt.Errorf("failed to backfill intent txid field: %w", err) }
internal/infrastructure/db/postgres/intent_txid_migration_test.go
Outdated
Show resolved
Hide resolved
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.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@internal/infrastructure/db/sqlite/intent_txid_migration.go`:
- Around line 40-89: backfillIntent's deferred rollback relies on an outer err
but multiple returns create shadowed/unnamed errors so the transaction won't
rollback; change backfillIntent to use a named return error (e.g., func
backfillIntent(ctx context.Context, db *sql.DB) (err error)) and remove any
shadowed short‑declares so all failures assign to that named err: capture errors
from deriveTxidFromProof (replace derr with assignment to err), check rows.Err()
by assigning to err, and assign tx.Commit() to err before returning; keep the
defer that rolls back when err != nil and ensure stmt.Close/rows.Close are
deferred without shadowing.
🧹 Nitpick comments (1)
internal/infrastructure/db/sqlite/migration/20260106000000_add_vtxo_updated_at.up.sql (1)
1-6: Confirm updated_at semantics and guard against NULLs.
updated_atis nullable with no default, and the backfill sets all existing rows to “now.” If any insert/update path omitsupdated_ator if historical ordering/TTL logic relies on true last-modified times, this can misbehave. Please verify that all write paths setupdated_atand that the “now” backfill is intended; otherwise consider adding a DEFAULT/trigger or deriving from existing timestamps.
Issue: #883
rpc for
GetIntentallowing caller to pass atxidand receive back corresponding intent.Currently the
intenttable does not have a column for txid. This makes the lookup for intent by txid not easy. We can derive the txid of an intent via theproofcolumn. This PR includes a db migration to add this newtxidfield, and backfill existing rows by grabbing theproofand deriving thetxidand storing this in the newtxidfield.The migration is crafted into files for sqlite and postgres called
intent_txid_migration.gowhich will:txidcolumn inintenttableI have this custom migration setup as:
(where
20260114000000is the date of the new schema addtion migration sql file)The idea here is that when we detect the db has not had the newest schema addition applied (which simply adds the
txidcolumn to theintenttable), we apply this simple schema addition. Then we immediately backfill in this newtxidcolumn via the code inintent_txid_migration.go.Testing was performed as follows:
txidcolumn, and that the existingintentrows have thistxidpopulated.NOTE: This same custom migration is not being performed for badger.
Going forward we will write intent rows with the txid.
Summary by CodeRabbit
New Features
Bug Fixes / Errors
Chores (Data & Migrations)
Tests
✏️ Tip: You can customize this high-level summary in your review settings.