Repository: Kinto/kinto

Issue:
GET on default bucket increases quota usage
While investigating #1225, I discovered that *every* GET request to e.g. `/buckets/default/collections/some-collection` causes quota usage to increase. For example,

```
select * from records where collection_id='quota';
       id        |                                    parent_id                 
                   | collection_id |       last_modified        |               
                data                                
-----------------+--------------------------------------------------------------
-------------------+---------------+----------------------------+---------------
----------------------------------------------------
 bucket_info     | /buckets/74f86a68-a03c-a5f5-fb29-e421b362f5b5                
                   | quota         | 2017-05-22 18:07:14.715782 | {"record_count
": 0, "storage_size": 1745, "collection_count": 13}
 collection_info | /buckets/74f86a68-a03c-a5f5-fb29-e421b362f5b5/collections/a-n
ewest-collection-3 | quota         | 2017-05-22 18:07:14.716923 | {"record_count
": 0, "storage_size": 540}
```

```
> http --auth 'user:pass6' 'localhost:8888/v1/buckets/default/collections/a-newest-collection-3'
HTTP/1.1 200 OK
..... more junk .....
```

```
select * from records where collection_id='quota';
       id        |                                    parent_id                 
                   | collection_id |       last_modified        |               
                data                                
-----------------+--------------------------------------------------------------
-------------------+---------------+----------------------------+---------------
----------------------------------------------------
 bucket_info     | /buckets/74f86a68-a03c-a5f5-fb29-e421b362f5b5                
                   | quota         | 2017-05-22 18:56:52.448115 | {"record_count
": 0, "storage_size": 1880, "collection_count": 14}
 collection_info | /buckets/74f86a68-a03c-a5f5-fb29-e421b362f5b5/collections/a-n
ewest-collection-3 | quota         | 2017-05-22 18:56:52.4493   | {"record_count
": 0, "storage_size": 600}
```

This appears to be partly because every request that goes to the default bucket "creates" a bucket and collection.


Discussion:

Resolving patch:
diff --git a/kinto/plugins/default_bucket/__init__.py b/kinto/plugins/default_bucket/__init__.py
--- a/kinto/plugins/default_bucket/__init__.py
+++ b/kinto/plugins/default_bucket/__init__.py
@@ -6,6 +6,7 @@
 
 from kinto.core.errors import raise_invalid
 from kinto.core.events import ACTIONS
+from kinto.core.storage.exceptions import UnicityError
 from kinto.core.utils import (
     build_request, reapply_cors, hmac_digest, instance_uri, view_lookup)
 
@@ -100,7 +101,12 @@ def resource_create_object(request, resource_cls, uri):
         raise_invalid(resource.request, **error_details)
 
     data = {'id': obj_id}
-    obj = resource.model.create_record(data, ignore_conflict=True)
+    try:
+        obj = resource.model.create_record(data)
+    except UnicityError as e:
+        # The record already exists; skip running events
+        return e.record
+
     # Since the current request is not a resource (but a straight Service),
     # we simulate a request on a resource.
     # This will be used in the resource event payload.


Test patch:
diff --git a/tests/plugins/test_default_bucket.py b/tests/plugins/test_default_bucket.py
--- a/tests/plugins/test_default_bucket.py
+++ b/tests/plugins/test_default_bucket.py
@@ -338,6 +338,20 @@ def test_events_sent_on_bucket_and_collection_creation(self):
         assert _events[2].payload['uri'] == records_uri.replace('default',
                                                                 bucket_id)
 
+    def test_second_call_on_default_bucket_doesnt_send_create_events(self):
+        bucket_url = '/buckets/default'
+        self.app.get(bucket_url, headers=self.headers)
+        assert len(_events) == 1
+        self.app.get(bucket_url, headers=self.headers)
+        assert len(_events) == 1
+
+    def test_second_call_on_default_bucket_collection_doesnt_send_create_events(self):
+        collection_url = '/buckets/default/collections/articles'
+        self.app.get(collection_url, headers=self.headers)
+        assert len(_events) == 2
+        self.app.get(collection_url, headers=self.headers)
+        assert len(_events) == 2
+
 
 class ReadonlyDefaultBucket(DefaultBucketWebTest):