3 Stimmen

ActiveRecord::StatementInvalid wenn Prozess SIGTERM empfängt?

In meiner Rails-App habe ich ein Skript, das einige Datensätze in der Datenbank aktualisiert. Wenn ich ein SIGTERM sende, um das Skript zu beenden, empfängt es gelegentlich dieses Signal, während ActiveRecord eine Abfrage ausführt. Dies führt dazu, dass eine ActiveRecord::StatementInvalid-Ausnahme ausgelöst wird.

Ich möchte StatementInvalid-Ausnahmen abfangen, die auftreten, wenn sie das Ergebnis eines SIGTERM sind, und das Skript beenden. Wie kann ich feststellen, dass ein StatementInvalid aufgrund eines Signals und nicht aus einem anderen Grund auftritt?

6voto

wuputah Punkte 11174

Wenn Sie das TERM-Signal abfangen, werden Sie die Ausnahme wohl vermeiden. Sie können dies am Anfang Ihres Skripts tun (oder eigentlich überall, aber Sie brauchen es nur einmal zu tun).

 Signal.trap("TERM") do
   Kernel.exit!
 end

Der Grund für den StatementInvalid-Fehler ist, dass Ruby das Signal behandelt, indem es an der Stelle der aktuellen Ausführung eine SIGTERM-Exception auslöst. ActiveRecord fängt die Ausnahme ab und wirft sie als StatementInvalid wieder aus. Wenn Sie einen Signal-Handler setzen, führt Ruby Ihren Handler aus, anstatt eine Exception auszulösen.

Siehe die Ruby Signal Dokumentation für weitere Informationen.

0voto

Martin Carpenter Punkte 5813

Es klingt, als ob dieses "Skript" außerhalb der Rails-Anwendung liegt ( script/runner oder ähnlich?), so dass Sie vielleicht den "Signalhandler" und den "Worker" entkoppeln können? Können Sie z.B. einen untergeordneten Prozess/Thread/Fiber/... abzweigen, um die Datenbank zu aktualisieren, und dem übergeordneten Prozess signalisieren, dass er jetzt aufhört? Natürlich muss der Elternprozess dann dem Kindprozess über einen geeigneten Mechanismus signalisieren, dass er aufhört (nicht SIGTERM ;-)).

0voto

Jasim Punkte 490

Dies ist keine exakte Antwort auf die Frage, aber Sie können den Beendigungspunkt kontrollieren - das Programm wird erst beendet, wenn es den von Ihnen festgelegten Beendigungspunkt erreicht hat.

time_to_die=false

# Prevent abrupt stopping of the daemon.
Signal.trap("TERM") { time_to_die=true; "SIG_IGN" }   

loop {
  .
  .
  exit_gracefully if time_to_die
  .
  .
}

def exit_gracefully
   #Cleaning up..
   $log.log "#{Time.now} TERM signal received. Exiting.."
   $db.close
   exit
 end

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X