mirror of
https://github.com/quay/quay.git
synced 2025-04-18 10:44:06 +03:00
Adds ACCOUNT_RECOVERY_MODE to allow Quay to run with some core features disabled. When this is set, the instance should only be used in order by existing users who hasn't linked their account to an external login service, after database authentication has been disabled.
91 lines
2.9 KiB
Python
91 lines
2.9 KiB
Python
import logging
|
|
import time
|
|
|
|
import features
|
|
|
|
from app import repository_gc_queue, all_queues, app
|
|
from data import model, database
|
|
from workers.queueworker import QueueWorker, WorkerSleepException
|
|
from util.log import logfile_path
|
|
from util.locking import GlobalLock, LockNotAcquiredException
|
|
from workers.gunicorn_worker import GunicornWorker
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
POLL_PERIOD_SECONDS = 60
|
|
REPOSITORY_GC_TIMEOUT = 3 * 60 * 60 # 3h
|
|
LOCK_TIMEOUT_PADDING = 60 # 60 seconds
|
|
|
|
|
|
class RepositoryGCWorker(QueueWorker):
|
|
"""
|
|
Worker which cleans up repositories enqueued to be GCed.
|
|
"""
|
|
|
|
def process_queue_item(self, job_details):
|
|
try:
|
|
with GlobalLock(
|
|
"LARGE_GARBAGE_COLLECTION", lock_ttl=REPOSITORY_GC_TIMEOUT + LOCK_TIMEOUT_PADDING
|
|
):
|
|
self._perform_gc(job_details)
|
|
except LockNotAcquiredException:
|
|
logger.debug("Could not acquire global lock for garbage collection")
|
|
raise WorkerSleepException
|
|
|
|
def _perform_gc(self, job_details):
|
|
logger.debug("Got repository GC queue item: %s", job_details)
|
|
marker_id = job_details["marker_id"]
|
|
|
|
try:
|
|
marker = database.DeletedRepository.get(id=marker_id)
|
|
except database.DeletedRepository.DoesNotExist:
|
|
logger.debug("Found no matching delete repo marker: %s", job_details)
|
|
return
|
|
|
|
logger.debug("Purging repository %s", marker.repository)
|
|
if not model.gc.purge_repository(marker.repository):
|
|
raise Exception("GC interrupted; will retry")
|
|
|
|
|
|
def create_gunicorn_worker():
|
|
"""
|
|
follows the gunicorn application factory pattern, enabling
|
|
a quay worker to run as a gunicorn worker thread.
|
|
|
|
this is useful when utilizing gunicorn's hot reload in local dev.
|
|
|
|
utilizing this method will enforce a 1:1 quay worker to gunicorn worker ratio.
|
|
"""
|
|
gc_worker = RepositoryGCWorker(
|
|
repository_gc_queue,
|
|
poll_period_seconds=POLL_PERIOD_SECONDS,
|
|
reservation_seconds=REPOSITORY_GC_TIMEOUT,
|
|
)
|
|
|
|
worker = GunicornWorker(__name__, app, gc_worker, features.REPOSITORY_GARBAGE_COLLECTION)
|
|
return worker
|
|
|
|
|
|
if __name__ == "__main__":
|
|
logging.config.fileConfig(logfile_path(debug=False), disable_existing_loggers=False)
|
|
|
|
if app.config.get("ACCOUNT_RECOVERY_MODE", False):
|
|
logger.debug("Quay running in account recovery mode")
|
|
while True:
|
|
time.sleep(100000)
|
|
|
|
if not features.REPOSITORY_GARBAGE_COLLECTION:
|
|
logger.info("Repository garbage collection is disabled; skipping")
|
|
while True:
|
|
time.sleep(100000)
|
|
|
|
GlobalLock.configure(app.config)
|
|
logger.debug("Starting repository GC worker")
|
|
worker = RepositoryGCWorker(
|
|
repository_gc_queue,
|
|
poll_period_seconds=POLL_PERIOD_SECONDS,
|
|
reservation_seconds=REPOSITORY_GC_TIMEOUT,
|
|
)
|
|
worker.start()
|