@@ -563,62 +563,13 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co
563
563
options .Database = dbfake .New ()
564
564
options .Pubsub = database .NewPubsubInMemory ()
565
565
} else {
566
- logger .Debug (ctx , "connecting to postgresql" )
567
- sqlDB , err := sql .Open (sqlDriver , cfg .PostgresURL .Value )
566
+ sqlDB , err := connectToPostgres (ctx , logger , sqlDriver , cfg .PostgresURL .Value )
568
567
if err != nil {
569
- return xerrors .Errorf ("dial postgres: %w" , err )
568
+ return xerrors .Errorf ("connect to postgres: %w" , err )
570
569
}
571
- defer sqlDB .Close ()
572
-
573
- pingCtx , pingCancel := context .WithTimeout (ctx , 15 * time .Second )
574
- defer pingCancel ()
575
-
576
- err = sqlDB .PingContext (pingCtx )
577
- if err != nil {
578
- return xerrors .Errorf ("ping postgres: %w" , err )
579
- }
580
-
581
- // Ensure the PostgreSQL version is >=13.0.0!
582
- version , err := sqlDB .QueryContext (ctx , "SHOW server_version;" )
583
- if err != nil {
584
- return xerrors .Errorf ("get postgres version: %w" , err )
585
- }
586
- if ! version .Next () {
587
- return xerrors .Errorf ("no rows returned for version select" )
588
- }
589
- var versionStr string
590
- err = version .Scan (& versionStr )
591
- if err != nil {
592
- return xerrors .Errorf ("scan version: %w" , err )
593
- }
594
- _ = version .Close ()
595
- versionStr = strings .Split (versionStr , " " )[0 ]
596
- if semver .Compare ("v" + versionStr , "v13" ) < 0 {
597
- return xerrors .New ("PostgreSQL version must be v13.0.0 or higher!" )
598
- }
599
- logger .Debug (ctx , "connected to postgresql" , slog .F ("version" , versionStr ))
600
-
601
- err = migrations .Up (sqlDB )
602
- if err != nil {
603
- return xerrors .Errorf ("migrate up: %w" , err )
604
- }
605
- // The default is 0 but the request will fail with a 500 if the DB
606
- // cannot accept new connections, so we try to limit that here.
607
- // Requests will wait for a new connection instead of a hard error
608
- // if a limit is set.
609
- sqlDB .SetMaxOpenConns (10 )
610
- // Allow a max of 3 idle connections at a time. Lower values end up
611
- // creating a lot of connection churn. Since each connection uses about
612
- // 10MB of memory, we're allocating 30MB to Postgres connections per
613
- // replica, but is better than causing Postgres to spawn a thread 15-20
614
- // times/sec. PGBouncer's transaction pooling is not the greatest so
615
- // it's not optimal for us to deploy.
616
- //
617
- // This was set to 10 before we started doing HA deployments, but 3 was
618
- // later determined to be a better middle ground as to not use up all
619
- // of PGs default connection limit while simultaneously avoiding a lot
620
- // of connection churn.
621
- sqlDB .SetMaxIdleConns (3 )
570
+ defer func () {
571
+ _ = sqlDB .Close ()
572
+ }()
622
573
623
574
options .Database = database .New (sqlDB )
624
575
options .Pubsub , err = database .NewPubsub (ctx , sqlDB , cfg .PostgresURL .Value )
@@ -1007,7 +958,8 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co
1007
958
postgresBuiltinURLCmd .Flags ().BoolVar (& pgRawURL , "raw-url" , false , "Output the raw connection URL instead of a psql command." )
1008
959
postgresBuiltinServeCmd .Flags ().BoolVar (& pgRawURL , "raw-url" , false , "Output the raw connection URL instead of a psql command." )
1009
960
1010
- root .AddCommand (postgresBuiltinURLCmd , postgresBuiltinServeCmd )
961
+ createAdminUserCommand := newCreateAdminUserCommand ()
962
+ root .AddCommand (postgresBuiltinURLCmd , postgresBuiltinServeCmd , createAdminUserCommand )
1011
963
1012
964
deployment .AttachFlags (root .Flags (), vip , false )
1013
965
@@ -1607,3 +1559,71 @@ func buildLogger(cmd *cobra.Command, cfg *codersdk.DeploymentConfig) (slog.Logge
1607
1559
}
1608
1560
}, nil
1609
1561
}
1562
+
1563
+ func connectToPostgres (ctx context.Context , logger slog.Logger , driver string , dbURL string ) (* sql.DB , error ) {
1564
+ logger .Debug (ctx , "connecting to postgresql" )
1565
+ sqlDB , err := sql .Open (driver , dbURL )
1566
+ if err != nil {
1567
+ return nil , xerrors .Errorf ("dial postgres: %w" , err )
1568
+ }
1569
+
1570
+ ok := false
1571
+ defer func () {
1572
+ if ! ok {
1573
+ _ = sqlDB .Close ()
1574
+ }
1575
+ }()
1576
+
1577
+ pingCtx , pingCancel := context .WithTimeout (ctx , 15 * time .Second )
1578
+ defer pingCancel ()
1579
+
1580
+ err = sqlDB .PingContext (pingCtx )
1581
+ if err != nil {
1582
+ return nil , xerrors .Errorf ("ping postgres: %w" , err )
1583
+ }
1584
+
1585
+ // Ensure the PostgreSQL version is >=13.0.0!
1586
+ version , err := sqlDB .QueryContext (ctx , "SHOW server_version;" )
1587
+ if err != nil {
1588
+ return nil , xerrors .Errorf ("get postgres version: %w" , err )
1589
+ }
1590
+ if ! version .Next () {
1591
+ return nil , xerrors .Errorf ("no rows returned for version select" )
1592
+ }
1593
+ var versionStr string
1594
+ err = version .Scan (& versionStr )
1595
+ if err != nil {
1596
+ return nil , xerrors .Errorf ("scan version: %w" , err )
1597
+ }
1598
+ _ = version .Close ()
1599
+ versionStr = strings .Split (versionStr , " " )[0 ]
1600
+ if semver .Compare ("v" + versionStr , "v13" ) < 0 {
1601
+ return nil , xerrors .New ("PostgreSQL version must be v13.0.0 or higher!" )
1602
+ }
1603
+ logger .Debug (ctx , "connected to postgresql" , slog .F ("version" , versionStr ))
1604
+
1605
+ err = migrations .Up (sqlDB )
1606
+ if err != nil {
1607
+ return nil , xerrors .Errorf ("migrate up: %w" , err )
1608
+ }
1609
+ // The default is 0 but the request will fail with a 500 if the DB
1610
+ // cannot accept new connections, so we try to limit that here.
1611
+ // Requests will wait for a new connection instead of a hard error
1612
+ // if a limit is set.
1613
+ sqlDB .SetMaxOpenConns (10 )
1614
+ // Allow a max of 3 idle connections at a time. Lower values end up
1615
+ // creating a lot of connection churn. Since each connection uses about
1616
+ // 10MB of memory, we're allocating 30MB to Postgres connections per
1617
+ // replica, but is better than causing Postgres to spawn a thread 15-20
1618
+ // times/sec. PGBouncer's transaction pooling is not the greatest so
1619
+ // it's not optimal for us to deploy.
1620
+ //
1621
+ // This was set to 10 before we started doing HA deployments, but 3 was
1622
+ // later determined to be a better middle ground as to not use up all
1623
+ // of PGs default connection limit while simultaneously avoiding a lot
1624
+ // of connection churn.
1625
+ sqlDB .SetMaxIdleConns (3 )
1626
+
1627
+ ok = true
1628
+ return sqlDB , nil
1629
+ }
0 commit comments