diff -pruN 1.3.16-1/Build.PL 1.3.17-1/Build.PL
--- 1.3.16-1/Build.PL	2025-04-12 10:29:42.000000000 +0000
+++ 1.3.17-1/Build.PL	2025-06-18 12:38:46.000000000 +0000
@@ -14,7 +14,7 @@ Module::Build->new(
         'Redis::Fast'    => 0,
     },
     test_requires      => { DBI => 0, 'DBD::SQLite' => 0, },
-    dist_version       => '1.3.16',
+    dist_version       => '1.3.17',
     autosplit          => [qw(lib/Apache/Session/Browseable/_common.pm)],
     configure_requires => { 'Module::Build' => 0, },
     meta_merge         => {
diff -pruN 1.3.16-1/Changes 1.3.17-1/Changes
--- 1.3.16-1/Changes	2025-04-12 10:29:42.000000000 +0000
+++ 1.3.17-1/Changes	2025-06-18 12:38:46.000000000 +0000
@@ -1,5 +1,8 @@
 Revision history for Perl extension Apache::Session::Browseable.
 
+1.3.17
+    - Add Patroni support
+
 1.3.16
     - Optimize deleteIfLowerThan for Redis
 
diff -pruN 1.3.16-1/MANIFEST 1.3.17-1/MANIFEST
--- 1.3.16-1/MANIFEST	2025-04-12 10:29:42.000000000 +0000
+++ 1.3.17-1/MANIFEST	2025-06-18 12:38:46.000000000 +0000
@@ -11,6 +11,7 @@ lib/Apache/Session/Browseable/LDAP.pm
 lib/Apache/Session/Browseable/MySQL.pm
 lib/Apache/Session/Browseable/MySQLJSON.pm
 lib/Apache/Session/Browseable/Oracle.pm
+lib/Apache/Session/Browseable/Patroni.pm
 lib/Apache/Session/Browseable/PgHstore.pm
 lib/Apache/Session/Browseable/PgJSON.pm
 lib/Apache/Session/Browseable/Postgres.pm
@@ -23,6 +24,7 @@ lib/Apache/Session/Browseable/Store/Info
 lib/Apache/Session/Browseable/Store/LDAP.pm
 lib/Apache/Session/Browseable/Store/MySQL.pm
 lib/Apache/Session/Browseable/Store/Oracle.pm
+lib/Apache/Session/Browseable/Store/Patroni.pm
 lib/Apache/Session/Browseable/Store/Postgres.pm
 lib/Apache/Session/Browseable/Store/Redis.pm
 lib/Apache/Session/Browseable/Store/SQLite.pm
@@ -36,12 +38,14 @@ MANIFEST
 META.json
 META.yml			Module meta-data (added by MakeMaker)
 README.md
+RELEASE.md
 rpm/Apache-Session-Browseable.spec
 t/Apache-Session-Browseable-Cassandra.t
 t/Apache-Session-Browseable-common.t
 t/Apache-Session-Browseable-DBI.t
 t/Apache-Session-Browseable-File.t
 t/Apache-Session-Browseable-LDAP.t
+t/Apache-Session-Browseable-Patroni.t
 t/Apache-Session-Browseable-Redis.t
 t/Apache-Session-Browseable-SQLite.t
 t/Apache-Session-Browseable-Store-DBI.t
diff -pruN 1.3.16-1/META.json 1.3.17-1/META.json
--- 1.3.16-1/META.json	2025-04-12 10:29:42.000000000 +0000
+++ 1.3.17-1/META.json	2025-06-18 12:38:46.000000000 +0000
@@ -41,7 +41,7 @@
    "provides" : {
       "Apache::Session::Browseable" : {
          "file" : "lib/Apache/Session/Browseable.pm",
-         "version" : "v1.3.16"
+         "version" : "v1.3.17"
       },
       "Apache::Session::Browseable::Cassandra" : {
          "file" : "lib/Apache/Session/Browseable/Cassandra.pm",
@@ -75,6 +75,10 @@
          "file" : "lib/Apache/Session/Browseable/Oracle.pm",
          "version" : "v1.2.2"
       },
+      "Apache::Session::Browseable::Patroni" : {
+         "file" : "lib/Apache/Session/Browseable/Patroni.pm",
+         "version" : "v1.3.17"
+      },
       "Apache::Session::Browseable::PgHstore" : {
          "file" : "lib/Apache/Session/Browseable/PgHstore.pm",
          "version" : "v1.3.9"
@@ -123,6 +127,10 @@
          "file" : "lib/Apache/Session/Browseable/Store/Oracle.pm",
          "version" : "v1.2.2"
       },
+      "Apache::Session::Browseable::Store::Patroni" : {
+         "file" : "lib/Apache/Session/Browseable/Store/Patroni.pm",
+         "version" : "v1.3.17"
+      },
       "Apache::Session::Browseable::Store::Postgres" : {
          "file" : "lib/Apache/Session/Browseable/Store/Postgres.pm",
          "version" : "v1.2.2"
@@ -165,6 +173,6 @@
          "url" : "https://github.com/LemonLDAPNG/Apache-Session-Browseable"
       }
    },
-   "version" : "v1.3.16",
+   "version" : "v1.3.17",
    "x_serialization_backend" : "JSON::PP version 4.16"
 }
diff -pruN 1.3.16-1/META.yml 1.3.17-1/META.yml
--- 1.3.16-1/META.yml	2025-04-12 10:29:42.000000000 +0000
+++ 1.3.17-1/META.yml	2025-06-18 12:38:46.000000000 +0000
@@ -17,7 +17,7 @@ name: Apache-Session-Browseable
 provides:
   Apache::Session::Browseable:
     file: lib/Apache/Session/Browseable.pm
-    version: v1.3.16
+    version: v1.3.17
   Apache::Session::Browseable::Cassandra:
     file: lib/Apache/Session/Browseable/Cassandra.pm
     version: v1.3.13
@@ -42,6 +42,9 @@ provides:
   Apache::Session::Browseable::Oracle:
     file: lib/Apache/Session/Browseable/Oracle.pm
     version: v1.2.2
+  Apache::Session::Browseable::Patroni:
+    file: lib/Apache/Session/Browseable/Patroni.pm
+    version: v1.3.17
   Apache::Session::Browseable::PgHstore:
     file: lib/Apache/Session/Browseable/PgHstore.pm
     version: v1.3.9
@@ -78,6 +81,9 @@ provides:
   Apache::Session::Browseable::Store::Oracle:
     file: lib/Apache/Session/Browseable/Store/Oracle.pm
     version: v1.2.2
+  Apache::Session::Browseable::Store::Patroni:
+    file: lib/Apache/Session/Browseable/Store/Patroni.pm
+    version: v1.3.17
   Apache::Session::Browseable::Store::Postgres:
     file: lib/Apache/Session/Browseable/Store/Postgres.pm
     version: v1.2.2
@@ -113,5 +119,5 @@ requires:
 resources:
   license: http://dev.perl.org/licenses/
   repository: https://github.com/LemonLDAPNG/Apache-Session-Browseable
-version: v1.3.16
+version: v1.3.17
 x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
diff -pruN 1.3.16-1/RELEASE.md 1.3.17-1/RELEASE.md
--- 1.3.16-1/RELEASE.md	1970-01-01 00:00:00.000000000 +0000
+++ 1.3.17-1/RELEASE.md	2025-06-18 12:38:46.000000000 +0000
@@ -0,0 +1,13 @@
+# Release process
+
+## Version
+
+Update version in `lib/Apache/Session/Browseable.pm`
+
+## Changes
+
+Update changelog in `Changes` file
+
+## Github release
+
+Create a new release on [https://github.com/LemonLDAPNG/Apache-Session-Browseable/releases](https://github.com/LemonLDAPNG/Apache-Session-Browseable/releases)
diff -pruN 1.3.16-1/debian/changelog 1.3.17-1/debian/changelog
--- 1.3.16-1/debian/changelog	2025-04-12 10:32:42.000000000 +0000
+++ 1.3.17-1/debian/changelog	2025-09-21 17:07:26.000000000 +0000
@@ -1,3 +1,14 @@
+libapache-session-browseable-perl (1.3.17-1) unstable; urgency=medium
+
+  * Team upload.
+  * Import upstream version 1.3.17.
+  * Declare compliance with Debian Policy 4.7.2.
+  * Remove «Rules-Requires-Root: no», which is the current default.
+  * Annotate test-only build dependencies with <!nocheck>.
+  * Remove «Priority: optional», which is the current default.
+
+ -- gregor herrmann <gregoa@debian.org>  Sun, 21 Sep 2025 19:07:26 +0200
+
 libapache-session-browseable-perl (1.3.16-1) unstable; urgency=medium
 
   * Import upstream version 1.3.16.
diff -pruN 1.3.16-1/debian/control 1.3.17-1/debian/control
--- 1.3.16-1/debian/control	2025-04-10 19:30:22.000000000 +0000
+++ 1.3.17-1/debian/control	2025-09-21 17:07:26.000000000 +0000
@@ -1,37 +1,40 @@
 Source: libapache-session-browseable-perl
+Standards-Version: 4.7.2
 Maintainer: Debian Perl Group <pkg-perl-maintainers@lists.alioth.debian.org>
-Uploaders: Yadd <yadd@debian.org>
+Uploaders:
+ Yadd <yadd@debian.org>,
 Section: perl
 Testsuite: autopkgtest-pkg-perl
-Priority: optional
-Build-Depends: debhelper-compat (= 13),
-               libmodule-build-perl,
-               perl
-Build-Depends-Indep: libapache-session-perl <!nocheck>,
-                     libdbd-cassandra-perl <!nocheck>,
-                     libdbd-mysql-perl <!nocheck>,
-                     libdbd-sqlite3-perl <!nocheck>,
-                     libdbi-perl <!nocheck>,
-                     libjson-perl <!nocheck>,
-                     libnet-ldap-perl <!nocheck>,
-                     libredis-fast-perl | libredis-perl <!nocheck>
-Standards-Version: 4.6.2
+Build-Depends:
+ debhelper-compat (= 13),
+ libmodule-build-perl,
+ perl,
+Build-Depends-Indep:
+ libapache-session-perl <!nocheck>,
+ libdbd-cassandra-perl <!nocheck>,
+ libdbd-mysql-perl <!nocheck>,
+ libdbd-sqlite3-perl <!nocheck>,
+ libdbi-perl <!nocheck>,
+ libjson-perl <!nocheck>,
+ libnet-ldap-perl <!nocheck>,
+ libredis-fast-perl <!nocheck> | libredis-perl <!nocheck>,
 Vcs-Browser: https://salsa.debian.org/perl-team/modules/packages/libapache-session-browseable-perl
 Vcs-Git: https://salsa.debian.org/perl-team/modules/packages/libapache-session-browseable-perl.git
 Homepage: https://metacpan.org/release/Apache-Session-Browseable
-Rules-Requires-Root: no
 
 Package: libapache-session-browseable-perl
 Architecture: all
 Multi-Arch: foreign
-Depends: ${misc:Depends},
-         ${perl:Depends},
-         libapache-session-perl,
-         libjson-perl
-Suggests: libdbd-cassandra-perl,
-          libdbi-perl,
-          libnet-ldap-perl,
-          libredis-fast-perl | libredis-perl
+Depends:
+ ${misc:Depends},
+ ${perl:Depends},
+ libapache-session-perl,
+ libjson-perl,
+Suggests:
+ libdbd-cassandra-perl,
+ libdbi-perl,
+ libnet-ldap-perl,
+ libredis-fast-perl | libredis-perl,
 Description: module adding index and search methods to Apache::Session
  Apache::Session::Browseable provides some class methods to manipulate all
  sessions and add the capability to index some fields to make research faster.
diff -pruN 1.3.16-1/lib/Apache/Session/Browseable/DBI.pm 1.3.17-1/lib/Apache/Session/Browseable/DBI.pm
--- 1.3.16-1/lib/Apache/Session/Browseable/DBI.pm	2025-04-12 10:29:42.000000000 +0000
+++ 1.3.17-1/lib/Apache/Session/Browseable/DBI.pm	2025-06-18 12:38:46.000000000 +0000
@@ -109,15 +109,20 @@ sub deleteIfLowerThan {
     elsif ( $rule->{and} ) {
         $query = join ' AND ', map {
             $fields{$_}++;
-            $class->_buildLowerThanExpression( $_, $rule->{or}->{$_} )
+            $class->_buildLowerThanExpression( $_, $rule->{and}->{$_} )
           }
-          keys %{ $rule->{or} };
+          keys %{ $rule->{and} };
     }
     if ( $rule->{not} ) {
-        $query = "($query) AND "
-          . join( ' AND ',
-            map { $fields{$_}++; "$_ <> '$rule->{not}->{$_}'" }
-              keys %{ $rule->{not} } );
+        $query = "($query) AND " . join(
+            ' AND ',
+            map {
+                $rule->{not}->{$_} =~ s/'/''/g;
+                $fields{$_}++;
+                "$_ <> '$rule->{not}->{$_}'"
+              }
+              keys %{ $rule->{not} }
+        );
     }
     return 0
       unless ( $query and $class->_tabInTab( [ keys %fields ], $index ) );
@@ -180,12 +185,12 @@ sub get_key_from_all_sessions {
         ? sub {
             require Storable;
             return Storable::thaw( pack( 'H*', $_[0] ) );
-        }
+          }
         : $args->{DataSource} =~ /^mysql/i ? sub {
             require MIME::Base64;
             require Storable;
             return Storable::thaw( MIME::Base64::decode_base64( $_[0] ) );
-        }
+          }
         : undef
     );
     while ( my @row = $sth->fetchrow_array ) {
diff -pruN 1.3.16-1/lib/Apache/Session/Browseable/Patroni.pm 1.3.17-1/lib/Apache/Session/Browseable/Patroni.pm
--- 1.3.16-1/lib/Apache/Session/Browseable/Patroni.pm	1970-01-01 00:00:00.000000000 +0000
+++ 1.3.17-1/lib/Apache/Session/Browseable/Patroni.pm	2025-06-18 12:38:46.000000000 +0000
@@ -0,0 +1,101 @@
+package Apache::Session::Browseable::Patroni;
+
+use strict;
+use Apache::Session::Lock::Null;
+use Apache::Session::Browseable::PgJSON;
+use Apache::Session::Browseable::Store::Patroni;
+use Apache::Session::Generate::SHA256;
+use Apache::Session::Serialize::JSON;
+
+our @ISA     = qw(Apache::Session::Browseable::PgJSON);
+our $VERSION = '1.3.17';
+
+sub populate {
+    my $self = shift;
+
+    $self->{object_store} =
+      new Apache::Session::Browseable::Store::Patroni $self;
+    $self->{lock_manager} = new Apache::Session::Lock::Null $self;
+    $self->{generate}     = \&Apache::Session::Generate::SHA256::generate;
+    $self->{validate}     = \&Apache::Session::Generate::SHA256::validate;
+    $self->{serialize}    = \&Apache::Session::Serialize::JSON::serialize;
+    $self->{unserialize}  = \&Apache::Session::Serialize::JSON::unserialize;
+
+    return $self;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Apache::Session::Browseable::Patroni - PostgreSQL/Patroni cluster support
+for L<Apache::Session::Browseable::PgJSON>
+
+=head1 SYNOPSIS
+
+  CREATE UNLOGGED TABLE sessions (
+      id varchar(64) not null primary key,
+      a_session jsonb,
+  );
+
+Optionally, add indexes on some fields. Example for Lemonldap::NG:
+
+  CREATE INDEX uid1 ON sessions USING BTREE ( (a_session ->> '_whatToTrace') );
+  CREATE INDEX  s1  ON sessions ( (a_session ->> '_session_kind') );
+  CREATE INDEX  u1  ON sessions ( ( cast(a_session ->> '_utime' AS bigint) ) );
+  CREATE INDEX ip1  ON sessions USING BTREE ( (a_session ->> 'ipAddr') );
+
+Use it with Perl:
+
+  use Apache::Session::Browseable::Postgres;
+
+  my $args = {
+       DataSource => 'dbi:Pg:sessions',
+       UserName   => $db_user,
+       Password   => $db_pass,
+       Commit     => 1,
+
+       # List all Patroni API available (to avoid any haproxy and/or floating IP)
+       PatroniUrl => 'http://1.2.3.4:8008/cluster http://2.3.4.5:8008/cluster',
+  };
+
+  # Use it like L<Apache::Session::Browseable::Postgres>
+
+=head1 DESCRIPTION
+
+Apache::Session::Browseable provides some class methods to manipulate all
+sessions and add the capability to index some fields to make research faster.
+
+Apache::Session::Browseable::Patroni implements it for PosqtgreSQL databases
+using "json" or "jsonb" type to be able to browse sessions and is able to dial
+directly with Patroni API to find the master node of PostgreSQL cluster in
+case of error.
+
+=head1 SEE ALSO
+
+L<http://lemonldap-ng.org>, L<Apache::Session::Postgres>
+
+=head1 COPYRIGHT AND LICENSE
+
+=encoding utf8
+
+=over
+
+=item 2009-2025 by Xavier Guimard
+
+=item 2013-2025 by Clément Oudot
+
+=item 2019-2025 by Maxime Besson
+
+=item 2013-2025 by Worteks
+
+=item 2023-2025 by Linagora
+
+=back
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.10.1 or,
+at your option, any later version of Perl 5 you may have available.
+
+=cut
diff -pruN 1.3.16-1/lib/Apache/Session/Browseable/Store/DBI.pm 1.3.17-1/lib/Apache/Session/Browseable/Store/DBI.pm
--- 1.3.16-1/lib/Apache/Session/Browseable/Store/DBI.pm	2025-04-12 10:29:42.000000000 +0000
+++ 1.3.17-1/lib/Apache/Session/Browseable/Store/DBI.pm	2025-06-18 12:38:46.000000000 +0000
@@ -17,14 +17,12 @@ sub insert {
       ? $session->{args}->{Index}
       : [ split /\s+/, $session->{args}->{Index} ];
 
-    if ( !defined $self->{insert_sth} ) {
-        $self->{insert_sth} =
-          $self->{dbh}->prepare_cached( "INSERT INTO $self->{table_name} ("
-              . join( ',', 'id', 'a_session', map { s/'/''/g; $_ } @$index )
-              . ') VALUES ('
-              . join( ',', ('?') x ( 2 + @$index ) )
-              . ')' );
-    }
+    $self->{insert_sth} //=
+      $self->{dbh}->prepare_cached( "INSERT INTO $self->{table_name} ("
+          . join( ',', 'id', 'a_session', map { s/'/''/g; $_ } @$index )
+          . ') VALUES ('
+          . join( ',', ('?') x ( 2 + @$index ) )
+          . ')' );
 
     $self->{insert_sth}->bind_param( 1, $session->{data}->{_session_id} );
     $self->{insert_sth}->bind_param( 2, $session->{serialized} );
diff -pruN 1.3.16-1/lib/Apache/Session/Browseable/Store/Patroni.pm 1.3.17-1/lib/Apache/Session/Browseable/Store/Patroni.pm
--- 1.3.16-1/lib/Apache/Session/Browseable/Store/Patroni.pm	1970-01-01 00:00:00.000000000 +0000
+++ 1.3.17-1/lib/Apache/Session/Browseable/Store/Patroni.pm	2025-06-18 12:38:46.000000000 +0000
@@ -0,0 +1,151 @@
+package Apache::Session::Browseable::Store::Patroni;
+
+use strict;
+
+use DBI;
+use Apache::Session::Store::Postgres;
+
+our @ISA     = qw(Apache::Session::Store::Postgres);
+our $VERSION = '1.3.17';
+
+our %knownMappings;
+
+sub connection {
+    my $self    = shift;
+    my $session = shift;
+
+    return if ( defined $self->{dbh} );
+
+    $self->{'table_name'} =
+      $session->{args}->{TableName} || $Apache::Session::Store::DBI::TableName;
+
+    if ( exists $session->{args}->{Handle} ) {
+        $self->{dbh}    = $session->{args}->{Handle};
+        $self->{commit} = $session->{args}->{Commit};
+        return;
+    }
+
+    # Use last known Patroni response if available
+    $session->{args}->{DataSource} =
+      $knownMappings{ $session->{args}->{DataSource} }
+      if $session->{args}->{DataSource}
+      and $knownMappings{ $session->{args}->{DataSource} };
+
+    foreach ( 0 .. 1 ) {
+        (
+            $self->checkMaster( $session->{args} )
+              or warn "Patroni check failed"
+        ) if $self->{failure};
+        eval {
+            $self->{dbh} = DBI->connect(
+                $session->{args}->{DataSource},
+                $session->{args}->{UserName},
+                $session->{args}->{Password},
+                { RaiseError => 1, AutoCommit => 0 }
+            ) || die $DBI::errstr;
+        };
+        if ( $@ and !$_ ) {
+            $self->{failure} = 1;
+        }
+        else {
+            last;
+        }
+    }
+    die $@ if $@;
+
+    #If we open the connection, we close the connection
+    $self->{disconnect} = 1;
+
+    #the programmer has to tell us what commit policy to use
+    $self->{commit} = $session->{args}->{Commit} // 1;
+}
+
+sub _try {
+    my $self = shift;
+    my $sub  = shift;
+    my $res;
+
+    foreach ( 0 .. 1 ) {
+        $res =
+          eval { Apache::Session::Store::Postgres->can($sub)->( $self, @_ ) };
+        if ( $@ and $@ !~ /Object does not exist/ and !$_ ) {
+            $self->{failure} = 1;
+            $self->DESTROY;
+            delete $self->{"${sub}_sth"};
+            delete $self->{dbh};
+        }
+        else {
+            last;
+        }
+    }
+    die $@ if $@;
+    return $res;
+}
+
+sub insert {
+    my $self = shift;
+    return $self->_try( 'insert', @_ );
+}
+
+sub update {
+    my $self = shift;
+    return $self->_try( 'update', @_ );
+}
+
+sub materialize {
+    my $self = shift;
+    return $self->_try( 'materialize', @_ );
+}
+
+sub remove {
+    my $self = shift;
+    return $self->_try( 'remove', @_ );
+}
+
+sub checkMaster {
+    my ( $self, $args ) = @_;
+    delete $self->{failure};
+    require JSON;
+    require LWP::UserAgent;
+    require IO::Socket::SSL;
+    my $ua = LWP::UserAgent->new(
+        env_proxy => 1,
+        ssl_opts  => {
+            verify_hostname => 0,
+            SSL_verify_mode => &IO::Socket::SSL::SSL_VERIFY_NONE,
+        },
+        timeout => 3,
+    );
+    my $res;
+
+    foreach my $patroniUrl ( split /[,\s]\s*/,
+        ( $args->{PatroniUrl} || $args->{patroniUrl} ) )
+    {
+        my $resp = $ua->get($patroniUrl);
+        if ( $resp->is_success ) {
+            my $c = eval { JSON::from_json( $resp->decoded_content ) };
+            if ( $@ or !$c->{members} or ref( $c->{members} ) ne 'ARRAY' ) {
+                print STDERR "Bad response from $patroniUrl\n"
+                  . $resp->decoded_content;
+                next;
+            }
+            my ($leader) = grep { $_->{role} eq 'leader' } @{ $c->{members} };
+            unless ($leader) {
+                print STDERR "No leader found from $patroniUrl\n"
+                  . $resp->decoded_content;
+                next;
+            }
+            my $old = $args->{DataSource};
+            $args->{DataSource} =~ s/(?:port|host)=[^;]+;*//g;
+            $args->{DataSource} =~ s/;$//;
+            $args->{DataSource} .= ( $args->{DataSource} =~ /:$/ ? '' : ';' )
+              . "host=$leader->{host};port=$leader->{port}";
+            $knownMappings{$old} = $args->{DataSource};
+            $res = 1;
+            last;
+        }
+    }
+    return $res;
+}
+
+1;
diff -pruN 1.3.16-1/lib/Apache/Session/Browseable.pm 1.3.17-1/lib/Apache/Session/Browseable.pm
--- 1.3.16-1/lib/Apache/Session/Browseable.pm	2025-04-12 10:29:42.000000000 +0000
+++ 1.3.17-1/lib/Apache/Session/Browseable.pm	2025-06-18 12:38:46.000000000 +0000
@@ -1,6 +1,6 @@
 package Apache::Session::Browseable;
 
-our $VERSION = '1.3.16';
+our $VERSION = '1.3.17';
 
 print STDERR "Use a sub module of Apache::Session::Browseable such as Apache::Session::Browseable::File";
 
@@ -33,6 +33,9 @@ chosen module documentation carefully to
 
 =item L<Apache::Session::Browseable::PgJSON>: uses "json/jsonb" field
 
+=item L<Apache::Session::Browseable::Patroni>: uses "json/jsonb" field and
+manage connection using Patroni API to find master node of PostgreSQL cluster
+
 =back
 
 =head3 MySQL or MariaDB
diff -pruN 1.3.16-1/t/Apache-Session-Browseable-Patroni.t 1.3.17-1/t/Apache-Session-Browseable-Patroni.t
--- 1.3.16-1/t/Apache-Session-Browseable-Patroni.t	1970-01-01 00:00:00.000000000 +0000
+++ 1.3.17-1/t/Apache-Session-Browseable-Patroni.t	2025-06-18 12:38:46.000000000 +0000
@@ -0,0 +1,53 @@
+use Test::More;
+
+plan skip_all => "Optional modules (DBD::Pg, DBI) not installed"
+  unless eval {
+    require DBI;
+    require DBD::Pg;
+  };
+
+$package = 'Apache::Session::Browseable::Store::Patroni';
+
+use_ok($package);
+
+my $foo = $package->new;
+
+isa_ok $foo, $package;
+
+$package = 'Apache::Session::Browseable::Patroni';
+use_ok($package);
+
+SKIP: {
+    skip 'No patroniUrl, skipping', 1 unless $ENV{PATRONI_URL};
+    my $args = {
+        DataSource => 'dbi:Pg:dbname=sessions;host='
+          . ( $ENV{PG_HOST} || '127.25.76.98:port=300' ),
+        UserName   => 'postgres',
+        Password   => 'postgres',
+        PatroniUrl => $ENV{PATRONI_URL},
+    };
+
+    my %h;
+    tie %h, $package, undef, $args;
+    ok( %h && $h{_session_id}, 'Hash populated' );
+    my $id = $h{_session_id};
+    $h{a} = 'aa';
+    untie %h;
+    %h = ();
+    tie %h, $package, $id, $args;
+    is( $h{a}, 'aa', 'data stored' );
+    untie %h;
+    if ($ENV{PATRONI_NEXT}) {
+        diag `$ENV{PATRONI_NEXT}`;
+        sleep 1;
+    }
+    tie %h, $package, $id, $args;
+    $h{a} = 'bb';
+    untie %h;
+    %h = ();
+    tie %h, $package, $id, $args;
+    is( $h{a}, 'bb', 'data changed' );
+    untie %h;
+}
+
+done_testing();
