Skip to content

Commit 490e511

Browse files
authored
chore: update documentation and minor bug fixes (#532)
1 parent 56ee470 commit 490e511

File tree

15 files changed

+187
-105
lines changed

15 files changed

+187
-105
lines changed

.github/workflows/draft_release.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,5 @@ jobs:
6464
draft: true
6565
name: "AWS Advanced Python Wrapper - v${{ env.RELEASE_VERSION }}"
6666
bodyFile: RELEASE_DETAILS.md
67+
artifacts: ./dist/*
6768
token: ${{ secrets.GITHUB_TOKEN }}

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## [1.0.0] - 2023-10-xx
1+
## [1.0.0] - 2024-05-16
22
The Amazon Web Services (AWS) Advanced Python Wrapper allows an application to take advantage of the features of clustered Aurora databases.
33

44
### :magic_wand: Added

Maintenance.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Release Schedule
2+
3+
| Release Date | Release |
4+
|--------------|--------------------------------------------------------------------------------------------|
5+
| May 16, 2024 | [Release 1.0.0](https://github.com/awslabs/aws-advanced-python-wrapper/releases/tag/1.0.0) |
6+
7+
`aws-advanced-python-wrapper` [follows semver](https://semver.org/#semantic-versioning-200) which means we will only
8+
release breaking changes in major versions. Generally speaking patches will be released to fix existing problems without
9+
adding new features. Minor version releases will include new features as well as fixes to existing features. We will do
10+
our best to deprecate existing features before removing them completely.
11+
12+
For minor version releases, `aws-advanced-python-wrapper` uses a “release-train” model. Approximately every four weeks we
13+
release a new minor version which includes all the new features and fixes that are ready to go.
14+
Having a set release schedule makes sure `aws-advanced-python-wrapper` is released in a predictable way and prevents a
15+
backlog of unreleased changes.
16+
17+
In contrast, `aws-advanced-python-wrapper` releases new major versions only when there are a critical mass of
18+
breaking changes (e.g. changes that are incompatible with existing APIs). This tends to happen if we need to
19+
change the way the driver is currently working. Fortunately, the JDBC API is fairly mature and has not changed, however
20+
in the event that the API changes we will release a version to be compatible.
21+
22+
Please note: Both the roadmap and the release dates reflect intentions rather than firm commitments and may change
23+
as we learn more or encounter unexpected issues. If dates do need to change, we will be as transparent as possible,
24+
and log all changes in the changelog at the bottom of this page.
25+
26+
# Maintenance Policy
27+
28+
For `aws-advanced-python-wrapper` new features and active development always takes place against the newest version.
29+
The `aws-advanced-python-wrapper` project follows the semantic versioning specification for assigning version numbers
30+
to releases, so you should be able to upgrade to the latest minor version of that same major version of the
31+
software without encountering incompatible changes (e.g., 1.1.0 → 1.3.x).
32+
33+
Sometimes an incompatible change is unavoidable. When this happens, the software’s maintainers will increment
34+
the major version number (e.g., increment from `aws-advanced-python-wrapper` 1.1.1 to `aws-advanced-python-wrapper` 2.0.0).
35+
The last minor version of the previous major version of the software will then enter a maintenance window
36+
(e.g., 1.3.x). During the maintenance window, the software will continue to receive bug fixes and security patches,
37+
but no new features.
38+
39+
We follow OpenSSF’s best practices for patching publicly known vulnerabilities, and we make sure that there are
40+
no unpatched vulnerabilities of medium or higher severity that have been publicly known for more than 60 days
41+
in our actively maintained versions.
42+
43+
The duration of the maintenance window will vary from product to product and release to release.
44+
By default, versions will remain under maintenance until the next major version enters maintenance,
45+
or 1-year passes, whichever is longer. Therefore, at any given time, the current major version and
46+
previous major version will both be supported, as well as older major versions that have been in maintenance
47+
for less than 12 months. Please note that maintenance windows are influenced by the support schedules for
48+
dependencies the software includes, community input, the scope of the changes introduced by the new version,
49+
and estimates for the effort required to continue maintenance of the previous version.
50+
51+
The software maintainers will not back-port fixes or features to versions outside the maintenance window.
52+
That said, PRs with said back-ports are welcome and will follow the project's review process.
53+
No new releases will result from these changes, but interested parties can create their own distribution
54+
from the updated source after the PRs are merged.
55+
56+
| Major Version | Latest Minor Version | Status | Initial Release | Maintenance Window Start | Maintenance Window End |
57+
|---------------|----------------------|---------|-----------------|--------------------------|------------------------|
58+
| 1 | 1.0.0 | Current | May 16, 2024 | May 16, 2024 | N/A |

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -211,12 +211,12 @@ The `aws-advanced-python-wrapper` has a regular monthly release cadence. A new r
211211

212212
This `aws-advanced-python-wrapper` is being tested against the following Community and Aurora database versions in our test suite:
213213

214-
| Database | Versions |
215-
|-------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
216-
| MySQL | 8.3.0 |
217-
| PostgreSQL | 15.2 |
218-
| Aurora MySQL | MySQL 8.0.mysql_aurora.3.02.2 (Wire-compatible with MySQL 8.0.23 onward. For more details see [here](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraMySQLReleaseNotes/AuroraMySQL.Updates.3022.html)) |
219-
| Aurora PostgreSQL | 14.7 and 15.2 (Compatible with PostgreSQL 14.7 and 15.2, see release notes [here](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraPostgreSQLReleaseNotes/AuroraPostgreSQL.Updates.html)) |
214+
| Database | Versions |
215+
|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
216+
| MySQL | 8.3.0 |
217+
| PostgreSQL | 16.2 |
218+
| Aurora MySQL | - LTS version, see [here](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Updates.Versions.html#AuroraMySQL.Updates.LTS) for more details. <br><br> - Latest release, as shown on [this page](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraMySQLReleaseNotes/AuroraMySQL.Updates.30Updates.html). |
219+
| Aurora PostgreSQL | - LTS version, see [here](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.Updates.LTS.html) for more details. <br><br> - Latest release, as shown on [this page](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraPostgreSQLReleaseNotes/AuroraPostgreSQL.Updates.html).) |
220220

221221
The `aws-advanced-python-wrapper` is compatible with MySQL 5.7 and MySQL 8.0 as per MySQL Connector/Python.
222222

aws_advanced_python_wrapper/driver_info.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
import os
16-
from pathlib import Path
17-
18-
import toml
19-
20-
PROJECT_DIR = Path(__file__).parent.parent
21-
PYPROJECT = toml.load(os.path.join(PROJECT_DIR, "pyproject.toml"))
22-
2315

2416
class DriverInfo:
25-
DRIVER_NAME = PYPROJECT["tool"]["poetry"]["description"]
26-
DRIVER_VERSION = PYPROJECT["tool"]["poetry"]["version"]
17+
DRIVER_NAME = "aws_advanced_python_wrapper"
18+
DRIVER_VERSION = "1.0.0-rc"

aws_advanced_python_wrapper/host_monitoring_plugin.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -638,9 +638,15 @@ def release_monitor(self, monitor: Monitor):
638638
self._monitor_map.remove_matching_values([monitor])
639639
self._tasks_map.compute_if_present(monitor, MonitoringThreadContainer._cancel)
640640

641-
# This method is only used for cleanup during testing
642641
@staticmethod
643-
def release_instance():
642+
def clean_up():
643+
"""Clean up any dangling monitoring threads created by the host monitoring plugin.
644+
This method should be called at the end of the application.
645+
The Host Monitoring Plugin creates monitoring threads in the background to monitor all connections established to each of cluster instances.
646+
The threads will terminate if there are no connections to the cluster instance the thread is monitoring for over a period of time,
647+
specified by the `monitor_disposal_time_ms`. Client applications can also manually call this method to clean up any dangling resources.
648+
This method should be called right before application termination.
649+
"""
644650
if MonitoringThreadContainer._instance is None:
645651
return
646652

@@ -649,7 +655,6 @@ def release_instance():
649655
MonitoringThreadContainer._instance._release_resources()
650656
MonitoringThreadContainer._instance = None
651657

652-
# This method is only used for cleanup during testing
653658
def _release_resources(self):
654659
with self._monitor_lock:
655660
self._monitor_map.clear()
@@ -662,7 +667,9 @@ def _release_resources(self):
662667

663668
self._tasks_map.clear()
664669

670+
# Reset the executor.
665671
self._executor.shutdown(wait=False)
672+
MonitoringThreadContainer._executor = ThreadPoolExecutor(thread_name_prefix="MonitoringThreadContainerExecutor")
666673

667674

668675
class MonitorService:

aws_advanced_python_wrapper/utils/pg_exception_handler.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,13 @@ def is_network_exception(self, error: Optional[Exception] = None, sql_state: Opt
3535
if isinstance(error, QueryTimeoutError) or isinstance(error, ConnectionTimeout):
3636
return True
3737
if sql_state is None:
38-
error_sql_state = getattr(error, "sqlstate")
39-
if error_sql_state is not None:
40-
sql_state = error_sql_state
38+
try:
39+
error_sql_state = getattr(error, "sqlstate")
40+
if error_sql_state is not None:
41+
sql_state = error_sql_state
42+
except AttributeError:
43+
# getattr may throw an AttributeError if the error does not have a `sqlstate` attribute
44+
pass
4145

4246
if sql_state is not None and sql_state in self._NETWORK_ERRORS:
4347
return True

docs/examples/PGFailover.py

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818

1919
import psycopg
2020

21+
from aws_advanced_python_wrapper.host_monitoring_plugin import \
22+
MonitoringThreadContainer
23+
2124
if TYPE_CHECKING:
2225
from aws_advanced_python_wrapper.pep249 import Connection
2326

@@ -61,27 +64,37 @@ def execute_queries_with_failover_handling(conn: Connection, sql: str, params: O
6164

6265

6366
if __name__ == "__main__":
67+
props = {
68+
"monitoring-connect_timeout": 10,
69+
"monitoring-socket_timeout": 10
70+
}
71+
6472
with AwsWrapperConnection.connect(
6573
psycopg.Connection.connect,
6674
host="database.cluster-xyz.us-east-1.rds.amazonaws.com",
6775
dbname="postgres",
6876
user="john",
6977
password="pwd",
70-
plugins="failover",
71-
wrapper_dialect="aurora-pg",
78+
plugins="failover,host_monitoring",
79+
connect_timeout=30,
80+
socket_timeout=30,
7281
autocommit=True
7382
) as awsconn:
74-
configure_initial_session_states(awsconn)
75-
execute_queries_with_failover_handling(
76-
awsconn, "CREATE TABLE IF NOT EXISTS bank_test (id int primary key, name varchar(40), account_balance int)")
77-
execute_queries_with_failover_handling(
78-
awsconn, "INSERT INTO bank_test VALUES (%s, %s, %s)", (0, "Jane Doe", 200))
79-
execute_queries_with_failover_handling(
80-
awsconn, "INSERT INTO bank_test VALUES (%s, %s, %s)", (1, "John Smith", 200))
81-
82-
cursor = execute_queries_with_failover_handling(awsconn, "SELECT * FROM bank_test")
83-
res = cursor.fetchall()
84-
for record in res:
85-
print(record)
86-
87-
execute_queries_with_failover_handling(awsconn, "DROP TABLE bank_test")
83+
try:
84+
configure_initial_session_states(awsconn)
85+
execute_queries_with_failover_handling(
86+
awsconn, "CREATE TABLE IF NOT EXISTS bank_test (id int primary key, name varchar(40), account_balance int)")
87+
execute_queries_with_failover_handling(
88+
awsconn, "INSERT INTO bank_test VALUES (%s, %s, %s)", (0, "Jane Doe", 200))
89+
execute_queries_with_failover_handling(
90+
awsconn, "INSERT INTO bank_test VALUES (%s, %s, %s)", (1, "John Smith", 200))
91+
92+
cursor = execute_queries_with_failover_handling(awsconn, "SELECT * FROM bank_test")
93+
res = cursor.fetchall()
94+
for record in res:
95+
print(record)
96+
97+
execute_queries_with_failover_handling(awsconn, "DROP TABLE bank_test")
98+
finally:
99+
# Clean up any remaining resources created by the Host Monitoring Plugin.
100+
MonitoringThreadContainer.clean_up()

docs/using-the-python-driver/using-plugins/UsingTheHostMonitoringPlugin.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ One use case is to pair EFM with the [Failover Connection Plugin](./UsingTheFail
1616

1717
The Host Monitoring Connection Plugin will be loaded by default if the [`plugins`](../UsingThePythonDriver.md#connection-plugin-manager-parameters) parameter is not specified. The Host Monitoring Connection Plugin can also be explicitly loaded by adding the plugin code `host_monitoring` to the [`plugins`](../UsingThePythonDriver.md#aws-advanced-python-driver-parameters) parameter. Enhanced Failure Monitoring is enabled by default when the Host Monitoring Connection Plugin is loaded, but it can be disabled by setting the `failure_detection_enabled` parameter to `False`.
1818

19+
This plugin only works with drivers that support aborting connections from a separate thread. At this moment, this plugin is incompatible with the MySQL Connector/Python driver.
20+
21+
> [IMPORTANT]\
22+
> The Host Monitoring Plugin creates monitoring threads in the background to monitor all connections established to each cluster instance. The monitoring threads can be cleaned up in two ways:
23+
> 1. If there are no connections to the cluster instance the thread is monitoring for over a period of time, the Host Monitoring Plugin will automatically terminate the thread. This period of time is adjustable via the `monitor_disposal_time_ms` parameter.
24+
> 2. Client applications can manually call `MonitoringThreadContainer.clean_up()` to clean up any dangling resources.
25+
> It is best practice to call `MonitoringThreadContainer.clean_up()` at the end of the application to ensure a graceful exit; otherwise, the application may wait until the `monitor_disposal_time_ms` has been passed before terminating. This is because the Python driver waits for all daemon threads to complete before exiting.
26+
> See [PGFailover](../../examples/PGFailover.py) for an example.
27+
1928
### Enhanced Failure Monitoring Parameters
2029

2130
<div style="text-align:center"><img src="../../images/monitor_process.png" /></div>
@@ -44,6 +53,11 @@ The Host Monitoring Connection Plugin may create new monitoring connections to c
4453
import psycopg
4554
from aws_advanced_python_wrapper import AwsWrapperConnection
4655

56+
props = {
57+
"monitoring-connect_timeout": 10,
58+
"monitoring-socket_timeout": 10
59+
}
60+
4761
conn = AwsWrapperConnection.connect(
4862
psycopg.Connection.connect,
4963
host="database.cluster-xyz.us-east-1.rds.amazonaws.com",
@@ -54,7 +68,7 @@ conn = AwsWrapperConnection.connect(
5468
# Configure the timeout values for all non-monitoring connections.
5569
connect_timeout=30, socket_timeout=30,
5670
# Configure different timeout values for the monitoring connections.
57-
monitoring-connect_timeout=10, monitoring-socket_timeout=10)
71+
**props)
5872
```
5973

6074
> [!IMPORTANT]\

0 commit comments

Comments
 (0)