-
Notifications
You must be signed in to change notification settings - Fork 75
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
Use ZManaged for resources in core #249
Conversation
6f8da72
to
bf7a44b
Compare
docs/essentials/resources.md
Outdated
ZManaged.scope.use { scope => | ||
|
||
val channel: IO[IOException, SocketChannel] = scope(SocketChannel.open).map { | ||
case (_ /* early release */, channel) => channel |
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 could use case (earlyRelease @ _, channel)
here to give it a name but avoid an unused param compiler warning.
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.
Good trick, I didn't know that.
|
||
### Using `close` for Early Release | ||
|
||
In the case of channels, we don't actually need the early release features that `ZManaged` provides, as every channel has a built-in early release in the form of the `close` method. Closing a channel more than once is a perfectly safe thing to do, so you can use `close` to release a channel's resources early. When the `ZManaged` scope of the channel later ends, `close` will be called again, but it will be a no-op. |
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.
Is it desirable to expose close
to the user in addition to open/close as a ZManaged
? With ZManaged
you can be sure that the resource is still 'open' as long as the ZManaged
is alive, but by exposing close
that is no longer the case.
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.
That's true, but the same risk exists if you get the release effect via withEarlyRelease
or scope
.
@@ -30,4 +30,11 @@ package object core { | |||
case _: EOFException => ZIO.none | |||
} | |||
|
|||
implicit final private[nio] class IOCloseableManagement[-R, +E, +A <: IOCloseable { type Env >: R }]( |
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.
Any particular reason to use a structured type here instead of trait IOCloseable[Env]
?
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.
When I was experimenting with blocking variants of the channel APIs I found a member type for this was less hassle, and I just copied that idea here. But for this PR, it doesn't actually matter.
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 believe using structural types uses reflection, which incurs some runtime overhead. Do you think that would matter for the usage in zio-nio?
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.
Reflection is definitely used to access term-level members, but I think type members are handled entirely at compile 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.
Cool, I didn't know that
bf7a44b
to
3cbd28d
Compare
@quelgar Conflicts? |
f593378
to
7c9865e
Compare
7c9865e
to
25db9f4
Compare
@jdegoes good to go |
docs/essentials/index.md
Outdated
@@ -34,7 +34,8 @@ libraryDependencies += "dev.zio" %% "zio-nio" % "1.0.0-RC10" | |||
## Main abstractions | |||
|
|||
- **[File Channel](files.md)** — For processing files that are available locally. For every operation a new fiber is started to perform the operation. | |||
- **[Socket Channel](sockets.md)** — Provides an API for remote communication with `InetSocket`s. | |||
- **[Socket Channel](sockets.md)** — Provides anAPI for remote communication with `InetSocket`s. |
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.
typo anAPI
The goal of this PR is to be a first step in undoing the split between the core and "high-level" modules. The split seemed like a good idea at the time, but in practice the only significant difference between the two modules is the high-level one uses
ZManaged
, whereas core requires the user to manually release resources usingclose
. This minor difference comes at the cost of maintaining mostly duplicate copies of much of the code.ZManaged
was originally seen as too opinionated as a requirement to use ZIO-NIO. There are situations where lexically scoping resources withuse
is too limiting. However,ZManaged
in ZIO 1.0 offers more flexible resource management via scopes or reservations, so aZManaged
based API shouldn't prevent ZIO-NIO from doing anything that can be done directly with NIO. So this PR makes all resource acquisition in core useZManaged
.I've also left
close
as public, which probably seems odd. Butclose
is still useful withZManaged
as an early release mechanism. WhileZManaged
lets you get an early release effect value, it's often more convenient to just have this effect available on the channel itself. For example, if we want to use the separate early release value with a channel registered in a selector, we have to attach it to theSelectionKey
and later get the attachment and cast it to the correct type. But we already have a reference to the channel, so it's a lot simpler to just callclose
on it directly to release early.zio.nio.core.channels.SelectorSpec
provides an example of what I'm talking about above. I've also added a documentation page describing the resource management options. Hopefully what I've said is accurate 🤞If we decide to go this way, we can at some point throw out the high-level module and rename
zio.nio.core
tozio.nio
.