Moves Status to it's own file

This way only qmonitor and qinfo need Curses and you can still run the cluster without it.
This commit is contained in:
Ilan Steemers
2015-08-26 13:11:58 +02:00
parent 3e92fddcdd
commit 439c8a2f77
6 changed files with 126 additions and 122 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ sys.path.insert(0, myPath)
from .tasks import async, schedule, result, result_group, fetch, fetch_group, count_group, delete_group, queue_size from .tasks import async, schedule, result, result_group, fetch, fetch_group, count_group, delete_group, queue_size
from .models import Task, Schedule, Success, Failure from .models import Task, Schedule, Success, Failure
from .cluster import Cluster from .cluster import Cluster
from .monitor import Stat from .status import Stat
VERSION = (0, 5, 3) VERSION = (0, 5, 3)
+1 -1
View File
@@ -32,7 +32,7 @@ import tasks
from django_q.conf import Conf, redis_client, logger, psutil, get_ppid from django_q.conf import Conf, redis_client, logger, psutil, get_ppid
from django_q.models import Task, Success, Schedule from django_q.models import Task, Success, Schedule
from django_q.monitor import Status, Stat, ping_redis from django_q.status import Stat, Status, ping_redis
class Cluster(object): class Cluster(object):
+2 -118
View File
@@ -1,5 +1,4 @@
from datetime import timedelta from datetime import timedelta
import socket
# external # external
from blessed import Terminal from blessed import Terminal
@@ -11,8 +10,8 @@ from django.utils import timezone
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
# local # local
import signing from django_q.conf import Conf, redis_client
from django_q.conf import Conf, redis_client, logger from django_q.status import Stat, ping_redis
from django_q import models from django_q import models
@@ -85,113 +84,6 @@ def monitor(run_once=False, r=redis_client):
val = term.inkey(timeout=1) val = term.inkey(timeout=1)
class Status(object):
"""Cluster status base class."""
def __init__(self, pid):
self.workers = []
self.tob = None
self.reincarnations = 0
self.cluster_id = pid
self.sentinel = 0
self.status = Conf.STOPPED
self.done_q_size = 0
self.host = socket.gethostname()
self.monitor = 0
self.task_q_size = 0
self.pusher = 0
self.timestamp = timezone.now()
class Stat(Status):
"""Status object for Cluster monitoring."""
def __init__(self, sentinel):
super(Stat, self).__init__(sentinel.parent_pid or sentinel.pid)
self.r = sentinel.r
self.tob = sentinel.tob
self.reincarnations = sentinel.reincarnations
self.sentinel = sentinel.pid
self.status = sentinel.status()
self.done_q_size = 0
self.task_q_size = 0
if Conf.QSIZE:
self.done_q_size = sentinel.result_queue.qsize()
self.task_q_size = sentinel.task_queue.qsize()
if sentinel.monitor:
self.monitor = sentinel.monitor.pid
if sentinel.pusher:
self.pusher = sentinel.pusher.pid
self.workers = [w.pid for w in sentinel.pool]
def uptime(self):
return (timezone.now() - self.tob).total_seconds()
@property
def key(self):
"""
:return: redis key for this cluster statistic
"""
return self.get_key(self.cluster_id)
@staticmethod
def get_key(cluster_id):
"""
:param cluster_id: cluster ID
:return: redis key for the cluster statistic
"""
return '{}:{}'.format(Conf.Q_STAT, cluster_id)
def save(self):
try:
self.r.set(self.key, signing.SignedPackage.dumps(self, True), 3)
except Exception as e:
logger.error(e)
def empty_queues(self):
return self.done_q_size + self.task_q_size == 0
@staticmethod
def get(cluster_id, r=redis_client):
"""
gets the current status for the cluster
:param cluster_id: id of the cluster
:return: Stat or Status
"""
key = Stat.get_key(cluster_id)
if r.exists(key):
pack = r.get(key)
try:
return signing.SignedPackage.loads(pack)
except signing.BadSignature:
return None
return Status(cluster_id)
@staticmethod
def get_all(r=redis_client):
"""
Get the status for all currently running clusters with the same prefix
and secret key.
:return: list of type Stat
"""
stats = []
keys = r.keys(pattern='{}:*'.format(Conf.Q_STAT))
if keys:
packs = r.mget(keys)
for pack in packs:
try:
stats.append(signing.SignedPackage.loads(pack))
except signing.BadSignature:
continue
return stats
def __getstate__(self):
# Don't pickle the redis connection
state = dict(self.__dict__)
del state['r']
return state
def info(r=redis_client): def info(r=redis_client):
term = Terminal() term = Terminal()
ping_redis(r) ping_redis(r)
@@ -272,11 +164,3 @@ def info(r=redis_client):
term.white('{0:.4f}'.format(exec_time)) term.white('{0:.4f}'.format(exec_time))
) )
return True return True
def ping_redis(r):
try:
r.ping()
except Exception as e:
logger.error('Can not connect to Redis server.')
raise e
+119
View File
@@ -0,0 +1,119 @@
import socket
from django.utils import timezone
from django_q.conf import Conf, logger, redis_client
import signing
class Status(object):
"""Cluster status base class."""
def __init__(self, pid):
self.workers = []
self.tob = None
self.reincarnations = 0
self.cluster_id = pid
self.sentinel = 0
self.status = Conf.STOPPED
self.done_q_size = 0
self.host = socket.gethostname()
self.monitor = 0
self.task_q_size = 0
self.pusher = 0
self.timestamp = timezone.now()
class Stat(Status):
"""Status object for Cluster monitoring."""
def __init__(self, sentinel):
super(Stat, self).__init__(sentinel.parent_pid or sentinel.pid)
self.r = sentinel.r
self.tob = sentinel.tob
self.reincarnations = sentinel.reincarnations
self.sentinel = sentinel.pid
self.status = sentinel.status()
self.done_q_size = 0
self.task_q_size = 0
if Conf.QSIZE:
self.done_q_size = sentinel.result_queue.qsize()
self.task_q_size = sentinel.task_queue.qsize()
if sentinel.monitor:
self.monitor = sentinel.monitor.pid
if sentinel.pusher:
self.pusher = sentinel.pusher.pid
self.workers = [w.pid for w in sentinel.pool]
def uptime(self):
return (timezone.now() - self.tob).total_seconds()
@property
def key(self):
"""
:return: redis key for this cluster statistic
"""
return self.get_key(self.cluster_id)
@staticmethod
def get_key(cluster_id):
"""
:param cluster_id: cluster ID
:return: redis key for the cluster statistic
"""
return '{}:{}'.format(Conf.Q_STAT, cluster_id)
def save(self):
try:
self.r.set(self.key, signing.SignedPackage.dumps(self, True), 3)
except Exception as e:
logger.error(e)
def empty_queues(self):
return self.done_q_size + self.task_q_size == 0
@staticmethod
def get(cluster_id, r=redis_client):
"""
gets the current status for the cluster
:param cluster_id: id of the cluster
:return: Stat or Status
"""
key = Stat.get_key(cluster_id)
if r.exists(key):
pack = r.get(key)
try:
return signing.SignedPackage.loads(pack)
except signing.BadSignature:
return None
return Status(cluster_id)
@staticmethod
def get_all(r=redis_client):
"""
Get the status for all currently running clusters with the same prefix
and secret key.
:return: list of type Stat
"""
stats = []
keys = r.keys(pattern='{}:*'.format(Conf.Q_STAT))
if keys:
packs = r.mget(keys)
for pack in packs:
try:
stats.append(signing.SignedPackage.loads(pack))
except signing.BadSignature:
continue
return stats
def __getstate__(self):
# Don't pickle the redis connection
state = dict(self.__dict__)
del state['r']
return state
def ping_redis(r):
try:
r.ping()
except Exception as e:
logger.error('Can not connect to Redis server.')
raise e
+1 -1
View File
@@ -14,7 +14,7 @@ from django_q.humanhash import DEFAULT_WORDLIST
from django_q.tasks import fetch, fetch_group, async, result, result_group, count_group, delete_group, queue_size from django_q.tasks import fetch, fetch_group, async, result, result_group, count_group, delete_group, queue_size
from django_q.models import Task, Success from django_q.models import Task, Success
from django_q.conf import Conf, redis_client from django_q.conf import Conf, redis_client
from django_q.monitor import Stat from django_q.status import Stat
from .tasks import multiply from .tasks import multiply
+2 -1
View File
@@ -3,7 +3,8 @@ import redis
from django_q import async from django_q import async
from django_q.cluster import Cluster from django_q.cluster import Cluster
from django_q.monitor import monitor, Stat, ping_redis, info from django_q.monitor import monitor, info
from django_q.status import Stat, ping_redis
@pytest.mark.django_db @pytest.mark.django_db