Skip to content

fix(storage): handle PIT + metadata filter on aggregated balances when ACCOUNT_METADATA_HISTORY is disabled (v2.3)#1423

Merged
gfyrag merged 3 commits into
release/v2.3from
hotfix/v2.3/aggregate-balances-pit-metadata-history-disabled
Jun 19, 2026
Merged

fix(storage): handle PIT + metadata filter on aggregated balances when ACCOUNT_METADATA_HISTORY is disabled (v2.3)#1423
gfyrag merged 3 commits into
release/v2.3from
hotfix/v2.3/aggregate-balances-pit-metadata-history-disabled

Conversation

@gfyrag

@gfyrag gfyrag commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Backport of #1421 to release/v2.3.

  • /aggregate/balances?pit=… with a metadata \$match filter silently returned {"data":{}} on ledgers configured with ACCOUNT_METADATA_HISTORY: DISABLED, because the PIT path joined the accounts_metadata history table that is never populated under that feature flag value.
  • Gate the history join on FeatureAccountMetadataHistory=SYNC and fall back to the current accounts.metadata column otherwise — matching the pattern already used in resource_accounts.go.
  • Adds a regression test (TestBalancesAggregatesPITWithMetadataHistoryDisabled) covering with-PIT, without-PIT, and the combined metadata + partial address filter case on a ledger configured with ACCOUNT_METADATA_HISTORY: DISABLED.

Notes on the backport:

  • Import conflict resolved in balances_test.go.
  • v2.3's CommitTransaction already upserts accounts internally, so the commitTransactionAndUpsertAccounts helper from main is unnecessary — the regression test was adapted to call store.CommitTransaction(ctx, &tx, nil) directly (separate adjustment commit).

Fixes #1416

Test plan

  • CI green on this branch

…n ACCOUNT_METADATA_HISTORY is disabled

The aggregated balances PIT path unconditionally joined the
`accounts_metadata` history table when filtering by metadata, returning
an empty result on ledgers configured with
`ACCOUNT_METADATA_HISTORY: DISABLED` because that table is never
populated under this setting.

Gate the history join on `FeatureAccountMetadataHistory=SYNC` and fall
back to the current `accounts.metadata` column otherwise, mirroring the
pattern already used in `resource_accounts.go`. This restores the
expected behaviour and matches what `/accounts` returns under the same
configuration.

Fixes #1416
The previous commit introduced a second lateral join aliased as
`accounts` in the metadata fallback branch, which collided with the
existing address-segments lateral when a PIT aggregate query combined a
metadata filter with a partial address filter on a ledger configured
with `ACCOUNT_METADATA_HISTORY: DISABLED`, producing
`ERROR: table name "accounts" specified more than once`.

Rename the fallback alias to `accounts_metadata` for symmetry with the
SYNC branch, and extend the regression test with the combined
metadata + partial address filter scenario.
@gfyrag gfyrag requested a review from a team as a code owner June 19, 2026 09:04
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1d08b592-83cb-4640-b7a1-37ac3141ae83

📥 Commits

Reviewing files that changed from the base of the PR and between 1be6728 and 8f46247.

📒 Files selected for processing (1)
  • internal/storage/ledger/balances_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/storage/ledger/balances_test.go

Walkthrough

When UsePIT and a metadata filter are both active in aggregatedBalancesResourceRepositoryHandler.BuildDataset, the lateral join for metadata is now conditional on FeatureAccountMetadataHistory: it uses the historical accounts_metadata table only if that feature is enabled, otherwise it reads from the current accounts table. A regression test covering this path is added.

Changes

Aggregate Balances PIT + Metadata Fix

Layer / File(s) Summary
Conditional metadata join based on FeatureAccountMetadataHistory
internal/storage/ledger/resource_aggregated_balances.go
In the UsePIT + UseFilter("metadata") branch, a feature-flag check is added: when FeatureAccountMetadataHistory is SYNC, the existing accounts_metadata lateral join with PIT-bounded first_value is used; otherwise, metadata is read directly from the current accounts table.
Regression test: PIT + metadata filter with history disabled
internal/storage/ledger/balances_test.go
Adds TestBalancesAggregatesPITWithMetadataHistoryDisabled, which disables FeatureAccountMetadataHistory, inserts a transaction and account metadata, then asserts correct aggregated volumes for three scenarios: no PIT, PIT-only, and PIT with a partial address filter.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hoppity-hop through the query land,
A PIT and metadata, hand in hand.
History off? No panic, no dread —
We fetch from accounts table instead!
The balances match, the test turns green,
No more silent empties to be seen. 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the bug fix: handling PIT + metadata filters on aggregated balances when ACCOUNT_METADATA_HISTORY is disabled. It directly summarizes the main change.
Description check ✅ Passed The description is well-documented, explaining the bug, root cause, solution, and backport-specific notes. It directly relates to the changeset and references the linked issue.
Linked Issues check ✅ Passed The PR successfully addresses issue #1416 by conditionally gating the history table join on FeatureAccountMetadataHistory and falling back to current metadata, aligning behavior with the /accounts endpoint and resolving the silent empty response bug.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the reported issue: conditional metadata join logic in resource_aggregated_balances.go and a regression test in balances_test.go. No unrelated modifications are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch hotfix/v2.3/aggregate-balances-pit-metadata-history-disabled

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@NumaryBot NumaryBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Changes requested — automated review

The production change appears aligned with the intended fallback, but the added integration test references an undefined type and will not compile when the it test suite is run.

})

t.Run("with pit and partial address filter", func(t *testing.T) {
ret, err := store.AggregatedVolumes().GetOne(ctx, common.ResourceQuery[ledger.GetAggregatedVolumesOptions]{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 [blocker] Use ledgerstore options in the new query

In this new subtest, ledger is the domain package (github.com/formancehq/ledger/internal), which does not define GetAggregatedVolumesOptions; the options type lives in internal/storage/ledger, imported above as ledgerstore. With the it tag enabled this file will fail to compile with undefined: ledger.GetAggregatedVolumesOptions, so the regression suite cannot run.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/storage/ledger/balances_test.go`:
- Line 441: The ResourceQuery generic type parameter in the
AggregatedVolumes().GetOne() method call on line 441 is using the incorrect type
ledger.GetAggregatedVolumesOptions when it should be using
ledgerstore.GetAggregatedVolumesOptions to match the storage contract and be
consistent with the surrounding tests. Replace
ledger.GetAggregatedVolumesOptions with ledgerstore.GetAggregatedVolumesOptions
in the ResourceQuery type parameter.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e35796e5-ea1d-48a6-8bbf-33319fb0b998

📥 Commits

Reviewing files that changed from the base of the PR and between 222fb71 and 1be6728.

📒 Files selected for processing (2)
  • internal/storage/ledger/balances_test.go
  • internal/storage/ledger/resource_aggregated_balances.go

Comment thread internal/storage/ledger/balances_test.go Outdated
v2.3's CommitTransaction handles account upsert internally, so the
`commitTransactionAndUpsertAccounts` helper from main is unnecessary.
@gfyrag gfyrag force-pushed the hotfix/v2.3/aggregate-balances-pit-metadata-history-disabled branch from 1be6728 to 8f46247 Compare June 19, 2026 10:45

@NumaryBot NumaryBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Approve — automated review

The change correctly gates the PIT metadata history join on the account metadata history feature and falls back to current account metadata when disabled. The added regression test covers the described aggregate-balance scenarios, and no introduced correctness issues were identified.

No findings.

@codecov

codecov Bot commented Jun 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.58%. Comparing base (222fb71) to head (8f46247).

Additional details and impacted files
@@               Coverage Diff                @@
##           release/v2.3    #1423      +/-   ##
================================================
+ Coverage         81.54%   81.58%   +0.03%     
================================================
  Files               187      187              
  Lines              9257     9266       +9     
================================================
+ Hits               7549     7560      +11     
- Misses             1253     1254       +1     
+ Partials            455      452       -3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@gfyrag gfyrag merged commit 406be2a into release/v2.3 Jun 19, 2026
9 checks passed
@gfyrag gfyrag deleted the hotfix/v2.3/aggregate-balances-pit-metadata-history-disabled branch June 19, 2026 11:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants