Каков рекомендуемый способ создания функциональности, аналогичной «Входящим» в Stackoverflow? - PullRequest
12 голосов
/ 12 марта 2012

У меня есть сайт asp.net-mvc, и люди управляют списком проектов. Основываясь на некотором алгоритме, я могу сказать, устарел ли проект. Когда пользователь входит в систему, я хочу, чтобы он отображал количество устаревших проектов (аналогично тому, когда я вижу количество обновлений в папке «Входящие»).

Алгоритм вычисления устаревших проектов довольно медленный, поэтому, если каждый раз, когда пользователь входит в систему, я должен:

  1. Запустить запрос для всех проектов, владельцем которых они являются
  2. Запустить алгоритм IsStale ()
  3. Показать счетчик, где IsStale = true

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

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

Есть идея быстрого и масштабируемого способа поддержки этой концепции входящих сообщений, чтобы предупредить пользователей о количестве элементов для проверки ??

Ответы [ 5 ]

10 голосов
/ 16 марта 2012

Первым шагом всегда является правильный анализ требований. Давайте предположим, что я менеджер проекта. Я вхожу в систему, и мой единственный проект отображается как на время . Разработчик приходит ко мне в офис и говорит, что его деятельность задерживается. Я выбираю активность разработчика и меняю ее продолжительность. Система по-прежнему отображает мой проект как по времени , поэтому я радостно ухожу с работы.

Как вы думаете, что бы я почувствовал, если бы в 3:00 я получил телефонный звонок от клиента с просьбой объяснить, почему проект больше не вовремя ? Очевидно, довольно удивлен, потому что система не предупредила меня в любом случае. Почему это случилось? Потому что мне пришлось ждать 30 секунд (а не только 1 секунду?) Для следующего запуска запланированного задания для обновления состояния проекта.

Это просто не может быть решением. Предупреждение должно быть немедленно отправлено пользователю, даже если для запуска процесса IsStale() требуется 30 секунд. Покажите пользователю изображение loading... или что-нибудь еще, но убедитесь, что у пользователя есть точные данные.

Теперь, что касается реализации, ничего не поделаешь, чтобы убежать от предыдущего вопроса: вам придется запускать этот процесс, когда что-то, что влияет на определенную дату выполнения, изменится. Однако то, что вы можете сделать, это не излишне запускать этот процесс. Например, вы упомянули, что можете запускать его всякий раз, когда пользователь входит в систему. Что если 2 или более пользователей входят в систему и видят один и тот же проект и ничего не меняют? Нет необходимости запускать процесс дважды.

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

Преимущества

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

Недостатки

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

Переход к тому, как вы реализуете систему уведомлений аналогично StackOverflow, это совсем другой вопрос. Я предполагаю, что у вас есть много-много отношений с пользователями и проектами. Простейшим решением было бы добавить один атрибут к отношениям между этими объектами ( средняя таблица ):

Количество элементов: У пользователя много проектов. У проекта много пользователей

Таким образом, при запуске процесса вы должны обновить Has_pending_notifications каждого пользователя новым результатом. Например, если пользователь обновляет проект, и он больше не по времени , вам следует установить в поле true all users Has_pending_notifications, чтобы они знали о ситуации. Аналогично, установите значение false, когда проект по времени (я так понимаю, вы просто хотите, чтобы уведомления отображались, когда проект больше не по времени ).

На примере StackOverflow, когда пользователь читает уведомление, вы должны установить флаг false. Убедитесь, что вы не используете временные метки, чтобы угадать, прочитал ли пользователь уведомление: вход в систему не означает чтение уведомлений .

Наконец, если само уведомление достаточно сложное, вы можете убрать его из отношений между пользователями и проектами и перейти к следующему:

Количество элементов: У пользователя много проектов.У проекта много пользователей.У пользователя много уведомлений.Уведомление имеет одного пользователя.Проект имеет много уведомлений.У уведомления есть один проект.

Надеюсь, что-то, что я сказал, имело смысл, или даст вам еще одну лучшую идею:)

6 голосов
/ 14 марта 2012

Вы можете сделать следующее:

  1. К каждой записи пользователя добавьте поле даты и времени, в котором в последний раз выполнялись медленные вычисления. Назовите это LastDate .
  2. Для каждого проекта добавьте логическое значение, чтобы сказать, должен ли он быть в списке. Назовите это: Выбрано
  3. Когда вы запускаете набор процедур Slow, вы обновляете Selected fileds
  4. Теперь, когда пользователь входит в систему, если LastDate достаточно близок к этому моменту, вы используете результаты последнего медленного вычисления и просто берете весь проект с Selected true. В противном случае вы снова медленные вычисления. Вышеуказанная процедура является оптимальной, потому что она пересчитывает медленную процедуру ТОЛЬКО ЕСЛИ ФАКТИЧЕСКИ НЕОБХОДИМО, а выполнение процедуры с фиксированными интервалами времени ... может привести к потере времени, поскольку, возможно, пользователь не будет использовать результат вычисления.
3 голосов
/ 12 марта 2012

Сделать поле "несвежим". Запустите оператор SQL, который обновляет stale = 1 со всеми записями, где stale = 0 AND (этот алгоритм возвращает true). Затем запустите оператор SQL, который выбирает все записи, где устаревшие = 1.

Причина, по которой это будет работать быстро, заключается в том, что синтаксические анализаторы SQL, такие как PHP, не должны выполнять вторую половину оператора AND, если первая половина возвращает true, что делает его очень быстрым по всему списку, проверяя все записи , пытаясь сделать их несвежими, если они уже не несвежие. Если он уже устарел, алгоритм не будет выполнен, что сэкономит ваше время. Если это не так, алгоритм будет запущен, чтобы увидеть, не устарел ли он, и тогда он будет установлен в 1.

Затем второй запрос просто возвращает все устаревшие записи, где stale = 1.

0 голосов
/ 21 марта 2012

Я думаю, что фундаментальные вопросы необходимо решить, прежде чем думать о базах данных и коде.Основной из них: «Почему IsStale () работает медленно?»

Из комментариев в других местах ясно, что концепция, что это медленно, не подлежит обсуждению.Это вычисление из ваших рук?Являются ли результаты устойчивыми к кешированию?Какой уровень изменений запускает повторное вычисление.

Записав системы планирования в прошлом, есть два типа изменений: те, которые могут происходить внутри провисания, и те, которые вызывают каскадные изменения расписания.Аналогично, существует два типа перестроений: полное и локальное.Полные перестройки очевидны;локальные перестройки пытаются минимизировать «ущерб» другим запланированным ресурсам.

Вот суть вопроса: если у вас есть полное перестроение при каждом обновлении, вы можете наблюдать 30-минутные задержки с момента изменения до времени, когда расписание стабильно.(Я основываю это на своем опыте с перестройкой системы ERP с очень сложной рабочей нагрузкой).

Если реальность вашей системы состоит в том, что такие задачи занимают 30 минут, достижение цели мгновенного удовлетворения ваших пользователей противоречит основополагающей истине.Тем не менее, вы можете обнаружить несоответствие графика гораздо быстрее, чем перестроить.В этом случае вы могли бы показать пользователю «расписание было переполнено, пересчитано новое время окончания» или что-то подобное ... но я подозреваю, что если у вас будет много изменений в расписании, вводимых разными пользователями одновременно, система будет ухудшатьсяв одном непрерывном отображении этого уведомления.Однако вы, по крайней мере, получаете преимущество, заключающееся в том, что вы можете пакетно вносить изменения, происходящие в течение определенного периода времени для следующей перестройки.

Именно по этой причине большинство проблем с расписанием, которые я видел, на самом деле не имеют реального значенияпересчет времени.В контексте ситуации с ERP существует мастер-график, который отвечает за планирование работы цеха, и любые изменения проходят через них.«Главное» расписание обновлялось перед каждой сменой (смены составляли 12 часов, то есть два раза в день), и во время смены задержки обрабатывались с помощью «локальных» модификаций, которые не перемешивали основное расписание до следующего 12-часового блока.

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

Короче говоря, я думаю, что, возможно, это момент "не задать вопрос", когда предположение должно бытьвызов.Если пересчет достаточно велик, чтобы непрерывные обновления были нецелесообразны, тогда необходимо привести ожидания в соответствие с реальностью.Либо алгоритм нуждается в работе (оптимизация под локальные изменения), либо аппаратная ферма нуждается в расширении, либо необходимо перекалибровать время ожидания «истины».

Более точный ответ, откровенно говоря, потребовал бы больше подробностей, чем «просто предположить дорогостоящий процесс», потому что невозможно определить правильные точки атаки на этот процесс.

0 голосов
/ 12 марта 2012

Вы можете сделать это:

В базе данных изменять метку времени каждый раз, когда пользователь получает доступ к проекту.Когда пользователь входит в систему, вытащить все свои проекты.Проверьте временную метку и сравните ее с сегодняшней датой, если она старше n-дней, добавьте ее в устаревший список.Я не верю, что сравнение дат приведет к медленной логике.

...