2021-08-06 16:44:57 +02:00
|
|
|
import os
|
2021-08-16 20:15:12 +02:00
|
|
|
import asyncio
|
|
|
|
import logging
|
|
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
2021-08-06 16:44:57 +02:00
|
|
|
|
|
|
|
|
|
|
|
class DiskSpaceManager:
|
|
|
|
|
2021-08-16 20:15:12 +02:00
|
|
|
def __init__(self, config, cleaning_interval=30 * 60):
|
2021-08-06 16:44:57 +02:00
|
|
|
self.config = config
|
2021-08-16 20:15:12 +02:00
|
|
|
self.cleaning_interval = cleaning_interval
|
|
|
|
self.running = False
|
|
|
|
self.task = None
|
2021-08-06 16:44:57 +02:00
|
|
|
|
|
|
|
@property
|
|
|
|
def space_used_bytes(self):
|
|
|
|
used = 0
|
2021-08-06 16:52:47 +02:00
|
|
|
data_dir = os.path.join(self.config.data_dir, 'blobfiles')
|
2021-08-16 20:15:12 +02:00
|
|
|
for item in os.scandir(data_dir):
|
|
|
|
if item.is_file:
|
|
|
|
used += item.stat().st_size
|
2021-08-06 16:44:57 +02:00
|
|
|
return used
|
|
|
|
|
|
|
|
@property
|
|
|
|
def space_used_mb(self):
|
|
|
|
return int(self.space_used_bytes/1024.0/1024.0)
|
2021-08-16 20:15:12 +02:00
|
|
|
|
|
|
|
def clean(self):
|
|
|
|
if not self.config.blob_storage_limit:
|
2021-08-16 23:02:13 +02:00
|
|
|
return False
|
2021-08-16 20:15:12 +02:00
|
|
|
used = 0
|
|
|
|
files = []
|
|
|
|
data_dir = os.path.join(self.config.data_dir, 'blobfiles')
|
|
|
|
for file in os.scandir(data_dir):
|
|
|
|
if file.is_file:
|
|
|
|
file_stats = file.stat()
|
|
|
|
used += file_stats.st_size
|
2021-08-16 20:41:16 +02:00
|
|
|
files.append((file_stats.st_mtime, file_stats.st_size, file.path))
|
2021-08-16 20:15:12 +02:00
|
|
|
files.sort()
|
|
|
|
available = (self.config.blob_storage_limit*1024*1024) - used
|
2021-08-16 23:02:13 +02:00
|
|
|
cleaned = False
|
2021-08-16 20:15:12 +02:00
|
|
|
for _, file_size, file in files:
|
|
|
|
available += file_size
|
|
|
|
if available > 0:
|
|
|
|
break
|
|
|
|
os.remove(file)
|
2021-08-16 23:02:13 +02:00
|
|
|
cleaned = True
|
|
|
|
return cleaned
|
2021-08-16 20:15:12 +02:00
|
|
|
|
|
|
|
async def cleaning_loop(self):
|
|
|
|
while self.running:
|
|
|
|
await asyncio.get_event_loop().run_in_executor(None, self.clean)
|
|
|
|
await asyncio.sleep(self.cleaning_interval)
|
|
|
|
|
|
|
|
async def start(self):
|
|
|
|
self.running = True
|
|
|
|
self.task = asyncio.create_task(self.cleaning_loop())
|
|
|
|
self.task.add_done_callback(lambda _: log.info("Stopping blob cleanup service."))
|
|
|
|
|
|
|
|
async def stop(self):
|
|
|
|
if self.running:
|
|
|
|
self.running = False
|
|
|
|
self.task.cancel()
|