package Ġcom . vas ler . book viewer . service Ċ Ċ import Ġcom . vas ler . book viewer . util . IS BN Util Ċ import Ġcom . vas ler . book viewer . util . PDF Util Ċ import Ġio . lett uce . core . api . State ful Redis Connection Ċ import Ġio . mic ronaut . context . annotation . Value Ċ import Ġorg . apache . logging . log 4 j . Log Manager Ċ import Ġorg . apache . logging . log 4 j . Logger Ċ import Ġjava . io . InputStream Ċ import Ġjava . math . BigDecimal Ċ import Ġjava . sql . Connection Ċ import Ġjava . sql . Driver Manager Ċ import Ġjava . sql . ResultSet Ċ import Ġjava . util .* Ċ import Ġjavax . inject . Inject Ċ import Ġjavax . inject . Singleton Ċ Ċ enum Ġclass ĠInsert ion Status Ċ { ĊĠĠĠ ĠSUCCESS , ĊĠĠĠ ĠAL READY _ EXISTS , ĊĠĠĠ ĠDOCUMENT _ EMPTY , ĊĠĠĠ ĠIS BN _ INVALID , ĊĠĠĠ ĠUSER _ NOT _ FOUND Ċ } Ċ Ċ enum Ġclass ĠProcessing Status Ċ { ĊĠĠĠ ĠUN PROC ES SED , ĊĠĠĠ ĠPROC ES SED , ĊĠĠĠ ĠFAILED Ċ } Ċ Ċ enum Ġclass ĠPage Status Ċ { ĊĠĠĠ ĠUN PROC ES SED , ĊĠĠĠ ĠDO ES _ NOT _ EXIST Ċ } Ċ Ċ data Ġclass ĠBook Metadata ( var Ġid : ĠLong , Ġvar ĠuserId : ĠLong , Ġvar Ġis bn : ĠString , Ġvar Ġstorage Key : ĠString , Ġvar Ġpage Count : ĠInt , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġprocess Count : ĠInt , Ġvar Ġstatus : ĠString , Ġvar Ġupdate Ts : ĠDate , Ġvar Ġcreate Ts : ĠDate ) Ċ Ċ @ Singleton Ċ class ĠBook Storage Service Ċ { ĊĠĠĠ Ġcompanion Ġobject ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġlogger : ĠLogger Ġ= ĠLog Manager . getLogger ( Book Storage Service :: class . java ) ĊĊĠĠĠĠĠĠĠ Ġconst Ġval ĠS CH M Ġ= Ġ" book viewer " ĊĠĠĠ Ġ} Ċ Ċ // ĠĠĠ ĠJDBC ĠWITH ĠIN JECTION ĠDO ES ĠNOT ĠWORK ĠFOR ĠSO ME ĠRE ASON , Ċ // ĠĠĠ ĠH AD ĠTO ĠMAN U ALLY ĠOPEN ĠTHE ĠCONNECTION Ċ // ĠĠĠ Ġ@ Inject Ġlateinit Ġvar Ġds : ĠDataSource ĊĊĠĠĠ Ġ@ Value ("\ ${ book viewer . processing Retry Interval }") ĊĠĠĠ Ġlateinit Ġvar Ġprocessing Retry Interval : ĠInteger ĊĊĠĠĠ Ġ@ Inject ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġredis : ĠStateful Redis Connection < String , ĠString > ĊĊĠĠĠ Ġfun Ġredis Set ( key : ĠString , Ġvalue : ĠString ) Ġ= Ġredis . sync (). set ( key , Ġvalue ) Ġ== Ġ" OK " ĊĊĠĠĠ Ġfun Ġredis Set Bin ( key : ĠString , Ġvalue : ĠByteArray ) Ġ= Ġredis . sync (). set ( key , ĠBase 6 4 . get Encoder (). encode ToString ( value )) Ġ== Ġ" OK " ĊĊĠĠĠ Ġfun Ġredis Get ( key : ĠString ): ĠString ? Ġ= Ġredis . sync (). get ( key ) ĊĊĠĠĠ Ġfun Ġredis Get Bin ( key : ĠString ): ĠByteArray ? ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġvalue Ġ= Ġredis . sync (). get ( key ) ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( value Ġ!= Ġnull Ġ&& Ġvalue . isNotEmpty ()) ĠBase 6 4 . get Decoder (). decode ( value ) Ġelse Ġnull ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġredis Exists ( key : ĠString ) Ġ= Ġredis . sync (). exists ( key ) Ġ> Ġ 0 ; ĊĊĠĠĠ Ġfun Ġredis Del ( key : ĠString ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġredis . sync (). del ( key ) Ġ> Ġ 0 ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġredis Ping () Ġ= Ġredis . sync (). ping () ĊĊĠĠĠ Ġ@ Value ("\ ${ datas ources . default . url }") ĊĠĠĠ Ġlateinit Ġvar Ġds URL : ĠString ĊĊĠĠĠ Ġ@ Value ("\ ${ datas ources . default . username }") ĊĠĠĠ Ġlateinit Ġvar Ġds Username : ĠString ĊĊĠĠĠ Ġ@ Value ("\ ${ datas ources . default . password }") ĊĠĠĠ Ġlateinit Ġvar Ġds Password : ĠString ĊĊĠĠĠ Ġfun Ġget Connection (): ĠConnection ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġconn Ġ= ĠDriver Manager . getConnection ( ds URL , Ġds Username , Ġds Password ) ĊĠĠĠĠĠĠĠ Ġconn . auto Commit Ġ= Ġfalse ĊĊĠĠĠĠĠĠĠ Ġreturn Ġconn ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġcreate Redis Key ( username : ĠString , Ġis bn : ĠString , Ġnormalized : ĠBoolean Ġ= Ġfalse ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ= Ġ" PDF -$ username -${ if Ġ(! normalized ) ĠIS BN Util . normalize ( isbn ) Ġ?: Ġthrow ĠException (" INVALID ĠIS BN ") Ġelse Ġis bn }" ĊĊĠĠĠ Ġdata Ġclass ĠBook List Metadata ( var Ġis bn : ĠString , Ġvar Ġpage Count : ĠInt ) ĊĠĠĠ Ġdata Ġclass ĠBook List ( var Ġfirst Item Index : ĠInt , Ġvar ĠpageSize : ĠInt , Ġval Ġbooks : ĠList < Book List Metadata >) ĊĊĠĠĠ Ġfun Ġlist Books ( username : ĠString , Ġoffset : ĠInt , Ġlimit : ĠInt Ġ= Ġ 5 0 ): ĠBook List ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbooks Ġ= Ġmutable ListOf < Book List Metadata >() ĊĊĠĠĠĠĠĠĠ Ġval Ġvalidated Offset Ġ= Ġif Ġ( offset Ġ< Ġ 0 ) Ġ 0 Ġelse Ġoffset ĊĠĠĠĠĠĠĠ Ġval Ġvalidated Limit Ġ= Ġif Ġ( limit Ġ! in Ġ 1 .. 1 0 0 ) Ġ 1 0 0 Ġelse Ġlimit ĊĊĠĠĠĠĠĠĠ Ġget Connection (). use Ġ{ Ġconn Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġps Ġ= Ġconn . prepareStatement (" SELECT Ġis bn , Ġpage _ count ĠFROM Ġ$ SCH M . book ĠWHERE Ġuser _ id Ġ= Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"( SELECT Ġid ĠFROM Ġ$ SCH M . user ĠWHERE Ġusername Ġ= Ġ? ) ĠORDER ĠBY Ġcreation _ ts ĠLIMIT Ġ? ĠOFFSET Ġ? ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġps . setString ( 1 , Ġusername ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġps . setInt ( 2 , Ġvalidated Limit ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġps . setInt ( 3 , Ġvalidated Offset ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrs Ġ= Ġps . executeQuery () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( rs . next ()) ĠĠ Ġbooks . add ( Book List Metadata ( rs . getString ( 1 ), Ġrs . getInt ( 2 ))) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġconn . rollback (); ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn ĠBook List ( validated Offset , Ġvalidated Limit , Ġbooks ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġinsert Book ( isbn : ĠString , Ġdata Stream : ĠInputStream , Ġusername : ĠString ): ĠInsert ion Status ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġnormalized IS BN Ġ= ĠIS BN Util . normalize ( isbn ) Ġ?: Ġreturn ĠInsert ion Status . IS BN _ INVALID ĊĊĠĠĠĠĠĠĠ Ġget Connection (). use Ġ{ Ġconn Ġ-> ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( findBy IS BN ( normalized IS BN , Ġusername , Ġconn ) Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconn . rollback () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠInsert ion Status . AL READY _ EXISTS ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdata Ġ= Ġdata Stream . read All Bytes () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpdf Util Ġ= ĠPDF Util () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpdf Util . load Doc ( data ). use Ġ{ Ġdoc Ġ-> ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpage Count Ġ= Ġdoc . numberOf Pages ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( page Count Ġ== Ġ 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconn . rollback () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠInsert ion Status . DOCUMENT _ EMPTY ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġseq Rs Ġ= Ġconn . prepareStatement (" SELECT Ġnext val ('$ SCH M . book _ pk _ seq ') "). executeQuery (); ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġseq Rs . next () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbook Id Ġ= Ġseq Rs . get BigDecimal ( 1 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠuserId Ġ= Ġget UserId ( username , Ġconn ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( userId Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconn . rollback () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠInsert ion Status . USER _ NOT _ FOUND ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstorage Key Ġ= Ġcreate Redis Key ( username , Ġnormalized IS BN , Ġtrue ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbook Ps Ġ= Ġconn . prepareStatement ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" INSERT ĠINTO Ġ$ SCH M . book Ġ( id , Ġuser _ id , Ġis bn , Ġstorage _ key , Ġpage _ count , Ġstatus )" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" ĠVALUES Ġ( ?, Ġ?, Ġ?, Ġ?, Ġ?, Ġ? )") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbook Ps . set BigDecimal ( 1 , Ġbook Id ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbook Ps . set BigDecimal ( 2 , ĠuserId ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbook Ps . setString ( 3 , Ġnormalized IS BN ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbook Ps . setString ( 4 , Ġstorage Key ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbook Ps . setInt ( 5 , Ġpage Count ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbook Ps . setString ( 6 , ĠProcessing Status . UN PROC ES SED . name ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbook Ps . executeUpdate () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġredis Set Bin ( storage Key , Ġdata ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconn . commit () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcatch Ġ( t : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconn . rollback () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . error ( t . message , Ġt ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow Ġt ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn ĠInsert ion Status . SUCCESS ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġload Page ( isbn : ĠString , Ġpage : ĠInt , Ġusername : ĠString ): ĠByteArray ? ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġget Connection (). use Ġ{ Ġconn Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnorm IS BN Ġ= ĠIS BN Util . normalize ( isbn ) Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbook Id Ġ= ĠfindBy IS BN ( norm IS BN , Ġusername , Ġconn ) Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbook Metadata Ġ= Ġload Book Metadata ( book Id , Ġconn ) Ġ?: Ġreturn Ġnull ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġredis Get Bin ("${ book Metadata . storage Key }- $ page ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġload Page ( book Id : ĠLong , Ġpage : ĠInt ): ĠByteArray ? ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġget Connection (). use Ġ{ Ġconn Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbook Metadata Ġ= Ġload Book Metadata ( book Id , Ġconn ) Ġ?: Ġreturn Ġnull ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġredis Get Bin ("${ book Metadata . storage Key }- $ page ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget Exp irable Page URL ( isbn : ĠString , Ġpage : ĠInt , Ġusername : ĠString ): ĠString ? ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġget Connection (). use Ġ{ Ġconn Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnorm IS BN Ġ= ĠIS BN Util . normalize ( isbn ) Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbook Id Ġ= ĠfindBy IS BN ( norm IS BN , Ġusername , Ġconn ) Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbook Metadata Ġ= Ġload Book Metadata ( book Id , Ġconn ) Ġ?: Ġreturn Ġnull ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġexists Ġ= Ġredis Exists ("${ book Metadata . storage Key }- $ page ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( exists ) Ġ"$ book Id :$ page " Ġelse Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġload Book Metadata ( book Id : ĠLong , Ġconn : ĠConnection ): ĠBook Metadata ? ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġps Ġ= Ġconn . prepareStatement (" SELECT Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" id , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" user _ id , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" isbn , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" storage _ key , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" page _ count , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" process _ count , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" status , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" update _ ts , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" creation _ ts Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" FROM Ġ$ SCH M . book Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" WHERE Ġid Ġ= Ġ? ") ĊĊĠĠĠĠĠĠĠ Ġps . set Long ( 1 , Ġbook Id ) ĊĠĠĠĠĠĠĠ Ġval Ġrs Ġ= Ġps . executeQuery () ĊĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( rs . next ()) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBook Metadata ( rs . getLong ( 1 ), Ġrs . getLong ( 2 ), Ġrs . getString ( 3 ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrs . getString ( 4 ), Ġrs . getInt ( 5 ), Ġrs . getInt ( 6 ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrs . getString ( 7 ), Ġrs . getTimestamp ( 8 ), Ġrs . getTimestamp ( 9 )) ĊĠĠĠĠĠĠĠ Ġelse Ġnull ĊĠĠĠ Ġ} ĊĠĠĠĠĊĠĠĠ Ġfun Ġload Book Data ( storage Key : ĠString ): ĠByteArray ? ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġredis Get Bin ( storage Key ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġlock Un processed Book ( conn : ĠConnection ): ĠBook Metadata ? ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġps Ġ= Ġconn . prepareStatement (" SELECT Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" id , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" user _ id , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" isbn , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" storage _ key , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" page _ count , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" process _ count , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" status , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" update _ ts , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" creation _ ts Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" FROM Ġ$ SCH M . book Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" WHERE Ġstatus Ġ= Ġ'${ Processing Status . UN PROC ES SED . name }' Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" AND Ġ(" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" update _ ts Ġ< Ġcurrent _ timestamp Ġ- ĠINTER VAL Ġ'${ processing Retry Interval . toInt ()} Ġsecond ' Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" OR Ġcreation _ ts Ġ= Ġupdate _ ts " Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ") Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" FOR ĠUPDATE ĠSKIP ĠLOCK ED ĠLIMIT Ġ 1 ") ĊĊĠĠĠĠĠĠĠ Ġval Ġrs Ġ= Ġps . executeQuery () ĊĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( rs . next ()) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠBook Metadata ( rs . getLong ( 1 ), Ġrs . getLong ( 2 ), Ġrs . getString ( 3 ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrs . getString ( 4 ), Ġrs . getInt ( 5 ), Ġrs . getInt ( 6 ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrs . getString ( 7 ), Ġrs . getTimestamp ( 8 ), Ġrs . getTimestamp ( 9 )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġnull ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġload Process Count AndUpdate Ts ( book Metadata : ĠBook Metadata , Ġconn : ĠConnection ) ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġselect Ps Ġ= Ġconn . prepareStatement (" SELECT Ġprocess _ count , Ġupdate _ ts ĠFROM Ġ$ SCH M . book ĠWHERE Ġid Ġ= Ġ? ") ĊĠĠĠĠĠĠĠ Ġselect Ps . set Long ( 1 , Ġbook Metadata . id ) ĊĊĠĠĠĠĠĠĠ Ġval Ġrs Ġ= Ġselect Ps . executeQuery () ĊĠĠĠĠĠĠĠ Ġif Ġ( rs . next ()) ĊĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbook Metadata . process Count Ġ= Ġrs . getInt ( 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbook Metadata . update Ts Ġ= Ġrs . getTimestamp ( 2 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġtouch Book ( book Metadata : ĠBook Metadata , Ġconn : ĠConnection ) ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġps Ġ= Ġconn . prepareStatement (" UPDATE Ġ$ SCH M . book ĠSET Ġprocess _ count Ġ= Ġprocess _ count Ġ+ Ġ 1 , Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" update _ ts Ġ= Ġcurrent _ timestamp ĠWHERE Ġid Ġ= Ġ? ") ĊĊĠĠĠĠĠĠĠ Ġps . set Long ( 1 , Ġbook Metadata . id ) ĊĠĠĠĠĠĠĠ Ġps . executeUpdate () ĊĊĠĠĠĠĠĠĠ Ġload Process Count AndUpdate Ts ( book Metadata , Ġconn ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġupdate Book Metadata ( book Metadata : ĠBook Metadata , Ġconn : ĠConnection ) ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġps Ġ= Ġconn . prepareStatement (" UPDATE Ġ$ SCH M . book ĠSET Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" user _ id Ġ= Ġ?, Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" isbn Ġ= Ġ?, Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" storage _ key Ġ= Ġ?, Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" page _ count Ġ= Ġ?, Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" process _ count Ġ= Ġ?, Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" status Ġ= Ġ?, Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" update _ ts Ġ= Ġcurrent _ timestamp Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" WHERE Ġid Ġ= Ġ? ") ĊĊĠĠĠĠĠĠĠ Ġwith Ġ( book Metadata ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġps . set Long ( 1 , ĠuserId ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġps . setString ( 2 , Ġis bn ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġps . setString ( 3 , Ġstorage Key ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġps . setInt ( 4 , Ġpage Count ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġps . setInt ( 5 , Ġprocess Count ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġps . setString ( 6 , Ġstatus ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġps . set Long ( 7 , Ġid ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġps . executeUpdate () ĊĊĠĠĠĠĠĠĠ Ġload Process Count AndUpdate Ts ( book Metadata , Ġconn ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠfindBy IS BN ( isbn : ĠString , Ġusername : ĠString , Ġconn : ĠConnection ): ĠLong ? ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġps Ġ= Ġconn . prepareStatement (" SELECT Ġid ĠFROM Ġ$ SCH M . book ĠWHERE Ġis bn Ġ= Ġ? Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" AND Ġuser _ id Ġ= Ġ( SELECT Ġid ĠFROM Ġ$ SCH M . user ĠWHERE Ġusername Ġ= Ġ? )") ĊĊĠĠĠĠĠĠĠ Ġps . setString ( 1 , Ġis bn ) ĊĠĠĠĠĠĠĠ Ġps . setString ( 2 , Ġusername ) ĊĊĠĠĠĠĠĠĠ Ġval Ġrs Ġ= Ġps . executeQuery () ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( rs . next ()) Ġrs . getLong ( 1 ) Ġelse Ġnull ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġget UserId ( username : ĠString , Ġconn : ĠConnection ): ĠBigDecimal ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġps Ġ= Ġconn . prepareStatement (" SELECT Ġid ĠFROM Ġ$ SCH M . user ĠWHERE Ġusername Ġ= Ġ? ") ĊĠĠĠĠĠĠĠ Ġps . setString ( 1 , Ġusername ) ĊĠĠĠĠĠĠĠ Ġval Ġrs Ġ= Ġps . executeQuery () ĊĊĠĠĠĠĠĠĠ Ġif Ġ( rs . next ()) ĊĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġrs . get BigDecimal ( 1 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġseq Rs Ġ= Ġconn . prepareStatement (" SELECT Ġnext val (' ${ SCH M }. user _ pk _ seq ') "). executeQuery () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġseq Rs . next () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġuser Seq Ġ= Ġseq Rs . get BigDecimal ( 1 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġinsert Ps Ġ= Ġconn . prepareStatement (" INSERT ĠINTO Ġ$ SCH M . user Ġ( id , Ġusername , Ġstatus ) ĠVALUES Ġ( ?, Ġ?, Ġ? )"); ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinsert Ps . set BigDecimal ( 1 , Ġuser Seq ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinsert Ps . setString ( 2 , Ġusername ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinsert Ps . setString ( 3 , Ġ" ACTIVE ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinsert Ps . executeUpdate () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġuser Seq ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ }