summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Shyba <victor1984@riseup.net>2017-11-11 00:37:01 -0300
committerVictor Shyba <victor1984@riseup.net>2017-11-13 18:17:15 -0300
commit8f3fdc2f9c3d4360669c2c7fd89dbd95e0f8dd22 (patch)
tree7d711a51d896811fe6309eb5a368ed468276a6d8
parent914579325d242e2643a964bbf1b271435b5c66cc (diff)
[feature] apply deletions from server
Sync method to propagate deletions in batch locally. -- Resolves: #8961
-rw-r--r--src/leap/soledad/client/_db/blobs/sql.py7
-rw-r--r--src/leap/soledad/client/_db/blobs/sync.py7
-rw-r--r--tests/server/test_blobs_server.py19
3 files changed, 33 insertions, 0 deletions
diff --git a/src/leap/soledad/client/_db/blobs/sql.py b/src/leap/soledad/client/_db/blobs/sql.py
index c5b0b64b..5337ab87 100644
--- a/src/leap/soledad/client/_db/blobs/sql.py
+++ b/src/leap/soledad/client/_db/blobs/sql.py
@@ -190,6 +190,13 @@ class SQLiteBlobBackend(object):
query = 'DELETE FROM blobs WHERE blob_id = ? AND namespace = ?'
return self.dbpool.runQuery(query, (blob_id, namespace,))
+ def batch_delete(self, blob_id_list, namespace=''):
+ query = 'DELETE FROM blobs WHERE blob_id IN '
+ size = len(blob_id_list)
+ query += ('(%s)' % ', '.join(['?' for _ in range(size)]))
+ values = tuple(blob_id_list)
+ return self.dbpool.runQuery(query, values)
+
def _init_tables(conn):
# unified init for running under the same lock
diff --git a/src/leap/soledad/client/_db/blobs/sync.py b/src/leap/soledad/client/_db/blobs/sync.py
index bfdc5fbe..bdfbb983 100644
--- a/src/leap/soledad/client/_db/blobs/sync.py
+++ b/src/leap/soledad/client/_db/blobs/sync.py
@@ -73,6 +73,12 @@ class BlobsSynchronizer(object):
namespace=namespace)
@defer.inlineCallbacks
+ def _apply_deletions_from_server(self, namespace=''):
+ remote_deletions = self.remote_list(namespace=namespace, deleted=True)
+ remote_deletions = yield remote_deletions
+ yield self.local.batch_delete(remote_deletions)
+
+ @defer.inlineCallbacks
def send_missing(self, namespace=''):
"""
Compare local and remote blobs and send what's missing in server.
@@ -131,6 +137,7 @@ class BlobsSynchronizer(object):
@defer.inlineCallbacks
def sync(self, namespace=''):
try:
+ yield self._apply_deletions_from_server(namespace)
yield self.refresh_sync_status_from_server(namespace)
yield self.fetch_missing(namespace)
yield self.send_missing(namespace)
diff --git a/tests/server/test_blobs_server.py b/tests/server/test_blobs_server.py
index ba4a03d7..4e7b4a3b 100644
--- a/tests/server/test_blobs_server.py
+++ b/tests/server/test_blobs_server.py
@@ -37,6 +37,7 @@ from leap.soledad.client._db.blobs import SyncStatus
from leap.soledad.client._db.blobs import RetriableTransferError
from leap.soledad.client._db.blobs import MaximumRetriesError
from leap.soledad.client._db import blobs as client_blobs
+from leap.soledad.client._document import BlobDoc
def sleep(x):
@@ -324,6 +325,24 @@ class BlobServerTestCase(unittest.TestCase):
@defer.inlineCallbacks
@pytest.mark.usefixtures("method_tmpdir")
+ def test_refresh_deletions_from_server(self):
+ manager = BlobManager(self.tempdir, self.uri, self.secret,
+ self.secret, uuid4().hex)
+ self.addCleanup(manager.close)
+ blob_id, content = 'delete_me', 'content'
+ blob_id2 = 'dont_delete_me'
+ doc1 = BlobDoc(BytesIO(content), blob_id)
+ doc2 = BlobDoc(BytesIO(content), blob_id2)
+ yield manager.put(doc1, len(content))
+ yield manager.put(doc2, len(content))
+ yield manager._delete_from_remote(blob_id) # remote only deletion
+ self.assertTrue((yield manager.local.exists(blob_id)))
+ yield manager.sync()
+ self.assertFalse((yield manager.local.exists(blob_id)))
+ self.assertTrue((yield manager.local.exists(blob_id2)))
+
+ @defer.inlineCallbacks
+ @pytest.mark.usefixtures("method_tmpdir")
def test_download_corrupted_tag_marks_blob_as_failed(self):
user_id = uuid4().hex
manager = BlobManager(self.tempdir, self.uri, self.secret,