apex-enterprise-patterns / fflib-apex-common

Common Apex Library supporting Apex Enterprise Patterns and much more!
BSD 3-Clause "New" or "Revised" License
907 stars 515 forks source link

Cyclic Triggers #86

Closed Autobat closed 8 years ago

Autobat commented 9 years ago

I'm working on a very large implementation using the platform and we have a number of cases where the business logic requires some APEX rollups and processing of related tables.

My usual method is to use a singleton to control if a trigger has run previously and have it gracefully return and thus stop any cyclic triggers from running away from each other or causing unwanted handlers to run and take up resources that just aren't needed.

As this code is now being repeated in a number of different Domain classes i was thinking of enhancing the fflib_SObjectDomain such that we have process controls within each handle[event] method.

So a few questions before I start:

1) Do you see this as a valid enhancement for the branch 2) if yes, how flexible do we want it?

Is it a straight, this has run before don't run it again per event per object, or, You can set how many times an objects trigger handler will run e.g. unbounded, once, twice etc?

Feedback is welcomed,

Chris

afawcett commented 8 years ago

Firstly Chris, soooo sorry for the late reply, just about got over the DF hump fallout as i call it! ;-) You might be interested in the trigger state feature described in my blog here. The stack of invocations is not currently exposed but could be if we have a good use case here.

afawcett commented 8 years ago

Any thoughts @Autobat would the trigger state feature work for you, perhaps with a few tweaks?

Autobat commented 8 years ago

Hey Andy and the team,

Had a disastrous week with the flu sadly. I'm hoping to get some headspace this weekend to take a crack at this once I have fixed up the inbox from a week off. I have taken a look at the trigger state and I think we can get a nice approach for this that can be utilised by all.

I should be able to pen an approach for us to discuss soon,

afawcett commented 8 years ago

Ah sorry to hear that, glad your feeling better, look forward to reading your ideas. :+1:

Autobat commented 8 years ago

Hey @afawcett

I have a working version, however, a weird issue.

In the test harness where we are passing an instance of the subclass to the trigger hander e.g. fflib_SObjectDomain.triggerHandler(fflib_SObjectDomain.TestSObjectStatefulDomainConstructor.class);

it is causing a very strange null pointer in a map where I store the Type vs. a class to track which methods are enabled.

Need to do some more investigation before i flip this over the SFDC support - have you seen anything similar?

private static Map<Type, TriggerEvent> TriggerEventByClass;
private static boolean isTriggerEventEnabled(Type domainClass)
{
    System.Debug(domainClass);  // not null
    System.Debug(TriggerEventByClass.keySet()); // no null pointer

    if(!TriggerEventByClass.containsKey(domainClass))    // this line fires a null pointer
    {
        TriggerEventByClass.put(domainClass, new TriggerEvent());
    }
    ... do stuff
}

Above is a snippet of the problem. Basically, if the domainClass is a subclass as we do in the test harness the System.Debug(...) lines show the correct values but the very next line gives a null pointer.

Autobat commented 8 years ago

p.s. it works when you pass it a top level class e.g. Accounts.class just only when it is a sub class it has the problem

tfuda commented 8 years ago

Just a thought, but is there by chance, a name collision with some other Apex class or static variable that happens to have the same name? Perhaps fully qualify your reference to TriggerEventByClass like ParentClass.TriggerEventByClass.

Autobat commented 8 years ago

Ah i wish it was as complex as that. All i needed was to step away from the computer for a bit and it was a stupid mistake on my end. I was referencing Trigger. e.g. isUpdate in my code which doesnt exist when we are mocking in the harness :)

SchoolBoyError

Autobat commented 8 years ago

Created pull request https://github.com/financialforcedev/fflib-apex-common/pull/98

Sorry, i couldn't work out how to put the pull request here :/

Feedback welcomed on the approach

afawcett commented 8 years ago

Merged the PR, thanks for the submission! :+1: