Is there a way for @future
annotated method to start execution before the synchronous request which invokes it has completed.
In other words, do I have some guarantees that the timing will look like this:
-start sync---call future---end sync---execute future->
instead of like this:
-start sync---call future---execute future---end sync->
I couldn't find the execution order guarantees in the documentation, although Future Methods states:
The reason why sObjects can’t be passed as arguments to future methods is because the sObject might change between the time you call the method and the time it executes. In this case, the future method will get the old sObject values and might overwrite them. To work with sObjects that already exist in the database, pass the sObject ID instead (or collection of IDs) and use the ID to perform a query for the most up-to-date record.
This can be read as saying that the future is not queued at the end of the transaction, otherwise Salesforce could guarantee that the sObject sent is the most recent version. And since it's queued during the transaction, it might imply that it also might execute and complete while the synchronous transaction is still running.
On the other hand, Does Database.rollback(savepoint) work with the Update method? implies that futures are only fired after the transaction completes:
Invoking Database.rollback not only rolls back inserts, but it goes much, much further. [...] It also rolls back:
Calls to @future methods. Any methods called within the rolled back part of your script will not be invoked (also why @future doesn't start until your script completes).