Repository navigation
Preflight all externalized payload sizes before starting uploads #308
Description
The Azure Blob interceptor externalizes response fields sequentially, validating each size only immediately before that field's upload. A later deterministic size violation can therefore occur after earlier valid uploads. The failed-completion fallback discards the partially transformed builder and its references, but does not undo those storage writes.
Current source evidence
Inspected current main at 0262c53c8f13401bfe2c25a3e058128963ad51a9.
externalizeOrchestratorResponseprocesses custom status and then actions. On a size exception, it returns a new failed completion rather than the builder containing earlier uploaded references.maybeExternalizevalidates only the current field and then callspayloadStore.upload.- Immutable protobuf messages prevent some caller-visible mutation, but they do not roll back successful Blob uploads.
The still-open parity PR 306, inspected at a6105169da7c72fed25d6411b2fe295a4d4fe2e7, changes transient failure handling but still has this per-field check/upload sequence.
Requested regression
Use the existing LargePayloadInterceptorTest harness, including its mock store and invokeExternalize helper:
options.setThresholdBytes(8).setMaxPayloadBytes(32);
interceptor = new LargePayloadInterceptor(mockStore, options);
OrchestratorResponse request = OrchestratorResponse.newBuilder()
.setInstanceId("size-preflight")
.setCompletionToken("completion")
.setCustomStatus(StringValue.of("s".repeat(16)))
.addActions(OrchestratorAction.newBuilder()
.setId(1)
.setScheduleTask(ScheduleTaskAction.newBuilder()
.setName("activity")
.setInput(StringValue.of("x".repeat(33)))))
.build();
OrchestratorResponse result = (OrchestratorResponse) invokeExternalize(request);
verify(mockStore, never()).upload(anyString());
assertEquals(1, result.getActionsCount());
assertEquals(
OrchestrationStatus.ORCHESTRATION_STATUS_FAILED,
result.getActions(0).getCompleteOrchestration().getOrchestrationStatus());The current sequence can upload the valid custom status before checking the oversized activity input, then omit its token from the failure response. Cover entity batches and completion carryover fields in the preflight as well.
Evidence boundary: this is a source-backed report. The Java regression recipe has not been run for this filing; the equivalent JavaScript storage-side-effect cases were reproduced and fixed.
Acceptance Criteria
- Inspect and validate the entire set of relevant outgoing payload fields before the first store upload, retaining original values for the later transformation pass.
- Any deterministic maximum-size violation causes zero uploads for that message.
- Include all currently supported fields: custom status, action inputs/results/details, carryover history, relevant failure details and entity payloads.
- Preserve existing permanent failure representation and the independently tracked entity-release obligations; do not retain invalid business actions merely to preserve uploaded references.
- Preserve empty/absent fields, threshold semantics, configured limits and cancellation/error behavior.
- Keep the eventual implementation compatible with known-token idempotency: references that are already final must not be re-uploaded or treated as new raw payloads.
- Add valid-first/oversized-later orchestration/entity tests, UTF-8 boundaries and all-valid transformations.
- Document that deterministic size validation now occurs before hypothetical earlier upload errors.
Non-goals
This does not make backend submission and Blob uploads one transaction, recover existing orphan blobs, or guarantee zero orphans after real I/O failures. No unconditional catch-and-delete rollback should be added: an uncertain completion response is not proof that the backend did not record a reference.
The current Java interceptor already traverses CompleteOrchestrationAction.CarryoverEvents; the JavaScript carryover omission does not need a separate Java issue.
Related
- JavaScript zero-upload preflight fix.
- .NET tracking issue 820.
- Java issue 307 addresses entity unlock retention and known-token handling. This issue is the distinct deterministic-size-before-storage guarantee.
Activity