forked from lucagrulla/node-tail
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tail.coffee
70 lines (58 loc) · 2.05 KB
/
tail.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
events= require("events")
fs =require('fs')
environment = process.env['NODE_ENV'] || 'development'
class Tail extends events.EventEmitter
readBlock:()=>
if @queue.length >= 1
block = @queue.shift()
if block.end > block.start
stream = fs.createReadStream(@filename, {start:block.start, end:block.end-1, encoding:"utf-8"})
stream.on 'error',(error) =>
console.log("Tail error:#{error}")
@emit('error', error)
stream.on 'end',=>
@internalDispatcher.emit("next") if @queue.length >= 1
stream.on 'data', (data) =>
@buffer += data
parts = @buffer.split(@separator)
@buffer = parts.pop()
@emit("line", chunk) for chunk in parts
constructor:(@filename, @separator='\n', @fsWatchOptions = {}) ->
@buffer = ''
@internalDispatcher = new events.EventEmitter()
@queue = []
@isWatching = false
stats = fs.statSync(@filename)
@pos = stats.size
@internalDispatcher.on 'next',=>
@readBlock()
@watch()
watch: ->
return if @isWatching
@isWatching = true
if fs.watch then @watcher = fs.watch @filename, @fsWatchOptions, (e) => @watchEvent e
else
fs.watchFile @filename, @fsWatchOptions, (curr, prev) => @watchFileEvent curr, prev
watchEvent: (e) ->
if e is 'change'
stats = fs.statSync(@filename)
@pos = stats.size if stats.size < @pos #scenario where texts is not appended but it's actually a w+
if stats.size > @pos
@queue.push({start: @pos, end: stats.size})
@pos = stats.size
@internalDispatcher.emit("next") if @queue.length is 1
else if e is 'rename'
@unwatch()
@emit "error", "File #{@filename} deleted"
watchFileEvent: (curr, prev) ->
if curr.size > prev.size
@queue.push({start:prev.size, end:curr.size})
@internalDispatcher.emit("next") if @queue.length is 1
unwatch: ->
if fs.watch && @watcher
@watcher.close()
@pos = 0
else fs.unwatchFile @filename
@isWatching = false
@queue = []
exports.Tail = Tail