For multiple consumers you might do something like: BEGIN; UPDATE processingqueue SET status = 'failed' WHERE status = 'processing' AND processor = :processor; UPDATE processingqueue SET status = 'processing', processor = :processor, started = strftime('%s') WHERE queueid = (SELECT queueid from processingqueue where status = 'ready' AND processor IS NULL ORDER BY queueid LIMIT 1); SELECT * FROM processingqueue WHERE status = 'processing' AND processor = :processor; UPDATE processingqueue SET status = 'ready', processor = NULL WHERE status = 'failed' AND processor = :processor; COMMIT;
and run it as a single statement providing the processor name binding to the named variable :processor and you will get back one row to processes on :processor, assuming that there is work to do. Otherwise you will not get back a row. If the same :processor asks for more work to do and it is already processing, then the currently dispatched task failed and you should get a new one. The failed job will then be returned to ready and can be dispatched to any worker in need of work. schema would look like: create table processingqueue ( queueid integer primary key, status text collate nocase, started integer, ... other data you need ... unique (processor, status, queueid) ); On Fri, 18 Oct 2013 19:04:54 -0400 "James K. Lowden" <jklow...@schemamania.org> wrote: >On Fri, 18 Oct 2013 13:57:18 -0400 >"Normand Mongeau" <nmong...@theobjects.com> wrote: > >> Also, the consuming should be a 2-step process because the >processing >> is involved and may fail for reasons too long to explain here. So in >> essence, select a record, modify it to indicate it's being >processed, >> and once the processing is done delete the record. Is there a way to >> do the initial selection in one swoop (select and update) or is it >> two SQL statements? I have to avoid two different processes >selecting >> and modifying the same record to minimize rollbacks/retries. > >Read after write, not write after read. > >Counterintuitive, perhaps, but if the reading process begins by >*updating* the record it's about to process, you have idempotent >processing without the need for a user-defined transaction. > >writer: > insert ... (status, key, data) values ('queued', 1, 'foo'); > >reader: > update ... set status = 'processing' > where key = (select min(key) ... where status <> 'done'); > select ... where status = 'processing'; > /* work work work */ > update ... set status = 'done' where key = @key; > >SQL-92 IIRC defines an OUTPUT clause for UPDATE, which would do what >you want (select+output in one statement). But that's not a SQLite >feature. > >--jkl > >_______________________________________________ >sqlite-users mailing list >sqlite-users@sqlite.org >http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users ---- #include <shrinkwrap-disclaimer.h> _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users