improve the new Wait method

This commit is contained in:
Gerasimos (Makis) Maropoulos 2024-01-15 04:20:45 +02:00
parent 70882914d4
commit 12546322eb
No known key found for this signature in database
GPG Key ID: B9839E9CD30B7B6B
3 changed files with 29 additions and 14 deletions

View File

@ -32,7 +32,7 @@ func main() {
ctx.Writef("Hello, %s!", "World") ctx.Writef("Hello, %s!", "World")
}) })
app.Listen(":8080", iris.NonBlocking()) app.Listen(":8080", iris.NonBlocking(), iris.WithoutServerError(iris.ErrServerClosed))
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel() defer cancel()

View File

@ -7,6 +7,7 @@ import (
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
"sync"
"time" "time"
"github.com/kataras/iris/v12/context" "github.com/kataras/iris/v12/context"
@ -976,13 +977,25 @@ type Configuration struct {
// //
// Defaults to empty map. // Defaults to empty map.
Other map[string]interface{} `ini:"other" json:"other,omitempty" yaml:"Other" toml:"Other"` Other map[string]interface{} `ini:"other" json:"other,omitempty" yaml:"Other" toml:"Other"`
mu sync.RWMutex // mutex for some of the configuration fields that may change during parallel jobs (see Application.NonBlocking & Wait).
} }
var _ context.ConfigurationReadOnly = (*Configuration)(nil) var _ context.ConfigurationReadOnly = (*Configuration)(nil)
// GetVHost returns the non-exported vhost config field. // GetVHost returns the non-exported VHost config field.
func (c *Configuration) GetVHost() string { func (c *Configuration) GetVHost() string {
return c.VHost c.mu.RLock()
vhost := c.VHost
c.mu.RUnlock()
return vhost
}
// SetVHost sets the non-exported VHost config field.
func (c *Configuration) SetVHost(s string) {
c.mu.Lock()
c.VHost = s
c.mu.Unlock()
} }
// GetLogLevel returns the LogLevel field. // GetLogLevel returns the LogLevel field.

24
iris.go
View File

@ -552,17 +552,17 @@ func (app *Application) NewHost(srv *http.Server) *host.Supervisor {
// bind the constructed server and return it // bind the constructed server and return it
su := host.New(srv) su := host.New(srv)
if app.config.VHost == "" { // vhost now is useful for router subdomain on wildcard subdomains, if app.config.GetVHost() == "" { // vhost now is useful for router subdomain on wildcard subdomains,
// in order to correct decide what to do on: // in order to correct decide what to do on:
// mydomain.com -> invalid // mydomain.com -> invalid
// localhost -> invalid // localhost -> invalid
// sub.mydomain.com -> valid // sub.mydomain.com -> valid
// sub.localhost -> valid // sub.localhost -> valid
// we need the host (without port if 80 or 443) in order to validate these, so: // we need the host (without port if 80 or 443) in order to validate these, so:
app.config.VHost = netutil.ResolveVHost(srv.Addr) app.config.SetVHost(netutil.ResolveVHost(srv.Addr))
} else { } else {
context.GetDomain = func(_ string) string { // #1886 context.GetDomain = func(_ string) string { // #1886
return app.config.VHost return app.config.VHost // GetVHost: here we don't need mutex protection as it's request-time and all modifications are already made.
} }
} }
@ -629,10 +629,7 @@ func (app *Application) NewHost(srv *http.Server) *host.Supervisor {
func (app *Application) Shutdown(ctx stdContext.Context) error { func (app *Application) Shutdown(ctx stdContext.Context) error {
app.mu.Lock() app.mu.Lock()
defer app.mu.Unlock() defer app.mu.Unlock()
defer app.setRunError(ErrServerClosed) // make sure to set the error so any .Wait calls return.
defer func() {
app.setRunError(ErrServerClosed) // make sure to set the error so any .Wait calls return.
}()
for i, su := range app.Hosts { for i, su := range app.Hosts {
app.logger.Debugf("Host[%d]: Shutdown now", i) app.logger.Debugf("Host[%d]: Shutdown now", i)
@ -816,7 +813,7 @@ type Runner func(*Application) error
// See `Run` for more. // See `Run` for more.
func Listener(l net.Listener, hostConfigs ...host.Configurator) Runner { func Listener(l net.Listener, hostConfigs ...host.Configurator) Runner {
return func(app *Application) error { return func(app *Application) error {
app.config.VHost = netutil.ResolveVHost(l.Addr().String()) app.config.SetVHost(netutil.ResolveVHost(l.Addr().String()))
return app.NewHost(&http.Server{Addr: l.Addr().String()}). return app.NewHost(&http.Server{Addr: l.Addr().String()}).
Configure(hostConfigs...). Configure(hostConfigs...).
Serve(l) Serve(l)
@ -1137,8 +1134,6 @@ func getMaxRetries(retryInterval time.Duration, base float64) int {
// tryConnect tries to connect to the server with the given context and retry parameters. // tryConnect tries to connect to the server with the given context and retry parameters.
func (app *Application) tryConnect(ctx stdContext.Context, maxRetries int, retryInterval time.Duration, base float64) error { func (app *Application) tryConnect(ctx stdContext.Context, maxRetries int, retryInterval time.Duration, base float64) error {
address := app.config.GetVHost() // Get this server's listening address.
// Try to connect to the server in a loop. // Try to connect to the server in a loop.
for i := 0; i < maxRetries; i++ { for i := 0; i < maxRetries; i++ {
// Check the context before each attempt. // Check the context before each attempt.
@ -1147,6 +1142,13 @@ func (app *Application) tryConnect(ctx stdContext.Context, maxRetries int, retry
// Context is canceled, return the context error. // Context is canceled, return the context error.
return ctx.Err() return ctx.Err()
default: default:
address := app.config.GetVHost() // Get this server's listening address.
if address == "" {
i-- // Note that this may be modified at another go routine of the serve method. So it may be empty at first chance. So retry fetching the VHost every 1 second.
time.Sleep(time.Second)
continue
}
// Context is not canceled, proceed with the attempt. // Context is not canceled, proceed with the attempt.
conn, err := net.Dial("tcp", address) conn, err := net.Dial("tcp", address)
if err == nil { if err == nil {
@ -1198,7 +1200,7 @@ func (app *Application) tryStartTunneling() {
publicAddr := publicAddrs[0] publicAddr := publicAddrs[0]
// to make subdomains resolution still based on this new remote, public addresses. // to make subdomains resolution still based on this new remote, public addresses.
app.config.VHost = publicAddr[strings.Index(publicAddr, "://")+3:] app.config.SetVHost(publicAddr[strings.Index(publicAddr, "://")+3:])
directLog := []byte(fmt.Sprintf("• Public Address: %s\n", publicAddr)) directLog := []byte(fmt.Sprintf("• Public Address: %s\n", publicAddr))
app.logger.Printer.Write(directLog) // nolint:errcheck app.logger.Printer.Write(directLog) // nolint:errcheck