Skip to content
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 a combine method to ConfigErrors #173

Merged
merged 4 commits into from Aug 7, 2018

Conversation

cb372
Copy link
Contributor

@cb372 cb372 commented Aug 2, 2018

Having a cats Semigroup is quite handy, as it means you can do a bunch of loadConfigs for small parts of your configuration and then parMapN them together like this.

@cb372
Copy link
Contributor Author

cb372 commented Aug 3, 2018

Looks like MiMa is complaining about bincompat. What's the correct way to deal with this?

@vlovgr
Copy link
Owner

vlovgr commented Aug 3, 2018

Thanks for this! Very neat idea. Definitely worth adding something to the usage guide about this, but I can do that later unless you want to.

Binary compatibility fails because adding a function with default implementation to a trait in Scala 2.11 breaks compatibility. We can keep compatibility by moving the new instance to a CirisInstancesForCatsBinCompat trait and make the cats package object (and possibly cats.effect) also extend this trait. Then I’ll merge these traits together for the next binary incompatible release.

@codecov
Copy link

codecov bot commented Aug 3, 2018

Codecov Report

Merging #173 into master will increase coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #173      +/-   ##
==========================================
+ Coverage   99.76%   99.77%   +<.01%     
==========================================
  Files          46       47       +1     
  Lines         868      870       +2     
  Branches        9       10       +1     
==========================================
+ Hits          866      868       +2     
  Misses          2        2
Impacted Files Coverage Δ
...iris/cats/api/CirisInstancesForCatsBinCompat.scala 100% <100%> (ø)
...ore/shared/src/main/scala/ciris/ConfigErrors.scala 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9a3457e...9f48d95. Read the comment docs.

@cb372
Copy link
Contributor Author

cb372 commented Aug 3, 2018

Thanks, moving it to a separate trait did the trick. I'll work on adding something to the user guide.

@cb372
Copy link
Contributor Author

cb372 commented Aug 4, 2018

I've added an example to the docs.

I had to enable -Ypartial-unification for it to compile, but unfortunately that caused a compile error in the kittens Show example.

[tut] *** Error reported at /Users/chris/code/ciris/docs/src/main/tut/docs/logging.md:93
<console>:40: error: type mismatch;
 found   : cats.Show[shapeless.CNil]
 required: cats.Show[Config]
         semi.show
              ^

I'll investigate later, but I'm pretty confused by this.

Copy link
Owner

@vlovgr vlovgr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few comments, but already looks pretty great! 👍

The kittens compile error message isn't very helpful. If we tweak the code slightly, we can get a more helpful error message.

diverging implicit expansion for type cats.derived.MkShow[Config]
starting with method refTypeViaContravariant in package cats
  semi.show[Config]
           ^
Compilation Failed

It looks like derived Show instances for refined types are provided both via an explicit Show derivation and via Contravariant derivation. I'll try to create to create a smaller example and open an issue against refined.

In the meantime, changing this import:

import eu.timepit.refined.cats._

to:

import eu.timepit.refined.cats.refTypeShow

should make things compile.

Edit: refined issue is here: fthomas/refined#553

different types of configuration.

```tut:silent
case class DbConfig(user: String, password: String)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The password and apiKey should probably be Secret[String].

We load each of the configurations using `loadConfig`:

```tut:invisible
sys.props.put("db.user", "myapp")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do a sys.props.remove on these at the very end? Or they'll stick around for the duration of the running JVM. (Ideally we want a try-finally thing for these, but AFAIK nothing like that exists in tut.)

* res0: ConfigErrors = ConfigErrors(ConfigError(error1), ConfigError(error2))
* }}}
*/
def combine(first: ConfigErrors, second: ConfigErrors): ConfigErrors =
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we move this to ConfigErrors itself? Or have both? Might be nice to be able to do first combine second.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm always in two minds about this. I guess moving it to the ConfigErrors would be consistent with ++ and friends in the standard collections lib.

Having both seems a bit redundant, so I'll move it into the class.

We can then compose the results into an `Either[ConfigErrors, AppConfig]`:

```tut:book
import _root_.cats.instances.parallel._
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should use a :reset modifier somewhere (top of the section?) to avoid having to use _root_ here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, forgot you could do that.

import ciris._

trait CirisInstancesForCatsBinCompat {
implicit val semigroupConfigErrors: Semigroup[ConfigErrors] = new Semigroup[ConfigErrors] {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With ConfigErrors#combine, we could write this as:

implicit val semigroupConfigErrors: Semigroup[ConfigErrors] =
  Semigroup.instance(_ combine _)

@vlovgr
Copy link
Owner

vlovgr commented Aug 7, 2018

This looks great! Thanks again! Merging. 🎉

@vlovgr vlovgr merged commit eda3fb3 into vlovgr:master Aug 7, 2018
@vlovgr
Copy link
Owner

vlovgr commented Aug 7, 2018

@cb372 this has been released in v0.10.2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants