Lost scheduled trigger requests

Hello, I have following issue with implemented threestep publishing workflow

test 1
User1 edit save and ask for publish for 1 document
User2 confirm publication
Result : document is published.

test 2
User1 edit save and ask for scheduled publish for 1 document
User2 confirm scheduled publication
Result : document is published (scheduled).

test 3
User1 edit save and ask for scheduled publish for 2 documents
User2 confirm all 2 scheduled publications
Result : only one document is published (scheduled).

test 4
User1 edit save and ask for scheduled publish for more than 2 documents
User2 confirm all scheduled publications
Result : only 2 documents are published (scheduled).

Results of Test with two different hippo configurations :

  1. All tests works fine if H2 ist configured (local)
  2. Test 1 and 2 OK, Test 3 and 4 fails if Oracle configuration (Using DB) is used

What I found :

  1. Hippo creates 2 Threads to read and execute workflows. Its hardcoded.
    So I can see in Log
    Hippo JCR Quartz Job Scheduler_Worker-1
    Hippo JCR Quartz Job Scheduler_Worker-2

Thats why max 2 Publish-request could be processed

  1. I reimplemented WorkflowJob (from org.onehippo.repository.documentworkflow.task.ScheduleWorkflowTask
    And got ALL Threads works sync :

public void execute(RepositoryJobExecutionContext context) throws RepositoryException {
log.info("****** WATING FOR SYNC SCHEDULING JOB… " + this.hashCode());
synchronized ( LOCK )
{
log.info("****** START SYNC SCHEDULING JOB… " + this.hashCode());

Just to check if there are some kind of racing conditions.

  1. I inserted Select at the begining and at the end of Job, to check hom much request exists every time Workflow ist started

Query query = qMgr.createQuery(“SELECT * FROM hipposched:trigger WHERE hipposched:nextFireTime <= TIMESTAMP '” + ISO8601.format(cal) + “’ ORDER BY hipposched:nextFireTime”, “sql”);

Now example with 3 documents

H2 Configurations runs like this :

Worker 1 starts and says we have 3 requests pending
Worker 2 starts and wait for worker 1
Worker 1 publish document1
Worker 1 finish and says wir have 3 requests pending
Hippo says : autoexport is processing changes…
Worker 2 starts and says we have 2 requests pending
Worker 1 starts and wait for worker 1
Worker 2 publish document2
Worker 2 finish and says wir have 2 requests pending
Hippo says : autoexport is processing changes…
Worker 1 starts and says we have 1 request pending
Worker 1 publish document3
Worker 1 finish and says wir have 1 requests pending
Hippo says : autoexport is processing changes…

Everything works fine :slight_smile: All documents are published successfully

Oracle Configurations runs like this :

Worker 1 starts and says we have 3 requests pending (doc1 doc2 and doc3)
Worker 2 starts and wait for worker 1
Worker 1 publish document1

!!! now happens something strange
24.07.2018 12:08:02 [ClusterNode-gf0vsxja839e.corp.int] INFO [org.apache.jackrabbit.core.cluster.ClusterNode.consume():858] Processing revision: 5796
24.07.2018 12:08:02 [ClusterNode-gf0vsxja839e.corp.int] INFO [org.apache.jackrabbit.core.cluster.ClusterNode.process():930] [174] 5796 system@default:/content/documents/HippoCMS/homepage/wissenswert/document2
!!!

Publish-Request for Doc2 disappears

Worker 1 finish and says wir have 2 requests pending (doc1 and doc3)
Worker 2 starts and says we have 1 requests pending (doc3)
Worker 1 starts and wait for worker 1
Worker 2 publish document3
Worker 2 finish and says wir have 1 request pending (doc3)

I’m not able to find out WHY Hippo consumes document2.
Error could be reproduced everytime.
If I have 6 Documents . all of Requests except two, will be consumed by hippo :frowning:

Scheduled publishing of more that 1 Document on https://cms.demo.onehippo.com/ works, But I think there ist H2 Configuration not MySQL or Oracle.

Oracle/Hippo started params and configuration :

One CMS Server

Hippo Release version 12.3.0
Hippo CMS version 5.3.0
Repository vendor Hippo B.V.
Repository version 5.3.0
Memory maximum 910.5 MB
Memory taken 500.5 MB
Memory free 68.16 MB
Memory in use 432.34 MB
Memory total free 478.16 MB
Java vendor Oracle Corporation
Java version 1.8.0_151
Java VM OpenJDK 64-Bit Server VM
OS architecture amd64
OS name Linux
OS version 3.10.0-862.6.3.el7.x86_64
Processors # 2

/usr/lib/jvm/java/bin/java -Xms512m -Xmx1g -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=256m -classpath /usr/share/tomcat8/bin/bootstrap.jar:/usr/share/tomcat8/bin/tomcat-juli.jar:/usr/share/tomcat8/bin/commons-daemon.jar -Dcatalina.base=/usr/share/tomcat8 -Dcatalina.home=/usr/share/tomcat8 -Djava.endorsed.dirs= -Djava.io.tmpdir=/J2EE/var/tomcat/temp -Djava.util.logging.config.file=/usr/share/tomcat8/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dorg.apache.jackrabbit.core.cluster.node_id=gf0vsxja839e.corp.int -Dlog4j.configurationFile=file:///J2EE/opt/tomcat/appconf/log4j2.xml -DLog4jContextSelector=org.apache.logging.log4j.core.selector.BasicContextSelector -Drepo.config=file:/J2EE/opt/tomcat/appconf/repository.xml org.apache.catalina.startup.Bootstrap start

One SITE Server

/usr/lib/jvm/java/bin/java -Xms512m -Xmx1g -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=256m -classpath /usr/share/tomcat8/bin/bootstrap.jar:/usr/share/tomcat8/bin/tomcat-juli.jar:/usr/share/tomcat8/bin/commons-daemon.jar -Dcatalina.base=/usr/share/tomcat8 -Dcatalina.home=/usr/share/tomcat8 -Djava.endorsed.dirs= -Djava.io.tmpdir=/J2EE/var/tomcat/temp -Djava.util.logging.config.file=/usr/share/tomcat8/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dorg.apache.jackrabbit.core.cluster.node_id=gf0vsxja843e.corp.int -Dlog4j.configurationFile=file:///J2EE/opt/tomcat/appconf/log4j2.xml -DLog4jContextSelector=org.apache.logging.log4j.core.selector.BasicContextSelector -Drepo.config=file:/J2EE/opt/tomcat/appconf/repository.xml org.apache.catalina.startup.Bootstrap start
svcwsmon 23570 23540 0 15:08 pts/0 00:00:00 grep --color=auto tomcat

WORKFLOW . PART 1

<?xml version="1.0" encoding="UTF-8" ?>
<!-- the atomic status state is used to report several statuses and info feedback to the invoking workflow -->
<state id="status">
  <onentry>
    <hippo:feedback key="status" value="editable"/>
    <hippo:feedback key="isLive" value="live"/>
    <hippo:feedback key="previewAvailable" value="previewAvailable"/>
    <!-- enable the checkModified operation if both draft and unpublished variants exists -->
    <hippo:action action="checkModified" enabledExpr="draft and unpublished"/>
  </onentry>

  <!-- target-less transition on event checkModified to compare the draft and unpublished variants which result is
       reported back as Boolean value through the 'modified' feedback variable and the workflow operation result -->
  <transition event="checkModified">
    <hippo:isModified/>
    <hippo:result value="workflowContext.feedback['modified']"/>
  </transition>
</state>

<!-- the composite edit state is used to manage all operations for editing a draft variant -->
<state id="edit">

  <!-- default no-edit state initially disables all editing operations -->
  <state id="no-edit">
    <onentry>
      <hippo:action action="disposeEditableInstance" enabledExpr="false"/>
      <hippo:action action="obtainEditableInstance" enabledExpr="false"/>
      <hippo:action action="commitEditableInstance" enabledExpr="false"/>
    </onentry>
    <!-- event-less transition to state "editing" if there is no pending request and the draft variant is edited -->
    <transition target="editing" cond="!requestPending and editing"/>
    <!-- (else) event-less transition to state "editable" if there is no pending request and the draft variant
                doesn't exist yet or isn't edited -->
    <transition target="editable" cond="!requestPending"/>
  </state>

  <!-- editing state becomes active when the draft variant is currently edited -->
  <state id="editing">
    <onentry>
      <if cond="editor">
        <!-- current editor is allowed all editing operations -->
        <hippo:action action="disposeEditableInstance" enabledExpr="true"/>
        <hippo:action action="obtainEditableInstance" enabledExpr="true"/>
        <hippo:action action="commitEditableInstance" enabledExpr="true"/>
        <else/>
        <!-- for a not-current editor the current editor (holder) is reported through the 'inUseBy' feedback -->
        <hippo:feedback key="inUseBy" value="holder"/>
      </if>
      <if cond="!editor and workflowContext.isGranted(draft,'hippo:editor')">
        <!-- For an admin (granted hippo:admin) enable the unlock operation if not-current editor -->
        <hippo:action action="unlock" enabledExpr="true"/>
      </if>
    </onentry>
  </state>

  <!-- editable state becomes active if editing is possible but there is no current editor -->
  <state id="editable">
    <onentry>
      <if cond="workflowContext.isGranted(draft,'hippo:editor')">
        <!-- for an admin (granted hippo:admin) report the unlock operation as available but disabled -->
        <hippo:action action="unlock" enabledExpr="false"/>
      </if>
      <!-- enable the operation to start editing -->
      <hippo:action action="obtainEditableInstance" enabledExpr="true"/>
    </onentry>
  </state>

  <!-- target-less transition to 'dispose' an editable instance by (only) removing the current draft holder, and the
       current unpublished document variant is returned if currently in preview state else the published variant -->
  <transition event="disposeEditableInstance">
    <!-- remove holder from the draft document -->
    <hippo:setHolder holder="null"/>
    <hippo:result value="preview ? unpublished : published"/>
  </transition>

  <!-- target-less transition to 'obtain' an editable draft document variant by creating or updating a draft variant
       by copying (the contents of) the current unpublished variant if available or else the published variant -->
  <transition event="obtainEditableInstance">
    <if cond="!!unpublished">
      <!-- unpublished document exists: copy it to draft first -->
      <hippo:copyVariant sourceState="unpublished" targetState="draft"/>
      <elseif cond="!!published"/>
      <!-- else if published document exists: first copy it to unpublished -->
      <hippo:copyVariant sourceState="published" targetState="unpublished"/>
      <if cond="live">
        <hippo:configVariant variant="published" availabilities="live"/>
        <else/>
        <hippo:configVariant variant="published" availabilities=""/>
      </if>
      <hippo:configVariant variant="unpublished" versionable="true" availabilities="preview"/>
      <!-- create a JCR version of the published document via the unpublished variant -->
      <hippo:version variant="unpublished"/>
      <!-- now copy the unpublished variant to draft -->
      <hippo:copyVariant sourceState="unpublished" targetState="draft"/>
    </if>
    <!-- mark the draft document as modified, set the user as editor and remove possibly copied availabilities -->
    <hippo:configVariant variant="draft" applyModified="true" setHolder="true" availabilities=""/>
    <!-- store the newly created or updated draft document as result -->
    <hippo:result value="draft"/>
  </transition>

  <!-- target-less transition to 'commit' an editable instance by removing the holder and, if new or modified,
       copying its content to the unpublished variant -->
  <transition event="commitEditableInstance">
    <hippo:setHolder holder="null"/>
    <if cond="!!unpublished">
      <!-- if unpublished variant exist only 'commit' changes if there are any -->
      <hippo:isModified/>
    </if>
    <if cond="!unpublished or workflowContext.feedback['modified']">
      <!-- we either have a new draft (no unpublished) or the draft is modified compared to the unpublished -->
      <if cond="!unpublished and !!published">
        <!-- we have no unpublished variant yet but do have a published variant:
             remove possible 'preview' availability from the published variant -->
        <if cond="live">
          <hippo:configVariant variant="published" availabilities="live"/>
          <else/>
          <hippo:configVariant variant="published" availabilities=""/>
        </if>
      </if>
      <!-- copy the new or modified draft variant to the unpublished variant, creating it if needed -->
      <hippo:copyVariant sourceState="draft" targetState="unpublished"/>
      <!-- configure the new or updated unpublished to be versionable, modified and available as 'preview' -->
      <hippo:configVariant variant="unpublished" versionable="true" applyModified="true" availabilities="preview"/>
    </if>
    <!-- return the possibly updated unpublished variant -->
    <hippo:result value="unpublished"/>
  </transition>

  <!-- target-less transition to 'unlock' the current edited draft variant by overriding its current holder
       with that of the current invoking admin (granted hippo:admin) user. -->
  <transition event="unlock">
    <hippo:setHolder holder="user"/>
  </transition>

</state>

<!-- the composite request state is used to manage all workflow operations on existing document workflow requests -->
<state id="request">

  <!-- the initial no-request state is used and active when there are no current document workflow requests -->
  <state id="no-request">
    <!-- event-less transition to state "requested" when requests exists -->
    <transition target="requested" cond="!empty(requests)"/>
  </state>

  <!-- the requested state becomes active when document workflow requests are present -->
  <state id="requested">
    <onentry>
      <foreach item="request" array="requests.values()">
        <!-- for all requests determine the available request actions and report them through the special 'requests'
             feedback map variable -->
        <!-- for document workflow requests: -->
        <if cond="request.requestType=='threestep:request'">
          <if cond="request.isStateRequest">
            <hippo:action action="requestReview" enabledExpr="false"/>
            <if cond="request.owner==user">
              <hippo:action action="cancelReview" enabledExpr="true"/>
            </if>
            <if cond="request.owner!=user and request.assignTo==user ">
              <hippo:action action="acceptReview" enabledExpr="true"/>
              <hippo:action action="rejectReview" enabledExpr="true"/>
            </if>
          </if>
          <else>
            <hippo:action action="acceptReview" enabledExpr="false"/>
            <hippo:action action="rejectReview" enabledExpr="false"/>
            <hippo:action action="requestReview" enabledExpr="true"/>
            <hippo:action action="cancelReview" enabledExpr="false"/>
          </else>
        </if>
        <if cond="request.workflowRequest">
          <if cond="workflowContext.isGranted(request, 'hippo:editor')">
            <if cond="workflowContext.isGranted(unpublished,'hippo:admin') or user!=request.owner">
              <!-- editor users (granted hippo:editor) may reject and accept as well as cancel requests -->
              <if cond="request.workflowType!='rejected'">
                <!-- if request not rejected yet, enable reject operation -->
                <hippo:requestAction identifierExpr="request.identity" action="rejectRequest" enabledExpr="true"/>
              </if>
              <if cond="request.workflowType=='delete'">
                <!-- if request for delete: enable accept operation if not live and not editing -->
                <hippo:requestAction identifierExpr="request.identity" action="acceptRequest" enabledExpr="!live and !editing"/>
                <elseif cond="request.workflowType=='publish'">
                  <!-- if request for publish: enable accept operation if modified and not editing -->
                  <hippo:requestAction identifierExpr="request.identity" action="acceptRequest" enabledExpr="modified and !editing"/>
                </elseif>
                <elseif cond="request.workflowType=='depublish'"/>
                <!-- if request for depublish: enable accept operation if live and not editing -->
                <hippo:requestAction identifierExpr="request.identity" action="acceptRequest" enabledExpr="live and !editing"/>
              </if>
            </if>
            <if cond="!request.owner or request.owner==user">
              <!-- if request owner or no request owner: enable cancel operation -->
              <hippo:requestAction identifierExpr="request.identity" action="cancelRequest" enabledExpr="true"/>
            </if>
            <!-- when not an editor user (not granted hippo:editor) then: -->
            <elseif cond="request?.owner==user"/>
            <!-- if request owner: enable cancel operation -->
            <hippo:requestAction identifierExpr="request.identity" action="cancelRequest" enabledExpr="true"/>
          </if>
          <else/>
          <!-- scheduled workflow operation -->
          <if cond="workflowContext.isGranted(request, 'hippo:editor')">
            <!-- if editor user (granted hippo:editor): enable cancel operation -->
            <hippo:requestAction identifierExpr="request.identity" action="cancelRequest" enabledExpr="true"/>
          </if>
        </if>
      </foreach>
    </onentry>

    <transition event="acceptReview">
      <!-- define temporary request variable for the event payload request parameter -->
      <!--<cs:var name="request" expr="_event.data?.request"/>-->
      <!-- store the request workflow type as temporary variable -->
      <hippo:acceptReview requestExpr="request" reviewer="user"/>
    </transition>

    <transition event="cancelReview">
      <!-- define temporary request variable for the event payload request parameter -->
      <!--<cs:var name="request" expr="_event.data?.request"/>-->
      <!-- store the request workflow type as temporary variable -->
      <hippo:deleteRequest requestExpr="request"/>
    </transition>

    <transition event="rejectReview">
      <!-- update the specific request to type rejected with an optional reason, using the event payload
           'request' and optional 'reason' parameters -->
      <hippo:rejectReview requestExpr="request" reviewer="user" reasonExpr="_event.data?.reason"/>
    </transition>

    <!-- target-less transition to 'accept' a specific request -->
    <transition event="acceptRequest">

      <!-- define temporary request variable for the event payload request parameter -->
      <cs:var name="request" expr="_event.data?.request"/>
      <!-- store the request workflow type as temporary variable -->
      <cs:var name="workflowType" expr="request.workflowType"/>
      <!-- store the request targetDate as temporary variable -->
      <cs:var name="targetDate" expr="request.scheduledDate"/>

      <!-- First delete the request itself.
           Note: After this, the request object no longer can be accessed!
                 Which is why we need to define the temporary variables workflowType and targetDate above.
      -->
      <hippo:deleteRequest requestExpr="request"/>

      <if cond="!targetDate">
        <!-- the request didn't have a targetDate defined, simply trigger the "workflowType" value as event -->
        <send event="workflowType"/>
        <!-- log the workflowType after it has been processed -->
        <send event="'logEvent.'+workflowType"/>
        <else/>
        <!-- the request did have a targetDate: trigger a 'scheduled' workflow action event -->
        <send event="workflowType" namelist="targetDate"/>
      </if>

    </transition>

    <!-- target-less transition to 'reject' a request -->
    <transition event="rejectRequest">
      <!-- update the specific request to type rejected with an optional reason, using the event payload
           'request' and optional 'reason' parameters -->
      <hippo:rejectRequest requestExpr="_event.data?.request" reasonExpr="_event.data?.reason"/>
    </transition>

    <!-- target-less transition to 'cancel' a request -->
    <transition event="cancelRequest">
      <!-- delete the specific request using the event payload 'request' parameter -->
      <hippo:deleteRequest requestExpr="_event.data?.request"/>
    </transition>

  </state>

</state>

WORKFLOW PART 2

<state id="publish">

  <!-- the initial no-publish state is used and active to indicate publish operations are currently not
       allowed or possible because the document is being edited or not (yet) modified -->
  <state id="no-publish">
    <onentry>


      <!--NO NO NO NO WHY?????  by default report the request publication operation as available but disabled -->
      <if cond="!workflowContext.isGranted(unpublished ?: published ?: draft, 'hippo:editor') or user==(unpublished ?: published ?: draft).lastModifiedBy">
        <hippo:action action="requestPublication" enabledExpr="false"/>
      </if>

      <if cond="workflowContext.isGranted(unpublished ?: published ?: draft, 'hippo:editor') and (workflowContext.isGranted(unpublished ?: published ?: draft,'hippo:admin') or user!=(unpublished ?: published ?: draft).lastModifiedBy)">
        <!-- if editor user (granted hippo:editor) by default report the publish operation as available but disabled -->
        <hippo:action action="publish" enabledExpr="false"/>
      </if>
    </onentry>
    <!-- event-less transition to publishable state if not currently editing and the document is modified -->
    <transition target="publishable" cond="!editing and modified"/>
  </state>

  <!-- state publishable is active when the  document is modified and not currently edited -->
  <state id="publishable">
    <onentry>
      <if cond="!requestPending or user=='workflowuser'">
        <!-- if no request pending OR invoked by the 'workflowuser' user (scheduled workflow jobs daemon):
             enable request publication operation -->
        <hippo:action action="requestReview" enabledExpr="true"/>
        <if cond="!workflowContext.isGranted(unpublished ?: published ?: draft, 'hippo:editor') or user==(unpublished ?: published ?: draft).lastModifiedBy">
          <hippo:action action="requestPublication" enabledExpr="true"/>
        </if>
        <if cond="workflowContext.isGranted(unpublished, 'hippo:editor') and (workflowContext.isGranted(unpublished,'hippo:admin') or user!=unpublished.lastModifiedBy)">
          <!-- if (also) editor user (granted hippo:editor): enable publish operation -->
          <hippo:action action="publish" enabledExpr="true"/>
        </if>
      </if>
    </onentry>

    <transition event="requestReview" >
      <hippo:requestReview contextVariantExpr="unpublished" assignTo="_event.data?.assignTo" />
      <hippo:action action="requestReview" enabledExpr="false"/>
    </transition>

    <!-- target-less transition to create a publish request when no event payload parameter targetDate is provided -->
    <transition event="requestPublication" cond="!_event.data?.targetDate">
      <hippo:workflowRequest type="publish" contextVariantExpr="unpublished"/>
    </transition>

    <!-- target-less transition to create a scheduledpublish request at the required event payload parameter targetDate -->
    <transition event="requestPublication" cond="!!_event.data?.targetDate">
      <hippo:workflowRequest type="scheduledpublish" contextVariantExpr="unpublished" targetDateExpr="_event.data?.targetDate"/>
    </transition>

    <!-- target-less transition to publish the document when no event payload parameter targetDate is provided -->
    <transition event="publish" cond="!_event.data?.targetDate">
      <!-- copy the content of the unpublished variant to the published variant -->
      <hippo:copyVariant sourceState="unpublished" targetState="published"/>
      <!-- mark the published variant as published and set its availability to (only) 'live' -->
      <hippo:configVariant variant="published" applyPublished="true" availabilities="live"/>
      <!-- create a JCR version of the published document via the unpublished variant -->
      <hippo:version variant="unpublished"/>

      <hippo:scheduleUnpublish sourceState="published" workflowAction="publish"/>
    </transition>

    <!-- target-less transition to schedule the publication of the document at the required event payload parameter targetDate -->
    <transition event="publish" cond="!!_event.data?.targetDate">
      <hippo:scheduleWorkflow type="publish" targetDateExpr="_event.data?.targetDate"/>
    </transition>

  </state>

</state>

<!-- the composite depublish state is used to manage workflow operations for depublishing a document -->
<state id="depublish">

  <!-- the initial no-depublish state is used and active to indicate depublish operations are currently not
       allowed or possible because the document is being edited or not 'live' -->
  <state id="no-depublish">
    <onentry>
      <!-- by default report the request depublication operation as available but disabled -->
      <hippo:action action="requestDepublication" enabledExpr="false"/>
      <if cond="workflowContext.isGranted(published ?: unpublished ?: draft, 'hippo:admin')">
        <!-- if editor user (granted hippo:editor) by default report the depublish operation as available but disabled -->
        <hippo:action action="depublish" enabledExpr="false"/>
      </if>
    </onentry>
    <!-- event-less transition to depublishable state if not currently editing and the document is 'live' -->
    <transition target="depublishable" cond="!editing and live"/>
  </state>

  <!-- state depublishable is active when the  document is live and not currently edited -->
  <state id="depublishable">
    <onentry>
      <if cond="!requestPending or user=='workflowuser'">
        <!-- if no request pending OR invoked by the 'workflowuser' user (scheduled workflow jobs daemon):
             enable request depublication operation -->
        <hippo:action action="requestDepublication" enabledExpr="true"/>
        <if cond="workflowContext.isGranted(published, 'hippo:admin')">
          <!-- if (also) editor user (granted hippo:editor): enable publish operation -->
          <hippo:action action="depublish" enabledExpr="true"/>
        </if>
      </if>
    </onentry>

    <!-- target-less transition to create a depublish request when no event payload parameter targetDate is provided -->
    <transition event="requestDepublication" cond="!_event.data?.targetDate">
      <hippo:workflowRequest type="depublish" contextVariantExpr="published"/>
    </transition>

    <!-- target-less transition to create a scheduleddepublish request at the required event payload parameter targetDate -->
    <transition event="requestDepublication" cond="!!_event.data?.targetDate">
      <hippo:workflowRequest type="scheduleddepublish" contextVariantExpr="published" targetDateExpr="_event.data?.targetDate"/>
    </transition>

    <!-- target-less transition to depublish the document when no event payload parameter targetDate is provided -->
    <transition event="depublish" cond="!_event.data?.targetDate">
      <if cond="!unpublished">
        <!-- if no unpublished variant exists yet, copy it from the published variant -->
        <hippo:copyVariant sourceState="published" targetState="unpublished"/>
      </if>
      <!-- ensure the unpublished variant to be versionable set its availability to (only) 'live' -->
      <hippo:configVariant variant="unpublished" versionable="true" availabilities="preview"/>
      <!-- remove all availabilities from the published variant -->
      <hippo:configVariant variant="published" availabilities=""/>
      <!-- create an extra version of the current unpublished (possibly modified?) -->
      <hippo:version variant="unpublished"/>
    </transition>

    <!-- target-less transition to schedule the depublication of the document at the required event payload parameter targetDate -->
    <transition event="depublish" cond="!!_event.data?.targetDate">
      <hippo:scheduleWorkflow type="depublish" targetDateExpr="_event.data?.targetDate"/>
    </transition>

  </state>

</state>

<!-- the composite versioning state is used to manage versioning related workflow operations of a document -->
<state id="versioning">

  <onentry>
    <!-- always enable the listVersions, even if no version is available (yet) -->
    <hippo:action action="listVersions" enabledExpr="true"/>
  </onentry>

  <!-- target-less transition to report a list of available versions of the document -->
  <transition event="listVersions">
    <hippo:listVersions variant="unpublished"/>
  </transition>

  <!-- the initial no-versioning state is used and active to indicate versioning operations are currently not
       allowed or possible because there is no unpublished document variant yet -->
  <state id="no-versioning">
    <!-- event-less transition to versionable state when an unpublished document variant exists -->
    <transition target="versionable" cond="!!unpublished"/>
  </state>

  <!-- the versionable state becomes active when an unpublished document variant exists -->
  <state id="versionable">
    <onentry>
      <!-- enable the retrieveVersion operation -->
      <hippo:action action="retrieveVersion" enabledExpr="true"/>
      <if cond="workflowContext.isGranted(unpublished, 'hippo:editor')">
        <!-- if the user is editor (granted hippo:editor) also enable the other versioning operations -->
        <hippo:action action="version" enabledExpr="true"/>
        <hippo:action action="restoreVersion" enabledExpr="true"/>
        <hippo:action action="versionRestoreTo" enabledExpr="true"/>
      </if>
    </onentry>

    <!-- target-less transition to create a new version for the current unpublished variant -->
    <transition event="version">
      <hippo:version variant="unpublished"/>
    </transition>

    <!-- target-less transition to retrieve a specific version created on the event payload provided date parameter -->
    <transition event="retrieveVersion">
      <hippo:retrieveVersion historic="_event.data?.date" variant="unpublished"/>
    </transition>

    <!-- target-less transition to restore a specific version from the event payload provided parameter date to the
         payload provided parameter target (document).
         Note: this uses custom/manual copying of the version contents, unlike the restoreVersion operation below -->
    <transition event="versionRestoreTo">
      <hippo:versionRestoreTo historic="_event.data?.date" variant="unpublished" target="_event.data?.target"/>
    </transition>

    <!-- target-less transition to restore a specific document version from the event payload provided parameter date.
         Note: this uses standard JCR version restore unlike the versionRestoreTo operation above -->
    <transition event="restoreVersion">
      <hippo:restoreVersion historic="_event.data?.date" variant="unpublished"/>
    </transition>

  </state>

</state>

<!-- the composite terminate state is used to manage termination and related/similar workflow operations like
     move and rename -->
<state id="terminate">

  <!-- the initial no-terminate state is used and active when delete/move/rename operations are currently now
       allowed or possible -->
  <state id="no-terminate">
    <onentry>
      <!-- report request delete operation as available but default disabled -->
      <hippo:action action="requestDelete" enabledExpr="false"/>
      <if cond="workflowContext.isGranted(deleteSource, 'hippo:editor') and workflowContext.isGranted(containingFolder, 'jcr:write')">
        <!-- if the user is editor (granted hippo:editor) AND allowed to modify (jcr:write) the document folder,
             report the delete/move/rename operations as available but default disabled -->
        <hippo:action action="delete" enabledExpr="false"/>
        <hippo:action action="move" enabledExpr="false"/>
        <hippo:action action="rename" enabledExpr="false"/>
      </if>
    </onentry>
    <!-- event-less transition to terminatable state if the document is not live and not being edited -->
    <transition target="terminateable" cond="!live and !editing"/>
  </state>

  <!-- the terminateable state becomes active when the document is not live and not being edited -->
  <state id="terminateable">
    <onentry>
      <if cond="!requestPending">
        <!-- delete operations are only allowed when (also) no request is pending -->
        <!-- (then) always enable the request delete operation -->
        <hippo:action action="requestDelete" enabledExpr="true"/>
        <if cond="workflowContext.isGranted(deleteSource, 'hippo:editor') and workflowContext.isGranted(containingFolder, 'jcr:write')">
          <!-- if the user is editor (granted hippo:editor) AND allowed to modify (jcr:write) the document folder,
               enable the delete/move/rename operations -->
          <hippo:action action="delete" enabledExpr="!published"/>
          <hippo:action action="move" enabledExpr="true"/>
          <hippo:action action="rename" enabledExpr="true"/>
        </if>
      </if>
    </onentry>

    <!-- target-less transition to create a delete request -->
    <transition event="requestDelete">
      <hippo:workflowRequest type="delete" contextVariantExpr="deleteSource"/>
    </transition>

    <!-- transition to delete the current document and go to final state terminated -->
    <transition event="delete" target="terminated">
      <hippo:archiveDocument/>
    </transition>

    <!-- transition to move the current document and go to final state terminated -->
    <transition event="move" target="terminated">
      <hippo:moveDocument destinationExpr="_event.data?.destination" newNameExpr="_event.data?.name"/>
    </transition>

    <!-- transition to rename the current document and go to final state terminated -->
    <transition event="rename" target="terminated">
      <hippo:renameDocument newNameExpr="_event.data?.name"/>
    </transition>

  </state>

</state>

<!-- the composite copy state is used to manage the copy workflow operation -->
<state id="copy">

  <!-- the initial no-copy state is used and active when the user is not an editor (granted hippo:editor) -->
  <state id="no-copy">
    <!-- event-less transition to copyable state when the user is an editor (granted hippo:editor) -->
    <transition target="copyable" cond="workflowContext.isGranted(copySource,'hippo:editor')"/>
  </state>

  <!-- the state copyable is only active for users which are editor (granted hippo:editor) -->
  <state id="copyable">
    <onentry>
      <!-- always enable the copy operation -->
      <hippo:action action="copy" enabledExpr="true"/>
    </onentry>

    <!-- target-less transition to copy the document to the event payload provided parameters destination and name -->
    <transition event="copy">
      <hippo:copyDocument destinationExpr="_event.data?.destination" newNameExpr="_event.data?.name"/>
    </transition>

  </state>

</state>

<!-- the simple and non-transitional logEvent state is used to log actions:
     such actions needs to be 'send' using an event name prefixed by 'logEvent.'
     the remainder of the event name will be logged as event action
-->
<state id="logEvent">
  <transition event="logEvent.*">
    <hippo:logEvent actionexpr="_event.name.substring('logEvent.'.length())"/>
  </transition>
</state>

HIPPO Local:

Hippo Release version 12.3.0
Hippo CMS version 5.3.0
Repository vendor Hippo B.V.
Repository version 5.3.0
Memory maximum 455,5 MB
Memory taken 455,5 MB
Memory free 161,76 MB
Memory in use 293,74 MB
Memory total free 161,76 MB
Java vendor Oracle Corporation
Java version 1.8.0_151
Java VM Java HotSpot™ 64-Bit Server VM
OS architecture x86_64
OS name Mac OS X
OS version 10.13.3
Processors # 8

Hi,
fwiw, our demo runs MySql database, and we have a number of clients running Oracle DB so, I think we should look at threestep workflow as a culprit here.
Have you been following this guide:

when implementing 3-step wf?

One more thing: what happens if you remove all your modifications and use original SCXM file (so without any modifications on your side) Do you observe same behavior?

yes we followed the same guide, but we have not 100% the same implementation.
if I change only scxml to the origin, its able to create requests without 3step, but not all of the will be triggered correctly :frowning:

I check all the reuests in repository GUI , using SELECT * FROM hipposched:trigger
All of them are correct.

Test with 4 Documents : 2 of them are consumed :frowning:

25.07.2018 14:35:00 [Hippo JCR Quartz Job Scheduler_Worker-2] INFO [org.apache.jackrabbit.core.cluster.ClusterNode.consume():858] Processing revision: 5511
25.07.2018 14:35:00 [Hippo JCR Quartz Job Scheduler_Worker-1] INFO [org.apache.jackrabbit.core.cluster.ClusterNode.consume():858] Processing revision: 5513

Log

I could not imagine the error in my Java-Implementation, cos
a) everything works localy (without Oracle, Without Cluster)
b) it could not be 3-step implementation error, cos all Requests are the same , except Node IDs
c) The whole 3-step Stuff works with one document , also with cluster and oracle

are your site and CMS deployed on the same server or separately e.g. as described here:


(I think it is) and have you disabled site scheduled jobs (-Dhippo.scheduler.disabled=true ) ?

cms and site are deployed separately with different cluster-IDs. cms runs one tomcat instance. site runs one tomcat instance

-Dhippo.scheduler.disabled=true was not set. I will try to check this

first success test :slight_smile: if SITE -Tomcat ist down, everything works fine.
Now I try to test with -Dhippo.scheduler.disabled=true and running SITe-Tomcat

thats it !

-Dhippo.scheduler.disabled=true on the SITE Tomcat and everything (with 3-step workflow) works fine.

thanks a lot !