mirror of
https://codeberg.org/scip/pgidler.git
synced 2025-12-18 21:11:01 +01:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c99e6e3f8a |
@@ -1,54 +0,0 @@
|
|||||||
# vim: set ts=2 sw=2 tw=0 fo=cnqoj
|
|
||||||
|
|
||||||
version: 2
|
|
||||||
|
|
||||||
before:
|
|
||||||
hooks:
|
|
||||||
- go mod tidy
|
|
||||||
|
|
||||||
gitea_urls:
|
|
||||||
api: https://codeberg.org/api/v1
|
|
||||||
download: https://codeberg.org
|
|
||||||
|
|
||||||
builds:
|
|
||||||
- env:
|
|
||||||
- CGO_ENABLED=0
|
|
||||||
goos:
|
|
||||||
- linux
|
|
||||||
- darwin
|
|
||||||
- freebsd
|
|
||||||
|
|
||||||
archives:
|
|
||||||
- formats: [binary]
|
|
||||||
name_template: >-
|
|
||||||
{{ .ProjectName }}_
|
|
||||||
{{- title .Os }}_
|
|
||||||
{{- if eq .Arch "amd64" }}x86_64
|
|
||||||
{{- else if eq .Arch "386" }}i386
|
|
||||||
{{- else }}{{ .Arch }}{{ end }}
|
|
||||||
{{- if .Arm }}v{{ .Arm }}{{ end }}_{{ .Tag }}
|
|
||||||
wrap_in_directory: true
|
|
||||||
|
|
||||||
changelog:
|
|
||||||
sort: asc
|
|
||||||
filters:
|
|
||||||
exclude:
|
|
||||||
- "^docs:"
|
|
||||||
- "^test:"
|
|
||||||
groups:
|
|
||||||
- title: Improved
|
|
||||||
regexp: '^.*?(feat|add|new)(\([[:word:]]+\))??!?:.+$'
|
|
||||||
order: 0
|
|
||||||
- title: Fixed
|
|
||||||
regexp: '^.*?(bug|fix)(\([[:word:]]+\))??!?:.+$'
|
|
||||||
order: 1
|
|
||||||
- title: Changed
|
|
||||||
order: 999
|
|
||||||
|
|
||||||
release:
|
|
||||||
header: "# Release Notes"
|
|
||||||
footer: >-
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Full Changelog: [{{ .PreviousTag }}...{{ .Tag }}](https://codeberg.org/scip/pgidler/compare/{{ .PreviousTag }}...{{ .Tag }})
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
matrix:
|
|
||||||
platform:
|
|
||||||
- linux/amd64
|
|
||||||
goversion:
|
|
||||||
- 1.24
|
|
||||||
|
|
||||||
labels:
|
|
||||||
platform: ${platform}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
build:
|
|
||||||
when:
|
|
||||||
event: [push]
|
|
||||||
image: golang:${goversion}
|
|
||||||
commands:
|
|
||||||
- go get
|
|
||||||
- go build
|
|
||||||
|
|
||||||
linter:
|
|
||||||
when:
|
|
||||||
event: [push]
|
|
||||||
image: golang:${goversion}
|
|
||||||
commands:
|
|
||||||
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.5.0
|
|
||||||
- golangci-lint --version
|
|
||||||
- golangci-lint run ./...
|
|
||||||
depends_on: [build]
|
|
||||||
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# build release
|
|
||||||
|
|
||||||
labels:
|
|
||||||
platform: linux/amd64
|
|
||||||
|
|
||||||
steps:
|
|
||||||
goreleaser:
|
|
||||||
image: goreleaser/goreleaser
|
|
||||||
when:
|
|
||||||
event: [tag]
|
|
||||||
environment:
|
|
||||||
GITEA_TOKEN:
|
|
||||||
from_secret: DEPLOY_TOKEN
|
|
||||||
commands:
|
|
||||||
- goreleaser release --clean --verbose
|
|
||||||
33
Makefile
33
Makefile
@@ -1,33 +0,0 @@
|
|||||||
|
|
||||||
# Copyright © 2023 Thomas von Dein
|
|
||||||
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# no need to modify anything below
|
|
||||||
tool = pgidler
|
|
||||||
dir = /home/postgres
|
|
||||||
pod = pgdkb-servicedbloadte4c2b6-0
|
|
||||||
|
|
||||||
all: buildlocal
|
|
||||||
|
|
||||||
buildlocal:
|
|
||||||
CGO_LDFLAGS='-static' go build -tags osusergo,netgo -ldflags="-extldflags=-static -s"
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf $(tool) coverage.out
|
|
||||||
|
|
||||||
goupdate:
|
|
||||||
go get -t -u=patch ./...
|
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
> [!IMPORTANT]
|
||||||
|
> This software is now being maintained on [Codeberg](https://codeberg.org/scip/pgidler/).
|
||||||
|
|
||||||
# pgidler
|
# pgidler
|
||||||
|
|
||||||
Create idle postgres connections for testing
|
Create idle postgres connections for testing
|
||||||
|
|||||||
8
go.mod
8
go.mod
@@ -1,8 +0,0 @@
|
|||||||
module pgidler
|
|
||||||
|
|
||||||
go 1.24
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/lib/pq v1.10.9
|
|
||||||
github.com/spf13/pflag v1.0.10
|
|
||||||
)
|
|
||||||
6
go.sum
6
go.sum
@@ -1,6 +0,0 @@
|
|||||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
|
||||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
|
||||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
|
||||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
|
||||||
182
main.go
182
main.go
@@ -1,182 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright © 2023 Thomas von Dein
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Commentary:
|
|
||||||
|
|
||||||
This little program implements:
|
|
||||||
https://aws.amazon.com/blogs/database/performance-impact-of-idle-postgresql-connections/
|
|
||||||
|
|
||||||
It opens 1k concurrent postgres connections, does a couple of
|
|
||||||
selects and then stops doing anything further, thus creating
|
|
||||||
hanging idle sessions.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
_ "github.com/lib/pq"
|
|
||||||
flag "github.com/spf13/pflag"
|
|
||||||
)
|
|
||||||
|
|
||||||
const version = "v0.0.2"
|
|
||||||
|
|
||||||
type Tableschema struct {
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
const Maxloop int = 100
|
|
||||||
const Getschema string = "SELECT table_schema||'.'||table_name as relname from information_schema.tables WHERE table_schema='information_schema';"
|
|
||||||
const Gettable string = "SELECT * FROM information_schema.columns LIMIT 1;"
|
|
||||||
const StartTransaction string = "BEGIN TRANSACTION"
|
|
||||||
const HostConnection string = "user=%s dbname=%s password=%s"
|
|
||||||
const NetConnection string = "user=%s dbname=%s password=%s host=%s port=%d"
|
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var optPasswd string
|
|
||||||
var optUser string
|
|
||||||
var optDatabase string
|
|
||||||
var optServer string
|
|
||||||
var optPort int
|
|
||||||
var optMaxconnections int
|
|
||||||
var optTimeout int
|
|
||||||
var optIdleTransaction, shversion bool
|
|
||||||
var ctx context.Context
|
|
||||||
var cancel context.CancelFunc
|
|
||||||
var conn string
|
|
||||||
|
|
||||||
flag.StringVarP(&optPasswd, "password", "p", "", "Password of the database user")
|
|
||||||
flag.StringVarP(&optUser, "user", "u", "postgres", "Database user")
|
|
||||||
flag.StringVarP(&optDatabase, "database", "d", "postgres", "Database")
|
|
||||||
flag.StringVarP(&optServer, "server", "s", "localhost", "Server")
|
|
||||||
flag.IntVarP(&optMaxconnections, "client", "c", 500, "Number of concurrent users")
|
|
||||||
flag.IntVarP(&optPort, "port", "P", 5432, "TCP Port")
|
|
||||||
flag.IntVarP(&optTimeout, "timeout", "t", 0, "Whether to stop the clients after N seconds")
|
|
||||||
flag.BoolVarP(&optIdleTransaction, "idletransaction", "i", false, "Wether to stay in idle in transaction state")
|
|
||||||
flag.BoolVarP(&shversion, "version", "v", false, "show version")
|
|
||||||
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
if shversion {
|
|
||||||
fmt.Printf("pgidler version %s\n", version)
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if optServer != "" {
|
|
||||||
conn = fmt.Sprintf(NetConnection, optUser, optDatabase, optPasswd, optServer, optPort)
|
|
||||||
} else {
|
|
||||||
conn = fmt.Sprintf(HostConnection, optUser, optDatabase, optPasswd)
|
|
||||||
}
|
|
||||||
|
|
||||||
// first do a connection test
|
|
||||||
db, err := sql.Open("postgres", conn)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := db.Close(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("DB Connection works, firing up %d clients\n", optMaxconnections)
|
|
||||||
|
|
||||||
if optTimeout > 0 {
|
|
||||||
ctx, cancel = context.WithTimeout(context.Background(), time.Duration(optTimeout)*time.Second)
|
|
||||||
log.Printf("Clients will be killed after %d seconds", optTimeout)
|
|
||||||
} else {
|
|
||||||
ctx = context.TODO()
|
|
||||||
log.Println("Clients will run endlessly, abort with C-c")
|
|
||||||
}
|
|
||||||
|
|
||||||
wg.Add(optMaxconnections)
|
|
||||||
|
|
||||||
for m := 0; m < optMaxconnections; m++ {
|
|
||||||
go dbClient(ctx, conn, optIdleTransaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
if cancel != nil {
|
|
||||||
cancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func dbClient(ctx context.Context, conn string, idle bool) {
|
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
db, err := sql.Open("postgres", conn)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if idle {
|
|
||||||
_, err := db.Exec(StartTransaction)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rows, err := db.Query(Getschema)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if err := rows.Close(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
//log.Println("Got rows")
|
|
||||||
|
|
||||||
for rows.Next() {
|
|
||||||
var T Tableschema
|
|
||||||
if err := rows.Scan(&T.Name); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
//log.Printf("Got table %s\n", T.Name)
|
|
||||||
|
|
||||||
for i := 0; i < Maxloop; i++ {
|
|
||||||
rows, err := db.Query(Gettable)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore result
|
|
||||||
if err := rows.Close(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//log.Println("Got tables")
|
|
||||||
|
|
||||||
// block this thread forever or timeout
|
|
||||||
//select {}
|
|
||||||
select {
|
|
||||||
case <-time.After(1 * time.Second):
|
|
||||||
case <-ctx.Done():
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user