Thanks to visit codestin.com
Credit goes to github.com

Skip to content

chore: dbpool #17753

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

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/actions/setup-go/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@ runs:
export GOCACHE_DIR="$RUNNER_TEMP""\go-cache"
export GOMODCACHE_DIR="$RUNNER_TEMP""\go-mod-cache"
export GOPATH_DIR="$RUNNER_TEMP""\go-path"
export GOTMP_DIR="$RUNNER_TEMP""\go-tmp"
mkdir -p "$GOCACHE_DIR"
mkdir -p "$GOMODCACHE_DIR"
mkdir -p "$GOPATH_DIR"
mkdir -p "$GOTMP_DIR"
go env -w GOCACHE="$GOCACHE_DIR"
go env -w GOMODCACHE="$GOMODCACHE_DIR"
go env -w GOPATH="$GOPATH_DIR"

go env -w GOTMPDIR="$GOTMP_DIR"
- name: Setup Go
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ jobs:
api-key: ${{ secrets.DATADOG_API_KEY }}

test-go-pg:
runs-on: ${{ matrix.os == 'ubuntu-latest' && github.repository_owner == 'coder' && 'depot-ubuntu-22.04-4' || matrix.os }}
runs-on: ${{ matrix.os == 'ubuntu-latest' && github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || matrix.os }}
needs: changes
if: needs.changes.outputs.go == 'true' || needs.changes.outputs.ci == 'true' || github.ref == 'refs/heads/main'
# This timeout must be greater than the timeout set by `go test` in
Expand Down
28 changes: 17 additions & 11 deletions .github/workflows/nightly-gauntlet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ on:
# Every day at 4AM
- cron: "0 4 * * 1-5"
workflow_dispatch:
pull_request:
branches:
- main

permissions:
contents: read

jobs:
test-go-pg:
runs-on: ${{ matrix.os == 'macos-latest' && github.repository_owner == 'coder' && 'depot-macos-latest' || matrix.os == 'windows-2022' && github.repository_owner == 'coder' && 'windows-latest-16-cores' || matrix.os }}
if: github.ref == 'refs/heads/main'
runs-on: ${{ matrix.os == 'macos-latest' && github.repository_owner == 'coder' && 'depot-macos-latest' || matrix.os == 'windows-2022' && github.repository_owner == 'coder' && 'depot-windows-2022-16' || matrix.os }}
# This timeout must be greater than the timeout set by `go test` in
# `make test-postgres` to ensure we receive a trace of running
# goroutines. Setting this to the timeout +5m should work quite well
Expand All @@ -31,22 +33,29 @@ jobs:
with:
egress-policy: audit

# Set up RAM disks to speed up the rest of the job. This action is in
# a separate repository to allow its use before actions/checkout.
- name: Setup RAM Disks
if: runner.os == 'Windows'
uses: coder/setup-ramdisk-action@79dacfe70c47ad6d6c0dd7f45412368802641439

- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 1

- name: Setup Go
uses: ./.github/actions/setup-go
with:
# Runners have Go baked-in and Go will automatically
# download the toolchain configured in go.mod, so we don't
# need to reinstall it. It's faster on Windows runners.
use-preinstalled-go: ${{ runner.os == 'Windows' }}
use-temp-cache-dirs: ${{ runner.os == 'Windows' }}

- name: Setup Terraform
uses: ./.github/actions/setup-tf

# Sets up the ImDisk toolkit for Windows and creates a RAM disk on drive R:.
- name: Setup ImDisk
if: runner.os == 'Windows'
uses: ./.github/actions/setup-imdisk

- name: Test with PostgreSQL Database
env:
POSTGRES_VERSION: "13"
Expand Down Expand Up @@ -81,10 +90,7 @@ jobs:
go run scripts/embedded-pg/main.go
fi

# Reduce test parallelism, mirroring what we do for race tests.
# We'd been encountering issues with timing related flakes, and
# this seems to help.
DB=ci gotestsum --format standard-quiet -- -v -short -count=1 -parallel 4 -p 4 ./...
DB=ci gotestsum --rerun-fails=2 --rerun-fails-max-failures=1000 --format standard-quiet -- -v -p 8 -parallel 16 -count=1 - ./...

- name: Upload test stats to Datadog
timeout-minutes: 1
Expand Down
31 changes: 31 additions & 0 deletions coderd/database/dbtestutil/dbpool/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package dbpool

import "net/rpc"

type Client struct {
rpcClient *rpc.Client
}

func NewClient(addr string) (*Client, error) {
rpcClient, err := rpc.DialHTTP("tcp", addr)
if err != nil {
return nil, err
}
return &Client{rpcClient: rpcClient}, nil
}

func (c *Client) GetDB() (string, error) {
var arg int
var reply string
err := c.rpcClient.Call("DBPool.GetDB", &arg, &reply)
return reply, err
}

func (c *Client) DisposeDB(dbURL string) error {
var reply int
return c.rpcClient.Call("DBPool.DisposeDB", &dbURL, &reply)
}

func (c *Client) Close() error {
return c.rpcClient.Close()
}
113 changes: 92 additions & 21 deletions coderd/database/dbtestutil/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"errors"
"fmt"
"net"
"net/url"
"os"
"path/filepath"
"strconv"
Expand All @@ -21,6 +22,7 @@
"github.com/ory/dockertest/v3/docker"
"golang.org/x/xerrors"

"github.com/coder/coder/v2/coderd/database/dbtestutil/dbpool"
"github.com/coder/coder/v2/coderd/database/migrations"
"github.com/coder/coder/v2/cryptorand"
"github.com/coder/retry"
Expand All @@ -38,6 +40,39 @@
return fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable", p.Username, p.Password, p.Host, p.Port, p.DBName)
}

func ParseDSN(dsn string) (ConnectionParams, error) {
u, err := url.Parse(dsn)
if err != nil {
return ConnectionParams{}, xerrors.Errorf("parse dsn: %w", err)
}

if u.Scheme != "postgres" {
return ConnectionParams{}, xerrors.Errorf("invalid dsn scheme: %s", u.Scheme)
}

var params ConnectionParams
if u.User != nil {
params.Username = u.User.Username()
params.Password, _ = u.User.Password()
}

params.Host = u.Hostname()
params.Port = u.Port()
if params.Port == "" {
// Default PostgreSQL port
params.Port = "5432"
}

// The path includes a leading slash, remove it.
if len(u.Path) > 1 {
params.DBName = u.Path[1:]
} else {
return ConnectionParams{}, xerrors.New("database name missing in dsn")
}

return params, nil
}

// These variables are global because all tests share them.
var (
connectionParamsInitOnce sync.Once
Expand Down Expand Up @@ -138,24 +173,75 @@
Logf(format string, args ...any)
}

func RemoveDB(t TBSubset, dbName string) error {
cleanupDbURL := defaultConnectionParams.DSN()
cleanupConn, err := sql.Open("postgres", cleanupDbURL)
if err != nil {
return xerrors.Errorf("cleanup database %q: failed to connect to postgres: %w", dbName, err)
}
defer func() {
if err := cleanupConn.Close(); err != nil {
t.Logf("cleanup database %q: failed to close connection: %s\n", dbName, err.Error())
}
}()
_, err = cleanupConn.Exec("DROP DATABASE " + dbName + ";")
if err != nil {
return xerrors.Errorf("cleanup database %q: failed to drop database: %w", dbName, err)
}
return nil
}

func getDBPoolClient() (*dbpool.Client, error) {
dbpoolURL := os.Getenv("DBPOOL")
if dbpoolURL == "" {
return nil, nil //nolint:nilnil
}
client, err := dbpool.NewClient(dbpoolURL)
if err != nil {
return nil, xerrors.Errorf("create db pool client: %w", err)
}
return client, nil
}

// Open creates a new PostgreSQL database instance.
// If there's a database running at localhost:5432, it will use that.
// Otherwise, it will start a new postgres container.
func Open(t TBSubset, opts ...OpenOption) (string, error) {
t.Helper()

openOptions := OpenOptions{}
for _, opt := range opts {
opt(&openOptions)
}

if openOptions.DBFrom == nil {
dbPoolClient, err := getDBPoolClient()
if err != nil {
return "", xerrors.Errorf("get db pool client: %w", err)
}
if dbPoolClient != nil {
dbURL, err := dbPoolClient.GetDB()
if err != nil {
return "", xerrors.Errorf("get db from pool: %w", err)
}
t.Cleanup(func() {
defer dbPoolClient.Close()
err := dbPoolClient.DisposeDB(dbURL)
if err != nil {
t.Logf("cleanup database %s: failed to dispose db: %+v\n", dbURL, err)
}
})
return dbURL, nil
}
}

connectionParamsInitOnce.Do(func() {
errDefaultConnectionParamsInit = initDefaultConnection(t)
})
if errDefaultConnectionParamsInit != nil {
return "", xerrors.Errorf("init default connection params: %w", errDefaultConnectionParamsInit)
}

openOptions := OpenOptions{}
for _, opt := range opts {
opt(&openOptions)
}

var (
username = defaultConnectionParams.Username
password = defaultConnectionParams.Password
Expand All @@ -182,22 +268,7 @@
}

t.Cleanup(func() {
cleanupDbURL := defaultConnectionParams.DSN()
cleanupConn, err := sql.Open("postgres", cleanupDbURL)
if err != nil {
t.Logf("cleanup database %q: failed to connect to postgres: %s\n", dbName, err.Error())
return
}
defer func() {
if err := cleanupConn.Close(); err != nil {
t.Logf("cleanup database %q: failed to close connection: %s\n", dbName, err.Error())
}
}()
_, err = cleanupConn.Exec("DROP DATABASE " + dbName + ";")
if err != nil {
t.Logf("failed to clean up database %q: %s\n", dbName, err.Error())
return
}
RemoveDB(t, dbName)

Check failure on line 271 in coderd/database/dbtestutil/postgres.go

View workflow job for this annotation

GitHub Actions / lint

Error return value is not checked (errcheck)
})

dsn := ConnectionParams{
Expand Down
Loading
Loading