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

httploader: Implement retries #5077

Merged
merged 5 commits into from Oct 6, 2022
Merged

httploader: Implement retries #5077

merged 5 commits into from Oct 6, 2022

Conversation

yroc92
Copy link
Collaborator

@yroc92 yroc92 commented Sep 24, 2022

Resolves #5070

Screen Shot 2022-09-23 at 11 46 50 PM

@yroc92 yroc92 requested a review from mholt September 24, 2022 06:52
@yroc92
Copy link
Collaborator Author

yroc92 commented Sep 24, 2022

Not sure if the logging is correct? I think I can replace their logger like so:

retryClient.Logger = ctx.Logger()

but I kept getting this error:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x18 pc=0x102c544ec]

goroutine 1 [running]:
github.com/caddyserver/caddy/v2.(*Logging).Logger(0x14000499860, {0x0?, 0x0?})
        /Users/corycooper/workspace/github/caddy/logging.go:202 +0x2c
github.com/caddyserver/caddy/v2.Context.Logger({{0x103f5e4f0, 0x140003b4d40}, 0x14000499800, 0x14000054f00, {0x0, 0x0, 0x0}, {0x0, 0x0, 0x0}}, ...)
        /Users/corycooper/workspace/github/caddy/context.go:478 +0xc0
github.com/caddyserver/caddy/v2/caddyconfig.getRetryClient({{0x103f5e4f0, 0x140003b4d40}, 0x14000499800, 0x14000054f00, {0x0, 0x0, 0x0}, {0x0, 0x0, 0x0}}, ...)
        /Users/corycooper/workspace/github/caddy/caddyconfig/httploader.go:131 +0xbc
github.com/caddyserver/caddy/v2/caddyconfig.HTTPLoader.makeClient({{0x140006ddf28, 0x4}, {0x14000044ae0, 0x22}, 0x0, 0x0, 0x5, 0x0}, {{0x103f5e4f0, 0x140003b4d40}, ...})
        /Users/corycooper/workspace/github/caddy/caddyconfig/httploader.go:145 +0x7c
github.com/caddyserver/caddy/v2/caddyconfig.HTTPLoader.LoadConfig({{0x140006ddf28, 0x4}, {0x14000044ae0, 0x22}, 0x0, 0x0, 0x5, 0x0}, {{0x103f5e4f0, 0x140003b4d40}, ...})
        /Users/corycooper/workspace/github/caddy/caddyconfig/httploader.go:81 +0x17c
github.com/caddyserver/caddy/v2.finishSettingUp({{0x103f5e4f0, 0x140003b4d40}, 0x14000499800, 0x14000054f00, {0x0, 0x0, 0x0}, {0x0, 0x0, 0x0}}, ...)
        /Users/corycooper/workspace/github/caddy/caddy.go:603 +0x4c0
github.com/caddyserver/caddy/v2.run(0x1400025e320?, 0x1)
        /Users/corycooper/workspace/github/caddy/caddy.go:525 +0x584
github.com/caddyserver/caddy/v2.unsyncedDecodeAndRun({0x1400025e1e0, 0x91, 0xa0}, 0x1)
        /Users/corycooper/workspace/github/caddy/caddy.go:337 +0xe4
github.com/caddyserver/caddy/v2.changeConfig({0x1037fc1a6, 0x4}, {0x1038092a9, 0x7}, {0x140002ec400, 0xe1, 0x200}, {0x0, 0x0}, 0x1)
        /Users/corycooper/workspace/github/caddy/caddy.go:228 +0x644
github.com/caddyserver/caddy/v2.Load({0x140002ec400?, 0xb?, 0x0?}, 0x0?)
        /Users/corycooper/workspace/github/caddy/caddy.go:127 +0x8c
github.com/caddyserver/caddy/v2/cmd.cmdRun({0x0?})
        /Users/corycooper/workspace/github/caddy/cmd/commandfuncs.go:212 +0x558
github.com/caddyserver/caddy/v2/cmd.caddyCmdToCoral.func1(0x140002e0500?, {0x1037fce86?, 0x2?, 0x2?})
        /Users/corycooper/workspace/github/caddy/cmd/cobra.go:114 +0x30
github.com/spf13/cobra.(*Command).execute(0x140002e0500, {0x140001c8b20, 0x2, 0x2})
        /Users/corycooper/go/pkg/mod/github.com/spf13/cobra@v1.1.3/command.go:852 +0x4c4
github.com/spf13/cobra.(*Command).ExecuteC(0x104baac40)
        /Users/corycooper/go/pkg/mod/github.com/spf13/cobra@v1.1.3/command.go:960 +0x34c
github.com/spf13/cobra.(*Command).Execute(...)
        /Users/corycooper/go/pkg/mod/github.com/spf13/cobra@v1.1.3/command.go:897
github.com/caddyserver/caddy/v2/cmd.Main()
        /Users/corycooper/workspace/github/caddy/cmd/main.go:64 +0x74
main.main()
        /Users/corycooper/workspace/github/caddy/cmd/caddy/main.go:39 +0x1c

@francislavoie
Copy link
Member

Is the dependency really necessary? This seems like the sort of thing we should just do ourselves in code. We try to avoid dependencies as much as possible.

@mholt
Copy link
Member

mholt commented Sep 24, 2022

Yeah, retries can be done with a for loop.

@yroc92
Copy link
Collaborator Author

yroc92 commented Sep 24, 2022

So I have the client.Do() call replaced with this function, but keep getting a nil point error when trying to use ctx.Logger(). What am I missing?

// Reattempts the http call using exponential back off when maxRetries is greater than 0.
func doHttpCallWithRetries(ctx caddy.Context, client *http.Client, request *http.Request, maxRetries int) (*http.Response, error) {
	var resp *http.Response
	var err error
	var errorMessage string
	for retry := 0; retry <= maxRetries; retry++ {
		resp, err = client.Do(request)
		if err != nil {
			errorMessage = fmt.Sprintf("problem calling endpoint: %v", err)
		} else if resp.StatusCode < 200 || resp.StatusCode > 499 {
			errorMessage = fmt.Sprintf("bad response status code from endpoint: %v", resp.StatusCode)
		} else {
			return resp, nil
		}
		ctx.Logger().Error(errorMessage)

		exponentialBackOff := math.Pow(2, float64(retry))
		ctx.Logger().Info(fmt.Sprintf("reattempting in %g seconds", exponentialBackOff))
		time.Sleep(time.Duration(exponentialBackOff) * time.Second)
	}

	return resp, err
}

Error:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x18 pc=0x100ac84ec]

goroutine 1 [running]:
github.com/caddyserver/caddy/v2.(*Logging).Logger(0x140000bd800, {0x0?, 0x0?})
        /Users/corycooper/workspace/github/caddy/logging.go:202 +0x2c
github.com/caddyserver/caddy/v2.Context.Logger({{0x101dc8c70, 0x14000683780}, 0x140000bd7d0, 0x1400018fd10, {0x0, 0x0, 0x0}, {0x0, 0x0, 0x0}}, ...)
        /Users/corycooper/workspace/github/caddy/context.go:478 +0xc0
github.com/caddyserver/caddy/v2/caddyconfig.HTTPLoader.doHttpCallWithRetries({{0x14000688f58, 0x4}, {0x140001d4d50, 0x24}, 0x0, 0x0, 0x5, 0x0}, {{0x101dc8c70, 0x14000683780}, ...}, ...)
        /Users/corycooper/workspace/github/caddy/caddyconfig/httploader.go:140 +0xa4
github.com/caddyserver/caddy/v2/caddyconfig.HTTPLoader.LoadConfig({{0x14000688f58, 0x4}, {0x140001d4d50, 0x24}, 0x0, 0x0, 0x5, 0x0}, {{0x101dc8c70, 0x14000683780}, ...})
        /Users/corycooper/workspace/github/caddy/caddyconfig/httploader.go:101 +0x35c
github.com/caddyserver/caddy/v2.finishSettingUp({{0x101dc8c70, 0x14000683780}, 0x140000bd7d0, 0x1400018fd10, {0x0, 0x0, 0x0}, {0x0, 0x0, 0x0}}, ...)
        /Users/corycooper/workspace/github/caddy/caddy.go:603 +0x4c0
github.com/caddyserver/caddy/v2.run(0x140000d6320?, 0x1)
        /Users/corycooper/workspace/github/caddy/caddy.go:525 +0x584
github.com/caddyserver/caddy/v2.unsyncedDecodeAndRun({0x140000d6280, 0x93, 0xa0}, 0x1)
        /Users/corycooper/workspace/github/caddy/caddy.go:337 +0xe4
github.com/caddyserver/caddy/v2.changeConfig({0x10166b466, 0x4}, {0x101678569, 0x7}, {0x14000474400, 0xe3, 0x200}, {0x0, 0x0}, 0x1)
        /Users/corycooper/workspace/github/caddy/caddy.go:228 +0x644
github.com/caddyserver/caddy/v2.Load({0x14000474400?, 0xb?, 0x0?}, 0x0?)
        /Users/corycooper/workspace/github/caddy/caddy.go:127 +0x8c
github.com/caddyserver/caddy/v2/cmd.cmdRun({0x0?})
        /Users/corycooper/workspace/github/caddy/cmd/commandfuncs.go:212 +0x558
github.com/caddyserver/caddy/v2/cmd.caddyCmdToCoral.func1(0x140003fc000?, {0x10166c146?, 0x2?, 0x2?})
        /Users/corycooper/workspace/github/caddy/cmd/cobra.go:114 +0x30
github.com/spf13/cobra.(*Command).execute(0x140003fc000, {0x140000bef80, 0x2, 0x2})
        /Users/corycooper/go/pkg/mod/github.com/spf13/cobra@v1.1.3/command.go:852 +0x4c4
github.com/spf13/cobra.(*Command).ExecuteC(0x102a12a20)
        /Users/corycooper/go/pkg/mod/github.com/spf13/cobra@v1.1.3/command.go:960 +0x34c
github.com/spf13/cobra.(*Command).Execute(...)
        /Users/corycooper/go/pkg/mod/github.com/spf13/cobra@v1.1.3/command.go:897
github.com/caddyserver/caddy/v2/cmd.Main()
        /Users/corycooper/workspace/github/caddy/cmd/main.go:64 +0x74
main.main()
        /Users/corycooper/workspace/github/caddy/cmd/caddy/main.go:39 +0x1c
        ```

@francislavoie francislavoie changed the title admin:httploader: Add max_retries caddyconfig: Add max_retries option to admin httploader Sep 24, 2022
@francislavoie francislavoie changed the title caddyconfig: Add max_retries option to admin httploader caddyconfig: Add max_retries option to admin http config loader Sep 24, 2022
@francislavoie
Copy link
Member

The logger issue is related to this change e43b6d8

But I don't know why it's failing. It seems like it's not able to get a module from the context for some reason. I'm confused. It might be because config loader modules don't get Provision'd so they don't go through the module auto-wiring stuff. Matt will need to chime in here of course.

@yroc92 yroc92 marked this pull request as ready for review September 25, 2022 06:36
@yroc92
Copy link
Collaborator Author

yroc92 commented Sep 25, 2022

I changed it to use the caddy.Log() directly which works.

@mholt
Copy link
Member

mholt commented Sep 28, 2022

I'll take a look at this shortly!

Copy link
Member

@mholt mholt left a comment

Choose a reason for hiding this comment

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

I think this looks good overall! I had some thoughts that I wanted to bounce off you.

caddyconfig/httploader.go Outdated Show resolved Hide resolved
@francislavoie francislavoie added the feature ⚙️ New feature or request label Oct 1, 2022
@yroc92 yroc92 changed the title caddyconfig: Add max_retries option to admin http config loader caddyconfig: Add retry_delay option to admin http config loader Oct 5, 2022
Copy link
Member

@mholt mholt left a comment

Choose a reason for hiding this comment

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

This is looking really good!

Most of my comments are nits but I have a few technical suggestions as well. Hopefully these make sense.

Thanks for your patience with me.

caddyconfig/httploader.go Outdated Show resolved Hide resolved
caddyconfig/httploader.go Outdated Show resolved Hide resolved
caddyconfig/httploader.go Outdated Show resolved Hide resolved
caddyconfig/httploader.go Outdated Show resolved Hide resolved
caddyconfig/httploader.go Outdated Show resolved Hide resolved
caddyconfig/httploader.go Outdated Show resolved Hide resolved
@mholt mholt added the under review 🧐 Review is pending before merging label Oct 5, 2022
@mholt mholt added this to the v2.6.2 milestone Oct 5, 2022
@yroc92 yroc92 changed the title caddyconfig: Add retry_delay option to admin http config loader httploader: Implement retries Oct 5, 2022
Copy link
Member

@mholt mholt left a comment

Choose a reason for hiding this comment

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

Awesome!! Looking much better and more straightforward.

Just a few suggestions for code tidiness but otherwise this has my approval.

caddyconfig/httploader.go Outdated Show resolved Hide resolved
caddyconfig/httploader.go Outdated Show resolved Hide resolved
caddyconfig/httploader.go Outdated Show resolved Hide resolved
@mholt mholt removed the under review 🧐 Review is pending before merging label Oct 5, 2022
Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
Copy link
Member

@mholt mholt left a comment

Choose a reason for hiding this comment

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

It's perfect. Thanks Cory!

@mholt mholt merged commit 498f32b into master Oct 6, 2022
@mholt mholt deleted the load-http-retries branch October 6, 2022 04:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature ⚙️ New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add retries to http loader
3 participants