diff --git a/deluge/core/core.py b/deluge/core/core.py index 15024258e..51c9b1fe9 100644 --- a/deluge/core/core.py +++ b/deluge/core/core.py @@ -419,11 +419,16 @@ class Core(component.Component): The metadata is base64 encoded. """ - def on_metadata(result): + def on_metadata(result, result_d): torrent_id, metadata = result - return torrent_id, b64encode(metadata) + result_d.callback((torrent_id, b64encode(metadata))) + return result - return self.torrentmanager.prefetch_metadata(magnet, timeout).addCallback(on_metadata) + d = self.torrentmanager.prefetch_metadata(magnet, timeout) + # Use a seperate callback chain to handle existing prefetching magnet. + result_d = defer.Deferred() + d.addBoth(on_metadata, result_d) + return result_d @export def add_torrent_file(self, filename, filedump, options): diff --git a/deluge/core/torrentmanager.py b/deluge/core/torrentmanager.py index cb5d1bb3f..484218ad4 100644 --- a/deluge/core/torrentmanager.py +++ b/deluge/core/torrentmanager.py @@ -316,6 +316,11 @@ class TorrentManager(component.Component): """ + torrent_id = get_magnet_info(magnet)['info_hash'] + if torrent_id in self.prefetching_metadata: + d = self.prefetching_metadata[torrent_id][0] + return d + add_torrent_params = {} add_torrent_params['save_path'] = gettempdir() add_torrent_params['url'] = magnet.strip().encode('utf8') diff --git a/deluge/tests/test_core.py b/deluge/tests/test_core.py index 4fc23ab7c..b87f56500 100644 --- a/deluge/tests/test_core.py +++ b/deluge/tests/test_core.py @@ -11,7 +11,7 @@ from base64 import b64encode from hashlib import sha1 as sha import pytest -from twisted.internet import defer, reactor +from twisted.internet import defer, reactor, task from twisted.internet.error import CannotListenError from twisted.python.failure import Failure from twisted.web.http import FORBIDDEN @@ -88,6 +88,8 @@ class CoreTestCase(BaseTestCase): self.rpcserver = RPCServer(listen=False) self.core = Core() self.core.config.config['lsd'] = False + self.clock = task.Clock() + self.core.torrentmanager.callLater = self.clock.callLater self.listen_port = 51242 return component.start().addCallback(self.start_web_server) @@ -311,6 +313,21 @@ class CoreTestCase(BaseTestCase): r2 = self.core.get_torrent_status(tid2, ['paused']) self.assertTrue(r2['paused']) + def test_prefetch_metadata_existing(self): + """Check another call with same magnet returns existing deferred.""" + magnet = 'magnet:?xt=urn:btih:ab570cdd5a17ea1b61e970bb72047de141bce173' + expected = ('ab570cdd5a17ea1b61e970bb72047de141bce173', '') + + def on_result(result): + self.assertEqual(result, expected) + + d = self.core.prefetch_magnet_metadata(magnet) + d.addCallback(on_result) + d2 = self.core.prefetch_magnet_metadata(magnet) + d2.addCallback(on_result) + self.clock.advance(30) + return defer.DeferredList([d, d2]) + @defer.inlineCallbacks def test_remove_torrent(self): options = {}