Как правильно рассчитать кредит в коммерческом чате?

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

Таймер начинает отсчет в начале сеанса чата, и пользователи через регулярные промежутки времени уведомляются об общем времени, которое они проводят в чате, и текущих общих кредитах текущего сеанса чата. Эти расчеты должны производиться на стороне сервера и сохраняться в базе данных. Кстати, сеанс чата может быть приостановлен/возобновлен экспертом.


Вот простой сценарий...
Текущий пользователь имеет: 10 кредитов
"Эксперт А" требует 2 кредита в минуту

CurrentTime Event       Timer       Credit
  • 10:40 Начало сеанса чата 00:01 мин 2credits
  • 10:41 Они болтают 00:02 мин 4credits
  • 10:42 Эксперт в простое 00:02 мин 4credits (пауза в чате)
  • 10:45 Эксперт становится онлайн 00:02 мин 4credits (Чат возобновляется)
  • 10:46 Они болтают 00:03 мин 6credits
  • 10:46 Клиент завершает сеанс 00:04 мин 8credits

С клиента взимается плата в размере 8 кредитов. У него осталось 2 кредита.

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


Мой вопрос заключается в том, как правильно выполнять эти расчеты на стороне сервера для каждого сеанса чата, о котором идет речь в данный момент?

Мой текущий подход:

Таймер на стороне сервера срабатывает каждые 15 секунд, получает данные о текущих сеансах чата,

Для каждого сеанса чата: если сеанс чата не приостановлен, то добавляет 15 секунд к промежутку времени сеанса, а затем вычисляет общее количество кредитов текущего сеанса, если у пользователя вот-вот закончатся кредиты, уведомляет его, если он уже запущен закончился, затем завершите текущий сеанс чата. Сохраните эти транзакции в базе данных. Обновите клиенты сеанса чата.

Но есть некоторые подводные камни в этом подходе. Например, если сеанс чата начался сейчас и таймер отсчитывает 2 секунды, то он добавляет 15 секунд к общему промежутку времени текущего сеанса чата, что приводит к просчету. Если я уменьшу интервал таймера, то может быть 500 текущих сеансов чата, и интервала таймера будет недостаточно для расчета кредитов каждого сеанса чата, например, за 10 секунд.

Есть ли лучший способ справиться с этим? Все предложения приветствуются.

Кстати, я использую Asp.net MVC4 C# и Signalr для обработки чата в реальном времени.

Заранее спасибо.


person Fevzi Apaydın    schedule 17.04.2013    source источник
comment
Похоже, вам нужно получить точную оценку времени начала/остановки/паузы/возобновления чата. Если используемая вами система чата не обеспечивает этого, то, возможно, каждую секунду (или несколько секунд) вы можете хранить список всех активных сеансов чата и использовать эти данные каждые 15 секунд для выполнения более дорогостоящей работы по полной обработке. все. Имейте в виду, что если вы не можете обработать свою текущую нагрузку за 10 секунд, то ее нужно увеличить только на 50%, и вы также не сможете сделать это за 15 секунд. Поэтому вскоре вам, возможно, придется подумать о том, чтобы сделать его более эффективным или каким-либо иным образом увеличить емкость.   -  person Steve Jessop    schedule 17.04.2013
comment
Зачем выполнять эти вычисления в пакетном режиме? Я думаю, было бы намного проще сделать его управляемым событиями: каждые n раз сообщение отправляется через программу чата (либо от эксперта, либо от пользователя), проверяйте общее затраченное время и подсчитывайте кредиты и действуйте. соответственно на них оттуда. Таким образом, анализ выполняется для каждого сеанса чата, он более точен и легче масштабируется, чем массовый анализ всех сеансов.   -  person Scott Mermelstein    schedule 17.04.2013
comment
@ScottMermelstein Существует множество разных случаев, например, если эксперт не пишет в течение 2 минут или более, приостановите сеанс чата. Так что я должен использовать таймер, я думаю. Вероятно, я не смогу определить, закончился ли у пользователя кредит, если кто-то не пишет в течение 2 минут при вашем подходе.   -  person Fevzi Apaydın    schedule 17.04.2013
comment
Вы можете сделать чат с одной или другой стороны ведущим для подсчета времени. Если пользователь задает вопрос, а эксперт не отвечает, никакой платы взиматься не должно. Как только эксперт ответит, вы можете использовать метку времени этого ответа для расчета текущей продолжительности чата и т. д.   -  person Chris Pratt    schedule 17.04.2013


Ответы (1)


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

Как я предположил в комментариях, часть этого влечет за собой просто точное вычисление использованного времени. Это легко сделать — сохранить время начала (или время начала эксперта, в зависимости от ваших предпочтений), вычесть его из времени окончания и соответственно выставить счет.

Проблемы, которые это может вызвать:

  • Когда наступает время окончания? Это время, когда программа чата закрывается либо из-за тайм-аута сеанса, либо из-за окончания сеанса эксперта, либо из-за завершения пользователя. В зависимости от вашей структуры выставления счетов я бы рекомендовал, чтобы время окончания в этом контексте также включало паузу сеанса. В целях расчета затрат каждую итерацию запуска-паузы можно учитывать отдельно (хотя в идеале они должны быть сгруппированы вместе в сводке счетов). Вы можете проверять каждый раз, когда сообщение отправляется, чтобы узнать, есть ли у пользователя кредит.
  • What about idle time? How do we account for the user idling for more time than they have, between messages? It shouldn't matter, really. Next time a message is sent, you can tell them they're past due. They may get annoyed that they spent a few minutes typing a message that won't get sent, but there are ways to avoid that.
    • If you do check the billing every time a message is sent, it's easy to note when they're running low, and issue a warning.
    • Вот совершенно другой способ выставления счетов: после начала сеанса ваш сервер может рассчитать на основе скорости и баланса продолжительность сеанса. Если до этого не было события остановки или паузы, вы точно знаете, когда у них закончатся кредиты, и если есть возобновление после паузы, вы можете пересчитать на основе оставшегося времени.

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

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

В противном случае, если вам нужно отправлять уведомления для времени и баланса, я бы все равно сделал это на индивидуальной основе, а не в массовых операциях. Вы можете обновлять каждое сообщение и добавлять таймер для каждого чата. Сбрасывайте таймер каждый раз, когда приходит сообщение, в противном случае, когда таймер срабатывает, отправьте обновление времени и баланса. Или, если у вас нет ресурсов для такого количества таймеров, проделайте ту же идею с отсортированным списком — обновляйте список каждый раз, когда есть активность, и сортируйте его по последнему активному времени + 15 секунд. Тем, кто находится в верхней части списка, может потребоваться обновление времени и баланса.

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

person Scott Mermelstein    schedule 17.04.2013
comment
Спасибо, Скотт, за подробное описание решения. Ваше решение с отсортированным списком, вероятно, не будет хорошим способом, поскольку клиенты не будут покупать кредиты для каждого сеанса чата. Они могут потреблять свои кредиты столько, сколько они хотят. Я добавил простой сценарий на свой вопрос. Мой подход не имеет смысла, поскольку он не масштабируется, как вы сказали. У меня были опасения по поводу добавления таймера для каждого чата, но я подумаю об этом. - person Fevzi Apaydın; 18.04.2013
comment
Я не буду слишком настаивать на этом, но я хочу упомянуть, что мое решение не предполагает, что кредиты покупаются за сеанс чата. Просто учитывая количество кредитов, которые есть у пользователя, и стоимость сеанса, вы можете рассчитать максимальное доступное время. В вашем примере сценария вы можете сказать в начале сеанса, что у пользователя будет максимум 5 активных минут с экспертом. Я не уверен, что с этим делать, но также приятно видеть, что вы платите за минуту. В этом случае достаточно 15-секундной точности, и вам просто нужно беспокоиться о масштабируемости. - person Scott Mermelstein; 18.04.2013