summaryrefslogtreecommitdiff
path: root/cask
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2019-09-15 13:11:17 +0800
committerLi Haoyi <haoyi.sg@gmail.com>2019-09-15 13:19:12 +0800
commitf158811a79f702a406e3dd2b961f3b085e6c47c0 (patch)
tree190d0b7eb7d3ea4bcfb7364bd8c73fa5315c966b /cask
parent0e098a93da94c251eb05d42bc7ef48394600508c (diff)
downloadcask-f158811a79f702a406e3dd2b961f3b085e6c47c0.tar.gz
cask-f158811a79f702a406e3dd2b961f3b085e6c47c0.tar.bz2
cask-f158811a79f702a406e3dd2b961f3b085e6c47c0.zip
Sketch out a standard `cask.Logger` interface and standardize dependency injection via case class implicits
Diffstat (limited to 'cask')
-rw-r--r--cask/src/cask/endpoints/WebSocketEndpoint.scala9
-rw-r--r--cask/src/cask/internal/BatchActor.scala7
-rw-r--r--cask/src/cask/main/Main.scala16
-rw-r--r--cask/src/cask/main/Routes.scala5
-rw-r--r--cask/src/cask/package.scala6
-rw-r--r--cask/src/cask/util/Logger.scala18
6 files changed, 46 insertions, 15 deletions
diff --git a/cask/src/cask/endpoints/WebSocketEndpoint.scala b/cask/src/cask/endpoints/WebSocketEndpoint.scala
index 6728581..a836321 100644
--- a/cask/src/cask/endpoints/WebSocketEndpoint.scala
+++ b/cask/src/cask/endpoints/WebSocketEndpoint.scala
@@ -4,6 +4,7 @@ import java.nio.ByteBuffer
import cask.internal.{BatchActor, Router}
import cask.model.Request
+import cask.util.Logger
import io.undertow.websockets.WebSocketConnectionCallback
import io.undertow.websockets.core.{AbstractReceiveListener, BufferedBinaryMessage, BufferedTextMessage, CloseMessage, WebSocketChannel, WebSockets}
import io.undertow.websockets.spi.WebSocketHttpExchange
@@ -31,7 +32,8 @@ class websocket(val path: String, override val subpath: Boolean = false)
def wrapPathSegment(s: String): Seq[String] = Seq(s)
}
-case class WsHandler(f: WsChannelActor => BatchActor[WsActor.Event])(implicit ec: ExecutionContext)
+case class WsHandler(f: WsChannelActor => BatchActor[WsActor.Event])
+ (implicit ec: ExecutionContext, log: Logger)
extends WebsocketResult with WebSocketConnectionCallback {
def onConnect(exchange: WebSocketHttpExchange, channel: WebSocketChannel): Unit = {
val actor = f(new WsChannelActor(channel))
@@ -67,7 +69,8 @@ extends WebsocketResult with WebSocketConnectionCallback {
}
}
-class WsChannelActor(channel: WebSocketChannel)(implicit ec: ExecutionContext)
+class WsChannelActor(channel: WebSocketChannel)
+ (implicit ec: ExecutionContext, log: Logger)
extends BatchActor[WsActor.Event]{
def run(items: Seq[WsActor.Event]): Unit = items.foreach{
case WsActor.Text(value) => WebSockets.sendTextBlocking(value, channel)
@@ -79,7 +82,7 @@ extends BatchActor[WsActor.Event]{
}
case class WsActor(handle: PartialFunction[WsActor.Event, Unit])
- (implicit ec: ExecutionContext)
+ (implicit ec: ExecutionContext, log: Logger)
extends BatchActor[WsActor.Event]{
def run(items: Seq[WsActor.Event]): Unit = {
items.foreach(handle.applyOrElse(_, (x: WsActor.Event) => ()))
diff --git a/cask/src/cask/internal/BatchActor.scala b/cask/src/cask/internal/BatchActor.scala
index 1566a18..60b5f57 100644
--- a/cask/src/cask/internal/BatchActor.scala
+++ b/cask/src/cask/internal/BatchActor.scala
@@ -1,5 +1,7 @@
package cask.internal
+import cask.util.Logger
+
import scala.collection.mutable
import scala.concurrent.ExecutionContext
@@ -8,7 +10,8 @@ import scala.concurrent.ExecutionContext
* of queued items. `run` handles items in batches, to allow for batch
* processing optimizations to be used where relevant.
*/
-abstract class BatchActor[T]()(implicit ec: ExecutionContext) {
+abstract class BatchActor[T]()(implicit ec: ExecutionContext,
+ log: Logger) {
def run(items: Seq[T]): Unit
private val queue = new mutable.Queue[T]()
@@ -24,7 +27,7 @@ abstract class BatchActor[T]()(implicit ec: ExecutionContext) {
def runWithItems(): Unit = {
val items = synchronized(queue.dequeueAll(_ => true))
try run(items)
- catch{case e: Throwable => e.printStackTrace()}
+ catch{case e: Throwable => log.exception(e)}
synchronized{
if (queue.nonEmpty) ec.execute(() => runWithItems())
else{
diff --git a/cask/src/cask/main/Main.scala b/cask/src/cask/main/Main.scala
index a5b4dc4..94f7f41 100644
--- a/cask/src/cask/main/Main.scala
+++ b/cask/src/cask/main/Main.scala
@@ -13,7 +13,7 @@ import io.undertow.util.HttpString
* A combination of [[cask.Main]] and [[cask.Routes]], ideal for small
* one-file web applications.
*/
-class MainRoutes extends BaseMain with Routes{
+class MainRoutes extends Main with Routes{
def allRoutes = Seq(this)
}
@@ -24,16 +24,13 @@ class MainRoutes extends BaseMain with Routes{
* serve, and override various properties on [[Main]] in order to configure
* application-wide properties.
*/
-class Main(servers0: Routes*) extends BaseMain{
- def allRoutes = servers0.toSeq
-}
-abstract class BaseMain{
+abstract class Main{
def mainDecorators = Seq.empty[cask.main.RawDecorator]
def allRoutes: Seq[Routes]
def port: Int = 8080
def host: String = "localhost"
def debugMode: Boolean = true
-
+ implicit def log = new cask.util.Logger.Console()
lazy val routeList = for{
routes <- allRoutes
route <- routes.caskMetadata.value.map(x => x: EndpointMetadata[_])
@@ -126,11 +123,16 @@ abstract class BaseMain{
routes: Routes,
metadata: EndpointMetadata[_],
e: Router.Result.Error) = {
+ e match {
+ case e: Router.Result.Error.Exception => log.exception(e.t)
+ case _ => // do nothing
+ }
val statusCode = e match {
case _: Router.Result.Error.Exception => 500
case _: Router.Result.Error.InvalidArguments => 400
case _: Router.Result.Error.MismatchedArguments => 400
}
+
val str =
if (!debugMode) s"Error $statusCode: ${Status.codesToStatus(statusCode).reason}"
else ErrorMsgs.formatInvokeError(
@@ -138,7 +140,7 @@ abstract class BaseMain{
metadata.entryPoint.asInstanceOf[EntryPoint[cask.main.Routes, _]],
e
)
- println(str)
+
Response(str, statusCode = statusCode)
}
diff --git a/cask/src/cask/main/Routes.scala b/cask/src/cask/main/Routes.scala
index be33581..9be9f50 100644
--- a/cask/src/cask/main/Routes.scala
+++ b/cask/src/cask/main/Routes.scala
@@ -1,9 +1,7 @@
package cask.main
-
import language.experimental.macros
-
trait Routes{
def decorators = Seq.empty[cask.main.RawDecorator]
@@ -15,5 +13,6 @@ trait Routes{
protected[this] def initialize()(implicit routes: RoutesEndpointsMetadata[this.type]): Unit = {
metadata0 = routes
}
-}
+ def log: cask.util.Logger
+}
diff --git a/cask/src/cask/package.scala b/cask/src/cask/package.scala
index f72e14b..93c1161 100644
--- a/cask/src/cask/package.scala
+++ b/cask/src/cask/package.scala
@@ -1,3 +1,5 @@
+import cask.util.Logger
+
package object cask {
// model
type Response[T] = model.Response[T]
@@ -45,4 +47,8 @@ package object cask {
type WsActor = cask.endpoints.WsActor
val WsActor = cask.endpoints.WsActor
type WsChannelActor = cask.endpoints.WsChannelActor
+
+ // util
+ type Logger = util.Logger
+ val Logger = util.Logger
}
diff --git a/cask/src/cask/util/Logger.scala b/cask/src/cask/util/Logger.scala
new file mode 100644
index 0000000..8dc3156
--- /dev/null
+++ b/cask/src/cask/util/Logger.scala
@@ -0,0 +1,18 @@
+package cask.util
+
+import sourcecode.{File, Line, Text}
+
+trait Logger {
+ def exception(t: Throwable): Unit
+
+ def debug(t: sourcecode.Text[Any])(implicit f: sourcecode.File, line: sourcecode.Line): Unit
+}
+object Logger{
+ class Console() extends Logger{
+ def exception(t: Throwable): Unit = t.printStackTrace()
+
+ def debug(t: Text[Any])(implicit f: File, line: Line): Unit = {
+ println(f.value.split('/').last + ":" + line + " " + t.source + " " + pprint.apply(t.value))
+ }
+ }
+} \ No newline at end of file