I wanted to know whether this is the standard way to invoke a schedulable class?
Many ISVs include a Configuration page, which is just a Visualforce page configured as a Home Page Custom Link and configured as the Managed Package's configuration link. From there, they usually have a button or link to call some Apex Code that performs the scheduling. It's more user friendly than asking admins to run code.
This class would be part of a managed package and I want to invoke the scheduled jobs when the package gets installed without having to go and run anonymous apex. Is that possible?
You can use an InstallHandler, which allows you to run code upon install. Normal asynchronous rules apply, so be aware of governor limits, and do consider trying it out in an ISV trial org before you give it to your customers.
The interface is a single function that accepts an InstallContext object:
global interface InstallHandler {
void onInstall(InstallContext context)
};
You implement as you would any other interface:
global class OurPackageInstallHandler implements InstallHandler {
global void onInstall(InstallContext context) {
// Do stuff here
}
}
The InstallContext has the following features:
global interface InstallContext {
ID organizationId();
ID installerId();
Boolean isUpgrade();
Boolean isPush();
Version previousVersion();
}
As you can see, it gives you some basic information about any prior context and some basic organization information. In onInstall
, you can go ahead and schedule your class.
Do I need to consider race conditions here. Ideally there would be only one job running at a time but Apex Schedular documentation mentions that "Actual execution may be delayed based on service availability." So can I have two instances running at the same time?
In theory, yes, you could. In practice, it's incredibly rare that the scheduler is so delayed that multiple instances would be running at once, especially since the scheduler prefers to load balance over all orgs' jobs, which means that you should rarely experience this problem. I'd say use "FOR UPDATE" on any records you need to query, which will row-lock relevant records to avoid duplicate processing in those rare circumstances. It should be okay in most cases.
Anything else I need to be aware of while creating schedulable jobs in apex.
You main problem is going to be that there's no convenient way to specify "every five minutes" as an option. You can only schedule hourly at minimum. This means you're going to have to deal with either "suicide scheduling", where your job aborts itself and schedules itself for five minutes later, or you're going to have to schedule 12 different jobs so they're staggered five minutes apart. Now, we do get 100 scheduled jobs, but most orgs are probably already pushing that limit, so you'll need to consider if that's the best idea.
Also, remember that jobs do not execute precisely at the scheduled second. I'm not sure what you're doing, but you're likely to miss records if you use time stamps/audit trail fields. You may have to resort to using some sort of queued job Custom Object to keep track of where you left off, or perhaps via Custom Settings. Not being able to depend on the exact start time means you should take extra care.