Skip to content

Commit a587976

Browse files
committed
simpfly speed limit logic and edge cases
1 parent 1adbf6b commit a587976

2 files changed

Lines changed: 15 additions & 20 deletions

File tree

pypdl/consumer.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from aiofiles import os
55

6-
from .downloader import Multidown, Singledown
6+
from .downloader import SegmentDownloader, SingleSegmentDownloader
77
from .utils import (
88
FileValidator,
99
auto_cancel_gather,
@@ -120,7 +120,7 @@ async def _multi_segment(self, segment_table, file_path, speed_limit, **kwargs):
120120
speed_limit = speed_limit / segments
121121
self._logger.debug("Multi-Segment download started %s", self._id)
122122
for segment in range(segments):
123-
md = Multidown(self._session, speed_limit)
123+
md = SegmentDownloader(self._session, speed_limit)
124124
self._workers.append(md)
125125
tasks.add(asyncio.create_task(md.worker(segment_table, segment, **kwargs)))
126126

@@ -132,7 +132,7 @@ async def _multi_segment(self, segment_table, file_path, speed_limit, **kwargs):
132132

133133
async def _single_segment(self, url, file_path, speed_limit, **kwargs):
134134
self._logger.debug("Single-Segment download started %s", self._id)
135-
sd = Singledown(self._session, speed_limit)
135+
sd = SingleSegmentDownloader(self._session, speed_limit)
136136
self._workers.append(sd)
137137
await sd.worker(url, file_path, **kwargs)
138138
self._logger.debug("Downloaded single segment %s", self._id)

pypdl/downloader.py

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,44 +7,39 @@
77
MEGABYTE = 1048576
88

99

10-
class Basicdown:
10+
class BaseDownloader:
1111
"""Base downloader class."""
1212

1313
def __init__(self, session: ClientSession, speed_limit: float) -> None:
1414
self.session = session
15-
self.speed_limit = speed_limit * MEGABYTE
15+
self.speed_limit = max(0, speed_limit * MEGABYTE)
1616
self.curr = 0
1717

1818
async def download(self, url: str, path: str, mode: str, **kwargs) -> None:
1919
"""Download data in chunks."""
20-
speedlimit_time = time.time()
21-
speedlimit_size = 0
20+
start_time = time.monotonic()
2221
async with self.session.get(url, **kwargs) as response:
2322
async with aiofiles.open(path, mode) as file:
2423
async for chunk in response.content.iter_chunked(MEGABYTE):
25-
if self.speed_limit > 0:
26-
now = time.time()
27-
time_passed = now - speedlimit_time
28-
if time_passed > 0.1:
29-
curr_download = self.curr - speedlimit_size
30-
if curr_download / time_passed >= self.speed_limit:
31-
await asyncio.sleep(curr_download / self.speed_limit)
32-
else:
33-
speedlimit_time = now
34-
speedlimit_size = self.curr
35-
3624
await file.write(chunk)
3725
self.curr += len(chunk)
3826

27+
if self.speed_limit > 0:
28+
expected_time = self.curr / self.speed_limit
29+
current_time = time.monotonic() - start_time
30+
sleep_time = expected_time - current_time
31+
if sleep_time > 0:
32+
await asyncio.sleep(sleep_time)
33+
3934

40-
class Singledown(Basicdown):
35+
class SingleSegmentDownloader(BaseDownloader):
4136
"""Class for downloading the whole file in a single segment."""
4237

4338
async def worker(self, url: str, file_path: str, **kwargs) -> None:
4439
await self.download(url, file_path, "wb", **kwargs)
4540

4641

47-
class Multidown(Basicdown):
42+
class SegmentDownloader(BaseDownloader):
4843
"""Class for downloading a specific segment of the file."""
4944

5045
async def worker(self, segment_table: dict, id: int, **kwargs) -> None:

0 commit comments

Comments
 (0)