The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.
Changes 072
MANIFEST 16
META.json 56
META.yml 56
Makefile.PL 89
README 11
lib/Search/Elasticsearch/Bulk.pm 22
lib/Search/Elasticsearch/Client/0_90/Direct/Cluster.pm 22
lib/Search/Elasticsearch/Client/0_90/Direct/Indices.pm 22
lib/Search/Elasticsearch/Client/0_90/Direct.pm 311
lib/Search/Elasticsearch/Client/Direct/Cat.pm 323
lib/Search/Elasticsearch/Client/Direct/Cluster.pm 43
lib/Search/Elasticsearch/Client/Direct/Indices.pm 663
lib/Search/Elasticsearch/Client/Direct/Nodes.pm 23
lib/Search/Elasticsearch/Client/Direct/Snapshot.pm 319
lib/Search/Elasticsearch/Client/Direct.pm 6160
lib/Search/Elasticsearch/Cxn/Factory.pm 33
lib/Search/Elasticsearch/Cxn/HTTPTiny.pm 649
lib/Search/Elasticsearch/Cxn/Hijk.pm 313
lib/Search/Elasticsearch/Cxn/LWP.pm 353
lib/Search/Elasticsearch/CxnPool/Sniff.pm 22
lib/Search/Elasticsearch/CxnPool/Static/NoPing.pm 22
lib/Search/Elasticsearch/CxnPool/Static.pm 22
lib/Search/Elasticsearch/Error.pm 22
lib/Search/Elasticsearch/Logger/LogAny.pm 33
lib/Search/Elasticsearch/Role/API/0_90.pm 1817
lib/Search/Elasticsearch/Role/API.pm 58191
lib/Search/Elasticsearch/Role/Bulk.pm 22
lib/Search/Elasticsearch/Role/Client/Direct.pm 23
lib/Search/Elasticsearch/Role/Client.pm 22
lib/Search/Elasticsearch/Role/Cxn/HTTP.pm 426
lib/Search/Elasticsearch/Role/Cxn.pm 33
lib/Search/Elasticsearch/Role/CxnPool/Sniff.pm 22
lib/Search/Elasticsearch/Role/CxnPool/Static/NoPing.pm 22
lib/Search/Elasticsearch/Role/CxnPool/Static.pm 22
lib/Search/Elasticsearch/Role/CxnPool.pm 22
lib/Search/Elasticsearch/Role/Is_Sync.pm 22
lib/Search/Elasticsearch/Role/Logger.pm 22
lib/Search/Elasticsearch/Role/Scroll.pm 1917
lib/Search/Elasticsearch/Role/Serializer/JSON.pm 22
lib/Search/Elasticsearch/Role/Serializer.pm 22
lib/Search/Elasticsearch/Role/Transport.pm 22
lib/Search/Elasticsearch/Scroll.pm 3037
lib/Search/Elasticsearch/Serializer/JSON/Cpanel.pm 22
lib/Search/Elasticsearch/Serializer/JSON/PP.pm 22
lib/Search/Elasticsearch/Serializer/JSON/XS.pm 33
lib/Search/Elasticsearch/Serializer/JSON.pm 22
lib/Search/Elasticsearch/TestServer.pm 22
lib/Search/Elasticsearch/Transport.pm 22
lib/Search/Elasticsearch/Util/API/Path.pm 22
lib/Search/Elasticsearch/Util/API/QS.pm 2642
lib/Search/Elasticsearch/Util.pm 22
lib/Search/Elasticsearch.pm 22
t/60_Cxn/40_fork_httptiny.t 05
t/60_Cxn/41_fork_lwp.t 05
t/60_Cxn/42_fork_hijk.t 05
t/60_Cxn/43_fork_netcurl.t 05
t/70_Helper/50_scroll.t 2425
t/lib/es_sync.pl 13
t/lib/es_sync_fork.pl 042
t/lib/index_test_data.pl 02
t/release-no-tabs.t 16
62 files changed (This is a version diff) 306992
@@ -1,5 +1,77 @@
 Revision history for Search::Elasticsearch
 
+1.16    2014-11-15
+        Added dependency on Pod::Simple, which was causing
+        installation on perl 5.8 to fail
+
+        Added params:
+        * percolate_preference and percolate_routing to percolate()
+
+        Bug fix:
+        * the index param is now required for indices.delete()
+
+1.15    2014-11-05
+        Enhancements:
+         *  All backends (except Hijk) now default to not verifying
+            SSL identities, but accept ssl_options to allow
+            backend-specific configuration
+         *  Improved Mojo exceptions
+
+        Bug fix:
+         *  is_https() didn't work
+
+        Changed:
+         *  index param to put_alias() is now required
+
+        Added methods:
+         *  index.get()
+         *  search_exists()
+         *  indices.upgrade()
+         *  indices.get_upgrade()
+         *  snapshot.verify_repository()
+
+        Added parameters:
+         *  query_cache to search(), clear_cache(), stats()
+         *  wait_if_ongoing to flush()
+         *  script_id and scripted_upsert to update()
+         *  version and version_type to put_script(), get_script(),
+            delete_script(), put_template(), get_template(), and
+            delete_template()
+         *  op_type to put_script() and put_template()
+         *  metric to cluster_reroute()
+         *  realtime to termvector() and mtermvector()
+         *  dfs to termvector()
+
+        Removed parameters:
+         *  filter_metadata from cluster_reroute()
+         *  search_query_hint from mlt()
+
+        Bumped versions:
+            JSON::XS        2.26
+            Package::Stash  0.34
+            Log::Any        0.15
+
+
+1.14    2014-07-24
+        Added support for indexed scripts and indexed templates.
+
+1.13    2014-06-13
+        Breaking change:
+            The Scroll helper used to pass the scroll ID to
+            scroll() and clear_scroll() in the query string by default,
+            with the scroll_in_body parameter to change the behaviour.
+            This was causing frequent errors with long scroll IDs, so
+            the new default behaviour is to pass the scroll ID in the
+            body, with the scroll_in_qs parameter to change that
+            behaviour.
+        All Search::Elasticsearch HTTP backends are now fork safe.
+        Added track_scores param to search()
+        Added create param to indices.put_template()
+        Removed index_templates param from cluster.state()
+        Removed indices_boost param from search()
+        Added percolate_format param to percolate()
+        Added cat.fielddata()
+
 1.12    2014-05-09
         Fixed bug when trying to reindex from a subref
         Added search_shards()
@@ -1,4 +1,4 @@
-# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.015.
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.020.
 Changes
 LICENSE
 MANIFEST
@@ -110,6 +110,10 @@ t/50_Cxn_Pool/70_live.t
 t/60_Cxn/10_basic.t
 t/60_Cxn/20_process_response.t
 t/60_Cxn/30_http.t
+t/60_Cxn/40_fork_httptiny.t
+t/60_Cxn/41_fork_lwp.t
+t/60_Cxn/42_fork_hijk.t
+t/60_Cxn/43_fork_netcurl.t
 t/70_Helper/10_bulk_add_action.t
 t/70_Helper/20_bulk_helpers.t
 t/70_Helper/30_bulk_flush.t
@@ -121,6 +125,7 @@ t/lib/LogCallback.pl
 t/lib/MockCxn.pm
 t/lib/default_cxn.pl
 t/lib/es_sync.pl
+t/lib/es_sync_fork.pl
 t/lib/index_test_data.pl
 t/release-eol.t
 t/release-no-tabs.t
@@ -4,7 +4,7 @@
       "Clinton Gormley <drtech@cpan.org>"
    ],
    "dynamic_config" : 0,
-   "generated_by" : "Dist::Zilla version 5.015, CPAN::Meta::Converter version 2.140640",
+   "generated_by" : "Dist::Zilla version 5.020, CPAN::Meta::Converter version 2.140640",
    "license" : [
       "apache_2_0"
    ],
@@ -21,7 +21,8 @@
       },
       "configure" : {
          "requires" : {
-            "ExtUtils::MakeMaker" : "6.30"
+            "ExtUtils::MakeMaker" : "0",
+            "Pod::Simple" : "3.28"
          }
       },
       "develop" : {
@@ -46,19 +47,19 @@
             "Hijk" : "0.12",
             "IO::Select" : "0",
             "IO::Socket" : "0",
-            "IO::Socket::SSL" : "0",
             "IO::Uncompress::Inflate" : "0",
             "JSON::MaybeXS" : "1.002002",
             "JSON::PP" : "0",
             "LWP::UserAgent" : "0",
             "List::Util" : "0",
-            "Log::Any" : "0",
+            "Log::Any" : "0.15",
             "Log::Any::Adapter" : "0",
             "MIME::Base64" : "0",
             "Module::Runtime" : "0",
             "Moo" : "1.003",
             "Moo::Role" : "0",
             "POSIX" : "0",
+            "Package::Stash" : "0.34",
             "Scalar::Util" : "0",
             "Sub::Exporter" : "0",
             "Time::HiRes" : "0",
@@ -97,6 +98,6 @@
          "web" : "https://github.com/elasticsearch/elasticsearch-perl"
       }
    },
-   "version" : "1.12"
+   "version" : "1.16"
 }
 
@@ -9,9 +9,10 @@ build_requires:
   Test::More: '0.98'
   lib: '0'
 configure_requires:
-  ExtUtils::MakeMaker: '6.30'
+  ExtUtils::MakeMaker: '0'
+  Pod::Simple: '3.28'
 dynamic_config: 0
-generated_by: 'Dist::Zilla version 5.015, CPAN::Meta::Converter version 2.140640'
+generated_by: 'Dist::Zilla version 5.020, CPAN::Meta::Converter version 2.140640'
 license: apache
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -30,19 +31,19 @@ requires:
   Hijk: '0.12'
   IO::Select: '0'
   IO::Socket: '0'
-  IO::Socket::SSL: '0'
   IO::Uncompress::Inflate: '0'
   JSON::MaybeXS: '1.002002'
   JSON::PP: '0'
   LWP::UserAgent: '0'
   List::Util: '0'
-  Log::Any: '0'
+  Log::Any: '0.15'
   Log::Any::Adapter: '0'
   MIME::Base64: '0'
   Module::Runtime: '0'
   Moo: '1.003'
   Moo::Role: '0'
   POSIX: '0'
+  Package::Stash: '0.34'
   Scalar::Util: '0'
   Sub::Exporter: '0'
   Time::HiRes: '0'
@@ -55,4 +56,4 @@ requires:
 resources:
   bugtracker: https://github.com/elasticsearch/elasticsearch-perl/issues
   repository: git://github.com/elasticsearch/elasticsearch-perl.git
-version: '1.12'
+version: '1.16'
@@ -1,11 +1,11 @@
 
-# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.015.
+# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.020.
 use strict;
 use warnings;
 
 
 
-use ExtUtils::MakeMaker 6.30;
+use ExtUtils::MakeMaker ;
 
 
 
@@ -16,7 +16,8 @@ my %WriteMakefileArgs = (
     "Test::More" => "0.98"
   },
   "CONFIGURE_REQUIRES" => {
-    "ExtUtils::MakeMaker" => "6.30"
+    "ExtUtils::MakeMaker" => 0,
+    "Pod::Simple" => "3.28"
   },
   "DISTNAME" => "Search-Elasticsearch",
   "EXE_FILES" => [],
@@ -33,19 +34,19 @@ my %WriteMakefileArgs = (
     "Hijk" => "0.12",
     "IO::Select" => 0,
     "IO::Socket" => 0,
-    "IO::Socket::SSL" => 0,
     "IO::Uncompress::Inflate" => 0,
     "JSON::MaybeXS" => "1.002002",
     "JSON::PP" => 0,
     "LWP::UserAgent" => 0,
     "List::Util" => 0,
-    "Log::Any" => 0,
+    "Log::Any" => "0.15",
     "Log::Any::Adapter" => 0,
     "MIME::Base64" => 0,
     "Module::Runtime" => 0,
     "Moo" => "1.003",
     "Moo::Role" => 0,
     "POSIX" => 0,
+    "Package::Stash" => "0.34",
     "Scalar::Util" => 0,
     "Sub::Exporter" => 0,
     "Time::HiRes" => 0,
@@ -63,7 +64,7 @@ my %WriteMakefileArgs = (
     "Test::More" => "0.98",
     "lib" => 0
   },
-  "VERSION" => "1.12",
+  "VERSION" => "1.16",
   "test" => {
     "TESTS" => "t/*.t t/10_Basic/*.t t/20_Serializer/*.t t/30_Logger/*.t t/40_Transport/*.t t/50_Cxn_Pool/*.t t/60_Cxn/*.t t/70_Helper/*.t t/90_Client_Spec/*.t"
   }
@@ -81,13 +82,12 @@ my %FallbackPrereqs = (
   "Hijk" => "0.12",
   "IO::Select" => 0,
   "IO::Socket" => 0,
-  "IO::Socket::SSL" => 0,
   "IO::Uncompress::Inflate" => 0,
   "JSON::MaybeXS" => "1.002002",
   "JSON::PP" => 0,
   "LWP::UserAgent" => 0,
   "List::Util" => 0,
-  "Log::Any" => 0,
+  "Log::Any" => "0.15",
   "Log::Any::Adapter" => 0,
   "Log::Any::Adapter::Callback" => 0,
   "MIME::Base64" => 0,
@@ -95,6 +95,7 @@ my %FallbackPrereqs = (
   "Moo" => "1.003",
   "Moo::Role" => 0,
   "POSIX" => 0,
+  "Package::Stash" => "0.34",
   "Scalar::Util" => 0,
   "Sub::Exporter" => 0,
   "Test::Deep" => 0,
@@ -2,7 +2,7 @@ NAME
     Search::Elasticsearch - The official client for Elasticsearch
 
 VERSION
-    version 1.12
+    version 1.16
 
 SYNOPSIS
         use Search::Elasticsearch;
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Bulk;
-$Search::Elasticsearch::Bulk::VERSION = '1.12';
+$Search::Elasticsearch::Bulk::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::Bulk',
     'Search::Elasticsearch::Role::Is_Sync';
@@ -107,7 +107,7 @@ Search::Elasticsearch::Bulk - A helper module for the Bulk API and for reindexin
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::0_90::Direct::Cluster;
-$Search::Elasticsearch::Client::0_90::Direct::Cluster::VERSION = '1.12';
+$Search::Elasticsearch::Client::0_90::Direct::Cluster::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API::0_90';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -17,7 +17,7 @@ Search::Elasticsearch::Client::0_90::Direct::Cluster - A client for running clus
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::0_90::Direct::Indices;
-$Search::Elasticsearch::Client::0_90::Direct::Indices::VERSION = '1.12';
+$Search::Elasticsearch::Client::0_90::Direct::Indices::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API::0_90';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -17,7 +17,7 @@ Search::Elasticsearch::Client::0_90::Direct::Indices - A client for running inde
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::0_90::Direct;
-$Search::Elasticsearch::Client::0_90::Direct::VERSION = '1.12';
+$Search::Elasticsearch::Client::0_90::Direct::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API::0_90';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -43,6 +43,15 @@ sub _index {
 }
 
 #===================================
+around 'clear_scroll' => sub {
+#===================================
+    my $orig = shift;
+    my ( $self, $params ) = parse_params(@_);
+    $params->{scroll_id}||=delete $params->{body};
+    $orig->( $self, $params );
+};
+
+#===================================
 sub _build__bulk_class {
 #===================================
     my $self = shift;
@@ -110,7 +119,7 @@ Search::Elasticsearch::Client::0_90::Direct - Thin client with full support for
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1050,7 +1059,6 @@ Query string parameters:
     C<routing>,
     C<search_from>,
     C<search_indices>,
-    C<search_query_hint>,
     C<search_scroll>,
     C<search_size>,
     C<search_source>,
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::Direct::Cat;
-$Search::Elasticsearch::Client::Direct::Cat::VERSION = '1.12';
+$Search::Elasticsearch::Client::Direct::Cat::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -28,7 +28,7 @@ Search::Elasticsearch::Client::Direct::Cat - A client for running cat debugging
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -133,6 +133,26 @@ Query string parameters:
 See the L<cat count docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-count.html>
 for more information.
 
+=head2 C<fielddata()>
+
+    say $e->cat->fielddata(
+        fields => 'field' | \@fields    # optional
+    );
+
+Shows the amount of memory used by each of the specified `fields` (or all
+fields) loaded into fielddata.
+
+Query string parameters:
+    C<bytes>,
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat fielddata docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-fielddata.html>
+for more information.
+
 =head2 C<health()>
 
     say $e->cat->health();
@@ -175,7 +195,7 @@ for more information.
 
 =head2 C<master()>
 
-    say $e->cat->indices();
+    say $e->cat->master();
 
 Displays the master’s node ID, bound IP address, and node name.
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::Direct::Cluster;
-$Search::Elasticsearch::Client::Direct::Cluster::VERSION = '1.12';
+$Search::Elasticsearch::Client::Direct::Cluster::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -29,7 +29,7 @@ Search::Elasticsearch::Client::Direct::Cluster - A client for running cluster-le
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -138,7 +138,6 @@ parameter.
 
 Query string parameters:
     C<flat_settings>,
-    <index_templates>,
     C<local>,
     C<master_timeout>
 
@@ -189,8 +188,8 @@ which changes should be made. For instance:
 Query string parameters:
     C<dry_run>,
     C<explain>,
-    C<filter_metadata>,
     C<master_timeout>,
+    C<metric>,
     C<timeout>
 
 See the L<reroute docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-reroute.html>
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::Direct::Indices;
-$Search::Elasticsearch::Client::Direct::Indices::VERSION = '1.12';
+$Search::Elasticsearch::Client::Direct::Indices::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -17,7 +17,7 @@ Search::Elasticsearch::Client::Direct::Indices - A client for running index-leve
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -51,6 +51,25 @@ Query string parameters:
 See the L<create index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-create-index.html>
 for more information.
 
+=head2 C<get()>
+
+    $response = $e->indices->get(
+        index   => 'index'   | \@indices    # optional
+        feature => 'feature' | \@features   # optional
+    );
+
+Returns the aliases, settings, mappings, and warmers for the specified indices.
+The C<feature> parameter can be set to none or more of: C<_settings>, C<_mappings>,
+C<_warmers> and C<_aliases>.
+
+See the L<get index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-get-index.html>.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>
+
 =head2 C<exists()>
 
     $bool = $e->indices->exists(
@@ -144,6 +163,7 @@ Query string parameters:
     C<id>,
     C<id_cache>,
     C<ignore_unavailable>,
+    C<query_cache>,
     C<recycler>
 
 See the L<clear_cache docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-clearcache.html>
@@ -183,7 +203,8 @@ Query string parameters:
     C<expand_wildcards>,
     C<force>,
     C<full>,
-    C<ignore_unavailable>
+    C<ignore_unavailable>,
+    C<wait_if_ongoing>
 
 See the L<flush index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-flush.html>
 for more information.
@@ -202,7 +223,6 @@ Query string parameters:
     C<allow_no_indices>,
     C<expand_wildcards>,
     C<flush>,
-    C<force>,
     C<ignore_unavailable>,
     C<max_num_segments>,
     C<only_expunge_deletes>,
@@ -211,6 +231,41 @@ Query string parameters:
 See the L<optimize index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-optimize.html>
 for more information.
 
+=head2 C<get_upgrade()>
+
+    $response = $e->indices->get_upgrade(
+        index => 'index' | \@indices    # optional
+    );
+
+The C<get_upgrade()> method returns information about which indices need to be
+upgraded, which can be done with the C<upgrade()> method.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<human>,
+    C<ignore_unavailable>
+
+See the L<upgrade docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-upgrade.html>
+for more information.
+
+=head2 C<upgrade()>
+
+    $response = $e->indices->upgrade(
+        index => 'index' | \@indices    # optional
+    );
+
+The C<upgrade()> method upgrades all segments in the specified indices to the latest format.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<wait_for_completion>
+
+See the L<upgrade docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-upgrade.html>
+for more information.
+
 =head1 MAPPING METHODS
 
 =head2 C<put_mapping()>
@@ -359,7 +414,7 @@ for more information.
 =head2 C<get_aliases()>
 
     $result = $e->indices->get_aliases(
-        index   => 'index' | \@indices      # optional
+        index   => 'index' | \@indices,     # optional
         alias   => 'alias' | \@aliases      # optional
     );
 
@@ -376,7 +431,7 @@ for more information.
 =head2 C<put_alias()>
 
     $response = $e->indices->put_alias(
-        index => 'index' | \@indices        # optional,
+        index => 'index' | \@indices,       # required
         name  => 'alias',                   # required
 
         body  => { alias defn }             # optional
@@ -515,6 +570,7 @@ for more information.
 The C<put_template()> method is used to create or update index templates.
 
 Query string parameters:
+    C<create>,
     C<flat_settings>,
     C<master_timeout>,
     C<order>,
@@ -659,6 +715,7 @@ Allowed metrics are:
     C<indexing>,
     C<merge>,
     C<percolate>,
+    C<query_cache>,
     C<refresh>,
     C<search>,
     C<segments>,
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::Direct::Nodes;
-$Search::Elasticsearch::Client::Direct::Nodes::VERSION = '1.12';
+$Search::Elasticsearch::Client::Direct::Nodes::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -17,7 +17,7 @@ Search::Elasticsearch::Client::Direct::Nodes - A client for running node-level r
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -109,6 +109,7 @@ Allowed index metrics are:
     C<indexing>,
     C<merge>,
     C<percolate>,
+    C<query_cache>,
     C<refresh>,
     C<search>,
     C<segments>,
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::Direct::Snapshot;
-$Search::Elasticsearch::Client::Direct::Snapshot::VERSION = '1.12';
+$Search::Elasticsearch::Client::Direct::Snapshot::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -17,7 +17,7 @@ Search::Elasticsearch::Client::Direct::Snapshot - A client for managing snapshot
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -40,7 +40,8 @@ Create a repository for backups.
 
 Query string parameters:
     C<master_timeout>,
-    C<timeout>
+    C<timeout>,
+    C<verify>
 
 See the L<"snapshot/restore docs"|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshot.html>
 for more information.
@@ -60,6 +61,21 @@ Query string parameters:
 See the L<"snapshot/restore docs"|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshot.html>
 for more information.
 
+=head2 C<verify_repository()>
+
+    $e->snapshot->verify_repository(
+        repository  => 'repository' # required
+    );
+
+Verify existing repository.
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>
+
+See the L<"snapshot/restore docs"|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
 =head2 C<delete_repository()>
 
     $e->snapshot->delete_repository(
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::Direct;
-$Search::Elasticsearch::Client::Direct::VERSION = '1.12';
+$Search::Elasticsearch::Client::Direct::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -34,13 +34,15 @@ sub index {
     $self->_index( 'index', $params );
 }
 
+my $index_with_id = { %{ __PACKAGE__->api->{index} }, method => 'PUT' };
+
 #===================================
 sub _index {
 #===================================
     my ( $self, $name, $params ) = @_;
     my $defn = $self->api->{index};
-    unless ( defined $params->{id} and length $params->{id} ) {
-        $defn = { %$defn, method => 'POST' };
+    if ( defined $params->{id} and length $params->{id} ) {
+        $defn = $index_with_id;
     }
     $self->perform_request( { %$defn, name => $name }, $params );
 }
@@ -116,7 +118,7 @@ Search::Elasticsearch::Client::Direct - Thin client with full support for Elasti
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -576,6 +578,8 @@ Query string parameters:
     C<retry_on_conflict>,
     C<routing>,
     C<script>,
+    C<script_id>,
+    C<scripted_upsert>,
     C<timeout>,
     C<timestamp>,
     C<ttl>,
@@ -600,6 +604,7 @@ offsets and payloads for the specified document, assuming that termvectors
 have been enabled.
 
 Query string parameters:
+    C<dfs>,
     C<field_statistics>,
     C<fields>,
     C<offsets>,
@@ -607,6 +612,7 @@ Query string parameters:
     C<payloads>,
     C<positions>,
     C<preference>,
+    C<realtime>,
     C<routing>,
     C<term_statistics>
 
@@ -827,6 +833,7 @@ Query string parameters:
     C<payloads>,
     C<positions>,
     C<preference>,
+    C<realtime>,
     C<routing>,
     C<term_statistics>
 
@@ -889,11 +896,11 @@ Query string parameters:
     C<fields>,
     C<from>,
     C<ignore_unavailable>,
-    C<indices_boost>,
     C<lenient>,
     C<lowercase_expanded_terms>,
     C<preference>,
     C<q>,
+    C<query_cache>,
     C<routing>,
     C<scroll>,
     C<search_type>,
@@ -906,6 +913,7 @@ Query string parameters:
     C<suggest_size>,
     C<suggest_text>,
     C<timeout>,
+    C<track_scores>,
     C<version>
 
 See the L<search reference|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-body.html>
@@ -913,6 +921,31 @@ for more information.
 
 Also see L<Search::Elasticsearch::Transport/send_get_body_as>.
 
+=head2 C<search_exists()>
+
+The C<search_exists()> method is a quick version of search which can be
+used to find out whether there are matching search results or not.
+It doesn't return any results itself.
+
+    $results = $e->search_exists(
+        index   => 'index' | \@indices,     # optional
+        type    => 'type'  | \@types,       # optional
+
+        body    => { search params }        # optional
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<min_score>,
+    C<preference>,
+    C<routing>,
+    C<source>
+
+See the L<search exists reference|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-exists.html>
+for more information.
+
 =head2 C<count()>
 
     $results = $e->count(
@@ -1167,7 +1200,10 @@ Query string parameters:
     C<allow_no_indices>,
     C<expand_wildcards>,
     C<ignore_unavailable>,
+    C<percolate_format>,
     C<percolate_index>,
+    C<percolate_preference>,
+    C<percolate_routing>,
     C<percolate_type>,
     C<preference>,
     C<routing>,
@@ -1315,7 +1351,6 @@ Query string parameters:
     C<routing>,
     C<search_from>,
     C<search_indices>,
-    C<search_query_hint>,
     C<search_scroll>,
     C<search_size>,
     C<search_source>,
@@ -1326,6 +1361,125 @@ Query string parameters:
 See the L<mlt docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-more-like-this.html>
 for more information.
 
+=HEAD1 INDEXED SCRIPT METHODS
+
+If dynamic scripting is enabled, Elasticsearch allows you to store scripts in an internal index known as
+C<.scripts> and reference them by id. The methods to manage indexed scripts are as follows:
+
+=head2 C<put_script()>
+
+    $result  = $e->put_script(
+        lang => 'lang',     # required
+        id   => 'id',       # required
+        body => { script }  # required
+    );
+
+The C<put_script()> method is used to store a script in the C<.scripts> index. For instance:
+
+    $result  = $e->put_scripts(
+        lang => 'groovy',
+        id   => 'hello_world',
+        body => {
+          script => q(return "hello world");
+        }
+    );
+
+Query string parameters:
+    C<op_type>,
+    C<version>,
+    C<version_type>
+
+See the L<indexed scripts docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-scripting.html#_indexed_scripts> for more.
+
+=head2 C<get_script()>
+
+    $script = $e->get_script(
+        lang => 'lang',     # required
+        id   => 'id',       # required
+    );
+
+Retrieve the indexed script from the C<.scripts> index.
+
+Query string parameters:
+    C<version>,
+    C<version_type>
+
+See the L<indexed scripts docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-scripting.html#_indexed_scripts> for more.
+
+=head2 C<delete_script()>
+
+    $script = $e->delete_script(
+        lang => 'lang',     # required
+        id   => 'id',       # required
+    );
+
+Delete the indexed script from the C<.scripts> index.
+
+Query string parameters:
+    C<version>,
+    C<version_type>
+
+See the L<indexed scripts docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-scripting.html#_indexed_scripts> for more.
+
+=HEAD1 INDEXED SEARCH TEMPLATE METHODS
+
+Mustache templates can be used to create search requests.  These templates can
+be stored in the C<.scripts> index and retrieved by ID. The methods to
+manage indexed scripts are as follows:
+
+=head2 C<put_template()>
+
+    $result  = $e->put_template(
+        id   => 'id',                       # required
+        body => { template } || "template"  # required
+    );
+
+The C<put_template()> method is used to store a template in the C<.scripts> index.
+For instance:
+
+    $result  = $e->put_template(
+        id   => 'hello_world',
+        body => {
+          template => {
+            query => {
+              match => {
+                title => "hello world"
+              }
+            }
+          }
+      }
+    );
+
+Query string parameters: None
+
+See the L<indexed search template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-template.html#_pre_registered_template> for more.
+
+=head2 C<get_template()>
+
+    $script = $e->get_template(
+        id   => 'id',       # required
+    );
+
+Retrieve the indexed template from the C<.scripts> index.
+
+Query string parameters:
+    C<version>,
+    C<version_type>
+
+See the L<indexed search template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-template.html#_pre_registered_template> for more.
+
+=head2 C<delete_template()>
+
+    $script = $e->delete_template(
+        id   => 'id',       # required
+    );
+
+Delete the indexed template from the C<.scripts> index.
+
+Query string parameters: None
+
+See the L<indexed search template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-template.html#_pre_registered_template> for more.
+
 =head1 BENCHMARK METHODS
 
 =head2 C<benchmark()>
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Cxn::Factory;
-$Search::Elasticsearch::Cxn::Factory::VERSION = '1.12';
+$Search::Elasticsearch::Cxn::Factory::VERSION = '1.16';
 use Moo;
 use Search::Elasticsearch::Util qw(parse_params load_plugin);
 use namespace::clean;
@@ -48,13 +48,13 @@ Search::Elasticsearch::Cxn::Factory - Used by CxnPools to create new Cxn instanc
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
 This class is used by the L<Search::Elasticsearch::Role::CxnPool> implementations
 to create new L<Search::Elasticsearch::Role::Cxn>-based instances. It holds on
-to all the configuration options passed to L<Elasticsearhch/new()> so
+to all the configuration options passed to L<Elasticsearch/new()> so
 that new Cxns can use them.
 
 It contains no user serviceable parts.
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Cxn::HTTPTiny;
-$Search::Elasticsearch::Cxn::HTTPTiny::VERSION = '1.12';
+$Search::Elasticsearch::Cxn::HTTPTiny::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::Cxn::HTTP',
     'Search::Elasticsearch::Role::Cxn',
@@ -58,10 +58,8 @@ sub _build_handle {
 #===================================
     my $self = shift;
     my %args = ( default_headers => $self->default_headers );
-    if ( $self->is_https ) {
-        require IO::Socket::SSL;
-        $args{SSL_options}{SSL_verify_mode}
-            = IO::Socket::SSL::SSL_VERIFY_NONE();
+    if ( $self->is_https && $self->has_ssl_options ) {
+        $args{SSL_options} = $self->ssl_options;
     }
 
     return HTTP::Tiny->new( %args, %{ $self->handle_args } );
@@ -83,7 +81,7 @@ Search::Elasticsearch::Cxn::HTTPTiny - A Cxn implementation which uses HTTP::Tin
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -131,6 +129,51 @@ From L<Search::Elasticsearch::Role::Cxn>
 
 =back
 
+=head1 SSL/TLS
+
+L<Search::Elasticsearch::Cxn::HTTPTiny> uses L<IO::Socket::SSL> to support
+HTTPS.  By default, no validation of the remote host is performed.
+
+This behaviour can be changed by passing the C<ssl_options> parameter
+with any options accepted by L<IO::Socket::SSL>. For instance, to check
+that the remote host has a trusted certificate, and to avoid man-in-the-middle
+attacks, you could do the following:
+
+    use Search::Elasticsearch;
+    use IO::Socket::SSL;
+
+    my $es = Search::Elasticsearch->new(
+        nodes => [
+            "https://node1.mydomain.com:9200",
+            "https://node2.mydomain.com:9200",
+        ],
+        ssl_options => {
+            SSL_verify_mode     => SSL_VERIFY_PEER,
+            SSL_ca_file         => '/path/to/cacert.pem',
+            SSL_verifycn_scheme => 'http',
+        }
+    );
+
+If you want your client to present its own certificate to the remote
+server, then use:
+
+    use Search::Elasticsearch;
+    use IO::Socket::SSL;
+
+    my $es = Search::Elasticsearch->new(
+        nodes => [
+            "https://node1.mydomain.com:9200",
+            "https://node2.mydomain.com:9200",
+        ],
+        ssl_options => {
+            SSL_verify_mode     => SSL_VERIFY_PEER,
+            SSL_ca_file         => '/path/to/cacert.pem',
+            SSL_verifycn_scheme => 'http',
+            SSL_cert_file       => '/path/to/client.pem',
+            SSL_key_file        => '/path/to/client.pem',
+        }
+    );
+
 =head1 METHODS
 
 =head2 C<perform_request()>
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Cxn::Hijk;
-$Search::Elasticsearch::Cxn::Hijk::VERSION = '1.12';
+$Search::Elasticsearch::Cxn::Hijk::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::Cxn::HTTP',
     'Search::Elasticsearch::Role::Cxn',
@@ -10,7 +10,7 @@ use Try::Tiny;
 use namespace::clean;
 
 has 'connect_timeout' => ( is => 'ro', default => 2 );
-has '_socket_cache' => ( is => 'ro', default => sub { {} } );
+has '_socket_cache' => ( is => 'rw', default => sub { {} } );
 
 my $Cxn_Error = qr/ Connection.(?:timed.out|re(?:set|fused))
                        | connect:.timeout
@@ -74,6 +74,12 @@ sub perform_request {
 }
 
 #===================================
+sub clear_handle {
+#===================================
+    my $self = shift;
+    $self->_socket_cache( {} );
+}
+#===================================
 sub error_from_text {
 #===================================
     local $_ = $_[2];
@@ -108,7 +114,7 @@ Search::Elasticsearch::Cxn::Hijk - A Cxn implementation which uses Hijk
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -163,6 +169,10 @@ From L<Search::Elasticsearch::Role::Cxn>
 
 =back
 
+=head1 SSL/TLS
+
+L<Search::Elasticsearch::Cxn::Hijk> does not support HTTPS.
+
 =head1 METHODS
 
 =head2 C<perform_request()>
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Cxn::LWP;
-$Search::Elasticsearch::Cxn::LWP::VERSION = '1.12';
+$Search::Elasticsearch::Cxn::LWP::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::Cxn::HTTP',
     'Search::Elasticsearch::Role::Cxn',
@@ -70,7 +70,10 @@ sub _build_handle {
         parse_head => 0
     );
     if ( $self->is_https ) {
-        $args{ssl_opts} = { verify_hostname => 0 };
+        $args{ssl_opts}
+            = $self->has_ssl_options
+            ? $self->ssl_options
+            : { verify_hostname => 0 };
     }
     return LWP::UserAgent->new( %args, %{ $self->handle_args } );
 }
@@ -91,7 +94,7 @@ Search::Elasticsearch::Cxn::LWP - A Cxn implementation which uses LWP
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -138,6 +141,53 @@ From L<Search::Elasticsearch::Role::Cxn>
 
 =back
 
+=head1 SSL/TLS
+
+L<Search::Elasticsearch::Cxn::LWP> uses L<IO::Socket::SSL> to support
+HTTPS.  By default, no validation of the remote host is performed.
+
+This behaviour can be changed by passing the C<ssl_options> parameter
+with any options accepted by L<IO::Socket::SSL>. For instance, to check
+that the remote host has a trusted certificate, and to avoid man-in-the-middle
+attacks, you could do the following:
+
+    use Search::Elasticsearch;
+    use IO::Socket::SSL;
+
+    my $es = Search::Elasticsearch->new(
+        cxn   => 'LWP',
+        nodes => [
+            "https://node1.mydomain.com:9200",
+            "https://node2.mydomain.com:9200",
+        ],
+        ssl_options => {
+            SSL_verify_mode     => SSL_VERIFY_PEER,
+            SSL_ca_file         => '/path/to/cacert.pem',
+            SSL_verifycn_scheme => 'http',
+        }
+    );
+
+If you want your client to present its own certificate to the remote
+server, then use:
+
+    use Search::Elasticsearch;
+    use IO::Socket::SSL;
+
+    my $es = Search::Elasticsearch->new(
+        cxn   => 'LWP',
+        nodes => [
+            "https://node1.mydomain.com:9200",
+            "https://node2.mydomain.com:9200",
+        ],
+        ssl_options => {
+            SSL_verify_mode     => SSL_VERIFY_PEER,
+            SSL_ca_file         => '/path/to/cacert.pem',
+            SSL_verifycn_scheme => 'http',
+            SSL_cert_file       => '/path/to/client.pem',
+            SSL_key_file        => '/path/to/client.pem',
+        }
+    );
+
 =head1 METHODS
 
 =head2 C<perform_request()>
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::CxnPool::Sniff;
-$Search::Elasticsearch::CxnPool::Sniff::VERSION = '1.12';
+$Search::Elasticsearch::CxnPool::Sniff::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::CxnPool::Sniff',
     'Search::Elasticsearch::Role::Is_Sync';
@@ -81,7 +81,7 @@ Search::Elasticsearch::CxnPool::Sniff - A CxnPool for connecting to a local clus
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::CxnPool::Static::NoPing;
-$Search::Elasticsearch::CxnPool::Static::NoPing::VERSION = '1.12';
+$Search::Elasticsearch::CxnPool::Static::NoPing::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::CxnPool::Static::NoPing',
     'Search::Elasticsearch::Role::Is_Sync';
@@ -18,7 +18,7 @@ Search::Elasticsearch::CxnPool::Static::NoPing - A CxnPool for connecting to a r
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::CxnPool::Static;
-$Search::Elasticsearch::CxnPool::Static::VERSION = '1.12';
+$Search::Elasticsearch::CxnPool::Static::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::CxnPool::Static',
     'Search::Elasticsearch::Role::Is_Sync';
@@ -50,7 +50,7 @@ Search::Elasticsearch::CxnPool::Static - A CxnPool for connecting to a remote cl
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Error;
-$Search::Elasticsearch::Error::VERSION = '1.12';
+$Search::Elasticsearch::Error::VERSION = '1.16';
 use Moo;
 
 our $DEBUG = 0;
@@ -158,7 +158,7 @@ Search::Elasticsearch::Error - Errors thrown by Search::Elasticsearch
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,11 +1,11 @@
 package Search::Elasticsearch::Logger::LogAny;
-$Search::Elasticsearch::Logger::LogAny::VERSION = '1.12';
+$Search::Elasticsearch::Logger::LogAny::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::Logger';
 use Search::Elasticsearch::Util qw(parse_params to_list);
 use namespace::clean;
 
-use Log::Any();
+use Log::Any 0.15 ();
 use Log::Any::Adapter();
 
 #===================================
@@ -44,7 +44,7 @@ Search::Elasticsearch::Logger::LogAny - A Log::Any-based Logger implementation
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::API::0_90;
-$Search::Elasticsearch::Role::API::0_90::VERSION = '1.12';
+$Search::Elasticsearch::Role::API::0_90::VERSION = '1.16';
 use Moo::Role;
 
 use Search::Elasticsearch::Util qw(throw);
@@ -249,7 +249,7 @@ sub api {
             "min_word_len",           "mlt_fields",
             "percent_terms_to_match", "routing",
             "search_from",            "search_indices",
-            "search_query_hint",      "search_scroll",
+            "search_scroll",
             "search_size",            "search_source",
             "search_type",            "search_types",
             "stop_words",
@@ -310,21 +310,20 @@ sub api {
             [ {}, "_search" ],
         ],
         qs => [
-            "_source",         "_source_exclude",
-            "_source_include", "analyze_wildcard",
-            "analyzer",        "default_operator",
-            "df",              "explain",
-            "fields",          "from",
-            "ignore_indices",  "indices_boost",
-            "lenient",         "lowercase_expanded_terms",
-            "preference",      "q",
-            "routing",         "scroll",
-            "search_type",     "size",
-            "sort",            "source",
-            "stats",           "suggest_field",
-            "suggest_mode",    "suggest_size",
-            "suggest_text",    "timeout",
-            "version",
+            "_source",                  "_source_exclude",
+            "_source_include",          "analyze_wildcard",
+            "analyzer",                 "default_operator",
+            "df",                       "explain",
+            "fields",                   "from",
+            "ignore_indices",           "lenient",
+            "lowercase_expanded_terms", "preference",
+            "q",                        "routing",
+            "scroll",                   "search_type",
+            "size",                     "sort",
+            "source",                   "stats",
+            "suggest_field",            "suggest_mode",
+            "suggest_size",             "suggest_text",
+            "timeout",                  "version",
         ],
     },
 
@@ -953,7 +952,7 @@ Search::Elasticsearch::Role::API::0_90 - This class contains the spec for the El
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::API;
-$Search::Elasticsearch::Role::API::VERSION = '1.12';
+$Search::Elasticsearch::Role::API::VERSION = '1.16';
 use Moo::Role;
 
 use Search::Elasticsearch::Util qw(throw);
@@ -159,6 +159,22 @@ sub api {
         ],
     },
 
+    'delete_script' => {
+        doc    => "modules-scripting",
+        method => "DELETE",
+        parts  => { id => { required => 1 }, lang => { required => 1 } },
+        paths => [ [ { id => 2, lang => 1 }, "_scripts", "{lang}", "{id}" ] ],
+        qs => [ "version", "version_type" ],
+    },
+
+    'delete_template' => {
+        doc    => "search-template",
+        method => "DELETE",
+        parts  => { id => {} },
+        paths  => [ [ { id => 2 }, "_search", "template", "{id}" ] ],
+        qs     => [],
+    },
+
     'exists' => {
         doc    => "docs-get",
         method => "HEAD",
@@ -223,6 +239,13 @@ sub api {
         ],
     },
 
+    'get_script' => {
+        doc   => "modules-scripting",
+        parts => { id => { required => 1 }, lang => { required => 1 } },
+        paths => [ [ { id => 2, lang => 1 }, "_scripts", "{lang}", "{id}" ] ],
+        qs => [ "version", "version_type" ],
+    },
+
     'get_source' => {
         doc   => "docs-get",
         parts => {
@@ -244,6 +267,13 @@ sub api {
         ],
     },
 
+    'get_template' => {
+        doc   => "search-template",
+        parts => { id => { required => 1 } },
+        paths => [ [ { id => 2 }, "_search", "template", "{id}" ] ],
+        qs => [ "version", "version_type" ],
+    },
+
     'index' => {
         body   => { required => 1 },
         doc    => "docs-index_",
@@ -318,10 +348,9 @@ sub api {
             "min_word_length",        "mlt_fields",
             "percent_terms_to_match", "routing",
             "search_from",            "search_indices",
-            "search_query_hint",      "search_scroll",
-            "search_size",            "search_source",
-            "search_type",            "search_types",
-            "stop_words",
+            "search_scroll",          "search_size",
+            "search_source",          "search_type",
+            "search_types",           "stop_words",
         ],
     },
 
@@ -371,7 +400,8 @@ sub api {
             "ids",              "offsets",
             "parent",           "payloads",
             "positions",        "preference",
-            "routing",          "term_statistics",
+            "realtime",         "routing",
+            "term_statistics",
         ],
     },
 
@@ -392,10 +422,11 @@ sub api {
         ],
         qs => [
             "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "percolate_index",
-            "percolate_type",     "preference",
-            "routing",            "version",
-            "version_type",
+            "ignore_unavailable", "percolate_format",
+            "percolate_index",    "percolate_preference",
+            "percolate_routing",  "percolate_type",
+            "preference",         "routing",
+            "version",            "version_type",
         ],
     },
 
@@ -407,6 +438,24 @@ sub api {
         qs     => []
     },
 
+    'put_script' => {
+        body   => { required => 1 },
+        doc    => "modules-scripting",
+        method => "PUT",
+        parts => { id => { required => 1 }, lang => { required => 1 } },
+        paths => [ [ { id => 2, lang => 1 }, "_scripts", "{lang}", "{id}" ] ],
+        qs => [ "op_type", "version", "version_type" ],
+    },
+
+    'put_template' => {
+        body   => { required => 1 },
+        doc    => "search-template",
+        method => "PUT",
+        parts => { id => { required => 1 } },
+        paths => [ [ { id => 2 }, "_search", "template", "{id}" ] ],
+        qs => [],
+    },
+
     'scroll' => {
         body  => {},
         doc   => "search-request-scroll",
@@ -429,22 +478,44 @@ sub api {
             [ {}, "_search" ],
         ],
         qs => [
-            "_source",            "_source_exclude",
-            "_source_include",    "allow_no_indices",
-            "analyze_wildcard",   "analyzer",
-            "default_operator",   "df",
-            "expand_wildcards",   "explain",
-            "fields",             "from",
-            "ignore_unavailable", "indices_boost",
-            "lenient",            "lowercase_expanded_terms",
-            "preference",         "q",
-            "routing",            "scroll",
-            "search_type",        "size",
-            "sort",               "source",
-            "stats",              "suggest_field",
-            "suggest_mode",       "suggest_size",
-            "suggest_text",       "timeout",
-            "version",
+            "_source",                  "_source_exclude",
+            "_source_include",          "allow_no_indices",
+            "analyze_wildcard",         "analyzer",
+            "default_operator",         "df",
+            "expand_wildcards",         "explain",
+            "fields",                   "from",
+            "ignore_unavailable",       "lenient",
+            "lowercase_expanded_terms", "preference",
+            "q",                        "query_cache",
+            "routing",                  "scroll",
+            "search_type",              "size",
+            "sort",                     "source",
+            "stats",                    "suggest_field",
+            "suggest_mode",             "suggest_size",
+            "suggest_text",             "timeout",
+            "track_scores",             "version",
+        ],
+    },
+
+    'search_exists' => {
+        body   => {},
+        doc    => "exists",
+        method => "POST",
+        parts  => { index => { multi => 1 }, type => { multi => 1 } },
+        paths  => [
+            [   { index => 0, type => 1 }, "{index}",
+                "{type}", "_search",
+                "exists",
+            ],
+            [ { type => 1 }, "_all", "{type}", "_search", "exists" ],
+            [ { index => 0 }, "{index}", "_search", "exists" ],
+            [ {}, "_search", "exists" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "min_score",
+            "preference",         "routing",
+            "source",
         ],
     },
 
@@ -516,10 +587,11 @@ sub api {
             ],
         ],
         qs => [
-            "field_statistics", "fields",
-            "offsets",          "parent",
-            "payloads",         "positions",
-            "preference",       "routing",
+            "dfs",       "field_statistics",
+            "fields",    "offsets",
+            "parent",    "payloads",
+            "positions", "preference",
+            "realtime",  "routing",
             "term_statistics",
         ],
     },
@@ -543,7 +615,8 @@ sub api {
             "lang",              "parent",
             "refresh",           "replication",
             "retry_on_conflict", "routing",
-            "script",            "timeout",
+            "script",            "script_id",
+            "scripted_upsert",   "timeout",
             "timestamp",         "ttl",
             "version",           "version_type",
         ],
@@ -579,6 +652,16 @@ sub api {
         qs => [ "h", "help", "local", "master_timeout", "v" ],
     },
 
+    'cat.fielddata' => {
+        doc   => "cat-fielddata",
+        parts => { fields => { multi => 1 } },
+        paths => [
+            [ { fields => 2 }, "_cat", "fielddata", "{fields}" ],
+            [ {}, "_cat", "fielddata" ],
+        ],
+        qs => [ "bytes", "h", "help", "local", "master_timeout", "v" ],
+    },
+
     'cat.health' => {
         doc   => "cat-health",
         parts => {},
@@ -702,11 +785,7 @@ sub api {
         method => "POST",
         parts  => {},
         paths  => [ [ {}, "_cluster", "reroute" ] ],
-        qs     => [
-            "dry_run",         "explain",
-            "filter_metadata", "master_timeout",
-            "timeout",
-        ],
+        qs => [ "dry_run", "explain", "master_timeout", "metric", "timeout" ],
     },
 
     'cluster.state' => {
@@ -760,7 +839,7 @@ sub api {
             "filter",           "filter_cache",
             "filter_keys",      "id",
             "id_cache",         "ignore_unavailable",
-            "recycler",
+            "query_cache",      "recycler",
         ],
     },
 
@@ -788,8 +867,8 @@ sub api {
     'indices.delete' => {
         doc    => "indices-delete-index",
         method => "DELETE",
-        parts  => { index => { multi => 1 } },
-        paths  => [ [ { index => 0 }, "{index}" ] ],
+        parts  => { index => { multi => 1, required => 1 } },
+        paths => [ [ { index => 0 }, "{index}" ] ],
         qs => [ "master_timeout", "timeout" ],
     },
 
@@ -839,7 +918,7 @@ sub api {
     },
 
     'indices.exists' => {
-        doc    => "indices-get-settings",
+        doc    => "indices-exists",
         method => "HEAD",
         parts  => { index => { multi => 1, required => 1 } },
         paths => [ [ { index => 0 }, "{index}" ] ],
@@ -855,8 +934,8 @@ sub api {
         parts  => { index => { multi => 1 }, name => { multi => 1 } },
         paths  => [
             [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ],
-            [ { name  => 1 }, "_alias",  "{name}" ],
             [ { index => 0 }, "{index}", "_alias" ],
+            [ { name  => 1 }, "_alias",  "{name}" ],
         ],
         qs => [
             "allow_no_indices",   "expand_wildcards",
@@ -893,9 +972,25 @@ sub api {
         paths =>
             [ [ { index => 0 }, "{index}", "_flush" ], [ {}, "_flush" ] ],
         qs => [
-            "allow_no_indices", "expand_wildcards",
-            "force",            "full",
-            "ignore_unavailable",
+            "allow_no_indices",   "expand_wildcards",
+            "force",              "full",
+            "ignore_unavailable", "wait_if_ongoing",
+        ],
+    },
+
+    'indices.get' => {
+        doc   => "indices-get-index",
+        parts => {
+            feature => { multi => 1 },
+            index   => { multi => 1, required => 1 }
+        },
+        paths => [
+            [ { feature => 1, index => 0 }, "{index}", "{feature}" ],
+            [ { index => 0 }, "{index}" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
         ],
     },
 
@@ -904,8 +999,8 @@ sub api {
         parts => { index => { multi => 1 }, name => { multi => 1 } },
         paths => [
             [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ],
-            [ { name  => 1 }, "_alias",  "{name}" ],
             [ { index => 0 }, "{index}", "_alias" ],
+            [ { name  => 1 }, "_alias",  "{name}" ],
             [ {}, "_alias" ],
         ],
         qs => [
@@ -919,8 +1014,8 @@ sub api {
         parts => { index => { multi => 1 }, name => { multi => 1 } },
         paths => [
             [ { index => 0, name => 2 }, "{index}", "_aliases", "{name}" ],
-            [ { name  => 1 }, "_aliases", "{name}" ],
             [ { index => 0 }, "{index}",  "_aliases" ],
+            [ { name  => 1 }, "_aliases", "{name}" ],
             [ {}, "_aliases" ],
         ],
         qs => [ "local", "timeout" ],
@@ -960,8 +1055,8 @@ sub api {
         parts => { index => { multi => 1 }, type => { multi => 1 } },
         paths => [
             [ { index => 0, type => 2 }, "{index}", "_mapping", "{type}" ],
-            [ { type  => 1 }, "_mapping", "{type}" ],
             [ { index => 0 }, "{index}",  "_mapping" ],
+            [ { type  => 1 }, "_mapping", "{type}" ],
             [ {}, "_mapping" ],
         ],
         qs => [
@@ -975,8 +1070,8 @@ sub api {
         parts => { index => { multi => 1 }, name => { multi => 1 } },
         paths => [
             [ { index => 0, name => 2 }, "{index}", "_settings", "{name}" ],
-            [ { name  => 1 }, "_settings", "{name}" ],
             [ { index => 0 }, "{index}",   "_settings" ],
+            [ { name  => 1 }, "_settings", "{name}" ],
             [ {}, "_settings" ],
         ],
         qs => [
@@ -994,6 +1089,17 @@ sub api {
         qs => [ "flat_settings", "local" ],
     },
 
+    'indices.get_upgrade' => {
+        doc   => "indices-upgrade",
+        parts => { index => { multi => 1 } },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_upgrade" ], [ {}, "_upgrade" ] ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "human",            "ignore_unavailable",
+        ],
+    },
+
     'indices.get_warmer' => {
         doc   => "indices-warmers",
         parts => {
@@ -1010,8 +1116,8 @@ sub api {
                 "{name}"
             ],
             [ { index => 0, name => 2 }, "{index}", "_warmer", "{name}" ],
-            [ { name  => 1 }, "_warmer", "{name}" ],
             [ { index => 0 }, "{index}", "_warmer" ],
+            [ { name  => 1 }, "_warmer", "{name}" ],
             [ {}, "_warmer" ],
         ],
         qs => [
@@ -1052,11 +1158,12 @@ sub api {
         body   => {},
         doc    => "indices-aliases",
         method => "PUT",
-        parts  => { index => { multi => 1 }, name => { required => 1 } },
-        paths  => [
-            [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ],
-            [ { name => 1 }, "_alias", "{name}" ],
-        ],
+        parts  => {
+            index => { multi    => 1, required => 1 },
+            name  => { required => 1 }
+        },
+        paths =>
+            [ [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ] ],
         qs => [ "master_timeout", "timeout" ],
     },
 
@@ -1098,7 +1205,11 @@ sub api {
         method => "PUT",
         parts => { name => { required => 1 } },
         paths => [ [ { name => 1 }, "_template", "{name}" ] ],
-        qs => [ "flat_settings", "master_timeout", "order", "timeout" ],
+        qs => [
+            "create",         "flat_settings",
+            "master_timeout", "order",
+            "timeout"
+        ],
     },
 
     'indices.put_warmer' => {
@@ -1179,8 +1290,8 @@ sub api {
         parts => { index => { multi => 1 }, metric => { multi => 1 } },
         paths => [
             [ { index => 0, metric => 2 }, "{index}", "_stats", "{metric}" ],
-            [ { metric => 1 }, "_stats",  "{metric}" ],
             [ { index  => 0 }, "{index}", "_stats" ],
+            [ { metric => 1 }, "_stats",  "{metric}" ],
             [ {}, "_stats" ],
         ],
         qs => [
@@ -1212,6 +1323,18 @@ sub api {
         qs => [ "master_timeout", "timeout" ],
     },
 
+    'indices.upgrade' => {
+        doc    => "indices-upgrade",
+        method => "POST",
+        parts  => { index => { multi => 1 } },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_upgrade" ], [ {}, "_upgrade" ] ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "wait_for_completion",
+        ],
+    },
+
     'indices.validate_query' => {
         body  => {},
         doc   => "search-validate",
@@ -1330,7 +1453,7 @@ sub api {
         method => "PUT",
         parts => { repository => { required => 1 } },
         paths => [ [ { repository => 1 }, "_snapshot", "{repository}" ] ],
-        qs => [ "master_timeout", "timeout" ],
+        qs => [ "master_timeout", "timeout", "verify" ],
     },
 
     'snapshot.delete' => {
@@ -1415,6 +1538,16 @@ sub api {
         qs => ["master_timeout"],
     },
 
+    'snapshot.verify_repository' => {
+        doc    => "modules-snapshots",
+        method => "POST",
+        parts  => { repository => { required => 1 } },
+        paths  => [
+            [ { repository => 1 }, "_snapshot", "{repository}", "_verify" ],
+        ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
 #=== AUTOGEN - END ===
 
 );
@@ -1435,7 +1568,7 @@ Search::Elasticsearch::Role::API - This class contains the spec for the Elastics
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Bulk;
-$Search::Elasticsearch::Role::Bulk::VERSION = '1.12';
+$Search::Elasticsearch::Role::Bulk::VERSION = '1.16';
 use Moo::Role;
 requires 'add_action', 'flush';
 
@@ -255,7 +255,7 @@ Search::Elasticsearch::Role::Bulk - Provides common functionality to L<Elasticse
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 AUTHOR
 
@@ -1,9 +1,10 @@
 package Search::Elasticsearch::Role::Client::Direct;
-$Search::Elasticsearch::Role::Client::Direct::VERSION = '1.12';
+$Search::Elasticsearch::Role::Client::Direct::VERSION = '1.16';
 use Moo::Role;
 with 'Search::Elasticsearch::Role::Client';
 use Search::Elasticsearch::Util::API::Path qw(path_handler);
 use Try::Tiny;
+use Package::Stash 0.34 ();
 use namespace::clean;
 
 #===================================
@@ -119,7 +120,7 @@ Search::Elasticsearch::Role::Client::Direct - Request parsing for Direct clients
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Client;
-$Search::Elasticsearch::Role::Client::VERSION = '1.12';
+$Search::Elasticsearch::Role::Client::VERSION = '1.16';
 use Moo::Role;
 use namespace::clean;
 
@@ -28,7 +28,7 @@ Search::Elasticsearch::Role::Client - Provides common functionality for Client i
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Cxn::HTTP;
-$Search::Elasticsearch::Role::Cxn::HTTP::VERSION = '1.12';
+$Search::Elasticsearch::Role::Cxn::HTTP::VERSION = '1.16';
 use Moo::Role;
 
 use URI();
@@ -11,7 +11,9 @@ has 'is_https'           => ( is => 'ro' );
 has 'userinfo'           => ( is => 'ro' );
 has 'max_content_length' => ( is => 'ro' );
 has 'default_headers'    => ( is => 'ro' );
-has 'handle'             => ( is => 'lazy' );
+has 'ssl_options'        => ( is => 'ro', predicate => 'has_ssl_options' );
+has 'handle'             => ( is => 'lazy', clearer => 1 );
+has '_pid'               => ( is => 'rw', default => $$ );
 
 #===================================
 sub protocol     {'http'}
@@ -70,7 +72,7 @@ sub BUILDARGS {
     }
 
     $params->{scheme}          = $scheme;
-    $params->{is_http}         = $scheme eq 'https';
+    $params->{is_https}        = $scheme eq 'https';
     $params->{host}            = $host;
     $params->{port}            = $port;
     $params->{path}            = $path;
@@ -109,6 +111,16 @@ before 'perform_request' => sub {
 };
 
 #===================================
+before 'handle' => sub {
+#===================================
+    my $self = shift;
+    if ( $$ != $self->_pid ) {
+        $self->clear_handle;
+        $self->_pid($$);
+    }
+};
+
+#===================================
 around 'process_response' => sub {
 #===================================
     my ( $orig, $self, $params, $code, $msg, $body, $headers ) = @_;
@@ -155,7 +167,7 @@ Search::Elasticsearch::Role::Cxn::HTTP - Provides common functionality to HTTP C
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -205,6 +217,16 @@ C<userinfo> and C<use_https>:
         nodes       => [ 'search1', 'search2' ]
     )
 
+=head2 C<ssl_options>
+
+By default, all backends that support HTTPS disable verification of
+the host they are connecting to.  Use C<ssl_options> to configure
+the type of verification that you would like the client to perform,
+or to configure the client to present its own certificate.
+
+The values accepted by C<ssl_options> depend on the C<Cxn> class.  See the
+documentation for the C<Cxn> class that you are using.
+
 =head2 C<max_content_length>
 
 By default, Elasticsearch nodes accept a maximum post body of 100MB or
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Cxn;
-$Search::Elasticsearch::Role::Cxn::VERSION = '1.12';
+$Search::Elasticsearch::Role::Cxn::VERSION = '1.16';
 use Moo::Role;
 use Search::Elasticsearch::Util qw(throw);
 use List::Util qw(min);
@@ -137,7 +137,7 @@ sub process_response {
 
     my $error_type = $Code_To_Error{$code};
     unless ($error_type) {
-        if ( defined $body ) {
+        if ( defined $body and length $body ) {
             $msg  = $body;
             $body = undef;
         }
@@ -183,7 +183,7 @@ Search::Elasticsearch::Role::Cxn - Provides common functionality to Cxn implemen
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::CxnPool::Sniff;
-$Search::Elasticsearch::Role::CxnPool::Sniff::VERSION = '1.12';
+$Search::Elasticsearch::Role::CxnPool::Sniff::VERSION = '1.16';
 use Moo::Role;
 with 'Search::Elasticsearch::Role::CxnPool';
 requires 'next_cxn', 'sniff';
@@ -88,7 +88,7 @@ Search::Elasticsearch::Role::CxnPool::Sniff - A CxnPool role for connecting to a
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 CONFIGURATION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::CxnPool::Static::NoPing;
-$Search::Elasticsearch::Role::CxnPool::Static::NoPing::VERSION = '1.12';
+$Search::Elasticsearch::Role::CxnPool::Static::NoPing::VERSION = '1.16';
 use Moo::Role;
 with 'Search::Elasticsearch::Role::CxnPool';
 
@@ -79,7 +79,7 @@ Search::Elasticsearch::Role::CxnPool::Static::NoPing - A CxnPool for connecting
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 AUTHOR
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::CxnPool::Static;
-$Search::Elasticsearch::Role::CxnPool::Static::VERSION = '1.12';
+$Search::Elasticsearch::Role::CxnPool::Static::VERSION = '1.16';
 use Moo::Role;
 with 'Search::Elasticsearch::Role::CxnPool';
 requires 'next_cxn';
@@ -39,7 +39,7 @@ Search::Elasticsearch::Role::CxnPool::Static - A CxnPool role for connecting to
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 METHODS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::CxnPool;
-$Search::Elasticsearch::Role::CxnPool::VERSION = '1.12';
+$Search::Elasticsearch::Role::CxnPool::VERSION = '1.16';
 use Moo::Role;
 use Search::Elasticsearch::Util qw(parse_params);
 use List::Util qw(shuffle);
@@ -134,7 +134,7 @@ Search::Elasticsearch::Role::CxnPool - Provides common functionality to the CxnP
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Is_Sync;
-$Search::Elasticsearch::Role::Is_Sync::VERSION = '1.12';
+$Search::Elasticsearch::Role::Is_Sync::VERSION = '1.16';
 use Moo::Role;
 use namespace::clean;
 
@@ -19,7 +19,7 @@ Search::Elasticsearch::Role::Is_Sync - A role to mark classes which should be us
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 AUTHOR
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Logger;
-$Search::Elasticsearch::Role::Logger::VERSION = '1.12';
+$Search::Elasticsearch::Role::Logger::VERSION = '1.16';
 use Moo::Role;
 
 use URI();
@@ -139,7 +139,7 @@ Search::Elasticsearch::Role::Logger - Provides common functionality to Logger im
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Scroll;
-$Search::Elasticsearch::Role::Scroll::VERSION = '1.12';
+$Search::Elasticsearch::Role::Scroll::VERSION = '1.16';
 use Moo::Role;
 requires '_clear_scroll';
 use Search::Elasticsearch::Util qw(parse_params throw);
@@ -7,18 +7,18 @@ use Scalar::Util qw(weaken blessed);
 use namespace::clean;
 
 has 'es' => ( is => 'ro', required => 1 );
-has 'scroll'         => ( is => 'ro' );
-has 'scroll_in_body' => ( is => 'ro' );
-has 'total'          => ( is => 'rwp' );
-has 'max_score'      => ( is => 'rwp' );
-has 'facets'         => ( is => 'rwp' );
-has 'aggregations'   => ( is => 'rwp' );
-has 'suggest'        => ( is => 'rwp' );
-has 'took'           => ( is => 'rwp' );
-has 'total_took'     => ( is => 'rwp' );
-has 'search_params'  => ( is => 'ro' );
-has 'is_finished'    => ( is => 'rwp', default => '' );
-has '_scroll_id'     => ( is => 'rwp', clearer => 1, predicate => 1 );
+has 'scroll'        => ( is => 'ro' );
+has 'scroll_in_qs'  => ( is => 'ro' );
+has 'total'         => ( is => 'rwp' );
+has 'max_score'     => ( is => 'rwp' );
+has 'facets'        => ( is => 'rwp' );
+has 'aggregations'  => ( is => 'rwp' );
+has 'suggest'       => ( is => 'rwp' );
+has 'took'          => ( is => 'rwp' );
+has 'total_took'    => ( is => 'rwp' );
+has 'search_params' => ( is => 'ro' );
+has 'is_finished'   => ( is => 'rwp', default => '' );
+has '_scroll_id'    => ( is => 'rwp', clearer => 1, predicate => 1 );
 
 #===================================
 sub finish {
@@ -29,18 +29,16 @@ sub finish {
     $self->_clear_scroll;
 }
 
-
-
 #===================================
 sub scroll_request {
 #===================================
     my $self = shift;
     my %args = ( scroll => $self->scroll );
-    if ( $self->scroll_in_body ) {
-        $args{body} = $self->_scroll_id;
+    if ( $self->scroll_in_qs ) {
+        $args{scroll_id} = $self->_scroll_id;
     }
     else {
-        $args{scroll_id} = $self->_scroll_id;
+        $args{body} = $self->_scroll_id;
     }
     $self->es->scroll(%args);
 }
@@ -68,7 +66,7 @@ Search::Elasticsearch::Role::Scroll - Provides common functionality to L<Elastic
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 AUTHOR
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Serializer::JSON;
-$Search::Elasticsearch::Role::Serializer::JSON::VERSION = '1.12';
+$Search::Elasticsearch::Role::Serializer::JSON::VERSION = '1.16';
 use Moo::Role;
 requires 'JSON';
 
@@ -103,7 +103,7 @@ Search::Elasticsearch::Role::Serializer::JSON - A Serializer role for JSON modul
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Serializer;
-$Search::Elasticsearch::Role::Serializer::VERSION = '1.12';
+$Search::Elasticsearch::Role::Serializer::VERSION = '1.16';
 use Moo::Role;
 
 requires qw(encode decode encode_pretty encode_bulk mime_type);
@@ -20,7 +20,7 @@ Search::Elasticsearch::Role::Serializer - An interface for Serializer modules
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Transport;
-$Search::Elasticsearch::Role::Transport::VERSION = '1.12';
+$Search::Elasticsearch::Role::Transport::VERSION = '1.16';
 use Moo::Role;
 
 requires qw(perform_request);
@@ -72,7 +72,7 @@ Search::Elasticsearch::Role::Transport - Transport role providing interface betw
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 AUTHOR
 
@@ -1,7 +1,7 @@
 package Search::Elasticsearch::Scroll;
-$Search::Elasticsearch::Scroll::VERSION = '1.12';
+$Search::Elasticsearch::Scroll::VERSION = '1.16';
 use Moo;
-use Search::Elasticsearch::Util qw(parse_params);
+use Search::Elasticsearch::Util qw(parse_params throw);
 use namespace::clean;
 
 has '_buffer' => ( is => 'ro' );
@@ -13,25 +13,30 @@ with 'Search::Elasticsearch::Role::Is_Sync',
 sub BUILDARGS {
 #===================================
     my ( $class, $params ) = parse_params(@_);
-    my $es             = delete $params->{es};
-    my $scroll         = $params->{scroll} ||= '1m';
-    my $scroll_in_body = delete $params->{scroll_in_body};
-    my $results        = $es->search($params);
+    my $es = delete $params->{es};
+    my $scroll = $params->{scroll} ||= '1m';
+
+    throw( 'Param',
+        'The (scroll_in_body) parameter has been replaced by (scroll_in_qs)' )
+        if exists $params->{scroll_in_body};
+
+    my $scroll_in_qs = delete $params->{scroll_in_qs};
+    my $results      = $es->search($params);
 
     my $total = $results->{hits}{total};
 
     return {
-        es             => $es,
-        scroll         => $scroll,
-        scroll_in_body => $scroll_in_body,
-        aggregations   => $results->{aggregations},
-        facets         => $results->{facets},
-        suggest        => $results->{suggest},
-        took           => $results->{took},
-        total_took     => $results->{took},
-        total          => $total,
-        max_score      => $results->{hits}{max_score},
-        _buffer        => $results->{hits}{hits},
+        es           => $es,
+        scroll       => $scroll,
+        scroll_in_qs => $scroll_in_qs,
+        aggregations => $results->{aggregations},
+        facets       => $results->{facets},
+        suggest      => $results->{suggest},
+        took         => $results->{took},
+        total_took   => $results->{took},
+        total        => $total,
+        max_score    => $results->{hits}{max_score},
+        _buffer      => $results->{hits}{hits},
         $total
         ? ( _scroll_id => $results->{_scroll_id} )
         : ( is_finished => 1 )
@@ -105,9 +110,10 @@ sub _clear_scroll {
     my $scroll_id = $self->_scroll_id or return;
     $self->_clear_scroll_id;
 
-    my %args = $self->scroll_in_body
-        ? ( body => $scroll_id )
-        : ( scroll_id => $scroll_id );
+    my %args
+        = $self->scroll_in_qs
+        ? ( scroll_id => $scroll_id )
+        : ( body => $scroll_id );
     eval { $self->es->clear_scroll(%args) };
 }
 
@@ -123,7 +129,7 @@ Search::Elasticsearch::Scroll - A helper module for scrolled searches
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -274,7 +280,7 @@ are memory constrained, you will need to take this into account.
     my $es = Search::Elasticsearch->new(...);
     my $scroll = $es->scroll_helper(
         scroll         => '1m',            # optional
-        scroll_in_body => 0|1,             # optional
+        scroll_in_qs   => 0|1,             # optional
         %search_params
     );
 
@@ -283,7 +289,7 @@ L<Search::Elasticsearch::Scroll> class and calls L</new()>,
 passing in any arguments.
 
 You can specify a C<scroll> duration (which defaults to C<"1m">) and
-C<scroll_in_body> (which defaults to C<false>). Any other parameters are
+C<scroll_in_qs> (which defaults to C<false>). Any other parameters are
 passed directly to L<Search::Elasticsearch::Client::Direct/search()>.
 
 The C<scroll> duration tells Elasticearch how long it should keep the scroll
@@ -292,13 +298,14 @@ all results, just long enough to process a single B<batch> of results.
 The expiry gets renewed for another C<scroll> period every time new
 a new batch of results is retrieved from the cluster.
 
-By default, the C<scroll_id> is passed in the
-L<scroll|Search::Elasticsearch::Client::Direct/scroll()> request as part
-of the query string. When querying very many indices, the scroll ID can become
-too long for intervening proxies.  To send it in the request body instead,
-set C<scroll_in_body> to a true value.  To send it in the request body
-as a C<POST> request, also set
-L<send_get_body_as|Search::Elasticsearch::Transport/send_get_body_as> to
+By default, the C<scroll_id> is passed as the C<body> to the
+L<scroll|Search::Elasticsearch::Client::Direct/scroll()> request.
+To send it in the query string instead, set C<scroll_in_qs> to a true value,
+but be aware: when querying very many indices, the scroll ID can become
+too long for intervening proxies.
+
+The C<scroll> request uses C<GET> by default.  To use C<POST> instead,
+set L<send_get_body_as|Search::Elasticsearch::Transport/send_get_body_as> to
 C<POST>.
 
 =head2 C<next()>
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Serializer::JSON::Cpanel;
-$Search::Elasticsearch::Serializer::JSON::Cpanel::VERSION = '1.12';
+$Search::Elasticsearch::Serializer::JSON::Cpanel::VERSION = '1.16';
 use Cpanel::JSON::XS;
 use Moo;
 
@@ -20,7 +20,7 @@ Search::Elasticsearch::Serializer::JSON::Cpanel - A JSON Serializer using Cpanel
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Serializer::JSON::PP;
-$Search::Elasticsearch::Serializer::JSON::PP::VERSION = '1.12';
+$Search::Elasticsearch::Serializer::JSON::PP::VERSION = '1.16';
 use Moo;
 use JSON::PP;
 
@@ -23,7 +23,7 @@ Search::Elasticsearch::Serializer::JSON::PP - A JSON Serializer using JSON::PP
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,7 +1,7 @@
 package Search::Elasticsearch::Serializer::JSON::XS;
-$Search::Elasticsearch::Serializer::JSON::XS::VERSION = '1.12';
+$Search::Elasticsearch::Serializer::JSON::XS::VERSION = '1.16';
 use Moo;
-use JSON::XS;
+use JSON::XS 2.26;
 
 has 'JSON' => ( is => 'ro', default => sub { JSON::XS->new->utf8(1) } );
 
@@ -19,7 +19,7 @@ Search::Elasticsearch::Serializer::JSON::XS - A JSON Serializer using JSON::XS
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Serializer::JSON;
-$Search::Elasticsearch::Serializer::JSON::VERSION = '1.12';
+$Search::Elasticsearch::Serializer::JSON::VERSION = '1.16';
 use Moo;
 use JSON::MaybeXS 1.002002 ();
 
@@ -24,7 +24,7 @@ Search::Elasticsearch::Serializer::JSON - The default JSON Serializer, using JSO
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::TestServer;
-$Search::Elasticsearch::TestServer::VERSION = '1.12';
+$Search::Elasticsearch::TestServer::VERSION = '1.16';
 use Moo;
 use Search::Elasticsearch();
 use POSIX 'setsid';
@@ -174,7 +174,7 @@ Search::Elasticsearch::TestServer - A helper class to launch Elasticsearch nodes
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Transport;
-$Search::Elasticsearch::Transport::VERSION = '1.12';
+$Search::Elasticsearch::Transport::VERSION = '1.16';
 use Moo;
 
 use URI();
@@ -73,7 +73,7 @@ Search::Elasticsearch::Transport - Provides interface between the client class a
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Util::API::Path;
-$Search::Elasticsearch::Util::API::Path::VERSION = '1.12';
+$Search::Elasticsearch::Util::API::Path::VERSION = '1.16';
 use strict;
 use warnings;
 use Any::URI::Escape qw(uri_escape);
@@ -66,7 +66,7 @@ Search::Elasticsearch::Util::API::Path - A utility class for converting path tem
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Util::API::QS;
-$Search::Elasticsearch::Util::API::QS::VERSION = '1.12';
+$Search::Elasticsearch::Util::API::QS::VERSION = '1.16';
 use strict;
 use warnings;
 
@@ -20,21 +20,22 @@ our %Handler = (
 );
 
 our %Params = (
-    active_only      => { type => 'bool' },
-    all              => { type => 'bool' },
-    allow_no_indices => { type => 'bool' },
-    analyze_wildcard => { type => 'bool' },
-    analyzer         => { type => 'string' },
-    boost_terms      => { type => 'number' },
-    bytes            => { type => 'enum', options => [ 'b', 'k', 'm', 'g' ] },
+    active_only       => { type => 'bool' },
+    all               => { type => 'bool' },
+    allow_no_indices  => { type => 'bool' },
+    analyze_wildcard  => { type => 'bool' },
+    analyzer          => { type => 'string' },
+    boost_terms       => { type => 'number' },
+    bytes             => { type => 'enum', options => [ 'b', 'k', 'm', 'g' ] },
     char_filters      => { type => 'list' },
     clear             => { type => 'bool' },
     completion        => { type => 'bool' },
     completion_fields => { type => 'list' },
-    consistency       => {
+    consistency => {
         options => [ 'one', 'quorum', 'all' ],
         type    => 'enum'
     },
+    create           => { type => 'bool' },
     default_operator => {
         default => 'OR',
         options => [ 'AND', 'OR' ],
@@ -43,6 +44,7 @@ our %Params = (
     delay            => { type => 'duration' },
     detailed         => { type => 'bool' },
     df               => { type => 'string' },
+    dfs              => { type => 'bool' },
     docs             => { type => 'bool' },
     dry_run          => { type => 'bool' },
     exit             => { type => 'bool' },
@@ -97,7 +99,6 @@ our %Params = (
     index_templates    => { type => 'list' },
     indexing           => { type => 'bool' },
     indices            => { type => 'bool' },
-    indices_boost      => { type => 'list' },
     interval           => { type => 'duration' },
     jvm                => { type => 'bool' },
     lang               => { type => 'string' },
@@ -114,18 +115,25 @@ our %Params = (
     max_query_terms          => { type => 'number' },
     max_word_len             => { type => 'number' },     # depr 0.90
     max_word_length          => { type => 'number' },
-    merge                    => { type => 'bool' },
-    min_doc_freq             => { type => 'number' },
-    min_score                => { type => 'number' },
-    min_term_freq            => { type => 'number' },
-    min_word_len             => { type => 'number' },     # depr 0.90
-    min_word_length          => { type => 'number' },
-    mlt_fields               => { type => 'list' },
-    name                     => { type => 'list' },
-    network                  => { type => 'bool' },
-    offsets                  => { type => 'bool' },
-    only_expunge_deletes     => { type => 'bool' },
-    op_type                  => {
+    metric                   => {
+        type    => 'enum',
+        options => [
+            "_all",          "blocks",      "metadata", "nodes",
+            "routing_table", "master_node", "version"
+        ]
+    },
+    merge                => { type => 'bool' },
+    min_doc_freq         => { type => 'number' },
+    min_score            => { type => 'number' },
+    min_term_freq        => { type => 'number' },
+    min_word_len         => { type => 'number' },    # depr 0.90
+    min_word_length      => { type => 'number' },
+    mlt_fields           => { type => 'list' },
+    name                 => { type => 'list' },
+    network              => { type => 'bool' },
+    offsets              => { type => 'bool' },
+    only_expunge_deletes => { type => 'bool' },
+    op_type              => {
         default => 'index',
         options => [ 'index', 'create' ],
         type    => 'enum'
@@ -136,7 +144,10 @@ our %Params = (
     payloads               => { type => 'bool' },
     percent_terms_to_match => { type => 'number' },
     percolate              => { type => 'string' },
+    percolate_format       => { type => 'string' },
     percolate_index        => { type => 'string' },
+    percolate_preference   => { type => 'string' },
+    percolate_routing      => { type => 'list' },
     percolate_type         => { type => 'string' },
     plugin                 => { type => 'bool' },
     positions              => { type => 'bool' },
@@ -145,6 +156,7 @@ our %Params = (
     pri                    => { type => 'bool' },
     process                => { type => 'bool' },
     q                      => { type => 'string' },
+    query_cache            => { type => 'bool' },
     realtime               => { type => 'bool' },
     recovery               => { type => 'bool' },
     recycler               => { type => 'bool' },
@@ -156,13 +168,14 @@ our %Params = (
     },
     retry_on_conflict => { type => 'number' },
     routing           => { type => 'string' },
-    script            => { type => 'string', },
+    script            => { type => 'string' },
+    script_id         => { type => 'string' },
+    scripted_upsert   => { type => 'bool' },
     scroll            => { type => 'duration' },
     scroll_id         => { type => 'string' },
     search            => { type => 'bool' },
     search_from       => { type => 'number' },
     search_indices    => { type => 'list' },
-    search_query_hint => { type => 'string' },
     search_scroll     => { type => 'string' },
     search_size       => { type => 'number' },
     search_source     => { type => 'string' },
@@ -202,6 +215,7 @@ our %Params = (
     timeout         => { type => 'duration' },
     timestamp       => { type => 'datetime' },
     tokenizer       => { type => 'string' },
+    track_scores    => { type => 'bool' },
     transport       => { type => 'bool' },
     ts              => { type => 'bool' },
     ttl             => { type => 'duration' },
@@ -209,6 +223,7 @@ our %Params = (
     types           => { type => 'list' },
     v               => { type => 'bool' },
     verbose         => { type => 'bool' },
+    verify          => { type => 'bool' },
     version         => { type => 'number' },
     version_type    => {
         type    => 'enum',
@@ -224,7 +239,8 @@ our %Params = (
         options => [ 'green', 'yellow', 'red' ],
         type    => 'enum'
     },
-    warmer => { type => 'bool' }
+    wait_if_ongoing => { type => 'bool' },
+    warmer          => { type => 'bool' }
 );
 
 #===================================
@@ -253,7 +269,7 @@ Search::Elasticsearch::Util::API::QS - A utility class for query string paramete
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Util;
-$Search::Elasticsearch::Util::VERSION = '1.12';
+$Search::Elasticsearch::Util::VERSION = '1.16';
 use Moo;
 use Search::Elasticsearch::Error();
 use Scalar::Util qw(blessed);
@@ -119,7 +119,7 @@ Search::Elasticsearch::Util - A utility class for internal use by Search::Elasti
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 AUTHOR
 
@@ -5,7 +5,7 @@ use Moo 1.003;
 use Search::Elasticsearch::Util qw(parse_params load_plugin);
 use namespace::clean;
 
-our $VERSION = '1.12';
+our $VERSION = '1.16';
 
 my %Default_Plugins = (
     client      => [ 'Search::Elasticsearch::Client',       'Direct' ],
@@ -53,7 +53,7 @@ Search::Elasticsearch - The official client for Elasticsearch
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -0,0 +1,5 @@
+use lib 't/lib';
+
+$ENV{ES_CXN} = 'HTTPTiny';
+do "es_sync_fork.pl" or die $!;
+
@@ -0,0 +1,5 @@
+use lib 't/lib';
+
+$ENV{ES_CXN} = 'LWP';
+do "es_sync_fork.pl" or die $!;
+
@@ -0,0 +1,5 @@
+use lib 't/lib';
+
+$ENV{ES_CXN} = 'Hijk';
+do "es_sync_fork.pl" or die $!;
+
@@ -0,0 +1,5 @@
+use lib 't/lib';
+
+$ENV{ES_CXN} = 'NetCurl';
+do "es_sync_fork.pl" or die $!;
+
@@ -70,12 +70,12 @@ SKIP: {
                 aggs   => { color => { terms => { field => 'color' } } },
             }
         },
-        total        => 50,
-        max_score    => num( 1.6, 0.2 ),
-        aggregations => $es_version ge '1' ? bool(1) : undef,
-        facets       => bool(1),
-        suggest      => bool(1),
-        steps        => [
+        total     => 50,
+        max_score => num( 1.6, 0.5 ),
+        aggs      => bool(1),
+        facets    => bool(1),
+        suggest   => bool(1),
+        steps     => [
             next        => [1],
             next_50     => [49],
             is_finished => 1,
@@ -83,9 +83,9 @@ SKIP: {
     );
 
     test_scroll(
-        "Scroll in body",
-        {   scroll_in_body => 1,
-            body           => {
+        "Scroll in qs",
+        {   scroll_in_qs => 1,
+            body         => {
                 query   => { term => { color => 'red' } },
                 suggest => {
                     mysuggest =>
@@ -95,12 +95,12 @@ SKIP: {
                 aggs   => { color => { terms => { field => 'color' } } },
             }
         },
-        total        => 50,
-        max_score    => num( 1.6, 0.2 ),
-        aggregations => $es_version ge '1' ? bool(1) : undef,
-        facets       => bool(1),
-        suggest      => bool(1),
-        steps        => [
+        total     => 50,
+        max_score => num( 1.6, 0.5 ),
+        aggs      => bool(1),
+        facets    => bool(1),
+        suggest   => bool(1),
+        steps     => [
             next        => [1],
             next_50     => [49],
             is_finished => 1,
@@ -116,15 +116,13 @@ SKIP: {
                         { text => 'green', term => { field => 'color' } }
                 },
                 facets => { color => { terms => { field => 'color' } } },
-                aggs   => { color => { terms => { field => 'color' } } },
             }
         },
-        total        => 100,
-        max_score    => 0,
-        aggregations => $es_version ge '1' ? bool(1) : undef,
-        facets       => bool(1),
-        suggest      => bool(1),
-        steps        => [
+        total     => 100,
+        max_score => 0,
+        facets    => bool(1),
+        suggest   => bool(1),
+        steps     => [
             buffer_size => 0,
             next        => [1],
             buffer_size => 49,
@@ -162,7 +160,8 @@ $es->indices->delete( index => 'test' );
 sub test_scroll {
 #===================================
     my ( $title, $params, %tests ) = @_;
-    delete $params->{body}{aggs} unless $es_version ge '1';
+    delete $params->{body}{ $es_version ge '1' ? 'facets' : 'aggs' };
+
     subtest $title => sub {
         isa_ok my $s
             = Search::Elasticsearch::Scroll->new( es => $es, %$params ),
@@ -170,8 +169,10 @@ sub test_scroll {
 
         is $s->total,             $tests{total},     "$title - total";
         cmp_deeply $s->max_score, $tests{max_score}, "$title - max_score";
-        cmp_deeply $s->facets,    $tests{facets},    "$title - facets";
         cmp_deeply $s->suggest,   $tests{suggest},   "$title - suggest";
+        $es_version ge 1
+            ? cmp_deeply $s->aggregations, $tests{aggs}, "$title - aggs"
+            : cmp_deeply $s->facets, $tests{facets}, "$title - facets";
 
         my $i     = 1;
         my @steps = @{ $tests{steps} };
@@ -13,6 +13,7 @@ my $api = $version =~ /^0.90/ ? '0_90::Direct' : 'Direct';
 my $body     = $ENV{ES_BODY}     || 'GET';
 my $cxn      = $ENV{ES_CXN}      || do "default_cxn.pl" || die $!;
 my $cxn_pool = $ENV{ES_CXN_POOL} || 'Static';
+my $timeout  = $ENV{ES_TIMEOUT}  || 30;
 
 my $es;
 if ( $ENV{ES} ) {
@@ -22,7 +23,8 @@ if ( $ENV{ES} ) {
         cxn              => $cxn,
         cxn_pool         => $cxn_pool,
         client           => $api,
-        send_get_body_as => $body
+        send_get_body_as => $body,
+        request_timeout  => $timeout
     );
     eval { $es->ping; } or do {
         diag $@;
@@ -0,0 +1,42 @@
+use Test::More;
+use POSIX ":sys_wait_h";
+
+my $es        = do "es_sync.pl";
+my $cxn_class = ref $es->transport->cxn_pool->cxns->[0];
+ok $es->info, "$cxn_class - Info before fork";
+
+my $Kids = 4;
+my %pids;
+
+for my $child ( 1 .. $Kids ) {
+    my $pid = fork();
+    if ($pid) {
+        $pids{$pid} = $child;
+        next;
+    }
+    if ( !defined $pid ) {
+        skip "fork() not supported";
+        done_testing;
+        last;
+    }
+
+    for ( 1 .. 100 ) {
+        $es->info;
+    }
+    exit;
+}
+
+my $ok = 0;
+for ( 1 .. 10 ) {
+    my $pid = waitpid( -1, WNOHANG );
+    if ( $pid > 0 ) {
+        delete $pids{$pid};
+        $ok++ unless $?;
+        redo;
+    }
+    last unless keys %pids;
+    sleep 1;
+}
+
+is $ok, $Kids, "$cxn_class - Fork";
+done_testing;
@@ -3,6 +3,8 @@ use warnings;
 use Search::Elasticsearch::Bulk;
 use lib 't/lib';
 
+local $ENV{ES_CXN};
+local $ENV{ES_CXN_POOL};
 my $es = do 'es_sync.pl';
 
 $es->indices->delete( index => 'test', ignore => 404 );
@@ -9,7 +9,7 @@ BEGIN {
 use strict;
 use warnings;
 
-# this test was generated with Dist::Zilla::Plugin::Test::NoTabs 0.07
+# this test was generated with Dist::Zilla::Plugin::Test::NoTabs 0.08
 
 use Test::More 0.88;
 use Test::NoTabs;
@@ -119,6 +119,10 @@ my @files = (
     't/60_Cxn/10_basic.t',
     't/60_Cxn/20_process_response.t',
     't/60_Cxn/30_http.t',
+    't/60_Cxn/40_fork_httptiny.t',
+    't/60_Cxn/41_fork_lwp.t',
+    't/60_Cxn/42_fork_hijk.t',
+    't/60_Cxn/43_fork_netcurl.t',
     't/70_Helper/10_bulk_add_action.t',
     't/70_Helper/20_bulk_helpers.t',
     't/70_Helper/30_bulk_flush.t',
@@ -130,6 +134,7 @@ my @files = (
     't/lib/MockCxn.pm',
     't/lib/default_cxn.pl',
     't/lib/es_sync.pl',
+    't/lib/es_sync_fork.pl',
     't/lib/index_test_data.pl',
     't/release-eol.t',
     't/release-no-tabs.t',