Skip to content

Fix #1026: handle DELETE_OPERATION_TOO_LARGE in LogBatchPurger - #1030

Draft
RajPabnani03 wants to merge 1 commit into
jongpie:mainfrom
RajPabnani03:bugfix/1026-logbatchpurger-partial-delete
Draft

RajPabnani03 wants to merge 1 commit into
jongpie:mainfrom
RajPabnani03:bugfix/1026-logbatchpurger-partial-delete

Conversation

@RajPabnani03

@RajPabnani03 RajPabnani03 commented Oct 1, 2026 •

Copy link
Copy Markdown

Summary

Fixes #1026 — LogBatchPurger.execute() performed a single all-or-none delete on the batch scope, so when the DML cascaded to too many related records at once (DELETE_OPERATION_TOO_LARGE on LogEntry__c or FeedItem records), the entire batch failed with an unhandled exception and none of the scope was purged.

LogBatchPurger now wraps the delete in hardDeleteRecords(scopeRecords) and, on a System.DmlException, retries via hardDeleteRecordsWithPartialDeletes(scopeRecords):

List<Database.DeleteResult> deleteResults = LoggerDataStore.getDatabase().deleteRecords(scopeRecords, false);
// successful rows -> emptyRecycleBin(deletedRecords)
// failed rows      -> Logger.error(LogMessage, failedDeleteResults) when EnableLoggerSystemMessages is on
  • Records that can be deleted are still purged within the same execute() call — a single record with an oversized cascade no longer blocks the rest of the batch.
  • Records that genuinely can't be deleted produce handled Logger.error entries (gated on EnableLoggerSystemMessages, matching the class's existing convention) instead of "Failed to process batch" unhandled-exception emails; they're re-attempted on the next scheduled run.
  • Adds a virtual emptyRecycleBin(List<SObject>) method to LoggerDataStore.Database (and routes hardDeleteRecords through it) so the whole delete chain stays mockable; hardDeleteRecord/hardDeleteRecords signatures are unchanged.

Adds it_should_partially_delete_records_when_batch_delete_throws_dml_exception to LogBatchPurger_Tests, using a new MockPartiallyFailingDatabase that throws on the all-or-none delete and returns mixed results on the partial delete.

Testing

Verified in a scratch org (Enterprise Edition, API v67): full nebula-logger/core deploy succeeded and the complete local Apex suite passed — 1260/1260 tests, 93% org-wide coverage — including the new it_should_partially_delete_records_when_batch_delete_throws_dml_exception (mocked LoggerDataStore.Database covering the fallback path).

A batch delete can fail when the DML cascades to too many related
records at once (e.g., DELETE_OPERATION_TOO_LARGE on LogEntry__c or
FeedItem records), which caused the whole LogBatchPurger job to fail
with an unhandled exception and prevented deletable records from being
purged.

On a DmlException from the all-or-none delete, LogBatchPurger now
retries with a partial delete: successfully deleted records are still
purged (and removed from the recycle bin), and any records that still
fail are logged as errors when system messages are enabled. The job
then continues instead of failing the batch.

Also adds a virtual emptyRecycleBin() method to LoggerDataStore.Database
so the full delete chain remains mockable in tests.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Handle DELETE_OPERATION_TOO_LARGE exception

1 participant