diff options
author | Victor Shyba <victor1984@riseup.net> | 2017-11-11 01:48:16 -0300 |
---|---|---|
committer | Victor Shyba <victor1984@riseup.net> | 2017-11-13 18:17:16 -0300 |
commit | 1d4f43570345fc644b42a96dfd70cd72435f55fd (patch) | |
tree | 9bea2f2e10b5562bff28fa30c6a5ba5387d2bd33 | |
parent | 8f3fdc2f9c3d4360669c2c7fd89dbd95e0f8dd22 (diff) |
[feature] support unsynced local_only blobs
Adds the ability to have document that wont be synced. This enables
applications to use soledad to store temporary blobs that should be
discarded later instead of unnecessarily keeping the sync loop busy.
-- Resolves: #8819
-rw-r--r-- | src/leap/soledad/client/_db/blobs/__init__.py | 12 | ||||
-rw-r--r-- | src/leap/soledad/client/_db/blobs/sql.py | 1 | ||||
-rw-r--r-- | src/leap/soledad/client/_db/blobs/sync.py | 4 | ||||
-rw-r--r-- | tests/blobs/test_blob_manager.py | 13 |
4 files changed, 27 insertions, 3 deletions
diff --git a/src/leap/soledad/client/_db/blobs/__init__.py b/src/leap/soledad/client/_db/blobs/__init__.py index a5b7d6e3..3c7492c6 100644 --- a/src/leap/soledad/client/_db/blobs/__init__.py +++ b/src/leap/soledad/client/_db/blobs/__init__.py @@ -207,7 +207,7 @@ class BlobManager(BlobsSynchronizer): def local_list_status(self, status, namespace=''): return self.local.list_status(status, namespace) - def put(self, doc, size, namespace=''): + def put(self, doc, size, namespace='', local_only=False): """ Put a blob in local storage and upload it to server. @@ -215,14 +215,16 @@ class BlobManager(BlobsSynchronizer): :type doc: leap.soledad.client._document.BlobDoc :param size: The size of the blob. :type size: int + :param local_only: Avoids sync (doesn't send to server). + :type local_only: bool :param namespace: Optional parameter to restrict operation to a given namespace. :type namespace: str """ - return self.semaphore.run(self._put, doc, size, namespace) + return self.semaphore.run(self._put, doc, size, namespace, local_only) @defer.inlineCallbacks - def _put(self, doc, size, namespace): + def _put(self, doc, size, namespace, local_only=False): if (yield self.local.exists(doc.blob_id, namespace=namespace)): error_message = "Blob already exists: %s" % doc.blob_id raise BlobAlreadyExistsError(error_message) @@ -230,6 +232,10 @@ class BlobManager(BlobsSynchronizer): # TODO this is a tee really, but ok... could do db and upload # concurrently. not sure if we'd gain something. yield self.local.put(doc.blob_id, fd, size=size, namespace=namespace) + if local_only: + yield self.local.update_sync_status( + doc.blob_id, SyncStatus.LOCAL_ONLY) + defer.returnValue(None) yield self.local.update_sync_status( doc.blob_id, SyncStatus.PENDING_UPLOAD) # In fact, some kind of pipe is needed here, where each write on db diff --git a/src/leap/soledad/client/_db/blobs/sql.py b/src/leap/soledad/client/_db/blobs/sql.py index 5337ab87..ebd6c095 100644 --- a/src/leap/soledad/client/_db/blobs/sql.py +++ b/src/leap/soledad/client/_db/blobs/sql.py @@ -42,6 +42,7 @@ class SyncStatus: FAILED_UPLOAD = 4 FAILED_DOWNLOAD = 5 PENDING_DELETE = 6 + LOCAL_ONLY = 7 UNAVAILABLE_STATUSES = (3, 5) diff --git a/src/leap/soledad/client/_db/blobs/sync.py b/src/leap/soledad/client/_db/blobs/sync.py index bdfbb983..3ee60305 100644 --- a/src/leap/soledad/client/_db/blobs/sync.py +++ b/src/leap/soledad/client/_db/blobs/sync.py @@ -77,6 +77,10 @@ class BlobsSynchronizer(object): remote_deletions = self.remote_list(namespace=namespace, deleted=True) remote_deletions = yield remote_deletions yield self.local.batch_delete(remote_deletions) + yield self.local.update_batch_sync_status( + remote_deletions, + SyncStatus.SYNCED, + namespace=namespace) @defer.inlineCallbacks def send_missing(self, namespace=''): diff --git a/tests/blobs/test_blob_manager.py b/tests/blobs/test_blob_manager.py index 58f99790..c7bbb0d3 100644 --- a/tests/blobs/test_blob_manager.py +++ b/tests/blobs/test_blob_manager.py @@ -83,6 +83,19 @@ class BlobManagerTestCase(unittest.TestCase): @defer.inlineCallbacks @pytest.mark.usefixtures("method_tmpdir") + def test_put_local_only_doesnt_send_to_server(self): + self.manager._encrypt_and_upload = Mock(return_value=None) + msg, blob_id = "Hey Joe", uuid4().hex + doc = BlobDoc(BytesIO(msg), blob_id=blob_id) + yield self.manager.put(doc, size=len(msg), local_only=True) + result = yield self.manager.local.get(blob_id) + status, _ = yield self.manager.local.get_sync_status(blob_id) + self.assertEquals(result.getvalue(), msg) + self.assertEquals(status, SyncStatus.LOCAL_ONLY) + self.assertFalse(self.manager._encrypt_and_upload.called) + + @defer.inlineCallbacks + @pytest.mark.usefixtures("method_tmpdir") def test_put_then_get_using_real_file_descriptor(self): self.manager._encrypt_and_upload = Mock(return_value=None) self.manager._download_and_decrypt = Mock(return_value=None) |