Repository: rails/rails
File: activerecord/test/cases/adapter_test.rb (Ruby)

Code before:
        Post.first

        remote_disconnect @connection

        assert Post.find(1)
        assert_predicate @connection, :active?

        remote_disconnect @connection

        assert Post.find_by(title: "Welcome to the weblog")
        assert_predicate @connection, :active?
      end

      test "#exists? queries are retried and result in a reconnect" do
        Post.first

        remote_disconnect @connection

        assert_predicate Post, :exists?
        assert_predicate @connection, :active?
      end

      test "statement-cached association queries are retried and result in a reconnect" do
        p = Post.first

        remote_disconnect @connection

        p.comments.to_a
        assert_predicate @connection, :active?
      end

      test "queries containing SQL fragments are not retried" do
        Post.first

        remote_disconnect @connection

        assert_raises(ActiveRecord::ConnectionFailed) { Post.where("1 = 1").to_a }
        assert_not_predicate @connection, :active?

        remote_disconnect @connection

        assert_raises(ActiveRecord::ConnectionFailed) { Post.select("title AS custom_title").first }
        assert_not_predicate @connection, :active?

        remote_disconnect @connection

        assert_raises(ActiveRecord::ConnectionFailed) { Post.find_by("updated_at < ?", 2.weeks.ago) }
        assert_not_predicate @connection, :active?
      end

      test "queries containing SQL functions are not retried" do

Review comment (suggestion):
An idea I had to make these tests avoid the `remote_disconnect` dance was we could add `allow_retry`/`retryable` to `sql.active_record`. Then we could make very simple positive/negative assertions for each kind of query

Code after:
      end

      test "queries containing SQL fragments do not allow retries" do
        notifications = capture_notifications("sql.active_record") do
          Post.where("1 = 1").to_a
          Post.select("title AS custom_title").first
          Book.find_by("updated_at < ?", 2.weeks.ago)
        end.select { |n| n.payload[:name] != "SCHEMA" }

        assert_equal 3, notifications.length

        notifications.each do |n|
          assert_not n.payload[:allow_retry]
        end
      end

      test "queries containing SQL functions do not allow retries" do
        tags_count_attr = Post.arel_table[:tags_count]
        abs_tags_count = Arel::Nodes::NamedFunction.new("ABS", [tags_count_attr])

        notifications = capture_notifications("sql.active_record") do
          Post.where(abs_tags_count.eq(2)).first
        end.select { |n| n.payload[:name] != "SCHEMA" }

        assert_equal 1, notifications.length

        notifications.each do |n|
          assert_not n.payload[:allow_retry]
        end
      end

      test "transaction restores after remote disconnection" do
        remote_disconnect @connection
        Post.transaction do
          Post.count
        end
        assert_predicate @connection, :active?
      end

      test "active transaction is restored after remote disconnection" do
        assert_operator Post.count, :>, 0
        Post.transaction do
          @connection.materialize_transactions
          remote_disconnect @connection

          # Regular queries are not retryable, so the only abstract operation we can
          # perform here is a direct verify. The outer transaction means using another
          # here would just be a ResetParent.
          @connection.verify!

          Post.delete_all