14

Ho rintracciato uno strano errore undefined method `run_callbacks' for nil:NilClass e sono riuscito a riprodurlo con questo codice di esempio.qual è il modo corretto per gestire i timeout per la registrazione attiva con un pool di connessioni?

Fondamentalmente il problema è il record attivo sta ricevendo un timeout (il valore predefinito è 5s) ma genera un'eccezione metodo non definita, che a me sembra errata.

Ma in ogni caso, qual è il modo giusto per gestire questo? Nel mio codice reale, ho un mucchio di thread che sono occupati a fare il vero lavoro, ma a volte ho riscontrato questo errore. Immagina quindi che il puts sia il codice reale. Voglio che i thread esistenti continuino a funzionare quando succede.

threads = [] 
10.times do |n| 

threads << Thread.new { 
    ActiveRecord::Base.connection_pool.with_connection do |conn| 
     puts "#{n} #{conn}" 
     res = conn.execute("select sleep(6)", :async => true) 
    end 
    } 
end 

# block and wait for all threads to finish 
threads.each { |t| puts "joined" ; t.join } 
rescue Exception => e 
    puts $!, [email protected] 
end 

Se eseguo questo codice come è, ottengo l'eccezione. Se riduco il sonno a 4s, non lo faccio. Ecco l'output con il sonno 6s.

joined 
0 #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xb73c6380> 
1 #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xb73c5548> 
2 #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xb73c4fe4> 
3 #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xb73c4a80> 
4 #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xb73c451c> 
joined 
joined 
joined 
joined 
joined 
undefined method `run_callbacks' for nil:NilClass 
/usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:212:in `checkin' 
sqltst.rb:31:in `join' 
sqltst.rb:31 
sqltst.rb:31:in `each' 
sqltst.rb:31 
+0

Si ottiene lo stesso errore, se si tenta di rilevare l'eccezione all'interno del thread? –

+0

Come gestirlo dipende un po 'dalla natura delle tue domande. Presumo che dal momento che vengono eseguiti in thread separati, le query in ogni thread sono contestualmente isolate l'una dall'altra. In questo caso, gestirò sicuramente l'errore all'interno del thread stesso. Fare 3 tentativi su timeout e quindi impostare un "codice di ritorno del thread" e uscire dalla discussione. Se stai facendo degli aggiornamenti, ovviamente li impacchetta in una transazione - ActiveRecord supporta questo. –

+0

Se vuoi solo scrivere codice per continuare a funzionare hai provato ad aggiungere 'rescue nil' alla fine del tuo blocco? – Stone

risposta

0

È necessario impostare il pool: 10 nel database.yml. Sembra che tu abbia raggiunto il limite.

Problemi correlati