consolle 0.2.6 → 0.2.8
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/.version +1 -1
- data/Gemfile +2 -2
- data/Gemfile.lock +1 -1
- data/bin/cone +2 -2
- data/bin/consolle +2 -2
- data/consolle.gemspec +20 -20
- data/lib/consolle/adapters/rails_console.rb +82 -77
- data/lib/consolle/cli.rb +380 -255
- data/lib/consolle/server/console_socket_server.rb +79 -72
- data/lib/consolle/server/console_supervisor.rb +216 -176
- data/lib/consolle/server/request_broker.rb +96 -99
- data/lib/consolle/version.rb +2 -2
- data/lib/consolle.rb +6 -6
- metadata +3 -3
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require "logger"
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
require 'logger'
|
|
6
5
|
|
|
7
6
|
module Consolle
|
|
8
7
|
module Server
|
|
@@ -21,53 +20,53 @@ module Consolle
|
|
|
21
20
|
|
|
22
21
|
def start
|
|
23
22
|
return if @running
|
|
24
|
-
|
|
23
|
+
|
|
25
24
|
@running = true
|
|
26
25
|
@worker_thread = start_worker
|
|
27
|
-
logger.info
|
|
26
|
+
logger.info '[RequestBroker] Started'
|
|
28
27
|
end
|
|
29
28
|
|
|
30
29
|
def stop
|
|
31
30
|
return unless @running
|
|
32
|
-
|
|
31
|
+
|
|
33
32
|
@running = false
|
|
34
|
-
|
|
33
|
+
|
|
35
34
|
# Push poison pill to wake up worker
|
|
36
35
|
@queue.push(nil)
|
|
37
|
-
|
|
36
|
+
|
|
38
37
|
# Wait for worker to finish
|
|
39
38
|
@worker_thread&.join(5)
|
|
40
|
-
|
|
41
|
-
logger.info
|
|
39
|
+
|
|
40
|
+
logger.info '[RequestBroker] Stopped'
|
|
42
41
|
end
|
|
43
42
|
|
|
44
43
|
def process_request(request)
|
|
45
|
-
request_id = request[
|
|
46
|
-
|
|
44
|
+
request_id = request['request_id'] || SecureRandom.uuid
|
|
45
|
+
|
|
47
46
|
# Create future for response
|
|
48
47
|
future = RequestFuture.new
|
|
49
|
-
|
|
48
|
+
|
|
50
49
|
# Store in map
|
|
51
50
|
@mutex.synchronize do
|
|
52
51
|
@request_map[request_id] = future
|
|
53
52
|
end
|
|
54
|
-
|
|
53
|
+
|
|
55
54
|
# Queue request
|
|
56
55
|
@queue.push({
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
id: request_id,
|
|
57
|
+
request: request,
|
|
58
|
+
timestamp: Time.now
|
|
59
|
+
})
|
|
60
|
+
|
|
62
61
|
# Wait for response (with timeout)
|
|
63
62
|
begin
|
|
64
|
-
future.get(timeout: request[
|
|
63
|
+
future.get(timeout: request['timeout'] || 30)
|
|
65
64
|
rescue Timeout::Error
|
|
66
65
|
{
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
'success' => false,
|
|
67
|
+
'error' => 'RequestTimeout',
|
|
68
|
+
'message' => 'Request timed out',
|
|
69
|
+
'request_id' => request_id
|
|
71
70
|
}
|
|
72
71
|
ensure
|
|
73
72
|
# Clean up
|
|
@@ -81,17 +80,17 @@ module Consolle
|
|
|
81
80
|
|
|
82
81
|
def start_worker
|
|
83
82
|
Thread.new do
|
|
84
|
-
logger.info
|
|
85
|
-
|
|
83
|
+
logger.info '[RequestBroker] Worker thread started'
|
|
84
|
+
|
|
86
85
|
while @running
|
|
87
86
|
begin
|
|
88
87
|
# Get next request
|
|
89
88
|
item = @queue.pop
|
|
90
|
-
|
|
89
|
+
|
|
91
90
|
# Check for poison pill
|
|
92
91
|
break if item.nil? && !@running
|
|
93
92
|
next if item.nil?
|
|
94
|
-
|
|
93
|
+
|
|
95
94
|
# Process request
|
|
96
95
|
process_item(item)
|
|
97
96
|
rescue StandardError => e
|
|
@@ -99,120 +98,118 @@ module Consolle
|
|
|
99
98
|
logger.error e.backtrace.join("\n")
|
|
100
99
|
end
|
|
101
100
|
end
|
|
102
|
-
|
|
103
|
-
logger.info
|
|
101
|
+
|
|
102
|
+
logger.info '[RequestBroker] Worker thread stopped'
|
|
104
103
|
end
|
|
105
104
|
end
|
|
106
105
|
|
|
107
106
|
def process_item(item)
|
|
108
107
|
request_id = item[:id]
|
|
109
108
|
request = item[:request]
|
|
110
|
-
|
|
109
|
+
|
|
111
110
|
logger.debug "[RequestBroker] Processing request: #{request_id}"
|
|
112
|
-
|
|
111
|
+
|
|
113
112
|
# Get future
|
|
114
113
|
future = @mutex.synchronize { @request_map[request_id] }
|
|
115
114
|
return unless future
|
|
116
|
-
|
|
115
|
+
|
|
117
116
|
# Process based on request type
|
|
118
|
-
response = case request[
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
117
|
+
response = case request['action']
|
|
118
|
+
when 'eval', 'exec'
|
|
119
|
+
process_eval_request(request)
|
|
120
|
+
when 'status'
|
|
121
|
+
process_status_request
|
|
122
|
+
when 'restart'
|
|
123
|
+
process_restart_request
|
|
124
|
+
else
|
|
125
|
+
{
|
|
126
|
+
'success' => false,
|
|
127
|
+
'error' => 'UnknownAction',
|
|
128
|
+
'message' => "Unknown action: #{request['action']}"
|
|
129
|
+
}
|
|
130
|
+
end
|
|
131
|
+
|
|
133
132
|
# Add request_id to response
|
|
134
|
-
response[
|
|
135
|
-
|
|
133
|
+
response['request_id'] = request_id
|
|
134
|
+
|
|
136
135
|
# Set future result
|
|
137
136
|
future.set(response)
|
|
138
|
-
|
|
137
|
+
|
|
139
138
|
logger.debug "[RequestBroker] Request completed: #{request_id}"
|
|
140
139
|
rescue StandardError => e
|
|
141
140
|
logger.error "[RequestBroker] Error processing request #{request_id}: #{e.message}"
|
|
142
|
-
|
|
141
|
+
|
|
143
142
|
error_response = {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
143
|
+
'success' => false,
|
|
144
|
+
'error' => e.class.name,
|
|
145
|
+
'message' => e.message,
|
|
146
|
+
'request_id' => request_id
|
|
148
147
|
}
|
|
149
|
-
|
|
148
|
+
|
|
150
149
|
future&.set(error_response)
|
|
151
150
|
end
|
|
152
151
|
|
|
153
152
|
def process_eval_request(request)
|
|
154
|
-
code = request[
|
|
155
|
-
timeout = request[
|
|
156
|
-
|
|
153
|
+
code = request['code']
|
|
154
|
+
timeout = request['timeout'] || 30
|
|
155
|
+
|
|
157
156
|
unless code
|
|
158
157
|
return {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
158
|
+
'success' => false,
|
|
159
|
+
'error' => 'MissingParameter',
|
|
160
|
+
'message' => 'Missing required parameter: code'
|
|
162
161
|
}
|
|
163
162
|
end
|
|
164
|
-
|
|
163
|
+
|
|
165
164
|
# Execute through supervisor
|
|
166
165
|
result = @supervisor.eval(code, timeout: timeout)
|
|
167
|
-
|
|
166
|
+
|
|
168
167
|
# Format response
|
|
169
168
|
if result[:success]
|
|
170
169
|
{
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
170
|
+
'success' => true,
|
|
171
|
+
'result' => result[:output],
|
|
172
|
+
'execution_time' => result[:execution_time]
|
|
174
173
|
}
|
|
175
174
|
else
|
|
176
175
|
{
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
176
|
+
'success' => false,
|
|
177
|
+
'error' => 'ExecutionError',
|
|
178
|
+
'message' => result[:output]
|
|
180
179
|
}
|
|
181
180
|
end
|
|
182
181
|
end
|
|
183
182
|
|
|
184
183
|
def process_status_request
|
|
185
184
|
{
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
185
|
+
'success' => true,
|
|
186
|
+
'running' => @supervisor.running?,
|
|
187
|
+
'pid' => @supervisor.pid,
|
|
188
|
+
'rails_root' => @supervisor.rails_root,
|
|
189
|
+
'rails_env' => @supervisor.rails_env
|
|
191
190
|
}
|
|
192
191
|
end
|
|
193
192
|
|
|
194
193
|
def process_restart_request
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
end
|
|
194
|
+
# Restart the Rails console subprocess
|
|
195
|
+
new_pid = @supervisor.restart
|
|
196
|
+
|
|
197
|
+
{
|
|
198
|
+
'success' => true,
|
|
199
|
+
'message' => 'Rails console subprocess restarted',
|
|
200
|
+
'pid' => new_pid,
|
|
201
|
+
'rails_root' => @supervisor.rails_root,
|
|
202
|
+
'rails_env' => @supervisor.rails_env
|
|
203
|
+
}
|
|
204
|
+
rescue StandardError => e
|
|
205
|
+
logger.error "[RequestBroker] Restart failed: #{e.message}"
|
|
206
|
+
logger.error e.backtrace.join("\n")
|
|
207
|
+
|
|
208
|
+
{
|
|
209
|
+
'success' => false,
|
|
210
|
+
'error' => 'RestartFailed',
|
|
211
|
+
'message' => "Failed to restart Rails console: #{e.message}"
|
|
212
|
+
}
|
|
216
213
|
end
|
|
217
214
|
|
|
218
215
|
# Simple future implementation
|
|
@@ -236,7 +233,7 @@ module Consolle
|
|
|
236
233
|
@mutex.synchronize do
|
|
237
234
|
unless @set
|
|
238
235
|
@condition.wait(@mutex, timeout)
|
|
239
|
-
raise Timeout::Error,
|
|
236
|
+
raise Timeout::Error, 'Future timed out' unless @set
|
|
240
237
|
end
|
|
241
238
|
@value
|
|
242
239
|
end
|
|
@@ -244,4 +241,4 @@ module Consolle
|
|
|
244
241
|
end
|
|
245
242
|
end
|
|
246
243
|
end
|
|
247
|
-
end
|
|
244
|
+
end
|
data/lib/consolle/version.rb
CHANGED
data/lib/consolle.rb
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
4
|
-
require_relative
|
|
3
|
+
require_relative 'consolle/version'
|
|
4
|
+
require_relative 'consolle/cli'
|
|
5
5
|
|
|
6
6
|
# Server components
|
|
7
|
-
require_relative
|
|
8
|
-
require_relative
|
|
9
|
-
require_relative
|
|
7
|
+
require_relative 'consolle/server/console_socket_server'
|
|
8
|
+
require_relative 'consolle/server/console_supervisor'
|
|
9
|
+
require_relative 'consolle/server/request_broker'
|
|
10
10
|
|
|
11
11
|
module Consolle
|
|
12
12
|
class Error < StandardError; end
|
|
13
|
-
end
|
|
13
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: consolle
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- nacyot
|
|
@@ -10,7 +10,7 @@ cert_chain: []
|
|
|
10
10
|
date: 2025-07-24 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
|
-
name:
|
|
13
|
+
name: logger
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
16
|
- - "~>"
|
|
@@ -24,7 +24,7 @@ dependencies:
|
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '1.0'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
|
-
name:
|
|
27
|
+
name: thor
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
30
|
- - "~>"
|