Skip to content

Commit

Permalink
feat(sqlite): Gracefully handle issues creating sqlite indices
Browse files Browse the repository at this point in the history
The creation of the `spr_obsolete` index is problematic for the PIP
service and any of the admin lookup workers running in the importers.

Because there are always multiple processes doing admin lookup, and each
one tries to create the index if it doesn't exist, most end up failing.
SQLite only allows a single write lock on the DB, so all but one will
fail to achieve it.

However, in my testing, all it takes to solve this gracefully is to wrap
the index creation in a try/catch block. The index will be created by
one of the worker processes, and all subsequent queries appear to have
the performance improvements of the index (about 30-50% faster time to
load admin data).

Supersedes #431
Fixes #454
Connects #453 (we should not
actually remove the index creation quite yet)
  • Loading branch information
orangejulius committed Aug 2, 2019
1 parent acba2f0 commit 8b0c2ae
Showing 1 changed file with 19 additions and 7 deletions.
26 changes: 19 additions & 7 deletions src/components/sqliteStream.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,28 @@ const Readable = require('stream').Readable;
const Sqlite3 = require('better-sqlite3');
const logger = require('pelias-logger').get('whosonfirst:sqliteStream');

// attempt to create index to improve read performance
//
// catch all failures since the PIP service will have several processes all
// trying to acquire a write lock on the DB, and only one will succeed
//
// note: can be removed once the upstream PR is merged and all data on
// dist.whosonfirst.org is updated:
// https://github.com/whosonfirst/go-whosonfirst-sqlite-features/pull/4
function createIndex(dbPath) {
try {
new Sqlite3(dbPath)
.exec('CREATE INDEX IF NOT EXISTS spr_obsolete ON spr (is_deprecated, is_superseded)')
.close();
} catch (e){
}
}

class SQLiteStream extends Readable {
constructor(dbPath, sql) {
super({ objectMode: true, autoDestroy: true, highWaterMark: 32 });

// ensure indices exist
// note: this can be removed once the upstream PR is merged:
// https://github.com/whosonfirst/go-whosonfirst-sqlite-features/pull/4
new Sqlite3(dbPath)
.exec('CREATE INDEX IF NOT EXISTS spr_obsolete ON spr (is_deprecated, is_superseded)')
.close();
createIndex(dbPath);

this._db = new Sqlite3(dbPath, { readonly: true });
this._iterator = this._db.prepare(sql).iterate();
Expand Down Expand Up @@ -81,4 +93,4 @@ function findGeoJSONByPlacetypeAndWOFId(placetypes, wofids) {
module.exports = SQLiteStream;
module.exports.findGeoJSON = findGeoJSON;
module.exports.findGeoJSONByPlacetype = findGeoJSONByPlacetype;
module.exports.findGeoJSONByPlacetypeAndWOFId = findGeoJSONByPlacetypeAndWOFId;
module.exports.findGeoJSONByPlacetypeAndWOFId = findGeoJSONByPlacetypeAndWOFId;

0 comments on commit 8b0c2ae

Please sign in to comment.