Bugzilla – Attachment 102816 Details for
Bug 25109
Add execution locking to Koha::Script
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 25109: Add ->new and ->lock_exec to Koha::Script
Bug-25109-Add--new-and--lockexec-to-KohaScript.patch (text/plain), 4.88 KB, created by
Tomás Cohen Arazi (tcohen)
on 2020-04-13 11:49:29 UTC
(
hide
)
Description:
Bug 25109: Add ->new and ->lock_exec to Koha::Script
Filename:
MIME Type:
Creator:
Tomás Cohen Arazi (tcohen)
Created:
2020-04-13 11:49:29 UTC
Size:
4.88 KB
patch
obsolete
>From cc8532af66c44667b0ef5fb1f85bf8be728db27b Mon Sep 17 00:00:00 2001 >From: Tomas Cohen Arazi <tomascohen@theke.io> >Date: Fri, 10 Apr 2020 19:37:31 -0300 >Subject: [PATCH] Bug 25109: Add ->new and ->lock_exec to Koha::Script > >--- > Koha/Script.pm | 97 +++++++++++++++++++++++++++++++++++++++++++++++++ > t/Koha/Script.t | 27 +++++++++++++- > t/Koha/sleep.pl | 19 ++++++++++ > 3 files changed, 142 insertions(+), 1 deletion(-) > create mode 100755 t/Koha/sleep.pl > >diff --git a/Koha/Script.pm b/Koha/Script.pm >index 2126d18506..9cfbc9ecf8 100644 >--- a/Koha/Script.pm >+++ b/Koha/Script.pm >@@ -35,7 +35,12 @@ This class should be used in all scripts. It sets the interface and userenv appr > > =cut > >+use File::Basename; >+use Fcntl qw(:flock); >+ > use C4::Context; >+use Koha::Exceptions; >+use Koha::Exceptions::Exception; > > sub import { > my $class = shift; >@@ -67,6 +72,98 @@ sub import { > } > } > >+=head1 API >+ >+=head2 Class methods >+ >+=head3 new >+ >+ my $script = Koha::Script->new( >+ { >+ script => $0, # mandatory >+ [ lock_name => 'my_script' ] >+ } >+ ); >+ >+Create a new Koha::Script object. The I<script> parameter is mandatory, >+and will usually be passed I<$0> in the caller script. The I<lock_name> >+parameter is optional, and is used to generate the lock file if passed. >+ >+=cut >+ >+sub new { >+ my ($class, $params) = @_; >+ my $script = $params->{script}; >+ >+ Koha::Exceptions::MissingParameter->throw( >+ "The 'script' parameter is mandatory. You should usually pass \$0" >+ ) unless $script; >+ >+ my $self = { script => $script }; >+ $self->{lock_name} = $params->{lock_name} >+ if exists $params->{lock_name} and $params->{lock_name}; >+ >+ bless $self, $class; >+ return $self; >+} >+ >+=head3 lock_exec >+ >+ # die if cannot get the lock >+ try { >+ $script->lock_exec; >+ } >+ catch { >+ die "$_"; >+ }; >+ >+ # wait for the lock to be released >+ $script->lock_exec({ wait => 1 }); >+ >+This method sets an execution lock to prevent concurrent execution of the caller >+script. If passed the I<wait> parameter with a true value, it will make the caller >+wait until it can be granted the lock (flock's LOCK_NB behaviour). It will >+otherwise throw an exception immediately. >+ >+=cut >+ >+sub lock_exec { >+ my ($self, $params) = @_; >+ >+ $self->_initialize_locking >+ unless $self->{lock_file}; >+ >+ my $lock_params = ($params->{wait}) ? LOCK_EX : LOCK_EX | LOCK_NB; >+ >+ open our $lock_handle, '>', $self->{lock_file} >+ or Koha::Exceptions::Exception->throw("Unable to open the lock file ".$self->{lock_file}.": $!"); >+ $self->{lock_handle} = $lock_handle; >+ flock( $lock_handle, $lock_params ) >+ or Koha::Exceptions::Exception->throw("Unable to acquire the lock ".$self->{lock_file}.": $!"); >+} >+ >+=head2 Internal methods >+ >+=head3 _initialize_locking >+ >+ $self->_initialize_locking >+ >+This method initializes the locking configuration. >+ >+=cut >+ >+sub _initialize_locking { >+ my ($self) = @_; >+ >+ my $lock_dir = C4::Context->config('lock_dir') >+ // C4::Context->temporary_directory(); >+ >+ my $lock_name = $self->{lock_name} // fileparse( $self->{script} ); >+ $self->{lock_file} = "$lock_dir/$lock_name"; >+ >+ return $self; >+} >+ > =head1 AUTHOR > > Martin Renvoize <martin.renvoize@ptfs-europe.com> >diff --git a/t/Koha/Script.t b/t/Koha/Script.t >index 778693b607..b5853282e8 100644 >--- a/t/Koha/Script.t >+++ b/t/Koha/Script.t >@@ -17,10 +17,13 @@ > > use Modern::Perl; > >-use Test::More tests => 3; >+use Test::More tests => 4; >+use Test::Exception; > > BEGIN { use_ok('Koha::Script') } > >+use File::Basename; >+ > use C4::Context; > > my $userenv = C4::Context->userenv; >@@ -44,4 +47,26 @@ is_deeply( > my $interface = C4::Context->interface; > is( $interface, 'commandline', "Context interface set correctly with no flags" ); > >+subtest 'lock_exec() tests' => sub { >+ plan tests => 2; >+ >+ # Launch the sleep script >+ my $pid = fork(); >+ if ( $pid == 0 ) { >+ system( dirname(__FILE__) . '/sleep.pl 2>&1' ); >+ exit; >+ } >+ >+ sleep 1; # Make sure we start after the fork >+ my $command = dirname(__FILE__) . '/sleep.pl'; >+ my $result = `$command 2>&1`; >+ >+ like( $result, qr{Unable to acquire the lock.*}, 'Exception found' ); >+ >+ throws_ok >+ { Koha::Script->new({ lock_name => 'blah' }); } >+ 'Koha::Exceptions::MissingParameter', >+ 'Not passing the "script" parameter makes it raise an exception'; >+}; >+ > 1; >diff --git a/t/Koha/sleep.pl b/t/Koha/sleep.pl >new file mode 100755 >index 0000000000..009b4034dc >--- /dev/null >+++ b/t/Koha/sleep.pl >@@ -0,0 +1,19 @@ >+#!/usr/bin/perl >+ >+use Modern::Perl; >+ >+use Koha::Script; >+use Fcntl qw(:flock); >+use Try::Tiny; >+ >+# # Lock execution >+my $script = Koha::Script->new({ script => 'sleep.pl' }); >+ >+$script->lock_exec; >+ >+# Sleep for a while, we need to force the concurrent access to the >+# lock file >+sleep 2; >+ >+# Normal exit >+1; >-- >2.26.0
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 25109
:
102757
|
102758
|
102759
|
102760
|
102761
|
102762
|
102814
|
102815
|
102816
|
102817
|
102840
|
102841
|
102842
|
102843
|
102856
|
102887
|
102904
|
102905
|
102906
|
102907
|
102908
|
102909