File Coverage

blib/lib/DBIx/BatchChunker/LoopState.pm
Criterion Covered Total %
statement 43 43 100.0
branch 2 2 100.0
condition n/a
subroutine 13 13 100.0
pod n/a
total 58 58 100.0


line stmt bran cond sub pod time code
1             package DBIx::BatchChunker::LoopState;
2              
3             our $AUTHORITY = 'cpan:GSG';
4             # ABSTRACT: Loop state object for DBIx::BatchChunker
5 6     6   41 use version;
  6         12  
  6         63  
6             our $VERSION = 'v0.941.0'; # VERSION
7              
8 6     6   494 use Moo;
  6         14  
  6         56  
9 6     6   2007 use MooX::StrictConstructor;
  6         13  
  6         62  
10              
11 6     6   5559 use Types::Standard qw( InstanceOf ArrayRef HashRef Int Str Num Maybe );
  6         14  
  6         289  
12 6     6   8976 use Types::Numbers qw( UnsignedInt PositiveNum PositiveOrZeroNum FloatSafeNum );
  6         13  
  6         51  
13 6     6   5224 use Type::Utils;
  6         14  
  6         46  
14              
15 6     6   8203 use Math::BigInt upgrade => 'Math::BigFloat';
  6         13  
  6         63  
16 6     6   2189 use Math::BigFloat;
  6         60  
  6         33  
17 6     6   3190 use Time::HiRes qw( time );
  6         18  
  6         39  
18              
19             # Don't export the above, but don't conflict with StrictConstructor, either
20 6     6   498 use namespace::clean -except => [qw< new meta >];
  6         12  
  6         78  
21              
22             #pod =encoding utf8
23             #pod
24             #pod =head1 SYNOPSIS
25             #pod
26             #pod sub chunk_method {
27             #pod my ($bc, $rs) = @_;
28             #pod
29             #pod my $loop_state = $bc->loop_state;
30             #pod # introspect stuff
31             #pod }
32             #pod
33             #pod =head1 DESCRIPTION
34             #pod
35             #pod This is the loop state object used during BatchChunker runs. It only exists within the
36             #pod BatchChunker execution loop, and would generally only be accessible through the coderef
37             #pod or method referenced within that loop.
38             #pod
39             #pod This is a quasi-private object and its API may be subject to change, but the module is
40             #pod in a pretty stable state at this point. While permissions are available to write to
41             #pod the attributes, it is highly recommended to not do so unless you know exactly what you
42             #pod doing. These are mostly available for introspection of loop progress.
43             #pod
44             #pod =head1 ATTRIBUTES
45             #pod
46             #pod =head2 batch_chunker
47             #pod
48             #pod Reference back to the parent L object.
49             #pod
50             #pod =cut
51              
52             has batch_chunker => (
53             is => 'ro',
54             isa => InstanceOf['DBIx::BatchChunker'],
55             required => 1,
56             weak_ref => 1,
57             );
58              
59             #pod =head2 progress_bar
60             #pod
61             #pod The progress bar being used in the loop. This may be different than
62             #pod L, since it could be auto-generated.
63             #pod
64             #pod If you're trying to access the progress bar for debug or display purposes, it's best to
65             #pod use this attribute:
66             #pod
67             #pod my $progress_bar = $bc->loop_state->progress_bar;
68             #pod $progress_bar->message('Found something here');
69             #pod
70             #pod =cut
71              
72             has progress_bar => (
73             is => 'rw',
74             isa => InstanceOf['Term::ProgressBar'],
75             required => 1,
76             );
77              
78             #pod =head2 timer
79             #pod
80             #pod Timer for debug messages. Always spans the time between debug messages.
81             #pod
82             #pod =cut
83              
84             has timer => (
85             is => 'rw',
86             isa => PositiveNum,
87             default => sub { time() },
88             );
89              
90 1251     1251   23885 sub _mark_timer { shift->timer(time); }
91              
92             #pod =head2 start
93             #pod
94             #pod The real start ID that the loop is currently on. May continue to exist within iterations
95             #pod if chunk resizing is trying to find a valid range. Otherwise, this value will become
96             #pod undef when a chunk is finally processed.
97             #pod
98             #pod =cut
99              
100             has start => (
101             is => 'rw',
102             isa => Maybe[UnsignedInt],
103             lazy => 1,
104             default => sub { shift->batch_chunker->min_id },
105             );
106              
107             #pod =head2 end
108             #pod
109             #pod The real end ID that the loop is currently looking at. This is always redefined at the
110             #pod beginning of the loop.
111             #pod
112             #pod =cut
113              
114             has end => (
115             is => 'rw',
116             isa => UnsignedInt,
117             lazy => 1,
118             default => sub {
119             my $self = shift;
120             $self->start + $self->batch_chunker->chunk_size - 1;
121             },
122             );
123              
124             #pod =head2 prev_end
125             #pod
126             #pod Last "processed" value of L. This also includes skipped blocks. Used in L
127             #pod calculations and to determine if the end of the loop has been reached.
128             #pod
129             #pod =cut
130              
131             has prev_end => (
132             is => 'rw',
133             isa => UnsignedInt,
134             lazy => 1,
135             default => sub { shift->start - 1 },
136             );
137              
138             #pod =head2 last_range
139             #pod
140             #pod A hashref of min/max values used for the bisecting of one block, measured in chunk
141             #pod multipliers. Cleared out after a block has been processed or skipped.
142             #pod
143             #pod =cut
144              
145             has last_range => (
146             is => 'rw',
147             isa => HashRef,
148             default => sub { {} },
149             );
150              
151             #pod =head2 last_timings
152             #pod
153             #pod An arrayref of hashrefs, containing data for the previous 5 runs. This data is used for
154             #pod runtime targeting.
155             #pod
156             #pod =cut
157              
158             has last_timings => (
159             is => 'rw',
160             isa => ArrayRef,
161             default => sub { [] },
162             );
163              
164 4     4   61 sub _reset_last_timings { shift->last_timings([]) }
165              
166             #pod =head2 multiplier_range
167             #pod
168             #pod The range (in units of L) between the start and end IDs. This starts at 1
169             #pod (at the beginning of the loop), but may expand or shrink depending on chunk count checks.
170             #pod Resets after block processing.
171             #pod
172             #pod =cut
173              
174             has multiplier_range => (
175             is => 'rw',
176             isa => FloatSafeNum,
177             lazy => 1,
178             default => sub {
179             shift->batch_chunker->_use_bignums ? Math::BigFloat->new(0) : 0;
180             },
181             );
182              
183             #pod =head2 multiplier_step
184             #pod
185             #pod Determines how fast L increases, so that chunk resizing happens at an
186             #pod accelerated pace. Speeds or slows depending on what kind of limits the chunk count
187             #pod checks are hitting. Resets after block processing.
188             #pod
189             #pod =cut
190              
191             has multiplier_step => (
192             is => 'rw',
193             isa => FloatSafeNum,
194             lazy => 1,
195             default => sub {
196             shift->batch_chunker->_use_bignums ? Math::BigFloat->new(1) : 1;
197             },
198             );
199              
200             #pod =head2 checked_count
201             #pod
202             #pod A check counter to make sure the chunk resizing isn't taking too long. After ten checks,
203             #pod it will give up, assuming the block is safe to process.
204             #pod
205             #pod =cut
206              
207             has checked_count => (
208             is => 'rw',
209             isa => Int,
210             default => 0,
211             );
212              
213             #pod =head2 chunk_size
214             #pod
215             #pod The I chunk size, which might be adjusted by runtime targeting.
216             #pod
217             #pod =cut
218              
219             has chunk_size => (
220             is => 'rw',
221             isa => UnsignedInt,
222             lazy => 1,
223             default => sub { shift->batch_chunker->chunk_size },
224             );
225              
226             #pod =head2 chunk_count
227             #pod
228             #pod Records the results of the C query for chunk resizing.
229             #pod
230             #pod =cut
231              
232             has chunk_count => (
233             is => 'rw',
234             isa => Maybe[UnsignedInt],
235             default => undef,
236             );
237              
238             #pod =head2 prev_check
239             #pod
240             #pod A short string recording what happened during the last chunk resizing check. Exists
241             #pod purely for debugging purposes.
242             #pod
243             #pod =cut
244              
245             has prev_check => (
246             is => 'rw',
247             isa => Str,
248             default => '',
249             );
250              
251             #pod =head2 prev_runtime
252             #pod
253             #pod The number of seconds the previously processed chunk took to run, not including sleep
254             #pod time.
255             #pod
256             #pod =cut
257              
258             has prev_runtime => (
259             is => 'rw',
260             isa => Maybe[PositiveOrZeroNum],
261             default => undef,
262             );
263              
264             sub _reset_chunk_state {
265 502     502   1052 my $ls = shift;
266 502         7915 $ls->start (undef);
267 502         20366 $ls->prev_end($ls->end);
268 502         64455 $ls->_mark_timer;
269              
270 502         30513 $ls->last_range ({});
271 502         19894 $ls->multiplier_range(0);
272 502         20593 $ls->multiplier_step (1);
273 502         19487 $ls->checked_count (0);
274              
275 502 100       20079 if ($ls->batch_chunker->_use_bignums) {
276 55         522 $ls->multiplier_range( Math::BigFloat->new(0) );
277 55         40862 $ls->multiplier_step ( Math::BigFloat->new(1) );
278             }
279             }
280              
281             1;
282              
283             __END__