Created
December 2, 2018 04:52
-
-
Save PavelZaytsev/8bc0b759aaff18d1dcd25535ae7003e2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scalaz.zio.{App, IO, KleisliIO} | |
case class AppConfig(service1QueueSize: Int, | |
service1SecretPath: String, | |
service2SecretPath: String, | |
service1DBToUse: String, | |
service2DBToUse: String, | |
service2MonitoringEndpoint: String) | |
case class SecretDependencyService(secretPath: String) | |
case class DBAdapter(db: String) | |
case class Monitor(endpoint: String) | |
case class Service1(queueSize: Int, | |
caller: SecretDependencyService, | |
db: DBAdapter) | |
case class Service2(caller: SecretDependencyService, | |
db: DBAdapter, | |
monitor: Monitor) | |
case class Application(service1: Service1, service2: Service2) { | |
def doThings(): IO[Nothing, Unit] = ??? | |
} | |
object ConfigApp { | |
// read from file or something | |
val fromConfigPathToConfig: String => AppConfig = ??? | |
val fromConfigPathToConfigK = | |
KleisliIO.lift(fromConfigPathToConfig) | |
val fromConfigToQueueSizeK = | |
KleisliIO.lift { config: AppConfig => | |
config.service1QueueSize | |
} | |
val fromConfigToSecretPath1K = KleisliIO.lift { config: AppConfig => | |
config.service1SecretPath | |
} | |
val fromConfigToSecretPath2K = KleisliIO.lift { config: AppConfig => | |
config.service2SecretPath | |
} | |
val fromSecretPathToSecretDependencyServiceK = KleisliIO.lift { | |
path: String => | |
SecretDependencyService(path) | |
} | |
val fromConfigToDB1K = KleisliIO.lift { config: AppConfig => | |
config.service1DBToUse | |
} | |
val fromConfigToDB2K = KleisliIO.lift { config: AppConfig => | |
config.service2DBToUse | |
} | |
val fromDBtoDBAdapterK = KleisliIO.lift { db: String => | |
DBAdapter(db) | |
} | |
val fromConfigToMonitorEndpointK = KleisliIO.lift { config: AppConfig => | |
config.service2MonitoringEndpoint | |
} | |
val fromMonitorEndpointToMonitorK = KleisliIO.lift { monitor: String => | |
Monitor(monitor) | |
} | |
// fuse 'em up | |
val fromPathToService1K: String => KleisliIO[Nothing, String, Service1] = { | |
path: String => | |
val queueSizeK | |
: KleisliIO[Nothing, String, Int] = fromConfigPathToConfigK >>> fromConfigToQueueSizeK | |
val secretService1K | |
: KleisliIO[Nothing, String, SecretDependencyService] = fromConfigPathToConfigK >>> fromConfigToSecretPath1K >>> fromSecretPathToSecretDependencyServiceK | |
val dbAdapter1K | |
: KleisliIO[Nothing, String, DBAdapter] = fromConfigPathToConfigK >>> fromConfigToDB1K >>> fromDBtoDBAdapterK | |
// Kleisli is a monad itself lol | |
for { | |
((queueSize, secretService1), dbAdapter) <- queueSizeK &&& secretService1K &&& dbAdapter1K | |
} yield Service1(queueSize, secretService1, dbAdapter) | |
} | |
val fromPathToService2K: String => KleisliIO[Nothing, String, Service2] = { | |
path: String => | |
val secretService2K | |
: KleisliIO[Nothing, String, SecretDependencyService] = fromConfigPathToConfigK >>> fromConfigToSecretPath2K >>> fromSecretPathToSecretDependencyServiceK | |
val dbAdapterK | |
: KleisliIO[Nothing, String, DBAdapter] = fromConfigPathToConfigK >>> fromConfigToDB2K >>> fromDBtoDBAdapterK | |
val monitorK | |
: KleisliIO[Nothing, String, Monitor] = fromConfigPathToConfigK >>> fromConfigToMonitorEndpointK >>> fromMonitorEndpointToMonitorK | |
for { | |
((secretService2, dbAdapter), monitor) <- secretService2K &&& dbAdapterK &&& monitorK | |
} yield Service2(secretService2, dbAdapter, monitor) | |
} | |
val fromPathToApp: String => KleisliIO[Nothing, String, Application] = { | |
path: String => | |
for { | |
(service1, service2) <- fromPathToService1K(path) &&& fromPathToService2K( | |
path) | |
} yield Application(service1, service2) | |
} | |
def buildAppFromConfig(configPath: String): IO[Nothing, Application] = | |
fromPathToApp(configPath).run(configPath) | |
} | |
object KleisliConfig extends App { | |
def run(args: List[String]): IO[Nothing, ExitStatus] = | |
program.attempt.map(_.fold(_ => 1, _ => 0)).map(ExitStatus.ExitNow(_)) | |
def program: IO[Nothing, Unit] = | |
for { | |
appInstance <- ConfigApp.buildAppFromConfig("productionConfig.json") | |
_ <- appInstance.doThings() | |
} yield () | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment