blob: d39fa18722d73b611bd90eb90e05ac09f093d6c1 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
package triad
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.marshalling.sse.EventStreamMarshalling._
import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller}
import akka.http.scaladsl.model.MediaTypes
import akka.http.scaladsl.model.sse.ServerSentEvent
import akka.http.scaladsl.server.Directives._
import akka.stream.scaladsl.Source
import spray.json._
import triad.ApiProtocol._
import scala.concurrent.duration._
class Routes(repository: Repository, liveMessages: LiveMessages) {
import repository.profile.api._
// allows using scalatags templates as HTTP responses
implicit val tagMarshaller: ToEntityMarshaller[scalatags.Text.Tag] = {
Marshaller.stringMarshaller(MediaTypes.`text/html`).compose {
(tag: scalatags.Text.Tag) =>
tag.render
}
}
private val lastMessages = repository.Messages.take(100).result
private val messageStream: Source[Message, _] = {
val publisher = repository.database.stream(lastMessages)
Source
.fromPublisher(publisher)
.concat(liveMessages.feed)
}
val messages = path("messages") {
get {
onSuccess(repository.database.run(lastMessages)) { messages =>
complete(messages)
}
} ~ post {
entity(as[Message]) { message =>
extractExecutionContext { implicit ec =>
val query = repository.Messages.insertOrUpdate(message)
val action = repository.database.run(query).flatMap { _ =>
liveMessages.push(message)
}
onSuccess(action) { _ =>
complete(message)
}
}
}
}
}
val ui = pathEndOrSingleSlash {
get {
parameter("js".as[Boolean] ? true) { js =>
onSuccess(repository.database.run(lastMessages)) { messages =>
complete(TextTemplates.page(messages, js))
}
}
}
}
val live = path("live") {
get {
val src = messageStream
.map(msg => ServerSentEvent(msg.toJson.compactPrint))
.keepAlive(10.seconds, () => ServerSentEvent.heartbeat)
complete(src)
}
}
val assets = pathPrefix("assets") {
getFromResourceDirectory("assets")
}
def all = messages ~ ui ~ live ~ assets
}
|