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 +4 -4
- data/lib/softwear/auth/standard_model.rb +20 -10
- data/lib/softwear/library/light_server.rb +121 -0
- data/lib/softwear/library/version.rb +1 -1
- data/softwear-lib.gemspec +1 -0
- metadata +17 -3
- data/lib/softwear/library/tcp_server.rb +0 -112
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 26254fb662076fc8e52a5f9bee3736d645699c65
|
4
|
+
data.tar.gz: 64b88c6e858c9000dd9806a8e83af67f8749faa8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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.
|
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.
|
202
|
+
response = default_socket.recv.try(:chomp)
|
192
203
|
if response.nil?
|
193
|
-
|
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
|
data/softwear-lib.gemspec
CHANGED
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:
|
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-
|
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
|