Skip to content

Upload S3 files concurrently instead of one directory call - #4208

Closed
Mpdreamz wants to merge 1 commit into
fix/nav-svg-spritefrom
fix/parallel-s3-sync
Closed

Mpdreamz wants to merge 1 commit into
fix/nav-svg-spritefrom
fix/parallel-s3-sync

Conversation

@Mpdreamz

@Mpdreamz Mpdreamz commented Sep 22, 2026 •

Copy link
Copy Markdown
Member

Replaces the single TransferUtilityUploadDirectoryRequest in the assembler deploy path with per-file Parallel.ForEachAsync, isolates upload failures, and ensures Apply returns false when any file fails.

Affects: CI/CD · Deploying

Prompt summary: Refresh stale PR #3650 — the original parallel S3 upload implementation that never landed due to a mechanical rebase conflict. Move the two integration tests that were deleted from tests-integration/ into the new tests/Elastic.Documentation.Deploying.Tests/ project.

Why

AwsS3SyncApplyStrategy.Apply copies every file into a temp directory and issues one TransferUtilityUploadDirectoryRequest. That single-threaded path is the bottleneck in the assembler deploy step, and a failure in any one file is opaque — the upload either all-succeeds or throws with no per-file context.

What

Parallel per-file upload

Parallel.ForEachAsync with a configurable semaphore replaces the single directory transfer. DOCS_SYNC_UPLOAD_CONCURRENCY (default 32) and DOCS_SYNC_DELETE_CONCURRENCY (default 4) tune the parallelism. Each file's upload and each delete batch run independently; a failure is caught, logged, and recorded — Apply returns false if any file fails rather than masking the error.

Error isolation in the deploy service

IncrementalDeployService wraps the per-file upload lambda in its own catch block so a single bad file does not abort the whole run.

Tests

Two new tests exercise the delete-chunking at the S3 1000-key limit and the failure-return-false path. Both use TUnit [Test] (matching the project's current test framework after main merged the TUnit migration) with CancellationToken.None rather than xUnit/TUnit context APIs.

Verify

dotnet test tests/Elastic.Documentation.Deploying.Tests/

Stack: 4 of 5, on top of #4207

🤖 Generated with Claude Code

@github-actions github-actions 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.

Requesting changes due to a high-severity reliability gap in per-file upload error isolation.


What is this? | From workflow: PR Review

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

}, async (upload, token) =>
{
var operation = addPaths.Contains(upload.LocalPath) ? "add" : "update";
var fileSize = context.WriteFileSystem.FileInfo.New(upload.LocalPath).Length;

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.

[HIGH] Per-file failure isolation does not cover pre-upload file I/O

Apply now reports per-file upload failures via collector.EmitError, but the try/catch only starts at UploadAsync. If a planned file is removed/unreadable between planning and apply, FileInfo.New(upload.LocalPath).Length throws before that catch, which escapes Parallel.ForEachAsync and aborts the whole apply.

Please wrap the full per-file lambda body (metadata read, request construction, and upload call) in the same non-cancellation catch so a single missing/corrupt file is recorded as an error and the batch continues.

@github-actions

Copy link
Copy Markdown
Contributor

Docs preview (local build)

Handbook preview: https://docs-v3-preview.elastic.dev/elastic/docs-builder/pull/4208/

@github-actions github-actions 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.

Requesting changes: this introduces a destructive partial-deploy path where deletes can run even after upload failures in the same apply run.


What is this? | From workflow: PR Review

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

Comments that could not be inline-anchored

src/services/Elastic.Documentation.Deploying/Synchronization/AwsS3SyncApplyStrategy.cs:161

[HIGH] Deletes proceed even after upload failures

Apply now catches per-file upload exceptions and records them, but it still always calls Delete afterward. That can remove still-serving objects even when their replacement upload failed.

Concrete failure scenario: a page rename becomes add(new-path) + delete(old-path). If the add fails (for example transient S3 error), this method still executes deletes, so old-path is removed and the page disappears until a later successful dep…

@Mpdreamz
Mpdreamz force-pushed the fix/parallel-s3-sync branch from fe06658 to e86b8c2 Compare September 24, 2026 12:28

@github-actions github-actions 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.

Requesting changes because the new tests currently fail to compile in this project.


What is this? | From workflow: PR Review

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

);
}

[Fact]

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.

[HIGH] New test attributes break this test project build

This test project is configured for TUnit (tests/Directory.Build.props references TUnit), but these new tests use [Fact], which is not available here. Running dotnet test tests/Elastic.Documentation.Deploying.Tests/ --nologo -v minimal fails with CS0246 on both new [Fact] lines (344 and 386), so CI cannot compile this PR.

Please switch both attributes to [Test] to match the rest of this file and the project’s test framework.

@Mpdreamz
Mpdreamz force-pushed the fix/parallel-s3-sync branch 2 times, most recently from 5f271c8 to 377b049 Compare September 24, 2026 14:14
Wraps the per-file upload lambda in error handling and uploads add/update
requests in parallel via Parallel.ForEachAsync. Tests migrated from xUnit
[Fact] to TUnit [Test].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Mpdreamz
Mpdreamz force-pushed the fix/parallel-s3-sync branch from 82c8274 to a98264e Compare September 29, 2026 10:01
@Mpdreamz

Copy link
Copy Markdown
Member Author

Closed to retarget to main as a standalone PR. Content preserved in new PR.

This branch was successfully deployed

2 active deployments
docs-preview — a98264e2 Deployed Sep 29, 2026 by github-actions[bot]
assembler-preview — a98264e2 Deployed Sep 29, 2026 by github-actions[bot]
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