Max error retry read-side JDBC Slick

How do I set a max error retry for Slick JDBC persistence or optionally handle the errors in the event processor handlers ?

I’m not sure I understand the problem you are facing.

Are you having issues when persisting your read-side model and/or offset on a Slick table? If so, do you want to skip (or give up) to process the current event?

I have composite unique key in my views, sometimes I will get a duplicate (which I want to ignore) like the following error:

2018-04-10T15:20:49.697Z [error] akka.actor.OneForOneStrategy [sourceThread=application-akka.actor.default-dispatcher-2, akkaTimestamp=15:20:49.696UTC, akkaSource=akka://application/system/sharding/EventProcessor/Event/Event/processor, sourceActorSystem=application] - ERROR: duplicate key value violates unique constraint “view_pkey”
Detail: Key (id, x_id)=(67CA62CC32C05F54E055000000000001, 67C9AA1E91C653A1E055000000000001) already exists.
Location: File: nbtinsert.c, Routine: _bt_check_unique, Line: 433
Server SQLState: 23505
org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint “view_pkey”
Detail: Key (id, x_id)=(67CA62CC32C05F54E055000000000001, 67C9AA1E91C653A1E055000000000001) already exists.

So I either want to have a maxError retry setting for which I can set a fixed number of retries (if error is some lock issues etc.) or be able the handle above SQL exceptions in the EventProcessor event handler functions.

I think your best option here is to handle that in the event handler or repository method you are calling. You should handle that specific error instead and ignore it.

A max retry is dangerous. If your DB is down for some reason, the processor will be keep going, try a couple of times and giving up. The stream consuming will be keep going and when the DB is back those events won’t be processed anymore.

I was hoping for actual examples or more explanation on the event handler option. Assuming I have the following setup using SlickReadSide:

builder.setEventHandler(eventHandler)
def eventHandler(eventElement: EventStreamElement[]) {
   sqlu"INSERT ...."
}

How do I handle the exception using SlickReadSide ?

I guess something along those lines will do the job:

val dbio = sqlu"INSERT …"
dbio.asTry.map {
  case  Failure(e:Throwable) => log.error(e.toString)
  case Success(_) =>
}

Just be aware that if you do this, your read-side processor will never re-process that event and you will lose the data, as @octonato mentioned previously.

(P.S. Discourse supports formatting code blocks, which would make your examples easier to read. It uses Markdown syntax, the same as GitHub. There is some more discussion about code formatting at https://meta.discourse.org/t/how-do-i-select-a-language-in-code-blocks/19247 and other posts on Meta Discourse.)

formatted! ;-)

1 Like