diff options
Diffstat (limited to 'server/src/main/scala/Routes.scala')
-rw-r--r-- | server/src/main/scala/Routes.scala | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/server/src/main/scala/Routes.scala b/server/src/main/scala/Routes.scala new file mode 100644 index 0000000..d39fa18 --- /dev/null +++ b/server/src/main/scala/Routes.scala @@ -0,0 +1,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 + +} |