View | Details | Raw Unified | Return to bug 28833
Collapse All | Expand All

(-)a/C4/HoldsQueue.pm (-11 / +38 lines)
Lines 30-37 use Koha::Items; Link Here
30
use Koha::Patrons;
30
use Koha::Patrons;
31
use Koha::Libraries;
31
use Koha::Libraries;
32
32
33
use List::Util qw( shuffle );
34
use List::MoreUtils qw( any );
33
use List::MoreUtils qw( any );
34
use List::Util qw( shuffle );
35
use POSIX qw(ceil);
36
use Parallel::ForkManager;
35
37
36
our (@ISA, @EXPORT_OK);
38
our (@ISA, @EXPORT_OK);
37
BEGIN {
39
BEGIN {
Lines 173-188 Top level function that turns reserves into tmp_holdsqueue and hold_fill_targets Link Here
173
=cut
175
=cut
174
176
175
sub CreateQueue {
177
sub CreateQueue {
176
    my $dbh   = C4::Context->dbh;
178
    my $loops = shift || 10;
179
180
    my $dbh = C4::Context->dbh;
177
181
178
    $dbh->do("DELETE FROM tmp_holdsqueue");  # clear the old table for new info
182
    $dbh->do("DELETE FROM tmp_holdsqueue");  # clear the old table for new info
179
    $dbh->do("DELETE FROM hold_fill_targets");
183
    $dbh->do("DELETE FROM hold_fill_targets");
180
184
181
    my $total_bibs            = 0;
182
    my $total_requests        = 0;
183
    my $total_available_items = 0;
184
    my $num_items_mapped      = 0;
185
186
    my $branches_to_use;
185
    my $branches_to_use;
187
    my $transport_cost_matrix;
186
    my $transport_cost_matrix;
188
    my $use_transport_cost_matrix = C4::Context->preference("UseTransportCostMatrix");
187
    my $use_transport_cost_matrix = C4::Context->preference("UseTransportCostMatrix");
Lines 199-217 sub CreateQueue { Link Here
199
198
200
    my $bibs_with_pending_requests = GetBibsWithPendingHoldRequests();
199
    my $bibs_with_pending_requests = GetBibsWithPendingHoldRequests();
201
200
201
    # Split the list of bibs into groups to run in parallel
202
    if ( $loops > 1 ) {
203
        my $bibs_per_chunk = ceil( scalar @$bibs_with_pending_requests / $loops );
204
        my @chunks;
205
206
        push( @chunks, [ splice @$bibs_with_pending_requests, 0, $bibs_per_chunk ] ) while @$bibs_with_pending_requests;
207
        push( @{$chunks[0]}, @$bibs_with_pending_requests ); # Add any remainders to the first parallel process
208
209
        my $pm = Parallel::ForkManager->new($loops);
210
211
        DATA_LOOP:
212
        foreach my $chunk (@chunks) {
213
            my $pid = $pm->start and next DATA_LOOP;
214
            _ProcessBiblios($chunk);
215
            $pm->finish;
216
        }
217
218
        $pm->wait_all_children;
219
    } else {
220
        _ProcessBiblios($bibs_with_pending_requests, $branches_to_use, $transport_cost_matrix);
221
    }
222
}
223
224
=head2 _ProcessBiblios
225
226
=cut
227
228
sub _ProcessBiblios {
229
    my $bibs_with_pending_requests = shift;
230
    my $branches_to_use = shift;
231
    my $transport_cost_matrix = shift;
232
202
    foreach my $biblionumber (@$bibs_with_pending_requests) {
233
    foreach my $biblionumber (@$bibs_with_pending_requests) {
203
        $total_bibs++;
204
        my $hold_requests   = GetPendingHoldRequestsForBib($biblionumber);
234
        my $hold_requests   = GetPendingHoldRequestsForBib($biblionumber);
205
        my $available_items = GetItemsAvailableToFillHoldRequestsForBib($biblionumber, $branches_to_use);
235
        my $available_items = GetItemsAvailableToFillHoldRequestsForBib($biblionumber, $branches_to_use);
206
        $total_requests        += scalar(@$hold_requests);
207
        $total_available_items += scalar(@$available_items);
208
236
209
        my $item_map = MapItemsToHoldRequests($hold_requests, $available_items, $branches_to_use, $transport_cost_matrix);
237
        my $item_map = MapItemsToHoldRequests($hold_requests, $available_items, $branches_to_use, $transport_cost_matrix);
210
        $item_map  or next;
238
        $item_map  or next;
211
        my $item_map_size = scalar(keys %$item_map)
239
        my $item_map_size = scalar(keys %$item_map)
212
          or next;
240
          or next;
213
241
214
        $num_items_mapped += $item_map_size;
215
        CreatePicklistFromItemMap($item_map);
242
        CreatePicklistFromItemMap($item_map);
216
        AddToHoldTargetMap($item_map);
243
        AddToHoldTargetMap($item_map);
217
        if (($item_map_size < scalar(@$hold_requests  )) and
244
        if (($item_map_size < scalar(@$hold_requests  )) and
(-)a/installer/data/mysql/atomicupdate/bug_28833.perl (+9 lines)
Line 0 Link Here
1
$DBversion = 'XXX'; # will be replaced by the RM
2
if( CheckVersion( $DBversion ) ) {
3
    $dbh->do(q{
4
        INSERT IGNORE INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `type` ) VALUES
5
        ('HoldsQueueParallelLoopsCount', '1', NULL, 'Number of parallel loops to use when running the holds queue builder', 'Integer');
6
    });
7
8
    NewVersion( $DBversion, 28833, "Speed up holds queue builder via parallel processing");
9
}
(-)a/installer/data/mysql/mandatory/sysprefs.sql (+1 lines)
Lines 241-246 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
241
('HoldsAutoFillPrintSlip','0',NULL,'If on, hold slip print dialog will be displayed automatically','YesNo'),
241
('HoldsAutoFillPrintSlip','0',NULL,'If on, hold slip print dialog will be displayed automatically','YesNo'),
242
('HoldsLog','0',NULL,'If ON, log create/cancel/suspend/resume actions on holds.','YesNo'),
242
('HoldsLog','0',NULL,'If ON, log create/cancel/suspend/resume actions on holds.','YesNo'),
243
('HoldsNeedProcessingSIP', '0', NULL, 'Require staff to check-in before hold is set to waiting state', 'YesNo' ),
243
('HoldsNeedProcessingSIP', '0', NULL, 'Require staff to check-in before hold is set to waiting state', 'YesNo' ),
244
('HoldsQueueParallelLoopsCount', '1', NULL, 'Number of parallel loops to use when running the holds queue builder', 'Integer'),
244
('HoldsQueueSkipClosed', '0', NULL, 'If enabled, any libraries that are closed when the holds queue is built will be ignored for the purpose of filling holds.', 'YesNo'),
245
('HoldsQueueSkipClosed', '0', NULL, 'If enabled, any libraries that are closed when the holds queue is built will be ignored for the purpose of filling holds.', 'YesNo'),
245
('HoldsSplitQueue','nothing','nothing|branch|itemtype|branch_itemtype','In the staff interface, split the holds view by the given criteria','Choice'),
246
('HoldsSplitQueue','nothing','nothing|branch|itemtype|branch_itemtype','In the staff interface, split the holds view by the given criteria','Choice'),
246
('HoldsToPullStartDate','2',NULL,'Set the default start date for the Holds to pull list to this many days ago','Integer'),
247
('HoldsToPullStartDate','2',NULL,'Set the default start date for the Holds to pull list to this many days ago','Integer'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref (+5 lines)
Lines 74-79 Circulation: Link Here
74
            - pref: HoldsToPullStartDate
74
            - pref: HoldsToPullStartDate
75
              class: integer
75
              class: integer
76
            - day(s) ago. Note that the default end date is controlled by the system preference <a href="/cgi-bin/koha/admin/preferences.pl?op=search&searchfield=ConfirmFutureHolds">ConfirmFutureHolds</a>.
76
            - day(s) ago. Note that the default end date is controlled by the system preference <a href="/cgi-bin/koha/admin/preferences.pl?op=search&searchfield=ConfirmFutureHolds">ConfirmFutureHolds</a>.
77
        -
78
            - When building the holds queue, calculate hold matches using
79
            - pref: HoldsQueueParallelLoopsCount
80
              class: integer
81
            - parallel loop(s). The more loops used, the faster it will calculate and the more computing resources it will use.
77
        -
82
        -
78
            - pref: AllowAllMessageDeletion
83
            - pref: AllowAllMessageDeletion
79
              choices:
84
              choices:
(-)a/misc/cronjobs/holds/build_holds_queue.pl (-2 / +3 lines)
Lines 18-25 BEGIN { Link Here
18
use Koha::Script -cron;
18
use Koha::Script -cron;
19
use C4::HoldsQueue qw(CreateQueue);
19
use C4::HoldsQueue qw(CreateQueue);
20
use C4::Log qw( cronlogaction );
20
use C4::Log qw( cronlogaction );
21
use C4::Context;
21
22
22
cronlogaction();
23
cronlogaction();
23
24
24
CreateQueue();
25
my $loops = C4::Context->preference('HoldsQueueParallelLoopsCount');
26
CreateQueue($loops);
25
27
26
- 

Return to bug 28833