From bc2ba25ff892afa270facf8a6ef913ee679e6bcf Mon Sep 17 00:00:00 2001 From: commoddity Date: Mon, 13 Nov 2023 17:06:07 +0000 Subject: [PATCH 1/3] feat: updated to use PGX postgres lib --- Makefile | 3 +- go.mod | 18 ++- go.sum | 49 +++++- postgres-driver/db.generated.go | 15 +- postgres-driver/models.generated.go | 84 +++++----- postgres-driver/pocket_session.go | 7 +- postgres-driver/postgresdriver.go | 185 ++++++++++++++-------- postgres-driver/query.sql.generated.go | 126 +++++++-------- postgres-driver/relay.go | 47 +++--- postgres-driver/relay_test.go | 32 ++-- postgres-driver/service_record.go | 10 +- postgres-driver/sqlc/query.sql | 190 +++++++++++++++++----- postgres-driver/sqlc/schema.sql | 210 +++++++++++++------------ postgres-driver/sqlc/sqlc.yaml | 5 +- postgres-driver/suite_test.go | 5 +- 15 files changed, 600 insertions(+), 386 deletions(-) diff --git a/Makefile b/Makefile index 96885c3..a2b8cfd 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ gen_sql: test: test_env_up run_driver_tests test_env_down test_env_up: - @echo "🧪 Starting up Transation DB test database ..." + @echo "🧪 Starting up Transaction DB test database ..." @docker-compose -f ./testdata/docker-compose.test.yml up -d --remove-orphans --build @echo "⏳ Waiting for test DB to be ready ..." @attempts=0; while ! pg_isready -h localhost -p 5432 -U postgres -d postgres >/dev/null && [[ $$attempts -lt 5 ]]; do sleep 1; attempts=$$(($$attempts + 1)); done @@ -27,7 +27,6 @@ run_driver_tests_ci: init-pre-commit: wget https://github.com/pre-commit/pre-commit/releases/download/v2.20.0/pre-commit-2.20.0.pyz python3 pre-commit-2.20.0.pyz install - python3 pre-commit-2.20.0.pyz autoupdate go install golang.org/x/tools/cmd/goimports@latest go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest go install -v github.com/go-critic/go-critic/cmd/gocritic@latest diff --git a/go.mod b/go.mod index 574b21f..906e071 100644 --- a/go.mod +++ b/go.mod @@ -3,16 +3,26 @@ module github.com/pokt-foundation/transaction-db go 1.20 require ( + github.com/jackc/pgx/v5 v5.4.3 github.com/lib/pq v1.10.9 github.com/stretchr/testify v1.8.1 - golang.org/x/crypto v0.9.0 + google.golang.org/grpc v1.59.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/kr/pretty v0.1.0 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect + github.com/kr/text v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.8.0 // indirect - gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect + github.com/rogpeppe/go-internal v1.6.1 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/sync v0.3.0 // indirect + golang.org/x/text v0.13.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index d66d4e1..869650b 100644 --- a/go.sum +++ b/go.sum @@ -1,30 +1,63 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= +github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c h1:jHkCUWkseRf+W+edG5hMzr/Uh1xkDREY4caybAq4dpY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/postgres-driver/db.generated.go b/postgres-driver/db.generated.go index 32c61ac..a5a707e 100644 --- a/postgres-driver/db.generated.go +++ b/postgres-driver/db.generated.go @@ -1,19 +1,20 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.22.0 +// sqlc v1.20.0 package postgresdriver import ( "context" - "database/sql" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgconn" ) type DBTX interface { - ExecContext(context.Context, string, ...interface{}) (sql.Result, error) - PrepareContext(context.Context, string) (*sql.Stmt, error) - QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) - QueryRowContext(context.Context, string, ...interface{}) *sql.Row + Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) + Query(context.Context, string, ...interface{}) (pgx.Rows, error) + QueryRow(context.Context, string, ...interface{}) pgx.Row } func New(db DBTX) *Queries { @@ -24,7 +25,7 @@ type Queries struct { db DBTX } -func (q *Queries) WithTx(tx *sql.Tx) *Queries { +func (q *Queries) WithTx(tx pgx.Tx) *Queries { return &Queries{ db: tx, } diff --git a/postgres-driver/models.generated.go b/postgres-driver/models.generated.go index 9962097..39ae5de 100644 --- a/postgres-driver/models.generated.go +++ b/postgres-driver/models.generated.go @@ -1,14 +1,14 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.22.0 +// sqlc v1.20.0 package postgresdriver import ( - "database/sql" "database/sql/driver" "fmt" - "time" + + "github.com/jackc/pgx/v5/pgtype" ) type ErrorSourcesEnum string @@ -54,12 +54,12 @@ func (ns NullErrorSourcesEnum) Value() (driver.Value, error) { } type PocketSession struct { - ID int64 `json:"id"` - SessionKey string `json:"sessionKey"` - SessionHeight int32 `json:"sessionHeight"` - PortalRegionName string `json:"portalRegionName"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID int64 `json:"id"` + SessionKey string `json:"sessionKey"` + SessionHeight int32 `json:"sessionHeight"` + PortalRegionName string `json:"portalRegionName"` + CreatedAt pgtype.Timestamp `json:"createdAt"` + UpdatedAt pgtype.Timestamp `json:"updatedAt"` } type PortalRegion struct { @@ -72,18 +72,18 @@ type Relay struct { EndpointID string `json:"endpointId"` SessionKey string `json:"sessionKey"` ProtocolAppPublicKey string `json:"protocolAppPublicKey"` - RelaySourceUrl sql.NullString `json:"relaySourceUrl"` - PoktNodeAddress sql.NullString `json:"poktNodeAddress"` - PoktNodeDomain sql.NullString `json:"poktNodeDomain"` - PoktNodePublicKey sql.NullString `json:"poktNodePublicKey"` - RelayStartDatetime time.Time `json:"relayStartDatetime"` - RelayReturnDatetime time.Time `json:"relayReturnDatetime"` + RelaySourceUrl pgtype.Text `json:"relaySourceUrl"` + PoktNodeAddress pgtype.Text `json:"poktNodeAddress"` + PoktNodeDomain pgtype.Text `json:"poktNodeDomain"` + PoktNodePublicKey pgtype.Text `json:"poktNodePublicKey"` + RelayStartDatetime pgtype.Timestamp `json:"relayStartDatetime"` + RelayReturnDatetime pgtype.Timestamp `json:"relayReturnDatetime"` IsError bool `json:"isError"` - ErrorCode sql.NullInt32 `json:"errorCode"` - ErrorName sql.NullString `json:"errorName"` - ErrorMessage sql.NullString `json:"errorMessage"` + ErrorCode pgtype.Int4 `json:"errorCode"` + ErrorName pgtype.Text `json:"errorName"` + ErrorMessage pgtype.Text `json:"errorMessage"` ErrorSource NullErrorSourcesEnum `json:"errorSource"` - ErrorType sql.NullString `json:"errorType"` + ErrorType pgtype.Text `json:"errorType"` RelayRoundtripTime float64 `json:"relayRoundtripTime"` RelayChainMethodIds string `json:"relayChainMethodIds"` RelayDataSize int32 `json:"relayDataSize"` @@ -94,30 +94,30 @@ type Relay struct { IsAltruistRelay bool `json:"isAltruistRelay"` IsUserRelay bool `json:"isUserRelay"` RequestID string `json:"requestId"` - PoktTxID sql.NullString `json:"poktTxId"` - GigastakeAppID sql.NullString `json:"gigastakeAppId"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - BlockingPlugin sql.NullString `json:"blockingPlugin"` + PoktTxID pgtype.Text `json:"poktTxId"` + GigastakeAppID pgtype.Text `json:"gigastakeAppId"` + CreatedAt pgtype.Timestamp `json:"createdAt"` + UpdatedAt pgtype.Timestamp `json:"updatedAt"` + BlockingPlugin pgtype.Text `json:"blockingPlugin"` } type ServiceRecord struct { - ID int64 `json:"id"` - NodePublicKey string `json:"nodePublicKey"` - PoktChainID string `json:"poktChainId"` - SessionKey string `json:"sessionKey"` - RequestID string `json:"requestId"` - PortalRegionName string `json:"portalRegionName"` - Latency float64 `json:"latency"` - Tickets int32 `json:"tickets"` - Result string `json:"result"` - Available bool `json:"available"` - Successes int32 `json:"successes"` - Failures int32 `json:"failures"` - P90SuccessLatency float64 `json:"p90SuccessLatency"` - MedianSuccessLatency float64 `json:"medianSuccessLatency"` - WeightedSuccessLatency float64 `json:"weightedSuccessLatency"` - SuccessRate float64 `json:"successRate"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID int64 `json:"id"` + NodePublicKey string `json:"nodePublicKey"` + PoktChainID string `json:"poktChainId"` + SessionKey string `json:"sessionKey"` + RequestID string `json:"requestId"` + PortalRegionName string `json:"portalRegionName"` + Latency float64 `json:"latency"` + Tickets int32 `json:"tickets"` + Result string `json:"result"` + Available bool `json:"available"` + Successes int32 `json:"successes"` + Failures int32 `json:"failures"` + P90SuccessLatency float64 `json:"p90SuccessLatency"` + MedianSuccessLatency float64 `json:"medianSuccessLatency"` + WeightedSuccessLatency float64 `json:"weightedSuccessLatency"` + SuccessRate float64 `json:"successRate"` + CreatedAt pgtype.Timestamp `json:"createdAt"` + UpdatedAt pgtype.Timestamp `json:"updatedAt"` } diff --git a/postgres-driver/pocket_session.go b/postgres-driver/pocket_session.go index 349f52b..204c4d5 100644 --- a/postgres-driver/pocket_session.go +++ b/postgres-driver/pocket_session.go @@ -2,6 +2,7 @@ package postgresdriver import ( "context" + "strings" "time" "github.com/pokt-foundation/transaction-db/types" @@ -18,11 +19,11 @@ func (d *PostgresDriver) WriteSession(ctx context.Context, session types.PocketS SessionKey: session.SessionKey, SessionHeight: int32(session.SessionHeight), PortalRegionName: session.PortalRegionName, - CreatedAt: now, - UpdatedAt: now, + CreatedAt: newTimestamp(now), + UpdatedAt: newTimestamp(now), }) if err != nil { - if isSpecifiedPqError(errMessageDuplicateSessionKey, err) { + if strings.Contains(err.Error(), errMessageDuplicateSessionKey) { return types.ErrRepeatedSessionKey } diff --git a/postgres-driver/postgresdriver.go b/postgres-driver/postgresdriver.go index 9bb1162..3ffae97 100644 --- a/postgres-driver/postgresdriver.go +++ b/postgres-driver/postgresdriver.go @@ -1,120 +1,171 @@ package postgresdriver import ( - "database/sql" - "database/sql/driver" - "net" + "context" + "fmt" "time" // PQ import is required - "github.com/lib/pq" - _ "github.com/lib/pq" - "golang.org/x/crypto/ssh" -) -type ViaSSHDialer struct { - client *ssh.Client -} + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgtype" + "github.com/jackc/pgx/v5/pgxpool" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) -func (self *ViaSSHDialer) Open(s string) (_ driver.Conn, err error) { - return pq.DialOpen(self, s) -} +// The PostgresDriver struct satisfies the Driver interface which defines all database driver methods +type ( + PostgresDriver struct { + *Queries + db *pgxpool.Pool + } -func (self *ViaSSHDialer) Dial(network, address string) (net.Conn, error) { - return self.client.Dial(network, address) -} + CloudSQLConfig struct { + DBUser string + DBPassword string + DBName string + InstanceConnectionName string + PublicIP string + PrivateIP string + } +) -func (self *ViaSSHDialer) DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) { - return self.client.Dial(network, address) -} +/* ---------- Postgres Connection Funcs ---------- */ -// The PostgresDriver struct satisfies the Driver interface which defines all database driver methods -type PostgresDriver struct { - *Queries - db *sql.DB -} +/* <--------- PGX Pool Connection ---------> */ -/* NewPostgresDriver returns PostgresDriver instance from Postgres connection string */ -func NewPostgresDriver(connectionString string) (*PostgresDriver, error) { - db, err := sql.Open("postgres", connectionString) +/* +NewPostgresDriver +- Creates a pool of connections to a PostgreSQL database using the provided connection string. +- Parses the connection string into a pgx pool configuration object. +- For each acquired connection from the pool, custom enum types are registered. +- Returns the established connection pool. +- This function is ideal for creating multiple reusable connections to a PostgreSQL database, particularly useful for handling multiple concurrent database operations. +*/ +func NewPostgresDriver(connectionString string) (*PostgresDriver, func() error, error) { + config, err := pgxpool.ParseConfig(connectionString) if err != nil { - return nil, err + return nil, nil, err } - driver := &PostgresDriver{ - Queries: New(db), - db: db, + pool, err := createAndConfigurePool(config) + if err != nil { + return nil, nil, err } - return driver, nil -} + cleanup := func() error { + pool.Close() + return nil + } -/* NewPostgresDriverFromDBInstance returns PostgresDriver instance from sdl.DB instance */ -// mostly used for mocking tests -func NewPostgresDriverFromDBInstance(db *sql.DB) *PostgresDriver { driver := &PostgresDriver{ - Queries: New(db), + Queries: New(pool), + db: pool, } - return driver + return driver, cleanup, nil } -/* NewPostgresDriver returns PostgresDriver instance from Postgres connection string */ -func NewPostgresDriverWithSSH(connectionString string, sshcon *ssh.Client) (*PostgresDriver, error) { - // Now we register the ViaSSHDialer with the ssh connection as a parameter - sql.Register("postgres+ssh", &ViaSSHDialer{sshcon}) +// Configures the connection pool with custom enum types. +func createAndConfigurePool(config *pgxpool.Config) (*pgxpool.Pool, error) { + pool, err := pgxpool.NewWithConfig(context.Background(), config) + if err != nil { + return nil, fmt.Errorf("pgxpool.NewWithConfig: %v", err) + } - db, err := sql.Open("postgres+ssh", connectionString) + // Collect the custom data types once, store them in memory, and register them for every future connection. + customTypes, err := getCustomDataTypes(context.Background(), pool) if err != nil { return nil, err } + config.AfterConnect = func(ctx context.Context, conn *pgx.Conn) error { + for _, t := range customTypes { + conn.TypeMap().RegisterType(t) + } + return nil + } - driver := &PostgresDriver{ - Queries: New(db), - db: db, + // Immediately close the old pool and open a new one with the new config. + pool.Close() + pool, err = pgxpool.NewWithConfig(context.Background(), config) + if err != nil { + return nil, err } - return driver, nil + return pool, nil } -func newSQLNullInt32(value int32) sql.NullInt32 { - if value == 0 { - return sql.NullInt32{} +// Any custom DB types made with CREATE TYPE need to be registered with pgx. +// https://github.com/kyleconroy/sqlc/issues/2116 +// https://stackoverflow.com/questions/75658429/need-to-update-psql-row-of-a-composite-type-in-golang-with-jack-pgx +// https://pkg.go.dev/github.com/jackc/pgx/v5/pgtype +func getCustomDataTypes(ctx context.Context, pool *pgxpool.Pool) ([]*pgtype.Type, error) { + // Get a single connection just to load type information. + conn, err := pool.Acquire(ctx) + defer conn.Release() + if err != nil { + return nil, err } - return sql.NullInt32{ - Int32: value, - Valid: true, + dataTypeNames := []string{ + "error_sources_enum", + "_error_sources_enum", + } + + var typesToRegister []*pgtype.Type + for _, typeName := range dataTypeNames { + dataType, err := conn.Conn().LoadType(ctx, typeName) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to load type %s: %v", typeName, err) + } + // You need to register only for this connection too, otherwise the array type will look for the register element type. + conn.Conn().TypeMap().RegisterType(dataType) + typesToRegister = append(typesToRegister, dataType) } + return typesToRegister, nil } -func newSQLNullString(value string) sql.NullString { +func newText(value string) pgtype.Text { if value == "" { - return sql.NullString{} + return pgtype.Text{} } - return sql.NullString{ + return pgtype.Text{ String: value, Valid: true, } } -func newSQLNullErrorSource(value ErrorSourcesEnum) NullErrorSourcesEnum { - if value == "" { - return NullErrorSourcesEnum{} +func newInt4(value int32, allowZero bool) pgtype.Int4 { + if !allowZero && value == 0 { + return pgtype.Int4{} } - return NullErrorSourcesEnum{ - ErrorSourcesEnum: value, - Valid: true, + return pgtype.Int4{ + Int32: value, + Valid: true, } } -func isSpecifiedPqError(errMessage string, err error) bool { - pqErr, ok := err.(*pq.Error) - if !ok { - return false +func newTimestamp(value time.Time) pgtype.Timestamp { + if value.IsZero() { + return pgtype.Timestamp{} + } + + return pgtype.Timestamp{ + Time: value, + Valid: true, } +} - return pqErr.Message == errMessage +func newNullErrorSourcesEnum(e ErrorSourcesEnum) NullErrorSourcesEnum { + if e == "" { + return NullErrorSourcesEnum{} + } + + return NullErrorSourcesEnum{ + ErrorSourcesEnum: e, + Valid: true, + } } diff --git a/postgres-driver/query.sql.generated.go b/postgres-driver/query.sql.generated.go index db396a9..6b787c9 100644 --- a/postgres-driver/query.sql.generated.go +++ b/postgres-driver/query.sql.generated.go @@ -1,14 +1,14 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.22.0 +// sqlc v1.20.0 // source: query.sql package postgresdriver import ( "context" - "database/sql" - "time" + + "github.com/jackc/pgx/v5/pgtype" ) const insertPocketSession = `-- name: InsertPocketSession :exec @@ -17,15 +17,15 @@ VALUES ($1, $2, $3, $4, $5) ` type InsertPocketSessionParams struct { - SessionKey string `json:"sessionKey"` - SessionHeight int32 `json:"sessionHeight"` - PortalRegionName string `json:"portalRegionName"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + SessionKey string `json:"sessionKey"` + SessionHeight int32 `json:"sessionHeight"` + PortalRegionName string `json:"portalRegionName"` + CreatedAt pgtype.Timestamp `json:"createdAt"` + UpdatedAt pgtype.Timestamp `json:"updatedAt"` } func (q *Queries) InsertPocketSession(ctx context.Context, arg InsertPocketSessionParams) error { - _, err := q.db.ExecContext(ctx, insertPocketSession, + _, err := q.db.Exec(ctx, insertPocketSession, arg.SessionKey, arg.SessionHeight, arg.PortalRegionName, @@ -41,7 +41,7 @@ VALUES ($1) ` func (q *Queries) InsertPortalRegion(ctx context.Context, portalRegionName string) error { - _, err := q.db.ExecContext(ctx, insertPortalRegion, portalRegionName) + _, err := q.db.Exec(ctx, insertPortalRegion, portalRegionName) return err } @@ -88,18 +88,18 @@ type InsertRelayParams struct { EndpointID string `json:"endpointId"` SessionKey string `json:"sessionKey"` ProtocolAppPublicKey string `json:"protocolAppPublicKey"` - RelaySourceUrl sql.NullString `json:"relaySourceUrl"` - PoktNodeAddress sql.NullString `json:"poktNodeAddress"` - PoktNodeDomain sql.NullString `json:"poktNodeDomain"` - PoktNodePublicKey sql.NullString `json:"poktNodePublicKey"` - RelayStartDatetime time.Time `json:"relayStartDatetime"` - RelayReturnDatetime time.Time `json:"relayReturnDatetime"` + RelaySourceUrl pgtype.Text `json:"relaySourceUrl"` + PoktNodeAddress pgtype.Text `json:"poktNodeAddress"` + PoktNodeDomain pgtype.Text `json:"poktNodeDomain"` + PoktNodePublicKey pgtype.Text `json:"poktNodePublicKey"` + RelayStartDatetime pgtype.Timestamp `json:"relayStartDatetime"` + RelayReturnDatetime pgtype.Timestamp `json:"relayReturnDatetime"` IsError bool `json:"isError"` - ErrorCode sql.NullInt32 `json:"errorCode"` - ErrorName sql.NullString `json:"errorName"` - ErrorMessage sql.NullString `json:"errorMessage"` + ErrorCode pgtype.Int4 `json:"errorCode"` + ErrorName pgtype.Text `json:"errorName"` + ErrorMessage pgtype.Text `json:"errorMessage"` ErrorSource NullErrorSourcesEnum `json:"errorSource"` - ErrorType sql.NullString `json:"errorType"` + ErrorType pgtype.Text `json:"errorType"` RelayRoundtripTime float64 `json:"relayRoundtripTime"` RelayChainMethodIds string `json:"relayChainMethodIds"` RelayDataSize int32 `json:"relayDataSize"` @@ -110,15 +110,15 @@ type InsertRelayParams struct { IsAltruistRelay bool `json:"isAltruistRelay"` IsUserRelay bool `json:"isUserRelay"` RequestID string `json:"requestId"` - PoktTxID sql.NullString `json:"poktTxId"` - GigastakeAppID sql.NullString `json:"gigastakeAppId"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - BlockingPlugin sql.NullString `json:"blockingPlugin"` + PoktTxID pgtype.Text `json:"poktTxId"` + GigastakeAppID pgtype.Text `json:"gigastakeAppId"` + CreatedAt pgtype.Timestamp `json:"createdAt"` + UpdatedAt pgtype.Timestamp `json:"updatedAt"` + BlockingPlugin pgtype.Text `json:"blockingPlugin"` } func (q *Queries) InsertRelay(ctx context.Context, arg InsertRelayParams) error { - _, err := q.db.ExecContext(ctx, insertRelay, + _, err := q.db.Exec(ctx, insertRelay, arg.PoktChainID, arg.EndpointID, arg.SessionKey, @@ -179,27 +179,27 @@ INSERT INTO service_record ( ` type InsertServiceRecordParams struct { - NodePublicKey string `json:"nodePublicKey"` - PoktChainID string `json:"poktChainId"` - SessionKey string `json:"sessionKey"` - RequestID string `json:"requestId"` - PortalRegionName string `json:"portalRegionName"` - Latency float64 `json:"latency"` - Tickets int32 `json:"tickets"` - Result string `json:"result"` - Available bool `json:"available"` - Successes int32 `json:"successes"` - Failures int32 `json:"failures"` - P90SuccessLatency float64 `json:"p90SuccessLatency"` - MedianSuccessLatency float64 `json:"medianSuccessLatency"` - WeightedSuccessLatency float64 `json:"weightedSuccessLatency"` - SuccessRate float64 `json:"successRate"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + NodePublicKey string `json:"nodePublicKey"` + PoktChainID string `json:"poktChainId"` + SessionKey string `json:"sessionKey"` + RequestID string `json:"requestId"` + PortalRegionName string `json:"portalRegionName"` + Latency float64 `json:"latency"` + Tickets int32 `json:"tickets"` + Result string `json:"result"` + Available bool `json:"available"` + Successes int32 `json:"successes"` + Failures int32 `json:"failures"` + P90SuccessLatency float64 `json:"p90SuccessLatency"` + MedianSuccessLatency float64 `json:"medianSuccessLatency"` + WeightedSuccessLatency float64 `json:"weightedSuccessLatency"` + SuccessRate float64 `json:"successRate"` + CreatedAt pgtype.Timestamp `json:"createdAt"` + UpdatedAt pgtype.Timestamp `json:"updatedAt"` } func (q *Queries) InsertServiceRecord(ctx context.Context, arg InsertServiceRecordParams) error { - _, err := q.db.ExecContext(ctx, insertServiceRecord, + _, err := q.db.Exec(ctx, insertServiceRecord, arg.NodePublicKey, arg.PoktChainID, arg.SessionKey, @@ -235,18 +235,18 @@ type SelectRelayRow struct { EndpointID string `json:"endpointId"` SessionKey string `json:"sessionKey"` ProtocolAppPublicKey string `json:"protocolAppPublicKey"` - RelaySourceUrl sql.NullString `json:"relaySourceUrl"` - PoktNodeAddress sql.NullString `json:"poktNodeAddress"` - PoktNodeDomain sql.NullString `json:"poktNodeDomain"` - PoktNodePublicKey sql.NullString `json:"poktNodePublicKey"` - RelayStartDatetime time.Time `json:"relayStartDatetime"` - RelayReturnDatetime time.Time `json:"relayReturnDatetime"` + RelaySourceUrl pgtype.Text `json:"relaySourceUrl"` + PoktNodeAddress pgtype.Text `json:"poktNodeAddress"` + PoktNodeDomain pgtype.Text `json:"poktNodeDomain"` + PoktNodePublicKey pgtype.Text `json:"poktNodePublicKey"` + RelayStartDatetime pgtype.Timestamp `json:"relayStartDatetime"` + RelayReturnDatetime pgtype.Timestamp `json:"relayReturnDatetime"` IsError bool `json:"isError"` - ErrorCode sql.NullInt32 `json:"errorCode"` - ErrorName sql.NullString `json:"errorName"` - ErrorMessage sql.NullString `json:"errorMessage"` + ErrorCode pgtype.Int4 `json:"errorCode"` + ErrorName pgtype.Text `json:"errorName"` + ErrorMessage pgtype.Text `json:"errorMessage"` ErrorSource NullErrorSourcesEnum `json:"errorSource"` - ErrorType sql.NullString `json:"errorType"` + ErrorType pgtype.Text `json:"errorType"` RelayRoundtripTime float64 `json:"relayRoundtripTime"` RelayChainMethodIds string `json:"relayChainMethodIds"` RelayDataSize int32 `json:"relayDataSize"` @@ -256,20 +256,20 @@ type SelectRelayRow struct { IsAltruistRelay bool `json:"isAltruistRelay"` IsUserRelay bool `json:"isUserRelay"` RequestID string `json:"requestId"` - PoktTxID sql.NullString `json:"poktTxId"` - GigastakeAppID sql.NullString `json:"gigastakeAppId"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - BlockingPlugin sql.NullString `json:"blockingPlugin"` + PoktTxID pgtype.Text `json:"poktTxId"` + GigastakeAppID pgtype.Text `json:"gigastakeAppId"` + CreatedAt pgtype.Timestamp `json:"createdAt"` + UpdatedAt pgtype.Timestamp `json:"updatedAt"` + BlockingPlugin pgtype.Text `json:"blockingPlugin"` SessionKey_2 string `json:"sessionKey2"` SessionHeight int32 `json:"sessionHeight"` - CreatedAt_2 time.Time `json:"createdAt2"` - UpdatedAt_2 time.Time `json:"updatedAt2"` + CreatedAt_2 pgtype.Timestamp `json:"createdAt2"` + UpdatedAt_2 pgtype.Timestamp `json:"updatedAt2"` PortalRegionName string `json:"portalRegionName"` } func (q *Queries) SelectRelay(ctx context.Context, id int64) (SelectRelayRow, error) { - row := q.db.QueryRowContext(ctx, selectRelay, id) + row := q.db.QueryRow(ctx, selectRelay, id) var i SelectRelayRow err := row.Scan( &i.ID, @@ -319,7 +319,7 @@ WHERE id = $1 ` func (q *Queries) SelectServiceRecord(ctx context.Context, id int64) (ServiceRecord, error) { - row := q.db.QueryRowContext(ctx, selectServiceRecord, id) + row := q.db.QueryRow(ctx, selectServiceRecord, id) var i ServiceRecord err := row.Scan( &i.ID, diff --git a/postgres-driver/relay.go b/postgres-driver/relay.go index 0d14987..92bc354 100644 --- a/postgres-driver/relay.go +++ b/postgres-driver/relay.go @@ -19,18 +19,18 @@ func (d *PostgresDriver) WriteRelay(ctx context.Context, relay types.Relay) erro EndpointID: relay.EndpointID, SessionKey: relay.SessionKey, ProtocolAppPublicKey: relay.ProtocolAppPublicKey, - RelaySourceUrl: newSQLNullString(relay.RelaySourceURL), - PoktNodeAddress: newSQLNullString(relay.PoktNodeAddress), - PoktNodeDomain: newSQLNullString(relay.PoktNodeDomain), - PoktNodePublicKey: newSQLNullString(relay.PoktNodePublicKey), - RelayStartDatetime: relay.RelayStartDatetime, - RelayReturnDatetime: relay.RelayReturnDatetime, + RelaySourceUrl: newText(relay.RelaySourceURL), + PoktNodeAddress: newText(relay.PoktNodeAddress), + PoktNodeDomain: newText(relay.PoktNodeDomain), + PoktNodePublicKey: newText(relay.PoktNodePublicKey), + RelayStartDatetime: newTimestamp(relay.RelayStartDatetime), + RelayReturnDatetime: newTimestamp(relay.RelayReturnDatetime), IsError: relay.IsError, - ErrorCode: newSQLNullInt32(int32(relay.ErrorCode)), - ErrorName: newSQLNullString(relay.ErrorName), - ErrorMessage: newSQLNullString(relay.ErrorMessage), - ErrorType: newSQLNullString(relay.ErrorType), - ErrorSource: newSQLNullErrorSource(ErrorSourcesEnum(relay.ErrorSource)), + ErrorCode: newInt4(int32(relay.ErrorCode), false), + ErrorName: newText(relay.ErrorName), + ErrorMessage: newText(relay.ErrorMessage), + ErrorType: newText(relay.ErrorType), + ErrorSource: newNullErrorSourcesEnum(ErrorSourcesEnum(relay.ErrorSource)), RelayRoundtripTime: relay.RelayRoundtripTime, RelayChainMethodIds: strings.Join(relay.RelayChainMethodIDs, chainMethodIDSeparator), RelayDataSize: int32(relay.RelayDataSize), @@ -40,17 +40,18 @@ func (d *PostgresDriver) WriteRelay(ctx context.Context, relay types.Relay) erro PortalRegionName: relay.PortalRegionName, IsAltruistRelay: relay.IsAltruistRelay, RequestID: relay.RequestID, - PoktTxID: newSQLNullString(relay.PoktTxID), + PoktTxID: newText(relay.PoktTxID), IsUserRelay: relay.IsUserRelay, - GigastakeAppID: newSQLNullString(relay.GigastakeAppID), - CreatedAt: now, - UpdatedAt: now, - BlockingPlugin: newSQLNullString(relay.BlockingPlugin), + GigastakeAppID: newText(relay.GigastakeAppID), + CreatedAt: newTimestamp(now), + UpdatedAt: newTimestamp(now), + BlockingPlugin: newText(relay.BlockingPlugin), }) } // TODO: use CopyFrom postgres method to do batch inserts more efficiently. -// https://docs.sqlc.dev/en/stable/howto/insert.html#using-copyfrom +// +// https://docs.sqlc.dev/en/stable/howto/insert.html#using-copyfrom func (d *PostgresDriver) WriteRelays(ctx context.Context, relays []*types.Relay) error { var errors []error for _, relay := range relays { @@ -82,8 +83,8 @@ func (d *PostgresDriver) ReadRelay(ctx context.Context, relayID int) (types.Rela PoktNodeAddress: relay.PoktNodeAddress.String, PoktNodeDomain: relay.PoktNodeDomain.String, PoktNodePublicKey: relay.PoktNodePublicKey.String, - RelayStartDatetime: relay.RelayStartDatetime, - RelayReturnDatetime: relay.RelayReturnDatetime, + RelayStartDatetime: relay.RelayStartDatetime.Time, + RelayReturnDatetime: relay.RelayReturnDatetime.Time, IsError: relay.IsError, ErrorCode: int(relay.ErrorCode.Int32), ErrorName: relay.ErrorName.String, @@ -102,13 +103,13 @@ func (d *PostgresDriver) ReadRelay(ctx context.Context, relayID int) (types.Rela IsUserRelay: relay.IsUserRelay, PoktTxID: relay.PoktTxID.String, GigastakeAppID: relay.GigastakeAppID.String, - CreatedAt: relay.CreatedAt, - UpdatedAt: relay.UpdatedAt, + CreatedAt: relay.CreatedAt.Time, + UpdatedAt: relay.UpdatedAt.Time, Session: types.PocketSession{ SessionKey: relay.SessionKey, SessionHeight: int(relay.SessionHeight), - CreatedAt: relay.CreatedAt_2, - UpdatedAt: relay.UpdatedAt_2, + CreatedAt: relay.CreatedAt_2.Time, + UpdatedAt: relay.UpdatedAt_2.Time, }, Region: types.PortalRegion{ PortalRegionName: relay.PortalRegionName, diff --git a/postgres-driver/relay_test.go b/postgres-driver/relay_test.go index 7cb617f..e016c09 100644 --- a/postgres-driver/relay_test.go +++ b/postgres-driver/relay_test.go @@ -42,19 +42,23 @@ func (ts *PGDriverTestSuite) TestPostgresDriver_WriteRelay() { { name: "Success error relay", relay: types.Relay{ - IsError: true, - ErrorCode: 21, - ErrorName: "favorite number", - ErrorMessage: "just Pablo can use it", - ErrorType: "chain_check", - ErrorSource: "internal", - PortalRegionName: ts.firstRelay.PortalRegionName, + IsError: true, + ErrorCode: 21, + ErrorName: "favorite number", + ErrorMessage: "just Pablo can use it", + ErrorType: "chain_check", + ErrorSource: "internal", + PortalRegionName: ts.firstRelay.PortalRegionName, + RelayStartDatetime: time.Now(), + RelayReturnDatetime: time.Now(), }, err: nil, }, } for _, tt := range tests { - ts.Equal(ts.driver.WriteRelay(context.Background(), tt.relay), tt.err) + ts.Run(tt.name, func() { + ts.Equal(ts.driver.WriteRelay(context.Background(), tt.relay), tt.err) + }) } } @@ -103,7 +107,9 @@ func (ts *PGDriverTestSuite) TestPostgresDriver_WriteRelays() { }, } for _, tt := range tests { - ts.Equal(ts.driver.WriteRelays(context.Background(), tt.relays), tt.err) + ts.Run(tt.name, func() { + ts.Equal(ts.driver.WriteRelays(context.Background(), tt.relays), tt.err) + }) } } @@ -122,8 +128,10 @@ func (ts *PGDriverTestSuite) TestPostgresDriver_ReadRelay() { }, } for _, tt := range tests { - relay, err := ts.driver.ReadRelay(context.Background(), tt.relayID) - ts.Equal(err, tt.err) - ts.Equal(relay, tt.expRelay) + ts.Run(tt.name, func() { + relay, err := ts.driver.ReadRelay(context.Background(), tt.relayID) + ts.Equal(err, tt.err) + ts.Equal(relay, tt.expRelay) + }) } } diff --git a/postgres-driver/service_record.go b/postgres-driver/service_record.go index 629b156..3b25f70 100644 --- a/postgres-driver/service_record.go +++ b/postgres-driver/service_record.go @@ -83,8 +83,8 @@ func (d *PostgresDriver) WriteServiceRecord(ctx context.Context, serviceRecord t MedianSuccessLatency: serviceRecord.MedianSuccessLatency, WeightedSuccessLatency: serviceRecord.WeightedSuccessLatency, SuccessRate: serviceRecord.SuccessRate, - CreatedAt: now, - UpdatedAt: now, + CreatedAt: newTimestamp(now), + UpdatedAt: newTimestamp(now), }) } @@ -131,7 +131,7 @@ func (d *PostgresDriver) WriteServiceRecords(ctx context.Context, serviceRecords updatedTimes = append(updatedTimes, now) } - _, err := d.db.Exec(insertServiceRecords, pq.StringArray(nodePublicKeys), + _, err := d.db.Exec(context.TODO(), insertServiceRecords, pq.StringArray(nodePublicKeys), pq.StringArray(poktChainIDs), pq.StringArray(sessionKeys), pq.StringArray(requestIDs), @@ -178,7 +178,7 @@ func (d *PostgresDriver) ReadServiceRecord(ctx context.Context, serviceRecordID MedianSuccessLatency: serviceRecord.MedianSuccessLatency, WeightedSuccessLatency: serviceRecord.WeightedSuccessLatency, SuccessRate: serviceRecord.SuccessRate, - CreatedAt: serviceRecord.CreatedAt, - UpdatedAt: serviceRecord.UpdatedAt, + CreatedAt: serviceRecord.CreatedAt.Time, + UpdatedAt: serviceRecord.UpdatedAt.Time, }, nil } diff --git a/postgres-driver/sqlc/query.sql b/postgres-driver/sqlc/query.sql index cc4fade..91b8436 100644 --- a/postgres-driver/sqlc/query.sql +++ b/postgres-driver/sqlc/query.sql @@ -1,39 +1,70 @@ -- name: InsertRelay :exec INSERT INTO relay ( - pokt_chain_id, - endpoint_id, - session_key, - protocol_app_public_key, - relay_source_url, - pokt_node_address, - pokt_node_domain, - pokt_node_public_key, - relay_start_datetime, - relay_return_datetime, - is_error, - error_code, - error_name, - error_message, - error_source, - error_type, - relay_roundtrip_time, - relay_chain_method_ids, - relay_data_size, - relay_portal_trip_time, - relay_node_trip_time, - relay_url_is_public_endpoint, - portal_region_name, - is_altruist_relay, - is_user_relay, - request_id, - pokt_tx_id, - gigastake_app_id, - created_at, - updated_at, - blocking_plugin -) VALUES ( - $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31 -); + pokt_chain_id, + endpoint_id, + session_key, + protocol_app_public_key, + relay_source_url, + pokt_node_address, + pokt_node_domain, + pokt_node_public_key, + relay_start_datetime, + relay_return_datetime, + is_error, + error_code, + error_name, + error_message, + error_source, + error_type, + relay_roundtrip_time, + relay_chain_method_ids, + relay_data_size, + relay_portal_trip_time, + relay_node_trip_time, + relay_url_is_public_endpoint, + portal_region_name, + is_altruist_relay, + is_user_relay, + request_id, + pokt_tx_id, + gigastake_app_id, + created_at, + updated_at, + blocking_plugin + ) +VALUES ( + $1, + $2, + $3, + $4, + $5, + $6, + $7, + $8, + $9, + $10, + $11, + $12, + $13, + $14, + $15, + $16, + $17, + $18, + $19, + $20, + $21, + $22, + $23, + $24, + $25, + $26, + $27, + $28, + $29, + $30, + $31 + ); -- name: InsertServiceRecord :exec INSERT INTO service_record ( node_public_key, @@ -53,22 +84,97 @@ INSERT INTO service_record ( success_rate, created_at, updated_at -) VALUES ( - $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17 -); + ) +VALUES ( + $1, + $2, + $3, + $4, + $5, + $6, + $7, + $8, + $9, + $10, + $11, + $12, + $13, + $14, + $15, + $16, + $17 + ); -- name: InsertPocketSession :exec -INSERT INTO pocket_session (session_key, session_height, portal_region_name, created_at, updated_at) +INSERT INTO pocket_session ( + session_key, + session_height, + portal_region_name, + created_at, + updated_at + ) VALUES ($1, $2, $3, $4, $5); -- name: InsertPortalRegion :exec INSERT INTO portal_region (portal_region_name) VALUES ($1); -- name: SelectRelay :one -SELECT r.id, r.pokt_chain_id, r.endpoint_id, r.session_key, r.protocol_app_public_key, r.relay_source_url, r.pokt_node_address, r.pokt_node_domain, r.pokt_node_public_key, r.relay_start_datetime, r.relay_return_datetime, r.is_error, r.error_code, r.error_name, r.error_message, r.error_source, r.error_type, r.relay_roundtrip_time, r.relay_chain_method_ids, r.relay_data_size, r.relay_portal_trip_time, r.relay_node_trip_time, r.relay_url_is_public_endpoint, r.is_altruist_relay, r.is_user_relay, r.request_id, r.pokt_tx_id, r.gigastake_app_id, r.created_at, r.updated_at, r.blocking_plugin, ps.session_key, ps.session_height, ps.created_at, ps.updated_at, pr.portal_region_name +SELECT r.id, + r.pokt_chain_id, + r.endpoint_id, + r.session_key, + r.protocol_app_public_key, + r.relay_source_url, + r.pokt_node_address, + r.pokt_node_domain, + r.pokt_node_public_key, + r.relay_start_datetime, + r.relay_return_datetime, + r.is_error, + r.error_code, + r.error_name, + r.error_message, + r.error_source, + r.error_type, + r.relay_roundtrip_time, + r.relay_chain_method_ids, + r.relay_data_size, + r.relay_portal_trip_time, + r.relay_node_trip_time, + r.relay_url_is_public_endpoint, + r.is_altruist_relay, + r.is_user_relay, + r.request_id, + r.pokt_tx_id, + r.gigastake_app_id, + r.created_at, + r.updated_at, + r.blocking_plugin, + ps.session_key, + ps.session_height, + ps.created_at, + ps.updated_at, + pr.portal_region_name FROM relay r - INNER JOIN pocket_session ps ON ps.session_key = r.session_key - INNER JOIN portal_region pr ON pr.portal_region_name = r.portal_region_name + INNER JOIN pocket_session ps ON ps.session_key = r.session_key + INNER JOIN portal_region pr ON pr.portal_region_name = r.portal_region_name WHERE r.id = $1; -- name: SelectServiceRecord :one -SELECT id, node_public_key, pokt_chain_id, session_key, request_id, portal_region_name, latency, tickets, result, available, successes, failures, p90_success_latency, median_success_latency, weighted_success_latency, success_rate, created_at, updated_at +SELECT id, + node_public_key, + pokt_chain_id, + session_key, + request_id, + portal_region_name, + latency, + tickets, + result, + available, + successes, + failures, + p90_success_latency, + median_success_latency, + weighted_success_latency, + success_rate, + created_at, + updated_at FROM service_record WHERE id = $1; diff --git a/postgres-driver/sqlc/schema.sql b/postgres-driver/sqlc/schema.sql index 778589b..07d4af5 100644 --- a/postgres-driver/sqlc/schema.sql +++ b/postgres-driver/sqlc/schema.sql @@ -1,108 +1,112 @@ CREATE TYPE error_sources_enum AS ENUM ('internal', 'external'); - -CREATE TABLE pocket_session ( - id bigint NOT NULL GENERATED ALWAYS AS IDENTITY , - session_key char(44) NOT NULL UNIQUE, - session_height integer NOT NULL , - portal_region_name varchar NOT NULL, - created_at timestamp NOT NULL , - updated_at timestamp NOT NULL , - CONSTRAINT pk_tbl_0 PRIMARY KEY ( id , portal_region_name) - ); - -CREATE TABLE portal_region ( - portal_region_name varchar NOT NULL , - CONSTRAINT pk_portal_region PRIMARY KEY ( portal_region_name ) - ); - -CREATE TABLE relay ( - id bigint NOT NULL GENERATED ALWAYS AS IDENTITY , - pokt_chain_id char(4) NOT NULL , - endpoint_id varchar NOT NULL , - session_key char(44) NOT NULL , - protocol_app_public_key char(64) NOT NULL , - relay_source_url varchar, - pokt_node_address char(40) , - pokt_node_domain varchar , - pokt_node_public_key char(64) , - relay_start_datetime timestamp NOT NULL , - relay_return_datetime timestamp NOT NULL , - is_error boolean NOT NULL , - error_code integer, - error_name varchar, - error_message varchar, - error_source error_sources_enum, - error_type varchar, - relay_roundtrip_time float NOT NULL , - relay_chain_method_ids varchar NOT NULL , - relay_data_size integer NOT NULL , - relay_portal_trip_time float NOT NULL , - relay_node_trip_time float NOT NULL , - relay_url_is_public_endpoint boolean NOT NULL , - portal_region_name varchar NOT NULL , - is_altruist_relay boolean NOT NULL , - is_user_relay boolean NOT NULL , - request_id varchar NOT NULL , - pokt_tx_id varchar , - gigastake_app_id varchar , - created_at timestamp NOT NULL , - updated_at timestamp NOT NULL , - blocking_plugin varchar , - CONSTRAINT pk_relay PRIMARY KEY ( id , portal_region_name ) - ); - +CREATE TABLE pocket_session ( + id bigint NOT NULL GENERATED ALWAYS AS IDENTITY, + session_key char(44) NOT NULL UNIQUE, + session_height integer NOT NULL, + portal_region_name varchar NOT NULL, + created_at timestamp NOT NULL, + updated_at timestamp NOT NULL, + CONSTRAINT pk_tbl_0 PRIMARY KEY (id, portal_region_name) +); +CREATE TABLE portal_region ( + portal_region_name varchar NOT NULL, + CONSTRAINT pk_portal_region PRIMARY KEY (portal_region_name) +); +CREATE TABLE relay ( + id bigint NOT NULL GENERATED ALWAYS AS IDENTITY, + pokt_chain_id char(4) NOT NULL, + endpoint_id varchar NOT NULL, + session_key char(44) NOT NULL, + protocol_app_public_key char(64) NOT NULL, + relay_source_url varchar, + pokt_node_address char(40), + pokt_node_domain varchar, + pokt_node_public_key char(64), + relay_start_datetime timestamp NOT NULL, + relay_return_datetime timestamp NOT NULL, + is_error boolean NOT NULL, + error_code integer, + error_name varchar, + error_message varchar, + error_source error_sources_enum, + error_type varchar, + relay_roundtrip_time float NOT NULL, + relay_chain_method_ids varchar NOT NULL, + relay_data_size integer NOT NULL, + relay_portal_trip_time float NOT NULL, + relay_node_trip_time float NOT NULL, + relay_url_is_public_endpoint boolean NOT NULL, + portal_region_name varchar NOT NULL, + is_altruist_relay boolean NOT NULL, + is_user_relay boolean NOT NULL, + request_id varchar NOT NULL, + pokt_tx_id varchar, + gigastake_app_id varchar, + created_at timestamp NOT NULL, + updated_at timestamp NOT NULL, + blocking_plugin varchar, + CONSTRAINT pk_relay PRIMARY KEY (id, portal_region_name) +); CREATE TABLE service_record ( - id bigint NOT NULL GENERATED ALWAYS AS IDENTITY , - node_public_key char(64) NOT NULL , - pokt_chain_id char(4) NOT NULL , - session_key char(44) NOT NULL, - request_id varchar NOT NULL, - portal_region_name varchar NOT NULL, - latency float NOT NULL, - tickets integer NOT NULL, - result varchar NOT NULL, - available boolean NOT NULL, - successes integer NOT NULL, - failures integer NOT NULL, - p90_success_latency float NOT NULL, - median_success_latency float NOT NULL, - weighted_success_latency float NOT NULL, - success_rate float NOT NULL, - created_at timestamp NOT NULL , - updated_at timestamp NOT NULL , - CONSTRAINT pk_service_record PRIMARY KEY ( id , portal_region_name ) + id bigint NOT NULL GENERATED ALWAYS AS IDENTITY, + node_public_key char(64) NOT NULL, + pokt_chain_id char(4) NOT NULL, + session_key char(44) NOT NULL, + request_id varchar NOT NULL, + portal_region_name varchar NOT NULL, + latency float NOT NULL, + tickets integer NOT NULL, + result varchar NOT NULL, + available boolean NOT NULL, + successes integer NOT NULL, + failures integer NOT NULL, + p90_success_latency float NOT NULL, + median_success_latency float NOT NULL, + weighted_success_latency float NOT NULL, + success_rate float NOT NULL, + created_at timestamp NOT NULL, + updated_at timestamp NOT NULL, + CONSTRAINT pk_service_record PRIMARY KEY (id, portal_region_name) ); - -ALTER TABLE relay ADD CONSTRAINT fk_relay_portal_region FOREIGN KEY ( portal_region_name ) REFERENCES portal_region( portal_region_name ); - -ALTER TABLE relay ADD CONSTRAINT fk_relay_session FOREIGN KEY ( session_key ) REFERENCES pocket_session( session_key ); - -ALTER TABLE service_record ADD CONSTRAINT fk_service_region_portal_region FOREIGN KEY ( portal_region_name ) REFERENCES portal_region( portal_region_name ); - -ALTER TABLE service_record ADD CONSTRAINT fk_service_record_session FOREIGN KEY ( session_key ) REFERENCES pocket_session( session_key ); - -ALTER TABLE pocket_session ADD CONSTRAINT fk_pocket_session_portal_region FOREIGN KEY ( portal_region_name ) REFERENCES portal_region( portal_region_name ); - +ALTER TABLE relay +ADD CONSTRAINT fk_relay_portal_region FOREIGN KEY (portal_region_name) REFERENCES portal_region(portal_region_name); +ALTER TABLE relay +ADD CONSTRAINT fk_relay_session FOREIGN KEY (session_key) REFERENCES pocket_session(session_key); +ALTER TABLE service_record +ADD CONSTRAINT fk_service_region_portal_region FOREIGN KEY (portal_region_name) REFERENCES portal_region(portal_region_name); +ALTER TABLE service_record +ADD CONSTRAINT fk_service_record_session FOREIGN KEY (session_key) REFERENCES pocket_session(session_key); +ALTER TABLE pocket_session +ADD CONSTRAINT fk_pocket_session_portal_region FOREIGN KEY (portal_region_name) REFERENCES portal_region(portal_region_name); INSERT INTO portal_region (portal_region_name) VALUES ('europe-west3'), - ('europe-north1'), - ('europe-west8'), - ('europe-southwest1'), - ('europe-west2'), - ('europe-west9'), - ('us-east4'), - ('us-east5'), - ('us-west2'), - ('us-west1'), - ('northamerica-northeast2'), - ('asia-east2'), - ('asia-northeast1'), - ('asia-northeast3'), - ('asia-south1'), - ('asia-southeast1'), - ('australia-southeast1'); - -INSERT INTO pocket_session -(session_key, session_height, portal_region_name, created_at, updated_at) -VALUES -('', 1, 'europe-west3', TIMESTAMP '1970-01-01 00:00:00', TIMESTAMP '1970-01-01 00:00:00'); + ('europe-north1'), + ('europe-west8'), + ('europe-southwest1'), + ('europe-west2'), + ('europe-west9'), + ('us-east4'), + ('us-east5'), + ('us-west2'), + ('us-west1'), + ('northamerica-northeast2'), + ('asia-east2'), + ('asia-northeast1'), + ('asia-northeast3'), + ('asia-south1'), + ('asia-southeast1'), + ('australia-southeast1'); +INSERT INTO pocket_session ( + session_key, + session_height, + portal_region_name, + created_at, + updated_at + ) +VALUES ( + '', + 1, + 'europe-west3', + TIMESTAMP '1970-01-01 00:00:00', + TIMESTAMP '1970-01-01 00:00:00' + ); diff --git a/postgres-driver/sqlc/sqlc.yaml b/postgres-driver/sqlc/sqlc.yaml index 75264e5..1f9aedd 100644 --- a/postgres-driver/sqlc/sqlc.yaml +++ b/postgres-driver/sqlc/sqlc.yaml @@ -1,8 +1,4 @@ version: "2" -overrides: - go: - rename: - price_usd: "PriceUSD" sql: - schema: "schema.sql" @@ -11,6 +7,7 @@ sql: gen: go: package: "postgresdriver" + sql_package: "pgx/v5" out: ".." json_tags_case_style: camel emit_json_tags: true diff --git a/postgres-driver/suite_test.go b/postgres-driver/suite_test.go index a287d25..9bc27b3 100644 --- a/postgres-driver/suite_test.go +++ b/postgres-driver/suite_test.go @@ -98,10 +98,13 @@ func (ts *PGDriverTestSuite) SetupSuite() { // Initializes a real instance of the Postgres driver that connects to the test Postgres Docker container func (ts *PGDriverTestSuite) initPostgresDriver() error { - driver, err := NewPostgresDriver(ts.connectionString) + driver, _, err := NewPostgresDriver(ts.connectionString) if err != nil { return err } + + // defer cleanup() + ts.driver = driver return nil From f875d99b4d7936d51a69fe6ade4d2b20ec6751dc Mon Sep 17 00:00:00 2001 From: commoddity Date: Mon, 13 Nov 2023 17:40:52 +0000 Subject: [PATCH 2/3] feat: add NewCloudSQLPostgresDriver func --- go.mod | 14 ++ go.sum | 171 ++++++++++++++++++++++ postgres-driver/postgresdriver.go | 61 ++++++++ postgres-driver/query.sql.generated.go | 190 +++++++++++++++++++------ 4 files changed, 394 insertions(+), 42 deletions(-) diff --git a/go.mod b/go.mod index 906e071..55f1706 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/pokt-foundation/transaction-db go 1.20 require ( + cloud.google.com/go/cloudsqlconn v1.3.0 github.com/jackc/pgx/v5 v5.4.3 github.com/lib/pq v1.10.9 github.com/stretchr/testify v1.8.1 @@ -10,18 +11,31 @@ require ( ) require ( + cloud.google.com/go/compute v1.23.0 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/google/s2a-go v0.1.4 // indirect + github.com/google/uuid v1.3.1 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect + github.com/googleapis/gax-go/v2 v2.11.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.6.1 // indirect + go.opencensus.io v0.24.0 // indirect golang.org/x/crypto v0.14.0 // indirect golang.org/x/net v0.17.0 // indirect + golang.org/x/oauth2 v0.11.0 // indirect golang.org/x/sync v0.3.0 // indirect + golang.org/x/sys v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect + golang.org/x/time v0.3.0 // indirect + google.golang.org/api v0.126.0 // indirect + google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 869650b..a3247b7 100644 --- a/go.sum +++ b/go.sum @@ -1,16 +1,85 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go/cloudsqlconn v1.3.0 h1:xe9pIA9l5m6C6TasxV7WA3MXiZrRRuekFIe7hjEUK1k= +cloud.google.com/go/cloudsqlconn v1.3.0/go.mod h1:e35ypX+dsoYQ2JK5Tm6clrFTZieCljqezjC7oYjfl2w= +cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= +cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= +github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= +github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4= +github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= +github.com/jackc/pgconn v1.14.0 h1:vrbA9Ud87g6JdFWkHTJXppVce58qPIdP7N8y0Ml/A7Q= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3/v2 v2.3.2 h1:7eY55bdBeCz1F2fTzSz69QC+pG46jYq9/jtSPiJ5nn0= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw= +github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0= github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= @@ -23,33 +92,131 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/microsoft/go-mssqldb v1.1.0 h1:jsV+tpvcPTbNNKW0o3kiCD69kOHICsfjZ2VcVu2lKYc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= +golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.126.0 h1:q4GJq+cAdMAC7XP7njvQ4tvohGLiSlytuL4BQxbIZ+o= +google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= +google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q= google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c h1:jHkCUWkseRf+W+edG5hMzr/Uh1xkDREY4caybAq4dpY= google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= @@ -58,6 +225,10 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/postgres-driver/postgresdriver.go b/postgres-driver/postgresdriver.go index 3ffae97..09d48b5 100644 --- a/postgres-driver/postgresdriver.go +++ b/postgres-driver/postgresdriver.go @@ -2,11 +2,14 @@ package postgresdriver import ( "context" + "errors" "fmt" + "net" "time" // PQ import is required + "cloud.google.com/go/cloudsqlconn" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgxpool" @@ -31,10 +34,68 @@ type ( } ) +var ( + errCantSetPrivateandPublicIP error = errors.New("cannot set both private and public IP; must set one or the other") +) + /* ---------- Postgres Connection Funcs ---------- */ /* <--------- PGX Pool Connection ---------> */ +/* +NewCloudSQLPostgresDriver +- Creates a pool of connections to a Cloud SQL instance using the provided CloudSQLConfig. +- Uses the Cloud SQL Connector for Go and pgx for the connections. +- Establishes a dialer with the desired options (like using private IP). +- For each acquired connection from the pool, custom enum types are registered.. +- It is important to note that this function will return an error if both PublicIP and PrivateIP are provided in the CloudSQLConfig. +*/ +func NewCloudSQLPostgresDriver(options CloudSQLConfig) (*PostgresDriver, func() error, error) { + if options.PublicIP != "" && options.PrivateIP != "" { + return nil, nil, errCantSetPrivateandPublicIP + } + + dsn := fmt.Sprintf("user=%s password=%s dbname=%s", options.DBUser, options.DBPassword, options.DBName) + + config, err := pgxpool.ParseConfig(dsn) + if err != nil { + return nil, nil, err + } + + var opts []cloudsqlconn.Option + if options.PublicIP != "" { + opts = append(opts, cloudsqlconn.WithDefaultDialOptions(cloudsqlconn.WithPublicIP())) + } + if options.PrivateIP != "" { + opts = append(opts, cloudsqlconn.WithDefaultDialOptions(cloudsqlconn.WithPrivateIP())) + } + + d, err := cloudsqlconn.NewDialer(context.Background(), opts...) + if err != nil { + return nil, nil, err + } + + config.ConnConfig.DialFunc = func(ctx context.Context, _, _ string) (net.Conn, error) { + return d.Dial(ctx, options.InstanceConnectionName) + } + pool, err := createAndConfigurePool(config) + if err != nil { + return nil, nil, err + } + + cleanup := func() error { + pool.Close() + return d.Close() + } + + driver := &PostgresDriver{ + Queries: New(pool), + db: pool, + } + + return driver, cleanup, nil +} + /* NewPostgresDriver - Creates a pool of connections to a PostgreSQL database using the provided connection string. diff --git a/postgres-driver/query.sql.generated.go b/postgres-driver/query.sql.generated.go index 6b787c9..44e45b3 100644 --- a/postgres-driver/query.sql.generated.go +++ b/postgres-driver/query.sql.generated.go @@ -12,7 +12,13 @@ import ( ) const insertPocketSession = `-- name: InsertPocketSession :exec -INSERT INTO pocket_session (session_key, session_height, portal_region_name, created_at, updated_at) +INSERT INTO pocket_session ( + session_key, + session_height, + portal_region_name, + created_at, + updated_at + ) VALUES ($1, $2, $3, $4, $5) ` @@ -47,40 +53,71 @@ func (q *Queries) InsertPortalRegion(ctx context.Context, portalRegionName strin const insertRelay = `-- name: InsertRelay :exec INSERT INTO relay ( - pokt_chain_id, - endpoint_id, - session_key, - protocol_app_public_key, - relay_source_url, - pokt_node_address, - pokt_node_domain, - pokt_node_public_key, - relay_start_datetime, - relay_return_datetime, - is_error, - error_code, - error_name, - error_message, - error_source, - error_type, - relay_roundtrip_time, - relay_chain_method_ids, - relay_data_size, - relay_portal_trip_time, - relay_node_trip_time, - relay_url_is_public_endpoint, - portal_region_name, - is_altruist_relay, - is_user_relay, - request_id, - pokt_tx_id, - gigastake_app_id, - created_at, - updated_at, - blocking_plugin -) VALUES ( - $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31 -) + pokt_chain_id, + endpoint_id, + session_key, + protocol_app_public_key, + relay_source_url, + pokt_node_address, + pokt_node_domain, + pokt_node_public_key, + relay_start_datetime, + relay_return_datetime, + is_error, + error_code, + error_name, + error_message, + error_source, + error_type, + relay_roundtrip_time, + relay_chain_method_ids, + relay_data_size, + relay_portal_trip_time, + relay_node_trip_time, + relay_url_is_public_endpoint, + portal_region_name, + is_altruist_relay, + is_user_relay, + request_id, + pokt_tx_id, + gigastake_app_id, + created_at, + updated_at, + blocking_plugin + ) +VALUES ( + $1, + $2, + $3, + $4, + $5, + $6, + $7, + $8, + $9, + $10, + $11, + $12, + $13, + $14, + $15, + $16, + $17, + $18, + $19, + $20, + $21, + $22, + $23, + $24, + $25, + $26, + $27, + $28, + $29, + $30, + $31 + ) ` type InsertRelayParams struct { @@ -173,9 +210,26 @@ INSERT INTO service_record ( success_rate, created_at, updated_at -) VALUES ( - $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17 -) + ) +VALUES ( + $1, + $2, + $3, + $4, + $5, + $6, + $7, + $8, + $9, + $10, + $11, + $12, + $13, + $14, + $15, + $16, + $17 + ) ` type InsertServiceRecordParams struct { @@ -222,10 +276,45 @@ func (q *Queries) InsertServiceRecord(ctx context.Context, arg InsertServiceReco } const selectRelay = `-- name: SelectRelay :one -SELECT r.id, r.pokt_chain_id, r.endpoint_id, r.session_key, r.protocol_app_public_key, r.relay_source_url, r.pokt_node_address, r.pokt_node_domain, r.pokt_node_public_key, r.relay_start_datetime, r.relay_return_datetime, r.is_error, r.error_code, r.error_name, r.error_message, r.error_source, r.error_type, r.relay_roundtrip_time, r.relay_chain_method_ids, r.relay_data_size, r.relay_portal_trip_time, r.relay_node_trip_time, r.relay_url_is_public_endpoint, r.is_altruist_relay, r.is_user_relay, r.request_id, r.pokt_tx_id, r.gigastake_app_id, r.created_at, r.updated_at, r.blocking_plugin, ps.session_key, ps.session_height, ps.created_at, ps.updated_at, pr.portal_region_name +SELECT r.id, + r.pokt_chain_id, + r.endpoint_id, + r.session_key, + r.protocol_app_public_key, + r.relay_source_url, + r.pokt_node_address, + r.pokt_node_domain, + r.pokt_node_public_key, + r.relay_start_datetime, + r.relay_return_datetime, + r.is_error, + r.error_code, + r.error_name, + r.error_message, + r.error_source, + r.error_type, + r.relay_roundtrip_time, + r.relay_chain_method_ids, + r.relay_data_size, + r.relay_portal_trip_time, + r.relay_node_trip_time, + r.relay_url_is_public_endpoint, + r.is_altruist_relay, + r.is_user_relay, + r.request_id, + r.pokt_tx_id, + r.gigastake_app_id, + r.created_at, + r.updated_at, + r.blocking_plugin, + ps.session_key, + ps.session_height, + ps.created_at, + ps.updated_at, + pr.portal_region_name FROM relay r - INNER JOIN pocket_session ps ON ps.session_key = r.session_key - INNER JOIN portal_region pr ON pr.portal_region_name = r.portal_region_name + INNER JOIN pocket_session ps ON ps.session_key = r.session_key + INNER JOIN portal_region pr ON pr.portal_region_name = r.portal_region_name WHERE r.id = $1 ` @@ -313,7 +402,24 @@ func (q *Queries) SelectRelay(ctx context.Context, id int64) (SelectRelayRow, er } const selectServiceRecord = `-- name: SelectServiceRecord :one -SELECT id, node_public_key, pokt_chain_id, session_key, request_id, portal_region_name, latency, tickets, result, available, successes, failures, p90_success_latency, median_success_latency, weighted_success_latency, success_rate, created_at, updated_at +SELECT id, + node_public_key, + pokt_chain_id, + session_key, + request_id, + portal_region_name, + latency, + tickets, + result, + available, + successes, + failures, + p90_success_latency, + median_success_latency, + weighted_success_latency, + success_rate, + created_at, + updated_at FROM service_record WHERE id = $1 ` From 6f8c9db91b80aabf5610be2003f0fa49f2eca76f Mon Sep 17 00:00:00 2001 From: Pascal van Leeuwen <47662958+commoddity@users.noreply.github.com> Date: Wed, 15 Nov 2023 21:36:58 +0000 Subject: [PATCH 3/3] Update suite_test.go --- postgres-driver/suite_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/postgres-driver/suite_test.go b/postgres-driver/suite_test.go index 9bc27b3..788eb87 100644 --- a/postgres-driver/suite_test.go +++ b/postgres-driver/suite_test.go @@ -103,8 +103,6 @@ func (ts *PGDriverTestSuite) initPostgresDriver() error { return err } - // defer cleanup() - ts.driver = driver return nil