diff --git a/core/src/main/scala/ox/channels/SourceOps.scala b/core/src/main/scala/ox/channels/SourceOps.scala index 4b999e72..6744663c 100644 --- a/core/src/main/scala/ox/channels/SourceOps.scala +++ b/core/src/main/scala/ox/channels/SourceOps.scala @@ -535,16 +535,16 @@ trait SourceOps[+T] { this: Source[T] => */ def headOption(): Option[T] = Try(head()).toOption - /** Returns the first element from this source or throws `NoSuchElementException` when the source is empty or `receive()` operation fails - * without error. In case when the `receive()` operation fails with exception that exception is re-thrown. Note that `headOption` is not - * an idempotent operation on source as it receives elements from it. + /** Returns the first element from this source or throws `NoSuchElementException` when the source is empty. In case when the `receive()` + * operation fails with exception then `ChannelClosedException.Error`` thrown. Note that `headOption` is not an idempotent operation on + * source as it receives elements from it. * * @return * A first element if source is not empty or throws otherwise. * @throws NoSuchElementException * When source is empty or `receive()` failed without error. - * @throws exception - * When `receive()` failed with exception then this exception is re-thrown. + * @throws ChannelClosedException.Error + * When `receive()` fails then this exception is thrown. * @example * {{{ * import ox.* @@ -562,7 +562,7 @@ trait SourceOps[+T] { this: Source[T] => supervised { receive() match case ChannelClosed.Done => throw new NoSuchElementException("cannot obtain head from an empty source") - case ChannelClosed.Error(r) => throw r.getOrElse(new NoSuchElementException("getting head failed")) + case e: ChannelClosed.Error => throw e.toThrowable case t: T @unchecked => t } diff --git a/core/src/test/scala/ox/channels/SourceOpsHeadTest.scala b/core/src/test/scala/ox/channels/SourceOpsHeadTest.scala index 0c3015a5..605a6df5 100644 --- a/core/src/test/scala/ox/channels/SourceOpsHeadTest.scala +++ b/core/src/test/scala/ox/channels/SourceOpsHeadTest.scala @@ -13,18 +13,18 @@ class SourceOpsHeadTest extends AnyFlatSpec with Matchers { } should have message "cannot obtain head from an empty source" } - it should "re-throw exception that was thrown during element retrieval" in supervised { - the[RuntimeException] thrownBy { + it should "throw ChannelClosedException.Error with exception and message that was thrown during retrieval" in supervised { + the[ChannelClosedException.Error] thrownBy { Source .failed(new RuntimeException("source is broken")) .head() - } should have message "source is broken" + } should have message "java.lang.RuntimeException: source is broken" } - it should "throw NoSuchElementException for source failed without exception" in supervised { - the[NoSuchElementException] thrownBy { + it should "throw ChannelClosedException.Error for source failed without exception" in supervised { + the[ChannelClosedException.Error] thrownBy { Source.failedWithoutReason[Int]().head() - } should have message "getting head failed" + } } it should "return first value from non empty source" in supervised {