Uma implementação semelhante ao Stackoverflow é, na verdade, muito mais simples do que você descreveu, com base em bits de informação descartados pela equipe de vez em quando.
No banco de dados, você simplesmente armazena uma coleção de
BadgeID
-UserID
pares para rastrear quem tem o quê (e uma contagem ou um rowID para permitir vários prêmios para alguns emblemas). No aplicativo, há um objeto trabalhador para cada tipo de crachá. O objeto está em cache e, quando o cache expira, o trabalhador executa sua própria lógica para determinar quem deve obter o emblema e fazer as atualizações e, em seguida, reinsere-se no cache:
public abstract class BadgeJob
{
protected BadgeJob()
{
//start cycling on initialization
Insert();
}
//override to provide specific badge logic
protected abstract void AwardBadges();
//how long to wait between iterations
protected abstract TimeSpan Interval { get; }
private void Callback(string key, object value, CacheItemRemovedReason reason)
{
if (reason == CacheItemRemovedReason.Expired)
{
this.AwardBadges();
this.Insert();
}
}
private void Insert()
{
HttpRuntime.Cache.Add(this.GetType().ToString(),
this,
null,
Cache.NoAbsoluteExpiration,
this.Interval,
CacheItemPriority.Normal,
this.Callback);
}
}
E uma implementação concreta:
public class CommenterBadge : BadgeJob
{
public CommenterBadge() : base() { }
protected override void AwardBadges()
{
//select all users who have more than x comments
//and dont have the commenter badge
//add badges
}
//run every 10 minutes
protected override TimeSpan Interval
{
get { return new TimeSpan(0,10,0); }
}
}