Problem
I have to build a reliable integration. This means that external callouts should be delivered even if the remote SOAP webservice is down. (when the ws is online)
The idea is to keep the callouts messages if the webservice is down and will retry to send them after some time.
Background
Thinking on the solution I noticed some important facts:
- The order of sent messages should be respected
- There are more than one external method
- The sent record data should be the current data, not the data when the callout was trigger.
- I have a dummy remote method to check the WS availability
- The response should be asynchronous (CallBack WS)
- I can't use outbound messages
Approach
My approach is to insert the message to send into a queue and consume it from a scheduled job. The stored message will have:
- recordId in order to get the current data
- message type in order to know which remote method will be called
- extra data (JSON serialized) to add some useful context
- timestamp
When the cron is executed I planning something like this:
kill schedule // to avoid more than one consumer
msgs = [select from queue order by timestamp asc limit 200] //limit to ensure bulk-safe
if !msgs.empty
if WS.isAvailable // check the remote webserver
for(m:msgs)
switch m.type
case typeA
ws = new WSA(m.id,m.extraData); //instance the WS wrapper
case....
ws.send(m); // I'll explain this later
consumed.add(m); // to remove later on queue
delete consumed
schedule job
WSA, WSB, .. will extends from WS
class WS{
abstract getData(); // this will retrive the needed data using the record Id
abstract callRemote(); // this will instance and call the remote ws
public static send(){
this.getData();
this.callRemote();
}
}
This is a draw to illustrate the idea
Questions
- Can you see any problem on my approach?
- Have this approach any governor limitation? It is planned for Unlimited
- Is out there any better/simpler approach to build a 99.9% reliable integration (SF > WS SOAP) ?
- Could you suggest any improvement?
Update
I've discovered a possible problem: if queue.size() > 200 (I put that limit for soql limitation during the process) in the scheduled time. The queue keeps growing and never will be totally consumed.
How could I solve this?