Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions src/Packages/Audience/Runtime/Transport/HttpTransport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,22 @@ internal async Task<bool> SendBatchAsync(CancellationToken ct = default)
{
// 4xx: server rejected the payload. Drop it (retry won't help) and
// reset backoff — server is healthy, our data was the problem.
// Pull the response body so the studio has something actionable:
// the status code alone just says "something is wrong"; the body
// names which field or event broke validation. Truncated to keep
// logs sane if the backend ever returns a long diagnostic.
string? body = null;
try { body = await response.Content.ReadAsStringAsync().ConfigureAwait(false); }
catch { /* Content read failed (disposed, network) — fall through with body=null. */ }

_store.Delete(batch);
ResetBackoff();
NotifyError(AudienceErrorCode.ValidationRejected,
$"Batch rejected with {statusCode}");

const int maxBodyLen = 500;
var message = string.IsNullOrEmpty(body)
? $"Batch rejected with {statusCode}"
: $"Batch rejected with {statusCode}: {(body.Length > maxBodyLen ? body.Substring(0, maxBodyLen) + "…" : body)}";
NotifyError(AudienceErrorCode.ValidationRejected, message);
}
else
{
Expand Down Expand Up @@ -210,11 +222,11 @@ private void ResetBackoff()
}

// Reads each path and wraps the concatenated JSON bodies in
// {"batch":[msg1,msg2,...]}. Returns null if every path was
// {"messages":[msg1,msg2,...]}. Returns null if every path was
// unreadable; the caller treats null as "nothing to send".
private static string? BuildPayload(IReadOnlyList<string> paths)
{
var sb = new StringBuilder("{\"batch\":[");
var sb = new StringBuilder("{\"messages\":[");
var count = 0;

for (var i = 0; i < paths.Count; i++)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public async Task SendBatchAsync_200_SendsGzippedPayloadWithCorrectHeaders()
Assert.AreEqual("gzip", capturedContentEncoding);

var decompressed = DecompressGzip(capturedBody);
StringAssert.StartsWith("{\"batch\":[", decompressed);
StringAssert.StartsWith("{\"messages\":[", decompressed);
StringAssert.EndsWith("]}", decompressed);
StringAssert.Contains("\"eventName\":\"test\"", decompressed);
}
Expand Down Expand Up @@ -116,7 +116,7 @@ public async Task SendBatchAsync_200_SendsPlainJsonPayloadWithoutContentEncoding
Assert.AreEqual("pk_imapik-test-key1", capturedKey);
Assert.AreEqual("application/json", capturedContentType);
Assert.AreEqual(0, capturedContentEncodingCount, "no Content-Encoding header is permitted in v1");
StringAssert.StartsWith("{\"batch\":[", capturedBody);
StringAssert.StartsWith("{\"messages\":[", capturedBody);
StringAssert.EndsWith("]}", capturedBody);
StringAssert.Contains("\"eventName\":\"test\"", capturedBody);
}
Expand Down Expand Up @@ -186,7 +186,8 @@ public async Task SendBatchAsync_4xx_DeletesFilesAndResetsBackoff()
{
_store.Write("{\"type\":\"track\"}");

var handler = new MockHandler(HttpStatusCode.BadRequest, "");
var handler = new MockHandler(HttpStatusCode.BadRequest,
"{\"error\":\"invalid eventName format at /batch/0/eventName\"}");
AudienceError reportedError = null;
using var transport = new HttpTransport(_store, "pk_imapik-test-key1",
onError: e => reportedError = e, handler: handler);
Expand All @@ -197,6 +198,9 @@ public async Task SendBatchAsync_4xx_DeletesFilesAndResetsBackoff()
Assert.IsFalse(transport.IsInBackoffWindow);
Assert.IsNotNull(reportedError);
Assert.AreEqual(AudienceErrorCode.ValidationRejected, reportedError.Code);
// Backend-supplied diagnostic must reach the studio, otherwise a 400
// collapses to "something broke, good luck" with no actionable signal.
StringAssert.Contains("invalid eventName format", reportedError.Message);
}

[Test]
Expand Down
2 changes: 1 addition & 1 deletion src/Packages/Audience/Tests/Runtime/Utility/GzipTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void Compress_ProducesValidGzip_ThatDecompressesToOriginal()
public void Compress_OutputIsSmallerThanInput_ForRealisticPayload()
{
// Repeated field names compress well in JSON batches.
var sb = new StringBuilder("{\"batch\":[");
var sb = new StringBuilder("{\"messages\":[");
for (var i = 0; i < 20; i++)
{
if (i > 0) sb.Append(',');
Expand Down
Loading