A customer of mine is seeing partial execution of an Apex Function.
In the Function, they need to Insert/Update multiple objects.
Insert new Contact(...);
...
Insert new Cust_object__c(...);
In the second insert, they are encountering an error, but the Contact from the first insert is remaining, and I am trying to understand why.
With how I am reading the documentation around transaction Control, because the entire apex isn't finishing, the entire transaction shouldn't be committed.
Transaction Control Documentation
If the entire request completes successfully, all changes are committed to the database. For example, suppose a Visualforce page called an Apex controller, which in turn called an additional Apex class. Only when all the Apex code has finished running and the Visualforce page has finished running, are the changes committed to the database.
I understand that I can create a save point, and roll back once the error is encountered, but I am trying to understand the Apex execution rules.
Shouldn't all transactions within the function be rolled back if there is an error encountered, even DML statements that completed successfully?
Update:
I have confirmed that there isn't any code that is captured in Try/Catch blocks. All DML operations are using DML "Insert" and not Database.insert(xxx,false). The underlying error stemmed from hard coded IDs that referenced objects that were deleted, but I still need to understand why only part of the transaction was rolled back.
The execution stack:
Lightning component Calls Apex Controller @AuraEnabled Function
Apex method Inserts Contact
Apex method Inserts Custom Object
Before Insert Trigger
After Insert Trigger
Apex Custom Trigger Helper Class
Insert Opportunity
Before Insert Trigger
After Insert Trigger
Apex Custom Opportunity Trigger
(Error Occurs)
The Insert for the Contact remains. The Insert of the Custom Object and the triggered Insert of the Opportunity are both rolled back.
Why wouldn't all DML actions in the Controller method be rolled back?