-
Notifications
You must be signed in to change notification settings - Fork 20
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 Resource-based simple constructors #1015
base: series/0.9
Are you sure you want to change the base?
Changes from 1 commit
33ca4c9
0384cb9
2b71c70
c5f098c
0f8e981
4cd2f14
3d2262d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -243,10 +243,28 @@ object JdkHttpClient { | |
* [[cats.effect.kernel.Async.executor executor]], sets the | ||
* [[org.http4s.client.defaults.ConnectTimeout default http4s connect timeout]], and disables | ||
* [[https://github.com/http4s/http4s-jdk-http-client/issues/200 TLS 1.3 on JDK 11]]. | ||
* | ||
* On Java 21 and higher, prefer [[simpleResource]] as it actively closes the underlying client, | ||
* releasing its resources early. | ||
*/ | ||
def simple[F[_]](implicit F: Async[F]): F[Client[F]] = | ||
defaultHttpClient[F].map(apply(_)) | ||
|
||
/** Like [[simple]], but wraps the client in a [[cats.effect.Resource Resource]] to ensure it's | ||
* properly shut down on JVM 21 and higher. On lower Java versions, closing the resource does | ||
* nothing (garbage collection will eventually clean up the client). | ||
*/ | ||
def simpleResource[F[_]](implicit F: Async[F]): Resource[F, Client[F]] = | ||
defaultHttpClientResource[F].map(apply(_)) | ||
|
||
private[jdkhttpclient] def defaultHttpClientResource[F[_]](implicit | ||
F: Async[F] | ||
): Resource[F, HttpClient] = | ||
Resource.make[F, HttpClient](defaultHttpClient[F]) { | ||
case c: AutoCloseable => Sync[F].blocking(c.close()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the most relevant bit, actively closing if |
||
case _ => Applicative[F].unit | ||
} | ||
|
||
private[jdkhttpclient] def defaultHttpClient[F[_]](implicit F: Async[F]): F[HttpClient] = | ||
F.executor.flatMap { exec => | ||
F.delay { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -131,6 +131,11 @@ object JdkWSClient { | |
}) | ||
} yield () | ||
} | ||
// If the input side is still open (no close received from server), the JDK will not clean up the connection. | ||
// This also implies the client can't be shutdown on Java 21+ as it waits for all open connections | ||
// to be be closed. As we don't expect/handle anything coming on the input anymore | ||
// at this point, we can safely abort. | ||
_ <- F.delay(webSocket.abort()) | ||
Comment on lines
+134
to
+138
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Without this, the test suite hangs when using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} yield () | ||
} | ||
.map { case (webSocket, queue, closedDef, sendSem) => | ||
|
@@ -164,7 +169,17 @@ object JdkWSClient { | |
* [[cats.effect.kernel.Async.executor executor]], sets the | ||
* [[org.http4s.client.defaults.ConnectTimeout default http4s connect timeout]], and disables | ||
* [[https://github.com/http4s/http4s-jdk-http-client/issues/200 TLS 1.3 on JDK 11]]. | ||
* | ||
* * On Java 21 and higher, prefer [[simpleResource]] as it actively closes the underlying | ||
* client, releasing its resources early. | ||
*/ | ||
def simple[F[_]](implicit F: Async[F]): F[WSClient[F]] = | ||
JdkHttpClient.defaultHttpClient[F].map(apply(_)) | ||
|
||
/** Like [[simple]], but wraps the client in a [[cats.effect.Resource Resource]] to ensure it's | ||
* properly shut down on JVM 21 and higher. On lower Java versions, closing the resource does | ||
* nothing (garbage collection will eventually clean up the client). | ||
*/ | ||
def simpleResource[F[_]](implicit F: Async[F]): Resource[F, WSClient[F]] = | ||
JdkHttpClient.defaultHttpClientResource[F].map(apply(_)) | ||
} |
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.
Name is up for discussion, I don't particular like
simpleResource
, but at least it's rather clear.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.
As already mentioned in #1011 (comment), we could just change the signature of
simple
and cut a 0.10 release; it should be rather simple for users to migrate.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 we should rename
simple
andsimpleResource
to something likeunsafeDefault
anddefault
. We should encourage users to do the right thing (using the resource variant)We can do that in a 0.10 release, or deprecate simple in this and create new new constructors.
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.
@hamnis I can adjust the names, no problem, just a bit unsure about the
unsafe
prefix. On everything below Java 21, it's actually not unsafe in the sense CE usually uses this, but the only thing you can have (theResource
variant won't close anything there either).So maybe a 0.10 with
simple
(returning aResource
, by re-using the name users get nudged towards this) and adef forEffect[F[_]: Async]: F[Client[F]]
(or any better name) with docs explaining the caveats on Java 21+?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.
do we really need the forEffect constructor? Do we lose anything with just having the
simple
|default
|insertyournamehere
resource constructor ?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.
@hamnis It may cause some (unnecessary) trouble for users who now need to bubble up
Resource
usage in case they hadn't so far. But asallocated
is safe on Java below 21, I changed the PR to only offerdef simple[F[_]: Async]: Resource[F, …]
and mentionedallocated
in the docs, so people have a hint on a workaround. Hope that's a fair compromise!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.
Obviously, that means MiMa is unhappy and we need to release it as
0.10
.