=str #16751 Update to reactive-streams 1.0-RC3

Changed rules:
* 1.9 Always onSubscribe prior to any other signals
* 1.9 NullPointerException if subscriber is null
* 3.17 Long overflow, effectively unbounded instead of onError

Fixed some more things:
* fixed some FIXME
* Long drop and take
* memory leaks in tck tests, use BeforeClass to create ActorSystem
  use AfterClass to shutdown ActorSystem
* more tck tests
* don't emit OnComplete when substream is cancelled
* work around for memory leak in PrefixAndTail
This commit is contained in:
Patrik Nordwall 2015-03-03 10:57:25 +01:00
parent e3e01d2c9b
commit 23c533fdd5
79 changed files with 862 additions and 414 deletions

View file

@ -17,11 +17,13 @@ private[stream] object ReactiveStreamsCompliance {
final val NumberOfElementsInRequestMustBePositiveMsg =
"The number of requested elements must be > 0 (see reactive-streams specification, rule 3.9)"
final val TotalPendingDemandMustNotExceedLongMaxValue =
"Total pending demand MUST NOT be > `java.lang.Long.MAX_VALUE` (see reactive-streams specification, rule 3.17)"
final val SubscriberMustNotBeNullMsg = "Subscriber must not be null, rule 1.9"
final def totalPendingDemandMustNotExceedLongMaxValueException: Throwable =
new IllegalStateException(TotalPendingDemandMustNotExceedLongMaxValue)
final val ExceptionMustNotBeNullMsg = "Exception must not be null, rule 2.13"
final val ElementMustNotBeNullMsg = "Element must not be null, rule 2.13"
final val SubscriptionMustNotBeNullMsg = "Subscription must not be null, rule 2.13"
final def numberOfElementsInRequestMustBePositiveException: Throwable =
new IllegalArgumentException(NumberOfElementsInRequestMustBePositiveMsg)
@ -29,18 +31,44 @@ private[stream] object ReactiveStreamsCompliance {
final def canNotSubscribeTheSameSubscriberMultipleTimesException: Throwable =
new IllegalStateException(CanNotSubscribeTheSameSubscriberMultipleTimes)
final def rejectDuplicateSubscriber[T](subscriber: Subscriber[T]): Unit =
final def subscriberMustNotBeNullException: Throwable =
new NullPointerException(SubscriberMustNotBeNullMsg)
final def exceptionMustNotBeNullException: Throwable =
new NullPointerException(ExceptionMustNotBeNullMsg)
final def elementMustNotBeNullException: Throwable =
new NullPointerException(ElementMustNotBeNullMsg)
final def subscriptionMustNotBeNullException: Throwable =
new NullPointerException(SubscriptionMustNotBeNullMsg)
final def rejectDuplicateSubscriber[T](subscriber: Subscriber[T]): Unit = {
// since it is already subscribed it has received the subscription first
// and we can emit onError immediately
tryOnError(subscriber, canNotSubscribeTheSameSubscriberMultipleTimesException)
}
final def rejectAdditionalSubscriber[T](subscriber: Subscriber[T], rejector: Publisher[T]): Unit =
final def rejectAdditionalSubscriber[T](subscriber: Subscriber[T], rejector: String): Unit = {
tryOnSubscribe(subscriber, CancelledSubscription)
tryOnError(subscriber, new IllegalStateException(s"$rejector $SupportsOnlyASingleSubscriber"))
final def rejectDueToOverflow[T](subscriber: Subscriber[T]): Unit =
tryOnError(subscriber, totalPendingDemandMustNotExceedLongMaxValueException)
}
final def rejectDueToNonPositiveDemand[T](subscriber: Subscriber[T]): Unit =
tryOnError(subscriber, numberOfElementsInRequestMustBePositiveException)
final def requireNonNullSubscriber[T](subscriber: Subscriber[T]): Unit =
if (subscriber eq null) throw subscriberMustNotBeNullException
final def requireNonNullException(cause: Throwable): Unit =
if (cause eq null) throw exceptionMustNotBeNullException
final def requireNonNullElement[T](element: T): Unit =
if (element == null) throw elementMustNotBeNullException
final def requireNonNullSubscription(subscription: Subscription): Unit =
if (subscription == null) throw subscriptionMustNotBeNullException
@SerialVersionUID(1L)
sealed trait SpecViolation extends Throwable
@ -56,15 +84,18 @@ private[stream] object ReactiveStreamsCompliance {
}
}
final def tryOnNext[T](subscriber: Subscriber[T], element: T): Unit =
final def tryOnNext[T](subscriber: Subscriber[T], element: T): Unit = {
requireNonNullElement(element)
try subscriber.onNext(element) catch {
case NonFatal(t) throw new SignalThrewException(subscriber + ".onNext", t)
}
}
final def tryOnSubscribe[T](subscriber: Subscriber[T], subscription: Subscription): Unit =
final def tryOnSubscribe[T](subscriber: Subscriber[T], subscription: Subscription): Unit = {
try subscriber.onSubscribe(subscription) catch {
case NonFatal(t) throw new SignalThrewException(subscriber + ".onSubscribe", t)
}
}
final def tryOnComplete[T](subscriber: Subscriber[T]): Unit =
try subscriber.onComplete() catch {