Skip to content

Add Retry annotation #139

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

Merged
merged 9 commits into from
Nov 17, 2020
Merged

Add Retry annotation #139

merged 9 commits into from
Nov 17, 2020

Conversation

TsuyoshiUshio
Copy link
Collaborator

@TsuyoshiUshio TsuyoshiUshio commented Nov 11, 2020

Create a PR for retry annotation to discuss the spec. The annotation requires maven plugin's change.
I'll update this PR to spot the correct spec once I figure out.

Current Version of the C# implementation has Typo. I correct the spelling on Java. The C# will fix it soon.
Azure/azure-webjobs-sdk#2637

What should we generate from this annotation?

On the maven plugin side, we need to generate retry strategy part. These are examples.
@Flanker32 Could you have a look and can we start discussion for the change the maven plugin side?

Exponential Backoff

function.json

{
  "scriptFile" : "../fabrikam-functions-1.0-SNAPSHOT.jar",
  "entryPoint" : "com.fabrikam.Function.run",
  "bindings" : [ {
    "type" : "httpTrigger",
    "direction" : "in",
    "name" : "req",
    "methods" : [ "GET" ],
    "authLevel" : "ANONYMOUS"
  }, {
    "type" : "http",
    "direction" : "out",
    "name" : "$return"
  } ],
  "retry": {
    "strategy": "exponentialBackoff",
    "maxRetryCount": 5,
    "minimumInterval": "00:00:02",
    "maximumInterval": "00:01:00"
  }
}

Fixed Delay

{
  "scriptFile" : "../fabrikam-functions-1.0-SNAPSHOT.jar",
  "entryPoint" : "com.fabrikam.Function.run",
  "bindings" : [ {
    "type" : "httpTrigger",
    "direction" : "in",
    "name" : "req",
    "methods" : [ "GET" ],
    "authLevel" : "ANONYMOUS"
  }, {
    "type" : "http",
    "direction" : "out",
    "name" : "$return"
  } ],
  "retry": {
    "strategy": "fixedDelay",
    "maxRetryCount": 4,
    "delayInterval": "00:00:05"
  }
}

It requires Microsoft.Azure.WebJobs 3.0.23 However, the functions host already release it at this version.
https://github.com/Azure/azure-functions-host/releases/tag/v3.0.14785
For the CoreTools that is used by Maven Plugin:

I tested with this version. It works.

Azure Functions Core Tools
Core Tools Version:       3.0.2996 Commit hash: c54cdc36323e9543ba11fb61dd107616e9022bba
Function Runtime Version: 3.0.14916.0

@pragnagopa
Copy link
Member

No need to block on webjobs sdk typo fix as this PR is not affected by it.

@pragnagopa
Copy link
Member

Shouldn't we add annotation that matches retry options in host.json : https://github.com/Azure/azure-functions-host/blob/dev/sample/NodeRetry/host.json#L3-L7 ? Also, this might need changes in maven plugin to produce right host.json with class level annotations

Method level annotations are required to produce retry section in function.json : https://github.com/Azure/azure-functions-host/blob/dev/sample/NodeRetry/HttpTrigger-RetryFunctionJson/function.json#L18-L22

@amamounelsayed
Copy link
Contributor

@pragnagopa This is is really good point, Thank you so much

Copy link
Member

@pragnagopa pragnagopa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update the java-library version as part of this PR. Once the changes are in , publish SNAPSHOT version so that mvn plugin can be updated.

@TsuyoshiUshio
Copy link
Collaborator Author

Hi @pragnagopa
I have a question for the class level annotation for host.json. What happens if there is several classes?
I think it might be good let the customers to modify host.json. Am I understand correctly?

@pragnagopa
Copy link
Member

I have a question for the class level annotation for host.json. What happens if there is several classes?

FunctionTimeout is at host.json as well. Would be good to understand how this is handled in mvn

@TsuyoshiUshio
Copy link
Collaborator Author

@pragnagopa
From the maven plugin side, for the host.json, they just generate the initial template, if there is not there.

@TsuyoshiUshio
Copy link
Collaborator Author

TsuyoshiUshio commented Nov 12, 2020

Hi @pragnagopa , @apawast and @jeffhollan

I have a question. I talked with @Flanker32 and he has an idea. Currently, I separate the annotation into too.
However, he gave us an idea for making it into one annotation since, the function.json has only one configuration. We were discussed what happens if the customer has two retry annotations on a function.

What do you think the idea? Hi @Flanker32 If I miss some context, feel free to add the context or correct what I wrote.

@Flanker32
Copy link

Flanker32 commented Nov 12, 2020

@TsuyoshiUshio Thanks a lot for your efforts, really exciting feature!

Here is my thoughts for the annotation, as @TsuyoshiUshio said, it seems one Retry annotation should be enough for both the cases, here is an example

public @interface Retry {
    RetryStrategy strategy();

    int maxRetryCount();

    int delayInterval();

    int maximumInterval();

    static enum RetryStrategy {
        EXPONENTIAL, FIXED;
    }
}

By the way could we pass the retry meta data to trigger? So that users may know how many times the trigger failed and send some telemetry based on this data.

@Flanker32
Copy link

I have a question for the class level annotation for host.json. What happens if there is several classes?

FunctionTimeout is at host.json as well. Would be good to understand how this is handled in mvn

maven plugin will not modify the host.json, we will just provide an host.json example with function archetype, here is the link

@Flanker32
Copy link

Flanker32 commented Nov 12, 2020

For the function.jsonconfiguration, we defined both minimumInterval and maximumInterval for exponentialBackoff, so what will happen if exponential interval is larger then maximumInterval?

For instance, if set minimumInterval to 2s and maximumInterval to 10s, and the interval for the fourth retry will be 16s which higher than the maximum value, will function host rerun the trigger in 10s or will throw an exception in this situation? Do we need to validate the annotation in tooling side? Besides, is there any value limitation for minimumInterval or maximumInterval

@pragnagopa
Copy link
Member

Yes, Annotation has to match : #139 (comment)

@Flanker32 -

Thanks for clarifying this

maven plugin will not modify the host.json, we will just provide an host.json example with function archetype, here is the link

@TsuyoshiUshio / @amamounelsayed - I believe we never supported class level annotations. Please open a separate issue. If more users ask for it then we can figure out right design. Please scope this PR to adding method level annotations only.

Do we need to validate the annotation in tooling side

No need to add validation in the tooling as the runtime will show proper validation errors at runtime. Same is true for other questions you asked. Validation is handled by the runtime so no need to duplicate validation logic in the tooling.

@pragnagopa
Copy link
Member

By the way could we pass the retry meta data to trigger? So that users may know how many times the trigger failed and send some telemetry based on this data.

Currently we do not have this. We are tracking the feature here: Azure/azure-webjobs-sdk#2595

@TsuyoshiUshio
Copy link
Collaborator Author

I'm ok for the @Flanker32 idea. What do you think? @jeffhollan or @apawast ? #139 (comment)

@pragnagopa
Copy link
Member

pragnagopa commented Nov 12, 2020

@TsuyoshiUshio - just to clarify , the annotation needed is the retry options that are exposed in the functions host: https://github.com/Azure/azure-functions-host/blob/dev/sample/NodeRetry/HttpTrigger-RetryFunctionJson/function.json#L18-L22 . WebJobs SDK attributes do not apply here. The change needed is #139 (comment)

@TsuyoshiUshio
Copy link
Collaborator Author

Hi @pragnagopa Thanks. I also tested from my side by changing function.json manually and it works. So that the annotation definition on the Java side doesn't matter. function.josn matters. So that I'd like to ask PM if it is OK as the customer experience. I'm ok for it.

@pragnagopa
Copy link
Member

So that the annotation definition on the Java side doesn't matter. function.josn matters

This is the design for all out-of-proc languages. In Java annotation is used to generate function.json so that users manually do not have to edit function.json

@TsuyoshiUshio
Copy link
Collaborator Author

Thank you for sharing the context of the design! So that we can design annotation as we like.

@TsuyoshiUshio
Copy link
Collaborator Author

Hi @Flanker32 @amamounelsayed @pragnagopa @apawast
I talked with @jeffhollan and he said that

Looks good to me. I like the approach.

I'd like to take your idea. I'll update this PR soon.

@TsuyoshiUshio
Copy link
Collaborator Author

Hi @Flanker32
I update the code and make it one Retry. Could you review the code, please?

Hi @pragnagopa
I update the version to 1.5.0-SNAPSHOT

Copy link
Member

@pragnagopa pragnagopa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added minor comment. Please wait for ACK from @amamounelsayed . Also, open issue in mvn plugin and link it here to ensure we have a track updates on the mvn plugin before publishing a version without -SNAPSHOT

@TsuyoshiUshio
Copy link
Collaborator Author

Hi @Flanker32

Do you know why this CI fails happens? it is cloning the maven plugin and cannot find azure-auth-helper. Do I need package repository?

image

https://github.com/microsoft/azure-maven-plugins/blob/develop/azure-maven-plugin-lib/pom.xml#L116

* The minimum delay interval.
* @return The minimum retry delay.
*/
String minimumInterval() default "";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we use integer here and set the interval in second directly? which may be more clear and no need to care about the format. Otherwise, do we support time string like 00:00:120?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thats a good point! minimumInterval, maximumInterval and delayInterval get converted to type TimeSpan , is there an equivalent in Java?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duration?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if converting Duration to string will give us the format hh:mm:ss

Copy link
Collaborator Author

@TsuyoshiUshio TsuyoshiUshio Nov 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can do it. There is an api to fetch it as second. However, I'm not sure Duration is good fit for the annotation. Probably String (as is) or int (second) might be a good fit for it. (I just reply the TimeSpan equivalent) https://www.dariawan.com/tutorials/java/java-time-duration-tutorial-examples/
Hi @Flanker32 Which would you want to prefer? If you choose int, you need to format String. If you use String, no need to convert it since it is the format of function.json IMO, String might be better. the reason is, Functions Host currently support String with that format. In the future, if people add expression on the String on the functions host side, we need to do breaking change. What do you think?

Copy link
Member

@pragnagopa pragnagopa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for going back and forth on this. Thinking about this more, initial commit you had probably makes sense as the scope is method level only and having separate annotations eliminates guess work for users on what values to provide for each strategy.

This would be similar to what webjobs SDK exposes but mvn would have to generate retry section in function.json

* The minimum delay interval.
* @return The minimum retry delay.
*/
String minimumInterval() default "";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if converting Duration to string will give us the format hh:mm:ss

@TsuyoshiUshio
Copy link
Collaborator Author

Hi @Flanker32

For the function.jsonconfiguration, we defined both minimumInterval and maximumInterval for exponentialBackoff, so what will happen if exponential interval is larger then maximumInterval?

For instance, if set minimumInterval to 2s and maximumInterval to 10s, and the interval for the fourth retry will be 16s which higher than the maximum value, will function host rerun the trigger in 10s or will throw an exception in this situation? Do we need to validate the annotation in tooling side? Besides, is there any value limitation for minimumInterval or maximumInterval

In this case, the retry duration is 10s. There is no exception. If the retry duration reach to the maximum interval, it keeps the maximum interval.

https://github.com/Azure/azure-webjobs-sdk/blob/b798412ad74ba97cf2d85487ae8479f277bdd85c/src/Microsoft.Azure.WebJobs.Host/Timers/RandomizedExponentialBackoffStrategy.cs

Copy link
Member

@pragnagopa pragnagopa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Signing off again :) thank you!

@TsuyoshiUshio TsuyoshiUshio merged commit 0098603 into dev Nov 17, 2020
@TsuyoshiUshio TsuyoshiUshio changed the title [DoNotMerge] Add Retry annotation Add Retry annotation Nov 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants