Skip to content
This repository was archived by the owner on Nov 9, 2022. It is now read-only.

Commit 5161c97

Browse files
authored
Merge pull request #101 from adamfowleruk/feature-100
Version 1.1 in flight fix. Introduces locking. Fixes #100.
2 parents 245fa5c + 54d4606 commit 5161c97

34 files changed

+244
-57
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module.exports = {"host":"192.168.123.225","port":"6061","database":"workflow-content",
1+
{"host":"192.168.123.4","port":"6061","database":"workflow-content",
22
"username":"admin","password":"admin","auth":"digest","defaultuser":"nobody","webport":5001,
33
"alertport":5002,"apppath":"./app","defaultpath":"/workplace.html5","modulesport":6060,
44
"modulesdatabase":"workflow-modules","ssl":false,"adminport":8002,"triggersdatabase":"Triggers"}

config/webserver-settings.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# CREATED BY YEOMAN generator-mljsworkplace!
44

5-
RESTHOST=192.168.123.225
5+
RESTHOST=192.168.123.4
66
RESTPORT=6061
77
DATABASE=workflow-content
88
MLADMINUSER=admin

modules/app/models/workflow-actions.xqy

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,27 @@ declare namespace error="http://marklogic.com/xdmp/error";
2121
declare function update-userTask($processId as xs:string,$data as node()*,$attachments as node()*) as node()? {
2222
let $_ := xdmp:log("In wfa:update-userTask")
2323
return
24-
update-generic($processId,$data,$attachments)
24+
update-generic($processId,$data,$attachments)
2525
};
2626

2727
(:
2828
: Complete a user task, moving it on to the next step. (Just marks as complete)
2929
:)
3030
declare function complete-userTask($processId as xs:string,$data as node()*,$attachments as node()*) as node()? {
3131
let $_ := xdmp:log("In wfa:complete-userTask")
32+
let $unlock :=
33+
if (fn:not(fn:empty(wfu:getProperties($processId)/wf:currentStep/wf:lock))) then
34+
wfu:unlock($processId) (: We call this to ensure this user has the current lock, even though wf:currentStep will be deleted :)
35+
else
36+
()
3237
(: Find process document :)
3338
(: Get next step ID :)
3439
(: TODO check required attachments and properties here (Should be done in the UI) :)
35-
let $update := update-userTask($processId,$data,$attachments)
40+
let $update :=
41+
if (fn:empty($unlock)) then
42+
update-userTask($processId,$data,$attachments)
43+
else
44+
$unlock (: report issue :)
3645
(: TODO lookup functionality from document patch in REST API to see if we can replicate that method here :)
3746
return
3847
if (fn:empty($update)) then complete-generic($processId) else $update

modules/app/models/workflow-util.xqy

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,66 @@ declare function m:list($processName as xs:string?) as element(wf:list) {
192192

193193

194194

195+
(:
196+
: Called by the REST API only.
197+
:)
198+
declare function m:lock($processId as xs:string) as node()? {
199+
(: Check that this is a human queue task or user task :)
200+
let $props := m:getProperties($processId)
201+
return
202+
if ($props/wf:currentStep/wf:step-type = "userTask" and $props/wf:currentStep/wf:step-status = "ENTERED") then
203+
if ($props/wf:currentStep/wf:type = "user" or $props/wf:currentStep/wf:type = "queue" or $props/wf:currentStep/wf:type = "role") then
204+
if (fn:empty($props/wf:currentStep/wf:lock)) then
205+
(: lock and return success :) (: TODO check what happens if this call fails... :)
206+
(
207+
xdmp:node-insert-child($props/wf:currentStep,<wf:lock><wf:by>{xdmp:get-current-user()}</wf:by><wf:when>{fn:current-dateTime()}</wf:when></wf:lock>)
208+
,
209+
m:audit(m:getProcessUri($processId),(),"ProcessEngine","Work item locked by '" || xdmp:get-current-user() || "'",())
210+
)
211+
else
212+
if ($props/wf:currentStep/wf:lock/wf:by = xdmp:get-current-user()) then
213+
(: Do nothing - ok :)
214+
()
215+
else
216+
(: Fail :)
217+
"Could not lock work item. Work item is already locked by '" || xs:string($props/wf:currentStep/wf:lock/wf:by) || "'"
218+
else
219+
"Could not lock work item. userTask type '" || xs:string($props/wf:currentStep/wf:type) || "' not supported for locking."
220+
else
221+
"Could not lock work item. Step is not a userTask, or status is not 'ENTERED'. Try again."
222+
(: If assigned to user task, and this user, always return true even if already locked :)
223+
(: Check that this item is not already locked if a queue task :)
224+
(: Lock the work item :)
225+
(: Return blank if ok :)
226+
};
227+
228+
(:
229+
: Allow unlocking of a work item. (Not the same as completion). Does not return data.
230+
:)
231+
declare function m:unlock($processId as xs:string) as node()? {
232+
let $props := m:getProperties($processId)
233+
return
234+
if ($props/wf:currentStep/wf:step-type = "userTask" and $props/wf:currentStep/wf:step-status = "ENTERED") then
235+
if ($props/wf:currentStep/wf:type = "user" or $props/wf:currentStep/wf:type = "queue" or $props/wf:currentStep/wf:type = "role") then
236+
if (fn:empty($props/wf:currentStep/wf:lock)) then
237+
() (: Just succeed, rather than error - means we are alreay unlocked! :)
238+
else
239+
if ($props/wf:currentStep/wf:lock/wf:by = xdmp:get-current-user()) then
240+
(: Unlock :)
241+
(
242+
xdmp:node-delete($props/wf:currentStep/wf:lock)
243+
,
244+
m:audit(m:getProcessUri($processId),(),"ProcessEngine","Work item unlocked by '" || xdmp:get-current-user() || "'",())
245+
)
246+
else
247+
(: Fail :)
248+
"Could not unlock work item. Work item is locked by a different user: '" || xs:string($props/wf:currentStep/wf:lock/wf:by) || "'"
249+
else
250+
"Could not unlock work item. userTask type '" || xs:string($props/wf:currentStep/wf:type) || "' not supported for locking."
251+
else
252+
"Could not unlock work item. Step is not a userTask, or status is not 'ENTERED'. Try again."
253+
};
254+
195255

196256
(:
197257
: This module performs process data document update functions via a high level abstraction.

rest-api/ext/process.xqy

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import module namespace wfa="http://marklogic.com/workflow-actions" at "/app/mod
1717
declare namespace roxy = "http://marklogic.com/roxy";
1818
declare namespace wf="http://marklogic.com/workflow";
1919

20+
declare namespace rapi = "http://marklogic.com/rest-api";
21+
2022
(:
2123
: To add parameters to the functions, specify them in the params annotations.
2224
: Example
@@ -124,9 +126,17 @@ function ext:get(
124126

125127

126128

127-
(: POST - update a process instance, potentially completing it (e.g. human step) :)
129+
(:
130+
: POST - update a process instance, potentially completing it (e.g. human step)
131+
:
132+
: POST process?processid=1234 -> Updates data only, does not lock or unlock item. DEPRECATED in current form - In future this will respect locks. Does not yet.
133+
: POST process?processid=1234&complete=true -> Completes work item. Respects locks. (optionally) updates work item data.
134+
: POST process?processid=1234&lock=true -> Locks the work item for the current user. (optionally) updates work item data. Respects locks.
135+
: POST process?processid=1234&unlock=true -> Unlocks the work item if locked by current user. (optionally) update work item data. Respects locks.
136+
:)
128137
declare
129138
%roxy:params("")
139+
%rapi:transaction-mode("update")
130140
function ext:post(
131141
$context as map:map,
132142
$params as map:map,
@@ -135,6 +145,8 @@ function ext:post(
135145

136146
let $preftype := if ("application/xml" = map:get($context,"accept-types")) then "application/xml" else "application/json"
137147

148+
let $part := (map:get($params,"part"),"document")[1]
149+
138150
let $_ := xdmp:log($input)
139151
let $pid := map:get($params,"processid")
140152
(:let $proc := wfu:get($pid):)
@@ -165,8 +177,63 @@ function ext:post(
165177
(: error - cannot call complete on non completable task :)
166178
<ext:updateResponse><ext:outcome>FAILURE</ext:outcome><ext:message>Cannot call complete on non completable task: {$props/wf:step-type/text()}</ext:message></ext:updateResponse>
167179
else
168-
(: TODO perform a data update but leave incomplete :)
169-
<ext:updateResponse><ext:outcome>SUCCESS</ext:outcome><ext:message>No complete parameter, or complete parameter false. Leaving incomplete.</ext:message></ext:updateResponse>
180+
181+
if ("true" = map:get($params,"lock")) then
182+
(: Lock the work item, and return its details as if get had been called. If already locked, instead return an error :)
183+
let $feedback := wfu:lock($pid)
184+
let $update :=
185+
if (fn:empty($feedback)) then
186+
<ext:readResponse><ext:outcome>SUCCESS</ext:outcome>
187+
{if ($part = "document") then
188+
<ext:document>{wfu:get(map:get($params,"processid"))}</ext:document>
189+
else if ($part = "properties") then
190+
<ext:properties>{wfu:getProperties(map:get($params,"processid"))}</ext:properties>
191+
else
192+
(<ext:document>{wfu:get(map:get($params,"processid"))}</ext:document>,
193+
<ext:properties>{wfu:getProperties(map:get($params,"processid"))}</ext:properties>)
194+
}
195+
</ext:readResponse>
196+
else
197+
<ext:updateResponse><ext:outcome>FAILURE</ext:outcome><ext:message>Work item could not be locked by user.</ext:message><ext:feedback>{$feedback}</ext:feedback></ext:updateResponse>
198+
return
199+
if (fn:empty($feedback)) then
200+
let $fb := wfa:update-userTask($pid,$input/ext:updateRequest/wf:data/node(),$input/ext:updateRequest/wf:attachments/node())
201+
return
202+
if (fn:not(fn:empty($fb))) then
203+
<ext:updateResponse><ext:outcome>FAILURE</ext:outcome><ext:message>Could not update userTask</ext:message><ext:feedback>{$fb}</ext:feedback></ext:updateResponse>
204+
else
205+
$update
206+
else
207+
$update
208+
else
209+
if ("true" = map:get($params,"unlock")) then
210+
let $feedback := wfu:unlock($pid)
211+
let $update :=
212+
if (fn:empty($feedback)) then
213+
<ext:readResponse><ext:outcome>SUCCESS</ext:outcome>
214+
{if ($part = "document") then
215+
<ext:document>{wfu:get(map:get($params,"processid"))}</ext:document>
216+
else if ($part = "properties") then
217+
<ext:properties>{wfu:getProperties(map:get($params,"processid"))}</ext:properties>
218+
else
219+
(<ext:document>{wfu:get(map:get($params,"processid"))}</ext:document>,
220+
<ext:properties>{wfu:getProperties(map:get($params,"processid"))}</ext:properties>)
221+
}
222+
</ext:readResponse>
223+
else
224+
<ext:updateResponse><ext:outcome>FAILURE</ext:outcome><ext:message>Work item could not be unlocked by user.</ext:message><ext:feedback>{$feedback}</ext:feedback></ext:updateResponse>
225+
return
226+
if (fn:empty($feedback)) then
227+
let $fb := wfa:update-userTask($pid,$input/ext:updateRequest/wf:data/node(),$input/ext:updateRequest/wf:attachments/node())
228+
return
229+
if (fn:not(fn:empty($fb))) then
230+
<ext:updateResponse><ext:outcome>FAILURE</ext:outcome><ext:message>Could not update userTask</ext:message><ext:feedback>{$fb}</ext:feedback></ext:updateResponse>
231+
else
232+
$update
233+
else
234+
$update
235+
else
236+
() (: Just default to updating the data, but doing nothing around locking :)
170237

171238

172239
let $out := ($res,<ext:updateResponse><ext:outcome>SUCCESS</ext:outcome></ext:updateResponse>)[1]

shtests/01-processmodel-create-out.txt

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)