All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.twitter.finagle.example.stream.StreamServer.scala Maven / Gradle / Ivy

The newest version!
package com.twitter.finagle.example.stream

import com.twitter.concurrent.{Broker, Offer}
import com.twitter.finagle.builder.{Server, ServerBuilder}
import com.twitter.finagle.Service
import com.twitter.finagle.stream.{Stream, StreamResponse}
import com.twitter.io.Charsets
import com.twitter.util.{Future, Timer, JavaTimer}
import com.twitter.conversions.time._
import java.net.InetSocketAddress
import org.jboss.netty.buffer.ChannelBuffer
import org.jboss.netty.buffer.ChannelBuffers.copiedBuffer
import org.jboss.netty.handler.codec.http.{DefaultHttpResponse, HttpRequest, HttpResponseStatus}
import scala.util.Random

/**
 * An example of a streaming server using HTTP Chunking. The Stream
 * Codec uses HTTP Chunks and newline delimited items.
 */
object StreamServer {
  // "tee" messages across all of the registered brokers.
  val addBroker = new Broker[Broker[ChannelBuffer]]
  val remBroker = new Broker[Broker[ChannelBuffer]]
  val messages = new Broker[ChannelBuffer]
  private[this] def tee(receivers: Set[Broker[ChannelBuffer]]) {
    Offer.select(
      addBroker.recv { b => tee(receivers + b) },
      remBroker.recv { b => tee(receivers - b) },
      if (receivers.isEmpty) Offer.never else {
        messages.recv { m =>
          Future.join(receivers map { _ ! m } toSeq) ensure tee(receivers)
        }
      }
    )
  }

  private[this] def produce(r: Random, t: Timer) {
    t.schedule(1.second.fromNow) {
      val m = copiedBuffer(r.nextInt.toString + "\n", Charsets.Utf8)
      messages.send(m) andThen produce(r, t)
    }
  }

  // start the two processes.
  tee(Set())
  produce(new Random, new JavaTimer)

  def main(args: Array[String]) {
    val myService = new Service[HttpRequest, StreamResponse] {
      def apply(request: HttpRequest) = Future {
        val subscriber = new Broker[ChannelBuffer]
        addBroker ! subscriber
        new StreamResponse {
          val httpResponse = new DefaultHttpResponse(
            request.getProtocolVersion, HttpResponseStatus.OK)
          def messages = subscriber.recv
          def error = new Broker[Throwable].recv
          def release() = {
            remBroker ! subscriber
            // sink any existing messages, so they
            // don't hold up the upstream.
            subscriber.recv foreach { _ => () }
          }
        }
      }
    }

    val server: Server = ServerBuilder()
      .codec(Stream())
      .bindTo(new InetSocketAddress(8080))
      .name("streamserver")
      .build(myService)
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy