Adding upstream version 1.37.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
42613ad5c6
commit
271b368104
1329 changed files with 4727104 additions and 0 deletions
22
issue198/go.mod
Normal file
22
issue198/go.mod
Normal file
|
@ -0,0 +1,22 @@
|
|||
module example.com/issue198
|
||||
|
||||
go 1.23.3
|
||||
|
||||
require (
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.24 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
golang.org/x/sync v0.9.0 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
|
||||
modernc.org/libc v1.55.3 // indirect
|
||||
modernc.org/mathutil v1.6.0 // indirect
|
||||
modernc.org/memory v1.8.0 // indirect
|
||||
modernc.org/sqlite v1.34.1 // indirect
|
||||
modernc.org/strutil v1.2.0 // indirect
|
||||
modernc.org/token v1.1.0 // indirect
|
||||
)
|
33
issue198/go.sum
Normal file
33
issue198/go.sum
Normal file
|
@ -0,0 +1,33 @@
|
|||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI=
|
||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
|
||||
modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U=
|
||||
modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w=
|
||||
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
|
||||
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
|
||||
modernc.org/sqlite v1.34.1 h1:u3Yi6M0N8t9yKRDwhXcyp1eS5/ErhPTBggxWFuR6Hfk=
|
||||
modernc.org/sqlite v1.34.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k=
|
||||
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
||||
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
158
issue198/main.go
Normal file
158
issue198/main.go
Normal file
|
@ -0,0 +1,158 @@
|
|||
// https://gitlab.com/cznic/sqlite/-/issues/198#note_2232364348
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||
defer cancel()
|
||||
|
||||
absDb, err := filepath.Abs("simple-web.db")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
dbSlash := "/" + strings.TrimPrefix(filepath.ToSlash(absDb), "/")
|
||||
connStr := "file://" + dbSlash + "?_pragma=foreign_keys(1)&_pragma=journal_mode(WAL)&_pragma=synchronous(NORMAL)&_pragma=busy_timeout(10000)"
|
||||
// connStr = "file:///" + dbSlash + "?_foreign_keys=1&_journal_mode=WAL&_synchronous=NORMAL&_busy_timeout=10000&_mutex=no"
|
||||
fmt.Printf("connecting to %s\n", connStr)
|
||||
db, err := sql.Open("sqlite", connStr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
db.SetMaxOpenConns(20)
|
||||
db.SetMaxIdleConns(2)
|
||||
db.SetConnMaxLifetime(5 * time.Minute)
|
||||
db.SetConnMaxIdleTime(1 * time.Minute)
|
||||
defer db.Close()
|
||||
|
||||
if _, err := db.Exec(`CREATE TABLE IF NOT EXISTS data (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL DEFAULT ''
|
||||
)`); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
db.Exec(`DELETE FROM data`)
|
||||
db.Exec(`INSERT INTO data (Id, Name) VALUES (1, 'A'),(2, 'B'),(3, 'C'),(4, 'D');`)
|
||||
|
||||
http.HandleFunc("/items/{id}", func(w http.ResponseWriter, r *http.Request) {
|
||||
id := r.PathValue("id")
|
||||
type entry struct {
|
||||
Id int64 `sql:"id"`
|
||||
Name string `sql:"name"`
|
||||
}
|
||||
|
||||
scanEntry := func(ctx context.Context, id string) (entry, error) {
|
||||
ctx = context.Background()
|
||||
// modernc sqlite breaks connections when context gets cancelled
|
||||
dbConn, err := db.Conn(ctx)
|
||||
// var sqliteErr *sqlite.Error
|
||||
// for err != nil && errors.As(err, &sqliteErr) && sqliteErr.Code() == sqlite3.SQLITE_BUSY {
|
||||
// // fmt.Fprintf(os.Stderr, "failed to obtain connection. retrying %#v\n", err)
|
||||
// time.Sleep(time.Microsecond)
|
||||
// dbConn, err = db.Conn(ctx)
|
||||
// }
|
||||
if err != nil {
|
||||
return entry{}, fmt.Errorf("obtaining db conn: %w", err)
|
||||
}
|
||||
defer dbConn.Close()
|
||||
|
||||
// modernc sqlite breaks connections when context gets cancelled
|
||||
// ctx = context.Background()
|
||||
row := dbConn.QueryRowContext(ctx, "SELECT Id,Name FROM data WHERE id = ? LIMIT 1", id)
|
||||
if err := row.Err(); err != nil {
|
||||
return entry{}, fmt.Errorf("retrieving row: %w", err)
|
||||
}
|
||||
|
||||
e := entry{}
|
||||
if err := row.Scan(&e.Id, &e.Name); err != nil {
|
||||
return entry{}, fmt.Errorf("scanning entry: %w", err)
|
||||
}
|
||||
return e, nil
|
||||
}
|
||||
|
||||
const HttpClientClosedRequest = 499
|
||||
|
||||
e, err := scanEntry(r.Context(), id)
|
||||
if err != nil {
|
||||
if errors.Is(err, context.Canceled) {
|
||||
w.WriteHeader(HttpClientClosedRequest)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
fmt.Fprintf(os.Stderr, "%v - failed to retrieve row %v\n", time.Now().Format(time.RFC3339), err)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
fmt.Fprintf(w, "%#v", e)
|
||||
})
|
||||
|
||||
server := http.Server{
|
||||
Addr: "127.0.0.1:8082",
|
||||
Handler: http.DefaultServeMux,
|
||||
}
|
||||
go func() {
|
||||
if err := server.ListenAndServe(); err != nil {
|
||||
fmt.Printf("server: %v\n", err)
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
RunClient(ctx)
|
||||
}()
|
||||
<-ctx.Done()
|
||||
server.Shutdown(context.Background())
|
||||
|
||||
db.Close()
|
||||
}
|
||||
|
||||
func RunClient(ctx context.Context) {
|
||||
eg, _ := errgroup.WithContext(ctx)
|
||||
|
||||
limit := 20
|
||||
eg.SetLimit(limit)
|
||||
c := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
MaxIdleConns: 6,
|
||||
MaxConnsPerHost: 6,
|
||||
DisableKeepAlives: false,
|
||||
IdleConnTimeout: 10 * time.Second,
|
||||
}, Timeout: 5 * time.Second}
|
||||
|
||||
for i := 0; i < limit; i++ {
|
||||
eg.Go(func() error {
|
||||
|
||||
for ctx.Err() == nil {
|
||||
res, err := c.Get("http://127.0.0.1:8082/items/2")
|
||||
if err != nil {
|
||||
fmt.Printf("err http.Do %v\n", err)
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
}
|
||||
io.Copy(io.Discard, res.Body)
|
||||
res.Body.Close()
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err := eg.Wait(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue