Я впервые учусь и делаю SSE на рельсах! Код моего контроллера:
def update
response.headers['Content-Type'] = 'text/event-stream'
sse = SSE.new(response.stream, event: 'notice')
begin
User.listen_to_creation do |user_id|
sse.write({id: user_id})
end
rescue ClientDisconnected
ensure
sse.close
end
end
Внешний интерфейс:
var source = new EventSource('/site_update');
source.addEventListener('notice', function(event) {
var data = JSON.parse(event.data)
console.log(data)
});
Модель pub / sub
class User
after_commit :notify_creation, on: :create
def notify_creation
ActiveRecord::Base.connection_pool.with_connection do |connection|
self.class.execute_query(connection, ["NOTIFY user_created, '?'", id])
end
end
def self.listen_to_creation
ActiveRecord::Base.connection_pool.with_connection do |connection|
begin
execute_query(connection, ["LISTEN user_created"])
connection.raw_connection.wait_for_notify do |event, pid, id|
yield id
end
ensure
execute_query(connection, ["UNLISTEN user_created"])
end
end
end
def self.clean_sql(query)
sanitize_sql(query)
end
private
def self.execute_query(connection, query)
sql = self.clean_sql(query)
connection.execute(sql)
end
end
Я заметил, что если я пишу в SSE , что-то тривиальное, как в учебнике, как ... sse.write({time_now: Time.now})
, все прекрасно работает. В командной строке CTRL+C
успешно завершает работу локального сервера.
Однако всякий раз, когда мне нужно написать что-то, требующее какого-либо действия с базой данных, например, когда я выполняю postgres pub / sub как в этом учебном пособии , тогда CTRL+C
не выключает локальный сервер, он просто зависает и зависает и требует от меня ручного уничтожения PID
.
при фактическом вращении на сервере, иногда ссылка refre sh также будет зависать вечно. В других случаях выдается ошибка тайм-аута:
ActiveRecord::ConnectionTimeoutError (could not obtain a connection from the pool within 5.000 seconds (waited 5.001 seconds); all pooled connections were in use):
К сожалению, эта проблема сохраняется и в производстве, где я использую Heroku. Я просто получаю много ошибок тайм-аута. Но я думаю, что у меня правильно настроен Heroku, а также локальные настройки ... Насколько я понимаю, мне просто нужен большой пул (у меня есть 5
), чтобы получать соединения и разрешать несколько потоков. Ниже вы найдете некоторый код конфигурации.
НЕТ ПЕРЕМЕННЫХ ENV, ПО УМОЛЧАНИЮ ИСПОЛЬЗУЕТСЯ!
# config/database.yml
default: &default
adapter: postgresql
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000
development:
<<: *default
database: proper_development
# config/puma.rb
workers Integer(ENV['WEB_CONCURRENCY'] || 1)
threads_count = Integer(ENV['MAX_THREADS'] || 5)
threads threads_count, threads_count
preload_app!
rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
on_worker_boot do
# Worker specific setup for Rails 4.1+
# See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
ActiveRecord::Base.establish_connection
end
Если это полезно, вот вывод, когда я запускаю rails s
=> Booting Puma
=> Rails 5.0.2 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 4.3.3 (ruby 2.4.0-p0), codename: Mysterious Traveller
* Min threads: 0, max threads: 16
* Environment: development
* Listening on tcp://127.0.0.1:3000
* Listening on tcp://[::1]:3000
Use Ctrl-C to stop