-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
`read-replica` had poor documentation. It was hard to understand it on a high level. I hope it's enough to lower the barrier of entry for the libraries consumers and for the libraries contributors. I skipped details about `ReplicaConsistency` as it's currently under development and will probably change soon.
- Loading branch information
Showing
12 changed files
with
154 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
## Classes diagram | ||
|
||
This diagram is intended to help understand how the library works internally. It may leak some implementation details and should not be used as API. | ||
|
||
 | ||
|
||
`DualConnection#Builder` creates [DualConnection](../src/main/java/com/atlassian/db/replica/api/DualConnection.java). | ||
[CircuitBreaker](../src/main/java/com/atlassian/db/replica/spi/circuitbreaker/CircuitBreaker.java) | ||
if [DualConnection](../src/main/java/com/atlassian/db/replica/api/DualConnection.java) can be created. | ||
Every call that goes to the database directly through the connection or through | ||
one of the `java.sql.Statement` implementations can be intercepted with | ||
[DualCall](../src/main/java/com/atlassian/db/replica/spi/DualCall.java). | ||
|
||
[ConnectionState](../src/main/java/com/atlassian/db/replica/internal/state/ConnectionState.java) is an internal class | ||
that is the source of truth to the current [State](../src/main/java/com/atlassian/db/replica/api/state/State.java). | ||
It can use [ConnectionProvider](../src/main/java/com/atlassian/db/replica/spi/ConnectionProvider.java) | ||
to obtain a connection to a database. It utilises | ||
[ReplicaConsistency](../src/main/java/com/atlassian/db/replica/spi/ReplicaConsistency.java) while transitioning | ||
between states. [StateListener](../src/main/java/com/atlassian/db/replica/spi/state/StateListener.java) is called on each transition. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
@startuml | ||
class "DualConnection#Builder" as builder | ||
builder : Connection build() | ||
|
||
class DualConnection | ||
interface ReplicaConsistency | ||
interface ConnectionProvider | ||
interface DualCall | ||
interface StateListener | ||
interface CircuitBreaker | ||
class ConnectionState | ||
class State | ||
|
||
interface Statement | ||
interface PreparedStatement | ||
interface CallableStatement | ||
interface Connection | ||
|
||
|
||
builder::build --> DualConnection : create | ||
|
||
|
||
DualConnection --|> Connection | ||
PreparedStatement --|> Statement | ||
CallableStatement --|> Statement | ||
|
||
|
||
ConnectionState *-- ReplicaConsistency | ||
ConnectionState *-- ConnectionProvider | ||
ConnectionState *-- StateListener | ||
ConnectionState *-- Connection | ||
ConnectionState *-- State | ||
|
||
DualConnection *-- DualCall | ||
DualConnection *-- Statement | ||
builder *-- CircuitBreaker | ||
DualConnection *-- ConnectionState | ||
|
||
|
||
|
||
|
||
@enduml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
## Consistency | ||
|
||
[DualConnection](../src/main/java/com/atlassian/db/replica/api/DualConnection.java) consistency is controlled by | ||
[com.atlassian.db.replica.spi.ReplicaConsistency](../src/main/java/com/atlassian/db/replica/spi/ReplicaConsistency.java). | ||
|
||
Currently, there's no default consistency implementation. Consistency model highly depends on the database and | ||
application's needs. There's one example of the implementation for Postgres available in | ||
[the integration test](../src/test/java/com/atlassian/db/replica/it/DualConnectionIT.java). | ||
|
||
The easiest way to start is to use | ||
[PessimisticPropagationConsistency](../src/main/java/com/atlassian/db/replica/api/PessimisticPropagationConsistency.java). | ||
|
||
 | ||
|
||
Every write operation is registered by `ReplicaConsistency#write` method. | ||
[DualConnection](../src/main/java/com/atlassian/db/replica/api/DualConnection.java) verifies | ||
the state of replica's consistency by calling `ReplicaConsistency#isConsistent` method. | ||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
@startuml | ||
|
||
@startuml | ||
|
||
class DualConnection | ||
|
||
interface ReplicaConsistency{ | ||
void write(Connection main) | ||
boolean isConsistent(Supplier<Connection> replica) | ||
} | ||
|
||
DualConnection *-- ReplicaConsistency | ||
DualConnection --> ReplicaConsistency::write : db write operation | ||
|
||
DualConnection --> ReplicaConsistency::isConsistent : validate consistency for db read operation | ||
|
||
|
||
@enduml | ||
|
||
|
||
@enduml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
## Configurable main/replica split instrumentation | ||
|
||
All calls to the database goes through [DualCall](../src/main/java/com/atlassian/db/replica/spi/DualCall.java). | ||
By default [DualConnection](../src/main/java/com/atlassian/db/replica/api/DualConnection.java) forwards all the calls. | ||
It can be used to log queries, gather metrics or to handle exceptions. | ||
|
||
 | ||
|
||
Every database operation on replica will go through `DualCall#callReplica`. | ||
Every call to the main database will go through `DualCall#callMain` method. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
@startuml | ||
|
||
@startuml | ||
|
||
class DualConnection | ||
|
||
interface DualCall{ | ||
<T> T callReplica(final SqlCall<T> call) | ||
<T> T callMain(final SqlCall<T> call) | ||
} | ||
|
||
DualConnection *-- DualCall | ||
DualConnection --> DualCall::callReplica : db operation in ReplicaConnection state | ||
DualConnection --> DualCall::callMain : db operatin in MainConnection state | ||
|
||
|
||
@enduml | ||
|
||
|
||
@enduml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
## How DualConnection chooses between main and replica? | ||
|
||
[DualConnection](../src/main/java/com/atlassian/db/replica/api/DualConnection.java) takes multiple aspects while deciding | ||
which connection to use: | ||
|
||
1. A [connection's state](dual-connection-states.md). | ||
2. A replica's [consistency](../src/main/java/com/atlassian/db/replica/spi/ReplicaConsistency.java). | ||
3. Context of `java.sql.Connection`/`java.sql.Statement` API usage. | ||
|
||
Some of the methods are intended to write into the database. For example every call to `java.sq.PreparedStatement#executeUpdate` | ||
will switch the connection's state to the main database. | ||
|
||
4. Availability of replica | ||
5. The query will use the main database in case it's: | ||
- `SELECT FOR UPDATE` statement. | ||
- `UPDATE` statement. | ||
- `DELETE` statement. | ||
- an SQL function call. | ||
- All calls with transaction isolation level higher than `TRANSACTION_READ_COMMITTED`. |