...

Source file src/github.com/ory/x/sqlcon/parse_opts.go

Documentation: github.com/ory/x/sqlcon

     1  package sqlcon
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  	"strconv"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/ory/x/logrusx"
    11  )
    12  
    13  // ParseConnectionOptions parses values for max_conns, max_idle_conns, max_conn_lifetime from DSNs.
    14  // It also returns the URI without those query parameters.
    15  func ParseConnectionOptions(l *logrusx.Logger, dsn string) (maxConns int, maxIdleConns int, maxConnLifetime time.Duration, cleanedDSN string) {
    16  	maxConns = maxParallelism() * 2
    17  	maxIdleConns = maxParallelism()
    18  	maxConnLifetime = time.Duration(0)
    19  	cleanedDSN = dsn
    20  
    21  	parts := strings.Split(dsn, "?")
    22  	if len(parts) != 2 {
    23  		l.
    24  			WithField("sql_max_connections", maxConns).
    25  			WithField("sql_max_idle_connections", maxIdleConns).
    26  			WithField("sql_max_connection_lifetime", maxConnLifetime).
    27  			Debugf("No SQL connection options have been defined, falling back to default connection options.")
    28  		return
    29  	}
    30  
    31  	query, err := url.ParseQuery(parts[1])
    32  	if err != nil {
    33  		l.
    34  			WithField("sql_max_connections", maxConns).
    35  			WithField("sql_max_idle_connections", maxIdleConns).
    36  			WithField("sql_max_connection_lifetime", maxConnLifetime).
    37  			WithError(err).
    38  			Warnf("Unable to parse SQL DSN query, falling back to default connection options.")
    39  		return
    40  	}
    41  
    42  	if v := query.Get("max_conns"); v != "" {
    43  		s, err := strconv.ParseInt(v, 10, 64)
    44  		if err != nil {
    45  			l.WithError(err).Warnf(`SQL DSN query parameter "max_conns" value %v could not be parsed to int, falling back to default value %d`, v, maxConns)
    46  		} else {
    47  			maxConns = int(s)
    48  		}
    49  		query.Del("max_conns")
    50  	}
    51  
    52  	if v := query.Get("max_idle_conns"); v != "" {
    53  		s, err := strconv.ParseInt(v, 10, 64)
    54  		if err != nil {
    55  			l.WithError(err).Warnf(`SQL DSN query parameter "max_idle_conns" value %v could not be parsed to int, falling back to default value %d`, v, maxIdleConns)
    56  		} else {
    57  			maxIdleConns = int(s)
    58  		}
    59  		query.Del("max_idle_conns")
    60  	}
    61  
    62  	if v := query.Get("max_conn_lifetime"); v != "" {
    63  		s, err := time.ParseDuration(v)
    64  		if err != nil {
    65  			l.WithError(err).Warnf(`SQL DSN query parameter "max_conn_lifetime" value %v could not be parsed to duration, falling back to default value %d`, v, maxConnLifetime)
    66  		} else {
    67  			maxConnLifetime = s
    68  		}
    69  		query.Del("max_conn_lifetime")
    70  	}
    71  	cleanedDSN = fmt.Sprintf("%s?%s", parts[0], query.Encode())
    72  
    73  	return
    74  }
    75  
    76  // FinalizeDSN will return a finalized DSN URI.
    77  func FinalizeDSN(l *logrusx.Logger, dsn string) string {
    78  	if strings.HasPrefix(dsn, "mysql://") {
    79  		var q url.Values
    80  		parts := strings.SplitN(dsn, "?", 2)
    81  
    82  		if len(parts) == 1 {
    83  			q = make(url.Values)
    84  		} else {
    85  			var err error
    86  			q, err = url.ParseQuery(parts[1])
    87  			if err != nil {
    88  				l.WithError(err).Warnf("Unable to parse SQL DSN query, could not finalize the DSN URI.")
    89  				return dsn
    90  			}
    91  		}
    92  
    93  		q.Set("multiStatements", "true")
    94  		q.Set("parseTime", "true")
    95  
    96  		return fmt.Sprintf("%s?%s", parts[0], q.Encode())
    97  	}
    98  
    99  	return dsn
   100  }
   101  

View as plain text