Pull to refresh

Comments 8

Active Record везде где работал в энтерпрайзе запрещен или является антипатерном по умолчанию. Именно из-за подобного класса проблем и неадекватного потребления ресурсов. Но у меня стек другой )

А что разрешено, какой паттерн скрывает сложность бд быстрее и правильнее?

Сложность все равно будет торчать - вот вы с ней и столкнулись. Либо вы уходите в шаманство с ORM, либо берете все в свои руки и изолируете уже в своем подконтрольном слое данных.

У нас везде используются простые анемичные модели (почти структуры в терминологии языка си) на слое данных. В качестве запросов либо сырые запросы, либо простые генераторы запросов. Выглядит дорого по количеству кода, но в поддержке код несложный, и максимально оптимально в рантайме относительно взаимодействия с базой. В хорошем языке это все присыпается сахаром и выглядит не сильно хуже.

В правильной архитектуре проекта все равно вы увидите насколько небольшое число вариантов изменения и выборки сущностей реально необходимо. Плюсом не теряется синтаксис массовых обновлений (опасненько конечно, но иногда важно), которые раньше возможно было делать только поштучным апдейтом после массовой материализации (понятно что можно в сырой sql всегда уйти, но это не по феншую при ActiveRecord).

Спасибо тебе, добрый молодец, за то, что я не один такой. Поклон тебе низкий. И семье твоей огромная благодарность за то, что воспитала не мальчика, но мужа.

Не сарказм.

Смешно но именно что воспитали старшие товарищи. До прихода в энтерпрайз я тоже любил орм. А там им уже наелись)

Есть подозрение, что у вас старая версия AR используется. Попробовал на далеко не новой версии activerecord 6.1.7, все прекрасно работает без явного указания использовать connection_pool:

```ruby

require 'active_record'

require 'pg'

ActiveRecord::Base.establish_connection(

# ...

pool: 10,

)

class User < ActiveRecord::Base; end

threads = []

10.times do

threads << Thread.new do

begin

puts User.count

rescue ActiveRecord::ConnectionTimeoutError => e

puts 'could not obtain a connection from the pool'

end

end

end

threads.each { |thr| thr.join }


```

Проверил свою версию, там также 6.1.7. (На проде также)

Попробуйте количество потоков увеличить. В вашем примере 10 потоков используют пул из 10 коннекшенов, все они получают из пула коннекшн, но не возвращают его обратно. Так как без with_connection (или https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html#method-i-release_connection) коннекшены не возвращаются в пул.

Я понял вас, я думал, что вы выставили значение pool, но оно не применялось. Но тогда вы не с той стороны решаете проблему. Вам нужно просто установить адекватное значение pool в конфиге подключения ActiveRecord. По умолчанию стоит 5 - и это очень-очень мало для прода. Нужно выставлять значение pool в зависимости от кол-ва воркеров/тредов приложения. У вас же наверное используется application server, например puma. Соответственно максимальное возможное кол-во подключений к БД будет известно. Например у вас 4 воркера пумы и 8 тредов на каждый воркер. Тогда pool = 4*8=32. Если используется сайдкик, то нужно увеличить значение pool на кол-во тредов сайдкика. И тд (шедулерный rake-таски и тд). Вот статья https://devcenter.heroku.com/articles/concurrency-and-database-connections

Sign up to leave a comment.

Articles