есть ли способ узнать об обновлениях базы данных без запросов/запросов?

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

В приложении rails мне нужно автоматически обновлять представления без обновления. Например

def index
    @states = State.page(params[:state_page])
    @level_one_companies = Company.includes(:state)
                                  .where(level: 1)
                                  .order('created_at DESC').limit(20)

    @level_two_companies = Company.includes(:state)
                                  .where(level: 2)
                                  .order('created_at DESC').limit(20)
end

На странице индекса у меня будут таблицы для каждого из них, и мне нужно обновлять таблицы, когда новые данные добавляются в состояние (или) компании уровня 1 (или) уровня 2.

Я знаю, что могу использовать два способа автоматического обновления представлений, т.е.

  1. Кабель действия.
  2. Пул данных через временной интервал с помощью Jquery.

Обычно при использовании Action Cable мы будем транслировать данные с сервера после создания записи в базе данных (после .save в действии создания (или) обратного вызова after_save из модели). Однако я не создаю никаких записей через приложение rails.

Мой первый вопрос: можно ли в этом случае использовать активный кабель?

Поэтому я выбрал второй вариант, и он отлично работает. Но он делает слишком много вызовов БД через каждые X секунд. есть ли способ уменьшить запросы на обновление представлений? Каков наилучший способ, которым я могу пойти сюда? Любая помощь высоко ценится. Спасибо.


person Narasimha Reddy - Geeker    schedule 13.10.2017    source источник


Ответы (2)


если ваши теги установлены правильно, вы используете postgres в качестве базы данных.

postgres предлагает механизм публикации-подписки, который вы можете использовать в сочетании с action-cable для прослушивания изменений в вашей базе данных.

в этой сути вы можете найти пример для postgres-pubsub с server-sent-events. должно быть просто перевести это в код, совместимый с кабелем действия.

person phoet    schedule 16.10.2017
comment
Спасибо, @phoet, попробую и дам вам знать. - person Narasimha Reddy - Geeker; 16.10.2017

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

Сначала вы создаете триггер:

CREATE FUNCTION deletes_notify_trigger() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
DECLARE
BEGIN
  PERFORM pg_notify('deletes_channel',  ('DELETED' || ';;' || OLD.id )::text );
  RETURN new;
END;
$$;

а также

CREATE TRIGGER deletes_trigger AFTER DELETE ON events FOR EACH ROW EXECUTE PROCEDURE deletes_notify_trigger();

Вы можете добавить все, что хотите, в пакеты данных, которые транслируются, в моем случае мне нужен только идентификатор записи. Для создания и обновления вы можете отправить всю строку или только некоторые выбранные столбцы. Вы также можете отправить его как JSON в PG 9.2 (я думаю) и выше. Я использую 9.1, поэтому я связываюсь с ;; сепараторы.

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

Затем наблюдатель и трансляция потребителям (в моем случае node, socketcluster и гем pg, в вашем случае вы можете использовать JS, Python, Ruby, что угодно)

var global_deletes = socket.subscribe('deletes_channel');
pg.connect(connectionString, function(err, client) {
      client.on('notification', function(dbmsg) {
        console.log(dbmsg.payload);
        var payload = dbmsg.payload.split(";;"); // you can use JSON instead

        if (payload[0] == "DELETED") { // when a DELETE is received...
            global_deletes.publish(dbmsg.payload);
            var tchannel = socket.subscribe('events-'+ payload[1]); // join the channel we want to broadcast
            setTimeout( () => tchannel.publish(dbmsg.payload), 50); // send the update to all consumers
            setTimeout( () => tchannel.unsubscribe(), 100);
        }
       );
    var query = client.query("LISTEN deletes_channel"); // turn on notifications from the server
});
person Nick M    schedule 16.10.2017