I'm trying to find a good design pattern, or perhaps series of patterns, for injecting error handling and retry handling when getting data from a webservice.
For instance, I have:
do {
//get the data here
data = Datagetter.getMyData(request)
if(data.hasError())
{
//handle error
}
} while(shouldRetry());
And I am trying to figure out a way to inject the mechanism the discovers and deals with any error, as well as the mechanism that handles how retrying works (should I wait? have I retried enough? should I modify a request parameter? etc).
I would guess I am not the first person faced with this, and there is a way to do this I just haven't discovered yet.
I have looked into chain-of-responsibility and strategy as possible solutions, but I can't seem to quite finagle them to work.
4 Answers 4
What language are you using? Depending on the language(synchronious, asynchronious) you will have different solutions.
If it is JavaScript, promise is indeed the way to go. Promises in JavaScript
If it is something like C#, you probably don't want to have a loop like you indicated, because you will be blocking the thread. In that scenario, I would look into setting up queuing system in combination with Command Design Pattern:
Using queue you can send failed messages into the retry queue and retry them in the order they were submitted, potentially with some delay.
-
It's not coincidence ;D World is small :)Alexus– Alexus2015年06月22日 20:24:23 +00:00Commented Jun 22, 2015 at 20:24
-
The language is PHP- so not only is it synchronous, it is not threaded. Fundamentally, blocking is unavoidable without getting into using extra process. The truth is, however, blocking isn't really a problem here... the problem is being able to inject different mechanisms to handle errors and retries...MirroredFate– MirroredFate2015年06月22日 22:20:56 +00:00Commented Jun 22, 2015 at 22:20
-
Blocking for single call vs blocking for multiple retries is 2 different issues. If the only problem here is how to inject different error handling, strategy is exactly the pattern you need. You can also try State Pattern - but it's a bit of an overkill, not quite the case you can use it for. The idea that I am trying to suggest from the state pattern is that the objects themselves are aware of the logic that needs to happen when a certain(generic) trigger is called. So as far as your function is concerned, it needs to call object.handleError() method every single time there is an error.Alexus– Alexus2015年06月22日 22:39:54 +00:00Commented Jun 22, 2015 at 22:39
There are several things to consider here. It is worth reading up on the HTTP specification, specifically about idempotent rules, and to also consider a RESTful style of webservice interface.
In short, if you implement a webservice with GET or HEAD, then in theory it should be safe to call multiple times with the same parameters, but webservices that are implemented as POST, PUT or DELETE should only be called once, and if they fail then it should not be retried without consideration to the consequences of multiple requests.
The theory is that if you are GET'ing a resource, multiple gets to the same resource should be logically equivilent, and that there are no server state consequences for multiple GET requests for the same resource. If the verb is a PUT, POST or DELETE then it is expected that the request could change the state of the server data, and so multiple / repeat requests are likely to have unwanted side effects.
To handle retries well, requires you to consider the error that occured. Retrying an error caused by a 404 may be handled differently from a tcp timeout error, or a 301 redirect, and to understand what that means in the context of this URL.
-
1Handling different types of errors and determining how/when to retry is exactly the problem I am facing. The question is, how can I design a loosely coupled system for these issues?MirroredFate– MirroredFate2015年06月22日 22:22:58 +00:00Commented Jun 22, 2015 at 22:22
Have you looked into Aspect oriented programming ?
https://en.wikipedia.org/wiki/Aspect-oriented_programming
Maybe it helps ?
An other idea would be to use an abstract factory to return the concrete implementation that you need to handle the error on runtime.
I'm afraid you need to code the retrying logic yourself. However, this can be separated from the actual service call by utilizing the Proxy pattern. The RetryingProxy wraps the actual service and implements the error handling and retrying policy you need.
Explore related questions
See similar questions with these tags.
promise
that will be resolved more than once if required. Thepromise
success callback is only executed if the resource is resolved during any attempt (only once), but theerror
callback is only called after all attempts fail.