Skip to content

getHistory bulk read: trim per-instance row buckets at MAX_HISTORY_ROWS during scan (heap efficiency) #220

Description

@madmax983

Summary

Heap-efficiency improvement in WorkflowHistoryRead.getHistory(List<Id>) (bulk read). Surfaced by Codex on PR #216. Severity P2 — deferred from that PR per the campaign's "only verified P1s hold the gate" rule. Behavior is correct today (right results, no throw for realistic input); this is an efficiency/robustness hardening, not a bug.

Context

The bulk scan in queryRowsByInstance (~WorkflowHistoryRead.cls:318) accumulates every scanned row into a per-instance bucket, ordered Workflow_Instance__c ASC, CreatedDate ASC, Id ASC, under a single shared scanLimit. The StepHistory projection later keeps only the earliest MAX_HISTORY_ROWS (500) rows per instance, and the authoritative totalCount comes from the grouped COUNT() in realStepTotals — not from the scanned rows.

Note the scan SELECT no longer includes any LongTextArea/blob fields — Error_Details__c / Input__c / Output__c / Captured_Values__c were removed, so scanned rows are lightweight scalar SObjects. This significantly reduces the heap pressure versus the earlier payload-carrying scan.

Before / After

Before: A bulk getHistory(List<Id>) call where one requested instance has far more than MAX_HISTORY_ROWS (500) executions and sorts first can accumulate up to the whole scan budget of SObjects in one heap bucket before the StepHistory projection discards all but 500. Under enough volume (a single hot instance with tens of thousands of executions in one bulk call), this can approach Apex heap limits even though rows are now blob-free.

After: During the bulk scan accumulation loop (~WorkflowHistoryRead.cls:318), stop adding rows to a per-instance bucket once it reaches MAX_HISTORY_ROWS. The authoritative totalCount already comes from the grouped COUNT(), so trimming does not affect totalCount or isTruncated — a scan-starved / over-cap instance is still reported with its true total and isTruncated = true. Only the redundant rows that projection would discard anyway are dropped, capping the retained heap per instance at the cap.

Proposed fix

In the accumulation loop, skip bucket.add(row) once bucket.size() >= MAX_HISTORY_ROWS. No change to totalCount (grouped COUNT is authoritative) or to the truncation flag.

Provenance

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions