15

I have a managed package that starts a batch job.

Right now, before attempting to start the batch it does a check like:

integer batchJobLimit = 5;
integer currentBatchCount = [SELECT count() 
    FROM AsyncApexJob 
    WHERE JobType='BatchApex' AND (Status='Processing' OR Status='Preparing')]; 
// Maybe Status='Queued' as well

if (currentBatchCount < batchJobLimit) {
    XyzBatchUploadOrderAttachment batchJob = new XyzBatchUploadOrderAttachment(parameters);
    integer batchSize = 1;
    Database.executeBatch(batchJob, batchSize);
} else {
    // Contingency plan to either reschedule starting the batch or give up in disgust 
}

The same pattern appears in Apex Batch job limits not clear Queued vs Scheduled and How to avoid hitting the concurrent Batch Apex limit with error: "Attempted to schedule too many concurrent batch jobs in this org"?

If the Apex Flex Queue Critical Update has been installed in the org running that managed package, then the batch job limit of 5 doesn't need to be enforced. Instead I could check if I'm going to hit the 100 queued jobs with the 'Holding' status limit.

How can I tell if the Apex Flex Queue is available in apex?
Maybe I just need to make the limit enforced by the code configurable.


Note that, as at Summer '15, the Apex Flex Queue isn't currently active in all orgs. It is a critical update, with an Auto-Activation date of 5/22/2015, that doesn't appear to auto activate.

Apex Flex Queue auto activation

5
  • I thought it went active with Summer 15. Shouldn't all orgs have it?
    – sfdcfox
    Commented Jul 22, 2015 at 3:30
  • 2
    is it not possible to use describeSObject on ApexAsyncJob and check the Status picklist value to see if Holding is a value and decide based on it if flex queue is enabled or not ? Commented Jul 22, 2015 at 4:28
  • @sfdcfox This question came about with a customers production org that didn't have flex queue activated and was hitting the batch limit exception. In several dev orgs the Apex Flex Queue is showing as a critical update that isn't auto-activating on the given date. So I don't think I can rely on it being available 100% of the time. Commented Jul 22, 2015 at 9:11
  • 1
    @VamsiKrishna Good idea. When I tried that I found that the "Holding" picklist value for Status appeared regardless of the critical update being active or inactive. Commented Jul 22, 2015 at 9:13
  • 2
    @Daniel, I tried an approach by trying a get request at the endpoint which displays Apex Flex Queue '/apexpages/setup/viewApexFlexQueue.apexp' And the weird observation - for both the orgs (one with feature active and one inactive) this URL gives same response. Then I went to the org with feature NOT active and appended the URL with '/apexpages/setup/viewApexFlexQueue.apexp' and guess what the Page Displays!! (Note: I search 'Apex Flex Queue' in quick find to conclude if feature is active or inactive) Commented Jul 29, 2015 at 5:48

1 Answer 1

7
+100

Building on the approach recommended by @Amit

/**
* @author Scott Covert
* @date 8/3/2015
* @description Salesforce Utility Class
*/
public with sharing class SFUtils {
    /** 
    * @author Scott Covert
    * @date 8/3/2015
    * @description Determines if the current org has the Apex Flex Queue enabled
    * @return Boolean A boolean value representing whether or not the Apex Flex Queue is enabled for the current org
    */
    public static Boolean detectApexFlexQueue() {
        String sfURL = System.URL.getSalesforceBaseURL().getHost();
        PageReference pageRef = new PageReference('https://'+ sfURL +'/apexpages/setup/viewApexFlexQueue.apexp?retURL=%2Fui%2Fsetup%2FSetup%3Fsetupid%3DJobs&setupid=ApexFlexQueue');
        String pageRefBody;
        if (Test.isRunningTest()){
            pageRefBody = '';
        }
        else{
            Blob pageRefBlob = pageRef.getContent();
            pageRefBody = pageRefBlob.toString();
        }
        // Count # of times 'setupHighlightLeaf' appears in body
        Integer highlightLeafMatches = pageRefBody.countMatches('setupHighlightLeaf');
        // In orgs without the Apex Flex Queue enabled there should be no highlighted leafs
        // meaning there should only be one match from the HTMLTreeNode initialization
        if (highlightLeafMatches<=1){
            // Apex Flex Queue is not enabled
            return false;
        }
        else {
            // Apex Flex Queue is enabled
            return true;
        }
    }

}
3
  • As best as I can tell this does appear to work. I say this as I can no longer see the "Apex Flex Queue" critical update in orgs that don't have it enabled. These is no Apex Flex Queue setup option, so I assume it isn't active. Having to use a callout also limits it's usefulness for areas like trigger contexts. Commented Aug 5, 2015 at 1:23
  • Agreed; not the most elegant solution but it should do the trick. You could also make the detectApexFlexQueue method asynchronous and use it within your package's post install script. The return type could be changed to void and it could save the result to a custom setting (or a custom metadata type record once this feature is delivered) for future reference. The callout would only need to be run once and execution context wouldn't be an issue, but your app would require the remote site setting to be set up before installation. Commented Aug 5, 2015 at 13:54
  • After thinking about this further I realized it would be better to make use of the PageReference.getContent() method to avoid the HTTP request altogether. Though still relying on clunky screen scraping this would eliminate the need for creating a remote site setting. In addition to being ignored during testing with Summer '15 the getContent() method behaves as a callout so it's still probably a good idea to add this to your package's post install script. I've updated my answer accordingly. Commented Aug 7, 2015 at 19:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .