Class: LocalDevelopmentGateway::DatabaseRouter

Inherits:
Object
  • Object
show all
Defined in:
lib/local_development_gateway/database_router.rb

Defined Under Namespace

Modules: Drivers, Tds, Wire Classes: DockerApi, DockerRoutes, Route

Constant Summary collapse

CONNECT_TIMEOUT =
3
MAX_CONNECTIONS =
128

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(routes: DockerRoutes.new, drivers: self.class.drivers, servers: nil) ⇒ DatabaseRouter

Returns a new instance of DatabaseRouter.



23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/local_development_gateway/database_router.rb', line 23

def initialize(
  routes: DockerRoutes.new,
  drivers: self.class.drivers,
  servers: nil
)
  @routes = routes
  @drivers = drivers
  @servers =
    servers ||
      drivers.to_h do |driver|
        [driver.name, TCPServer.new("0.0.0.0", driver.listen_port)]
      end
end

Class Method Details

.driversObject



16
17
18
19
20
21
# File 'lib/local_development_gateway/database_router.rb', line 16

def self.drivers
  @drivers ||= [
    Drivers::SqlServerDriver.new,
    Drivers::PostgreSqlDriver.new
  ].freeze
end

.runObject



12
13
14
# File 'lib/local_development_gateway/database_router.rb', line 12

def self.run
  new.run
end

Instance Method Details

#route(client, driver) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/local_development_gateway/database_router.rb', line 58

def route(client, driver)
  routes = @routes.call.select { |route| route.driver == driver.name }

  source, target =
    driver.connect(client, routes, connector: method(:connect))
  proxy(source, target)
rescue EOFError
  nil
rescue Error => error
  warn error.message
rescue StandardError => error
  warn error.full_message
ensure
  source&.close unless source.equal?(client)
  client&.close
  target&.close
end

#runObject



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/local_development_gateway/database_router.rb', line 37

def run
  slots = SizedQueue.new(MAX_CONNECTIONS)
  MAX_CONNECTIONS.times { slots << true }
  @drivers
    .map do |driver|
      Thread.new do
        server = @servers.fetch(driver.name)
        loop do
          client = server.accept
          slots.pop
          Thread.new(client) do |connection|
            route(connection, driver)
          ensure
            slots << true
          end
        end
      end
    end
    .each(&:join)
end