softwear-lib 2.1.7 → 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 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