Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Janitor optimization use requested at index #3115

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/testhelpers/janitor_test_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ func JanitorTests(conf *config.Provider, consentManager consent.Manager, clientM

// cleanup
t.Run("step=cleanup", func(t *testing.T) {
require.NoError(t, fositeManager.FlushInactiveLoginConsentRequests(ctx, time.Now().Round(time.Second), 2, 1))
require.NoError(t, fositeManager.FlushInactiveLoginConsentRequests(ctx, time.Now().Round(time.Second), 4, 1))
})

// validate
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
DROP INDEX hydra_oauth2_refresh_requested_at_idx;
DROP INDEX hydra_oauth2_authentication_request_requested_at_idx;
DROP INDEX hydra_oauth2_consent_request_requested_at_idx;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CREATE INDEX hydra_oauth2_refresh_requested_at_idx ON hydra_oauth2_refresh (requested_at);
CREATE INDEX hydra_oauth2_authentication_request_requested_at_idx ON hydra_oauth2_authentication_request (requested_at);
CREATE INDEX hydra_oauth2_consent_request_requested_at_idx ON hydra_oauth2_consent_request (requested_at);
27 changes: 14 additions & 13 deletions persistence/sql/persister_consent.go
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,8 @@ func (p *Persister) FlushInactiveLoginConsentRequests(ctx context.Context, notAf
notAfter = requestMaxExpire
}

challenges := []string{}
consent_challenges := []string{}
// Order by requested_at field to avoid full scan and use requested_at index
queryFormat := `
SELECT %[1]s.challenge
FROM %[1]s
Expand All @@ -464,7 +465,7 @@ func (p *Persister) FlushInactiveLoginConsentRequests(ctx context.Context, notAf
OR (%[2]s.error IS NOT NULL AND %[2]s.error <> '{}' AND %[2]s.error <> '')
)
AND %[1]s.requested_at < ?
ORDER BY %[1]s.challenge
ORDER BY %[1]s.requested_at
LIMIT %[3]d
`

Expand All @@ -476,21 +477,21 @@ func (p *Persister) FlushInactiveLoginConsentRequests(ctx context.Context, notAf
// - hydra_oauth2_consent_request.requested_at < minimum between ttl.login_consent_request and notAfter
q := p.Connection(ctx).RawQuery(fmt.Sprintf(queryFormat, (&cr).TableName(), (&crh).TableName(), limit), notAfter)

if err := q.All(&challenges); err == sql.ErrNoRows {
if err := q.All(&consent_challenges); err == sql.ErrNoRows {
return errors.Wrap(fosite.ErrNotFound, "")
}

// Delete in batch consent requests and their references in cascade
for i := 0; i < len(challenges); i += batchSize {
for i := 0; i < len(consent_challenges); i += batchSize {
j := i + batchSize
if j > len(challenges) {
j = len(challenges)
if j > len(consent_challenges) {
j = len(consent_challenges)
}

if i != j {
q := p.Connection(ctx).RawQuery(
fmt.Sprintf("DELETE FROM %s WHERE challenge in (?)", (&cr).TableName()),
challenges[i:j],
consent_challenges[i:j],
)

if err := q.Exec(); err != nil {
Expand All @@ -499,6 +500,7 @@ func (p *Persister) FlushInactiveLoginConsentRequests(ctx context.Context, notAf
}
}

login_challenges := []string{}
// Select challenges from all authentication requests that can be safely deleted with limit
// where hydra_oauth2_authentication_request were unhandled or rejected, so either of these is true
// - hydra_oauth2_authentication_request_handled does not exist (unhandled)
Expand All @@ -507,21 +509,20 @@ func (p *Persister) FlushInactiveLoginConsentRequests(ctx context.Context, notAf
// - hydra_oauth2_authentication_request.requested_at < minimum between ttl.login_consent_request and notAfter
q = p.Connection(ctx).RawQuery(fmt.Sprintf(queryFormat, (&lr).TableName(), (&lrh).TableName(), limit), notAfter)

if err := q.All(&challenges); err == sql.ErrNoRows {
if err := q.All(&login_challenges); err == sql.ErrNoRows {
return errors.Wrap(fosite.ErrNotFound, "")
}

// Delete in batch authentication requests
for i := 0; i < len(challenges); i += batchSize {
for i := 0; i < len(login_challenges); i += batchSize {
j := i + batchSize
if j > len(challenges) {
j = len(challenges)
if j > len(login_challenges) {
j = len(login_challenges)
}

if i != j {
q := p.Connection(ctx).RawQuery(
fmt.Sprintf("DELETE FROM %s WHERE challenge in (?)", (&lr).TableName()),
challenges[i:j],
login_challenges[i:j],
)

if err := q.Exec(); err != nil {
Expand Down
3 changes: 2 additions & 1 deletion persistence/sql/persister_oauth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,9 @@ func (p *Persister) flushInactiveTokens(ctx context.Context, notAfter time.Time,
signatures := []string{}

// Select tokens' signatures with limit
// Order by requested_at field to avoid full scan and use requested_at index
q := p.Connection(ctx).RawQuery(
fmt.Sprintf("SELECT signature FROM %s WHERE requested_at < ? ORDER BY signature LIMIT %d",
fmt.Sprintf("SELECT signature FROM %s WHERE requested_at < ? ORDER BY requested_at LIMIT %d",
OAuth2RequestSQL{Table: table}.TableName(), limit),
notAfter,
)
Expand Down