@ -8,6 +8,7 @@ const knexLibrary = require("knex");
const { knexSnakeCaseMappers } = require ( "objection" ) ;
const { addMilliseconds } = require ( "date-fns" ) ;
const ValidationError = require ( "@validatem/error" ) ;
const debug = require ( "debug" ) ( "srap:backend:postgresql:queries" ) ;
const models = require ( "./models" ) ;
const mergeItems = require ( "../../semantics/merge-items" ) ;
@ -84,14 +85,37 @@ module.exports = function(state) {
} ,
lock : function ( tx , { id , task } ) {
return this . runInTransaction ( tx , ( tx ) => {
return Promise . try ( ( ) => {
// FIXME: use Objection for this?
// FIXME: Read item first to make it prevent edit conflicts via transaction
return tx . raw ( ` UPDATE srap_queue SET started = TRUE, started_at = NOW() WHERE task = :task AND item_id = :id ` , { task : task . name , id : id } ) ;
return db . TaskInProgress . query ( tx ) . forUpdate ( ) . findById ( [ task . name , id ] ) ;
} ) . then ( ( item ) => {
if ( item != null ) {
debug ( ` Task ' ${ task . name } : ${ id } ' currently locked: ${ item . started } ` ) ;
if ( item . started === false ) {
return Promise . try ( ( ) => {
return db . TaskInProgress . query ( tx )
. findById ( [ task . name , id ] )
. update ( {
started : true ,
started _at : knex . fn . now ( )
} ) ;
} ) . then ( ( ) => {
debug ( ` Task ' ${ task . name } : ${ id } ' locked successfully ` ) ;
return true ;
} ) . catch ( { name : "UniqueViolationError" } , ( ) => {
// FIXME: This is not the correct error...
debug ( ` Task ' ${ task . name } : ${ id } ' failed lock because already locked on write ` ) ;
return false ;
} ) ;
} else {
debug ( ` Task ' ${ task . name } : ${ id } ' failed lock because already locked on read ` ) ;
return false ;
}
} else {
debug ( ` Task ' ${ task . name } : ${ id } ' failed lock because it no longer exists in queue ` ) ;
return false ;
}
} ) ;
} ) ;
} ,