-
Notifications
You must be signed in to change notification settings - Fork 522
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 SystemProperties
#3924
Add SystemProperties
#3924
Conversation
Thank you for looking at this! An interesting question for us to answer though is what we want to do with Native and JavaScript. This is a bit different from |
They both support System properties. It's basically just a global mutable map. |
A question: the |
I would agree. TBH, I wondered whether we should try and make them atomic, but that's probably not something you'd expect by system props. |
I don't think we can make them atomic. Or do you know a way? |
Right, not sure how could be made atomic. Citing Arman, it's basically just a global mutable map. |
Unfortunately I think it's still confusing. Anyway, I expect 99% of usecases to just be reading system properties. APIs that require setting/updating system properties seem really dicey 🙄 |
I'd just go with get, set and remove. If that's the functionality offered by the platform, and we can't provide atomicity, its best simply to wrap those. |
Similar to |
*/ | ||
def unset(key: String): F[Unit] | ||
|
||
def entries: F[Properties] |
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'm not sure I like returning a mutable object here. (I think we usually try to avoid that?)
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.
For Env
we decided to return an Iterable[(String, String)]
, but that was because of case-sensitivity issues which I don't think apply here. So probably makes most sense to return an immutable Map[String, String]
.
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 the entries
is not an atomic snapshot of the system properties. it would be nice if we could do that, but I don't think it's possible with the available JDK API.
F.delay(Option(System.getProperty(key))) // thread-safe | ||
|
||
def set(key: String, value: String): F[Unit] = | ||
F.void(F.delay(System.setProperty(key, value))) |
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.
If I'm reading the JDK source correctly, this eventually calls a synchronized
method. So, technically, it should be F.blocking
. I don't know if we care about this though...
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, that's right. I think we should do that.
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.
F.void(F.delay(System.setProperty(key, value))) | |
F.void(F.blocking(System.setProperty(key, value))) |
@nowarn3("cat=deprecation") | ||
def entries: F[Map[String, String]] = { | ||
import scala.collection.JavaConverters._ | ||
F.delay(Map.empty ++ System.getProperties().asScala) |
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.
Similarly, I think this calls into a Collections.synchronizedSet
, so technically should be blocking
. (Although this should be uncontended, I think. So we probably care even less...)
for { | ||
_ <- Prop[IO].set("some property", "the value") | ||
props <- Prop[IO].entries | ||
assertion <- IO(props mustEqual System.getProperties()) |
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.
There is a test failure here, I think it's just because we're comparing a Scala Map
with a Java hashtable.
|
||
import scala.collection.immutable.Map | ||
|
||
trait Prop[F[_]] { self => |
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.
Maybe we should make this sealed
, just for future-proofing?
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.
On the other hand, this prevents mocking. Our current practice is not really to sealed
anything, for better or for worse 🤷
[BIKESHEDDING] I'm late to the party to comment probably, but I fear that |
I actually also dislike the name The reason that I dislike it is because this API is very specifically abstracting over the (global singleton) system properties, not the generic JDK If we want to keep the name short we could rename to |
The JDK suggests there is some notion of "bulk" operations.
I am still trying to figure out what the bulk operations are exactly. If serializing the properties to a stream is one such bulk operation, perhaps we can use that to make an atomic copy first ... 🤔 |
It is possible, I think I was able to fix it. Thanks for catching :) |
import scala.collection.JavaConverters._ | ||
val props = System.getProperties | ||
val back = new java.util.HashMap[String, String](props.size()) | ||
props.putAll(back) |
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.
Aw crap, I think I got this backwards 😕 it should be back.putAll(props)
but then it's no longer atomic which was the point of copying. Hmm.
That's my favorite too. |
8bf996e
to
4a71b85
Compare
std/shared/src/main/scala/cats/effect/std/SystemProperties.scala
Outdated
Show resolved
Hide resolved
After going through a few iterations, I think we should just stick to Technically |
This reverts commit 99de034.
Addresses #3313.