@@ -20,12 +20,15 @@ package org.apache.spark.streaming.akka
2020import java .nio .ByteBuffer
2121import java .util .concurrent .atomic .AtomicInteger
2222
23+ import scala .concurrent .Future
2324import scala .concurrent .duration ._
2425import scala .language .postfixOps
2526import scala .reflect .ClassTag
2627
2728import akka .actor ._
2829import akka .actor .SupervisorStrategy .{Escalate , Restart }
30+ import akka .pattern .ask
31+ import akka .util .Timeout
2932import com .typesafe .config .ConfigFactory
3033
3134import org .apache .spark .{Logging , TaskContext }
@@ -105,13 +108,26 @@ abstract class ActorReceiver extends Actor {
105108 }
106109
107110 /**
108- * Store a single item of received data to Spark's memory.
111+ * Store a single item of received data to Spark's memory asynchronously .
109112 * These single items will be aggregated together into data blocks before
110113 * being pushed into Spark's memory.
111114 */
112115 def store [T ](item : T ) {
113116 context.parent ! SingleItemData (item)
114117 }
118+
119+ /**
120+ * Store a single item of received data to Spark's memory and returns a `Future`.
121+ * The `Future` will be completed when the operator finishes, or with an
122+ * `akka.pattern.AskTimeoutException` after the given timeout has expired.
123+ * These single items will be aggregated together into data blocks before
124+ * being pushed into Spark's memory.
125+ *
126+ * This method allows the user to control the flow speed using `Future`
127+ */
128+ def store [T ](item : T , timeout : Timeout ): Future [Unit ] = {
129+ context.parent.ask(AskStoreSingleItemData (item))(timeout).map(_ => ())(context.dispatcher)
130+ }
115131}
116132
117133/**
@@ -162,6 +178,19 @@ abstract class JavaActorReceiver extends UntypedActor {
162178 def store [T ](item : T ) {
163179 context.parent ! SingleItemData (item)
164180 }
181+
182+ /**
183+ * Store a single item of received data to Spark's memory and returns a `Future`.
184+ * The `Future` will be completed when the operator finishes, or with an
185+ * `akka.pattern.AskTimeoutException` after the given timeout has expired.
186+ * These single items will be aggregated together into data blocks before
187+ * being pushed into Spark's memory.
188+ *
189+ * This method allows the user to control the flow speed using `Future`
190+ */
191+ def store [T ](item : T , timeout : Timeout ): Future [Unit ] = {
192+ context.parent.ask(AskStoreSingleItemData (item))(timeout).map(_ => ())(context.dispatcher)
193+ }
165194}
166195
167196/**
@@ -179,8 +208,10 @@ case class Statistics(numberOfMsgs: Int,
179208/** Case class to receive data sent by child actors */
180209private [akka] sealed trait ActorReceiverData
181210private [akka] case class SingleItemData [T ](item : T ) extends ActorReceiverData
211+ private [akka] case class AskStoreSingleItemData [T ](item : T ) extends ActorReceiverData
182212private [akka] case class IteratorData [T ](iterator : Iterator [T ]) extends ActorReceiverData
183213private [akka] case class ByteBufferData (bytes : ByteBuffer ) extends ActorReceiverData
214+ private [akka] object Ack extends ActorReceiverData
184215
185216/**
186217 * Provides Actors as receivers for receiving stream.
@@ -233,6 +264,12 @@ private[akka] class ActorReceiverSupervisor[T: ClassTag](
233264 store(msg.asInstanceOf [T ])
234265 n.incrementAndGet
235266
267+ case AskStoreSingleItemData (msg) =>
268+ logDebug(" received single sync" )
269+ store(msg.asInstanceOf [T ])
270+ n.incrementAndGet
271+ sender() ! Ack
272+
236273 case ByteBufferData (bytes) =>
237274 logDebug(" received bytes" )
238275 store(bytes)
0 commit comments