-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ability to generalize over a HTTP request being async or not. #347
Conversation
Move AsyncHttp to CallbackfulHttp, and instead of inheriting from ThreadPoolExecutor, take any Executor as a parameter. Then, have both AsyncHttp and SyncHttp inheriting from it. AsyncHttp injects a ThreadPoolExecutor, as before, while SyncHttp injects an Executor that just executes Runnables right away, in the current thread. Thus, SyncHttp exposes an “asynchronous” (callbackful) interface while behaving synchronously. By using CallbackfulHttp, we can abstract over whether an operation is executed synchronously or asynchronously. To make this more user-friendly, AnySyncHttp wraps both a SyncHttp and an AsyncHttp, and lets you specify how to execute (class Execute) a request (class Request) and then getting its result synchronously or asynchronously (in another thread), as a method call result or passed to a callback, with the `sync` and `async` methods respectively. This design should make the Http class obsolete, once/if all the code that uses it is ported. It could also be left as a proxy to SyncHttp. (I did this after I renamed something in a `foo` method but forgot to do the same in a `fooAsync` method, causing a bug that was reported by a user.)
Plus, fix bug by which RTL6g3 was not implemented for the async version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few small comments in regards to naming & code comments, but otherwise looks good to me. Caveat is that I don't really know the Java code base that well so can't really comment on the overall design and how it fits in.
* Created by tcard on 28/04/2017. | ||
*/ | ||
|
||
public class AnySyncHttp { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we perhaps add a brief comment as to the purpose of this class for future us?
* Created by tcard on 31/8/17. | ||
*/ | ||
|
||
public class CallbackfulHttp<Executor extends java.util.concurrent.Executor> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is CallbackfulHttp
i.e. I am not clear on what the ful
after Callback
implies. Perhaps a high level comment on what this does is needed.
Overall I like this as a way of rationalising the duplication we had but my reservations at the moment are:
I'll be back with a few naming suggestions. |
If we get rid of I also don't love |
f782a9e addresses @paddybyers 's point 3. |
this.syncHttp = syncHttp; | ||
} | ||
|
||
public static class Request<Result> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see why this is static
and yet it has a anySyncHttp
member. I think you can remove that member and remove the static
declaration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done at 08f3c98.
} | ||
|
||
public Result sync() throws AblyException { | ||
final SyncExecuteResult<Result> result = new SyncExecuteResult<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I was looking at just having syncResult
and syncErr
members in the Result
type, instead of a new type to hold them, but what you have is a bit cleaner.
OK, I think we're heading towards a messy state where the existing That will potentially free up the Doing that refactor isn't trivial because we also have a lot of tests that rely on those primitive APIs. Anyway, if we're not doing that yet, how about renaming things as:
|
} | ||
|
||
public interface Execute<Result> { | ||
public void execute(CallbackfulHttp http, Callback<Result> callback) throws AblyException; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've getting a raw types warning here and elsewhere; it should be CallbackfulHttp<? extends Executor> http
.
The old Http class has been split up. We have now: * HttpCore implements the core primitives to do Ably-ready requests, ie. HTTP requests on the current thread that implement Ably auth, know how to reauthorize, and interpret Ably's error responses as ErrorInfos. It also has ancillary inner classes like Response, BodyHandler. * HttpScheduler, that implements operations on top of a HttpCore scheduled to an Executor. The API is asynchronous, but the underlying Executor may make its behaviour synchronous. We have both SyncHttpScheduler and AsyncHttpScheduler subclasses. * Http, which offers a higher level API to SyncHttpScheduler and AsyncHttpScheduler to help expose a synchronous or asynchronous API out of HTTP operations without duplicating code. * HttpHelpers, for helper methods used primarily in tests. It's also used in some non-test places that don't need the sync/async unification so I didn't bother converting them to use Http, which would make them more complex. * HttpConstants to hold constants like method names, header names, etc. PaginatedQuery/Result and AsyncPaginatedQuery/Result have now unified implementations too. Now both wrap BasePaginatedQuery/Result. To make this user-friendly some internal bridging classes boilerplate had to be added, unfortunately, but the end result should be simple enough. Tests have not been converted yet.
@paddybyers PTAL. I should have split 080a386 in at least a couple of steps but unfortunately I didn't, and since renaming and refactoring went hand in hand it's impossible to do after the fact. See the comments in 080a386 's commit message. |
This looks very good, thanks. Are you planning to update the tests in this PR? |
@paddybyers Yes, I'll do that tomorrow. |
There are some test that are failing, but I took a look and they didn't seem related to these changes. I'm raising an issue to fix them and merging this PR. |
This was something I had done in the push, but is independent of it.
Move AsyncHttp to CallbackfulHttp, and instead of inheriting from
ThreadPoolExecutor, take any Executor as a parameter. Then, have
both AsyncHttp and SyncHttp inheriting from it. AsyncHttp injects a
ThreadPoolExecutor, as before, while SyncHttp injects an Executor
that just executes Runnables right away, in the current thread.
Thus, SyncHttp exposes an “asynchronous” (callbackful) interface
while behaving synchronously.
By using CallbackfulHttp, we can abstract over whether an operation
is executed synchronously or asynchronously.
To make this more user-friendly, AnySyncHttp wraps both a SyncHttp
and an AsyncHttp, and lets you specify how to execute (class Execute) a
request (class Request) and then getting its result synchronously or
asynchronously (in another thread), as a method call result or passed
to a callback, with the
sync
andasync
methods respectively.This design should make the Http class obsolete, once/if all the code
that uses it is ported. It could also be left as a proxy to SyncHttp.
(I did this after I renamed something in a
foo
method but forgot todo the same in a
fooAsync
method, causing a bug that was reported bya user.)
As an example, I've refactored Channel.publish(Message[]). Luckily, I've found an instance of the class of errors this is supposed to fix: RTL6g3 was implemented for publish, but not for publishAsync. Now, as they share their code, is implemented by both.