Skip to content

Commit

Permalink
refactor: start() should throw if filename doesn't exist
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Error handling for `start` is changing.

Since `start` is an `async` function, one would expect to
be able to try/catch it. The original version ran any
failures through the `quit` method, but it's designed to
fail gracefully and work asynchronously by using `'error'`
events. This causes weird flow issues if  `start` is throwing·
because the filename does not exist. This change allows
`start` to simply throw.

Semver: major
Ref: LOG-8030
  • Loading branch information
darinspivey committed Nov 16, 2020
1 parent 279b15e commit b05648c
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 41 deletions.
50 changes: 32 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,12 @@ const tail = new TailFile('/path/to/your/logfile.txt', {encoding: 'utf8'})
.on('data', (chunk) => {
console.log(`Recieved a utf8 character chunk: ${chunk}`)
})
.on('error', (err) => {
.on('tail_error', (err) => {
console.error('TailFile had an error!', err)
})
.on('error', (err) => {
console.error('A TailFile stream error was likely encountered', err)
})
.start()
.catch((err) => {
console.error('Cannot start. Does the file exist?', err)
Expand All @@ -86,12 +89,14 @@ const TailFile = require('@logdna/tail-file')
const LineSplitter = require('your-line-splitter') // There are many of these in the wild

const tail = new TailFile('/path/to/your/logfile.txt')
.on('error', (err) => {
.on('tail_error', (err) => {
console.error('TailFile had an error!', err)
throw err
})
.start()
.catch((err) => {
console.error('Cannot start. Does the file exist?', err)
throw err
})

// Data won't start flowing until piping
Expand All @@ -111,23 +116,33 @@ recommended since it will edge out `readline` slightly in performance.

```js
const readline = require('readline')
const tail = new TailFile('./somelog.txt')
.on('error', (err) => {
console.error('TailFile had an error!', err)
})
.start()
.catch((err) => {
console.error('Cannot start. Does the file exist?', err)
})
const TailFile = require('@logdna/tail-file')

const linesplitter = readline.createInterface({
input: tail
})
async function startTail() {
const tail = new TailFile('./somelog.txt')
.on('tail_error', (err) => {
console.error('TailFile had an error!', err)
})

try {
await tail.start()
const linesplitter = readline.createInterface({
input: tail
})

linesplitter.on('line', (line) => {
console.log(line)
})
} catch (err) {
console.error('Cannot start. Does the file exist?', err)
}
}

linesplitter.on('line', (line) => {
console.log(line)
startTail().catch((err) => {
process.nextTick(() => {
throw err
})
})

```

## Events
Expand Down Expand Up @@ -242,8 +257,7 @@ Useful settings such as `encoding: 'utf8'` can be used this way.
### `tail.start()`

* Returns: [`<Promise>`][] - Resolves after the file is polled successfully
* Emits: [`<Error>`][] and [other `Readable` events](#event-any-readable-event)
* Rejects: If `filename` is not found, the promise is rejected
* Rejects: If `filename` is not found

Calling `start()` begins the polling of `filename` to watch for added/changed bytes.
`start()` may be called before or after data is set up to be consumed with a
Expand Down
8 changes: 2 additions & 6 deletions lib/tail-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,8 @@ class TailFile extends Readable {
}

async start() {
try {
await this._openFile()
await this._pollFileForChanges()
} catch (err) {
return this.quit(err)
}
await this._openFile()
await this._pollFileForChanges()
return
}

Expand Down
25 changes: 8 additions & 17 deletions test/tail-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,23 +324,14 @@ test('Success: startPos can be provided to start tailing at a given place', (t)
})
})

test('Error: filename provided does not exist (poll error)', (t) => {
t.plan(3)

const tail = new TailFile('THISFILEDOSNOTEXIST', {maxPollFailures: 1})
.on('error', (err) => {
t.type(err, Error, 'error was emitted')
t.match(err, {
name: 'Error'
, code: 'ENOENT'
, path: 'THISFILEDOSNOTEXIST'
, message: /no such file or directory/
})
})

t.test('Start', async (tt) => {
await tail.start()
})
test('Error: filename provided does not exist (throws on start)', async (t) => {
const tail = new TailFile('THISFILEDOSNOTEXIST')
await t.rejects(tail.start(), {
name: 'Error'
, code: 'ENOENT'
, path: 'THISFILEDOSNOTEXIST'
, message: /no such file or directory/
}, 'Expected error is thrown')
})

test('Error: poll error will retry a certain number of times', (t) => {
Expand Down

0 comments on commit b05648c

Please sign in to comment.