softwear-lib 2.1.7 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 686f7869e707c46dcb3e00e096f5d9a9fbeca06b
4
- data.tar.gz: 33f93003887efb1bb16f1001ad5e018b061562bf
3
+ metadata.gz: 26254fb662076fc8e52a5f9bee3736d645699c65
4
+ data.tar.gz: 64b88c6e858c9000dd9806a8e83af67f8749faa8
5
5
  SHA512:
6
- metadata.gz: 0209fba37cbee0ce9226ae95dd83014acbe4bf45ef3e3d8d21f15e06c00c54297d585ef62c2dc24ee02a04feff0b083440ed92f47492ab27450598706fc260f1
7
- data.tar.gz: a43acf8622808a23ac6e52196156c7fcaff8074cba848864cbbe30eec89339cf7ff504ac8d7eaca0ad325f171eb741d7ad061d222971ea118ad7afbe5db1f14e
6
+ metadata.gz: 0c766b1ed256367e2c1f58ef2d8dcc45f46164c268feb0c10169724cb0509c187b69b646b822c8765120871098f4629f8f1104d7d8a1d655aa2a724f35bfd133
7
+ data.tar.gz: 24be483b5caa64e24e39800a41a08aeee07d2914a76e1ab99041e1dae3256f5948f6887079f59c788870e0b33ae7498634bac0331746d0a5653910975d949518
@@ -1,3 +1,5 @@
1
+ require 'rbczmq'
2
+
1
3
  module Softwear
2
4
  module Auth
3
5
  class StandardModel
@@ -170,8 +172,22 @@ module Softwear
170
172
  end
171
173
  end
172
174
 
175
+ def zmq
176
+ $zmq_context ||= ZMQ::Context.new
177
+ end
178
+
173
179
  def default_socket
174
- @default_socket ||= TCPSocket.open(auth_server_host, auth_server_port)
180
+ if existing = Thread.current[:auth_socket]
181
+ return existing
182
+ end
183
+
184
+ Thread.current[:auth_socket] = zmq.connect(
185
+ :REQ, "tcp://#{auth_server_host}:#{auth_server_port}"
186
+ )
187
+ end
188
+
189
+ def destroy_default_socket!
190
+ Thread.current[:auth_socket].try(:destroy) rescue nil
175
191
  end
176
192
 
177
193
  # ====================
@@ -180,18 +196,12 @@ module Softwear
180
196
  # ====================
181
197
  def raw_query(message)
182
198
  begin
183
- default_socket.puts message
184
- default_socket.flush
185
-
186
- rescue Errno::EPIPE => e
187
- @default_socket = TCPSocket.open(auth_server_host, auth_server_port)
188
- @default_socket.puts message
199
+ default_socket.send message
189
200
  end
190
201
 
191
- response = default_socket.gets.try(:chomp)
202
+ response = default_socket.recv.try(:chomp)
192
203
  if response.nil?
193
- @default_socket.close rescue nil
194
- @default_socket = nil
204
+ destroy_default_socket!
195
205
  return raw_query(message)
196
206
  end
197
207
  response
@@ -0,0 +1,121 @@
1
+ require 'rbczmq'
2
+
3
+ def split(string, limit = nil)
4
+ string.split(/\s+/, limit)
5
+ end
6
+
7
+ def report_error(rep, whole_command, error)
8
+ $stderr.puts "=== ERROR WHILE PROCESSING THE COMMAND \"#{whole_command}\" ===\n"\
9
+ "#{error.class.name}: #{error.message}\n#{error.backtrace.join("\n")}"
10
+
11
+ begin
12
+ rep.send "sorry" if rep
13
+ rescue StandardError => e
14
+ $stderr.puts "(could not send 'sorry' message: \"#{e.class} #{e.message}\")"
15
+ end
16
+ end
17
+
18
+ def dev_log(*a)
19
+ $stdout.puts(*a) #if Rails.env.development?
20
+ end
21
+
22
+ def log(*a)
23
+ $stdout.puts(*a) #unless Rails.env.test?
24
+ end
25
+
26
+ # ==== Send Format: =======
27
+ # One line strings: "#{command} #{arg1} #{arg2} #{etc}"
28
+ # The last argument, depending on the command, may contain spaces (but usually does not need to)
29
+ # =========================
30
+ # === Receive Format: =====
31
+ # Usually one string, like "yes", or "no".
32
+ # Returns "denied" if an unauthorized command was attempted.
33
+ # Returns "invalid" if an invalid command was attempted.
34
+ # Returns "sorry" if an error was raised while processing the command.
35
+ # Can be a json argument, often following "yes ".
36
+ # =========================
37
+ def start_server!(*args)
38
+ log "Connecting...!"
39
+
40
+ if args.size > 1
41
+ port = args.first
42
+ else
43
+ port = ENV['port'] || ENV['PORT'] || 2900
44
+ end
45
+ address = ENV['SOCKET_ADDR'] || "tcp://*"
46
+
47
+ if address =~ /:$/
48
+ socket_address = address
49
+ else
50
+ socket_address = "#{address}:#{port}"
51
+ end
52
+
53
+ ctx = ZMQ::Context.new
54
+ rep = ctx.bind(:REP, socket_address)
55
+
56
+ log "Ready! Using \"#{ActiveRecord::Base.connection.current_database}\" database"
57
+
58
+ commands = args.last
59
+
60
+ loop do
61
+ begin
62
+ loop do
63
+ line_in = rep.recv
64
+ raise "Got nil response (ZMQ REP/REQ out of sync?)" if line_in.nil?
65
+ command, rest_of_command = split(line_in, 2)
66
+
67
+ before = Time.now
68
+ begin
69
+ command = commands[command.downcase.to_sym]
70
+
71
+ if command.nil?
72
+ log "Received invalid command: \"#{line_in}\""
73
+ else
74
+ dev_log "<== #{line_in}"
75
+ ActiveRecord::Base.connection_pool.with_connection do
76
+
77
+ # The ZMQ socket requires that a reply be send after every
78
+ # message -- so we pass a lambda for the client code to
79
+ # call to send a message and make sure it only happens
80
+ # once.
81
+ replied = false
82
+ reply = lambda do |msg|
83
+ if replied
84
+ raise "Reply sent twice"
85
+ else
86
+ rep.send(msg)
87
+ replied = true
88
+ end
89
+ end
90
+ command.call(reply, rest_of_command)
91
+
92
+ if !replied
93
+ rep.send "noreply"
94
+ end
95
+
96
+ end
97
+ end
98
+
99
+ rescue StandardError => e
100
+ report_error(rep, line_in, e)
101
+ rescue Exception => e
102
+ report_error(rep, line_in, e)
103
+ break
104
+ end
105
+ after = Time.now
106
+
107
+ ms = (after - before) * 1000
108
+ dev_log %[(#{'%.2f' % ms}ms)]
109
+ dev_log ""
110
+ end
111
+
112
+ rescue StandardError => error
113
+ $stderr.puts "=== ERROR -- RESTARTING SERVER ===\n"\
114
+ "#{error.class.name}: #{error.message}\n#{error.backtrace.join("\n")}"
115
+
116
+ rep.destroy
117
+ log "Reconnecting...!"
118
+ rep = ctx.bind(:REP, socket_address)
119
+ end
120
+ end
121
+ end
@@ -1,5 +1,5 @@
1
1
  module Softwear
2
2
  module Library
3
- VERSION = "2.1.7"
3
+ VERSION = "3.0.0"
4
4
  end
5
5
  end
data/softwear-lib.gemspec CHANGED
@@ -23,4 +23,5 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "rspec", "~> 3.2.0"
24
24
 
25
25
  spec.add_dependency "activesupport", "~> 4.2.1"
26
+ spec.add_dependency "rbczmq"
26
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: softwear-lib
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.7
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nigel Baillie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-20 00:00:00.000000000 Z
11
+ date: 2017-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 4.2.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: rbczmq
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  description:
70
84
  email:
71
85
  - nigel@annarbortees.com
@@ -113,8 +127,8 @@ files:
113
127
  - lib/softwear/library/capistrano.rb
114
128
  - lib/softwear/library/controller_authentication.rb
115
129
  - lib/softwear/library/enqueue.rb
130
+ - lib/softwear/library/light_server.rb
116
131
  - lib/softwear/library/spec.rb
117
- - lib/softwear/library/tcp_server.rb
118
132
  - lib/softwear/library/version.rb
119
133
  - softwear-lib.gemspec
120
134
  - spec/spec_helper.rb
@@ -1,112 +0,0 @@
1
- def split(string, limit = nil)
2
- string.split(/\s+/, limit)
3
- end
4
-
5
- def report_error(client, whole_command, error)
6
- $stderr.puts "=== ERROR WHILE PROCESSING THE COMMAND \"#{whole_command}\" ===\n"\
7
- "#{error.class.name}: #{error.message}\n#{error.backtrace.join("\n")}"
8
- client.puts "sorry"
9
- end
10
-
11
- def dev_log(*a)
12
- $stdout.puts(*a) if Rails.env.development?
13
- end
14
-
15
- def log(*a)
16
- $stdout.puts(*a) unless Rails.env.test?
17
- end
18
-
19
- # ==== Send Format: =======
20
- # One line strings: "#{command} #{arg1} #{arg2} #{etc}"
21
- # The last argument, depending on the command, may contain spaces (but usually does not need to)
22
- # =========================
23
- # === Receive Format: =====
24
- # Usually one string, like "yes", or "no".
25
- # Returns "denied" if an unauthorized command was attempted.
26
- # Returns "invalid" if an invalid command was attempted.
27
- # Returns "sorry" if an error was raised while processing the command.
28
- # Can be a json argument, often following "yes ".
29
- # =========================
30
- def address_of(socket)
31
- _family, port, name, host = socket.addr
32
- if host == name
33
- "#{host}:#{port}"
34
- else
35
- "#{name}(#{host}):#{port}"
36
- end
37
- end
38
-
39
- def start_server!(*args)
40
- log "Connecting...!"
41
-
42
- if args.size > 1
43
- port = args.first
44
- else
45
- port = ENV['port'] || ENV['PORT'] || 2900
46
- end
47
-
48
- server = TCPServer.new port
49
- log "Ready! Using \"#{ActiveRecord::Base.connection.current_database}\" database"
50
-
51
- client_count = 0
52
- commands = args.last
53
-
54
- loop do
55
- Thread.start(server.accept) do |client|
56
- begin
57
- client.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
58
- rescue Exception => e
59
- puts "Couldn't set TCP_NODELAY"
60
- end
61
-
62
- client_count += 1
63
- dev_log "New client! ##{client_count} #{address_of client}"
64
-
65
- if Rails.env.development?
66
- response_logger = Module.new do
67
- def puts(s)
68
- $stdout.puts "==> #{s}"
69
- super
70
- end
71
- end
72
- client.singleton_class.send :include, response_logger
73
- end
74
-
75
- while line_in = client.gets.chomp
76
- log "Processing \"#{line_in}\"" if Rails.env.test?
77
-
78
- command, rest_of_command = split(line_in, 2)
79
-
80
- before = Time.now
81
- begin
82
- command = commands[command.downcase.to_sym]
83
-
84
- if command.nil?
85
- log "SOMEONE attempted invalid command: \"#{line_in}\""
86
- else
87
- dev_log "<== #{line_in}"
88
- ActiveRecord::Base.connection_pool.with_connection do
89
- command.call(client, rest_of_command)
90
- client.flush
91
- end
92
- end
93
-
94
- rescue StandardError => e
95
- report_error(client, line_in, e)
96
- rescue Exception => e
97
- report_error(client, line_in, e)
98
- break
99
- end
100
- after = Time.now
101
-
102
- ms = (after - before) * 1000
103
- dev_log %((#{'%.2f' % ms}ms) from #{address_of(client)})
104
- dev_log ""
105
- end
106
-
107
- client_count -= 1
108
- client.close rescue nil
109
- dev_log "Client disconnected. #{address_of client}"
110
- end
111
- end
112
- end