Repository navigation
Bulk document upload with ingestion wait (NDI-matlab#1047); ctest failure values (NDI-matlab#1046) - #340
Conversation
…#1047) uploadDocumentCollection's bridge entry said "Exact match", but the port only had MATLAB's serial path: every document went up as its own addDocument request, whatever NDI_CLOUD_UPLOAD_NO_ZIP said -- one request per document, hours for a 100,000-document dataset. It now has MATLAB's default batch path: each chunk (Cloud.Upload.Max_Document_Batch_Count) is one JSON array, zipped by the new zip_documents_for_upload (did's json_encode_nan, as MATLAB's jsonencodenan) and PUT to getBulkUploadURL. NDI_CLOUD_UPLOAD_NO_ZIP=true keeps the serial path, as in MATLAB. upload_type now says 'batch' or 'serial'. VH-Lab/NDI-matlab#1047 comes with it. A bulk upload returns once the zip is stored, before the server has ingested it, and has no job id, so a listing made straight afterwards can miss documents (Cloud CI 1 on NDI-matlab main failed that way). New ndi.cloud.api.documents.waitForDocumentCount polls countDocuments with backoff until the count reaches a target or times out; a failed poll is retried. The batch path reads the count before uploading and afterwards waits for it to grow by the documents in the stored batches (wait_for_ingestion, ingestion_timeout = 300 s). A timeout logs a warning and leaves status alone; the result is in report["ingestion"]. Bridge: waitForDocumentCount added; uploadDocumentCollection synced to 004585c with the two new arguments; zip_documents_for_upload ported (it was recorded as covered by zipForUpload, which zips files, not documents). Tests: tests/test_cloud_upload_bulk_documents.py covers the zip, the batch path (chunks, partial failure, zips deleted, the wait's target, timeout, no starting count, wait off), the serial switch, and waitForDocumentCount's poll logic (WaitForDocumentCountMockTest.m). Sync tests that model the transport by patching addDocument now run on the serial path through a new serial_document_upload fixture. black, ruff clean. pytest tests/: 6121 passed, 1 failed -- the ctest (+ndi/+mock/ctest.m) drift from NDI-matlab#1046, already on main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KChjwyZT9314dmEuS5ovUP
…-matlab#1046) Ports VH-Lab/NDI-matlab 0374dd2. reportSummary named the out-of-tolerance fields but not the values, so a failing calculator self-test -- on unseeded mock data that cannot be re-run -- said which field was off, not by how much. Each failing field now gets a line with its actual value, expected value, absolute difference (when both are numeric and the same shape) and the comparison's comment. New static valueString renders values as MATLAB's mat2str(v,6) does, text quoted, anything else as its size and type, cut at 200 characters. DocComparison's results call the values value1/value2/detail; compare_mock_docs now also carries them as MATLAB's actualValue/expectedValue/comment for reportSummary to read. Bridge: ctest synced to 0374dd2, valueString added. This clears the test_matlab_bridge_hashes drift failure. TestCtestReportSummary.m ports over as TestReportSummarySaysHowFarOut. black, ruff clean; pytest tests/: 6130 passed, 0 failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KChjwyZT9314dmEuS5ovUP
|
Cloud API (User 1, prod) fails on one test, This failure isn't caused by this PR:
Update: the cause was the fixture itself. The coarsest level of Generated by Claude Code |
test_the_coarsest_level_computes_and_is_not_all_zero has failed in the
User 1 / prod Cloud API cell since Oct 20, on main and on this PR: the
coarsest pyramid level of fixture 6accf3a0044c77d93a6ebdb7 read entirely as
fill_value, consistent with its chunk files having been removed from the
cloud while the documents stayed. The fixture was rebuilt today with
ndi.test.cloud.lightsheet_blob_cloud_roundtrip as test user 1 on prod:
6adb9d501dabe363f1268c3f ("Blob Test Dataset 20261023T134551 121").
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KChjwyZT9314dmEuS5ovUP
Summary
Two ports from NDI-matlab, plus a fix for the lightsheet test fixture that
main's nightly cloud run has been failing on.1. Upload documents in bulk and wait for them to be ingested (VH-Lab/NDI-matlab#1047)
uploadDocumentCollection's bridge entry said "Exact match", but the port only had MATLAB's serial path: every document went up as its ownaddDocumentrequest, whateverNDI_CLOUD_UPLOAD_NO_ZIPsaid. That is one request per document, which for a 100,000-document dataset takes hours.Cloud.Upload.Max_Document_Batch_Count) is one JSON array, zipped by the newzip_documents_for_uploadand PUT togetBulkUploadURL..jsonholding the documents' JSON array, encoded with did'sjson_encode_nan.NDI_CLOUD_UPLOAD_NO_ZIP=truekeeps the serial path, as in MATLAB.upload_typenow reports'batch'or'serial'truthfully.ndi.cloud.api.documents.waitForDocumentCount. A bulk upload returns once the zip is stored, before the server has ingested it, and has no job id to wait on. A listing made straight afterwards can therefore miss documents; that's how Cloud CI 1 on NDI-matlabmainfailed.countDocumentswith backoff until the count reaches a target or the timeout elapses. A failed poll is retried.state,count,expectedCountandelapsed.wait_for_ingestion/ingestion_timeout(300 s) mirror MATLAB's options.statusalone. The result is inreport["ingestion"].waitForDocumentCountadded.uploadDocumentCollectionsynced to004585c.zip_documents_for_uploadis now ported. It had been recorded as covered byzipForUpload, which zips files, not documents.2.
ctest.reportSummarysays how far out of tolerance each field was (VH-Lab/NDI-matlab#1046)valueStringrenders values the way MATLAB'smat2str(v,6)does. Text is quoted, anything else is shown as its size and type, and the result is cut at 200 characters.compare_mock_docsnow also carriesDocComparison'svalue1/value2/detailunder MATLAB's names (actualValue/expectedValue/comment), whichreportSummaryreads.ctestsynced to0374dd2, andvalueStringadded. This clears thetest_matlab_bridge_hashesdrift failure that was already onmain.3. Point the lightsheet pyramid tests at the rebuilt fixture
test_the_coarsest_level_computes_and_is_not_all_zerohas failed in the User 1 / prod Cloud API cell since Oct 20, onmainand on this PR.6accf3a0044c77d93a6ebdb7read entirely as fill_value. That fits its chunk files having been removed from the cloud while its documents stayed.ndi.test.cloud.lightsheet_blob_cloud_roundtripas test user 1 on prod, as6adb9d501dabe363f1268c3f.tests/fixtures/lightsheet_cloud_fixture.jsonnow points at it.Tests
tests/test_cloud_upload_bulk_documents.py(20 tests) covers:waitForDocumentCount's poll logic, ported fromWaitForDocumentCountMockTest.m.addDocument(26 tests) run on the serial path through a newserial_document_uploadfixture. Their assertions are unchanged.TestReportSummarySaysHowFarOut(8 tests) portsTestCtestReportSummary.m, plus a check thatcompare_mock_docs' report carries the values.Validation
black --check src/ tests/andruff check src/ tests/: clean.pytest tests/locally (with a full-history NDI-matlab checkout at004585c): 6130 passed, 0 failed.912ff61: all 19 checks pass, including all four live Cloud API cells (users 1 and 2, prod and dev) and the bridge, symmetry and Windows jobs.🤖 Generated with Claude Code
https://claude.ai/code/session_01KChjwyZT9314dmEuS5ovUP