spider-gazelle 3.0.5 → 3.0.6

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: d98f7022babe544f38425eacb223337cef347ade
4
- data.tar.gz: d214d5a1192828a1d272f7955817f64f9829c7b9
3
+ metadata.gz: 49d9e0d9dee57cc23287f2155e6ebe81137e3f15
4
+ data.tar.gz: 385f9ee18cdc18dab2b1de1f34b689968c617e8a
5
5
  SHA512:
6
- metadata.gz: 659f91228f5efc1879874407ae54ea20c15df0b9129eb30f8d96b59b57c4979e2da5a4ff0b6686ecd701c4976b36903571156401c93b0c0384b218b08b249d5d
7
- data.tar.gz: b4264bc65bad3ec4736f25d38b63e0e0ec3e37617b12f794936a9ed66f0081ef114d206856635e6778d991900c7edf9b6ae9d919baef132ff9407510a2ff28cb
6
+ metadata.gz: 932d6770571115d8e01d8e039725222929e7da5800be5d3ec9730505e97e1f8d153a76dfab4bbfb8ce8deea47993deb7d5a1797fabb7d869e5349c512108b6f7
7
+ data.tar.gz: 3b33aa02ef5fad6b922ef577e22c3b209cd6f2db336f85d74c666f75cc38574dec6db3ae7b76ce2ab1bd50b7af33fdbdc8d26893943f0e1982e3bb3303fff102
@@ -73,25 +73,21 @@ module SpiderGazelle
73
73
  # ---------------------------------------
74
74
  def launch_spider(args)
75
75
  require 'securerandom'
76
- require 'thread'
77
76
 
78
77
  @password ||= SecureRandom.hex
79
- #cmd = "#{EXEC_NAME} -s #{@password} #{Shellwords.join(args)}"
80
- cmd = [EXEC_NAME, '-s', @password] + args
81
78
 
82
- Thread.new do
83
- result = system(*cmd)
79
+ #cmd = "#{EXEC_NAME} -s #{@password} #{Shellwords.join(args)}"
84
80
 
85
- # TODO:: We need to detect a failed load
86
- # This is a little more tricky as spiders
87
- # may come and go without this process exiting
81
+ thread = Reactor.instance.thread
82
+ spider = thread.spawn(EXEC_NAME, args: (['-s', @password] + args), mode: :inherit)
83
+ spider.finally do
84
+ signaller = ::SpiderGazelle::Signaller.instance
85
+ signaller.panic!('Unexpected spider exit') unless signaller.shutting_down
88
86
  end
89
87
  end
90
88
 
91
89
  # This is called when a spider process starts
92
90
  def start_spider(signaller, logger, options)
93
- logger.set_client signaller.pipe unless options[0][:isolate]
94
-
95
91
  require 'spider-gazelle/spider'
96
92
  Spider.instance.run!(options)
97
93
  end
@@ -5,7 +5,7 @@ require 'libuv'
5
5
  module SpiderGazelle
6
6
  class Logger
7
7
  include Singleton
8
- attr_reader :level, :thread, :pipe
8
+ attr_reader :level, :thread, :stdout
9
9
  attr_accessor :formatter
10
10
 
11
11
 
@@ -22,19 +22,14 @@ module SpiderGazelle
22
22
 
23
23
  def initialize
24
24
  @thread = ::Libuv::Reactor.default
25
+ @stdout = @thread.pipe
26
+ @stdout.open(1)
25
27
  @level = DEFAULT_LEVEL
26
- @write = method(:server_write)
27
28
  end
28
29
 
29
30
 
30
31
  def self.log(data)
31
- Logger.instance.server_write(data)
32
- end
33
-
34
-
35
- def set_client(uv_io)
36
- @pipe = uv_io
37
- @write = method(:client_write)
32
+ Logger.instance.stdout.write(data)
38
33
  end
39
34
 
40
35
  def level=(level)
@@ -83,7 +78,7 @@ module SpiderGazelle
83
78
  def verbose(msg = nil)
84
79
  if @verbose
85
80
  msg = yield if block_given?
86
- @write.call ">> #{msg}\n"
81
+ @stdout.write ">> #{msg}\n"
87
82
  end
88
83
  end
89
84
 
@@ -95,11 +90,6 @@ module SpiderGazelle
95
90
  error(message)
96
91
  end
97
92
 
98
- # NOTE:: should only be called on reactor thread
99
- def server_write(msg)
100
- STDOUT.write msg
101
- end
102
-
103
93
 
104
94
  protected
105
95
 
@@ -107,13 +97,8 @@ module SpiderGazelle
107
97
  def log(level, msg)
108
98
  output = "[#{level}] #{msg}\n"
109
99
  @thread.schedule do
110
- @write.call output
100
+ @stdout.write output
111
101
  end
112
102
  end
113
-
114
- # NOTE:: should only be called on reactor thread
115
- def client_write(msg)
116
- @pipe.write "\x02Logger log #{msg}\x03"
117
- end
118
103
  end
119
104
  end
@@ -38,16 +38,17 @@ module SpiderGazelle
38
38
  end
39
39
 
40
40
  @thread.schedule do
41
- return if @shutdown_called
42
- @shutdown_called = true
41
+ if not @shutdown_called
42
+ @shutdown_called = true
43
43
 
44
- # Signaller will manage the shutdown of the gazelles
45
- signaller = Signaller.instance.shutdown
46
- signaller.finally do
47
- @thread.stop
48
- # New line on exit to avoid any ctrl-c characters
49
- # We check for pipe as we only want the master process to print this
50
- puts "\nSpider-Gazelle leaps through the veldt\n" unless @logger.pipe
44
+ # Signaller will manage the shutdown of the gazelles
45
+ signaller = Signaller.instance.shutdown
46
+ signaller.finally do
47
+ @thread.stop
48
+ # New line on exit to avoid any ctrl-c characters
49
+ # We check for pipe as we only want the master process to print this
50
+ puts "\nSpider-Gazelle leaps through the veldt\n"
51
+ end
51
52
  end
52
53
  end
53
54
  end
@@ -8,7 +8,7 @@ module SpiderGazelle
8
8
  include Singleton
9
9
 
10
10
 
11
- attr_reader :thread, :pipe
11
+ attr_reader :thread, :pipe, :is_connected, :shutting_down
12
12
  attr_accessor :gazelle
13
13
 
14
14
 
@@ -19,7 +19,8 @@ module SpiderGazelle
19
19
  # This is used to check if an instance of spider-gazelle is already running
20
20
  @is_master = false
21
21
  @is_client = false
22
- @is_connected = false
22
+ @is_connected = false
23
+ @shutting_down = false
23
24
  @client_check = @thread.defer
24
25
  @validated = [] # Set requires more processing
25
26
  @validating = {}
@@ -42,6 +43,7 @@ module SpiderGazelle
42
43
 
43
44
  def shutdown
44
45
  defer = @thread.defer
46
+ @shutting_down = true
45
47
 
46
48
  # Close the SIGNAL_SERVER pipe
47
49
  @pipe.close if @is_connected
@@ -115,7 +117,6 @@ module SpiderGazelle
115
117
  @pipe.finally do
116
118
  if @is_client
117
119
  @is_connected = false
118
- panic!(nil)
119
120
  else
120
121
  # Assume the role of master
121
122
  become_sg_master
@@ -154,7 +155,7 @@ module SpiderGazelle
154
155
  # If all the process connections are gone then we want to shutdown
155
156
  # This should never happen under normal conditions
156
157
  if @validated.length == 0
157
- Reactor.instance.shutdown
158
+ Reactor.instance.shutdown unless @shutting_down
158
159
  end
159
160
  end
160
161
 
@@ -174,7 +175,7 @@ module SpiderGazelle
174
175
  #@logger.error "Master pipe went missing: #{reason}"
175
176
  # Server most likely exited
176
177
  # We'll shutdown here
177
- STDERR.puts "\n\npanic! #{reason.inspect}\n\n\n"
178
+ STDERR.puts "\n\npanic! #{reason.inspect}\n#{caller.join("\n")}\n\n\n"
178
179
  STDERR.flush
179
180
  Reactor.instance.shutdown
180
181
  end
@@ -101,7 +101,7 @@ module SpiderGazelle
101
101
  def shutdown(finished)
102
102
  @shutdown_defer = finished
103
103
 
104
- @logger.verbose { "Spider Pid: #{Process.pid} shutting down" }
104
+ @logger.verbose { "Spider Pid: #{Process.pid} shutting down (loaded #{@loaded})" }
105
105
 
106
106
  if @loaded
107
107
  perform_shutdown
@@ -3,104 +3,95 @@
3
3
  require 'websocket/driver'
4
4
  require 'forwardable'
5
5
 
6
- module SpiderGazelle
7
- class Websocket < ::Libuv::Q::DeferredPromise
8
- attr_reader :env, :url, :reactor, :socket
6
+ class SpiderGazelle::Websocket < ::Libuv::Q::DeferredPromise
7
+ attr_reader :env, :url, :reactor, :socket
9
8
 
9
+ extend ::Forwardable
10
+ def_delegators :@driver, :start, :ping, :protocol, :ready_state, :set_header, :state, :close
11
+ def_delegators :@socket, :write, :peername
10
12
 
11
- RACK_URL_SCHEME = 'rack.url_scheme'
12
- HTTP_HOST = 'HTTP_HOST'
13
- REQUEST_URI= 'REQUEST_URI'
14
- HTTPS = 'https'
13
+ def initialize(tcp, env)
14
+ @socket, @env = tcp, env
15
15
 
16
+ # Initialise the promise
17
+ super tcp.reactor, tcp.reactor.defer
16
18
 
17
- extend Forwardable
18
- def_delegators :@driver, :start, :ping, :protocol, :ready_state, :set_header, :state, :close
19
- def_delegators :@socket, :write, :peername
19
+ scheme = env['rack.url_scheme'] == 'https' ? 'wss://' : 'ws://'
20
+ @url = scheme + env['HTTP_HOST'] + env['REQUEST_URI']
21
+ @driver = ::WebSocket::Driver.rack self
20
22
 
21
- def initialize(tcp, env)
22
- @socket, @env = tcp, env
23
+ # Pass data from the socket to the driver
24
+ @socket.progress &method(:socket_read)
25
+ @socket.finally &method(:socket_close)
23
26
 
24
- # Initialise the promise
25
- super tcp.reactor, tcp.reactor.defer
26
27
 
27
- scheme = env[RACK_URL_SCHEME] == HTTPS ? 'wss://' : 'ws://'
28
- @url = scheme + env[HTTP_HOST] + env[REQUEST_URI]
29
- @driver = ::WebSocket::Driver.rack self
30
-
31
- # Pass data from the socket to the driver
32
- @socket.progress &method(:socket_read)
33
- @socket.finally &method(:socket_close)
34
-
35
-
36
- # Driver has indicated that it is closing
37
- # We'll close the socket after writing any remaining data
38
- @driver.on :close, &method(:on_close)
39
- @driver.on :message, &method(:on_message)
40
- @driver.on :error, &method(:on_error)
41
- end
28
+ # Driver has indicated that it is closing
29
+ # We'll close the socket after writing any remaining data
30
+ @driver.on :close, &method(:on_close)
31
+ @driver.on :message, &method(:on_message)
32
+ @driver.on :error, &method(:on_error)
33
+ end
42
34
 
43
- # Write some text to the websocket connection
44
- #
45
- # @param string [String] a string of data to be sent to the far end
46
- def text(string)
47
- @reactor.schedule { @driver.text(string.to_s) }
48
- end
35
+ # Write some text to the websocket connection
36
+ #
37
+ # @param string [String] a string of data to be sent to the far end
38
+ def text(string)
39
+ @reactor.schedule { @driver.text(string.to_s) }
40
+ end
49
41
 
50
- # Write some binary data to the websocket connection
51
- #
52
- # @param array [Array] an array of bytes to be sent to the far end
53
- def binary(array)
54
- @reactor.schedule { @driver.binary(array.to_a) }
55
- end
42
+ # Write some binary data to the websocket connection
43
+ #
44
+ # @param array [Array] an array of bytes to be sent to the far end
45
+ def binary(array)
46
+ @reactor.schedule { @driver.binary(array.to_a) }
47
+ end
56
48
 
57
- # Used to define a callback when data is received from the client
58
- #
59
- # @param callback [Proc] the callback to be called when data is received
60
- def progress(callback = nil, &blk)
61
- @progress = callback || blk
62
- end
49
+ # Used to define a callback when data is received from the client
50
+ #
51
+ # @param callback [Proc] the callback to be called when data is received
52
+ def progress(callback = nil, &blk)
53
+ @progress = callback || blk
54
+ end
63
55
 
64
- # Used to define a callback when the websocket connection is established
65
- # Data sent before this callback is buffered.
66
- #
67
- # @param callback [Proc] the callback to be triggered on establishment
68
- def on_open(callback = nil, &blk)
69
- callback ||= blk
70
- @driver.on :open, &callback
71
- end
56
+ # Used to define a callback when the websocket connection is established
57
+ # Data sent before this callback is buffered.
58
+ #
59
+ # @param callback [Proc] the callback to be triggered on establishment
60
+ def on_open(callback = nil, &blk)
61
+ callback ||= blk
62
+ @driver.on :open, &callback
63
+ end
72
64
 
73
- protected
65
+ protected
74
66
 
75
- def socket_read(data, tcp)
76
- begin
77
- @driver.parse data
78
- rescue => e
79
- # Prevent hanging sockets
80
- @socket.close
81
- raise e
82
- end
67
+ def socket_read(data, tcp)
68
+ begin
69
+ @driver.parse data
70
+ rescue => e
71
+ # Prevent hanging sockets
72
+ @socket.close
73
+ raise e
83
74
  end
75
+ end
84
76
 
85
- def socket_close
86
- if @shutdown_called.nil?
87
- @defer.reject WebSocket::Driver::CloseEvent.new(1006, 'connection was closed unexpectedly')
88
- end
77
+ def socket_close
78
+ if @shutdown_called.nil?
79
+ @defer.reject WebSocket::Driver::CloseEvent.new(1006, 'connection was closed unexpectedly')
89
80
  end
81
+ end
90
82
 
91
83
 
92
- def on_message(event)
93
- @progress.call(event.data, self) unless @progress.nil?
94
- end
84
+ def on_message(event)
85
+ @progress.call(event.data, self) unless @progress.nil?
86
+ end
95
87
 
96
- def on_error(event)
97
- @defer.reject event
98
- end
88
+ def on_error(event)
89
+ @defer.reject event
90
+ end
99
91
 
100
- def on_close(event)
101
- @shutdown_called = true
102
- @socket.shutdown
103
- @defer.resolve event
104
- end
92
+ def on_close(event)
93
+ @shutdown_called = true
94
+ @socket.shutdown
95
+ @defer.resolve event
105
96
  end
106
97
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SpiderGazelle
4
- VERSION = '3.0.5'
4
+ VERSION = '3.0.6'
5
5
  EXEC_NAME = 'sg'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spider-gazelle
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.5
4
+ version: 3.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen von Takach
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-27 00:00:00.000000000 Z
11
+ date: 2017-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http-parser
@@ -189,7 +189,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
189
189
  version: '0'
190
190
  requirements: []
191
191
  rubyforge_project:
192
- rubygems_version: 2.6.10
192
+ rubygems_version: 2.6.12
193
193
  signing_key:
194
194
  specification_version: 4
195
195
  summary: A fast, parallel and concurrent web server for ruby