1
0
mirror of https://github.com/dkmstr/openuds.git synced 2025-03-20 06:50:23 +03:00

Better singleton pattern (more reusable)

This commit is contained in:
Adolfo Gómez García 2021-09-04 17:16:57 +02:00
parent 8e3d90e7f3
commit 54f7fd21dc
10 changed files with 67 additions and 64 deletions

View File

@ -45,36 +45,36 @@ if typing.TYPE_CHECKING:
def cryptoManager() -> 'CryptoManager':
from .crypto import CryptoManager # pylint: disable=redefined-outer-name
from .crypto import CryptoManager
return CryptoManager.manager()
def taskManager() -> typing.Type['TaskManager']:
from .task import TaskManager # pylint: disable=redefined-outer-name
def taskManager() -> 'TaskManager':
from .task import TaskManager
return TaskManager
return TaskManager.manager()
def downloadsManager() -> 'DownloadsManager':
from .downloads import DownloadsManager # pylint: disable=redefined-outer-name
from .downloads import DownloadsManager
return DownloadsManager.manager()
def logManager() -> 'LogManager':
from .log import LogManager # pylint: disable=redefined-outer-name
from .log import LogManager
return LogManager.manager()
def userServiceManager() -> 'UserServiceManager':
from .user_service import UserServiceManager # pylint: disable=redefined-outer-name
from .user_service import UserServiceManager
return UserServiceManager.manager()
def publicationManager() -> 'PublicationManager':
from .publication import PublicationManager # pylint: disable=redefined-outer-name
from .publication import PublicationManager
return PublicationManager.manager()

View File

@ -49,6 +49,8 @@ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from django.conf import settings
from uds.core.util import singleton
logger = logging.getLogger(__name__)
if typing.TYPE_CHECKING:
@ -58,9 +60,7 @@ if typing.TYPE_CHECKING:
from cryptography.hazmat.primitives.asymmetric.dh import DHPrivateKey
class CryptoManager:
instance = None
class CryptoManager(metaclass=singleton.Singleton):
def __init__(self):
self._rsa = serialization.load_pem_private_key(
settings.RSA_KEY.encode(), password=None, backend=default_backend()
@ -87,9 +87,7 @@ class CryptoManager:
@staticmethod
def manager() -> 'CryptoManager':
if CryptoManager.instance is None:
CryptoManager.instance = CryptoManager()
return CryptoManager.instance
return CryptoManager() # Singleton pattern will return always the same instance
def encrypt(self, value: str) -> str:
return codecs.encode(
@ -117,7 +115,7 @@ class CryptoManager:
label=None,
),
)
except Exception: # If fails, try old method
except Exception: # Old method is not supported
logger.exception('Decripting: %s', value)
return 'decript error'
# logger.debug('Decripted: %s %s', data, decrypted)

View File

@ -39,12 +39,12 @@ from wsgiref.util import FileWrapper
from django.http import HttpResponse, Http404
from uds.core.managers import cryptoManager
from uds.core.util import singleton
logger = logging.getLogger(__name__)
class DownloadsManager:
class DownloadsManager(metaclass=singleton.Singleton):
"""
Manager so connectors can register their own downloadables
For registering, use at __init__.py of the conecto something like this:
@ -56,17 +56,16 @@ class DownloadsManager:
'application/x-msdos-program')
"""
_manager: typing.Optional['DownloadsManager'] = None
_downloadables: typing.Dict[str, typing.Dict[str, str]] = {}
def __init__(self):
self._downloadables = {}
@staticmethod
def manager():
if DownloadsManager._manager is None:
DownloadsManager._manager = DownloadsManager()
return DownloadsManager._manager
def manager() -> 'DownloadsManager':
return (
DownloadsManager()
) # Singleton pattern will return always the same instance
def registerDownloadable(
self, name: str, comment: str, path: str, mime: str = 'application/octet-stream'

View File

@ -36,6 +36,7 @@ import typing
from uds import models
from uds.core.util.config import GlobalConfig
from uds.core.util import singleton
# Not imported at runtime, just for type checking
if typing.TYPE_CHECKING:
@ -72,21 +73,17 @@ transDict: typing.Dict[typing.Type['Model'], int] = {
}
class LogManager:
class LogManager(metaclass=singleton.Singleton):
"""
Manager for logging (at database) events
"""
_manager: typing.Optional['LogManager'] = None
def __init__(self):
pass
@staticmethod
def manager() -> 'LogManager':
if not LogManager._manager:
LogManager._manager = LogManager()
return LogManager._manager
return LogManager() # Singleton pattern will return always the same instance
def __log(
self,
@ -204,7 +201,9 @@ class LogManager:
self.__clearLogs(owner_type, wichObject.id) # type: ignore
else:
logger.debug(
'Requested clearLogs for a type of object not covered: %s: %s', type(wichObject), wichObject
'Requested clearLogs for a type of object not covered: %s: %s',
type(wichObject),
wichObject,
)
for line in traceback.format_stack(limit=5):
logger.debug('>> %s', line)

View File

@ -45,6 +45,8 @@ from uds.core.util import log
from uds.models import ServicePoolPublication, getSqlDatetime, ServicePool
from uds.core.util import singleton
if typing.TYPE_CHECKING:
from uds.core import services
@ -255,13 +257,11 @@ class PublicationFinishChecker(DelayedTask):
)
class PublicationManager:
class PublicationManager(metaclass=singleton.Singleton):
"""
Manager responsible of controlling publications
"""
_manager: typing.Optional['PublicationManager'] = None
def __init__(self):
pass
@ -270,9 +270,9 @@ class PublicationManager:
"""
Returns the singleton to this manager
"""
if not PublicationManager._manager:
PublicationManager._manager = PublicationManager()
return PublicationManager._manager
return (
PublicationManager()
) # Singleton pattern will return always the same instance
def publish(
self, servicePool: ServicePool, changeLog: typing.Optional[str] = None

View File

@ -35,6 +35,7 @@ import logging
import typing
from uds.core.util.config import GlobalConfig
from uds.core.util import singleton
from uds.models import StatsCounters
from uds.models import getSqlDatetime, getSqlDatetimeAsUnix
from uds.models import StatsEvents
@ -53,7 +54,7 @@ REVERSE_FLDS_EQUIV: typing.Mapping[str, str] = {
}
class StatsManager:
class StatsManager(metaclass=singleton.Singleton):
"""
Manager for statistics, so we can provide usefull info about platform usage
@ -62,16 +63,12 @@ class StatsManager:
are assigned, are in use, in cache, etc...
"""
_manager: typing.Optional['StatsManager'] = None
def __init__(self):
pass
@staticmethod
def manager():
if not StatsManager._manager:
StatsManager._manager = StatsManager()
return StatsManager._manager
def manager() -> 'StatsManager':
return StatsManager() # Singleton pattern will return always the same instance
def __doCleanup(self, model):
minTime = time.mktime(

View File

@ -41,6 +41,7 @@ from uds.core.jobs.scheduler import Scheduler
from uds.core.jobs.delayed_task_runner import DelayedTaskRunner
from uds.core import jobs
from uds.core.util.config import GlobalConfig
from uds.core.util import singleton
logger = logging.getLogger(__name__)
@ -66,9 +67,16 @@ class DelayedTaskThread(BaseThread):
DelayedTaskRunner.runner().notifyTermination()
class TaskManager:
class TaskManager(metaclass=singleton.Singleton):
keepRunning: bool = True
def __init__(self):
pass
@staticmethod
def manager() -> 'TaskManager':
return TaskManager()
@staticmethod
def sigTerm(sigNum, frame):
"""
@ -80,24 +88,20 @@ class TaskManager:
Take a look at killTaskManager.sh :-)
"""
logger.info("Caught term signal, finishing task manager")
TaskManager.keepRunning = False
TaskManager.manager().keepRunning = False
@staticmethod
def registerJob(jobType: typing.Type[jobs.Job]) -> None:
def registerJob(self, jobType: typing.Type[jobs.Job]) -> None:
jobName = jobType.friendly_name
jobs.factory().insert(jobName, jobType)
@staticmethod
def registerScheduledTasks() -> None:
def registerScheduledTasks(self) -> None:
logger.info("Registering sheduled tasks")
# Simply import this to make workers "auto import themself"
from uds.core import workers # @UnusedImport pylint: disable=unused-import
@staticmethod
def run() -> None:
TaskManager.keepRunning = True
def run(self) -> None:
self.keepRunning = True
# Don't know why, but with django 1.8, must "reset" connections so them do not fail on first access...
# Is simmilar to https://code.djangoproject.com/ticket/21597#comment:29
@ -106,7 +110,7 @@ class TaskManager:
# Releases owned schedules so anyone can access them...
Scheduler.releaseOwnShedules()
TaskManager.registerScheduledTasks()
self.registerScheduledTasks()
noSchedulers: int = GlobalConfig.SCHEDULER_THREADS.getInt()
noDelayedTasks: int = GlobalConfig.DELAYED_TASKS_THREADS.getInt()

View File

@ -38,6 +38,8 @@ import typing
from django import forms
from django.utils.translation import ugettext as _, ugettext_lazy
from uds.core.util import singleton
if typing.TYPE_CHECKING:
from uds.models import User
@ -45,8 +47,7 @@ logger = logging.getLogger(__name__)
# UserPrefs is DEPRECATED
# Currently not used anywhere
class UserPrefsManager:
_manager: typing.Optional['UserPrefsManager'] = None
class UserPrefsManager(metaclass=singleton.Singleton):
_prefs: typing.Dict[str, typing.Dict]
def __init__(self):
@ -54,9 +55,7 @@ class UserPrefsManager:
@staticmethod
def manager() -> 'UserPrefsManager':
if UserPrefsManager._manager is None:
UserPrefsManager._manager = UserPrefsManager()
return UserPrefsManager._manager
return UserPrefsManager()
def __nameFor(self, module, name):
return module + "_" + name

View File

@ -58,6 +58,7 @@ from uds.models import (
)
from uds.models.meta_pool import MetaPoolMember
from uds.core import services, transports
from uds.core.util import singleton
from uds.core.util.stats import events
from .userservice import comms
@ -67,17 +68,13 @@ logger = logging.getLogger(__name__)
traceLogger = logging.getLogger('traceLog')
class UserServiceManager:
_manager: typing.Optional['UserServiceManager'] = None
class UserServiceManager(metaclass=singleton.Singleton):
def __init__(self):
pass
@staticmethod
def manager() -> 'UserServiceManager':
if not UserServiceManager._manager:
UserServiceManager._manager = UserServiceManager()
return UserServiceManager._manager
return UserServiceManager() # Singleton pattern will return always the same instance
@staticmethod
def getCacheStateFilter(level: int) -> Q:

View File

@ -0,0 +1,10 @@
# Metaclass for singleton pattern
class Singleton(type):
def __init__(self, *args, **kwargs):
self.__instance = None
super().__init__(*args, **kwargs)
def __call__(self, *args, **kwargs):
if self.__instance is None:
self.__instance = super().__call__(*args, **kwargs)
return self.__instance