-
Notifications
You must be signed in to change notification settings - Fork 15
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
Conversation
74e2629
to
9c02151
Compare
* 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) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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") |
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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 usespgxpool.ParseConfig()
for creating apgxpool.Config
object from a DSN-style connection string (which is using thepool_max_conns
parameter to configure the maximum pool size), and then uses thecreatePool()
application primitive to create apgxpool.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 theMaxConnections
setting manually. Then, it usesnewCrateEndpoint()
to create an Endpoint object, and invokes theendpoint.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 theMaxConnections
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.
There was a problem hiding this 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.
/** | ||
* Verify that the pool size gets obtained from the database connection string. | ||
**/ | ||
poolConf, _ := pgxpool.ParseConfig("postgres://crate:foo@localhost:5432/?pool_max_conns=42") |
There was a problem hiding this comment.
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 usespgxpool.ParseConfig()
for creating apgxpool.Config
object from a DSN-style connection string (which is using thepool_max_conns
parameter to configure the maximum pool size), and then uses thecreatePool()
application primitive to create apgxpool.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 theMaxConnections
setting manually. Then, it usesnewCrateEndpoint()
to create an Endpoint object, and invokes theendpoint.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 theMaxConnections
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.
9c02151
to
082736b
Compare
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) { |
There was a problem hiding this comment.
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.
b334534
to
30fb216
Compare
082736b
to
b8f4119
Compare
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.