Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Adding Lucky to TechEmpower benchmarks showed us that we were hitting Postgres' connection limit. The pool limit we set for our app was 56 per connection. Starting 10 instances of the app should have only opened up 560 connections, but we started hitting the postgres configuration's 2000 connection limit! Adding in some puts debugging showed that this
Avram::Database#db
method was getting called and going past the memoized value more than we were expecting. The theory is that an instance of the app was handling requests so fast that another request tried to get a database connection before the previous one had fully opened one and set the class variable. The load test was going so fast that it was sending a ton of requests into this situation, thus hitting the connection limit.By adding a mutex lock around it, we make sure that situation doesn't happen by forcing only one thread (request) to be able to open a connection at a time. We do the class variable check inside the mutex because requests could be queued up at the mutex having already checked the class variable while it was getting opened.
I don't expect many apps to have experienced issues with this as the app has to have experienced heavy load before the db variable was set but this was definitely a bug. Maybe there is a better way to solve it?
Are other ORM's affected by this?
Granite - doesn't seem to be as they require registering a connection in the app start process https://docs.amberframework.org/granite/docs/docs#register-a-connection
Crecto - they memoize the connection and lazily call it exactly as we do. https://github.com/Crecto/crecto/blob/master/src/crecto/repo/config.cr
Jennifer.cr - also memoizes https://github.com/imdrasil/jennifer.cr/blob/22bbaa466856594ef601589faae25320c8aa3f20/src/jennifer/adapter/base.cr#L39