2

My post-install script is failing on just one sandbox, and I can't figure out why. It has been working successfully for more than a year, on a number of different orgs, but this one fails. When it fails, I don't get any other details beyond the simple message "The post install script failed."

Here's my script:

public without sharing class ApiInstallHandler implements InstallHandler, UninstallHandler {

    public void onInstall(InstallContext context) {
        ApiSentinelRunLaterScheduled.scheduleSelf('');
    }

    public void onUninstall(UninstallContext context) {
        ApiSentinelRunLaterScheduled.cancelSelf('');
    }
}

And then, the dependent class:

// Sweeps up any sentinels that we couldn't start because they were
// triggered from a Batch or Future context. Time-based workflow
// would make more sense, but cannot be added to a managed package
public class ApiSentinelRunLaterScheduled implements Schedulable {

    private static String jobName = 'API Sentinel Run Later';

    public void execute(SchedulableContext SC) {
        NebulaApiWorker.runLaterWorkers();
    }

    public static void cancelSelf(String namePrefix) {
        List<CronTrigger> existingToCancel = [SELECT Id, CronJobDetail.Name, State 
                                              FROM CronTrigger 
                                              WHERE CronJobDetail.Name LIKE :namePrefix + jobName + '%'
                                              AND CronJobDetail.JobType = '7' 
                                              AND State != 'DELETED'];

        for(CronTrigger t : existingToCancel) {
            System.abortJob(t.Id);
        }


    }  

    public static void scheduleSelf(String namePrefix) {
        cancelSelf(namePrefix);

        ApiSentinelRunLaterScheduled asr = new ApiSentinelRunLaterScheduled();

        // every 15 minutes
        for(integer i=0; i < 4; i++) {
            String minutes = '' + (i*15);
            System.schedule(namePrefix + jobName + ' (' + minutes + ')', '0 ' + minutes + ' * * * ?', asr);
        }
    }        
}

Any ideas about how I can attack this? One obvious thing is to make a version of the package with a try..catch and then log the errors. But is there anything else to try before I go through that laborious process?

7
  • Code should work. The only difference between orgs (if it works for some and does not work for some) is the data, in your case - CronTrigger table. Try clearing it in the problematic org, also, try running this code manually on the org Commented Aug 31, 2017 at 4:37
  • Thanks, but I'd already checked the CronTrigger table, and I tried running the body of cancelSelf() in the dev console - neither has helper. I can't run the rest of it because the classes are not global, and I don't want to make them permanently global just for this. I think I'm going to have to add some logging and see if that helps :(
    – Aidan
    Commented Aug 31, 2017 at 8:19
  • Logging is always good. But can't you run the rest of the code from executeAnonimous? Commented Aug 31, 2017 at 8:21
  • It's not global, so nope, can't run it.
    – Aidan
    Commented Aug 31, 2017 at 8:22
  • I mean just run this: // every 15 minutes for(integer i=0; i < 4; i++) { String minutes = '' + (i*15); System.schedule(namePrefix + jobName + ' (' + minutes + ')', '0 ' + minutes + ' * * * ?', asr); } from Execute Anonimous in dev console Commented Aug 31, 2017 at 8:24

1 Answer 1

1

I've logged the error during the post-install and it is:

The Apex job named "API Sentinel Run Later (0)" is already scheduled for execution. Class.Nebula_Api.ApiSentinelRunLaterScheduled.scheduleSelf: line 34, column 1 Class.Nebula_Api.NebulaApiInstallHandler.onInstall: line 5, column 1

So, I ran this in the dev console:

List<CronTrigger> triggers = [SELECT Id, CronJobDetail.Name, State FROM Crontrigger ALL ROWS];

for(CronTrigger ct : triggers) {
    System.debug(ct.CronJobDetail.Name + ': ' + ct);
}

Which gives the following debug output (just one row):

09:46:39:009 USER_DEBUG [4]|DEBUG|pi_Async_Request_Scheduler-1503878362374: CronTrigger:{Id=08e4E0000074VEvQAM, CronJobDetailId=08a4E0000074W5VQAU, State=WAITING}

Which seems to mean that there's a phantom instance of the scheduled job already recorded in the sandbox. I can't find it, so I can't cancel it. Which looks like an interaction between two known issues:

  1. AsyncApexJob row for Scheudled Apex Jobs is not sandbox copied https://success.salesforce.com/issues_view?id=a1p300000008Ym6AAE
  2. Scheduled batch "already scheduled"

So, the solution is to throw the current time in ms on to the end of the scheduled job name. Interestingly, if you look at the debug output from what I tried above, you can see that Pardot are doing this for their scheduled job!

2
  • 4
    How did you manage to log the error and see those logs?
    – zaitsman
    Commented Sep 11, 2019 at 0:18
  • I am super curious about that too! As far as I know there is no way to see debug logs generated by a managed package in the post install script. Commented Apr 13, 2022 at 22:23

You must log in to answer this question.

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