carnivore-files 0.2.0 → 0.2.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4150377900b933160fc7b0efb9ad3b022f30d062
4
- data.tar.gz: 29eee65845600e46a3b99d3f15fca7c61d54e679
3
+ metadata.gz: c9393f45222d01b7842f08069591d1e50c3371dc
4
+ data.tar.gz: 515225fcea7f56ae7c1d4596c951ee3ca827668f
5
5
  SHA512:
6
- metadata.gz: 35a949382dbeedde31e19f07c1bc9682876446f7b889defb4352c620d95885ca45330d7f86835aaa106f2b77a3315175a7ff4ef93259b6cf9bd3a1e3dec83217
7
- data.tar.gz: 8bf78650c8048131e5b64ef7c6816fc5704791986dd62a5217a3863e48f6c8e5942a4c9966e4ea7f8e247381513dc28fb483b6b3544e5d0b1aa8db2c783122cc
6
+ metadata.gz: 36b7787ad5dbbcff760a296a5dcb405d1998ed87451ecfd43bdd0461623629a8f368c7076f284409ceed821038af270837e886b5bcd803ccc4766d79013275e0
7
+ data.tar.gz: 435775b1547fa6920900783830c1fd5bbc057606608ed9a7bc7e934a3cf0bfc5790b693ffc41150a14ea0d4cc1573910867835cfc79a0c6eba477616b0814e67
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ # v0.2.2
2
+ * Clean up file content fetcher implementations
3
+
1
4
  # v0.2.0
2
5
  * Rename Carnivore::Source::File to Carnivore::Source::CarnFile
3
6
 
@@ -1,6 +1,6 @@
1
1
  $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__)) + '/lib/'
2
2
  require 'carnivore-files/version'
3
- Gem::Specification.new do |s|
3
+ spec = Gem::Specification.new do |s|
4
4
  s.name = 'carnivore-files'
5
5
  s.version = Carnivore::Files::VERSION.version
6
6
  s.summary = 'Message processing helper'
@@ -11,9 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.license = 'Apache 2.0'
12
12
  s.require_path = 'lib'
13
13
  s.add_dependency 'carnivore', '>= 0.1.8'
14
- # support both but don't want to install both
15
- # update to be setup like carnivore-rabbitmq
16
- # s.add_dependency 'nio4r'
17
14
  s.add_dependency 'sleepy_penguin'
15
+ s.add_dependency 'nio4r'
18
16
  s.files = Dir['{lib}/**/**/*'] + %w(carnivore-files.gemspec README.md CHANGELOG.md)
19
17
  end
@@ -8,7 +8,10 @@ module Carnivore
8
8
  # @return [String] path to file
9
9
  attr_reader :path
10
10
  # @return [Symbol] registry name of fetcher
11
- attr_reader :fetcher_name
11
+ attr_reader :fetcher
12
+
13
+ trap_exit :fetcher_failure
14
+ finalizer :fetcher_destroyer
12
15
 
13
16
  # Setup source
14
17
  #
@@ -16,40 +19,46 @@ module Carnivore
16
19
  # @option args [String] :path path to file
17
20
  # @option args [Symbol] :foundation underlying file interaction library
18
21
  # @option args [Celluloid::Actor] :notify_actor actor to notify on line receive
19
- def setup(args={})
22
+ def setup(*_)
20
23
  @path = ::File.expand_path(args[:path])
21
- @fetcher_name = "log_fetcher_#{name}".to_sym
22
24
  unless(args[:foundation])
23
- args[:foundation] = RUBY_ENGINE == 'jruby' ? :nio4r : :penguin
25
+ args[:foundation] = RUBY_PLATFORM == 'java' ? :nio4r : :penguin
24
26
  end
27
+ end
28
+
29
+ # Start the line fetcher
30
+ def connect
31
+ @fetcher_name = "log_fetcher_#{name}".to_sym
25
32
  case args[:foundation].to_sym
26
33
  when :nio, :nio4r
27
- callback_supervisor.supervise_as(fetcher_name, Carnivore::Files::Util::Fetcher::Nio,
28
- args.merge(:notify_actor => current_actor)
29
- )
34
+ @fetcher = Carnivore::Files::Util::Fetcher::Nio.new(args)
30
35
  else
31
- callback_supervisor.supervise_as(fetcher_name, Carnivore::Files::Util::Fetcher::Penguin,
32
- args.merge(:notify_actor => current_actor)
33
- )
36
+ @fetcher = Carnivore::Files::Util::Fetcher::Penguin.new(args)
34
37
  end
38
+ self.link fetcher
39
+ fetcher.async.start_fetcher
35
40
  end
36
41
 
37
- # @return [Carnivore::Files::Util::Fetcher] line fetcher
38
- def fetcher
39
- callback_supervisor[fetcher_name]
42
+ # Restart file collector if unexpectedly failed
43
+ #
44
+ # @param object [Actor] crashed actor
45
+ # @param reason [Exception, NilClass]
46
+ def fetcher_failure(object, reason)
47
+ if(reason && object == fetcher)
48
+ error "File message collector unexpectedly failed: #{reason} (restarting)"
49
+ connect
50
+ end
40
51
  end
41
52
 
42
- # Start the line fetcher
43
- def connect
44
- fetcher.async.start_fetcher
53
+ def fetcher_destroyer
54
+ if(fetcher && fetcher.alive?)
55
+ fetcher.terminate
56
+ end
45
57
  end
46
58
 
47
59
  # @return [Array<Hash>] return messages
48
60
  def receive(*args)
49
- wait(:new_log_lines)
50
- fetcher.return_lines.map do |l|
51
- format_message(l)
52
- end
61
+ format_message(Celluloid::Future.new{ fetcher.messages.pop }.value)
53
62
  end
54
63
 
55
64
  # Send payload
@@ -1,3 +1,5 @@
1
+ require 'carnivore-files'
2
+
1
3
  module Carnivore
2
4
  module Files
3
5
  # Helper utilities
@@ -15,10 +17,8 @@ module Carnivore
15
17
  attr_reader :path
16
18
  # @return [String] string to split messages on
17
19
  attr_reader :delimiter
18
- # @return [Celluloid::Actor] actor to notify on new messages
19
- attr_reader :notify_actor
20
20
 
21
- # @return [Array] messages
21
+ # @return [Queue] messages
22
22
  attr_accessor :messages
23
23
  # @return [IO] underlying IO instance
24
24
  attr_accessor :io
@@ -33,29 +33,12 @@ module Carnivore
33
33
  @leftover = ''
34
34
  @path = ::File.expand_path(args[:path])
35
35
  @delimiter = args.fetch(:delimiter, "\n")
36
- @notify_actor = args[:notify_actor]
37
- @messages = []
36
+ @messages = Queue.new
38
37
  end
39
38
 
40
39
  # Start the line fetcher
41
40
  def start_fetcher
42
- defer do
43
- loop do
44
- build_socket
45
- messages = nil
46
- selector.select.each do |mon|
47
- self.messages += retrieve_lines
48
- end
49
- notify_actor.signal(:new_logs_lines) unless self.messages.empty?
50
- end
51
- end
52
- end
53
-
54
- # @return [Array<String>] current lines
55
- def return_lines
56
- msgs = messages.dup
57
- messages.clear
58
- msgs
41
+ raise NotImplementedError
59
42
  end
60
43
 
61
44
  # Write line to IO
@@ -84,6 +67,31 @@ module Carnivore
84
67
  end
85
68
  end
86
69
 
70
+ # Build the IO and monitor
71
+ #
72
+ # @return [TrueClass, FalseClass]
73
+ def build_io
74
+ unless(io)
75
+ if(::File.exists?(path))
76
+ @io = ::File.open(path, 'r')
77
+ unless(@waited)
78
+ @io.seek(0, ::IO::SEEK_END) # fast-forward to EOF
79
+ else
80
+ @waited = false
81
+ retrieve_lines.each do |l|
82
+ self.messages << l
83
+ end
84
+ end
85
+ else
86
+ wait_for_file
87
+ build_io
88
+ end
89
+ true
90
+ else
91
+ false
92
+ end
93
+ end
94
+
87
95
  end
88
96
  end
89
97
  end
@@ -26,14 +26,13 @@ module Carnivore
26
26
 
27
27
  # Start the fetcher
28
28
  def start_fetcher
29
- defer do
30
- loop do
31
- build_io
32
- messages = nil
33
- selector.select.each do |mon|
34
- self.messages += retrieve_lines
29
+ loop do
30
+ build_io
31
+ messages = nil
32
+ Celluloid::Future.new{ selector.select }.value.each do |mon|
33
+ retrieve_lines.each do |l|
34
+ self.messages << l
35
35
  end
36
- notify_actor.signal(:new_log_lines) unless self.messages.empty?
37
36
  end
38
37
  end
39
38
  end
@@ -46,6 +45,7 @@ module Carnivore
46
45
  begin
47
46
  unless(io.stat.ino == ::File.stat(path).ino)
48
47
  destroy_io
48
+ @waited = true
49
49
  end
50
50
  rescue Errno::ENOENT
51
51
  destroy_io
@@ -57,19 +57,11 @@ module Carnivore
57
57
  #
58
58
  # @return [TrueClass]
59
59
  def build_io
60
- unless(monitor)
61
- if(::File.exists?(path))
62
- unless(io)
63
- @io = ::File.open(path, 'r')
64
- @io.seek(0, ::IO::SEEK_END) # fast-forward to EOF
65
- end
66
- @monitor = selector.register(io, :r)
67
- else
68
- wait_for_file
69
- build_io
70
- end
60
+ result = super
61
+ if(result && @monitor.nil?)
62
+ @monitor = selector.register(io, :r)
71
63
  end
72
- true
64
+ result
73
65
  end
74
66
 
75
67
  # Destroy the IO instance and monitor
@@ -93,6 +85,7 @@ module Carnivore
93
85
  def wait_for_file
94
86
  warn "Waiting for file to appear (#{path})"
95
87
  until(::File.exists?(path))
88
+ @waited = true
96
89
  sleep(5)
97
90
  end
98
91
  info "File has appeared (#{path})!"
@@ -24,41 +24,41 @@ module Carnivore
24
24
 
25
25
  # Start the fetcher
26
26
  def start_fetcher
27
- defer do
28
- loop do
29
- build_io
30
- notify.each do |event|
31
- event.events.each do |ev|
32
- case ev
33
- when :MODIFY
34
- self.messages += retrieve_lines
35
- when :MOVE_SELF, :DELETE_SELF, :ATTRIB
36
- destroy_io
27
+ loop do
28
+ build_io
29
+ notify.each do |event|
30
+ Celluloid::Future.new{ event.events }.value.each do |ev|
31
+ case ev
32
+ when :MODIFY
33
+ retrieve_lines.each do |l|
34
+ self.messages << l
37
35
  end
36
+ when :MOVE_SELF, :DELETE_SELF, :ATTRIB
37
+ info "Destroying file IO due to FS modification! (#{ev.inspect})"
38
+ destroy_io
39
+ @waited = true
40
+ break
41
+ else
42
+ debug "Received unhandled event: #{ev.inspect}"
38
43
  end
39
- notify_actor.signal(:new_log_lines) unless messages.empty?
40
44
  end
45
+ break unless io
41
46
  end
42
47
  end
43
48
  end
44
49
 
50
+
45
51
  private
46
52
 
47
53
  # Build the IO and monitor
48
54
  #
49
- # @return [TrueClass]
55
+ # @return [TrueClass, FalseClass]
50
56
  def build_io
51
- unless(io)
52
- if(::File.exists?(path))
53
- notify_descriptors[:file_watch] = notify.add_watch(path, :ALL_EVENTS)
54
- @io = ::File.open(path, 'r')
55
- @io.seek(0, ::IO::SEEK_END) # fast-forward to EOF
56
- else
57
- wait_for_file
58
- build_io
59
- end
57
+ result = super
58
+ if(result)
59
+ notify_descriptors[:file_watch] = notify.add_watch(path, :ALL_EVENTS)
60
60
  end
61
- true
61
+ result
62
62
  end
63
63
 
64
64
  # Destroy the IO and monitor
@@ -84,13 +84,12 @@ module Carnivore
84
84
  notify_descriptors[:file_wait] = notify.add_watch(directory, :OPEN)
85
85
  until(notified)
86
86
  warn "Waiting for file to appear (#{path})"
87
- event = notify.take
88
- if(event.name)
89
- notified = ::File.expand_path(event.name) == path
90
- end
87
+ event = Celluloid::Future.new{ notify.take }.value
88
+ notified = ::File.exists?(path)
91
89
  end
92
90
  notify.rm_watch(notify_descriptors.delete(:file_wait))
93
91
  end
92
+ @waited = true
94
93
  info "File has appeared (#{path})!"
95
94
  end
96
95
 
@@ -1,6 +1,6 @@
1
1
  module Carnivore
2
2
  module Files
3
3
  # Current version of library
4
- VERSION = Gem::Version.new('0.2.0')
4
+ VERSION = Gem::Version.new('0.2.2')
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carnivore-files
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Roberts
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-11 00:00:00.000000000 Z
11
+ date: 2015-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: carnivore
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: nio4r
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  description: Carnivore file source
42
56
  email: code@chrisroberts.org
43
57
  executables: []