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

Use a different connection pool for read vs. write operations #81

Merged
merged 1 commit into from Sep 1, 2023

Conversation

amotl
Copy link
Member

@amotl amotl commented Aug 31, 2023

About

At #72 (comment), there is an item about using two different connection pools for read vs. write operations. In this way, excessive/overuse of one communication channel will not impact the other, and different usage characteristics can be tuned individually.

@amotl amotl marked this pull request as ready for review August 31, 2023 20:19
* Initialize two connection pools, one for read/write each. Do it lazily / on-demand,
* so that the adapter does not crash on startup if an endpoint is unavailable.
**/
c.readPool, err = createPoolWithPoolSize(ctx, c.poolConf.Copy(), c.readPoolSize)
Copy link
Member

Choose a reason for hiding this comment

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

Is this by mistake? looks like this is not needed and breaks the laziness?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks. I think the comment got misplaced, so it is indeed confusing. I just fixed it, and added more details at #81 (review) about it. Please let me know if you still think I am missing something.

/**
* Verify that the pool size gets obtained from the database connection string.
**/
poolConf, _ := pgxpool.ParseConfig("postgres://crate:foo@localhost:5432/?pool_max_conns=42")
Copy link
Member

Choose a reason for hiding this comment

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

Is this really testing our code and not pgx one's as our code will generate this connection string by given setting maxConnections?
Afaik TestPoolsWithMaxConnections is the related test, what value does this test add over TestPoolsWithMaxConnections?

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree that both functions test similar conditions, but still there are differences.

  • TestConfigurePoolWithPoolSizeFromConnectionString directly uses pgxpool.ParseConfig() for creating a pgxpool.Config object from a DSN-style connection string (which is using the pool_max_conns parameter to configure the maximum pool size), and then uses the createPool() application primitive to create a pgxpool.Pool object. That's a bare-bones test case.
  • TestPoolsWithMaxConnections on the other hand creates an application configuration object, in this case the "builtin" exemplar, and adjusts the MaxConnections setting manually. Then, it uses newCrateEndpoint() to create an Endpoint object, and invokes the endpoint.createPools() method on it, in order to run the full setup of creating both read+write pools. At the end, it verifies that both pool sizes derive their values from the MaxConnections configuration setting. That's a bit of a more integrated test case than the other one.

In order to add a few more thoughts here, which may help to understand my nitpickyness on test cases here: I am planning to abandon the configuration style of suppyling individual settings for Host, Port, etc. completely, and just use the connecting-string-style way, similar to pgx and libpq.

There are so many details in the parsing routines there, like recently added capabilities to describe and parse multiple host names and such, there is no way to emulate all of it in any different way. So, the best path forward, also reducing maintenance a lot, is to give users full power by just using a single connection string value as configuration setting.

While working on this, I will be happy to have different kinds of test cases around, which offer different perspectives to the parameter juggling and its upcoming changes.

Copy link
Member Author

@amotl amotl left a comment

Choose a reason for hiding this comment

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

Thanks for the review. I found another two spots to improve, and responded to your questions.

README.rst Outdated Show resolved Hide resolved
README.rst Outdated Show resolved Hide resolved
/**
* Verify that the pool size gets obtained from the database connection string.
**/
poolConf, _ := pgxpool.ParseConfig("postgres://crate:foo@localhost:5432/?pool_max_conns=42")
Copy link
Member Author

Choose a reason for hiding this comment

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

I agree that both functions test similar conditions, but still there are differences.

  • TestConfigurePoolWithPoolSizeFromConnectionString directly uses pgxpool.ParseConfig() for creating a pgxpool.Config object from a DSN-style connection string (which is using the pool_max_conns parameter to configure the maximum pool size), and then uses the createPool() application primitive to create a pgxpool.Pool object. That's a bare-bones test case.
  • TestPoolsWithMaxConnections on the other hand creates an application configuration object, in this case the "builtin" exemplar, and adjusts the MaxConnections setting manually. Then, it uses newCrateEndpoint() to create an Endpoint object, and invokes the endpoint.createPools() method on it, in order to run the full setup of creating both read+write pools. At the end, it verifies that both pool sizes derive their values from the MaxConnections configuration setting. That's a bit of a more integrated test case than the other one.

In order to add a few more thoughts here, which may help to understand my nitpickyness on test cases here: I am planning to abandon the configuration style of suppyling individual settings for Host, Port, etc. completely, and just use the connecting-string-style way, similar to pgx and libpq.

There are so many details in the parsing routines there, like recently added capabilities to describe and parse multiple host names and such, there is no way to emulate all of it in any different way. So, the best path forward, also reducing maintenance a lot, is to give users full power by just using a single connection string value as configuration setting.

While working on this, I will be happy to have different kinds of test cases around, which offer different perspectives to the parameter juggling and its upcoming changes.

Comment on lines 109 to 114
func (c *crateEndpoint) endpoint() endpoint.Endpoint {
/**
* Initialize connection pools lazily here instead of in `newCrateEndpoint()`,
* so that the adapter does not crash on startup if the endpoint is unavailable.
**/
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Added the comment about lazy initialization back here, to the spot where it was coming from. The delayed intialization seems to be implemented by returning a function closure here, that detail did not change.

The pool creation has just been refactored into the createPools() method, and this one is still called from within the function closure.

@amotl amotl requested a review from seut September 1, 2023 10:57
@amotl amotl force-pushed the amo/read-write-timeout branch 2 times, most recently from b334534 to 30fb216 Compare September 1, 2023 19:30
Base automatically changed from amo/read-write-timeout to main September 1, 2023 19:32
@amotl amotl merged commit bf17316 into main Sep 1, 2023
6 checks passed
@amotl amotl deleted the amo/read-write-pools branch September 1, 2023 19:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants