File Coverage

blib/lib/PGObject/Util/Replication/SMO.pm
Criterion Covered Total %
statement 24 70 34.2
branch 0 6 0.0
condition 0 6 0.0
subroutine 9 21 42.8
pod 11 11 100.0
total 44 114 38.6


line stmt bran cond sub pod time code
1             package PGObject::Util::Replication::SMO;
2              
3 4     4   61190 use 5.006;
  4         20  
4 4     4   25 use strict;
  4         12  
  4         107  
5 4     4   23 use warnings;
  4         14  
  4         114  
6 4     4   1887 use Moo;
  4         42824  
  4         20  
7 4     4   9940 use DBI;
  4         57591  
  4         294  
8 4     4   53 use Carp;
  4         9  
  4         246  
9 4     4   2266 use PGObject::Util::PGConfig;
  4         3945  
  4         119  
10 4     4   1684 use PGObject::Util::Replication::Slot;
  4         96062  
  4         2725  
11              
12             =head1 NAME
13              
14             PGObject::Util::Replication::SMO - Replication Server Management Objects!
15              
16             =head1 VERSION
17              
18             Version 0.01
19              
20             =cut
21              
22             our $VERSION = '0.01';
23              
24              
25             =head1 SYNOPSIS
26              
27             This is intended to be a base class for server management objects for
28             specific roles (master, standby, etc). It consolidates the PostgreSQL
29             logic for these. It is not currently intended to be directly used
30             though it could for basic configuration.
31              
32             use PGObject::Util::Replication::SMO;
33             my $server = PGObject::Util::Replication::SMO->new(); # local pg
34             $server->slots(); # replication slots
35             my $config = $server->config;
36              
37             This module provides a wrapper around the config handlers and replication
38             slots.
39              
40             =head1 PROPERTIES
41              
42             =head2 host
43              
44             Hostname or IP address
45              
46             =head2 port
47              
48             defaults to 5432
49              
50             =head2 user
51              
52             Username for the connection string. If not provided, dbi defaults to the
53             username for the system user of the script running this module
54              
55             =head2 password
56              
57             Password for connecting, if needed based on pg_hba.conf settings
58              
59             =head2 dbname
60              
61             Database name for connecting. Defaults to postgres
62              
63             =head2 autocommit
64              
65             Whether to autocommit statements. This defaults to true.
66              
67             =head2 persist_connect
68              
69             If set, save the connection for repeated use. Defaults to off
70             which means we reconnect for each operation.
71              
72             Set to true if you are doing a lot of operations.
73              
74             =head2 manage_vars
75              
76             This is the variables we read or write. It is intended to be unmodified as it is.
77              
78             =cut manage_vars
79              
80             has host => (is => 'ro');
81             has port => (is => 'ro', default => 5432);
82             has user => (is => 'ro');
83             has password => (is => 'ro');
84             has dbname => (is => 'ro', default => 'postgres');
85             has autocommit => (is => 'ro', default => 1);
86             has persist_connect => (is => 'ro', default => 0);
87             has manage_vars => (is => 'rw', default => sub { _manage_vars() } );
88             has config => (is => 'lazy');
89              
90             sub _manage_vars {
91 2     2   38 return [qw(
92             wal_level fsync synchronous_commit synchronous_standby_names
93             wal_sync_method full_page_writes wal_log_hints wal_compression
94             wal_buffers archive_mode archive_command archive_timeout
95             max_wal_senders max_replication_slots wal_keep_segments
96             wal_sender_timeout track_commit_timestamps
97             )];
98             }
99             sub _build_config {
100 0     0     my ($self) = @_;
101 0           return PGObject::Util::PGConfig->new($self->manage_vars, $self->connect);
102             }
103              
104             =head1 METHDOS
105              
106             =head2 connect
107              
108             Returns a DBI connection to the database and checks to make sure
109             we are not in recovery. If we are in recovery, an exception is thrown.
110              
111             =head2 disconnect
112              
113             Disconnect, if using persist_connect
114              
115             =cut
116              
117             {
118              
119             my $pdbh;
120             sub connect {
121 0     0 1   my ($self) = @_;
122 0 0 0       return $pdbh if $pdbh and $self->persist_connect;
123 0           my $dbh = DBI->connect("dbi:Pg:dbname=" . $self->dbname, $self->user, $self->password, { AutoCommit => $self->autocommit });
124 0           my $sth = $dbh->prepare('select pg_is_in_recovery()');
125 0           $sth->execute;
126 0 0         $pdbh = $dbh if $self->persist_connect;
127 0           return $dbh;
128             }
129             sub disconnect {
130 0 0 0 0 1   $pdbh->disconnect if $pdbh and $pdbh->can('disconnect');
131 0           undef $pdbh;
132             }
133              
134             }
135              
136             =head1 METHODS
137              
138             =head2 is_recovering
139              
140             Returns true if the database is in recovery mode and false if not. Typically
141             in replication environments, standby databases will always be in recovery mode
142             while master systems should generally not be.
143              
144             =cut
145              
146             sub is_recovering {
147 0     0 1   my ($self) = @_;
148 0           my $dbh = $self->dbh();
149 0           my $sth = $dbh->prepare('select pg_is_in_recovery()');
150 0           $sth->execute;
151 0           return ($sth->fetchrow_array)[0];
152             }
153              
154             =head2 can_manage
155              
156             Returns true if the user credentials allow us to create and manage replication slots.
157              
158             This requires either superuser or replication attributes for the user.
159              
160             =cut
161              
162             sub can_manage {
163 0     0 1   my ($self) = @_;
164 0           my $dbh = $self->connect();
165 0           my $sth = $dbh->prepare('select rolsuper or rolreplication from pg_roles where rolname = session_user');
166 0           $sth->execute;
167 0           return ($sth->fetchrow_array())[0];
168             }
169              
170             =head2 slots([prefix])
171              
172             Lists all replication slots, their lags, etc.
173              
174             =cut
175              
176             sub slots {
177 0     0 1   my ($self, $filter) = @_;
178 0           return PGObject::Util::Replication::Slot->all($self->connect, $filter);
179             }
180              
181             =head2 getslot($name)
182              
183             Returns info from a single named slot
184              
185             =cut
186              
187             sub getslot {
188 0     0 1   my ($self, $name) = @_;
189 0           return PGObject::Util::Replication::Slot->get($self->connect, $name);
190             }
191              
192             =head2 addslot
193              
194             Adds a named replication slot
195              
196             =cut
197              
198             sub addslot {
199 0     0 1   my ($self, $name) = @_;
200 0           return PGObject::Util::Replication::Slot->create($self->connect, $name);
201             }
202              
203             =head2 deleteslot($name)
204              
205             Deletes a named replication slot
206              
207             =cut
208              
209             sub deleteslot {
210 0     0 1   my ($self, $name) = @_;
211 0           return PGObject::Util::Replication::Slot->delete($self->connect, $name);
212             }
213              
214             =head2 readconfig
215              
216             Reads all settings from the pg instance.
217              
218             =head2 addconfig
219              
220             Adds one more config setting to the managed list and sets it to the default
221              
222             =head2 setconfig
223              
224             Sets a config value for later config file writing.
225              
226             =head2 configcontents
227              
228             Returns a file of the structure of the config file, based on all managed values.
229              
230             =cut
231              
232             sub readconfig {
233 0     0 1   my ($self) = @_;
234 0           my $dbh = $self->connect;
235 0           my $sth = $dbh->prepare("
236             SELECT name, current_setting(name)
237             FROM pg_settings
238             WHERE name = any(?)");
239 0           $sth->execute($self->manage_vars);
240 0           my @outlist = ();
241 0           my @next;
242 0           push @outlist, @next while @next = $sth->fetchrow_array;
243 0           my %vars = @outlist;
244 0           $self->config->set($_, $vars{$_}) for keys %vars;
245              
246             }
247              
248             sub addconfig {
249 0     0 1   my ($self, $name);
250 0           my $manage_ref = $self->manage_vars;
251 0           push @$manage_ref,$name;
252 0           my $sth = $self->connect->prepare("select current_setting(?)");
253 0           $sth->execute($name);
254 0           $self->config->update({$name => $sth->fetchrow_array});
255             }
256              
257             sub configcontents {
258 0     0 1   my ($self) = @_;
259 0           return $self->config->filecontents();
260             }
261              
262              
263              
264              
265             =head1 AUTHOR
266              
267             Chris Travers, C<< >>
268              
269             =head1 BUGS
270              
271             Please report any bugs or feature requests to C, or through
272             the web interface at L. I will be notified, and then you'll
273             automatically be notified of progress on your bug as I make changes.
274              
275              
276              
277              
278             =head1 SUPPORT
279              
280             You can find documentation for this module with the perldoc command.
281              
282             perldoc PGObject::Util::Replication::SMO
283              
284              
285             You can also look for information at:
286              
287             =over 4
288              
289             =item * RT: CPAN's request tracker (report bugs here)
290              
291             L
292              
293             =item * AnnoCPAN: Annotated CPAN documentation
294              
295             L
296              
297             =item * CPAN Ratings
298              
299             L
300              
301             =item * Search CPAN
302              
303             L
304              
305             =back
306              
307              
308             =head1 ACKNOWLEDGEMENTS
309              
310              
311             =head1 LICENSE AND COPYRIGHT
312              
313             Copyright 2017 Adjust.com
314              
315             This program is distributed under the (Revised) BSD License:
316             L
317              
318             Redistribution and use in source and binary forms, with or without
319             modification, are permitted provided that the following conditions
320             are met:
321              
322             * Redistributions of source code must retain the above copyright
323             notice, this list of conditions and the following disclaimer.
324              
325             * Redistributions in binary form must reproduce the above copyright
326             notice, this list of conditions and the following disclaimer in the
327             documentation and/or other materials provided with the distribution.
328              
329             * Neither the name of Adjust.com
330             nor the names of its contributors may be used to endorse or promote
331             products derived from this software without specific prior written
332             permission.
333              
334             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
335             "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
336             LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
337             A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
338             OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
339             SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
340             LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
341             DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
342             THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
343             (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
344             OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
345              
346              
347             =cut
348              
349             1; # End of PGObject::Util::Replication::SMO