Repository navigation
Add ndi.cloud.api.files.waitForFileUpload; wait for upload processing in uploadSingleFile and FilesTest - #1027
Merged
Merged
Conversation
A single-file PUT returning 200 only means S3 has the object; the server records the upload (uploaded, size, crc32) in an S3-triggered lambda afterwards. That lambda runs with reservedConcurrency 8, so when another Cloud CI shard is bulk-uploading (each extracted file wakes the same lambda) the record can lag the PUT by more than the fixed 10 s FilesTest waited, and the curl upload tests saw uploaded=false, size=0. waitForFileUpload polls lookupFiles with exponential backoff until every given uid is marked uploaded, or the timeout (default 120 s) elapses. It is the single-file counterpart to waitForBulkUpload, with the same call-class layout and a pollStatus seam like WaitForFileTierJob. Tests: - FileUploadWaitMockTest (offline, via ndi.test.helper.ScriptedFileUpload): pending-then-uploaded, missing record, timeout, transient lookup error, several uids, duplicate uids. - FilesTest.testWaitForFileUpload (live): happy path and a timeout on a uid that was never uploaded. - FilesTest's seven pause(10) waits after single-file uploads now call waitForFileUpload. Authored without a local MATLAB runtime; needs MATLAB to validate/run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016pWYt77CB6boPRzKxxu9e5
uploadSingleFile gains 'waitForUpload' (default true). For a single-file upload it calls ndi.cloud.api.files.waitForFileUpload after the PUT and fails if the server has not recorded the file within the timeout; for a bulk upload it passes waitForCompletion to putFiles so the extraction job is awaited. A bulk wait failure now reports the job state instead of failing on a missing .message field. The serial sync path (uploadFilesForDatasetDocuments) passes 'waitForUpload', false and waits for all sent uids with one waitForFileUpload call at the end, so a large sync does not wait on the server after every file. FilesTest.testUploadSingleFileRecordsChecksum no longer waits itself: it checks the file is already marked uploaded when uploadSingleFile returns. Authored without a local MATLAB runtime; needs MATLAB to validate/run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016pWYt77CB6boPRzKxxu9e5
Contributor
The test class lives in package ndi.unittest, so the bare FileUploadWaitMockTest.lookup(...) static-method calls failed with MATLAB:undefinedVarOrClass in all 7 tests. Move lookup/scripted to file-local functions (lookupResult/scriptedCall), which need no package qualification. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016pWYt77CB6boPRzKxxu9e5
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1027 +/- ##
==========================================
+ Coverage 30.32% 30.36% +0.03%
==========================================
Files 876 878 +2
Lines 44217 44299 +82
==========================================
+ Hits 13410 13452 +42
- Misses 30807 30847 +40 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
stevewds
approved these changes
Oct 13, 2026
2 of 5 tasks
stevevanhooser
pushed a commit
that referenced
this pull request
Oct 13, 2026
Brings in #1027 (waitForFileUpload; uploadSingleFile waits for NDI Cloud to record the upload; FilesTest uses it). Conflict in uploadFilesForDatasetDocuments: kept both sides -- this branch's files_uploaded_count / Verbose summary and main's sentUids collection with one waitForFileUpload after the serial loop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wj6cuvAwgAaYN5dNM1o6L
stevevanhooser
pushed a commit
to Waltham-Data-Science/NDI-python
that referenced
this pull request
Oct 13, 2026
VH-Lab/NDI-matlab#1027 added +ndi/+cloud/+api/+files/waitForFileUpload.m on main, and bridge completeness (which reads NDI-matlab main) failed for want of an entry. Recorded as not_yet_ported with the reason. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wj6cuvAwgAaYN5dNM1o6L
stevevanhooser
pushed a commit
to Waltham-Data-Science/NDI-python
that referenced
this pull request
Oct 13, 2026
…inst NDI-matlab 9c21eb61 VH-Lab/NDI-matlab#1027 made both wait for NDI Cloud to record uploads (through the new waitForFileUpload). Bumped both hashes with a note that the wait is not ported yet, and gave the waitForFileUpload entry its sync hash (eb583289). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wj6cuvAwgAaYN5dNM1o6L
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
FilesTest/testSingleFileUploadAndDownloadUseCurland...UseCurlStopfail intermittently in Cloud CI. This happened on #979 in runs 38418516741 and 38461572210, and the first passed on re-run. In the failures, curl reports success, butlistFiles/detailthen showuploaded=false, size=0, crc32=""and nodownloadUrl.That is the record's pending state from before the server processes the upload, so the PUT itself succeeded:
putFiles(useCurl)already runscurl -fsSL, so a 4xx from S3 would have madeb_putfalse.x-amz-checksum-crc32=AAAAAA==query parameter on no-checksum URLs is not new with ndi-cloud-node#162.ChecksumAlgorithm: 'CRC32'has been in the signer since April (ndi-cloud-node#47). These tests passed with it until now, including on main 1426fcd today. Spikesorter lisandro #162 records that S3 ignores a checksum sent in the query string.rawFileUploadHandler,reservedConcurrency: 8) records the upload. Files extracted from bulk uploads land in the same bucket and wake that same lambda. Lightsheet pyramids: ingest from OME-Zarr or SmartSPIM, chunk materialization, cloud round trip, and napari viewing #979 addsTestSignedUrlSetJobScalingandTestSignedUrlSetJobFixture, which bulk-upload about 600 files to prod per run, and the other Cloud CI shards run in parallel. When those overlap, this test's event can wait in line for more than the fixedpause(10).The last point is inferred from the code and the run history. I did not have the CI logs or CloudWatch to confirm the timing overlap.
What
ndi.cloud.api.files.waitForFileUpload(datasetId, uids, ...)(new), with the implementation classndi.cloud.api.implementation.files.WaitForFileUpload.lookupFileswith exponential backoff until every uid is marked uploaded or the timeout passes (default 120 s).state,files,pendingandelapsed.waitForAllBulkUploads, with apollStatusmethod tests can override, asWaitForFileTierJobdoes.ndi.cloud.uploadSingleFilegets a'waitForUpload'option, default true.waitForFileUploadafter the PUT and fail if the server hasn't recorded the file in time.waitForCompletiontoputFiles..messagefield.ndi.cloud.sync.internal.uploadFilesForDatasetDocuments(serial strategy) passes'waitForUpload', falseper file. It then waits for all the uids it sent with onewaitForFileUploadcall, so a large sync doesn't wait on the server after every file.FilesTest:pause(10)calls after single-file uploads now callwaitForFileUpload.testUploadSingleFileRecordsChecksumnow checks that the file is already marked uploaded whenuploadSingleFilereturns.Tests
FileUploadWaitMockTest(offline, via the newndi.test.helper.ScriptedFileUpload) covers:FilesTest.testWaitForFileUpload(live) covers the happy path, checking the reported uid and size, and a 3 s timeout on a uid that was never uploaded.Written without a local MATLAB runtime. Nothing here has been run, so it needs CI or a MATLAB run to validate.
🤖 Generated with Claude Code
https://claude.ai/code/session_016pWYt77CB6boPRzKxxu9e5
Generated by Claude Code