-
Notifications
You must be signed in to change notification settings - Fork 25
fix: Prevent data loss when batched events exceed 32KB payload limit #82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
This fix addresses a critical data loss issue where batched events exceeding 32KB were silently dropped instead of being split and sent successfully. ## Problem - Events were queued in memory with default batch_size of 100 - When batch payload exceeded 32KB, entire batch was silently dropped - No error propagation to calling application - Customer reported losing 40,000+ events per day ## Solution - Implement automatic batch splitting when payload exceeds 32KB limit - Continue processing all batches even if some fail (no early termination) - Proper error handling and logging for oversized single messages - Maintain backward compatibility with existing API ## Changes - LibCurl: Add recursive batch splitting with size validation - QueueConsumer: Improve flush() to process all batches - Tests: Comprehensive test suite for payload size scenarios - MockedHttpClient: Add support for /batch/ endpoint mocking ## Impact - Eliminates silent data loss for oversized batches - Maintains performance for normal-sized batches - Provides visibility into payload size issues via error logging - Zero breaking changes to existing API 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Fix whitespace at end of line in docblock - Move MockErrorHandler to separate file to comply with PSR-1 - Add proper import for MockErrorHandler class All tests continue to pass and linting errors are resolved.
d5a6140
to
0937f49
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes a critical data loss issue where batched events exceeding the 32KB payload limit were silently dropped instead of being split and sent successfully.
Key changes:
- Automatic batch splitting when payloads exceed 32KB limit
- Improved error handling to continue processing all batches even if some fail
- Enhanced logging for oversized single messages that cannot be split
Reviewed Changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
File | Description |
---|---|
lib/Consumer/LibCurl.php | Refactored batch sending logic with automatic splitting and recursive handling of oversized payloads |
lib/QueueConsumer.php | Modified flush method to continue processing all batches even when individual batches fail |
test/PayloadSizeLimitFixTest.php | Comprehensive test suite covering oversized batch splitting, single oversized messages, and normal operation |
test/MockedHttpClient.php | Added support for /batch/ endpoint to enable proper testing |
test/MockErrorHandler.php | New mock error handler for capturing and verifying error reporting in tests |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
public function flushBatch($messages) | ||
{ | ||
if (empty($messages)) { | ||
return true; | ||
} | ||
|
||
return $this->sendBatch($messages); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The flushBatch
method now serves as a simple wrapper around sendBatch
. Consider if this indirection is necessary or if the logic could be simplified by moving the empty check into sendBatch
directly.
public function flushBatch($messages) | |
{ | |
if (empty($messages)) { | |
return true; | |
} | |
return $this->sendBatch($messages); | |
} |
Copilot uses AI. Check for mistakes.
// Return boolean based on whether we got a response | ||
return !empty($response->getResponse()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method returns true
for any non-empty response, but doesn't validate if the response indicates success. A 4xx or 5xx HTTP status code would still return true
as long as there's a response body, which could mask actual failures.
// Return boolean based on whether we got a response | |
return !empty($response->getResponse()); | |
} | |
// Return boolean based on HTTP status code (2xx = success) | |
$statusCode = method_exists($response, 'getStatusCode') ? $response->getStatusCode() : null; | |
return $statusCode !== null && $statusCode >= 200 && $statusCode < 300; |
Copilot uses AI. Check for mistakes.
if (!isset($this->mockHttpClient->calls)) { | ||
return 0; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The method checks if calls
property is set but doesn't initialize it consistently. Consider initializing calls
as an empty array in the constructor or setUp method to avoid this defensive check.
if (!isset($this->mockHttpClient->calls)) { | |
return 0; | |
} |
Copilot uses AI. Check for mistakes.
Summary
Fixes critical data loss issue where batched events exceeding 32KB were silently dropped instead of being split and sent successfully.
Internal ticket context
Problem Description
batch_size
of 100flushBatch()
returnsfalse
but errors aren't propagated to calling applicationRoot Cause Analysis
batch_size
reached, triggersflush()
flushBatch()
false
but doesn't split batchflush()
stopped on first failure, losing remaining eventsSolution Implementation
✅ Automatic Batch Splitting
✅ Improved Error Handling
✅ Performance Optimized
Changes Made
sendBatch()
,handleOversizedBatch()
,performHttpRequest()
methodsflush()
to continue processing all batches/batch/
endpoint support for testingTest Coverage
Verification
Impact Assessment
Before Fix
After Fix
Migration Notes
payload_too_large
errors in logs to identify apps sending very large events🤖 Generated with Claude Code