mirror of
https://github.com/ArchiveBox/ArchiveBox.git
synced 2025-05-09 12:21:57 -04:00
move main funcs into cli files and switch to using click for CLI
This commit is contained in:
parent
569081a9eb
commit
328eb98a38
35 changed files with 1885 additions and 2296 deletions
|
@ -1,103 +1,103 @@
|
|||
import uuid
|
||||
from functools import wraps
|
||||
from django.db import connection, transaction
|
||||
from django.utils import timezone
|
||||
from huey.exceptions import TaskLockedException
|
||||
# import uuid
|
||||
# from functools import wraps
|
||||
# from django.db import connection, transaction
|
||||
# from django.utils import timezone
|
||||
# from huey.exceptions import TaskLockedException
|
||||
|
||||
from archivebox.config import CONSTANTS
|
||||
# from archivebox.config import CONSTANTS
|
||||
|
||||
class SqliteSemaphore:
|
||||
def __init__(self, db_path, table_name, name, value=1, timeout=None):
|
||||
self.db_path = db_path
|
||||
self.table_name = table_name
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.timeout = timeout or 86400 # Set a max age for lock holders
|
||||
# class SqliteSemaphore:
|
||||
# def __init__(self, db_path, table_name, name, value=1, timeout=None):
|
||||
# self.db_path = db_path
|
||||
# self.table_name = table_name
|
||||
# self.name = name
|
||||
# self.value = value
|
||||
# self.timeout = timeout or 86400 # Set a max age for lock holders
|
||||
|
||||
# Ensure the table exists
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(f"""
|
||||
CREATE TABLE IF NOT EXISTS {self.table_name} (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT,
|
||||
timestamp DATETIME
|
||||
)
|
||||
""")
|
||||
# # Ensure the table exists
|
||||
# with connection.cursor() as cursor:
|
||||
# cursor.execute(f"""
|
||||
# CREATE TABLE IF NOT EXISTS {self.table_name} (
|
||||
# id TEXT PRIMARY KEY,
|
||||
# name TEXT,
|
||||
# timestamp DATETIME
|
||||
# )
|
||||
# """)
|
||||
|
||||
def acquire(self, name=None):
|
||||
name = name or str(uuid.uuid4())
|
||||
now = timezone.now()
|
||||
expiration = now - timezone.timedelta(seconds=self.timeout)
|
||||
# def acquire(self, name=None):
|
||||
# name = name or str(uuid.uuid4())
|
||||
# now = timezone.now()
|
||||
# expiration = now - timezone.timedelta(seconds=self.timeout)
|
||||
|
||||
with transaction.atomic():
|
||||
# Remove expired locks
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(f"""
|
||||
DELETE FROM {self.table_name}
|
||||
WHERE name = %s AND timestamp < %s
|
||||
""", [self.name, expiration])
|
||||
# with transaction.atomic():
|
||||
# # Remove expired locks
|
||||
# with connection.cursor() as cursor:
|
||||
# cursor.execute(f"""
|
||||
# DELETE FROM {self.table_name}
|
||||
# WHERE name = %s AND timestamp < %s
|
||||
# """, [self.name, expiration])
|
||||
|
||||
# Try to acquire the lock
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(f"""
|
||||
INSERT INTO {self.table_name} (id, name, timestamp)
|
||||
SELECT %s, %s, %s
|
||||
WHERE (
|
||||
SELECT COUNT(*) FROM {self.table_name}
|
||||
WHERE name = %s
|
||||
) < %s
|
||||
""", [name, self.name, now, self.name, self.value])
|
||||
# # Try to acquire the lock
|
||||
# with connection.cursor() as cursor:
|
||||
# cursor.execute(f"""
|
||||
# INSERT INTO {self.table_name} (id, name, timestamp)
|
||||
# SELECT %s, %s, %s
|
||||
# WHERE (
|
||||
# SELECT COUNT(*) FROM {self.table_name}
|
||||
# WHERE name = %s
|
||||
# ) < %s
|
||||
# """, [name, self.name, now, self.name, self.value])
|
||||
|
||||
if cursor.rowcount > 0:
|
||||
return name
|
||||
# if cursor.rowcount > 0:
|
||||
# return name
|
||||
|
||||
# If we couldn't acquire the lock, remove our attempted entry
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(f"""
|
||||
DELETE FROM {self.table_name}
|
||||
WHERE id = %s AND name = %s
|
||||
""", [name, self.name])
|
||||
# # If we couldn't acquire the lock, remove our attempted entry
|
||||
# with connection.cursor() as cursor:
|
||||
# cursor.execute(f"""
|
||||
# DELETE FROM {self.table_name}
|
||||
# WHERE id = %s AND name = %s
|
||||
# """, [name, self.name])
|
||||
|
||||
return None
|
||||
# return None
|
||||
|
||||
def release(self, name):
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(f"""
|
||||
DELETE FROM {self.table_name}
|
||||
WHERE id = %s AND name = %s
|
||||
""", [name, self.name])
|
||||
return cursor.rowcount > 0
|
||||
# def release(self, name):
|
||||
# with connection.cursor() as cursor:
|
||||
# cursor.execute(f"""
|
||||
# DELETE FROM {self.table_name}
|
||||
# WHERE id = %s AND name = %s
|
||||
# """, [name, self.name])
|
||||
# return cursor.rowcount > 0
|
||||
|
||||
|
||||
LOCKS_DB_PATH = CONSTANTS.DATABASE_FILE.parent / 'locks.sqlite3'
|
||||
# LOCKS_DB_PATH = CONSTANTS.DATABASE_FILE.parent / 'locks.sqlite3'
|
||||
|
||||
|
||||
def lock_task_semaphore(db_path, table_name, lock_name, value=1, timeout=None):
|
||||
"""
|
||||
Lock which can be acquired multiple times (default = 1).
|
||||
# def lock_task_semaphore(db_path, table_name, lock_name, value=1, timeout=None):
|
||||
# """
|
||||
# Lock which can be acquired multiple times (default = 1).
|
||||
|
||||
NOTE: no provisions are made for blocking, waiting, or notifying. This is
|
||||
just a lock which can be acquired a configurable number of times.
|
||||
# NOTE: no provisions are made for blocking, waiting, or notifying. This is
|
||||
# just a lock which can be acquired a configurable number of times.
|
||||
|
||||
Example:
|
||||
# Example:
|
||||
|
||||
# Allow up to 3 workers to run this task concurrently. If the task is
|
||||
# locked, retry up to 2 times with a delay of 60s.
|
||||
@huey.task(retries=2, retry_delay=60)
|
||||
@lock_task_semaphore('path/to/db.sqlite3', 'semaphore_locks', 'my-lock', 3)
|
||||
def my_task():
|
||||
...
|
||||
"""
|
||||
sem = SqliteSemaphore(db_path, table_name, lock_name, value, timeout)
|
||||
def decorator(fn):
|
||||
@wraps(fn)
|
||||
def inner(*args, **kwargs):
|
||||
tid = sem.acquire()
|
||||
if tid is None:
|
||||
raise TaskLockedException(f'unable to acquire lock {lock_name}')
|
||||
try:
|
||||
return fn(*args, **kwargs)
|
||||
finally:
|
||||
sem.release(tid)
|
||||
return inner
|
||||
return decorator
|
||||
# # Allow up to 3 workers to run this task concurrently. If the task is
|
||||
# # locked, retry up to 2 times with a delay of 60s.
|
||||
# @huey.task(retries=2, retry_delay=60)
|
||||
# @lock_task_semaphore('path/to/db.sqlite3', 'semaphore_locks', 'my-lock', 3)
|
||||
# def my_task():
|
||||
# ...
|
||||
# """
|
||||
# sem = SqliteSemaphore(db_path, table_name, lock_name, value, timeout)
|
||||
# def decorator(fn):
|
||||
# @wraps(fn)
|
||||
# def inner(*args, **kwargs):
|
||||
# tid = sem.acquire()
|
||||
# if tid is None:
|
||||
# raise TaskLockedException(f'unable to acquire lock {lock_name}')
|
||||
# try:
|
||||
# return fn(*args, **kwargs)
|
||||
# finally:
|
||||
# sem.release(tid)
|
||||
# return inner
|
||||
# return decorator
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue