When implementing a system which creates tasks that need to be resolved by some workers, my idea would be to create a table which would have some task definition along with a status, e.g. for document review we'd have something like reviewId, documentId, reviewerId, reviewTime
.
When documents are uploaded to the system we'd just store the documentId
along with a generated reviewId
and leave the reviewerId
and reviewTime
empty. When next reviewer comes along and starts the review we'd just set his id and current time to mark the job as "in progress" (I deliberately skip the case where the reviewer takes a long time, or dies during the review).
When implementing such a use case in e.g. PostgreSQL we could use the UPDATE review SET reviewerId = :reviewerId, reviewTime: reviewTime WHERE reviewId = (SELECT reviewId from review WHERE reviewId is null AND reviewTime is null FOR UPDATE SKIP LOCKED LIMIT 1) RETURNING reviewId, documentId, reviewerId, reviewTime
(so basically update the first non-taken row, using SKIP LOCKED
to skip any already in-processing rows).
But when moving from native solution to JDBC and beyond, I'm having troubles implementing this:
- Spring Data JPA and Spring Data JDBC don't allow the
@Modifying
query to return anything else thanvoid
/boolean
/int
and force us to perform 2 queries in a single transaction - one for the first pending row, and second one with the update - one alternative would be to use a stored procedure but I really hate the idea of storing such logic so away from the code
- other alternative would be to use a persistent queue and skip the database all along but this introduced additional infrastructure components that need to be maintained and learned. Any suggestions are welcome though.
Am I missing something? Is it possible to have it all or do we have to settle for multiple queries or stored procedures?