mirror of
https://github.com/outbackdingo/patroni.git
synced 2026-08-25 14:53:37 +00:00
Release v3.3.1 (#3087)
* Update release notes * Bump version * Bump pyright version and solve reported issues --------- Co-authored-by: Alexander Kukushkin <[email protected]>
This commit is contained in:
co-authored by
Alexander Kukushkin
parent
d4fd782038
commit
6b7ec49282
@@ -186,7 +186,7 @@ jobs:
|
||||
|
||||
- uses: jakebailey/pyright-action@v2
|
||||
with:
|
||||
version: 1.1.356
|
||||
version: 1.1.367
|
||||
|
||||
docs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -3,6 +3,33 @@
|
||||
Release notes
|
||||
=============
|
||||
|
||||
Version 3.3.1
|
||||
-------------
|
||||
|
||||
Released 2024-06-17
|
||||
|
||||
**Stability improvements**
|
||||
|
||||
- Compatibility with Python 3.12 (Alexander Kukushkin)
|
||||
|
||||
Handle a new attribute added to ``logging.LogRecord``.
|
||||
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
- Fix infinite recursion in ``replicatefrom`` tags handling (Alexander Kukushkin)
|
||||
|
||||
As a part of this fix, also improve ``is_physical_slot()`` check and adjust documentation.
|
||||
|
||||
- Fix wrong role reporting in standby clusters (Alexander Kukushkin)
|
||||
|
||||
`synchronous_standby_names` and synchronous replication only work on a real primary node and in the case of cascading replication are simply ignored by Postgres. Before this fix, `patronictl list` and `GET /cluster` were falsely reporting some nodes as synchronous.
|
||||
|
||||
- Fix availability of the ``allow_in_place_tablespaces`` GUC (Polina Bungina)
|
||||
|
||||
``allow_in_place_tablespaces`` was not only added to PostgreSQL 15 but also backpatched to PostgreSQL 10-14.
|
||||
|
||||
|
||||
Version 3.3.0
|
||||
-------------
|
||||
|
||||
|
||||
+16
-6
@@ -62,6 +62,15 @@ def error_exception(self: logging.Logger, msg: object, *args: Any, **kwargs: Any
|
||||
self.error(msg, *args, exc_info=exc_info, **kwargs)
|
||||
|
||||
|
||||
def _type(value: Any) -> str:
|
||||
"""Get type of the *value*.
|
||||
|
||||
:param value: any arbitrary value.
|
||||
:returns: a string with a type name.
|
||||
"""
|
||||
return value.__class__.__name__
|
||||
|
||||
|
||||
class QueueHandler(logging.Handler):
|
||||
"""Queue-based logging handler.
|
||||
|
||||
@@ -292,7 +301,7 @@ class PatroniLogger(Thread):
|
||||
"""
|
||||
|
||||
if not isinstance(logformat, str):
|
||||
_LOGGER.warning('Expected log format to be a string when log type is plain, but got "%s"', type(logformat))
|
||||
_LOGGER.warning('Expected log format to be a string when log type is plain, but got "%s"', _type(logformat))
|
||||
logformat = PatroniLogger.DEFAULT_FORMAT
|
||||
|
||||
return logging.Formatter(logformat, dateformat)
|
||||
@@ -330,13 +339,13 @@ class PatroniLogger(Thread):
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
'Expected renamed log field to be a string, but got "%s"',
|
||||
type(renamed_field)
|
||||
_type(renamed_field)
|
||||
)
|
||||
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
'Expected each item of log format to be a string or dictionary, but got "%s"',
|
||||
type(field)
|
||||
_type(field)
|
||||
)
|
||||
|
||||
if len(log_fields) > 0:
|
||||
@@ -346,11 +355,12 @@ class PatroniLogger(Thread):
|
||||
else:
|
||||
jsonformat = PatroniLogger.DEFAULT_FORMAT
|
||||
rename_fields = {}
|
||||
_LOGGER.warning('Expected log format to be a string or a list, but got "%s"', type(logformat))
|
||||
_LOGGER.warning('Expected log format to be a string or a list, but got "%s"', _type(logformat))
|
||||
|
||||
try:
|
||||
from pythonjsonlogger import jsonlogger
|
||||
if hasattr(jsonlogger, 'RESERVED_ATTRS') and 'taskName' not in jsonlogger.RESERVED_ATTRS:
|
||||
if hasattr(jsonlogger, 'RESERVED_ATTRS') \
|
||||
and 'taskName' not in jsonlogger.RESERVED_ATTRS: # pyright: ignore [reportUnnecessaryContains]
|
||||
# compatibility with python 3.12, that added a new attribute to LogRecord
|
||||
jsonlogger.RESERVED_ATTRS += ('taskName',)
|
||||
|
||||
@@ -380,7 +390,7 @@ class PatroniLogger(Thread):
|
||||
static_fields = config.get('static_fields', {})
|
||||
|
||||
if dateformat is not None and not isinstance(dateformat, str):
|
||||
_LOGGER.warning('Expected log dateformat to be a string, but got "%s"', type(dateformat))
|
||||
_LOGGER.warning('Expected log dateformat to be a string, but got "%s"', _type(dateformat))
|
||||
dateformat = None
|
||||
|
||||
if logtype == 'json':
|
||||
|
||||
@@ -893,7 +893,8 @@ class ConfigHandler(object):
|
||||
return re.sub(r'([:\\])', r'\\\1', str(value))
|
||||
|
||||
# 'host' could be several comma-separated hostnames, in this case we need to write on pgpass line per host
|
||||
hosts = map(escape, filter(None, map(str.strip, (record.get('host') or '*').split(','))))
|
||||
hosts = map(escape, filter(None, map(str.strip,
|
||||
(record.get('host', '') or '*').split(',')))) # pyright: ignore [reportUnknownArgumentType]
|
||||
record = {n: escape(record.get(n) or '*') for n in ('port', 'user', 'password')}
|
||||
return '\n'.join('{host}:{port}:*:{user}:{password}'.format(**record, host=host) for host in hosts)
|
||||
|
||||
|
||||
@@ -428,7 +428,8 @@ class CitusHandler(Citus, AbstractMPPHandler, Thread):
|
||||
# citus extension must be on the first place in shared_preload_libraries
|
||||
shared_preload_libraries = list(filter(
|
||||
lambda el: el and el != 'citus',
|
||||
[p.strip() for p in parameters.get('shared_preload_libraries', '').split(',')]))
|
||||
map(str.strip, parameters.get('shared_preload_libraries', '').split(',')))
|
||||
) # pyright: ignore [reportUnknownArgumentType]
|
||||
parameters['shared_preload_libraries'] = ','.join(['citus'] + shared_preload_libraries)
|
||||
|
||||
# if not explicitly set Citus overrides max_prepared_transactions to max_connections*2
|
||||
|
||||
+1
-1
@@ -2,4 +2,4 @@
|
||||
|
||||
:var __version__: the current Patroni version.
|
||||
"""
|
||||
__version__ = '3.3.0'
|
||||
__version__ = '3.3.1'
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
"reportMissingImports": true,
|
||||
"reportMissingTypeStubs": false,
|
||||
|
||||
"pythonVersion": "3.11",
|
||||
"pythonVersion": "3.12",
|
||||
"pythonPlatform": "All",
|
||||
|
||||
"typeCheckingMode": "strict"
|
||||
|
||||
+1
-1
@@ -187,7 +187,7 @@ class TestPatroniLogger(unittest.TestCase):
|
||||
self.assertEqual(captured_log_level, 'WARNING')
|
||||
self.assertRegex(
|
||||
captured_log_message,
|
||||
fr'Expected log dateformat to be a string, but got "{type(config["dateformat"])}"'
|
||||
r'Expected log dateformat to be a string, but got "int"'
|
||||
)
|
||||
|
||||
def test_invalid_plain_format(self):
|
||||
|
||||
Reference in New Issue
Block a user