mirror of
https://github.com/zulip/zulip.git
synced 2025-11-02 13:03:29 +00:00
management: Provide a common lockfile dir, and a decorator for it.
Factor out the repeated pattern of taking a lock, or immediately aborting with a message if it cannot be acquired. The exit code in that situation is changed to be exit code 1, rather than the successful 0; we are likely missing new work since that process started. We move the lockfiles to a common directory under `/srv/zulip-locks` rather than muddy up `/home/zulip/deployments`.
This commit is contained in:
committed by
Tim Abbott
parent
572fafd6b9
commit
11dd6791c4
@@ -1,9 +1,11 @@
|
||||
# Library code for use in management commands
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from argparse import ArgumentParser, RawTextHelpFormatter, _ActionsContainer
|
||||
from dataclasses import dataclass
|
||||
from functools import reduce
|
||||
from typing import Any, Dict, Optional
|
||||
from functools import reduce, wraps
|
||||
from typing import Any, Dict, Optional, Protocol
|
||||
|
||||
from django.conf import settings
|
||||
from django.core import validators
|
||||
@@ -12,6 +14,7 @@ from django.core.management.base import BaseCommand, CommandError, CommandParser
|
||||
from django.db.models import Q, QuerySet
|
||||
from typing_extensions import override
|
||||
|
||||
from zerver.lib.context_managers import lockfile_nonblocking
|
||||
from zerver.lib.initial_password import initial_password
|
||||
from zerver.models import Client, Realm, UserProfile
|
||||
from zerver.models.clients import get_client
|
||||
@@ -38,6 +41,31 @@ def check_config() -> None:
|
||||
raise CommandError(f"Error: You must set {setting_name} in /etc/zulip/settings.py.")
|
||||
|
||||
|
||||
class HandleMethod(Protocol):
|
||||
def __call__(self, *args: Any, **kwargs: Any) -> None: ...
|
||||
|
||||
|
||||
def abort_unless_locked(handle_func: HandleMethod) -> HandleMethod:
|
||||
@wraps(handle_func)
|
||||
def our_handle(self: BaseCommand, *args: Any, **kwargs: Any) -> None:
|
||||
os.makedirs(settings.LOCKFILE_DIRECTORY, exist_ok=True)
|
||||
# Trim out just the last part of the module name, which is the
|
||||
# command name, to use as the lockfile name;
|
||||
# `zerver.management.commands.send_zulip_update_announcements`
|
||||
# becomes `/srv/zulip-locks/send_zulip_update_announcements.lock`
|
||||
lockfile_name = handle_func.__module__.split(".")[-1]
|
||||
lockfile_path = settings.LOCKFILE_DIRECTORY + "/" + lockfile_name + ".lock"
|
||||
with lockfile_nonblocking(lockfile_path) as lock_acquired:
|
||||
if not lock_acquired: # nocoverage
|
||||
self.stdout.write(
|
||||
self.style.ERROR(f"Lock {lockfile_path} is unavailable; exiting.")
|
||||
)
|
||||
sys.exit(1)
|
||||
handle_func(self, *args, **kwargs)
|
||||
|
||||
return our_handle
|
||||
|
||||
|
||||
@dataclass
|
||||
class CreateUserParameters:
|
||||
email: str
|
||||
|
||||
Reference in New Issue
Block a user