Нужна альтернатива фильтрам / наблюдателям для проекта Ruby on Rails - PullRequest
0 голосов
/ 23 мая 2009

В Rails есть хороший набор фильтров (before_validation, before_create, after_save и т. Д.), А также поддержка наблюдателей, но я столкнулся с ситуацией, когда использование фильтра или наблюдателя слишком затратно для вычислений. Мне нужна альтернатива.

Проблема: я регистрирую обращения к веб-серверу на большое количество страниц. Мне нужен триггер, который будет выполнять действие (скажем, отправлять электронное письмо), когда данную страницу просматривали более X раз. Из-за огромного количества страниц и обращений использование фильтра или наблюдателя приведет к значительным потерям времени, поскольку в 99% случаев проверяемое условие будет ложным. Письмо не должно быть отправлено сразу (т. Е. Допускается задержка в 5-10 минут).

Вместо этого я рассматриваю реализацию какого-то процесса, который сканирует базу данных каждые 5 минут или около того и проверяет, какие страницы были просмотрены более X раз, записывая это состояние в новую таблицу БД, а затем отправляя соответствующий адрес электронной почты. Это не совсем элегантно, но будет работать.

У кого-нибудь есть идея получше?

Ответы [ 4 ]

1 голос
/ 23 мая 2009

Я когда-то был частью команды, которая написала собственный рекламный сервер, который предъявлял те же требования: отслеживать количество обращений на документ и что-то делать, когда они достигают определенного порога. Этот сервер будет питать существующий очень большой сайт с большим трафиком, и масштабируемость была реальной проблемой. Моя компания наняла двух консультантов Doubleclick, чтобы выбрать себе мозги.

Их мнение таково: самый быстрый способ сохранить любую информацию - записать ее в пользовательскую директиву журнала Apache. Поэтому мы создали сайт, на котором каждый раз, когда кто-то нажимал на документ (объявление, страница и т. Д.), Сервер, который обрабатывал запрос, записывал в журнал оператор SQL: «INSERT INTO impression (метка времени, страница, ip и т. Д. ) VALUES (x, 'path / to / doc', y и т. Д.); " - все выводится динамически с данными с веб-сервера. Каждые 5 минут мы собирали эти файлы с веб-серверов, а затем по одному выгружали их в основную базу данных. Затем на досуге мы можем проанализировать эти данные, чтобы сделать все, что нам нравится.

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

1 голос
/ 23 мая 2009

Рейк-задания это хорошо! Но в конечном итоге вы будете писать больше пользовательского кода для каждой добавляемой фоновой работы. Проверьте плагин отложенной работы http://blog.leetsoft.com/2008/2/17/delayed-job-dj

DJ - это асинхронная очередь с приоритетами, основанная на одной простой таблице базы данных. Согласно веб-сайту диджея, вы можете создать работу, используя метод Delayed :: Job.enqueue () , показанный ниже.

class NewsletterJob < Struct.new(:text, :emails)
  def perform
    emails.each { |e| NewsletterMailer.deliver_text_to_email(text, e) }
  end    
end  

Delayed::Job.enqueue( NewsletterJob.new("blah blah", Customers.find(:all).collect(&:email)) )
0 голосов
/ 23 мая 2009

Я должен написать здесь что-нибудь, чтобы код stackoverflow выделил первую строку.

class ApplicationController < ActionController::Base
  before_filter :increment_fancy_counter

  private

  def increment_fancy_counter
    # somehow increment the counter here
  end
end

# lib/tasks/fancy_counter.rake
namespace :fancy_counter do
  task :process do
    # somehow process the counter here
  end
end

Запустите задание cron rake fancy_counter:process, как часто вы хотите, чтобы оно запускалось.

0 голосов
/ 23 мая 2009

При сохранении модели попаданий обновите избыточный столбец в модели страницы, в котором хранится текущее общее количество попаданий. Это потребует от вас 2 дополнительных запросов, поэтому, возможно, каждое обращение обрабатывается вдвое дольше, но вы можете решить, нужно ли вам отправить письмо с простым if.

Ваше оригинальное решение тоже неплохое.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...