(community wiki)
@future (valid for triggers and visualforce)
From trigger or VF context you can have up to 10 calls to @future
& each of them has a separate context that allows 10 callouts. So you can get up to 100 callouts from a trigger (that itself you're guaranteed will not contain more than 200 records if it's saved with API > 20.0, capped at 100 otherwise) or 10+100 in VF. Not bad. Before you decide to abuse it - consider the fact that there's a 24 hour rolling limit on @future
invocations and that multiple callouts to same endpoint might also throw an error. From governor limits page:
A callout request is limited to a maximum of 20 simultaneous requests
to URLs with the same host. The host is defined by the unique
subdomain for the URL, for example, www.mysite.com and
extra.mysite.com are two different hosts. This limit is calculated
across all organizations that access the same host. If this limit is
exceeded, a CalloutException will be thrown.
Batch Jobs
Batch jobs let you process many records (up to 50 M) with whatever granularity you wish (if you don't specify it, granularity will be 200). Essentially you decide which records you want to work on, you get a fresh context & governor limits for each chunk of data you're processing and then at the end of the batch job you can send an email, kick-off another batch etc. They're great for background processing tasks.
In batch jobs you can specify an optional scope parameter. If you really need this, the batch job may even be instructed to process 1 record at a time (and again - each execute()
will let you make 10 callouts). That is - if you'll make sure that the batch class implements Database.AllowsCallouts
;) Read more about Database.executeBatch
if you want to take this path.
Essentially:
public class MyBatchableClass implements Database.Batchable<sObject>, Database.AllowsCallouts{
// definitions of start(), execute() and finish() as in any batch
}
// and then in code that fires it (scheduled class? something that happens
// after user clicks a button? you use
Database.executeBatch(new MyBatchableClass(), 1);
// instead of
// Database.executeBatch(new MyBatchableClass());
Javascript-related solutions
You can jump back and forth in the context. Build a Visualforce page that would process N records at a time, return to the browser, issue a next call that processes another N...
You know your data best - N can be a fixed number or maybe you'll just want to compare output of Limits methods:
if(Limits.getCallouts() == Limits.getLimitCallouts()){
return 'I\'m not done yet';
}
This is best suited in environment where user expects some kind of progress report like "X out of Y records processed". If you're after a fully automated background solution that can't be interrupted by user closing the tab for example - go for one of previous two.
"The call" can be Javascript that hits Apex code in form of webservice call (in ajax toolkit - for example a button on list view that processes selected records), @RemoteAction , actionFunction etc.
The basic definition is Setup and Non-Setup objects can not be updated together in single transaction. Asynchronous transaction can not invoke other asynchronous transaction.
However, one of the approach which can be scaled with this existing solution is "Batch chaining"
As yo have already updated the Setup object in execute()
method. Now just keep that information in stateful
batch.
Pass that information in a new Batch which would be invoked from finish()
method proving all Ids
of accounts which require new sharing update. Don't form such bulk records in finish.
In chained batch, you can control size of batch to manage future calls limit.
Note: This would increase process time but solution will become feasible to any number of records.
Best Answer
I follow a pattern known as the Service Layer. If you can elaborate on your 'function a' signature and needs I can provide some more specific examples for you, but this should give the general idea.
Service Layer, “Defines an application's boundary with a layer of services that establishes a set of available operations and coordinates the application's response in each operation.” Martin Fowler / Randy Stafford, EAA Patterns
In an Apex world it essentially encapsulates all your applications process logic in single layer that is agnostic of the callers, be they Batch Apex, Future, Apex Triggers, VF Controllers etc.... If you follow this practice closely you can even turn such things into a public Apex or REST API for your application quite easily.
This is an example of such a service method.
This is then consumed by a VF controller like so...
Or a Batch Apex class like so...
There are a few other examples in the article linked below.
Designing a Service Layer. In either case the transactional scope and containment of the logic is managed entirely by the service layer, the callers responsibility is only to pass in the correct information, interpret responses and handle any Apex exceptions accordingly. Note also that service methods take bulkified parameters to match most callers needs and to better enforce bulkifcaiton within the service logic itself.
Further Reading. You can read more about this sample code, the guidelines and and other Apex Enterprise Patterns link within here. I'd be keen to know more about the signature of function A so I can perhaps taylor this answer a bit further for you.
Hope this helps!