mirror of
https://github.com/jazzband/django-ddp.git
synced 2026-05-24 07:03:48 +00:00
Fix generation of meteor ID's to match meteor client implementation.
This commit is contained in:
parent
7dea154d0d
commit
41c544dadb
6 changed files with 78 additions and 12 deletions
|
|
@ -52,16 +52,44 @@ class ThreadLocal(local):
|
|||
def get(self, name, factory, *factory_args, **factory_kwargs):
|
||||
"""Get attribute, creating if required using specified factory."""
|
||||
if not hasattr(self, name):
|
||||
return setattr(self, name, factory(*factory_args, **factory_kwargs))
|
||||
obj = factory(*factory_args, **factory_kwargs)
|
||||
setattr(self, name, obj)
|
||||
return obj
|
||||
return getattr(self, name)
|
||||
|
||||
|
||||
THREAD_LOCAL = ThreadLocal(alea_random=alea.Alea)
|
||||
class RandomStreams(object):
|
||||
|
||||
def __init__(self):
|
||||
self._streams = {}
|
||||
self._seed = THREAD_LOCAL.alea_random.hex_string(20)
|
||||
|
||||
def get_seed(self):
|
||||
return self._seed
|
||||
def set_seed(self, val):
|
||||
self._streams = {}
|
||||
self._seed = val
|
||||
random_seed = property(get_seed, set_seed)
|
||||
|
||||
def __getitem__(self, key):
|
||||
if key not in self._streams:
|
||||
return self._streams.setdefault(key, alea.Alea(self._seed, key))
|
||||
return self._streams[key]
|
||||
|
||||
|
||||
THREAD_LOCAL = ThreadLocal(
|
||||
alea_random=alea.Alea,
|
||||
random_streams=RandomStreams,
|
||||
)
|
||||
METEOR_ID_CHARS = u'23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz'
|
||||
|
||||
|
||||
def meteor_random_id():
|
||||
return THREAD_LOCAL.alea_random.random_string(17, METEOR_ID_CHARS)
|
||||
def meteor_random_id(name=None):
|
||||
if name is None:
|
||||
stream = THREAD_LOCAL.alea_random
|
||||
else:
|
||||
stream = THREAD_LOCAL.random_streams[name]
|
||||
return stream.random_string(17, METEOR_ID_CHARS)
|
||||
|
||||
|
||||
def autodiscover():
|
||||
|
|
|
|||
|
|
@ -155,6 +155,11 @@ class Alea(object):
|
|||
self.choice(alphabet) for n in range(length)
|
||||
)
|
||||
|
||||
def hex_string(self, digits):
|
||||
"""Return a hex string of `digits` length."""
|
||||
return self.random_string(digits, '0123456789abcdef')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
|
|
|||
20
dddp/migrations/0003_auto_20150413_1328.py
Normal file
20
dddp/migrations/0003_auto_20150413_1328.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('dddp', '0002_auto_20150408_0321'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='objectmapping',
|
||||
name='object_id',
|
||||
field=models.CharField(max_length=255),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
from django.db import models, transaction
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
import ejson
|
||||
from dddp import meteor_random_id
|
||||
|
|
@ -12,12 +13,22 @@ from dddp import meteor_random_id
|
|||
def get_meteor_id(obj):
|
||||
"""Return an Alea ID for the given object."""
|
||||
# Django model._meta is now public API -> pylint: disable=W0212
|
||||
content_type = ContentType.objects.get_for_model(obj._meta.model)
|
||||
mapping, _ = ObjectMapping.objects.get_or_create(
|
||||
content_type=content_type,
|
||||
object_id=obj.pk,
|
||||
)
|
||||
return mapping.meteor_id
|
||||
meta = obj._meta
|
||||
obj_pk = str(obj.pk)
|
||||
content_type = ContentType.objects.get_for_model(meta.model)
|
||||
try:
|
||||
return ObjectMapping.objects.values_list(
|
||||
'meteor_id', flat=True,
|
||||
).get(
|
||||
content_type=content_type,
|
||||
object_id=obj_pk,
|
||||
)
|
||||
except ObjectDoesNotExist:
|
||||
return ObjectMapping.objects.create(
|
||||
content_type=content_type,
|
||||
object_id=obj_pk,
|
||||
meteor_id=meteor_random_id('/collection/%s' % meta),
|
||||
).meteor_id
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
|
|
@ -51,7 +62,7 @@ class ObjectMapping(models.Model):
|
|||
|
||||
meteor_id = AleaIdField()
|
||||
content_type = models.ForeignKey(ContentType, db_index=True)
|
||||
object_id = models.PositiveIntegerField()
|
||||
object_id = models.CharField(max_length=255)
|
||||
# content_object = GenericForeignKey('content_type', 'object_id')
|
||||
|
||||
def __str__(self):
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from django.db import connections
|
|||
from django.utils.module_loading import import_string
|
||||
|
||||
from dddp.api import collection_name
|
||||
from dddp.models import Subscription
|
||||
from dddp.models import get_meteor_id, Subscription
|
||||
from dddp.msg import obj_change_as_msg
|
||||
|
||||
|
||||
|
|
@ -49,6 +49,7 @@ def send_notify(model, obj, msg, using):
|
|||
sub_ids.add(sub.sub_id)
|
||||
|
||||
if not sub_ids:
|
||||
get_meteor_id(obj) # force creation of meteor ID using randomSeed
|
||||
return # no subscribers for this object, nothing more to do.
|
||||
|
||||
name, payload = obj_change_as_msg(obj, msg)
|
||||
|
|
|
|||
|
|
@ -306,6 +306,7 @@ class DDPWebSocketApplication(geventwebsocket.WebSocketApplication):
|
|||
def recv_method(self, method, params, id_, randomSeed=None):
|
||||
"""DDP method handler."""
|
||||
if randomSeed is not None:
|
||||
this.random_streams.random_seed = randomSeed
|
||||
this.alea_random = alea.Alea(randomSeed)
|
||||
API.method(method, params, id_)
|
||||
self.reply('updated', methods=[id_])
|
||||
|
|
|
|||
Loading…
Reference in a new issue