summaryrefslogtreecommitdiff
path: root/api.js
diff options
context:
space:
mode:
authorschneefux <schneefux+commit@schneefux.xyz>2017-03-21 18:23:40 +0100
committerschneefux <schneefux+commit@schneefux.xyz>2017-03-21 18:23:40 +0100
commiteffeea65388b116f3ec1a41e7596b39bf3c1d576 (patch)
tree8265eeaec8642c41b607d84dd07daee845aab4fe /api.js
parent42d06bc2da87f2c7805c2e693dde9a90ca5476e1 (diff)
downloadbridge-effeea65388b116f3ec1a41e7596b39bf3c1d576.tar.gz
bridge-effeea65388b116f3ec1a41e7596b39bf3c1d576.zip
prevent deadlocks
Diffstat (limited to 'api.js')
-rw-r--r--api.js60
1 files changed, 46 insertions, 14 deletions
diff --git a/api.js b/api.js
index 48207bf..f24d1bc 100644
--- a/api.js
+++ b/api.js
@@ -141,22 +141,54 @@ app.get("/api/player/:name", async (req, res) => {
}
};
- var job = await raw.query(`
- UPDATE jobs SET priority=0
- WHERE
- (
- (type='grab' AND payload=$1) OR
- (type='process' AND payload->>'playername'=$1->'params'->>'filter[playerNames]') OR
- (type='compile' AND payload->>'type'='player' AND payload->>'id'=$1->'params'->>'filter[playerIds]')
- ) AND status<>'finished' AND status<>'failed'
- RETURNING id
- `, [payload]);
- if (job.rows.length == 0) {
- job = await raw.query(`
- INSERT INTO jobs(type, payload, priority)
- VALUES('grab', $1, 0)
+ /* transaction begin */
+ try {
+ await raw.query("BEGIN");
+ await raw.query("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
+ var job = await raw.query(`
+ UPDATE jobs SET priority=0
+ WHERE
+ (
+ (type='grab' AND payload=$1) OR
+ (type='process' AND payload->>'playername'=$1->'params'->>'filter[playerNames]') OR
+ (type='compile' AND payload->>'type'='player' AND payload->>'id'=$1->'params'->>'filter[playerIds]')
+ ) AND status<>'finished' AND status<>'failed'
RETURNING id
`, [payload]);
+ await raw.query("COMMIT");
+ } catch (err) {
+ if (err.code == "40001") {
+ // serialization error - expected
+ res.sendStatus(202); // try again
+ return;
+ } else {
+ throw err;
+ }
+ }
+ /* transaction end */
+
+ if (job.rows.length == 0) {
+ /* transaction begin */
+ try {
+ await raw.query("BEGIN");
+ await raw.query("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
+ job = await raw.query(`
+ INSERT INTO jobs(type, payload, priority)
+ VALUES('grab', $1, 0)
+ RETURNING id
+ `, [payload]);
+ await raw.query("COMMIT");
+ } catch (err) {
+ if (err.code == "40001") {
+ // serialization error - expected
+ res.sendStatus(202); // try again
+ return;
+ } else {
+ throw err;
+ }
+ }
+ /* transaction end */
+
// wake apigrabber up
await raw.query(`NOTIFY grab_open`, []);
console.log("player '" + name + "' new job requested");