Database connection behaviour and database connection pool designed for
handling transaction, prepare/execute, cursors and client process
Examples of using the `DBConnection` behaviour are available in
`./examples/db_agent/` and `./examples/tcp_connection/`.
There is also [a series of articles on building database adapters](http://blog.plataformatec.com.br/2018/11/building-a-new-mysql-adapter-for-ecto-part-i-hello-world/). It includes articles covering both DBConnection and Ecto integrations.
Run unit tests with:
$ mix test
To run the integration tests (for each available pool):
$ mix test.pools
To run all tests:
$ mix test.all
This library is made of four main modules:
* `DBConnection` - this is the code running on the client
and the specification of the DBConnection API
* `DBConnection.Connection` - this is the process that
establishes the database connection
* `DBConnection.ConnectionPool` - this is the connection
pool. A client asks the connection pool for a connection.
There is also an ownership pool, used mostly during tests,
which we won't discuss here.
* `DBConnection.Holder` - the holder is responsible for
keeping the connection and checkout state. It is modelled
by using an ETS table.
Once a connection is created, it creates a holder and
assigns the connection pool as the heir. Then the holder
is promptly given away to the pool. The connection itself
is mostly a dummy. It is there to handle connections and pings.
The state itself (such as the socket) is all in the holder.
Once there is a checkout, the pool gives the holder to the
client process and stores all relevant information in the
holder table itself. If the client terminates without
checking in, then the holder is given back to the pool via
the heir mechanism. The pool will then discard the connection.
One important design detail in DBConnection is that it avoids
copying data. Other database libraries would send a request
to the connection process, perform the query in the connection
process, and then send it back to the client. This means a lot of
data copying in Elixir. DBConnection keeps the socket in the
holder and works on it directly.
DBConnection also takes all of the care necessary to handle
failures, and it shuts down the connection and the socket
whenever the client does not check in the connection to avoid
recycling sockets/connections in a corrupted state (such as a socket
that is stuck inside a transaction).
When a checkout happens, a deadline is started by the client
to send a message to the pool after a time interval. If the
deadline is reached and the connection is still checked out,
the holder is deleted and the connection is terminated. If the
client tries to use a terminated connection, an error will
be raised (see `Holder.handle/4`).
The queuing algorithm used by the pool is [CoDel](https://queue.acm.org/appendices/codel.html)
which allows us to plan for overloads and reject requests
without clogging the pool once checkouts do not read a certain
Copyright 2015 James Fish
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.