Skip to content

Commit 9037b38

Browse files
committed
refactor: Changes requested in PR review
1 parent 8c3afef commit 9037b38

File tree

18 files changed

+193
-189
lines changed

18 files changed

+193
-189
lines changed

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ lazy val jvmExecution = (project in file("jvm-execution"))
4949
.settings(
5050
commonSettings,
5151
name := "scala-server-toolkit-jvm-execution",
52-
libraryDependencies += Dependencies.scalaLogging
52+
libraryDependencies += Dependencies.slf4jApi
5353
)
5454

5555
lazy val jvmSsl = (project in file("jvm-ssl"))

docs/jvm.md

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,30 @@
44

55
`libraryDependencies += "com.avast" %% "scala-server-toolkit-jvm-system" % "<VERSION>"`
66

7-
There is a set of `scala-server-toolkit-jvm-*` modules that provide pure implementations of JVM-related utilities such as standard in/out,
8-
time, random number generation, thread pools and SSL context initialization. The following modules are available:
7+
There is a set of `scala-server-toolkit-jvm-*` modules that provide pure implementations of different JVM-related utilities:
98

10-
* `scala-server-toolkit-jvm-execution`,
11-
* `scala-server-toolkit-jvm-ssl`,
12-
* `scala-server-toolkit-jvm-system`.
9+
* `scala-server-toolkit-jvm-execution` - creation of thread pools,
10+
* `scala-server-toolkit-jvm-ssl` - initialization of SSL context,
11+
* `scala-server-toolkit-jvm-system` - standard in/out/err, random number generation.
1312

1413
```scala
15-
import java.util.concurrent.TimeUnit
16-
import com.avast.server.toolkit.system.SystemModule
14+
import com.avast.server.toolkit.system.console.ConsoleModule
15+
import com.avast.server.toolkit.system.random.RandomModule
1716
import zio.interop.catz._
17+
import zio.DefaultRuntime
1818
import zio.Task
1919

2020
val program = for {
21-
systemModule <- SystemModule.make[Task]
22-
currentTime <- systemModule.clock.realTime(TimeUnit.MILLISECONDS)
23-
randomNumber <- systemModule.random.nextInt
24-
_ <- systemModule.console.printLine(s"Current Unix epoch time is $currentTime ms. Random number: $randomNumber")
21+
random <- RandomModule.makeRandom[Task]
22+
randomNumber <- random.nextInt
23+
console = ConsoleModule.make[Task]
24+
_ <- console.printLine(s"Random number: $randomNumber")
2525
} yield ()
26-
// program: zio.ZIO[Any, Throwable, Unit] = zio.ZIO$FlatMap@7f42b194
26+
// program: zio.ZIO[Any, Throwable, Unit] = zio.ZIO$FlatMap@2f1f9515
27+
28+
val runtime = new DefaultRuntime {} // this is just in example
29+
// runtime: AnyRef with DefaultRuntime = repl.Session$App$$anon$1@33ebe4f0 // this is just in example
30+
runtime.unsafeRun(program)
31+
// Random number: 776310297
2732
```
2833

docs/pureconfig.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ import zio.Task
2020
final case class ServerConfiguration(listenAddress: String, listenPort: Int)
2121

2222
implicit val serverConfigurationReader: ConfigReader[ServerConfiguration] = deriveReader
23-
// serverConfigurationReader: ConfigReader[ServerConfiguration] = pureconfig.generic.DerivedConfigReader1$$anon$3@1a9e2c3b
23+
// serverConfigurationReader: ConfigReader[ServerConfiguration] = pureconfig.generic.DerivedConfigReader1$$anon$3@2a8eed58
2424

2525
val maybeConfiguration = PureConfigModule.make[Task, ServerConfiguration]
26-
// maybeConfiguration: Task[Either[cats.data.NonEmptyList[String], ServerConfiguration]] = zio.ZIO$EffectPartial@5f92e5eb
26+
// maybeConfiguration: Task[Either[cats.data.NonEmptyList[String], ServerConfiguration]] = zio.ZIO$EffectPartial@352bea0e
2727
```
2828

example/src/main/mdoc/jvm.md

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,26 @@
44

55
`libraryDependencies += "com.avast" %% "scala-server-toolkit-jvm-system" % "<VERSION>"`
66

7-
There is a set of `scala-server-toolkit-jvm-*` modules that provide pure implementations of JVM-related utilities such as standard in/out,
8-
time, random number generation, thread pools and SSL context initialization. The following modules are available:
9-
10-
* `scala-server-toolkit-jvm-execution`,
11-
* `scala-server-toolkit-jvm-ssl`,
12-
* `scala-server-toolkit-jvm-system`.
7+
There is a set of `scala-server-toolkit-jvm-*` modules that provide pure implementations of different JVM-related utilities:
138

9+
* `scala-server-toolkit-jvm-execution` - creation of thread pools,
10+
* `scala-server-toolkit-jvm-ssl` - initialization of SSL context,
11+
* `scala-server-toolkit-jvm-system` - standard in/out/err, random number generation.
12+
1413
```scala mdoc
15-
import java.util.concurrent.TimeUnit
16-
import com.avast.server.toolkit.system.SystemModule
14+
import com.avast.server.toolkit.system.console.ConsoleModule
15+
import com.avast.server.toolkit.system.random.RandomModule
1716
import zio.interop.catz._
17+
import zio.DefaultRuntime
1818
import zio.Task
1919

2020
val program = for {
21-
systemModule <- SystemModule.make[Task]
22-
currentTime <- systemModule.clock.realTime(TimeUnit.MILLISECONDS)
23-
randomNumber <- systemModule.random.nextInt
24-
_ <- systemModule.console.printLine(s"Current Unix epoch time is $currentTime ms. Random number: $randomNumber")
21+
random <- RandomModule.makeRandom[Task]
22+
randomNumber <- random.nextInt
23+
console = ConsoleModule.make[Task]
24+
_ <- console.printLine(s"Random number: $randomNumber")
2525
} yield ()
26+
27+
val runtime = new DefaultRuntime {} // this is just in example
28+
runtime.unsafeRun(program)
2629
```

example/src/main/scala/com/avast/server/toolkit/example/Main.scala

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ package com.avast.server.toolkit.example
22

33
import java.util.concurrent.TimeUnit
44

5-
import cats.effect.Resource
5+
import cats.effect.{Clock, Resource}
66
import com.avast.server.toolkit.example.config.Configuration
77
import com.avast.server.toolkit.execution.ExecutorModule
88
import com.avast.server.toolkit.pureconfig.PureConfigModule
9-
import com.avast.server.toolkit.system.SystemModule
9+
import com.avast.server.toolkit.system.console.{Console, ConsoleModule}
1010
import zio.interop.catz._
1111
import zio.{Task, ZIO}
1212

@@ -15,13 +15,12 @@ object Main extends CatsApp {
1515
def program: Resource[Task, Unit] = {
1616
for {
1717
configuration <- Resource.liftF(PureConfigModule.makeOrRaise[Task, Configuration])
18-
systemModule <- Resource.liftF(SystemModule.make[Task])
19-
executorModule <- ExecutorModule.make[Task](runtime.Platform.executor.asEC)
20-
currentTime <- Resource.liftF(systemModule.clock.realTime(TimeUnit.MILLISECONDS))
18+
executorModule <- ExecutorModule.makeFromExecutionContext[Task](runtime.Platform.executor.asEC)
19+
clock = Clock.create[Task]
20+
currentTime <- Resource.liftF(clock.realTime(TimeUnit.MILLISECONDS))
21+
console <- Resource.pure[Task, Console[Task]](ConsoleModule.make[Task])
2122
_ <- Resource.liftF(
22-
systemModule
23-
.console
24-
.printLine(s"The current Unix epoch time is $currentTime. This system has ${executorModule.numOfCpus} CPUs.")
23+
console.printLine(s"The current Unix epoch time is $currentTime. This system has ${executorModule.numOfCpus} CPUs.")
2524
)
2625
} yield ()
2726
}

jvm-execution/src/main/scala/com/avast/server/toolkit/execution/ExecutorModule.scala

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,69 +21,77 @@ import scala.language.higherKinds
2121
/** Provides necessary executors - the default one for execution of your business logic and callbacks and special one designated for
2222
* blocking operations. Also allows you to create more executors if you need them.
2323
*/
24-
class ExecutorModule[F[_]: Sync](val numOfCpus: Int, val executor: ExecutionContext, blockingExecutor: ExecutionContextExecutorService) {
24+
class ExecutorModule[F[_]: Sync](val numOfCpus: Int,
25+
val executionContext: ExecutionContext,
26+
blockingExecutor: ExecutionContextExecutorService) {
2527
module =>
2628

2729
/** Executor designated for blocking operations. */
2830
val blocker: Blocker = Blocker.liftExecutionContext(blockingExecutor)
2931

3032
/** [[java.util.concurrent.ExecutorService]] that can be used for blocking operations in Java-interop code. */
31-
lazy val blockingExecutorService: ExecutorService = blockingExecutor
33+
val blockingExecutorService: ExecutorService = blockingExecutor
3234

3335
/** Provides implicit reference to the default callback executor for easier use. */
3436
object Implicits {
3537

36-
implicit val executor: ExecutionContext = module.executor
38+
implicit val executionContext: ExecutionContext = module.executionContext
3739

3840
}
3941

4042
/** Makes [[java.util.concurrent.ThreadPoolExecutor]] according to the given config and with [[java.util.concurrent.ThreadFactory]]. */
41-
def makeThreadPoolExecutor(config: ThreadPoolExecutorConfig,
42-
threadFactory: ThreadFactory): Resource[F, ExecutionContextExecutorService] = {
43-
ExecutorModule.makeThreadPoolExecutor(config, threadFactory, new LinkedBlockingQueue).map(ExecutionContext.fromExecutorService)
43+
def makeThreadPoolExecutor(config: ThreadPoolExecutorConfig, threadFactory: ThreadFactory): Resource[F, ThreadPoolExecutor] = {
44+
ExecutorModule.makeThreadPoolExecutor(config, threadFactory, new LinkedBlockingQueue)
4445
}
4546

4647
/** Makes [[java.util.concurrent.ForkJoinPool]] according to the given config and with [[java.util.concurrent.ThreadFactory]]. */
47-
def makeForkJoinExecutor(config: ForkJoinPoolConfig,
48-
threadFactory: ForkJoinWorkerThreadFactory): Resource[F, ExecutionContextExecutorService] = {
49-
ExecutorModule.makeForkJoinPool(config, numOfCpus, threadFactory).map(ExecutionContext.fromExecutorService)
48+
def makeForkJoinPool(config: ForkJoinPoolConfig, threadFactory: ForkJoinWorkerThreadFactory): Resource[F, ForkJoinPool] = {
49+
ExecutorModule.makeForkJoinPool(config, numOfCpus, threadFactory)
5050
}
5151

5252
}
5353

5454
object ExecutorModule {
5555

56-
/** Makes [[ExecutorModule]] with default callback executor and extra [[cats.effect.Blocker]] executor for blocking operations. */
57-
def make[F[_]: Sync]: Resource[F, ExecutorModule[F]] = {
56+
/** Makes [[com.avast.server.toolkit.execution.ExecutorModule]] with default callback executor and extra [[cats.effect.Blocker]] executor
57+
* for blocking operations.
58+
*/
59+
def makeDefault[F[_]: Sync]: Resource[F, ExecutorModule[F]] = {
5860
for {
5961
numOfCpus <- Resource.liftF(Sync[F].delay(Runtime.getRuntime.availableProcessors))
6062
coreSize = numOfCpus * 2
6163
executor <- makeThreadPoolExecutor(ThreadPoolExecutorConfig(coreSize, coreSize), toolkitThreadFactory, new LinkedBlockingQueue)
6264
.map(ExecutionContext.fromExecutorService)
63-
be <- makeBlockingExecutor.map(ExecutionContext.fromExecutorService)
64-
} yield new ExecutorModule[F](numOfCpus, executor, be)
65+
blockingExecutor <- makeBlockingExecutor.map(ExecutionContext.fromExecutorService)
66+
} yield new ExecutorModule[F](numOfCpus, executor, blockingExecutor)
6567
}
6668

67-
/** Makes [[ExecutorModule]] with the provided callback executor and extra [[cats.effect.Blocker]] executor for blocking operations. */
68-
def make[F[_]: Sync](executor: ExecutionContext): Resource[F, ExecutorModule[F]] = {
69+
/** Makes [[com.avast.server.toolkit.execution.ExecutorModule]] with the provided callback executor and extra [[cats.effect.Blocker]]
70+
* executor for blocking operations.
71+
*/
72+
def makeFromExecutionContext[F[_]: Sync](executor: ExecutionContext): Resource[F, ExecutorModule[F]] = {
6973
for {
7074
numOfCpus <- Resource.liftF(Sync[F].delay(Runtime.getRuntime.availableProcessors))
71-
be <- makeBlockingExecutor.map(ExecutionContext.fromExecutorService)
72-
} yield new ExecutorModule[F](numOfCpus, executor, be)
75+
blockingExecutor <- makeBlockingExecutor.map(ExecutionContext.fromExecutorService)
76+
} yield new ExecutorModule[F](numOfCpus, executor, blockingExecutor)
7377
}
7478

75-
/** Makes [[ExecutorModule]] with executor and extra [[cats.effect.Blocker]] executor for blocking operations. */
76-
def make[F[_]: Sync](executorConfig: ThreadPoolExecutorConfig): Resource[F, ExecutorModule[F]] = {
79+
/** Makes [[com.avast.server.toolkit.execution.ExecutorModule]] with executor and extra [[cats.effect.Blocker]] executor
80+
* for blocking operations.
81+
*/
82+
def makeFromConfig[F[_]: Sync](executorConfig: ThreadPoolExecutorConfig): Resource[F, ExecutorModule[F]] = {
7783
for {
7884
numOfCpus <- Resource.liftF(Sync[F].delay(Runtime.getRuntime.availableProcessors))
7985
executor <- makeThreadPoolExecutor(executorConfig, toolkitThreadFactory, new LinkedBlockingQueue)
8086
.map(ExecutionContext.fromExecutorService)
81-
be <- makeBlockingExecutor.map(ExecutionContext.fromExecutorService)
82-
} yield new ExecutorModule[F](numOfCpus, executor, be)
87+
blockingExecutor <- makeBlockingExecutor.map(ExecutionContext.fromExecutorService)
88+
} yield new ExecutorModule[F](numOfCpus, executor, blockingExecutor)
8389
}
8490

85-
/** Makes [[ExecutorModule]] with fork-join executor and extra [[cats.effect.Blocker]] executor for blocking operations. */
86-
def makeWithForkJoin[F[_]: Sync](executorConfig: ForkJoinPoolConfig): Resource[F, ExecutorModule[F]] = {
91+
/** Makes [[com.avast.server.toolkit.execution.ExecutorModule]] with fork-join executor and extra [[cats.effect.Blocker]] executor
92+
* for blocking operations.
93+
*/
94+
def makeForkJoinFromConfig[F[_]: Sync](executorConfig: ForkJoinPoolConfig): Resource[F, ExecutorModule[F]] = {
8795
for {
8896
numOfCpus <- Resource.liftF(Sync[F].delay(Runtime.getRuntime.availableProcessors))
8997
executor <- makeForkJoinPool(executorConfig, numOfCpus, toolkitThreadFactory)

jvm-execution/src/main/scala/com/avast/server/toolkit/execution/LoggingUncaughtExceptionHandler.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ package com.avast.server.toolkit.execution
22

33
import java.lang.Thread.UncaughtExceptionHandler
44

5-
import com.typesafe.scalalogging.LazyLogging
5+
import org.slf4j.LoggerFactory
66

7-
object LoggingUncaughtExceptionHandler extends UncaughtExceptionHandler with LazyLogging {
7+
object LoggingUncaughtExceptionHandler extends UncaughtExceptionHandler {
8+
9+
private lazy val logger = LoggerFactory.getLogger("LoggingUncaughtExceptionHandler")
810

911
override def uncaughtException(t: Thread, ex: Throwable): Unit = logger.error(s"Uncaught exception on thread ${t.getName}", ex)
1012

jvm-execution/src/test/scala/com/avast/server/toolkit/execution/ExecutorModuleTest.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import org.scalatest.FunSuite
55

66
class ExecutorModuleTest extends FunSuite {
77

8-
test("ExecutorModule") {
9-
val executorModule = ExecutorModule.make[SyncIO].use(m => SyncIO.pure(m)).unsafeRunSync()
10-
assert(executorModule.executor !== executorModule.blocker.blockingContext)
8+
test("ExecutorModule initializes properly and blocking executor differs from callback executor") {
9+
val executorModule = ExecutorModule.makeDefault[SyncIO].use(m => SyncIO.pure(m)).unsafeRunSync()
10+
assert(executorModule.executionContext !== executorModule.blocker.blockingContext)
1111
}
1212

1313
}

jvm-ssl/src/main/scala/com/avast/server/toolkit/ssl/SslContextModule.scala

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import cats.effect.{Resource, Sync}
77
import cats.syntax.flatMap._
88
import cats.syntax.functor._
99
import cats.syntax.show._
10-
import javax.net.ssl.{KeyManager, KeyManagerFactory, SSLContext, TrustManager, TrustManagerFactory, X509KeyManager, X509TrustManager}
10+
import javax.net.ssl.{KeyManager, KeyManagerFactory, SSLContext, TrustManager, TrustManagerFactory}
1111

1212
import scala.language.higherKinds
1313

@@ -64,8 +64,6 @@ object SslContextModule {
6464
factory
6565
.getKeyManagers
6666
.toList
67-
.filter(_.isInstanceOf[X509KeyManager])
68-
.map(_.asInstanceOf[X509KeyManager])
6967
}
7068

7169
private def getTrustManagers(keystore: KeyStore): List[TrustManager] = {
@@ -75,8 +73,6 @@ object SslContextModule {
7573
factory
7674
.getTrustManagers
7775
.toList
78-
.filter(_.isInstanceOf[X509TrustManager])
79-
.map(_.asInstanceOf[X509TrustManager])
8076
}
8177

8278
}

jvm-ssl/src/test/scala/com/avast/server/toolkit/ssl/SslContextModuleTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import org.scalatest.FunSuite
77

88
class SslContextModuleTest extends FunSuite {
99

10-
test("SslContextModule") {
10+
test("SslContextModule initializes properly from JKS store") {
1111
val truststore = getClass.getResource("/truststore.jks").toURI.getPath
1212
val sslContext = SslContextModule
1313
.make[SyncIO](

jvm-system/src/main/scala/com/avast/server/toolkit/system/SystemModule.scala

Lines changed: 0 additions & 62 deletions
This file was deleted.

jvm-system/src/main/scala/com/avast/server/toolkit/system/console/Console.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,26 @@ trait Console[F[_]] {
1313

1414
def printLine(value: String): F[Unit]
1515

16+
def printLineToError(value: String): F[Unit]
17+
1618
def readLine: F[String]
1719

1820
}
1921

2022
object Console {
2123

22-
def apply[F[_]: Sync](in: Reader, out: OutputStream): Console[F] = new Console[F] {
24+
def apply[F[_]: Sync](in: Reader, out: OutputStream, err: OutputStream): Console[F] = new Console[F] {
2325

2426
private val F = Sync[F]
2527

2628
override def printLine(value: String): F[Unit] = F.delay {
2729
SConsole.withOut(out)(SConsole.println(value))
2830
}
2931

32+
override def printLineToError(value: String): F[Unit] = F.delay {
33+
SConsole.withErr(err)(SConsole.err.println(value))
34+
}
35+
3036
override def readLine: F[String] = F.delay {
3137
SConsole.withIn(in)(StdIn.readLine())
3238
}

0 commit comments

Comments
 (0)