akka.stream.scaladsl.Framing Scala Examples
The following examples show how to use akka.stream.scaladsl.Framing.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example.
Example 1
Source File: TcpEcho.scala From akka_streams_tutorial with MIT License | 5 votes |
package sample.stream import akka.actor.ActorSystem import akka.stream.scaladsl.{Flow, Framing, Keep, Sink, Source, Tcp} import akka.util.ByteString import scala.concurrent.Future import scala.util.{Failure, Success} object TcpEcho extends App { val systemServer = ActorSystem("TcpEchoServer") val systemClient = ActorSystem("TcpEchoClient") var serverBinding: Future[Tcp.ServerBinding] = _ if (args.isEmpty) { val (address, port) = ("127.0.0.1", 6000) serverBinding = server(systemServer, address, port) (1 to 10).par.foreach(each => client(each, systemClient, address, port)) } else { val (address, port) = if (args.length == 3) (args(1), args(2).toInt) else ("127.0.0.1", 6000) if (args(0) == "server") { serverBinding = server(systemServer, address, port) } else if (args(0) == "client") { client(1, systemClient, address, port) } } def server(system: ActorSystem, address: String, port: Int): Future[Tcp.ServerBinding] = { implicit val sys = system implicit val ec = system.dispatcher val handler = Sink.foreach[Tcp.IncomingConnection] { connection => // parse incoming commands and append ! val commandParser = Flow[String].takeWhile(_ != "BYE").map(_ + "!") val welcomeMsg = s"Welcome to: ${connection.localAddress}, you are: ${connection.remoteAddress}!" val welcomeSource = Source.single(welcomeMsg) val serverEchoFlow = Flow[ByteString] .via(Framing.delimiter( //chunk the inputs up into actual lines of text ByteString("\n"), maximumFrameLength = 256, allowTruncation = true)) .map(_.utf8String) .via(commandParser) .merge(welcomeSource) // merge the initial banner after parser .map(_ + "\n") .map(ByteString(_)) .watchTermination()((_, done) => done.onComplete { case Failure(err) => println(s"Server flow failed: $err") case _ => println(s"Server flow terminated for client: ${connection.remoteAddress}") }) connection.handleWith(serverEchoFlow) } val connections = Tcp().bind(interface = address, port = port) val binding = connections.watchTermination()(Keep.left).to(handler).run() binding.onComplete { case Success(b) => println("Server started, listening on: " + b.localAddress) case Failure(e) => println(s"Server could not bind to: $address:$port: ${e.getMessage}") system.terminate() } binding } def client(id: Int, system: ActorSystem, address: String, port: Int): Unit = { implicit val sys = system implicit val ec = system.dispatcher val connection: Flow[ByteString, ByteString, Future[Tcp.OutgoingConnection]] = Tcp().outgoingConnection(address, port) val testInput = ('a' to 'z').map(ByteString(_)) ++ Seq(ByteString("BYE")) val source = Source(testInput).via(connection) val closed = source.runForeach(each => println(s"Client: $id received echo: ${each.utf8String}")) closed.onComplete(each => println(s"Client: $id closed: $each")) } }
Example 2
Source File: SplitWhen.scala From akka_streams_tutorial with MIT License | 5 votes |
package sample.stream_shared_state import java.nio.file.Paths import akka.NotUsed import akka.actor.ActorSystem import akka.stream.IOResult import akka.stream.scaladsl.{FileIO, Flow, Framing, Keep, Sink, Source} import akka.util.ByteString import org.slf4j.{Logger, LoggerFactory} import scala.concurrent.Future import scala.util.{Failure, Success} object SplitWhen extends App { val logger: Logger = LoggerFactory.getLogger(this.getClass) implicit val system = ActorSystem("SplitWhen") implicit val executionContext = system.dispatcher val nonLinearCapacityFactor = 100 //raise to see how it scales val filename = "splitWhen.csv" def genResourceFile() = { logger.info(s"Writing resource file: $filename...") def fileSink(filename: String): Sink[String, Future[IOResult]] = Flow[String] .map(s => ByteString(s + "\n")) .toMat(FileIO.toPath(Paths.get(filename)))(Keep.right) Source.fromIterator(() => (1 to nonLinearCapacityFactor).toList.combinations(2)) .map(each => s"${each.head},${each.last}") .runWith(fileSink(filename)) } val sourceOfLines = FileIO.fromPath(Paths.get(filename)) .via(Framing.delimiter(ByteString("\n"), maximumFrameLength = 1024, allowTruncation = true) .map(_.utf8String)) val csvToRecord: Flow[String, Record, NotUsed] = Flow[String] .map(_.split(",").map(_.trim)) .map(stringArrayToRecord) val terminationHook: Flow[Record, Record, Unit] = Flow[Record] .watchTermination() { (_, done) => done.onComplete { case Failure(err) => logger.info(s"Flow failed: $err") case _ => system.terminate(); logger.info(s"Flow terminated") } } val printSink = Sink.foreach[Vector[Record]](each => println(s"Reached sink: $each")) private def stringArrayToRecord(cols: Array[String]) = Record(cols(0), cols(1)) private def hasKeyChanged = { () => { var lastRecordKey: Option[String] = None currentRecord: Record => lastRecordKey match { case Some(currentRecord.key) | None => lastRecordKey = Some(currentRecord.key) List((currentRecord, false)) case _ => lastRecordKey = Some(currentRecord.key) List((currentRecord, true)) } } } genResourceFile().onComplete { case Success(_) => logger.info(s"Start processing...") sourceOfLines .via(csvToRecord) .via(terminationHook) .statefulMapConcat(hasKeyChanged) // stateful decision .splitWhen(_._2) // split when key has changed .map(_._1) // proceed with payload .fold(Vector.empty[Record])(_ :+ _) // sum payload .mergeSubstreams // better performance, but why? .runWith(printSink) case Failure(exception) => logger.info(s"Exception: $exception") } case class Record(key: String, value: String) }
Example 3
Source File: LogEntityMarshaller.scala From 006877 with MIT License | 5 votes |
package aia.stream import akka.NotUsed import akka.stream.scaladsl.Framing import akka.stream.scaladsl.JsonFraming import akka.http.scaladsl.model.HttpCharsets._ import akka.http.scaladsl.model.MediaTypes._ import akka.http.scaladsl.model.headers.Accept import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ import akka.http.scaladsl.model._ import akka.stream.scaladsl.Source import akka.util.ByteString import spray.json._ import akka.http.scaladsl.marshalling.Marshaller import akka.http.scaladsl.marshalling.ToEntityMarshaller object LogEntityMarshaller extends EventMarshalling { type LEM = ToEntityMarshaller[Source[ByteString, _]] def create(maxJsonObject: Int): LEM = { val js = ContentTypes.`application/json` val txt = ContentTypes.`text/plain(UTF-8)` val jsMarshaller = Marshaller.withFixedContentType(js) { src:Source[ByteString, _] => HttpEntity(js, src) } val txtMarshaller = Marshaller.withFixedContentType(txt) { src:Source[ByteString, _] => HttpEntity(txt, toText(src, maxJsonObject)) } Marshaller.oneOf(jsMarshaller, txtMarshaller) } def toText(src: Source[ByteString, _], maxJsonObject: Int): Source[ByteString, _] = { src.via(LogJson.jsonToLogFlow(maxJsonObject)) } }
Example 4
Source File: EventUnmarshaller.scala From 006877 with MIT License | 5 votes |
package aia.stream import scala.concurrent.{ ExecutionContext, Future } import akka.NotUsed import akka.stream.scaladsl.Framing import akka.stream.scaladsl.JsonFraming import akka.stream.Materializer import akka.stream.scaladsl.Source import akka.http.scaladsl.model.HttpCharsets._ import akka.http.scaladsl.model.MediaTypes._ import akka.http.scaladsl.model.headers.Accept import akka.http.scaladsl.marshalling._ import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ import akka.http.scaladsl.model._ import akka.util.ByteString import spray.json._ import akka.http.scaladsl.unmarshalling.Unmarshaller import akka.http.scaladsl.unmarshalling.Unmarshaller._ object EventUnmarshaller extends EventMarshalling { val supported = Set[ContentTypeRange]( ContentTypes.`text/plain(UTF-8)`, ContentTypes.`application/json` ) def create(maxLine: Int, maxJsonObject: Int) = { new Unmarshaller[HttpEntity, Source[Event, _]] { def apply(entity: HttpEntity)(implicit ec: ExecutionContext, materializer: Materializer): Future[Source[Event, _]] = { val future = entity.contentType match { case ContentTypes.`text/plain(UTF-8)` => Future.successful(LogJson.textInFlow(maxLine)) case ContentTypes.`application/json` => Future.successful(LogJson.jsonInFlow(maxJsonObject)) case other => Future.failed( new UnsupportedContentTypeException(supported) ) } future.map(flow => entity.dataBytes.via(flow))(ec) } }.forContentTypes(supported.toList:_*) } }
Example 5
Source File: Event.scala From 006877 with MIT License | 5 votes |
package aia.stream import java.io.File import java.time.ZonedDateTime import scala.concurrent.Future import akka.NotUsed import akka.util.ByteString import akka.stream.IOResult import akka.stream.scaladsl.{ Source, FileIO, Framing } import scala.concurrent.duration.FiniteDuration case class Event( host: String, service: String, state: State, time: ZonedDateTime, description: String, tag: Option[String] = None, metric: Option[Double] = None ) sealed trait State case object Critical extends State case object Error extends State case object Ok extends State case object Warning extends State object State { def norm(str: String): String = str.toLowerCase def norm(state: State): String = norm(state.toString) val ok = norm(Ok) val warning = norm(Warning) val error = norm(Error) val critical = norm(Critical) def unapply(str: String): Option[State] = { val normalized = norm(str) if(normalized == norm(Ok)) Some(Ok) else if(normalized == norm(Warning)) Some(Warning) else if(normalized == norm(Error)) Some(Error) else if(normalized == norm(Critical)) Some(Critical) else None } } case class LogReceipt(logId: String, written: Long) case class ParseError(logId: String, msg: String)
Example 6
Source File: LogJson.scala From 006877 with MIT License | 5 votes |
package aia.stream import java.nio.file.{ Files, Path } import java.io.File import java.time.ZonedDateTime import scala.concurrent.duration._ import scala.concurrent.ExecutionContext import scala.concurrent.Future import scala.util.{ Success, Failure } import akka.Done import akka.actor._ import akka.util.ByteString import akka.stream.{ ActorAttributes, ActorMaterializer, IOResult } import akka.stream.scaladsl.JsonFraming import akka.stream.scaladsl.{ FileIO, BidiFlow, Flow, Framing, Keep, Sink, Source } import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ import akka.http.scaladsl.marshalling.Marshal import akka.http.scaladsl.model._ import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server._ import spray.json._ object LogJson extends EventMarshalling with NotificationMarshalling with MetricMarshalling { def textInFlow(maxLine: Int) = { Framing.delimiter(ByteString("\n"), maxLine) .map(_.decodeString("UTF8")) .map(LogStreamProcessor.parseLineEx) .collect { case Some(e) => e } } def jsonInFlow(maxJsonObject: Int) = { JsonFraming.objectScanner(maxJsonObject) .map(_.decodeString("UTF8").parseJson.convertTo[Event]) } def jsonFramed(maxJsonObject: Int) = JsonFraming.objectScanner(maxJsonObject) val jsonOutFlow = Flow[Event].map { event => ByteString(event.toJson.compactPrint) } val notifyOutFlow = Flow[Summary].map { ws => ByteString(ws.toJson.compactPrint) } val metricOutFlow = Flow[Metric].map { m => ByteString(m.toJson.compactPrint) } val textOutFlow = Flow[Event].map{ event => ByteString(LogStreamProcessor.logLine(event)) } def logToJson(maxLine: Int) = { BidiFlow.fromFlows(textInFlow(maxLine), jsonOutFlow) } def jsonToLog(maxJsonObject: Int) = { BidiFlow.fromFlows(jsonInFlow(maxJsonObject), textOutFlow) } def logToJsonFlow(maxLine: Int) = { logToJson(maxLine).join(Flow[Event]) } def jsonToLogFlow(maxJsonObject: Int) = { jsonToLog(maxJsonObject).join(Flow[Event]) } }
Example 7
Source File: FileUploadStream.scala From introduction-to-akkahttp with Apache License 2.0 | 5 votes |
package com.shashank.akkahttp.basic.routing import akka.http.scaladsl.model.{ContentTypes, HttpEntity, Multipart, StatusCodes} import akka.http.scaladsl.server.Directives._ import akka.stream.scaladsl.Framing import akka.util.ByteString import scala.concurrent.Future object FileUploadStream extends BaseSpec{ def main(args: Array[String]) { val route = extractRequestContext { ctx => implicit val materializer = ctx.materializer implicit val ec = ctx.executionContext fileUpload("csv") { case (metadata, byteSource) => val sumF: Future[Int] = // sum the numbers as they arrive so that we can byteSource.via(Framing.delimiter(ByteString("\n"), 1024)) .mapConcat(_.utf8String.split(",").toVector) .map(_.toInt) .runFold(0) { (acc, n) => acc + n } onSuccess(sumF) { sum => complete(s"Sum: $sum") } } } //Test file upload stream val multipartForm = Multipart.FormData(Multipart.FormData.BodyPart.Strict( "csv", HttpEntity(ContentTypes.`text/plain(UTF-8)`, "2,3,5\n7,11,13,17,23\n29,31,37\n"), Map("filename" -> "primes.csv"))) Post("/", multipartForm) ~> route ~> check { status shouldEqual StatusCodes.OK responseAs[String] shouldEqual "Sum: 178" } system.terminate() } } //File upload direct //curl --form "[email protected]" http://<host>:<port>
Example 8
Source File: UploadingFileServer.scala From Akka-Cookbook with MIT License | 5 votes |
package com.packt.chapter9 import akka.http.scaladsl.model.Multipart import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.HttpApp import akka.http.scaladsl.settings.ServerSettings import akka.stream.scaladsl.Framing import akka.util.ByteString import com.typesafe.config.ConfigFactory import scala.concurrent.duration._ object UploadingFileServer extends HttpApp { val route = extractRequestContext { ctx => implicit val materializer = ctx.materializer implicit val ec = ctx.executionContext path("regularupload") { entity(as[Multipart.FormData]) { formData => val partsFuture = formData.parts.mapAsync(1) { b => b.toStrict(2.seconds).map(_.entity.data.utf8String) }.runFold(List.empty[String])(_ :+ _) onSuccess(partsFuture) { allParts => complete { val wholeFile = allParts.mkString s"Regular upload: submitted file has ${wholeFile.split("\n").size} lines" } } } } ~ path("streamupload") { entity(as[Multipart.FormData]) { formData => val partsFuture = formData.parts.mapAsync(1) { b => b.entity.dataBytes .via(Framing.delimiter(ByteString("\n"), 1024, allowTruncation = true)) .map(_ => 1) .runReduce(_ + _) }.runReduce(_ + _) onSuccess(partsFuture) { lines => complete { s"Regular upload: submitted file has $lines lines" } } } } } } object UploadingFileServerApplication extends App { UploadingFileServer.startServer("0.0.0.0", 8088, ServerSettings(ConfigFactory.load)) }
Example 9
Source File: AkkaResponseHandler.scala From chronicler with Apache License 2.0 | 5 votes |
package com.github.fsanaulla.chronicler.akka.shared.handlers import akka.http.scaladsl.model.HttpResponse import akka.stream.scaladsl.{Framing, Source} import akka.util.ByteString import com.github.fsanaulla.chronicler.akka.shared.implicits._ import com.github.fsanaulla.chronicler.core.alias.ErrorOr import com.github.fsanaulla.chronicler.core.components.{JsonHandler, ResponseHandler} import com.github.fsanaulla.chronicler.core.either import com.github.fsanaulla.chronicler.core.either.EitherOps import com.github.fsanaulla.chronicler.core.jawn.RichJParser import com.github.fsanaulla.chronicler.core.model.{InfluxReader, ParsingException} import org.typelevel.jawn.ast.{JArray, JParser} import scala.concurrent.{ExecutionContext, Future} import scala.reflect.ClassTag class AkkaResponseHandler( jsonHandler: JsonHandler[Future, HttpResponse] )(implicit ex: ExecutionContext) extends ResponseHandler[Future, HttpResponse](jsonHandler) { final def queryChunkedResultJson(response: HttpResponse): Source[ErrorOr[Array[JArray]], Any] = { response.entity.dataBytes .via(Framing.delimiter(ByteString("\n"), Int.MaxValue)) .map(_.utf8String) .map(JParser.parseFromStringEither) .map( _.flatMapRight( jv => jsonHandler .queryResult(jv) .toRight[Throwable](new ParsingException("Can't extract query result from response")) ) ) } final def queryChunkedResult[T: ClassTag]( response: HttpResponse )(implicit rd: InfluxReader[T] ): Source[ErrorOr[Array[T]], Any] = { queryChunkedResultJson(response) .map(_.flatMapRight { arr => either.array(arr.map(rd.read)) }) } }
Example 10
Source File: TelnetEchoApp.scala From asura with MIT License | 5 votes |
package asura.dubbo.telnet import akka.actor.ActorSystem import akka.stream.ActorMaterializer import akka.stream.scaladsl.{Flow, Framing, Tcp} import akka.util.ByteString import com.typesafe.scalalogging.Logger object TelnetEchoApp { val logger = Logger("TelnetEchoApp") implicit val system = ActorSystem("telnet") implicit val ec = system.dispatcher implicit val materializer = ActorMaterializer() val echo = Flow[ByteString] .via(Framing.delimiter(ByteString("\n"), maximumFrameLength = 256, allowTruncation = false)) .map(_.utf8String) .map(txt => { logger.info(s"got(${txt.length}):${txt}") txt + "\n" }) .map(ByteString(_)) def main(args: Array[String]): Unit = { val connections = Tcp().bind("127.0.0.1", 8888) connections runForeach { connection => logger.info(s"New connection from: ${connection.remoteAddress}") connection.handleWith(echo) } } }
Example 11
Source File: EchoDemo.scala From fusion-data with Apache License 2.0 | 5 votes |
package example.akkastream.streamio import akka.NotUsed import akka.actor.ActorSystem import akka.stream.ActorMaterializer import akka.stream.scaladsl.{ Flow, Framing, Sink, Source, Tcp } import akka.util.ByteString import example.akkastream.streamio.EchoServer.system import scala.concurrent.Future import scala.io.StdIn object EchoServer extends App { implicit val system = ActorSystem() implicit val mat = ActorMaterializer() val connections = Tcp().bind("localhost", 8888) connections.runForeach { connection => println(s"New connection from: ${connection.remoteAddress}") val echo: Flow[ByteString, ByteString, NotUsed] = Flow[ByteString] .via(Framing.delimiter(ByteString("\n"), 256, true)) .map(_.utf8String) .map(_ + "!!!\n") .map(ByteString(_)) connection.handleWith(echo) } StdIn.readLine() system.terminate() } object EchoClient extends App { implicit val system = ActorSystem() implicit val mat = ActorMaterializer() val connection = Tcp().outgoingConnection("localhost", 8888) val replParser = Flow[String].takeWhile(_ != "q").concat(Source.single("BYE")).map { elem => println(s"send msg: $elem") ByteString(s"$elem\n") } val repl = Flow[ByteString] .via(Framing.delimiter(ByteString("\n"), maximumFrameLength = 256, allowTruncation = true)) .map(_.utf8String) .map(text => println("Server: " + text)) .map(_ => StdIn.readLine("> ")) .via(replParser) val connected: Future[Tcp.OutgoingConnection] = connection.join(repl).run() // StdIn.readLine() // system.terminate() } object EchoDemo {}