Upgrade von Discourse auf Rails 6

Hallo Team,

Rails 6.0.0 wurde vor 25 Tagen veröffentlicht, daher denke ich, es ist an der Zeit, Discourse zu aktualisieren :slight_smile: Dafür musste ich einige Schritte durchführen.

  1. Fehlerhafte Tests beheben
  • Leere Methode trigger_transactional_callbacks? zu lib/mini_sql_multisite_connection.rb hinzufügen
  • UrlHelper lädt standardmäßig ActionView::Helpers::UrlHelper statt lib/UrlHelper. Ich habe das gelöst, indem ich :: davor gesetzt habe. Was haltet ihr davon, den Namen dieser Klasse zu ändern?
  • In Rails 5.2.3 akzeptierte MigrationContext ein Argument, in 6.0.0 ist zusätzlich ein Schema erforderlich.
  1. Veraltete Methoden beheben
  • update_attributes! durch update! ersetzen
  • Content_type enthält nun Charset; stattdessen sollte der Medientyp verwendet werden – rails/guides/source/upgrading_ruby_on_rails.md at main · rails/rails · GitHub
  • Warnung bezüglich bereits initialisierter Konstanten (TRADITIONAL_ESCAPED_CHAR, RFC_5987_ESCAPED_CHAR) beheben. Bevor ich sie entfernte, habe ich bestätigt, dass die Werte in ActionPack identisch sind.
  1. Klassischen Autoloader als ersten Schritt vor Zeitwerk verwenden.

  2. Migrationen unter Rails 6.0.0 korrigieren – das neueste Rails erlaubt keine Fehler aus alten Migrationen (man kann keine bereits definierte Spalte ‘integer’ erneut definieren).

Ich habe Rauchtests durchgeführt, um sicherzustellen, dass Discourse wie erwartet funktioniert. Zusätzlich habe ich Leistungstests durchgeführt, um sicherzustellen, dass es keine Regressionen gibt (ich habe die Standard-500-Iterationen verwendet).

Test Rails 5.2.3 Rails 6.0.0 Prozent
categories-50 27 24 88,89%
categories-75 31 26 83,87%
categories-90 36 37 102,78%
categories-99 52 50 96,15%
home-50 27 26 96,30%
home-75 30 28 93,33%
home-90 39 38 97,44%
home-99 53 55 103,77%
topic-50 35 27 77,14%
topic-75 36 29 80,56%
topic-90 37 39 105,41%
topic-99 56 50 89,29%
categories_admin-50 47 47 100,00%
categories_admin-75 54 59 109,26%
categories_admin-90 64 66 103,13%
categories_admin-99 132 116 87,88%
home_admin-50 47 46 97,87%
home_admin-75 51 56 109,80%
home_admin-90 63 64 101,59%
home_admin-99 110 97 88,18%
topic_admin-50 50 49 98,00%
topic_admin-75 58 59 101,72%
topic_admin-90 65 67 103,08%
topic_admin-99 113 86 76,11%
load_rails 2593 2618 100,96%
rss_kb 318800 287332 90,13%
pss_kb 306913 275378 89,73%
Durchschnitt 89,31%

Ich werde einen Pull Request mit allen oben genannten Änderungen erstellen. Bitte lasst mich wissen, ob ihr Anpassungen wünscht oder zusätzliche Tests durchführt werden sollen, um sicherzustellen, dass alles wie erwartet funktioniert.

PR – DEV: Upgrading Discourse to Rails 6 by KrisKotlarek · Pull Request #8083 · discourse/discourse · GitHub

Viele Grüße
Kris

Das ist großartig :confetti_ball:

Kannst du das in eine Markdown-Tabelle mit prozentualer Änderung umwandeln? Ein oberflächlicher Blick zeigt, dass sich nicht viel geändert hat, was großartig ist.

Was Plugins betrifft, haben wir eine Rake-Aufgabe, die alle offiziellen Plugins installiert. Kannst du diese ausführen und sicherstellen, dass die Pluginspezifikationen unter Rails 6 bestehen? (rake plugin:spec sollte den Zweck erfüllen)

Ich habe den ursprünglichen Beitrag aktualisiert, um eine Tabelle anzuzeigen. Danke, dass du mich auf die Plugin-Spezifikationen hingewiesen hast. Ich sehe, dass 2 Spezifikationen auf Travis fehlgeschlagen sind. Ich werde mir das ansehen und sie beheben.

Hier gibt es zwei Zahlen, die ich sehr interessant finde:

RSS auf 6.0 ist fast 10 % besser.

Topic (Medianzeit) – unsere häufigste Route – ist 22 % schneller.

Das ist eine wirklich deutliche Leistungsverbesserung. Können Sie die 22 % schneller auf topic-50 konsistent messen? Können Sie bestätigen, dass die tatsächliche Seite korrekt gerendert wird?

Ich habe den Benchmark dreimal ausgeführt, und diesmal sind die Ergebnisse weniger spektakulär. Mein Ablauf besteht darin, ruby script/bench.rb im richtigen Branch master oder rails6 einzugeben, Enter zu drücken und die Tastatur nicht zu berühren, um die Ergebnisse nicht zu beeinflussen.

topic-50 RSS
5.2.3 50 322852
5.2.3 50 309684
5.2.3 50 346376
Durchschnitt 50 326304
6.0.0 49 328844
6.0.0 49 321824
6.0.0 49 283584
Durchschnitt 49 311417

Ich habe außerdem meinen Entwicklungsserver mit der Performance-Datenbank verbunden, um sicherzustellen, dass die Topic-Seite korrekt aussieht. Der Screenshot unten sieht für mich in Ordnung aus.

Ich würde gerne deine Meinung zu einer Korrektur einholen.
Ich habe alle Plugins heruntergeladen, jedoch schlägt eine neue Spezifikation im Vergleich zu master fehl (./plugins/discourse-data-explorer/spec/controllers/queries_controller_spec.rb:32)

  1) DataExplorer::QueryController when disabled denies every request
     Failure/Error: render 'default/empty'

     ActionView::Template::Error:
       wrong number of arguments (given 2, expected 1)

Das ist in master bei rspec-rails behoben https://github.com/rspec/rspec-rails/blob/4-0-dev/lib/rspec/rails/view_rendering.rb
durch die Änderung
def self.call(_template) zu def self.call(_template, _source = nil)

Ich könnte rspec-rails mit einer neuen Datei in lib/freedom_patched/rspec-rails.rb per Monkey Patch anpassen, wollte aber sicherstellen, dass dies der beste Ansatz ist.

Ich denke, dies ist die letzte Änderung, die das Zusammenführen von Rails 6 blockiert.

Außerdem habe ich festgestellt, dass diese Spezifikation fehlerhaft ist, jedoch ist sie auch in master fehlerhaft. Ich kann versuchen, sie zu reparieren (./plugins/discourse-calendar/spec/jobs/update_holiday_usernames_spec.rb:14)

 Failure/Error: expect(DiscourseCalendar.users_on_holiday).to eq([post.user.username])
       expected: ["bruce1"]
            got: []

Schließlich gibt es in den Plugins veraltete Methoden, die ich morgen leicht beheben kann.

Was ist deine Meinung zu rspec-rails?

Oh je, ich schätze, wir müssen bis zur Veröffentlichung von rspec-rails 4 einen Monkey-Patch verwenden. Mir fällt hier keine sauberere Lösung ein.

Oder… vielleicht… nutzen wir vorerst das Beta-Gem, wenn alles funktioniert?

Alles klar, ich werde heute Abend versuchen, das Beta zu installieren und schauen, wie es läuft. Das Update könnte einfach und reibungslos sein.

Ich habe ein paar zusätzliche Korrekturen vorgenommen.

Zunächst einmal habe ich herausgefunden, warum ein Test sowohl im master- als auch im rails6-Branch bei mir fehlgeschlagen ist – FIX: Freezed time used in update_holiday_usernames_spec.rb should be UTC by KrisKotlarek · Pull Request #3 · discourse/discourse-calendar · GitHub

Außerdem habe ich Pull Requests für veraltete Methoden in verschiedenen Plugins erstellt:

Ich habe den neuesten master-Branch in den rails6-Branch re-based.

Schließlich habe ich rspec-rails auf Version 4.0.0.beta2 aktualisiert, und es funktioniert auf meinem lokalen Rechner einwandfrei. Travis hatte zwar einige Probleme, aber ich sehe dieselben Probleme auch in anderen Pull Requests, sodass ich nicht glaube, dass dies mit dem Upgrade von rspec-rails zusammenhängt.

Dies ist jetzt gemerged :confetti_ball: :confetti_ball: :confetti_ball:

Ich werde heute ein Auge darauf haben, vielen Dank für diese Arbeit.

Und ein großes Dankeschön an das Rails-Team, das dieses Upgrade so angenehm gemacht hat!!

Ich werde mit ein paar hübschen Grafiken zu diesem Thema zurückmelden.

Das Upgrade verläuft recht ereignislos, was großartig ist. Die Leistung ist gleichmäßig und bleibt erstaunlich ähnlich.

Speicher und CPU sehen ebenfalls bemerkenswert ähnlich aus.

Meine einzige Sorge (und etwas, dem ich auf den Grund gehen möchte) ist, dass es auf den Web-Workern regelmäßig für einige Sekunden zu „entgleisten

Dies sollte gemäß folgendem Link behoben werden:

Dies ist eine Folge von neuem Code in Rails 6, der den Zugriff auf die an den Thread gebundene Variable schützt, die bestimmt, ob Sie Prepared Statements verwenden können oder nicht.

Bei Discourse verwenden wir überhaupt keine Prepared Statements, daher ist dieser Patch für uns nicht erforderlich.

Weitere Informationen unter:

Und … bestätigt … meine Lösung beseitigt die vielen Thread-Spitzen

Auch erwähnenswert: So habe ich es debuggt:

  1. Ich habe diese kleine Klasse geschrieben
# frozen_string_literal: true

class Thread
  attr_accessor :origin
end

class ThreadDetective
  def self.test_thread
    Thread.new { sleep 1 }
  end
  def self.start(max_threads)
    @thread ||= Thread.new do
      self.new.monitor(max_threads)
    end

    @trace = TracePoint.new(:thread_begin) do |tp|
      Thread.current.origin = Thread.current.inspect
    end
    @trace.enable
  end

  def self.stop
    @thread&.kill
    @thread = nil
    @trace&.disable
    @trace.stop
  end

  def monitor(max_threads)
    STDERR.puts "Monitoring threads in #{Process.pid}"

    while true
      threads = Thread.list

      if threads.length > max_threads
        str = +("-" * 60)
        str << "#{threads.length} found in Process #{Process.pid}!\n"

        threads.each do |thread|
          str << "\n"
          if thread.origin
            str << thread.origin
          else
            str << thread.inspect
          end
          str << "\n"
        end
        str << ("-" * 60)

        STDERR.puts str
      end
      sleep 1
    end
  end

end
  1. Ich habe dann in Unicorn after_fork ein Require dieser Klasse eingebunden und ThreadDetective.start(14) ausgeführt.

  2. Die Klasse beobachtete sorgfältig jedes Mal, wenn ein Thread mit einem TracePoint erstellt wurde, und platzierte einen kleinen Frame namens origin auf dem Thread, um mir zu helfen, die Herkunft nachzuverfolgen. Sobald eine große Anzahl von Threads beobachtet wurde, gab sie Informationen auf STDERR aus. Dies kann in /var/www/discourse/logs/unicorn.stderr.log nachverfolgt werden.

Sobald ich wusste, dass alle 100 Threads von einem einzigen Punkt kamen, war es sehr einfach, die Ursache zu isolieren.

Ich habe festgestellt, dass ich dev.local im Entwicklungsmodus von Rails 6 nicht mehr als Hostnamen verwenden kann. Daher habe ich eine Umgebungsvariable hinzugefügt, um diese Whitelist zu konfigurieren:

Wir sollten diesen Monkey-Patch langfristig nicht weiter benötigen, da wir in Rails eine Lösung implementiert haben.

Hallo,

vielen Dank für deine Bemühungen, Rails 6 nach Discourse zu bringen! Darf ich höflich nachfragen, wann dies voraussichtlich in Discourse landen wird? Oder ist es bereits in 2.4.0.beta enthalten? Ich frage nur, ob dies möglicherweise Plugins brechen könnte, die Benutzer auf ihren Instanzen installiert haben.

Mit freundlichen Grüßen,
Andreas.

Dies ist seit September für alle Nutzer des Standard-Release-Kanals live. Es wurde erstmals in der Version 2.4.0.beta5 vorgestellt.

Alles klar, vielen Dank. Beste Wünsche für 2020 und danke für alles, was du hier tust.