Skip to content

Commit

Permalink
rref #5357
Browse files Browse the repository at this point in the history
ref #GH-64
p70 #5357
  • Loading branch information
evrenesat committed Aug 26, 2016
1 parent d73142b commit cdb2b31
Show file tree
Hide file tree
Showing 10 changed files with 347 additions and 74 deletions.
4 changes: 4 additions & 0 deletions tests/test_management_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ def test_update_permissions():
# TODO: Add cleanup for both Permission and User models
# TODO: Add assertation
ManagementCommands(args=['update_permissions'])

def test_load_load_diagrams():
ManagementCommands(args=['load_diagrams'])
#ManagementCommands(args=['load_diagrams', '--wf_path', './diagrams/multi_user2.bpmn'])
6 changes: 4 additions & 2 deletions zengine/current.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,17 @@
from zengine import signals
from zengine.client_queue import ClientQueue
from zengine.config import settings
from zengine.lib.cache import WFCache
from zengine.log import log
from zengine.models import WFCache

DEFAULT_LANE_CHANGE_MSG = {
'title': settings.MESSAGES['lane_change_message_title'],
'body': settings.MESSAGES['lane_change_message_body'],
}




class Current(object):
"""
This object holds the whole state of the app for passing to view methods (views/tasks)
Expand Down Expand Up @@ -186,7 +188,7 @@ def __init__(self, **kwargs):
self.new_token = True
# log.info("TOKEN NEW: %s " % self.token)

self.wfcache = WFCache(self.token)
self.wfcache = WFCache(self.token, self.session.sess_id)
# log.debug("\n\nWF_CACHE: %s" % self.wfcache.get())
self.set_client_cmds()

Expand Down
21 changes: 14 additions & 7 deletions zengine/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,13 @@
from zengine.auth.permissions import PERM_REQ_TASK_TYPES
from zengine.config import settings
from zengine.current import WFCurrent
from zengine.lib.camunda_parser import InMemoryPackager
from zengine.lib.camunda_parser import InMemoryPackager, ZopsSerializer
from zengine.lib.exceptions import HTTPError
from zengine.log import log


# crud_view = CrudView()
from zengine.models import BPMNWorkflow


class ZEngine(object):
Expand Down Expand Up @@ -175,7 +176,7 @@ def load_or_create_workflow(self):
Tries to load the previously serialized (and saved) workflow
Creates a new one if it can't
"""
self.workflow_spec = self.get_worfklow_spec()
self.workflow_spec = self.get_worfklow_spec
return self._load_workflow() or self.create_workflow()
# self.current.update(workflow=self.workflow)

Expand All @@ -195,6 +196,7 @@ def find_workflow_path(self):
log.error(err_msg)
raise RuntimeError(err_msg)

@property
def get_worfklow_spec(self):
"""
Generates and caches the workflow spec package from
Expand All @@ -205,9 +207,14 @@ def get_worfklow_spec(self):
"""
# TODO: convert from in-process to redis based caching
if self.current.workflow_name not in self.workflow_spec_cache:
path = self.find_workflow_path()
spec_package = InMemoryPackager.package_in_memory(self.current.workflow_name, path)
spec = BpmnSerializer().deserialize_workflow_spec(spec_package)
# path = self.find_workflow_path()
# spec_package = InMemoryPackager.package_in_memory(self.current.workflow_name, path)
# spec = BpmnSerializer().deserialize_workflow_spec(spec_package)

self.current.wf_object = BPMNWorkflow.objects.get(name=self.current.workflow_name)
xml_content = self.current.wf_object.xml.body
spec = ZopsSerializer().deserialize_workflow_spec(xml_content, self.current.workflow_name)

self.workflow_spec_cache[self.current.workflow_name] = spec
return self.workflow_spec_cache[self.current.workflow_name]

Expand Down Expand Up @@ -281,7 +288,7 @@ def switch_from_external_to_main_wf(self):
if self.wf_cache['in_external'] and self.current.task_type == 'Simple' and self.current.task_name == 'End':
main_wf = self.wf_cache['main_wf']
self.current.workflow_name = main_wf['wf_name']
self.workflow_spec = self.get_worfklow_spec()
self.workflow_spec = self.get_worfklow_spec
self.workflow = self.deserialize_workflow(main_wf['wf_state'])
self.current.workflow = self.workflow
self.wf_cache['in_external'] = False
Expand All @@ -299,7 +306,7 @@ def switch_to_external_wf(self):
main_wf = self.wf_cache.copy()
external_wf_name = self.current.task.task_spec.topic
self.current.workflow_name = external_wf_name
self.workflow_spec = self.get_worfklow_spec()
self.workflow_spec = self.get_worfklow_spec
self.workflow = self.create_workflow()
self.current.workflow = self.workflow
self.check_for_authentication()
Expand Down
11 changes: 0 additions & 11 deletions zengine/lib/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,17 +267,6 @@ def is_alive(self):
return time.time() - float(self.get(0.0)) < self.SESSION_EXPIRE_TIME


class WFCache(Cache):
"""
Cache object for workflow instances.
Args:
wf_token: Token of the workflow instance.
"""
PREFIX = 'WF'

def __init__(self, wf_token):
super(WFCache, self).__init__(wf_token)


class ClearCache(Cache):
Expand Down
19 changes: 18 additions & 1 deletion zengine/lib/camunda_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@
#
# This file is licensed under the GNU General Public License v3
# (GPLv3). See LICENSE.txt for details.
from StringIO import StringIO

from SpiffWorkflow.bpmn.parser.util import full_attr, BPMN_MODEL_NS, ATTRIBUTE_NS
from SpiffWorkflow.bpmn.storage.BpmnSerializer import BpmnSerializer
from SpiffWorkflow.bpmn.storage.Packager import Packager
from SpiffWorkflow.storage.Serializer import Serializer
from six import BytesIO

import xml.etree.ElementTree as ET
__author__ = "Evren Esat Ozkan"

from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnParser
Expand Down Expand Up @@ -185,6 +189,19 @@ def _parse_list(cls, elm):
def _parse_script(cls, elm):
return elm.get('scriptFormat'), elm.text

class ZopsSerializer(Serializer):
"""
Deserialize direct XML -> Spec
"""

def deserialize_workflow_spec(self, xml_content, filename):

parser = CamundaBMPNParser()
bpmn = ET.parse(BytesIO(xml_content))
parser.add_bpmn_xml(bpmn, svg=None, filename='%s' % filename)
return parser.get_spec(filename)


class InMemoryPackager(Packager):
"""
Creates spiff's wf packages on the fly.
Expand Down
86 changes: 81 additions & 5 deletions zengine/management_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
#
# This file is licensed under the GNU General Public License v3
# (GPLv3). See LICENSE.txt for details.
import glob

import six

from pyoko.db.adapter.db_riak import BlockSave
from pyoko.db.adapter.db_riak import BlockSave, BlockDelete
from pyoko.exceptions import ObjectDoesNotExist
from pyoko.lib.utils import get_object_from_path
from pyoko.manage import *
Expand Down Expand Up @@ -194,8 +196,6 @@ def run(self):
worker.run()




class PrepareMQ(Command):
"""
Creates necessary exchanges, queues and bindings
Expand Down Expand Up @@ -236,12 +236,88 @@ class LoadDiagrams(Command):
"""
Loads wf diagrams from disk to DB
"""

CMD_NAME = 'load_diagrams'
HELP = 'Loads workflow diagrams from diagrams folder to DB'
PARAMS = [
{'name': 'wf_path', 'default': None, 'help': 'Only update given BPMN diagram'},
{'name': 'clear', 'action': 'store_true', 'help': 'Clear all task related models'},
{'name': 'force', 'action': 'store_true', 'help': 'Load BPMN file even if there are active WFInstances exists.'},
]

def run(self):
self.get_workflows()
"""
read workflows, checks if it's updated,
tries to update if there aren't any running instances of that wf
"""
from zengine.models.workflow_manager import DiagramXML, BPMNWorkflow, RunningInstancesExist

if self.manager.args.clear:
self._clear_models()
return

if self.manager.args.wf_path:
paths = self.get_wf_from_path(self.manager.args.wf_path)
else:
paths = self.get_workflows()
count = 0
for wf_name, content in paths:
wf, wf_is_new = BPMNWorkflow.objects.get_or_create(name=wf_name)
content = self._tmp_fix_diagram(content)
diagram, diagram_is_updated = DiagramXML.get_or_create_by_content(wf_name, content)
if wf_is_new or diagram_is_updated:
count += 1
print("%s created or updated" % wf_name.upper())
try:
wf.set_xml(diagram, self.manager.args.force)
except RunningInstancesExist as e:
print(e.message)
print("Give \"--force\" parameter to enforce")
print("%s BPMN file loaded" % count)


def _clear_models(self):
from zengine.models.workflow_manager import DiagramXML, BPMNWorkflow, WFInstance
print("Workflow related models will be cleared")
c = len(DiagramXML.objects.delete())
print("%s DiagramXML object deleted" % c)
c = len(BPMNWorkflow.objects.delete())
print("%s BPMNWorkflow object deleted" % c)
c = len(WFInstance.objects.delete())
print("%s WFInstance object deleted" % c)

def _tmp_fix_diagram(self, content):
# Temporary solution for easier transition from old to new xml format
# TODO: Will be removed after all diagrams converted.
return content.replace(
'targetNamespace="http://activiti.org/bpmn"',
'targetNamespace="http://bpmn.io/schema/bpmn"'
).replace(
'xmlns:camunda="http://activiti.org/bpmn"',
'xmlns:camunda="http://camunda.org/schema/1.0/bpmn"'
)

def get_wf_from_path(self, path):
"""
load xml from given path
Args:
path: diagram path
Returns:
"""
with open(path) as fp:
content = fp.read()
return [(os.path.basename(os.path.splitext(path)[0]), content), ]

def get_workflows(self):
pass
"""
Scans and loads all wf found under WORKFLOW_PACKAGES_PATHS
Yields: XML content of diagram file
"""
for pth in settings.WORKFLOW_PACKAGES_PATHS:
for f in glob.glob("%s/*.bpmn" % pth):
with open(f) as fp:
yield os.path.basename(os.path.splitext(f)[0]), fp.read()
1 change: 1 addition & 0 deletions zengine/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
# This file is licensed under the GNU General Public License v3
# (GPLv3). See LICENSE.txt for details.
from .auth import *
from .workflow_manager import *
from ..messaging.model import *
2 changes: 1 addition & 1 deletion zengine/models/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Unit(Model):
"""
name = field.String("İsim", index=True)
parent = LinkProxy('Unit', verbose_name='Parent Unit', reverse_name='sub_units')
# parent = LinkProxy('Unit', verbose_name='Parent Unit', reverse_name='sub_units')

class Meta:
verbose_name = "Unit"
Expand Down
Loading

0 comments on commit cdb2b31

Please sign in to comment.