Implement long polling using Tornado.

(imported from commit 4385304b27d7fe55a57a23133cd214fe8fc33482)
This commit is contained in:
Tim Abbott
2012-08-28 16:56:21 -04:00
parent 9714cf920e
commit 9afd63692f
6 changed files with 437 additions and 41 deletions

View File

@@ -16,10 +16,31 @@ def get_display_recipient(recipient):
user = User.objects.get(pk=recipient.user_or_class)
return user.username
callback_table = {}
class UserProfile(models.Model):
user = models.OneToOneField(User)
pointer = models.IntegerField()
# The user receives this message
def receive(self, message):
global callback_table
# Should also store in permanent database the receipt
for cb in callback_table.get(self.user.id, []):
cb([message])
callback_table[self.user.id] = []
def add_callback(self, cb, last_received):
global callback_table
# This filter should also restrict to the current user's subs
new_zephyrs = Zephyr.objects.filter(id__gt=last_received)
if new_zephyrs:
return cb(new_zephyrs)
callback_table.setdefault(self.user.id, []).append(cb)
def __repr__(self):
return "<UserProfile: %s>" % (self.user.username,)
@@ -55,9 +76,36 @@ class Zephyr(models.Model):
display_recipient = get_display_recipient(self.recipient)
return "<Zephyr: %s / %s / %r>" % (display_recipient, self.instance, self.sender)
def send_zephyr(**kwargs):
zephyr = kwargs["instance"]
if zephyr.recipient.type == "personal":
recipients = UserProfile.objects.filter(user=zephyr.recipient.user_or_class)
assert(len(recipients) == 1)
elif zephyr.recipient.type == "class":
recipients = [UserProfile.objects.get(user=s.userprofile_id) for
s in Subscription.objects.filter(recipient_id=zephyr.recipient)]
else:
raise
for recipient in recipients:
recipient.receive(zephyr)
post_save.connect(send_zephyr, sender=Zephyr)
class Subscription(models.Model):
userprofile_id = models.ForeignKey(UserProfile)
recipient_id = models.ForeignKey(Recipient)
def __repr__(self):
return "<Subscription: %r -> %r>" % (self.userprofile_id, self.recipient_id)
def filter_by_subscriptions(zephyrs, user):
userprofile = UserProfile.objects.get(user=user)
subscribed_zephyrs = []
subscriptions = [sub.recipient_id for sub in Subscription.objects.filter(userprofile_id=userprofile)]
for zephyr in zephyrs:
# If you are subscribed to the personal or class, or if you sent the personal, you can see the zephyr.
if (zephyr.recipient in subscriptions) or \
(zephyr.recipient.type == "personal" and zephyr.sender == userprofile):
subscribed_zephyrs.append(zephyr)
return subscribed_zephyrs