Каков рекомендуемый способ создания функциональности, подобный «Inbox» от Stackoverflow?

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

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

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

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

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

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

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

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

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

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

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

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

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

Недостатки

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

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

Сильные стороны: у пользователя много проектов. В проекте много пользователей

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

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

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

Сильные стороны: у пользователя много проектов. В проекте много пользователей. У пользователя есть много уведомлений. В уведомлениях есть один пользователь. В проекте много уведомлений. Уведомление имеет один проект.

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

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

  1. Для каждой записи пользователя добавьте поле datetime sayng в последний раз, когда было выполнено медленное вычисление. Назовите это LastDate .
  2. Для каждого проекта добавьте логическое значение, чтобы сказать, нужно ли его указывать. Назовите это: Выбрано
  3. Когда вы запустите установку «Медленная», вы обновите выбранные файлы
  4. Теперь, когда пользователь регистрируется, если LastDate достаточно близко, вы используете результаты последнего медленного вычисления и просто выполняете весь проект с помощью Selected true. В противном случае yourun снова медленное вычисление. Вышеуказанная процедура является оптимальной, потому что она повторно вычисляет медленную процедуру ТОЛЬКО, ЕСЛИ НАСТОЯТЕЛЬНО НЕОБХОДИМА, при выполнении процедуры с фиксированными интервалами времени … имеет риск потерять время, потому что, возможно, пользователь будет использовать результат вычисления.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Время ожидания IO для SQL Server 2005 (тип ожидания ASYNC_NETWORK_IO) Проблема
  • Lucene.Net, SQL Server, NHibernate, ASP.NET MVC
  • NHibernate: Настроить () в каждом запросе страницы?
  • Почему LINK не поддерживает простые внешние соединения (с учетом предложения where на внешней объединенной таблице)?
  • Операции NHibernate: Является ли заказ INSERT-UPDATE_DELETE для партии документированным где-то?
  • QueryOver найти строку псевдонима
  • C # Nhibernate Сохранить список
  • Использование NHibernate с древней базой данных с некоторыми «динамическими» таблицами
  • Загрузка файла ASP.NET MVC 3 из базы данных
  • Моделирование общих отношений (выраженных в C #) в базе данных
  • Почему таймаут может произойти в SqlConnection.Open ()?
  • Давайте будем гением компьютера.