Comments (10)
@jdegoes If I interpret this idea correctly, due to referential transparency MyConfig would be re-evaluated each time config[MyConfig] is summoned? (For example, re-reading a json or hocon file etc)
Yes, but in most common cases, config
will be defined in terms of ZIO.succeed
.
The actual loading of the data occurs in the effect returned by Config.make
, which will typically occur during startup as the dependencies are wired together.
So it will not be necessary for a user to concern themselves with this; from their perspective, the config data is a constant across their entire application.
Now, the interface allows one to provide a config module backed by "live" data, so it could change; but the default implementation would not do that. In fact, one could make that mandatory by making config: A
, although it's not strictly necessary for the above reasons.
from zio-config.
Yes that's right, and you can see it will not be reloaded every time you access it.
from zio-config.
@jdegoes If I interpret this idea correctly, due to referential transparency MyConfig
would be re-evaluated each time config[MyConfig]
is summoned? (For example, re-reading a json or hocon file etc)
from zio-config.
@jdegoes
Thanks for that. It sounds really good the idea of MyConfig as part of the Environment rather than the ConfigSource. It sounds much more intuitive for the user to consider Config[MyConfig]
to be part of the environment everywhere.
As @leigh-perry mentioned, to avoid the re-evaluation, lets say
trait Config[A] {
def config: A
}
object config {
def config[A]: ZIO[Config, Nothing, A] = ZIO.accessM(_.config)
}
object Config {
...
def fromEnv[A](configDescriptor: ConfigDescriptor[A]): UIO[Config[A]] =
envSource.flatMap(sysEnv => read(configDescriptor).provide(sysEnv))
...
}
And at the user site:
import zio.config._
val myApp: ZIO[Config, Nothing, A] =
for {
myConfig <- config[MyConfig]
} yield (myConfig.port, myConfig.server)
val configDescription: ConfigDescriptor[MyConfig] =
(int("PORT") |@| string("SERVER"))(MyConfig.apply, MyConfig.unapply)
Config.fromEnv(configDescription).flatMap(myConfig => myApp.provide(myConfig))
from zio-config.
This is part of a real-world app pattern where you want to do some relatively heavyweight setup only once as part of a bootstrap phase, as shown in @afsalthaj 's comment. For example, reading config, creating a Spark session, etc.
The developer needs to be aware that referential transparency can cause constant re-evaluation, so the bootstrap phase is to resolve the program, providing it with those once-only environmental dependencies.
I have a sample app template that prototypes this. The essential part is:
override def run(args: List[String]): ZIO[Environment, Nothing, Int] =
for {
log <- Log.slf4j(prefix = "TESTING")
r <- resolvedProgram(log).foldM(
e => log.error(s"Application failed: $e") *> ZIO.succeed(1),
_ => log.info("Application terminated with no error indication") *> ZIO.succeed(0)
)
} yield r
final case class SomeResult()
def resolvedProgram(log: Log): ZIO[Any, MainAppError, Unit] =
for {
// Config is loaded separately in order to provide to `program`
cfg <- Bootstrap.ConfigSupport.Live.load.mapError(ConfigLoadError)
sparkSession <- Bootstrap.SparkSupport.Live.sparkSession("TESTING").mapError(ExceptionEncountered).provide(Blocking.Live)
resolved <- program.provide(
new AppRuntime.All(cfg, log, sparkSession) with Blocking.Live {}
)
} yield resolved
def program: ZIO[
AppRuntime.Config with AppRuntime.Logging with AppRuntime.Spark with Blocking,
MainAppError,
Unit
] =
ZIO.accessM {
env => ...
Any better suggestions are welcome :-)
from zio-config.
@jdegoes that’s nice.
To reinforce my understanding,
Config.make is nothing but
read(description).provide(env).map(result => new Config{ override def Config = Zio.succeed(result)}
And user calls at this only in the main.
This means accessing MyConfig by the user anywhere from the environment is accessing a constant value. Isn’t it?
from zio-config.
from zio-config.
This is resolved (exactly the same pattern) in #72
Thanks John
from zio-config.
Reopening, since we can keep this for another round of review during direct-discussion.
from zio-config.
This is done!
from zio-config.
Related Issues (20)
- Duration seems broken in 4.0.0-RC10 HOT 2
- `.kebabCase` is not working for array in hocon config HOT 5
- unable to read `zio.Duration` HOT 3
- Make sure YML supports keys with period delimiter
- Avoid throwing exceptions when parsing or reading YML or HOCON from Files (and embed this within ConfigProvider)
- Clean up website - probably port the README content
- Default value not in docs HOT 1
- Compile failed on case class with default value and type parameter
- Rename nameWithLabel with discriminator
- Runtime hangs when deriving a config using `given` in Scala 3
- ConfigProvider#orElse does not replace value from default provider HOT 5
- Comma-separated parsing does not work with sealed hierarchies
- Scala 3 javadoc artifacts are empty
- ConfigProvider.fromYamlFile Is Not Sufficiently Lazy HOT 1
- Weird regression in ZIO Config 4 with the derived config
- ConfigSource.fromSystemEnv fails when env has variables leading with _ and you are using keyDelimiter "_"
- sbt packageDoc fails with error HOT 2
- Support TestSystem in Typesafe Config provider HOT 2
- Cannot build a Docker image with Scala 3.3.0 and sbt-native-packager (4.0.0-RC16) HOT 2
- No FiniteDuration parser HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from zio-config.