Skip to content

Commit

Permalink
fix: Use fs.watchFile instead of fs.watch to detect changes to lo…
Browse files Browse the repository at this point in the history
…aded database file (#368)

* Use `watchFile` instead of `watch` to better handle database replacements

* Try 3 times when db changes to find new file before failing
  • Loading branch information
andrewkarell authored Oct 25, 2020
1 parent 3fc00fa commit db7ab72
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 10 deletions.
3 changes: 1 addition & 2 deletions src/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ import util from 'util';
export default {
existsSync: fs.existsSync,
readFile: util.promisify(fs.readFile),
readFileSync: fs.readFileSync,
watch: fs.watch,
watchFile: fs.watchFile,
};
9 changes: 4 additions & 5 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@ describe('index', () => {
beforeEach(() => {
sandbox = sinon.createSandbox();
// @ts-ignore
sandbox.stub(fs, 'watch').callsFake((paramA, paramB, cb) => {
sandbox.stub(fs, 'watchFile').callsFake((paramA, paramB, cb) => {
watchHandler = cb;
});
sandbox.spy(fs, 'readFile');
sandbox.spy(fs, 'readFileSync');
});
afterEach(() => {
sandbox.restore();
Expand Down Expand Up @@ -51,17 +50,17 @@ describe('index', () => {
const options = { cache: { max: 1000 }, watchForUpdates: true };
const lookup = await maxmind.open(dbPath, options);
assert(lookup.get('2001:230::'));
assert((fs.watch as SinonSpy).calledOnce);
assert((fs.watchFile as SinonSpy).calledOnce);
assert((fs.readFile as SinonSpy).calledOnce);
});

it('should work with auto updates', async () => {
const options = { watchForUpdates: true };
const lookup = await maxmind.open(dbPath, options);
assert(lookup.get('2001:230::'));
assert((fs.watch as SinonSpy).calledOnce);
assert((fs.watchFile as SinonSpy).calledOnce);
assert((fs.readFile as SinonSpy).calledOnce);
watchHandler();
await watchHandler();
assert((fs.readFile as SinonSpy).calledTwice);
});

Expand Down
17 changes: 14 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,21 @@ export const open = async <T>(
persistent: opts.watchForUpdatesNonPersistent !== true,
};

fs.watch(filepath, watcherOptions, async () => {
fs.watchFile(filepath, watcherOptions, async () => {
// When database file is being replaced,
// it could be removed for a fraction of a second.
if (!fs.existsSync(filepath)) {
const waitExists = async () => {
for (let i = 0; i < 3; i++) {
if (fs.existsSync(filepath)) {
return true;
}

await new Promise(a => setTimeout(a, 500));
}

return false;
}
if (!(await waitExists())) {
return;
}
const updateDatabase = await fs.readFile(filepath);
Expand Down Expand Up @@ -83,4 +94,4 @@ export default {
validate: ip.validate,
};

export { Reader };
export { Reader };

0 comments on commit db7ab72

Please sign in to comment.