transactional lookup/create

64 views
Skip to first unread message

Matthew Pocock

unread,
Apr 15, 2015, 5:56:52 PM4/15/15
to scala...@googlegroups.com
Hi,

I'm wanting to memoise some values into a database table. In this case it's a url/verb pair. I've got a table with an ID, url, verb, createdAt fields. To look it up, I do a filter over the table. To insert a new row, I use += on a projection without the ID.

I'd like to execute this logic transactionally. First, look up an exiting row using the url/verb pair. If one exists, return the data in this row. If it does not exist, insert a new row and return data corresponding to this new row.

def createRequest(url: String, verb: String, createdAt: Timestamp) =
newUrlScanRequests += (url, verb, createdAt)


def lookupRequest(url: Rep[String], verb: Rep[String]) =
urlScanRequests filter (r => r.url === url && r.verb === verb)

val lookupRequestWith = Compiled(lookupRequest _)

def lookupOrCreate(url: String, verb: String, createdAt: Timestamp = new Timestamp(new Date().getTime))
(implicit ec: ExecutionContext) =
lookupRequestWith(url, verb).result.headOption.flatMap {
case Some((id, url, verb, createdAt)) =>
DBIO.successful(Request(id, url, verb, createdAt))
case None =>
createRequest(url, verb, createdAt) map (id => Request(id, url, verb, createdAt))
}
So two questions.

1. what would I do to lookupOrCreate() to ensure that this all runs transactionally? I want to avoid two invocations of lookupOrCreate() both having a failed lookup and then racing to do the create.
2. is this idiomatic slick code? Is there some better way to represent this?

Thanks,
Matthew


--
Dr Matthew Pocock
Turing ate my hamster LTD

Integrative Bioinformatics Group, School of Computing Science, Newcastle University

skype: matthew.pocock
tel: (0191) 2566550

Matan Safriel

unread,
Apr 17, 2015, 6:52:19 AM4/17/15
to scala...@googlegroups.com
Hi Matthew,

Is that result.headOption.flatMap there the scala concurrent flatMap, or is it slick's monadic flatMap?
If it is the scala plain Future's flatMap, then I believe that you should rather, in this case, use Slick's flatMap monad to solve this case of composition. Staying within the boundaries of DBIO compositions, you can call .transactionally and voila.

To further clarify, inside slick's flatMap block argument, you may use any logic you need, as long as any route of logic inside it ends with an instance of a DBIO. So you would flatMap lookupRequestWith(url, verb) itself, and only then interrogate the result of it before embarking on a match block. 

Let me know if that is the case or if this helps

Cheers,
matan

Matthew Pocock

unread,
Apr 17, 2015, 7:33:25 AM4/17/15
to scala...@googlegroups.com
Hi Martin,

Thanks. I could call transactionally on the whole block. Thanks for the answer.

Matthew

--

---
You received this message because you are subscribed to the Google Groups "Slick / ScalaQuery" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scalaquery+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/scalaquery/c2c9f4fa-51d8-46fd-97bd-bd474f392f5c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Naftoli Gugenheim

unread,
Apr 19, 2015, 1:40:18 PM4/19/15
to scala...@googlegroups.com

result.headOption further returns a DBIO. result gives you a Seq, headOption gives you an Option, and head gives you a plain row value. You can also call .to[List] (or Set or Stream etc.) to build that collection type. But those all work within DBIO.


--

Matan Safriel

unread,
Apr 19, 2015, 3:09:06 PM4/19/15
to scala...@googlegroups.com
Yes I stand corrected. Didn't notice it's BasicStreamingAction's headOption there. 

--

---
You received this message because you are subscribed to a topic in the Google Groups "Slick / ScalaQuery" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/scalaquery/C0Cev0_TN2E/unsubscribe.
To unsubscribe from this group and all its topics, send an email to scalaquery+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/scalaquery/CANpg8PAofgHMRXwhKW2jwhM8-SrbqEtPmSQvoncxQ%3DyUi5d3bg%40mail.gmail.com.
Reply all
Reply to author
Forward
0 new messages