Skip to content

[Fusion] Make FusionArchive generation deterministic - #8994

Merged
tobias-tengler merged 1 commit into
mainfrom
tte/deterministic-fusion-archive
Dec 11, 2025
Merged

tobias-tengler merged 1 commit into
mainfrom
tte/deterministic-fusion-archive

Conversation

@tobias-tengler

@tobias-tengler tobias-tengler commented Dec 11, 2025 •

Copy link
Copy Markdown
Member

FusionArchives previously always had a different hash even for the same source schema and settings inputs, since the "last write time" of each entry was set to the current timestamp.

This PR back-ports a fix I did for the OpenApiCollectionArchive that introduces a fixed timestamp, resulting in deterministic archive generation.

Copilot AI review requested due to automatic review settings December 11, 2025 12:21
@tobias-tengler
tobias-tengler merged commit 2252131 into main Dec 11, 2025
117 of 118 checks passed
@tobias-tengler
tobias-tengler deleted the tte/deterministic-fusion-archive branch December 11, 2025 12:30
@codecov

codecov Bot commented Dec 11, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 0.00%. Comparing base (e66036f) to head (98c967e).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@     Coverage Diff      @@
##   main   #8994   +/-   ##
============================
============================

☔ View full report in Codecov by Sentry.
📢 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.

Copilot AI 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.

Pull request overview

This PR makes FusionArchive generation deterministic by using a fixed timestamp for ZIP entries, ensuring that archives created with identical inputs produce identical binary outputs. Previously, archives had different hashes due to timestamps reflecting the current time during creation.

Key Changes

  • Introduced deterministic file ordering in CommitAsync by sorting files by path using StringComparer.Ordinal
  • Refactored ZIP entry creation into a new CreateEntryFromFileAsync method that sets a fixed timestamp (January 1, 2000) for all entries
  • Removed redundant conditional compilation blocks and consolidated the implementation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +129 to +149
foreach (var file in _files.Values.OrderBy(f => f.Path, StringComparer.Ordinal))
{
#if NET10_0_OR_GREATER
switch (file.State)
{
case FileState.Created:
await _archive.CreateEntryFromFileAsync(
file.TempPath,
file.Path,
cancellationToken: cancellationToken);
await CreateEntryFromFileAsync(file.TempPath, file.Path, cancellationToken);
break;

case FileState.Replaced:
_archive.GetEntry(file.Path)?.Delete();
await _archive.CreateEntryFromFileAsync(
file.TempPath,
file.Path,
cancellationToken);
await CreateEntryFromFileAsync(file.TempPath, file.Path, cancellationToken);
break;

case FileState.Deleted:
_archive.GetEntry(file.Path)?.Delete();
break;
}
#else
switch (file.State)
{
case FileState.Created:
_archive.CreateEntryFromFile(file.TempPath, file.Path);
break;

case FileState.Replaced:
_archive.GetEntry(file.Path)?.Delete();
_archive.CreateEntryFromFile(file.TempPath, file.Path);
break;
file.MarkRead();
}
}

Copilot AI Dec 11, 2025

Copy link

Choose a reason for hiding this comment

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

The deterministic archive generation feature (fixed timestamp and ordered file processing) lacks test coverage. Consider adding a test that creates two archives with identical content and verifies they produce byte-for-byte identical output. This would ensure the determinism is maintained across future changes.

Copilot uses AI. Check for mistakes.
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Fusion Gateway Performance Results

Simple Composite Query

Constant Load (50 VUs)

Requests/sec Error Rate
5843.85 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.78ms 7.12ms 160.72ms 8.40ms 12.86ms 18.63ms

Ramping Load (0→50→500→50 VUs)

Requests/sec Error Rate
4611.86 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.77ms 37.07ms 287.72ms 48.09ms 110.84ms 128.46ms

Executed Query

fragment User on User {
  id
  username
  name
}

fragment Review on Review {
  id
  body
}

fragment Product on Product {
  inStock
  name
  price
  shippingEstimate
  upc
  weight
}

query TestQuery {
  topProducts(first: 5) {
    ...Product
    reviews {
      ...Review
      author {
        ...User
      }
    }
  }
}

Deep Recursion Query

Constant Load (50 VUs)

Requests/sec Error Rate
268.89 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
12.62ms 174.52ms 647.01ms 180.39ms 229.20ms 255.96ms

Ramping Load (0→50→500→50 VUs)

Requests/sec Error Rate
304.32 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
3.06ms 662.42ms 1719.21ms 694.45ms 1403.93ms 1541.57ms

Executed Query

fragment User on User {
  id
  username
  name
}

fragment Review on Review {
  id
  body
}

fragment Product on Product {
  inStock
  name
  price
  shippingEstimate
  upc
  weight
}

query TestQuery {
  users {
    ...User
    reviews {
      ...Review
      product {
        ...Product
        reviews {
          ...Review
          author {
            ...User
            reviews {
              ...Review
              product {
                ...Product
              }
            }
          }
        }
      }
    }
  }
  topProducts(first: 5) {
    ...Product
    reviews {
      ...Review
      author {
        ...User
        reviews {
          ...Review
          product {
            ...Product
          }
        }
      }
    }
  }
}

Variable Batching Throughput

Constant Load (50 VUs)

Requests/sec Error Rate
23582.14 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.09ms 1.71ms 48.13ms 2.07ms 3.94ms 4.80ms

Ramping Load (0→50→500→50 VUs)

Requests/sec Error Rate
18622.52 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.09ms 9.28ms 102.51ms 11.35ms 23.42ms 28.07ms

Executed Query

query TestQuery_8f7a46ce_2(
  $__fusion_1_upc: ID!
  $__fusion_2_price: Long!
  $__fusion_2_weight: Long!
) {
  productByUpc(upc: $__fusion_1_upc) {
    inStock
    shippingEstimate(weight: $__fusion_2_weight, price: $__fusion_2_price)
  }
}

Variables (5 sets batched in single request)

[
  { "__fusion_1_upc": "1", "__fusion_2_price": 899, "__fusion_2_weight": 100 },
  { "__fusion_1_upc": "2", "__fusion_2_price": 1299, "__fusion_2_weight": 1000 },
  { "__fusion_1_upc": "3", "__fusion_2_price": 15, "__fusion_2_weight": 20 },
  { "__fusion_1_upc": "4", "__fusion_2_price": 499, "__fusion_2_weight": 100 },
  { "__fusion_1_upc": "5", "__fusion_2_price": 1299, "__fusion_2_weight": 1000 }
]

No baseline data available for comparison.


Run 20132916209 • Commit 65249e2 • Thu, 11 Dec 2025 12:39:29 GMT

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.

2 participants