-
-
Save chuwy/b0f6b2d8df974dd10a9fa2d2e9533272 to your computer and use it in GitHub Desktop.
Scala code research
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
def loadFromPath[F[_]: Sync](path: JPath): F[Config] = | |
val source = ConfigSource.default(ConfigSource.file(path)).withFallback(ConfigSource.default) | |
loadF[F, Config](source) | |
def load(args: List[String]): IO[Either[Help, (SubCommand, Option[Config])]] = //input array: List[String], output: why IO | |
command.parse(args) match // how it matching string with help/commands? | |
case Left(help) => IO.pure(help.asLeft) //help command | |
case Right(cli) => //other commands | |
cli match //match with SubCommand | |
case SubCommand.Run(configPath, _) => //Run command | |
loadFromPath[IO](configPath).map(c => (cli, Some(c)).asRight) | |
case SubCommand.Load(configPath, _) => //Load command | |
loadFromPath[IO](configPath).map(c => (cli, Some(c)).asRight) | |
case SubCommand.ApiExport(path) => //ApiExport command | |
IO.pure(Right(SubCommand.ApiExport(path), None)) |
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
object Main extends IOApp: | |
def run(args: List[String]): IO[ExitCode] = //function, input list, output IO | |
greet //print version | |
*> // | |
Config. //load config file | |
load(args). //pattern matching the input command | |
flatMap { //the inner grouping of an item is removed and a sequence is generated | |
case Right((Config.SubCommand.Load(_, fixtures), Some(config))) => //subcommand "Load" matched with Some parameters | |
Resources. //excexute Load command with parameters | |
build[IO](config) //can't understand this definition: def build[F[_]: Async: Trace: Network: Console] | |
.use{ resources => //use? | |
import resources.given //something like lambda function | |
//using for load fixtures | |
val path = Path.fromNioPath(fixtures) | |
Fixtures.load[IO](path) | |
}.as(ExitCode.Success)// why casting success type? execute command? | |
case Right((run: Config.SubCommand.Run, Some(config))) => //subcommand "Run" matched | |
config.database match //database type matching | |
case _: Config.Database.Postgres if run.fixtures.isDefined => //fixtures are defined | |
IO.println("It is prohibited to autoload fixtures with Postgres in config, use `load` command instead") .as(ExitCode.Error)//should use another command, casting as error, can't excute command | |
case _ => | |
Resources.//excexute Run command with parameters | |
build[IO](config).use { resources => //same build function | |
import resources.given | |
Server.server(config).use { _ => | |
run.fixtures.traverse_(jpath => Fixtures.load[IO](Path.fromNioPath(jpath))) *> IO.never | |
} | |
}.as(ExitCode.Success)// why casting success type? | |
case Right((Config.SubCommand.ApiExport(path), None)) => //subcommand "ApiExport" matched | |
Server.exportApi[IO](Path.fromNioPath(path)).as(ExitCode.Success) | |
case Right(other) => //undefined command | |
IO.println(s"$other is not expected").as(ExitCode.Error)//print error text, why casting error type? can't execute command? | |
case Left(help) => //help command | |
IO.println(help.toString).as(ExitCode.Error) //help returning from load(), ptint help, why casting error type? | |
} | |
def greet: IO[Unit] = | |
IO.println(s"Running Ratio ${BuildInfo.version}...") // IO used for execute println only when greet called |
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
case class Resources[F[_]](random: Random[F], | |
passwords: Passwords[F], | |
persons: Persons[F], | |
tasks: Tasks[F], | |
session: Session[F], | |
inventory: Inventory[F], | |
blobs: Blobs[F], | |
comments: Comments[F], | |
fixtures: Fixtures[F], | |
events: Events[F], | |
bus: Bus[F], | |
eventStorage: EventStorage[F], | |
chats: Chats[F]): | |
given Random[F] = random | |
given Persons[F] = persons | |
given Tasks[F] = tasks | |
given Inventory[F] = inventory | |
given Session[F] = session | |
given Blobs[F] = blobs | |
given Comments[F] = comments | |
given Passwords[F] = passwords | |
given Fixtures[F] = fixtures | |
given Events[F] = events | |
given Bus[F] = bus | |
given EventStorage[F] = eventStorage | |
given Chats[F] = chats | |
object Resources: | |
def build[F[_]: Async: Trace: Network: Console](config: Config): Resource[F, Resources[F]] = //can't understand function definition | |
for { //sequence comprehensions | |
//variables for Resources | |
random <- Resource.eval(Random.scalaUtilRandom[F]) | |
passwords = auth.Service.argon[F](random, config.auth.pepper) | |
_ <- Resource.eval(precreate[F](List(config.storage._1, config.storage._2, config.storage._3))) //what does it mean _? | |
a <- buildDb[F](random, passwords, config.database, config.storage) //includes fields: persons ... chats | |
_ <- notifications.Service.run[F](config.notifications.flatMap(_.telegram), a._9, a._1, a._11).background //what does it mean _? | |
} yield Resources(random, passwords, a._1, a._2, a._3, a._4, a._5, a._6, a._7, a._8, a._9, a._10, a._11) //return Resource[F, Resources[F]] type | |
def mkPostgresF[F[_]: Async: Files: Clock: Console: Network: Trace: Random: Passwords](storage: Config.Storage)(session: Resource[F, DbSession[F]]) = | |
for { | |
p <- Resource.eval(users.Postgres.build[F](session)) | |
t <- Resource.pure(tasks.Postgres.build[F](session)) | |
s <- Resource.eval(Session.inMemory[F]) | |
i <- Resource.pure(inventory.Postgres.build[F](session)) | |
b <- Resource.pure(blobs.Postgres.build[F](blobs.Service.read(storage), blobs.Service.write(storage), session)) | |
c <- Resource.pure(comments.Postgres.build[F](session)) | |
f <- Resource.pure(Fixtures.postgres[F](session)) | |
e <- Resource.pure(calendar.Postgres.build[F](session)) | |
eb <- bus.Postgres.build[F](session) | |
es <- Resource.pure(bus.Postgres.buildStorage(session)) | |
ch <- Resource.pure(notifications.Postgres.build[F](session)) | |
_ <- eb.subscribe.evalTap(es.add).compile.drain.background | |
} yield (p, t, s, i, b, c, f, e, eb, es, ch) | |
def inMemory[F[_]: Concurrent: Passwords: Random: Clock: Files: UUIDGen: Console](storage: Config.Storage) = | |
for { | |
p <- Persons.inMemory[F].map(_._2) | |
t <- Tasks.inMemory[F].map(_._2) | |
s <- Session.inMemory[F] | |
i <- Inventory.inMemory[F].map(_._2) | |
b <- Blobs.inMemory[F](blobs.Service.read(storage), blobs.Service.write(storage)).map(_._2) | |
c <- Comments.inMemory[F].map(_._2) | |
f = Fixtures.inMemory[F] | |
e <- Events.inMemory[F].map(_._2) | |
eb <- Bus.inMemory[F] | |
es <- EventStorage.inMemory[F].map(_._2) | |
ch <- Chats.inMemory[F].map(_._2) | |
} yield (p, t, s, i, b, c, f, e, eb, es, ch) | |
def buildDb[F[_]: Async: Files: Clock: Console: Network: Trace](random: Random[F], | |
passwords: Passwords[F], | |
database: Config.Database, | |
storage: Config.Storage): Resource[F, (Persons[F], Tasks[F], Session[F], Inventory[F], Blobs[F], Comments[F], Fixtures[F], Events[F], Bus[F], EventStorage[F], Chats[F])] = | |
given Random[F] = random | |
given Passwords[F] = passwords | |
val resources = database match | |
case pg: Config.Database.Postgres => | |
Postgres.build[F](pg).flatMap(mkPostgresF[F](storage)) | |
case Config.Database.InMemory => | |
Resource.eval(inMemory[F](storage)) | |
resources | |
def precreate[F[_]: Files: Monad](paths: List[Path]): F[Unit] = | |
paths.traverse_ { path => Files[F].exists(path).ifM(Monad[F].unit, Files[F].createDirectories(path)) } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment