feat(storage): read only transactions (#6417)

feat(storage): read only transactions for queries (#6415)

* fix: tests

* bastle wie en grosse

* fix(database): scan as callback

* fix tests

* fix merge failures

* remove as of system time

* refactor: remove unused test

* refacotr: remove unused lines
This commit is contained in:
Silvan
2023-08-22 14:49:02 +02:00
committed by GitHub
parent 7442492b8a
commit 22af4dcd97
128 changed files with 1355 additions and 897 deletions

View File

@@ -11,6 +11,7 @@ import (
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/api/call"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/database/dialect"
z_errors "github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/eventstore/repository"
@@ -24,13 +25,33 @@ type querier interface {
eventQuery() string
maxSequenceQuery() string
instanceIDsQuery() string
db() *sql.DB
db() *database.DB
orderByEventSequence(desc bool) string
dialect.Database
}
type scan func(dest ...interface{}) error
type tx struct {
*sql.Tx
}
func (t *tx) QueryContext(ctx context.Context, scan func(rows *sql.Rows) error, query string, args ...any) error {
rows, err := t.Tx.QueryContext(ctx, query, args...)
if err != nil {
return err
}
defer func() {
closeErr := rows.Close()
logging.OnError(closeErr).Info("rows.Close failed")
}()
if err = scan(rows); err != nil {
return err
}
return rows.Err()
}
func query(ctx context.Context, criteria querier, searchQuery *repository.SearchQuery, dest interface{}) error {
query, rowScanner := prepareColumns(criteria, searchQuery.Columns)
where, values := prepareCondition(criteria, searchQuery.Filters)
@@ -56,26 +77,27 @@ func query(ctx context.Context, criteria querier, searchQuery *repository.Search
query = criteria.placeholder(query)
var contextQuerier interface {
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
QueryContext(context.Context, func(rows *sql.Rows) error, string, ...interface{}) error
}
contextQuerier = criteria.db()
if searchQuery.Tx != nil {
contextQuerier = searchQuery.Tx
contextQuerier = &tx{Tx: searchQuery.Tx}
}
rows, err := contextQuerier.QueryContext(ctx, query, values...)
err := contextQuerier.QueryContext(ctx,
func(rows *sql.Rows) error {
for rows.Next() {
err := rowScanner(rows.Scan, dest)
if err != nil {
return err
}
}
return nil
}, query, values...)
if err != nil {
logging.New().WithError(err).Info("query failed")
return z_errors.ThrowInternal(err, "SQL-KyeAx", "unable to filter events")
}
defer rows.Close()
for rows.Next() {
err = rowScanner(rows.Scan, dest)
if err != nil {
return err
}
}
return nil
}