I'm developing an integration that makes an HTTP call to an external system from SFDC. The entry point for this code is an opportunity trigger. After a user updates the opportunity, my trigger fires, and calls a future method to make the HTTP request. This works just fine.
However, I ran into a situation where there's code that runs on the quote object and programmatically updates opportunities via a future method. This in turn fires my code, which errors with:
execution of AfterUpdate caused by: System.AsyncException: Future method cannot be called from a future or batch method
I tried to account for this by using system.isBatch() || system.isFuture and if this evaluates to true, call a non-future version of my function that makes the HTTP callout. When I tried this, though, I got:
System.CalloutException: Callout from triggers are currently not supported.
What's the proper way to architect this so that my callout is allowed regardless of whether the opportunity is updated normally, from a future method, or from a batch?