Skip to content

Commit

Permalink
add pre_delete signal
Browse files Browse the repository at this point in the history
check for new and deleted scripts
  • Loading branch information
clavay committed Jun 3, 2021
1 parent e75f589 commit e2f4a30
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 30 deletions.
2 changes: 1 addition & 1 deletion pyscada/scripting/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import pyscada

__version__ = '0.7.0'
__version__ = '0.7.0rc18'
__author__ = 'Martin Schröder'

default_app_config = 'pyscada.scripting.apps.PyScadaScriptingConfig'
Expand Down
22 changes: 21 additions & 1 deletion pyscada/scripting/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from pyscada.scripting.models import Script

from django.dispatch import receiver
from django.db.models.signals import post_save
from django.db.models.signals import post_save, pre_delete

import logging

Expand All @@ -17,6 +17,8 @@ def _reinit_daq_daemons(sender, instance, **kwargs):
"""
update the daq daemon configuration when changes be applied in the models
"""
logger.debug("post_save script")
logger.debug(instance)
if type(instance) is Script:
try:
#todo select only one script not all
Expand All @@ -26,3 +28,21 @@ def _reinit_daq_daemons(sender, instance, **kwargs):
bp.restart()
else:
logger.debug('post_save from %s' % type(instance))


@receiver(pre_delete, sender=Script)
def _del_daq_daemons(sender, instance, **kwargs):
"""
update the daq daemon configuration when changes be applied in the models
"""
logger.debug("pre_delete script")
logger.debug(instance)
if type(instance) is Script:
try:
#todo select only one script not all
bp = BackgroundProcess.objects.get(process_class_kwargs__contains=str('"script_id": ' + str(instance.id)))
except:
return False
bp.stop()
else:
logger.debug('post_save from %s' % type(instance))
91 changes: 64 additions & 27 deletions pyscada/scripting/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@
def import_module_from_file(inst, file_name, func_name):
spec = spec_from_file_location('pyscada.scripting.user_script', file_name)
mod = module_from_spec(spec)
spec.loader.exec_module(mod)
try:
spec.loader.exec_module(mod)
except FileNotFoundError:
logger.warning("Script file not found : " + str(spec.origin))
return None
if not hasattr(mod, func_name):
return None
return MethodType(getattr(mod, func_name), inst)
Expand Down Expand Up @@ -311,6 +315,20 @@ def __init__(self, dt=5, **kwargs):
super(MasterProcess, self).__init__(dt=dt, **kwargs)
self.SCRIPT_PROCESSES = []

def _add_process_to_list(self, script_process):
bp = BackgroundProcess(label='pyscada.scripting-%d' % script_process.pk,
message='waiting..',
enabled=True,
parent_process_id=self.process_id,
process_class='pyscada.scripting.worker.ScriptingProcess',
process_class_kwargs=json.dumps({"script_id": script_process.pk,
'script_file': script_process.script_file,
'dt_set': script_process.interval}))
bp.save()
self.SCRIPT_PROCESSES.append({'id': bp.id,
'script_id': script_process.pk,
'failed': 0})

def init_process(self):
"""
for process in BackgroundProcess.objects.filter(parent_process__pk=self.process_id, done=False):
Expand All @@ -327,42 +345,61 @@ def init_process(self):
BackgroundProcess.objects.filter(parent_process__pk=self.process_id, done=False).delete()
"""
for script_process in Script.objects.filter(active=True):
bp = BackgroundProcess(label='pyscada.scripting.ScriptingProcess-%d' % script_process.pk,
message='waiting..',
enabled=True,
parent_process_id=self.process_id,
process_class='pyscada.scripting.worker.ScriptingProcess',
process_class_kwargs=json.dumps({"script_id": script_process.pk,
'script_file': script_process.script_file,
'dt_set': script_process.interval}))
bp.save()
self.SCRIPT_PROCESSES.append({'id': bp.id,
'script_id':script_process.pk,
'failed': 0})
self._add_process_to_list(script_process)

def loop(self):
"""
"""
#logger.debug(self.SCRIPT_PROCESSES)
#logger.debug(Script.objects.filter(active=True))
# add new active scripts
for s in Script.objects.filter(active=True):
script_found = False
for script_process in self.SCRIPT_PROCESSES:
if s.pk == script_process['script_id']:
script_found = True
if not script_found:
logger.info("%s not found - add script to %s" % (s.label, self.label))
self._add_process_to_list(s)

#logger.debug("script master loop")

# check if all scripting processes are running
for script_process in self.SCRIPT_PROCESSES:
try:
BackgroundProcess.objects.get(pk=script_process['id'])
except BackgroundProcess.DoesNotExist or BackgroundProcess.MultipleObjectsReturned:
bp = BackgroundProcess.objects.get(pk=script_process['id'])
# stop deactivated script and remove from list
try:
if not Script.objects.get(pk=script_process['script_id']).active:
bp.stop(cleanup=True)
logger.debug("stop %s" % bp)
logger.debug("remove %s" % script_process)
self.SCRIPT_PROCESSES.remove(script_process)
except Script.DoesNotExist:
bp.stop(cleanup=True)
logger.debug("stop %s" % bp)
logger.debug("remove %s" % script_process)
self.SCRIPT_PROCESSES.remove(script_process)
except (BackgroundProcess.DoesNotExist, BackgroundProcess.MultipleObjectsReturned):
# Process is dead, spawn new instance
if script_process['failed'] < 3:
script = Script.objects.get(pk=script_process['script_id'])
bp = BackgroundProcess(label='pyscada.scripting.ScriptingProcess-%d' % script.pk,
message='waiting..',
enabled=True,
parent_process_id=self.process_id,
process_class='pyscada.scripting.worker.ScriptingProcess',
process_class_kwargs=json.dumps({"script_id": script.pk,
'script_file': script.script_file,
'dt_set': script.interval}))
bp.save()
script_process['id'] = bp.id
script_process['failed'] += 1
try:
script = Script.objects.get(pk=script_process['script_id'], active=True)
bp = BackgroundProcess(label='pyscada.scripting-%d' % script.pk,
message='waiting..',
enabled=True,
parent_process_id=self.process_id,
process_class='pyscada.scripting.worker.ScriptingProcess',
process_class_kwargs=json.dumps({"script_id": script.pk,
'script_file': script.script_file,
'dt_set': script.interval}))
bp.save()
script_process['id'] = bp.id
script_process['failed'] += 1
except Script.DoesNotExist:
logger.debug("removing %s from list" % script_process)
self.SCRIPT_PROCESSES.remove(script_process)
else:
logger.error('process pyscada.scripting.user_script-%d failed more than 3 times' % script_process['script_id'])
except:
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
platforms=['OS Independent'],
classifiers=CLASSIFIERS,
install_requires=[
'pyscada',
'pyscada>=0.7.0rc18',
],
packages=find_packages(exclude=["project", "project.*"]),
include_package_data=True,
Expand Down

0 comments on commit e2f4a30

Please sign in to comment.