Class: LazyGraph::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/lazy_graph/server.rb

Constant Summary collapse

ALLOWED_VALUES_VALIDATE =
[true, false, nil, 'input', 'context'].to_set.freeze
ALLOWED_VALUES_DEBUG =
[true, false, nil].to_set.freeze

Instance Method Summary collapse

Constructor Details

#initialize(routes: {}) ⇒ Server

Returns a new instance of Server.



8
9
10
# File 'lib/lazy_graph/server.rb', line 8

def initialize(routes: {})
  @routes = routes.transform_keys(&:to_sym).compare_by_identity
end

Instance Method Details

#call(env) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/lazy_graph/server.rb', line 12

def call(env)
  # Rack environment contains request details
  env[:X_REQUEST_TIME_START] = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  request = Rack::Request.new(env)

  unless (graph_module = @routes[request.path.to_sym])
    return not_found!(request.path)
  end

  return success!(request, graph_module.usage) if request.get?

  if request.post?
    body = JSON.parse(request.body.read)
    context, modules, validate, debug, query = body.values_at('context', 'modules', 'validate', 'debug', 'query')
    unless context.is_a?(Hash) && !context.empty?
      return not_acceptable!(request, "Invalid 'context' Parameter", 'Should be a non-empty object.')
    end

    unless modules.is_a?(Hash) && !modules.empty?
      return not_acceptable!(request, "Invalid 'modules' Parameter", 'Should be a non-empty object.')
    end

    unless ALLOWED_VALUES_VALIDATE.include?(validate)
      return not_acceptable!(
        request, "Invalid 'validate' Parameter", "Should be nil, bool, or one of 'input', 'context'"
      )
    end

    unless ALLOWED_VALUES_DEBUG.include?(debug)
      return not_acceptable!(request, "Invalid 'debug' Parameter", 'Should be nil or bool')
    end

    unless query.nil? || query.is_a?(String) || (query.is_a?(Array) && query.all? do |q|
      q.is_a?(String)
    end)
      return not_acceptable!(request, "Invalid 'query' Parameter", 'Should be nil, array or string array')
    end

    begin
      result = graph_module.eval!(
        modules: modules, context: context,
        validate: validate, debug: debug,
        query: query
      )
      return not_acceptable!(request, result[:message], result[:detail]) if result[:type] == :error

      return success!(request, result)
    rescue StandardError => e
      LazyGraph.logger.error(e.message)
      LazyGraph.logger.error(e.backtrace.join("\n"))
      return error!(request, 500, 'Internal Server Error', e.message)
    end
  end

  not_found!("#{request.request_method} #{request.path}")
end

#error!(request, status, message, details = '') ⇒ Object



86
87
88
89
# File 'lib/lazy_graph/server.rb', line 86

def error!(request, status, message, details = '')
  LazyGraph.logger.info("#{request.request_method}: #{request.path} => #{status} #{request_ms(request)}ms")
  [status, { 'Content-Type' => 'text/json' }, [{ 'error': message, 'details': details }.to_json]]
end

#not_acceptable!(request, message, details = '') ⇒ Object



69
70
71
# File 'lib/lazy_graph/server.rb', line 69

def not_acceptable!(request, message, details = '')
  error!(request, 406, message, details)
end

#not_found!(request, details = '') ⇒ Object



73
74
75
# File 'lib/lazy_graph/server.rb', line 73

def not_found!(request, details = '')
  error!(request, 404, 'Not Found', details)
end

#request_ms(request) ⇒ Object



77
78
79
# File 'lib/lazy_graph/server.rb', line 77

def request_ms(request)
  ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - request.env[:X_REQUEST_TIME_START]) * 1000.0).round(3)
end

#success!(request, result, status: 200) ⇒ Object



81
82
83
84
# File 'lib/lazy_graph/server.rb', line 81

def success!(request, result, status: 200)
  LazyGraph.logger.info("#{request.request_method}: #{request.path} => #{status} #{request_ms(request)}ms")
  [status, { 'Content-Type' => 'text/json' }, [result.to_json]]
end