Mehrere simultane Datenbankverbindungen mit ActiveRecord

Die Aufgabe klang trivial:

Mehrere Server sammeln Daten und speichern diese in einer lokalen Datenbank. Es ist eine Rails Anwendung zu schreiben, die die Zustände aller Datenbanken auf einer Website darstellt.

Lösung

Die Datei database.yml enthält für jeden Betriebsmodus einer Rails-Anwendung die passende Konfiguration einer Datenbankverbindung, welche von ActiveRecord automatisch benutzt wird, wenn keine andere angegeben wurde.

Wir versuchten als erstes die jeweilige Verbindung für einen Zugriff anzugeben. Dabei stellte sich heraus, dass ActiveRecord für jedes Modell nur eine Datenbankverbindung erlaubt. Intern wird eine statische HashMap von Klassennamen auf eine Datenbankverbindung gehalten. Diese wird automatisch für alle Anfragen für das Modell genutzt.

Im Umkehrschluss bedeutet das, dass zur Lösung der Aufgabe eine Modell-Klasse je Server benötigt wird. Zum Glück ist Ruby eine dynamische Sprache. Wir generieren uns einfach zur Laufzeit eine passende Ableitung für eine Datenbankverbindung:

module ConnectionModelFactory  
  def self.build(connection, model)
    symbol = ([model.to_s, connection.camelize.to_s] * '_').to_sym
    unless self.const_defined? symbol
      derived = Class.new model
      self.const_set(symbol, derived)
    end
    self.const_get symbol
  end
end

Mit der neuen Klasse können wir nun die Datenbankverbindung einfach festlegen:

derived.establish_connection connection

Soweit so gut! Das Ganze funktioniert nur so lange, wie das Modell keine externen Relationen benötigt. Damit diese ebenfalls über die Datenbankverbindung abgefragt werden können, erzeugen wir alle Relationen mit angepassten Modellen neu:

derived.reflect_on_all_associations.each do |a|
  connection_a = ConnectionModelFactory.build(connection, a.klass)
  a_options = a.options.merge(:class_name => connection_a.name)
  derived.create_reflection(a.macro, a.name, a_options, a.active_record)
end

Damit ist die Aufgabe gelöst.

Als Erweiterung könnte man nun noch alle Anfragen zu den Servern in eigenen Threads durchführen.

←zurück

© 2012 – 2024 HicknHack Software GmbH | Impressum | Datenschutzerklärung