Skip to content

perf: reduce duplicate push audit storage - #1795

Open
dcoric wants to merge 20 commits into
finos:mainfrom
dcoric:perf/push-storage-rollups
Open

dcoric wants to merge 20 commits into
finos:mainfrom
dcoric:perf/push-storage-rollups

Conversation

@dcoric

@dcoric dcoric commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Description

Large pushes store the diff repeatedly in processor logs and content, and the final step is duplicated in lastStep. Store each diff once and replace an identical final step with an internal reference in the file, MongoDB, and PostgreSQL sinks. Detail reads restore the complete API response; existing records remain readable.

Push lists and profile activity use the same metadata allowlist across all three sinks. Unused top-level author, message, protocol, and errorMessage fields are excluded. Commit/tag metadata needed by the UI is preserved; full diffs and processor results remain available on the detail endpoint.

Related Issue

Storage portion of #1691 and PostgreSQL parity in #1794, following the merge of #1687. Repository activity summaries and the related UI refresh fixes are now in #1801. Both PRs are needed to complete the agreed scope. The Action.diff refactor in #1693 and #1701 remains separate.

Validation

  • 1,705 unit tests passed; 91.62% line coverage.
  • 67 MongoDB and 87 PostgreSQL integration tests passed, including the shared storage contract and legacy record compatibility.
  • Six real Git push/fetch scenarios and all 18 current Cypress tests passed against PostgreSQL in the combined verification build.
  • Manually verified metadata-only list responses, complete detail diffs, restored lastStep, and rendered push details.
  • Production build, TypeScript, formatting, and lint passed, with the existing tagPush Cypress warning.
  • Combined with perf: cache repository activity summaries #1801 locally: 729 unit/service/processor tests, 95 MongoDB integration tests, and 101 PostgreSQL integration tests passed. The sink adapter overlap has been resolved and verified locally for when the second PR is updated after the first merges.

A constructed push whose final step held a 2 MiB diff serialized to 8,389,308 bytes before compaction and 2,097,722 bytes afterward. Historical records are preserved rather than rewritten.

Checklist

  • CONTRIBUTING.md reviewed; Conventional Commits used
  • FINOS CLA on file
  • Tests and processor documentation updated
  • Unit/integration tests, lint, formatting, type checks, and build passed

No configuration schema changes.

@dcoric
dcoric requested a review from a team as a code owner October 4, 2026 14:37
@netlify

netlify Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for endearing-brigadeiros-63f9d0 ready!

Name Link
🔨 Latest commit a1ee202
🔍 Latest deploy log https://app.netlify.com/projects/endearing-brigadeiros-63f9d0/deploys/6ad200a58c7dce6d6d808f79
😎 Deploy Preview https://deploy-preview-1795.git-proxy.preview.finos.org
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@codecov

codecov Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.91%. Comparing base (7a30ae6) to head (a1ee202).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1795      +/-   ##
==========================================
+ Coverage   87.00%   87.91%   +0.91%     
==========================================
  Files         113      121       +8     
  Lines        6463     6809     +346     
  Branches     1253     1289      +36     
==========================================
+ Hits         5623     5986     +363     
+ Misses        536      514      -22     
- Partials      304      309       +5     

☔ 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.

dcoric added 2 commits October 4, 2026 18:15
Signed-off-by: Denis Ćorić <denis85@gmail.com>
Signed-off-by: Denis Ćorić <denis85@gmail.com>

@jescalada jescalada 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.

Looks good so far, just wondering if we could simplify the PR description/title a bit to make it easier to follow.

Since we're technically fixing the audit problem but also doing the push count recalculation stuff, it might even be better to have separate PRs for each 🤔

Comment thread src/db/pushProjection.ts Outdated
commitFrom: 1,
commitTo: 1,
error: 1,
errorMessage: 1,

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.

Are all the newly added fields here in pushListProjection actually being used? I'm wondering about the errorMessage for instance, since that might contain processor output that may or may not be relevant to the user.

I noticed there's also a few extra ones like protocol, message and author.

Comment thread src/db/mongo/repoActivity.ts Outdated
return index.snapshot();
};

export const getRepoPushRollupsByCanonicalUrl =

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.

It seems that when loading any of the following dashboard tabs...

  • Repositories (/dashboard/repo)
  • Activity (/dashboard/push)
  • Push Details (/dashboard/push/:id)
  • User Profile (/dashboard/user/:id)

...we're triggering getRepoPushRollupsByCanonicalUrl, which ends up doing the whole dirty entry updating.

I'm wondering if this isn't accidentally affecting performance, what would happen if multiple users were to access the same pages? If we recalculate the rollups for multiple repos at the same time, wouldn't conflicts arise on dirty detection too?

Comment thread src/db/mongo/repoActivity.ts Outdated
return { pushes, summaries };
};

const backfillActivity = async (): Promise<void> => {

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.

I noticed that backfillActivity is running on getRepos on the first proxy startup. Wouldn't a cleaner solution be to run this on a migration so that it doesn't block any operations while the proxy is already up and running?

Comment thread src/db/mongo/repoActivity.ts Outdated
let initialization = initialized.get(database);
if (!initialization) {
initialization = Promise.all([
pushes.createIndex({ id: 1 }, { unique: true }),

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.

Was the unique check on push IDs previously enforced? If not, would that cause any clashes on calling getRepos?

Comment thread src/db/mongo/repoActivity.ts Outdated
throw new Error(`Push ${id} changed repeatedly during deletion; retry the request`);
};

export const rebuildRepoPushRollups = async (): Promise<RepoPushRollupsByCanonicalUrl> => {

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.

I think this is only being used in tests, and we aren't exporting it via src/db/index.ts so I don't think it can be used:

image


const att = push.attestation;
const ts = DateTime.fromMillis(Number(att.timestamp));
const numericTimestamp = Number(att.timestamp);

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.

We're doing the same conversion on RejectionInfo.tsx right below - might want to extract into a helper.

@kriswest kriswest mentioned this pull request Oct 5, 2026
17 of 24 tasks
dcoric added 4 commits October 6, 2026 12:02
Signed-off-by: Denis Ćorić <denis85@gmail.com>
Signed-off-by: Denis Ćorić <denis85@gmail.com>
Signed-off-by: Denis Ćorić <denis85@gmail.com>
Signed-off-by: Denis Ćorić <denis85@gmail.com>
@dcoric dcoric mentioned this pull request Oct 6, 2026
4 tasks done
@dcoric dcoric changed the title perf: reduce push audit storage and repository rollup scans perf: reduce duplicate push audit storage Oct 6, 2026
Signed-off-by: Denis Ćorić <denis85@gmail.com>
Signed-off-by: Denis Ćorić <denis85@gmail.com>
Signed-off-by: Denis Ćorić <denis85@gmail.com>
Comment thread src/db/pushStorage.ts

type StoredPush = Action & { _lastStepIndex?: number; _activity?: unknown };

export const compactPush = (action: Action) => {

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.

Adding a verbal description of what this is doing in a comment would be use full here and on restorePush

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.

I see it in the architecture doc, but it'd be good to have the same description inline in the code

@kriswest kriswest modified the milestone: 2.4.0 Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reduce stored push document size and rollup scan cost across sink backends

3 participants