# HG changeset patch # User Alexandre Fayolle # Date 1292962819 -3600 # Node ID bc878ec35794eb68e5cc2b1e41f57000a0fe1f6f # Parent 46297c498842b65106e9a68e08bdbe81612f3ddc #1382705 forbid with sql level locking the simultaneous fireing of a transition on a given entity diff -r 46297c498842 -r bc878ec35794 hooks/workflow.py --- a/hooks/workflow.py Mon Jan 03 11:22:32 2011 +0100 +++ b/hooks/workflow.py Tue Dec 21 21:20:19 2010 +0100 @@ -191,6 +191,8 @@ msg = session._('mandatory relation') raise ValidationError(entity.eid, {qname: msg}) forentity = session.entity_from_eid(foreid) + # see comment in the TrInfo entity definition + entity.cw_edited['tr_count']=len(forentity.reverse_wf_info_for) iworkflowable = forentity.cw_adapt_to('IWorkflowable') # then check it has a workflow set, unless we're in the process of changing # entity's workflow diff -r 46297c498842 -r bc878ec35794 misc/migration/3.10.7_Any.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/migration/3.10.7_Any.py Tue Dec 21 21:20:19 2010 +0100 @@ -0,0 +1,2 @@ +add_attribute('TrInfo', 'tr_count') +sync_schema_props_perms('TrInfo') diff -r 46297c498842 -r bc878ec35794 schemas/workflow.py --- a/schemas/workflow.py Mon Jan 03 11:22:32 2011 +0100 +++ b/schemas/workflow.py Tue Dec 21 21:20:19 2010 +0100 @@ -22,7 +22,7 @@ _ = unicode from yams.buildobjs import (EntityType, RelationType, SubjectRelation, - RichString, String) + RichString, String, Int) from cubicweb.schema import RQLConstraint, RQLUniqueConstraint from cubicweb.schemas import (META_ETYPE_PERMS, META_RTYPE_PERMS, HOOKS_RTYPE_PERMS) @@ -159,13 +159,21 @@ 'delete': (), # XXX should we allow managers to delete TrInfo? 'update': ('managers', 'owners',), } - - from_state = SubjectRelation('State', cardinality='1*') - to_state = SubjectRelation('State', cardinality='1*') + # The unique_together constraint ensures that 2 repositories + # sharing the db won't be able to fire a transition simultaneously + # on the same entity tr_count is filled in the FireTransitionHook + # to the number of TrInfo attached to the entity on which we + # attempt to fire a transition. In other word, it contains the + # rank of the TrInfo for that entity, and the constraint says we + # cannot have 2 TrInfo with the same rank. + __unique_together__ = [('tr_count', 'wf_info_for')] + from_state = SubjectRelation('State', cardinality='1*', inlined=True) + to_state = SubjectRelation('State', cardinality='1*', inlined=True) # make by_transition optional because we want to allow managers to set # entity into an arbitrary state without having to respect wf transition by_transition = SubjectRelation('BaseTransition', cardinality='?*') comment = RichString(fulltextindexed=True) + tr_count = Int(description='autocomputed attribute used to ensure transition coherency') # get actor and date time using owned_by and creation_date class from_state(RelationType):