Skip to content
This repository has been archived by the owner on Apr 2, 2024. It is now read-only.

Fix connection leaks #190

Merged
merged 3 commits into from
Aug 13, 2020
Merged

Fix connection leaks #190

merged 3 commits into from
Aug 13, 2020

Conversation

JLockerman
Copy link
Contributor

@JLockerman JLockerman commented Aug 10, 2020

Keeping around a pgx.Rows is dangerous, as doing so keeps a lock on the underlying connection. This means that the connecter can self-starve if it gets partway through a Rows and decides it needs to fetch more data from the database. To fix this, this commit materializes all pgx.Rows into a []timescaleRow as soon as possible.

(Further, It looks like there's no guarantee that a SeriesSet will be read until the end anyway)

This commit also refactors the TestPGXQuerierQuery test, as updating the old version to the new code was too onerous, and batches multi-metrics queries together, as I was rewriting that code anyway. It seems to give a nice performance increase.


results = append(results, ts...)
}
results, err := buildTimeSeries(rows, q)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[golangci-lint-github-pr-review] reported by reviewdog 🐶
ineffectual assignment to err (ineffassign)

@@ -287,19 +279,20 @@ func (q *pgxQuerier) getResultRows(startTimestamp int64, endTimestamp int64, hin

sqlQuery := buildMetricNameSeriesIDQuery(cases)
rows, err := q.conn.Query(context.Background(), sqlQuery, values...)
defer rows.Close()

This comment was marked as resolved.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is wrong for this interface

@@ -342,6 +336,7 @@ func (q *pgxQuerier) querySingleMetric(metric string, filter metricTimeRangeFilt
return nil, nil, err
}
rows, err := q.conn.Query(context.Background(), sqlQuery, values...)
defer rows.Close()

This comment was marked as resolved.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is wrong for this interface

metrics, series, err := getSeriesPerMetric(rows)

if err != nil {
return nil, nil, err
}

results := make([]pgx.Rows, 0, len(metrics))
// TODO this assume on average on row per-metric. Is this right?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup.

@JLockerman
Copy link
Contributor Author

@antekresic I added a commit with more batching, would you re-review?


batchResults, err := q.conn.SendBatch(context.Background(), batch)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[golangci-lint-github-pr-review] reported by reviewdog 🐶
ineffectual assignment to err (ineffassign)


batchResults, err := q.conn.SendBatch(context.Background(), batch)
defer batchResults.Close()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[golangci-lint-github-pr-review] reported by reviewdog 🐶
SA5001: should check returned error before deferring batchResults.Close() (staticcheck)

The old test was difficult to read and update since the state of each
query was spread across multiple slices. This commit consolidates them
all into a single sqlQuery struct allowing us to determine the inputs
and outputs for each query at a glance. We also switch to a new mock
that works better with this format, and is able to report errors as
they occur.
Keeping around a pgx.Rows is dangerous, as doing so keeps a lock on the
underlying connection. This means that the connecter can self-starve if
it gets partway through a Rows and decides it needs to fetch more data
from the database. To fix this, this commit materializes all pgx.Rows
into a []timescaleRow as soon as possible.
This is a drive-by performance optimization: there's no need to send
each of these queries individually, we can batch them together and save
on multiple roundtrip times.
Copy link
Contributor

@davidkohn88 davidkohn88 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Glad we got to do the pair review, and glad we got the batching in as well. Can you remove the TODOs that look like they've been obviated by Ante's responses?

@JLockerman JLockerman merged commit cd76d85 into master Aug 13, 2020
@JLockerman JLockerman deleted the fix-connection-leak branch August 13, 2020 13:16
Copy link
Contributor

@cevian cevian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some issues with error checking

numQueries += 1
}

batchResults, err := q.conn.SendBatch(context.Background(), batch)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error return should be checked.


results = append(results, ts...)
}
results, err := buildTimeSeries(rows, q)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this err should be checked or returned.

log.Error("err", row.err)
return out
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need to check in.Err() here too.

This was referenced Aug 17, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants