listen 2.10.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +11 -46
- data/lib/listen.rb +19 -40
- data/lib/listen/adapter.rb +1 -3
- data/lib/listen/adapter/base.rb +66 -36
- data/lib/listen/adapter/config.rb +21 -0
- data/lib/listen/adapter/linux.rb +5 -7
- data/lib/listen/adapter/polling.rb +2 -1
- data/lib/listen/backend.rb +41 -0
- data/lib/listen/change.rb +45 -26
- data/lib/listen/cli.rb +3 -11
- data/lib/listen/directory.rb +31 -29
- data/lib/listen/event/config.rb +59 -0
- data/lib/listen/event/loop.rb +113 -0
- data/lib/listen/event/processor.rb +122 -0
- data/lib/listen/event/queue.rb +54 -0
- data/lib/listen/file.rb +9 -9
- data/lib/listen/fsm.rb +131 -0
- data/lib/listen/internals/thread_pool.rb +1 -1
- data/lib/listen/listener.rb +66 -305
- data/lib/listen/listener/config.rb +45 -0
- data/lib/listen/logger.rb +32 -0
- data/lib/listen/options.rb +1 -1
- data/lib/listen/queue_optimizer.rb +38 -20
- data/lib/listen/record.rb +50 -65
- data/lib/listen/silencer/controller.rb +48 -0
- data/lib/listen/version.rb +1 -1
- metadata +12 -21
- data/lib/listen/adapter/tcp.rb +0 -88
- data/lib/listen/internals/logging.rb +0 -35
- data/lib/listen/tcp.rb +0 -8
- data/lib/listen/tcp/broadcaster.rb +0 -79
- data/lib/listen/tcp/message.rb +0 -50
data/lib/listen/adapter/tcp.rb
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
require 'celluloid/io'
|
2
|
-
|
3
|
-
require 'listen/tcp/message'
|
4
|
-
|
5
|
-
module Listen
|
6
|
-
module Adapter
|
7
|
-
# Adapter to receive file system modifications over TCP
|
8
|
-
class TCP < Base
|
9
|
-
OS_REGEXP = // # match any
|
10
|
-
|
11
|
-
include Celluloid::IO
|
12
|
-
finalizer :finalize
|
13
|
-
|
14
|
-
DEFAULTS = {
|
15
|
-
host: 'localhost',
|
16
|
-
port: '4000'
|
17
|
-
}
|
18
|
-
|
19
|
-
attr_reader :buffer, :socket
|
20
|
-
|
21
|
-
# Initializes and starts a Celluloid::IO-powered TCP-recipient
|
22
|
-
def start
|
23
|
-
attempts ||= 3
|
24
|
-
_log :info, "TCP: opening socket #{options.host}:#{options.port}"
|
25
|
-
@socket = TCPSocket.new(options.host, options.port)
|
26
|
-
@buffer = ''
|
27
|
-
async.run
|
28
|
-
rescue Celluloid::Task::TerminatedError
|
29
|
-
_log :debug, "TCP adapter was terminated: #{$ERROR_INFO.inspect}"
|
30
|
-
rescue Errno::ECONNREFUSED
|
31
|
-
sleep 1
|
32
|
-
attempts -= 1
|
33
|
-
_log :warn, "TCP.start: #{$ERROR_INFO.inspect}"
|
34
|
-
retry if attempts > 0
|
35
|
-
_log :error, format('TCP.start: %s:%s', $ERROR_INFO.inspect,
|
36
|
-
$ERROR_POSITION * "\n")
|
37
|
-
raise
|
38
|
-
rescue
|
39
|
-
_log :error, format('TCP.start: %s:%s', $ERROR_INFO.inspect,
|
40
|
-
$ERROR_POSITION * "\n")
|
41
|
-
raise
|
42
|
-
end
|
43
|
-
|
44
|
-
# Cleans up buffer and socket
|
45
|
-
def finalize
|
46
|
-
@buffer = nil
|
47
|
-
return unless @socket
|
48
|
-
|
49
|
-
@socket.close
|
50
|
-
@socket = nil
|
51
|
-
end
|
52
|
-
|
53
|
-
# Number of bytes to receive at a time
|
54
|
-
RECEIVE_WINDOW = 1024
|
55
|
-
|
56
|
-
# Continuously receive and asynchronously handle data
|
57
|
-
def run
|
58
|
-
while (data = @socket.recv(RECEIVE_WINDOW))
|
59
|
-
async.handle_data(data)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# Buffers incoming data and handles messages accordingly
|
64
|
-
def handle_data(data)
|
65
|
-
@buffer << data
|
66
|
-
while (message = Listen::TCP::Message.from_buffer(@buffer))
|
67
|
-
handle_message(message)
|
68
|
-
end
|
69
|
-
rescue
|
70
|
-
_log :error, format('TCP.handle_data crashed: %s:%s', $ERROR_INFO,
|
71
|
-
$ERROR_POSITION * "\n")
|
72
|
-
raise
|
73
|
-
end
|
74
|
-
|
75
|
-
# Handles incoming message by notifying of path changes
|
76
|
-
def handle_message(message)
|
77
|
-
type, change, dir, path, _ = message.object
|
78
|
-
_log(:debug) { "TCP message: #{[type, change, dir, path].inspect}" }
|
79
|
-
|
80
|
-
_queue_change(type.to_sym, Pathname(dir), path, change: change.to_sym)
|
81
|
-
end
|
82
|
-
|
83
|
-
def self.local_fs?
|
84
|
-
false
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'celluloid/logger'
|
2
|
-
|
3
|
-
module Listen
|
4
|
-
module Internals
|
5
|
-
module Logging
|
6
|
-
def _info(*args, &block)
|
7
|
-
_log(:info, *args, &block)
|
8
|
-
end
|
9
|
-
|
10
|
-
def _warn(*args, &block)
|
11
|
-
_log(:warn, *args, &block)
|
12
|
-
end
|
13
|
-
|
14
|
-
def _debug(*args, &block)
|
15
|
-
_log(:debug, *args, &block)
|
16
|
-
end
|
17
|
-
|
18
|
-
def _log(*args, &block)
|
19
|
-
if block
|
20
|
-
Celluloid::Logger.send(*args, block.call)
|
21
|
-
else
|
22
|
-
Celluloid::Logger.send(*args)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def _format_error(fmt)
|
27
|
-
format(fmt, $ERROR_INFO, ", Backtrace: \n" + $ERROR_POSITION * "\n")
|
28
|
-
end
|
29
|
-
|
30
|
-
def _error_exception(fmt)
|
31
|
-
_log :error, _format_error(fmt)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
data/lib/listen/tcp.rb
DELETED
@@ -1,79 +0,0 @@
|
|
1
|
-
require 'celluloid/io'
|
2
|
-
|
3
|
-
module Listen
|
4
|
-
module TCP
|
5
|
-
class Broadcaster
|
6
|
-
include Celluloid::IO
|
7
|
-
|
8
|
-
finalizer :finalize
|
9
|
-
|
10
|
-
# Initializes a Celluloid::IO-powered TCP-broadcaster
|
11
|
-
#
|
12
|
-
# @param [String] host to broadcast on
|
13
|
-
# @param [String] port to broadcast on
|
14
|
-
#
|
15
|
-
# Note: Listens on all addresses when host is nil
|
16
|
-
#
|
17
|
-
def initialize(host, port)
|
18
|
-
@sockets = []
|
19
|
-
_log :debug, format('Broadcaster: tcp server listening on: %s:%s',
|
20
|
-
host, port)
|
21
|
-
@server = TCPServer.new(host, port)
|
22
|
-
rescue
|
23
|
-
_log :error, format('Broadcaster.initialize: %s:%s', $ERROR_INFO,
|
24
|
-
$ERROR_POSITION * "\n")
|
25
|
-
raise
|
26
|
-
end
|
27
|
-
|
28
|
-
# Asynchronously start accepting connections
|
29
|
-
def start
|
30
|
-
async.run
|
31
|
-
end
|
32
|
-
|
33
|
-
# Cleans up sockets and server
|
34
|
-
def finalize
|
35
|
-
@sockets.map(&:close) if @sockets
|
36
|
-
@sockets = nil
|
37
|
-
|
38
|
-
return unless @server
|
39
|
-
@server.close
|
40
|
-
@server = nil
|
41
|
-
end
|
42
|
-
|
43
|
-
# Broadcasts given payload to all connected sockets
|
44
|
-
def broadcast(payload)
|
45
|
-
active_sockets = @sockets.select do |socket|
|
46
|
-
_unicast(socket, payload)
|
47
|
-
end
|
48
|
-
@sockets.replace(active_sockets)
|
49
|
-
end
|
50
|
-
|
51
|
-
# Continuously accept and handle incoming connections
|
52
|
-
def run
|
53
|
-
while (socket = @server.accept)
|
54
|
-
@sockets << socket
|
55
|
-
end
|
56
|
-
rescue Celluloid::Task::TerminatedError
|
57
|
-
_log :debug, "TCP adapter was terminated: #{$ERROR_INFO}"
|
58
|
-
rescue
|
59
|
-
_log :error, format('Broadcaster.run: %s:%s', $ERROR_INFO,
|
60
|
-
$ERROR_POSITION * "\n")
|
61
|
-
raise
|
62
|
-
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
def _log(type, message)
|
67
|
-
Celluloid::Logger.send(type, message)
|
68
|
-
end
|
69
|
-
|
70
|
-
def _unicast(socket, payload)
|
71
|
-
socket.write(payload)
|
72
|
-
true
|
73
|
-
rescue IOError, Errno::ECONNRESET, Errno::EPIPE
|
74
|
-
_log :debug, "Broadcaster failed: #{socket.inspect}"
|
75
|
-
false
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
data/lib/listen/tcp/message.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
|
3
|
-
module Listen
|
4
|
-
module TCP
|
5
|
-
class Message
|
6
|
-
attr_reader :body, :object, :payload, :size
|
7
|
-
|
8
|
-
HEADER_SIZE = 4
|
9
|
-
HEADER_FORMAT = 'N'
|
10
|
-
PAYLOAD_FORMAT = "#{HEADER_FORMAT}a*"
|
11
|
-
|
12
|
-
# Initializes a new message
|
13
|
-
#
|
14
|
-
# @param [Object] object to initialize message with
|
15
|
-
#
|
16
|
-
def initialize(*args)
|
17
|
-
self.object = args
|
18
|
-
end
|
19
|
-
|
20
|
-
# Generates message size and payload for given object
|
21
|
-
def object=(obj)
|
22
|
-
@object = obj
|
23
|
-
@body = JSON.generate(@object)
|
24
|
-
@size = @body.bytesize
|
25
|
-
@payload = [@size, @body].pack(PAYLOAD_FORMAT)
|
26
|
-
end
|
27
|
-
|
28
|
-
# Extracts message size and loads object from given payload
|
29
|
-
def payload=(payload)
|
30
|
-
@payload = payload
|
31
|
-
@size, @body = @payload.unpack(PAYLOAD_FORMAT)
|
32
|
-
@object = JSON.parse(@body)
|
33
|
-
end
|
34
|
-
|
35
|
-
# Extracts a message from given buffer
|
36
|
-
def self.from_buffer(buffer)
|
37
|
-
if buffer.bytesize > HEADER_SIZE
|
38
|
-
size = buffer.unpack(HEADER_FORMAT).first
|
39
|
-
payload_size = HEADER_SIZE + size
|
40
|
-
if buffer.bytesize >= payload_size
|
41
|
-
payload = buffer.slice!(0...payload_size)
|
42
|
-
new.tap do |message|
|
43
|
-
message.payload = payload
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|