replace unicode arrows
* ⇒, →, ← * because we don't want to show them in documentation snippets and then it's complicated to avoid that when snippets are located in src/test/scala in individual modules * dont replace object `→` in FSM.scala and PersistentFSM.scala
This commit is contained in:
parent
e4d38f92a4
commit
5c96a5f556
1521 changed files with 18846 additions and 18786 deletions
|
|
@ -20,9 +20,9 @@ import scala.util.control.NonFatal
|
|||
* INTERNAL API
|
||||
*/
|
||||
@InternalApi private[akka] final class UnfoldResourceSourceAsync[T, S](
|
||||
create: () ⇒ Future[S],
|
||||
readData: (S) ⇒ Future[Option[T]],
|
||||
close: (S) ⇒ Future[Done]) extends GraphStage[SourceShape[T]] {
|
||||
create: () => Future[S],
|
||||
readData: (S) => Future[Option[T]],
|
||||
close: (S) => Future[Done]) extends GraphStage[SourceShape[T]] {
|
||||
val out = Outlet[T]("UnfoldResourceSourceAsync.out")
|
||||
override val shape = SourceShape(out)
|
||||
override def initialAttributes: Attributes = DefaultAttributes.unfoldResourceSourceAsync
|
||||
|
|
@ -33,83 +33,83 @@ import scala.util.control.NonFatal
|
|||
private var state: Option[S] = None
|
||||
|
||||
private val createdCallback = getAsyncCallback[Try[S]] {
|
||||
case Success(resource) ⇒
|
||||
case Success(resource) =>
|
||||
state = Some(resource)
|
||||
if (isAvailable(out)) onPull()
|
||||
case Failure(t) ⇒ failStage(t)
|
||||
case Failure(t) => failStage(t)
|
||||
}.invokeWithFeedback _
|
||||
|
||||
private val errorHandler: PartialFunction[Throwable, Unit] = {
|
||||
case NonFatal(ex) ⇒ decider(ex) match {
|
||||
case Supervision.Stop ⇒
|
||||
case NonFatal(ex) => decider(ex) match {
|
||||
case Supervision.Stop =>
|
||||
failStage(ex)
|
||||
case Supervision.Restart ⇒ restartResource()
|
||||
case Supervision.Resume ⇒ onPull()
|
||||
case Supervision.Restart => restartResource()
|
||||
case Supervision.Resume => onPull()
|
||||
}
|
||||
}
|
||||
|
||||
private val readCallback = getAsyncCallback[Try[Option[T]]] {
|
||||
case Success(data) ⇒ data match {
|
||||
case Some(d) ⇒ push(out, d)
|
||||
case None ⇒
|
||||
case Success(data) => data match {
|
||||
case Some(d) => push(out, d)
|
||||
case None =>
|
||||
// end of resource reached, lets close it
|
||||
state match {
|
||||
case Some(resource) ⇒
|
||||
case Some(resource) =>
|
||||
close(resource).onComplete(getAsyncCallback[Try[Done]] {
|
||||
case Success(Done) ⇒ completeStage()
|
||||
case Failure(ex) ⇒ failStage(ex)
|
||||
case Success(Done) => completeStage()
|
||||
case Failure(ex) => failStage(ex)
|
||||
}.invoke)
|
||||
state = None
|
||||
|
||||
case None ⇒
|
||||
case None =>
|
||||
// cannot happen, but for good measure
|
||||
throw new IllegalStateException("Reached end of data but there is no open resource")
|
||||
}
|
||||
}
|
||||
case Failure(t) ⇒ errorHandler(t)
|
||||
case Failure(t) => errorHandler(t)
|
||||
}.invoke _
|
||||
|
||||
override def preStart(): Unit = createResource()
|
||||
|
||||
override def onPull(): Unit =
|
||||
state match {
|
||||
case Some(resource) ⇒
|
||||
case Some(resource) =>
|
||||
try {
|
||||
readData(resource).onComplete(readCallback)(sameThreadExecutionContext)
|
||||
} catch errorHandler
|
||||
case None ⇒
|
||||
case None =>
|
||||
// we got a pull but there is no open resource, we are either
|
||||
// currently creating/restarting then the read will be triggered when creating the
|
||||
// resource completes, or shutting down and then the pull does not matter anyway
|
||||
}
|
||||
|
||||
override def postStop(): Unit = {
|
||||
state.foreach(r ⇒ close(r))
|
||||
state.foreach(r => close(r))
|
||||
}
|
||||
|
||||
private def restartResource(): Unit = {
|
||||
state match {
|
||||
case Some(resource) ⇒
|
||||
case Some(resource) =>
|
||||
// wait for the resource to close before restarting
|
||||
close(resource).onComplete(getAsyncCallback[Try[Done]] {
|
||||
case Success(Done) ⇒
|
||||
case Success(Done) =>
|
||||
createResource()
|
||||
case Failure(ex) ⇒ failStage(ex)
|
||||
case Failure(ex) => failStage(ex)
|
||||
}.invoke)
|
||||
state = None
|
||||
case None ⇒
|
||||
case None =>
|
||||
createResource()
|
||||
}
|
||||
}
|
||||
|
||||
private def createResource(): Unit = {
|
||||
create().onComplete { resource ⇒
|
||||
create().onComplete { resource =>
|
||||
createdCallback(resource).recover {
|
||||
case _: StreamDetachedException ⇒
|
||||
case _: StreamDetachedException =>
|
||||
// stream stopped
|
||||
resource match {
|
||||
case Success(r) ⇒ close(r)
|
||||
case Failure(ex) ⇒ throw ex // failed to open but stream is stopped already
|
||||
case Success(r) => close(r)
|
||||
case Failure(ex) => throw ex // failed to open but stream is stopped already
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue