Есть ли способ получить сопоставляемый элемент, когда генерируется исключение akka streams?

Мне нравится анализировать HTML с регулярными выражениями. Я не пытаюсь разбирать идиот HTML, который намеренно нарушен. Этот код является моим основным парсером (версия Perl):

$_ = join "",; tr/\n\r \t/ /s; s//>\n/g; s/\n ?\n/\n/g;
s/^ ?\n//s; s/ $//s; print

Он называется htmlsplit, разбивает HTML на строки, с одним тегом или фрагментом текста в каждой строке. Затем линии могут быть обработаны другими текстовыми инструментами и сценариями, такими как grep , sed , Perl и т. Д. Я даже не шучу :) Наслаждайтесь.

Достаточно просто переписать мой скрипт Perl-all-first Perl в приятную поточную вещь, если вы хотите обрабатывать огромные веб-страницы. Но это действительно не обязательно.

Бьюсь об заклад, я заберусь для этого.

HTML Split


Против моего ожидая, что это получило некоторые upvotes, поэтому я предлагаю несколько правильных выражений:

/(<.*?>|[^<]+)\s*/g    # get tags and text
/(\w+)="(.*?)"/g       # get attibutes

Они хороши для XML / XHTML.

С небольшими вариациями он может справиться с беспорядочным HTML ... или сначала конвертировать HTML -> XHTML.


Лучший способ записи регулярных выражений - в Lex / Yacc стиль, а не непрозрачные однострочные или прокомментированные многострочные чудовища. Я не делал этого здесь; эти им едва ли нужны.

1
задан sazzy4o 17 January 2019 в 15:43
поделиться

3 ответа

Вы можете использовать Supervision.Decider для регистрации этих атрибутов.

object Test extends App {

  implicit val system = ActorSystem("test")

  implicit val mat = ActorMaterializer()

  val testSupervisionDecider: Supervision.Decider = {
    case ex: RuntimeException =>
      println(s"some run time exception ${ex.getMessage}")
      Supervision.Resume
    case ex: Exception =>
     //if you want to stop the stream
   Supervision.Stop
  }

  val source = Source(List("1", "2", "3")).map { item =>
    if (item == "2") {
      throw new RuntimeException(s"$item")
    } else {
      item
    }
  }

  source
    .to(Sink.foreach(println(_)))
    .withAttributes(ActorAttributes.supervisionStrategy(testSupervisionDecider))
    .run

}

Вывод:

1
some run time exception 2
3
0
ответ дан VKT 17 January 2019 в 15:43
поделиться

Не с Supervision.Decide, но вы могли бы достичь этого по-другому.

Проверьте эту программу:

object Streams extends App{

  implicit val system = ActorSystem("test")

  implicit val mat = ActorMaterializer()

  val source = Source(List("1", "2", "3")).map { item =>
    Try {
      if (item == "2") {
        throw new RuntimeException("Error")
      } else {
        item
      }
    }
  }
  source
    .alsoTo(
      Flow[Try[String]]
        .filter(_.isFailure)
        .to(Sink.foreach(t => println("failure: " + t))))
    .to(
      Flow[Try[String]]
        .filter(_.isSuccess)
        .to(Sink.foreach(t => println("success " + t)))).run()

}

Выходы:

success Success(1)
failure: Failure(java.lang.RuntimeException: Error)
success Success(3)
0
ответ дан Ivan Stanislavciuc 17 January 2019 в 15:43
поделиться

Это несколько запутанно, но вы можете сделать это, обернув свою функцию отображения в потоке и используя flatMapConcat примерно так:

Source(List(item1, item2, item3)).flatMapConcat { item =>
  Source(List(item))
    .map(mapF)
    .withAttributes(ActorAttributes.supervisionStrategy { e: Throwable =>
      logger.error("Exception in stream with itemId:" + item.id, e)
      Supervision.Resume
    })
}

def mapF(item: Item) =
  if (item.property < 0) {
    throw new RuntimeException("Error")
  } else {
    i
  }

Это возможно, потому что у каждой стадии потока может быть своя собственная стратегия наблюдения .

0
ответ дан yahor 17 January 2019 в 15:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: