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

com.twitter.finagle.stream.Stream.scala Maven / Gradle / Ivy

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

import com.twitter.finagle.stats.StatsReceiver
import com.twitter.finagle.transport.{Transport, ChannelTransport}
import com.twitter.finagle.{
  Codec, CodecFactory, Service, ServiceFactory, ServiceProxy, TooManyConcurrentRequestsException}
import com.twitter.util.{Future, Promise, Time, Closable}
import org.jboss.netty.channel.{ChannelPipelineFactory, Channels, Channel}
import org.jboss.netty.handler.codec.http.{  HttpClientCodec, HttpRequest, HttpServerCodec}

/**
 * Don't release the underlying service until the response has
 * completed.
 */
private[stream] class DelayedReleaseService(self: Service[HttpRequest, StreamResponse])
  extends ServiceProxy[HttpRequest, StreamResponse](self)
{
  @volatile private[this] var done: Future[Unit] = Future.Done

  override def apply(req: HttpRequest) = {
    if (!done.isDefined)
      Future.exception(new TooManyConcurrentRequestsException)
    else {
      val p = new Promise[Unit]
      done = p
      self(req) map { res =>
        new StreamResponse {
          def httpResponse = res.httpResponse
          def messages = res.messages
          def error = res.error
          def release() {
            p.setDone()
            res.release()
          }
        }
      } onFailure { _ => p.setDone() }
    }
  }

  override def close(deadline: Time) =
    done ensure { self.close(deadline) }
}

object Stream {
  def apply(): Stream = new Stream()
  def get() = apply()
}

class Stream extends CodecFactory[HttpRequest, StreamResponse] {
  def server = Function.const {
    new Codec[HttpRequest, StreamResponse] {
      def pipelineFactory = new ChannelPipelineFactory {
        def getPipeline = {
          val pipeline = Channels.pipeline()
          pipeline.addLast("httpCodec", new HttpServerCodec)
          pipeline
        }
      }

      override def newServerDispatcher(
          transport: Transport[Any, Any], 
          service: Service[HttpRequest, StreamResponse]): Closable =
        new StreamServerDispatcher(transport, service)
    }
  }

 def client = Function.const {
    new Codec[HttpRequest, StreamResponse] {
      def pipelineFactory = new ChannelPipelineFactory {
        def getPipeline = {
          val pipeline = Channels.pipeline()
          pipeline.addLast("httpCodec", new HttpClientCodec)
          pipeline
        }
      }

     override def newClientDispatcher(trans: Transport[Any, Any])
       : Service[HttpRequest, StreamResponse] = new StreamClientDispatcher(trans)

      // TODO: remove when the Meta[_] patch lands.
      override def prepareServiceFactory(
        underlying: ServiceFactory[HttpRequest, StreamResponse]
      ): ServiceFactory[HttpRequest, StreamResponse] =
        underlying map(new DelayedReleaseService(_))
      
      // TODO: remove when ChannelTransport is the default for clients.
      override def newClientTransport(
          ch: Channel, statsReceiver: StatsReceiver): Transport[Any, Any] =
        new ChannelTransport(ch)

    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy