Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Actor DurationUtils parsing of duration throws an exception #712

Closed
mukundansundar opened this issue Mar 23, 2022 · 0 comments · Fixed by #714
Closed

Actor DurationUtils parsing of duration throws an exception #712

mukundansundar opened this issue Mar 23, 2022 · 0 comments · Fixed by #714
Assignees
Labels
kind/bug Something isn't working P0 size/XS
Milestone

Comments

@mukundansundar
Copy link
Contributor

mukundansundar commented Mar 23, 2022

Expected Behavior

Duration is parsed correctly and no exception is thrown

Actual Behavior

Following Actor API reference in docs : https://docs.dapr.io/reference/api/actors_api/#examples-3

if a reminder is created in the format

curl http://localhost:3500/v1.0/actors/stormtrooper/50/reminders/checkRebels \
  -H "Content-Type: application/json"
-d '{
      "data": "someData",
      "dueTime": "1m",
      "period": "20s"
    }'

And used in a Java with an Actor Type names stormtrooper and the Actor class implements Remindable data ...

public Mono<Void> receiveReminder(String reminderName, String state, Duration dueTime, Duration period) {

When receiveReminder is called by the actor runtime, the dueTime field is parsed and converted to Java Duration using the class
DurationUtils.java

 public static Duration convertDurationFromDaprFormat(String valueString) {
    // Convert the format returned by the Dapr runtime into Duration
    // An example of the format is: 4h15m50s60ms. It does not include days.
    int hourIndex = valueString.indexOf('h');
    int minuteIndex = valueString.indexOf('m');
    int secondIndex = valueString.indexOf('s');
    int milliIndex = valueString.indexOf("ms");

    String hoursSpan = valueString.substring(0, hourIndex);

    int hours = Integer.parseInt(hoursSpan);
    int days = hours / 24;
    hours = hours % 24;

    String minutesSpan = valueString.substring(hourIndex + 1, minuteIndex);
    int minutes = Integer.parseInt(minutesSpan);

    String secondsSpan = valueString.substring(minuteIndex + 1, secondIndex);
    int seconds = Integer.parseInt(secondsSpan);

    String millisecondsSpan = valueString.substring(secondIndex + 1, milliIndex);
    int milliseconds = Integer.parseInt(millisecondsSpan);

    return Duration.ZERO
        .plusDays(days)
        .plusHours(hours)
        .plusMinutes(minutes)
        .plusSeconds(seconds)
        .plusMillis(milliseconds);
  }

In this an exception is thrown as such:

== APP == 2022-03-23 12:26:12,023 {HH:mm:ss.SSS} [http-nio-3000-exec-5] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: java.lang.StringIndexOutOfBoundsException: begin 0, end -1, length 3] with root cause
== APP == java.lang.StringIndexOutOfBoundsException: begin 0, end -1, length 3
== APP == 	at java.base/java.lang.String.checkBoundsBeginEnd(String.java:3319)
== APP == 	at java.base/java.lang.String.substring(String.java:1874)
== APP == 	at io.dapr.utils.DurationUtils.convertDurationFromDaprFormat(DurationUtils.java:34)
== APP == 	at io.dapr.actors.runtime.ActorObjectSerializer.extractDurationOrNull(ActorObjectSerializer.java:229)
== APP == 	at io.dapr.actors.runtime.ActorObjectSerializer.deserializeActorReminder(ActorObjectSerializer.java:209)
== APP == 	at io.dapr.actors.runtime.ActorObjectSerializer.deserialize(ActorObjectSerializer.java:168)
== APP == 	at io.dapr.actors.runtime.ActorManager.lambda$invokeReminder$4(ActorManager.java:104)
== APP == 	at reactor.core.publisher.MonoSupplier.call(MonoSupplier.java:85)
== APP == 	at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:126)
== APP == 	at reactor.core.publisher.MonoFlatMap.subscribeOrReturn(MonoFlatMap.java:53)
== APP == 	at reactor.core.publisher.Mono.subscribe(Mono.java:4198)
....

Dapr parses the dueTime correctly and reminds the app on time ... But the DurationUtils class expects the full format of ISO 8601 duration.

Steps to Reproduce the Problem

Create any actor type and create reminder with only partial dueTime example "1m", "1s" etc.

Release Note

RELEASE NOTE:

@mukundansundar mukundansundar added kind/bug Something isn't working P1 size/XS labels Mar 23, 2022
@artursouza artursouza added P0 and removed P1 labels Mar 23, 2022
This was referenced Mar 24, 2022
@mukundansundar mukundansundar self-assigned this Mar 24, 2022
@mukundansundar mukundansundar added this to the v1.5 milestone Mar 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Something isn't working P0 size/XS
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants