-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Implemented thread-safe CookieStore #1494
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
Conversation
What have you done with the poms??? Please revert. |
This reverts commit 094faaa
@slandelle Done :) |
import java.util.concurrent.locks.ReentrantLock; | ||
import java.util.stream.Collectors; | ||
|
||
public class ThreadSafeCookieStore implements CookieStore { |
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.
please make final
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.
Ok
public boolean remove(Cookie cookie) { | ||
try { | ||
lock.lock(); | ||
return cookieJar.entrySet().removeIf(v -> v.getValue().cookie == cookie); |
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.
You mean equals
, not ==
.
Then, I suspect the predicate is wrong and one want to remove by (domain, path, name, value) and don't take other fields into account. Letting user pass a predicate instead would probably be better.
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.
No, I intentionally wanted to remove by reference because intention is to modify cookie jar using Cookie
objects returned by .getAll()
or get()
methods. This is similar to what java.net.InMemoryCookieStore.remove()
does.
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 think this is specific to your use case, Other people might want a different strategy, eg drop all cookies for a given domain. So it might be best to change the parameter to a Predicate<Cookie>
.
if (!requestUri.getPath().isEmpty()) | ||
return requestUri.getPath(); | ||
else | ||
return "/"; |
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.
Please use ternary operator ?
.
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. Forgot it exists in Java after years in Scala :)
final boolean[] removeExpired = {false}; | ||
List<Cookie> result = cookieJar | ||
.entrySet() | ||
.parallelStream() |
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.
Why do you need a parallelStream here? Looks overkill, all the more as most users would only have a few cookies at the same time.
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.
Not really. Let me downgrade then.
public List<Cookie> getAll() { | ||
try { | ||
lock.lock(); | ||
final boolean[] removeExpired = {false}; |
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.
Why do you need an array instead of a mutable boolean?
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.
Variables used in lambda have to be final or effectively final so you can't modify them. Sad limitation of Java8.
* @param requestFilters {@link List<RequestFilter>} | ||
* @return {@link FilterContext} | ||
*/ | ||
public FilterContext<T> preProcessRequest(List<RequestFilter> requestFilters) throws FilterException { |
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.
Unused, please revert
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
import org.asynchttpclient.AsyncHandler; | ||
import org.asynchttpclient.AsyncHttpClientConfig; | ||
import org.asynchttpclient.HttpResponseStatus; | ||
import org.asynchttpclient.cookie.CookieStore; |
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.
Please revert changes here
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
|
||
final boolean[] removeExpired = {false}; | ||
|
||
List<Cookie> result = cookieJar.entrySet().parallelStream().filter(pair -> { |
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.
why parallelStream?
|
||
private List<Cookie> get(String domain, String path, boolean secure) { | ||
|
||
final boolean[] removeExpired = {false}; |
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.
why an array?
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.
Limitation of Java8 lambdas.
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.
Damn. OK. I guess a array of booleans of size 1 is smaller than an AtomicBoolean.
public class ThreadSafeCookieStore implements CookieStore { | ||
|
||
private Map<CookieKey, StoredCookie> cookieJar = new HashMap<>(); | ||
private ReentrantLock lock = new ReentrantLock(); |
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 are the pros of this HashMap
+ ReentrantLock
? Why not a ConcurrentHashMap
?
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 actually used ReadWriteLock first but then thought it's overkill so I replaced it with simpler class. I can use ConcurrentHashMap if you prefer that.
Made minor modifications that you've requested. |
public final class ThreadSafeCookieStore implements CookieStore { | ||
|
||
private Map<CookieKey, StoredCookie> cookieJar = new HashMap<>(); | ||
private ReentrantLock lock = new ReentrantLock(); |
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.
Comments were lost when you pushed. Could you please change to a CHM?
} else { | ||
// rfc6265#section-5.1.4 | ||
if (!requestPath.isEmpty() && requestPath.charAt(0) == '/' && requestPath.lastIndexOf('/') > 0) | ||
return requestPath.substring(0, requestPath.lastIndexOf('/')); |
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.
Not exactly my commit: you're computing lastIndexOf('/') twice :)
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.
Crap, my bad. I pushed the fix.
Updated definition of |
@@ -151,4 +151,4 @@ public Request getRequest() { | |||
} | |||
} | |||
|
|||
} | |||
} |
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.
Please restore last empty line
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 :)
Almost there :) |
@unoexperto Great! One last thing: could you please squash your commit into a single one and add a commit message such as described here: https://netty.io/wiki/writing-a-commit-message.html? |
Took me an hour to create and apply single patch :( Not sure how to amend this PR so I create new clean one #1495 |
|
@slandelle I copied your unitests from gattling too. I kept extra methods in
CookieStore
besidesadd
andget
you and I discussed. I actively useremove
,getAll
andclear
because I heavily use AHC for web scraping and serialize and manipulate cookies between sessions while maintaining connection to HTTP server.If everything looks good to you could you please push new build to Maven ? I need it in production :)
Thanks!