Ich habe Probleme beim Umgang mit Nebenläufigkeitsproblemen beim Einfügen in eine Postgres-Datenbank. Das Modell verfügt über eine Eindeutigkeitseinschränkung für eine Indexspalte. Dies gilt auch für die Postgres-Tabelle. Manchmal versuchen zwei Threads, den gleichen Datensatz zur gleichen Zeit einzufügen (dies ist unvermeidlich), in welchem Fall beide die Modellvalidierung bestehen, aber der zweite die Postgres-Validierung verletzt. Also ich fange die Ausnahme und alles ist in Ordnung. Das ist nicht das Problem.Wie kann ich die Datenbank nach einer Postgres-Ausnahme abfragen?
Das Problem ist, meine Methode muss das Objekt aus der Datenbank zurückgeben, so dass ich die db abfragen, um den Datensatz vom ersten Thread eingefügt zu bekommen (ich kann sicher annehmen, es ist das gleiche wie das im zweiten Thread). Dies schlägt jedoch fehl, da sich die Transaktion aufgrund des fehlgeschlagenen Einfügens immer noch in einem ungültigen Zustand befindet.
Meine Frage ist: Wie kann ich die zweite Ausnahme vermeiden, die innerhalb des Rettungsblocks ausgelöst wird, und/oder die Methode aktivieren, um den Datensatz zurückzugeben, der vom ersten Thread eingefügt wurde?
class Place
validates :index_column, uniqueness: true, allow_nil: true
def self.create_and_insert(some_params)
more_params = additional_params(some_params)
place = Place.new(some_params, more_params)
begin
place.save # Insert into place table. This initiates a transaction.
rescue ActiveRecord::RecordNotUnique => e
# Oops! Another thread beat us to it.
# The transaction is now in an invalid state.
place = Place.find_by(index_column: some_params.id) # This throws a new exception
end
place
end
end
Was genau ist Ihre zweite Ausnahme? – archana
@archana ActiveRecord :: AnweisungInvalid: PG :: InFailedSqlTransaction: FEHLER: aktuelle Transaktion wird abgebrochen, Befehle bis Ende des Transaktionsblocks ignoriert: SELECT "Orte". * FROM "Orte" WO "Orte". "ID" = "Some_id" LIMIT 1 –
@archana Also im Grunde ist die Transaktion nicht beendet. Ich habe keine Transaktion gestartet, aber 'save' hat es getan. Die Implementierung von 'after_rollback' wird nicht helfen, da ich einen Wert von' create_and_insert' zurückgeben muss. Kann ich es aus 'create_and_insert' zurückholen? –