Error on a timer expression

Hi,

I have a requirement where i will need the workflow to start at 9 AM every day. I found the Timer Event document which specifies an expression though not exactly matching the requirement.

However, when setting the timer definition type to cycle and setting the same value as shown in the document i.e. R4/2016-03-11T12:13/PT5M I get the following error when deploying the workflow,

command ‘CREATE’ rejected with code ‘INVALID_ARGUMENT’: Expected to deploy new resources, but encountered the following errors:
‘Process.bpmn’: - Element: Event_13k8t9l - ERROR: Invalid timer cycle expression (Text cannot be parsed to a Period)

So two questions here,

  • What could be the reason I am getting the error on deploying the workflow as I have specified the timer cycle as shown on the document ?

  • What would be the right expression to set a timer to kick off at a specific time every day. I have tried R/2021-05-18T09:00/P1D but I get the error message mentioned above.

Thank you

Hi @Bisoux,

thank you for raising this up. Regarding your questions:

You looked at the wrong documentation :sweat_smile:

The docs for Camunda cloud are located at https://docs.camunda.io/docs/reference/bpmn-processes/timer-events/timer-events#time-cycle

The other docs are for Camunda platform (aka Camunda 7).

Currently, this feature is not supported. Here is an open feature request: Feature Request: On Timer events add scheduling at specific time · Issue #3038 · camunda-cloud/zeebe · GitHub

However, you could use a FEEL expression to calculate the duration. The expression is evaluated every time when the timer is triggered. It calculated the duration until the given time (here every day at 09:00). For example,

= {
  time: time("09:00:00@Europe/Berlin"),
  date: if (time(now()) < time) then today() else today() + duration("P1D"),
  duration: date and time(date, time) - now(),
  cycleWithDuration: cycle(duration)
}.cycleWithDuration

Related topic: Timer event that needs to start every Tuesday

Does this help you?

Best regards,
Philipp

1 Like

Thank you very much @philipp.ossler . Looks like the expression is working great. One more question if i may, this with regards to the timezone mentioned, as we are not in Europe the applicable timezones would be what can be found here ?

Happy to hear :slight_smile:

Yes, the time zones from that list should work :+1:

1 Like

Hi @philipp.ossler,

I have noticed an odd behaviour on a couple of workflows where i have used the FEEL timer expression. So this is what the expression looks like,

= { time: time(“09:00:00@Asia/Baku”), date: if (time(now()) < time) then today() else today() + duration(“P1D”), duration: date and time(date, time) - now(), cycleWithDuration: cycle(duration) }.cycleWithDuration

As you can see below on the screenhsot from operate, the timer, thus the workflow, starts one tenth of a second before 9 AM and at 9AM as well,

This is happening on our production instance. I did not observe this in our dev instance where i tested the expression on a workflow so i am suspecting the issue is something to do with some setting on our production engine and not directly related to the expression. But i would appreciate your thoughts.

Thank you

That is interesting. I’m not sure why the timer is triggered a bit too early.
But as a result, it triggered the timer again because it was before 09:00:00.

We could try to root cause the behavior.

Was the timer also triggered on the 2021-05-20? When?
Please share a screenshot of the details view from the timer event in Operate.

1 Like

I am seeing the issue intermittently. On the 25th it did not happen, on the 24th it did and the one i shared earlier on the 21st. It was deployed on the 20th evening so we can only view operate logs for this from the 21st.

image

It is still not clear why this is happening. Feel free to create a new issue that the timer is triggered too early.

Depending on the impact, you could implement different workarounds. For example, using two timer events. One timer with an expression to determine the duration until 09:00 and a second timer event with a cycle expression that triggered every 24 hours (i.e. P1D).
Or, using a variable to determine if the timer event was triggered today already.

1 Like

Hi @philipp.ossler,

I realise this a slightly dated topic but I thought i’d share my recent findings with you and I have a hunch we can probably solve this without creating an issue so please bear with me.

I broke down the components of the expression to see the outputs of the variables in the expression i.e.
date,duration etc. Here is what I observed in instances where the event is fired twice,

For an expression set as follows,

= { time: time("11:05:00@Etc/UTC"),   
    date: if (time(now()) < time) then today() else today() + duration("P1D"),   
    theDuration: date and time(date, time) - now(), 
    cycleWithDuration: cycle(theDuration)
  }.cycleWithDuration

Here is the output for the first event that was fired,

time(now()) = 11:04:59.945@Etc/UTC**
today() = 2021-06-11
date = 2021-06-11
theDuration = R/PT0.055S**
cycle(theDuration) = PT0.055S

Please note the duration PT0.055S, which i beleive might explain why a second event firing at almost the same time.

For the same time i.e. time(“11:05:00@Etc/UTC”), the second event that was fired has the following output,

time(now()) = 11:05:00.15@Etc/UTC
today() = 2021-06-11
date = 2021-06-12
theDuration = R/PT23H59M59.85S
cycle(theDuration) = PT23H59M59.85S

Now my thinking is if we could enhance the expression so that it will exclude all durations that do not have an hour included. A somewhat simplified solution, but maybe you have a better idea. Here is my attempt to enhance the expression,

= { time: time("11:05:00@Etc/UTC"),       
    date: if (time(now()) < time) then today() else today() + duration("P1D"),     
    theDuration: date and time(date, time) - now(),      
    cycleWithDuration: if (is defined(duration(string(theDuration)).hours)) then cycle(theDuration) else cycle(date and time(today() + duration("P1D")))
}.cycleWithDuration

So in cycleWithDuration I am trying to add a condition so that if the duration does not have an hour component, a day should be added to the duration. I am not so good with FEEL expressions but I was hoping you would get where my thinking is with this and tell me how i could implement the condition on the expression.

Thank you

1 Like

Hi @philipp.ossler ,

So i did a small tweak to the script

= { time: time(“11:05:00@Etc/UTC”),
date: if (time(now()) < time) then today() else today() + duration(“P1D”),
theDuration: date and time(date, time) - now(),
cycleWithDuration: if (cycle(theDuration) < cycle(duration(“PT1M”))) then cycle(theDuration + duration(“P1D”)) else cycle(theDuration)
}.cycleWithDuration

i have been testing this since my last post. It looks like that did the trick. No duplicate event starts.

Thanks again for the original solution.

@Bisoux thanks for sharing your findings :rocket:

I like your solution :+1:

As an alternative, you could write the expression in the following way:

= { time: time("11:05:00@Etc/UTC"),   
    date: if (time(now()) + duration("PT1H") < time) then today() else today() + duration("P1D"),   
    theDuration: date and time(date, time) - now(), 
    cycleWithDuration: cycle(theDuration)
  }.cycleWithDuration

I’ll also look into the engine to see why the timer is triggered a bit too early :eyes:

1 Like