Merge pull request #1031 from MRigal/fix/1011-capped-collection-size-multiple-of-256
CappedCollection max_size normalized to multiple of 256
This commit is contained in:
commit
4d5200c50f
@ -24,6 +24,7 @@ Changes in 0.9.X - DEV
|
|||||||
- Fixes some internal _id handling issue. #961
|
- Fixes some internal _id handling issue. #961
|
||||||
- Updated URL and Email Field regex validators, added schemes argument to URLField validation. #652
|
- Updated URL and Email Field regex validators, added schemes argument to URLField validation. #652
|
||||||
- Removed get_or_create() deprecated since 0.8.0. #300
|
- Removed get_or_create() deprecated since 0.8.0. #300
|
||||||
|
- Capped collection multiple of 256. #1011
|
||||||
|
|
||||||
Changes in 0.9.0
|
Changes in 0.9.0
|
||||||
================
|
================
|
||||||
|
@ -447,8 +447,10 @@ A :class:`~mongoengine.Document` may use a **Capped Collection** by specifying
|
|||||||
:attr:`max_documents` and :attr:`max_size` in the :attr:`meta` dictionary.
|
:attr:`max_documents` and :attr:`max_size` in the :attr:`meta` dictionary.
|
||||||
:attr:`max_documents` is the maximum number of documents that is allowed to be
|
:attr:`max_documents` is the maximum number of documents that is allowed to be
|
||||||
stored in the collection, and :attr:`max_size` is the maximum size of the
|
stored in the collection, and :attr:`max_size` is the maximum size of the
|
||||||
collection in bytes. If :attr:`max_size` is not specified and
|
collection in bytes. :attr:`max_size` is rounded up to the next multiple of 256
|
||||||
:attr:`max_documents` is, :attr:`max_size` defaults to 10000000 bytes (10MB).
|
by MongoDB internally and mongoengine before. Use also a multiple of 256 to
|
||||||
|
avoid confusions. If :attr:`max_size` is not specified and
|
||||||
|
:attr:`max_documents` is, :attr:`max_size` defaults to 10485760 bytes (10MB).
|
||||||
The following example shows a :class:`Log` document that will be limited to
|
The following example shows a :class:`Log` document that will be limited to
|
||||||
1000 entries and 2MB of disk space::
|
1000 entries and 2MB of disk space::
|
||||||
|
|
||||||
|
@ -114,9 +114,11 @@ class Document(BaseDocument):
|
|||||||
specifying :attr:`max_documents` and :attr:`max_size` in the :attr:`meta`
|
specifying :attr:`max_documents` and :attr:`max_size` in the :attr:`meta`
|
||||||
dictionary. :attr:`max_documents` is the maximum number of documents that
|
dictionary. :attr:`max_documents` is the maximum number of documents that
|
||||||
is allowed to be stored in the collection, and :attr:`max_size` is the
|
is allowed to be stored in the collection, and :attr:`max_size` is the
|
||||||
maximum size of the collection in bytes. If :attr:`max_size` is not
|
maximum size of the collection in bytes. :attr:`max_size` is rounded up
|
||||||
|
to the next multiple of 256 by MongoDB internally and mongoengine before.
|
||||||
|
Use also a multiple of 256 to avoid confusions. If :attr:`max_size` is not
|
||||||
specified and :attr:`max_documents` is, :attr:`max_size` defaults to
|
specified and :attr:`max_documents` is, :attr:`max_size` defaults to
|
||||||
10000000 bytes (10MB).
|
10485760 bytes (10MB).
|
||||||
|
|
||||||
Indexes may be created by specifying :attr:`indexes` in the :attr:`meta`
|
Indexes may be created by specifying :attr:`indexes` in the :attr:`meta`
|
||||||
dictionary. The value should be a list of field names or tuples of field
|
dictionary. The value should be a list of field names or tuples of field
|
||||||
@ -137,7 +139,7 @@ class Document(BaseDocument):
|
|||||||
By default, any extra attribute existing in stored data but not declared
|
By default, any extra attribute existing in stored data but not declared
|
||||||
in your model will raise a :class:`~mongoengine.FieldDoesNotExist` error.
|
in your model will raise a :class:`~mongoengine.FieldDoesNotExist` error.
|
||||||
This can be disabled by setting :attr:`strict` to ``False``
|
This can be disabled by setting :attr:`strict` to ``False``
|
||||||
in the :attr:`meta` dictionnary.
|
in the :attr:`meta` dictionary.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# The __metaclass__ attribute is removed by 2to3 when running with Python3
|
# The __metaclass__ attribute is removed by 2to3 when running with Python3
|
||||||
@ -176,8 +178,11 @@ class Document(BaseDocument):
|
|||||||
# Create collection as a capped collection if specified
|
# Create collection as a capped collection if specified
|
||||||
if cls._meta.get('max_size') or cls._meta.get('max_documents'):
|
if cls._meta.get('max_size') or cls._meta.get('max_documents'):
|
||||||
# Get max document limit and max byte size from meta
|
# Get max document limit and max byte size from meta
|
||||||
max_size = cls._meta.get('max_size') or 10000000 # 10MB default
|
max_size = cls._meta.get('max_size') or 10 * 2 ** 20 # 10MB default
|
||||||
max_documents = cls._meta.get('max_documents')
|
max_documents = cls._meta.get('max_documents')
|
||||||
|
# Round up to next 256 bytes as MongoDB would do it to avoid exception
|
||||||
|
if max_size % 256:
|
||||||
|
max_size = (max_size // 256 + 1) * 256
|
||||||
|
|
||||||
if collection_name in db.collection_names():
|
if collection_name in db.collection_names():
|
||||||
cls._collection = db[collection_name]
|
cls._collection = db[collection_name]
|
||||||
|
@ -88,7 +88,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
options = Log.objects._collection.options()
|
options = Log.objects._collection.options()
|
||||||
self.assertEqual(options['capped'], True)
|
self.assertEqual(options['capped'], True)
|
||||||
self.assertEqual(options['max'], 10)
|
self.assertEqual(options['max'], 10)
|
||||||
self.assertTrue(options['size'] >= 4096)
|
self.assertEqual(options['size'], 4096)
|
||||||
|
|
||||||
# Check that the document cannot be redefined with different options
|
# Check that the document cannot be redefined with different options
|
||||||
def recreate_log_document():
|
def recreate_log_document():
|
||||||
@ -103,6 +103,69 @@ class InstanceTest(unittest.TestCase):
|
|||||||
|
|
||||||
Log.drop_collection()
|
Log.drop_collection()
|
||||||
|
|
||||||
|
def test_capped_collection_default(self):
|
||||||
|
"""Ensure that capped collections defaults work properly.
|
||||||
|
"""
|
||||||
|
class Log(Document):
|
||||||
|
date = DateTimeField(default=datetime.now)
|
||||||
|
meta = {
|
||||||
|
'max_documents': 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.drop_collection()
|
||||||
|
|
||||||
|
# Create a doc to create the collection
|
||||||
|
Log().save()
|
||||||
|
|
||||||
|
options = Log.objects._collection.options()
|
||||||
|
self.assertEqual(options['capped'], True)
|
||||||
|
self.assertEqual(options['max'], 10)
|
||||||
|
self.assertEqual(options['size'], 10 * 2**20)
|
||||||
|
|
||||||
|
# Check that the document with default value can be recreated
|
||||||
|
def recreate_log_document():
|
||||||
|
class Log(Document):
|
||||||
|
date = DateTimeField(default=datetime.now)
|
||||||
|
meta = {
|
||||||
|
'max_documents': 10,
|
||||||
|
}
|
||||||
|
# Create the collection by accessing Document.objects
|
||||||
|
Log.objects
|
||||||
|
recreate_log_document()
|
||||||
|
Log.drop_collection()
|
||||||
|
|
||||||
|
def test_capped_collection_no_max_size_problems(self):
|
||||||
|
"""Ensure that capped collections with odd max_size work properly.
|
||||||
|
MongoDB rounds up max_size to next multiple of 256, recreating a doc
|
||||||
|
with the same spec failed in mongoengine <0.10
|
||||||
|
"""
|
||||||
|
class Log(Document):
|
||||||
|
date = DateTimeField(default=datetime.now)
|
||||||
|
meta = {
|
||||||
|
'max_size': 10000,
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.drop_collection()
|
||||||
|
|
||||||
|
# Create a doc to create the collection
|
||||||
|
Log().save()
|
||||||
|
|
||||||
|
options = Log.objects._collection.options()
|
||||||
|
self.assertEqual(options['capped'], True)
|
||||||
|
self.assertTrue(options['size'] >= 10000)
|
||||||
|
|
||||||
|
# Check that the document with odd max_size value can be recreated
|
||||||
|
def recreate_log_document():
|
||||||
|
class Log(Document):
|
||||||
|
date = DateTimeField(default=datetime.now)
|
||||||
|
meta = {
|
||||||
|
'max_size': 10000,
|
||||||
|
}
|
||||||
|
# Create the collection by accessing Document.objects
|
||||||
|
Log.objects
|
||||||
|
recreate_log_document()
|
||||||
|
Log.drop_collection()
|
||||||
|
|
||||||
def test_repr(self):
|
def test_repr(self):
|
||||||
"""Ensure that unicode representation works
|
"""Ensure that unicode representation works
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user