rider-server 0.1.1 → 0.1.2

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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.build.yml +3 -3
  3. data/CHANGELOG.md +17 -1
  4. data/README.rdoc +39 -0
  5. data/Rakefile +5 -0
  6. data/exe/rider-server +3 -3
  7. data/lib/rider_server/config.rb +76 -0
  8. data/lib/rider_server/core_ext/array.rb +3 -1
  9. data/lib/rider_server/core_ext/class.rb +5 -0
  10. data/lib/rider_server/core_ext/env.rb +14 -0
  11. data/lib/rider_server/core_ext/hash.rb +3 -1
  12. data/lib/rider_server/core_ext/kernel.rb +5 -0
  13. data/lib/rider_server/core_ext/module.rb +18 -0
  14. data/lib/rider_server/core_ext/object.rb +7 -1
  15. data/lib/rider_server/core_ext/string.rb +3 -1
  16. data/lib/rider_server/core_ext/symbol.rb +3 -1
  17. data/lib/rider_server/exception_extension.rb +2 -0
  18. data/lib/rider_server/inspect.rb +108 -32
  19. data/lib/rider_server/logger.rb +11 -4
  20. data/lib/rider_server/operation.rb +39 -20
  21. data/lib/rider_server/{ops → operations}/clone.rb +3 -2
  22. data/lib/rider_server/{ops → operations}/close.rb +3 -2
  23. data/lib/rider_server/operations/completions.rb +146 -0
  24. data/lib/rider_server/operations/lookup.rb +102 -0
  25. data/lib/rider_server/operations/ls_sessions.rb +51 -0
  26. data/lib/rider_server/operations/toggle_catch_all_exceptions.rb +24 -0
  27. data/lib/rider_server/operations.rb +42 -68
  28. data/lib/rider_server/request.rb +61 -0
  29. data/lib/rider_server/response.rb +10 -2
  30. data/lib/rider_server/server.rb +28 -16
  31. data/lib/rider_server/services/capture_exceptions.rb +1 -1
  32. data/lib/rider_server/services/rails.rb +1 -1
  33. data/lib/rider_server/session.rb +75 -44
  34. data/lib/rider_server/session_operation.rb +17 -0
  35. data/lib/rider_server/session_operations/eval.rb +61 -0
  36. data/lib/rider_server/session_operations/inspect.rb +123 -0
  37. data/lib/rider_server/session_operations/inspect_exception.rb +46 -0
  38. data/lib/rider_server/session_operations/interrupt.rb +29 -0
  39. data/lib/rider_server/session_operations/load_path.rb +19 -0
  40. data/lib/rider_server/session_operations/ls_exceptions.rb +28 -0
  41. data/lib/rider_server/session_operations/ls_services.rb +18 -0
  42. data/lib/rider_server/session_operations/service.rb +42 -0
  43. data/lib/rider_server/session_operations/set_namespace.rb +82 -0
  44. data/lib/rider_server/session_operations/set_namespace_variable.rb +81 -0
  45. data/lib/rider_server/session_operations/stdin.rb +19 -0
  46. data/lib/rider_server/utils.rb +7 -7
  47. data/lib/rider_server/validate/array.rb +32 -0
  48. data/lib/rider_server/validate/base.rb +28 -0
  49. data/lib/rider_server/validate/boolean.rb +47 -0
  50. data/lib/rider_server/validate/hash.rb +32 -0
  51. data/lib/rider_server/validate/integer.rb +56 -0
  52. data/lib/rider_server/validate/predicates.rb +30 -0
  53. data/lib/rider_server/validate/string.rb +60 -0
  54. data/lib/rider_server/validate/symbol.rb +90 -0
  55. data/lib/rider_server/validate.rb +15 -0
  56. data/lib/rider_server/version.rb +1 -1
  57. data/lib/rider_server/workspace.rb +1 -1
  58. data/lib/rider_server.rb +3 -1
  59. metadata +54 -24
  60. data/README.md +0 -46
  61. data/lib/rider_server/ops/completions.rb +0 -145
  62. data/lib/rider_server/ops/eval.rb +0 -62
  63. data/lib/rider_server/ops/inspect.rb +0 -121
  64. data/lib/rider_server/ops/inspect_exception.rb +0 -47
  65. data/lib/rider_server/ops/interrupt.rb +0 -30
  66. data/lib/rider_server/ops/load_path.rb +0 -20
  67. data/lib/rider_server/ops/lookup.rb +0 -104
  68. data/lib/rider_server/ops/ls_exceptions.rb +0 -29
  69. data/lib/rider_server/ops/ls_services.rb +0 -19
  70. data/lib/rider_server/ops/ls_sessions.rb +0 -52
  71. data/lib/rider_server/ops/service.rb +0 -43
  72. data/lib/rider_server/ops/set_namespace.rb +0 -79
  73. data/lib/rider_server/ops/set_namespace_variable.rb +0 -80
  74. data/lib/rider_server/ops/stdin.rb +0 -20
  75. data/lib/rider_server/ops/toggle_catch_all_exceptions.rb +0 -27
@@ -3,14 +3,15 @@ require "rider_server/response"
3
3
 
4
4
  module RiderServer
5
5
  module Ops
6
- class Close < Operation
6
+ Close = Operation.define do
7
+ name "close"
7
8
  documentation "Close a specific session."
8
9
 
9
10
  argument :id, :string, "The request id", required: true
10
11
  argument :session, :string, "The session to close", required: true
11
12
 
12
13
  # Handle the close operation, session will be nil
13
- def handle(session, operation)
14
+ def handle(controller, operation)
14
15
  response = Response.new(operation)
15
16
 
16
17
  session_id = operation["session"]
@@ -0,0 +1,146 @@
1
+ require "rider_server/operation"
2
+ require "rider_server/response"
3
+ require "rider_server/inspect"
4
+ require "rider_server/workspace"
5
+
6
+ module RiderServer
7
+ Operation.define do
8
+ name "completions"
9
+ documentation "Get completions for a given prefix"
10
+
11
+ argument :id, :string, "The request id", required: true
12
+ argument :prefix, :string, "The prefix to complete", required: true
13
+ argument :complete_fn, :string, "What completion function to use, top-level, module, method or singleton-method"
14
+ argument :ns, :string, "The namespace to search for completions"
15
+
16
+ @workspace = Workspace.new
17
+
18
+ def handle(controller, operation)
19
+ response = Response.new(operation)
20
+
21
+ prefix = operation["prefix"]
22
+ ns = operation["ns"]
23
+ complete_fn = operation.fetch("complete-fn", "top-level")
24
+
25
+ if prefix.nil? || parse_string(prefix).nil?
26
+ response.set("completions", [])
27
+ else
28
+ ns_object = if ns.empty?
29
+ ::Object
30
+ else
31
+ @workspace.lookup_module(ns)
32
+ end
33
+
34
+ # If the prefix isn't parseable, return an empty list
35
+ response.set("completions", lookup_module(prefix, klass: ns_object, completion_fn: complete_fn))
36
+ end
37
+ response.status("done")
38
+ response
39
+ end
40
+
41
+ def lookup_module(module_name, klass: ::Object, completion_fn: "top-level")
42
+ node = parse_string(module_name)
43
+ case node.type
44
+ when :const
45
+ ns = lookup_module_ast(node.children.first, klass)
46
+ prefix = node.children.last
47
+ all_constants(ns, prefix)
48
+ when :send
49
+ ns = lookup_module_ast(node.children.first, klass)
50
+ prefix = node.children.last
51
+ if completion_fn == "method"
52
+ all_constants(ns, prefix) + encode_methods(class_instance_methods(ns, prefix) + class_singleton_methods(::Kernel, prefix))
53
+ else
54
+ all_constants(ns, prefix) + encode_methods(class_methods(ns, prefix) + class_singleton_methods(::Kernel, prefix))
55
+ end
56
+ else
57
+ []
58
+ end
59
+ end
60
+
61
+ def parse_string(string)
62
+ buffer = Parser::Source::Buffer.new("(string)")
63
+ buffer.source = string
64
+ Parser::CurrentRuby.new.parse(buffer)
65
+ end
66
+
67
+ def lookup_module_ast(node, klass = ::Object)
68
+ return klass if node.nil?
69
+
70
+ case node.type
71
+ when :cbase
72
+ ::Object
73
+ when :const
74
+ if node.children.first.nil?
75
+ klass.const_get(node.children.last)
76
+ else
77
+ lookup_module_ast(node.children.first, klass).const_get(node.children.last)
78
+ end
79
+ else
80
+ raise ModuleLookupError, "Unknown node type #{node.type}"
81
+ end
82
+ end
83
+
84
+ def parent_constant(ns_object)
85
+ ns_object_name = ns_object.to_s
86
+ parent_name, _ = ns_object_name.rpartition("::")
87
+ parent_name.empty? ? nil : ::Object.const_get(parent_name)
88
+ end
89
+
90
+ def all_constants(ns_object, prefix)
91
+ consts = []
92
+ ns_object.constants.grep(/^#{prefix}/).each do |constant|
93
+ consts << constant.to_s
94
+ end
95
+
96
+ # Search up the tree to find all the other constants
97
+ constant = ns_object
98
+ loop do
99
+ constant = parent_constant(constant)
100
+ break if constant.nil?
101
+
102
+ constant.constants.grep(/^#{prefix}/).each do |constant|
103
+ consts << constant.to_s
104
+ end
105
+ end
106
+
107
+ ::Object.constants.grep(/^#{prefix}/).each do |constant|
108
+ consts << constant.to_s
109
+ end
110
+
111
+ consts.map do |constant|
112
+ {
113
+ "candidate" => constant,
114
+ "type" => "constant"
115
+ }
116
+ end
117
+ end
118
+
119
+ ##
120
+ # Get all instance methods that match a +prefix+ for a given object +obj+
121
+ #
122
+ # This method should be called when in the context of an
123
+ # instance method, as all other instance methods will be
124
+ # acessable.
125
+ def class_instance_methods(obj, prefix)
126
+ Set.new(obj.instance_methods.grep(/^#{prefix}/))
127
+ end
128
+
129
+ def class_methods(obj, prefix)
130
+ Set.new(obj.methods.grep(/^#{prefix}/))
131
+ end
132
+
133
+ def class_singleton_methods(obj, prefix)
134
+ Set.new(obj.singleton_methods.grep(/^#{prefix}/))
135
+ end
136
+
137
+ def encode_methods(methods)
138
+ methods.map do |method|
139
+ {
140
+ "candidate" => method.to_s,
141
+ "type" => "method"
142
+ }
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,102 @@
1
+ require "rider_server/operation"
2
+ require "rider_server/response"
3
+ require "rider_server/inspect"
4
+
5
+ module RiderServer
6
+ Operation.define do
7
+ name "lookup"
8
+ documentation "Get info about a symbol."
9
+
10
+ argument :id, :string, "The request id", required: true
11
+ argument :sym, :string, "The symbol to lookup", required: true
12
+ argument :lookup_fn, :string, "What lookup function to use, top-level, module, method or singleton-method"
13
+ argument :ns, :string, "The namespace to search for completions"
14
+
15
+ def handle(controller, operation)
16
+ response = Response.new(operation)
17
+ ns = operation["ns"]
18
+ sym = operation["sym"]
19
+ lookup_fn = operation.fetch("lookup-fn", "top-level")
20
+
21
+ if sym.nil? || parse_string(sym).nil?
22
+ response.set("info", {})
23
+ else
24
+ ns_object = if ns.empty?
25
+ ::Object
26
+ else
27
+ workspace.lookup_module(ns)
28
+ end
29
+
30
+ # If the prefix isn't parseable, return an empty list
31
+ response.set("info", lookup_module(sym, klass: ns_object, lookup_fn: lookup_fn))
32
+ end
33
+ response.status("done")
34
+ response
35
+ end
36
+
37
+ def lookup_module(module_name, klass: ::Object, lookup_fn: "top-level")
38
+ node = parse_string(module_name)
39
+ case node.type
40
+ when :const
41
+ ns = lookup_module_ast(node.children.first, klass)
42
+ name node.children.last
43
+ encode_const(ns, name)
44
+ when :send
45
+ ns = lookup_module_ast(node.children.first, klass)
46
+ prefix = node.children.last
47
+ if lookup_fn == "method"
48
+ encode_method(ns.instance_method(prefix))
49
+ else
50
+ encode_method(ns.method(prefix))
51
+ end
52
+ else
53
+ []
54
+ end
55
+ end
56
+
57
+ def parse_string(string)
58
+ buffer = Parser::Source::Buffer.new("(string)")
59
+ buffer.source = string
60
+ Parser::CurrentRuby.new.parse(buffer)
61
+ end
62
+
63
+ def lookup_module_ast(node, klass = ::Object)
64
+ return klass if node.nil?
65
+
66
+ case node.type
67
+ when :cbase
68
+ ::Object
69
+ when :const
70
+ if node.children.first.nil?
71
+ klass.const_get(node.children.last)
72
+ else
73
+ lookup_module_ast(node.children.first, klass).const_get(node.children.last)
74
+ end
75
+ else
76
+ raise ModuleLookupError, "Unknown node type #{node.type}"
77
+ end
78
+ end
79
+
80
+ def encode_const(ns, const_name)
81
+ if ns.const_defined? const_name
82
+ {
83
+ "name" => "#{ns}::#{const_name}",
84
+ "source_location" => ns.const_source_location(const_name)
85
+ }
86
+ else
87
+ {}
88
+ end
89
+ end
90
+
91
+ def encode_method(thing)
92
+ {
93
+ "name" => thing.name.to_s,
94
+ "source_location" => thing.source_location
95
+ }
96
+ end
97
+
98
+ def workspace
99
+ @workspace ||= Workspace.new
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,51 @@
1
+ require "rider_server/operation"
2
+ require "rider_server/response"
3
+
4
+ module RiderServer
5
+ Operation.define do
6
+ name "ls-sessions"
7
+ documentation "List all sessions"
8
+
9
+ argument :id, :string, "The request id", required: true
10
+
11
+ def handle(controller, operation)
12
+ response = Response.new(operation)
13
+ response.set("sessions", controller.sessions.map { |k, v| k })
14
+ response.set("rider/session-headings",
15
+ [
16
+ {
17
+ "id" => "id",
18
+ "name" => "ID",
19
+ "length" => 36
20
+ },
21
+ {
22
+ "id" => "namespace_name",
23
+ "name" => "Namespace",
24
+ "length" => 25
25
+ },
26
+ {
27
+ "id" => "history_items",
28
+ "name" => "History Items",
29
+ "length" => 5
30
+ },
31
+ {
32
+ "id" => "exceptions",
33
+ "name" => "Exceptions",
34
+ "length" => 5
35
+ }
36
+ ])
37
+ response.set("rider/sessions", controller.sessions.map { |k, v| session_summary(v) })
38
+ response.status("done")
39
+ response
40
+ end
41
+
42
+ def session_summary(session)
43
+ {
44
+ "id" => session.id,
45
+ "namespace_name" => session.workspace.namespace_name,
46
+ "history_items" => session.history.length.to_s,
47
+ "exceptions" => session.exceptions.length.to_s
48
+ }
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,24 @@
1
+ require "rider_server/operation"
2
+ require "rider_server/response"
3
+
4
+ module RiderServer
5
+ Operation.define do
6
+ name "toggle-catch-all-exceptions"
7
+ documentation "Enable catching all exceptions. Not just the ones with a session."
8
+
9
+ argument :id, :string, "The request id", required: true
10
+
11
+ def handle(controller, operation)
12
+ value = if controller.toggle_capture_exceptions
13
+ "enabled"
14
+ else
15
+ "disabled"
16
+ end
17
+
18
+ response = Response.new(operation)
19
+ response.status("done")
20
+ response.set("value", value)
21
+ response
22
+ end
23
+ end
24
+ end
@@ -12,112 +12,78 @@ require "rider_server/session"
12
12
  require "rider_server/errors"
13
13
  require "rider_server/response"
14
14
  require "rider_server/core_ext/array"
15
+ require "rider_server/core_ext/class"
16
+ require "rider_server/core_ext/env"
15
17
  require "rider_server/core_ext/hash"
18
+ require "rider_server/core_ext/kernel"
19
+ require "rider_server/core_ext/module"
16
20
  require "rider_server/core_ext/object"
17
21
  require "rider_server/core_ext/string"
18
22
  require "rider_server/core_ext/symbol"
19
- require "rider_server/ops/clone"
20
- require "rider_server/ops/close"
21
- require "rider_server/ops/completions"
22
- require "rider_server/ops/eval"
23
- require "rider_server/ops/inspect"
24
- require "rider_server/ops/inspect_exception"
25
- require "rider_server/ops/interrupt"
26
- require "rider_server/ops/load_path"
27
- require "rider_server/ops/lookup"
28
- require "rider_server/ops/ls_exceptions"
29
- require "rider_server/ops/ls_services"
30
- require "rider_server/ops/ls_sessions"
31
- require "rider_server/ops/service"
32
- require "rider_server/ops/set_namespace"
33
- require "rider_server/ops/set_namespace_variable"
34
- require "rider_server/ops/toggle_catch_all_exceptions"
23
+ require "rider_server/operations/clone"
24
+ require "rider_server/operations/close"
25
+ require "rider_server/operations/completions"
26
+ require "rider_server/operations/lookup"
27
+ require "rider_server/operations/ls_sessions"
28
+ require "rider_server/operations/toggle_catch_all_exceptions"
35
29
 
36
30
  module RiderServer
31
+ def self.create_operation_handler(config, response_queue)
32
+ Operations.new(config, response_queue)
33
+ end
34
+
37
35
  class Operations
38
36
  include RiderServer::Logger
39
37
 
40
- attr_reader :executing_requests
41
38
  attr_reader :sessions
42
- attr_reader :stdin, :stdout, :stderr
43
39
  attr_reader :response_queue
44
- attr_accessor :sessions_catching_exceptions
45
-
46
- OPERATIONS = [
47
- Ops::Clone,
48
- Ops::Close,
49
- Ops::Completions,
50
- Ops::Eval,
51
- Ops::Inspect,
52
- Ops::InspectException,
53
- Ops::Interrupt,
54
- Ops::LoadPath,
55
- Ops::Lookup,
56
- Ops::LsExceptions,
57
- Ops::LsServices,
58
- Ops::LsSessions,
59
- Ops::Service,
60
- Ops::SetNamespace,
61
- Ops::SetNamespaceVariable,
62
- Ops::ToggleCatchAllExceptions
63
- ]
64
40
 
65
- def initialize(response_queue)
41
+ def initialize(config, response_queue)
42
+ @config = config
66
43
  @sessions = {}
67
44
  @response_queue = response_queue
68
- @executing_requests = []
69
- @operations = OPERATIONS.each_with_object({}) do |klass, h|
70
- h[klass.operation_name] = klass.new(self)
71
- end
72
- @sessions_catching_exceptions = []
73
45
  end
74
46
 
75
47
  def send_response(response)
76
48
  if response
77
49
  @response_queue.push(response)
78
- if response.done?
79
- @executing_requests.delete(response.id)
80
- end
81
50
  end
82
51
  end
83
52
 
84
- def handle(operation)
85
- session = nil
86
-
87
- session_id = operation["session"]
88
- op = operation["op"].tr("-", "_")
89
- log.info("Handling operation '#{operation}'")
90
- session = get_session(session_id)
91
- @executing_requests << operation["id"]
92
- if @operations.key? op
93
- @operations[op].validate_request!(operation)
94
- send_response(@operations[op].handle(session, operation))
53
+ def handle(request)
54
+ op = request.op
55
+ log.info("Handling operation '#{request.inspect}'")
56
+ session = get_session(request.session)
57
+ if Operation.handles?(request)
58
+ send_response(Operation.handle(self, request))
59
+ elsif !session.nil? && SessionOperation.handles?(request)
60
+ send_response(SessionOperation.handle(session, request))
95
61
  else
96
62
  log.warn("Unknown operation '#{op}' requested")
97
- response = Response.new(operation)
63
+ response = Response.new(request)
98
64
  response.status "unknown-op", "done"
99
65
  send_response(response)
100
66
  end
101
67
  rescue ScriptError, StandardError => e
102
- response = Response.new(operation)
68
+ response = Response.new(request)
103
69
  response.set("ex", e.inspect)
104
70
  response.set("out", e.full_message)
105
71
  response.status("eval-error", "done")
72
+ log.error "Error handling request: #{e}\n #{e.backtrace.join("\n")}"
106
73
  if session
107
- exception = session.push_exception(operation["id"], e)
108
- response.set("rider/exception-id", exception["id"])
109
- end
110
- @sessions_catching_exceptions.each do |session_id|
111
- session = @sessions[session_id]
112
- next if session.nil?
113
- exception = session.push_exception(operation["id"], e)
74
+ exception = session.add_exception(request.id, e)
114
75
  response.set("rider/exception-id", exception["id"])
115
76
  end
77
+ RiderServer::Services::CaptureExceptions.handle_exception(e)
116
78
  send_response(response)
117
79
  end
118
80
 
81
+ #
82
+ # Sessions
83
+ #
84
+
119
85
  def new_session
120
- Session.new(@response_queue)
86
+ RiderServer.create_session(@config, @response_queue)
121
87
  end
122
88
 
123
89
  def get_session(id)
@@ -132,5 +98,13 @@ module RiderServer
132
98
  def delete_session(session_id)
133
99
  @sessions.delete(session_id)
134
100
  end
101
+
102
+ #
103
+ # Exceptions
104
+ #
105
+
106
+ def toggle_capture_exceptions
107
+ @config.capture_exceptions(!@config.capture_exceptions)
108
+ end
135
109
  end
136
110
  end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # request.rb -- A simple wrapper around a request
5
+ #
6
+ # Author: Russell Sim
7
+ # Copyright (c) 2024 Russell Sim
8
+ # SPDX-License-Identifier: MIT
9
+
10
+ require "bencode"
11
+
12
+ module RiderServer
13
+ class Request
14
+ def initialize(operation)
15
+ raise "Operation ID cannot be nil" if operation["id"].nil?
16
+ raise "Operation name cannot be nil" if operation["op"].nil?
17
+
18
+ @data = operation
19
+ end
20
+
21
+ def op
22
+ @data["op"]
23
+ end
24
+
25
+ def id
26
+ @data["id"]
27
+ end
28
+
29
+ def session
30
+ @data["session"]
31
+ end
32
+
33
+ def set(key, value)
34
+ @data[key] = value
35
+ end
36
+
37
+ def fetch(*args)
38
+ @data.fetch(*args)
39
+ end
40
+
41
+ def key?(name)
42
+ @data.key? name
43
+ end
44
+
45
+ def [](name)
46
+ @data[name]
47
+ end
48
+
49
+ def []=(name, value)
50
+ @data[name] = value
51
+ end
52
+
53
+ def inspect
54
+ "#<RiderServer::Request:#{object_id} id=#{id} session=#{session} op=#{op}}>"
55
+ end
56
+
57
+ def to_h
58
+ @data
59
+ end
60
+ end
61
+ end
@@ -42,8 +42,16 @@ module RiderServer
42
42
  @data.fetch(*args)
43
43
  end
44
44
 
45
- def [](item)
46
- @data[item]
45
+ def key?(name)
46
+ @data.key? name
47
+ end
48
+
49
+ def [](name)
50
+ @data[name]
51
+ end
52
+
53
+ def []=(name, value)
54
+ @data[name] = value
47
55
  end
48
56
 
49
57
  def status(*value)
@@ -9,6 +9,7 @@
9
9
 
10
10
  require "rider_server/exception_extension"
11
11
  require "rider_server/operations"
12
+ require "rider_server/request"
12
13
  require "rider_server/utils"
13
14
  require "rider_server/logger"
14
15
  require "bencode"
@@ -17,30 +18,28 @@ module RiderServer
17
18
  class Server
18
19
  include RiderServer::Logger
19
20
 
21
+ # The status of the server, either +:running+ or +:stopped+
20
22
  attr_reader :status
21
- attr_reader :listeners
22
23
 
23
- def initialize
24
+ def initialize(config)
25
+ @config = config
24
26
  @status = :stopped
25
- @shutdown_pipe = nil
26
- end
27
27
 
28
- def listen(address, port)
29
- Utils.create_listeners(address, port)
30
- end
31
-
32
- def setup_shutdown_pipe
33
- @shutdown_pipe ||= IO.pipe
28
+ RiderServer::Logger.configure_logger(level: @config.log_level)
34
29
  end
35
30
 
31
+ # Start the servers main event loop. This will bind to the
32
+ # configured host and port, and create threads for sending and
33
+ # recieving requests.
36
34
  def run
37
- socket = listen("127.0.0.1", 7888)
35
+ socket = listen(@config.host, @config.port)
38
36
  request_count = 0
39
37
 
40
38
  responses = Thread::Queue.new
41
- operations = Operations.new(responses)
39
+ operations = RiderServer.create_operation_handler(@config, responses)
42
40
 
43
41
  loop do
42
+ @status = :running
44
43
  client = socket[0].accept
45
44
 
46
45
  request_count += 1
@@ -58,7 +57,7 @@ module RiderServer
58
57
  begin
59
58
  output = response.bencode
60
59
  rescue => e
61
- log.error "Error encoding response: #{e}"
60
+ log.error "Error encoding response: #{e}\n #{e.backtrace.join("\n")}"
62
61
  response = Response.new(response.to_h)
63
62
  response.set("ex", e.inspect)
64
63
  response.set("out", e.full_message)
@@ -67,9 +66,9 @@ module RiderServer
67
66
  end
68
67
 
69
68
  if log.debug?
70
- log.debug "sending response #{response.to_h}"
69
+ log.debug "Sending response #{response.to_h}"
71
70
  else
72
- log.info "sending response #{response.inspect}"
71
+ log.info "Sending response #{response.inspect}"
73
72
  end
74
73
  client.write(output)
75
74
  # Try to allow time for the client to read the response
@@ -92,13 +91,26 @@ module RiderServer
92
91
  operation = parser.parse!
93
92
 
94
93
  log.debug(operation.inspect)
95
- operations.handle(operation)
94
+
95
+ begin
96
+ operations.handle(::RiderServer::Request.new(operation))
97
+ rescue => e
98
+ log.error "Error handling request: #{e}\n #{e.backtrace}"
99
+ end
96
100
  end
97
101
  }
98
102
  threads.each { |thr| thr.join }
99
103
 
100
104
  client.close
105
+ @status = :stopped
101
106
  end
102
107
  end
108
+
109
+ private
110
+
111
+ # Open a TCP server listening on an +address+ and +port+.
112
+ def listen(address, port)
113
+ Utils.create_listeners(address, port)
114
+ end
103
115
  end
104
116
  end
@@ -44,7 +44,7 @@ module RiderServer
44
44
  # This needs to use push exception
45
45
 
46
46
  @sessions.each do |session, stream_id|
47
- ex = session.push_anonymous_exception(wrapped_ex)
47
+ ex = session.add_wrapped_exception(wrapped_ex)
48
48
  session.response_queue.push(create_response(stream_id, ex))
49
49
  end
50
50