The Rapido ILL plugin [1] has a simple `after_hold_action` hook that checks if the current hold is linked to an ILL request [2], and in the positive case, it inserts a row on a `task_queue` table for the action to be processed asynchronously by a separate daemon/worker. Even though the plugin itself is not doing any heavy action on the DB, this causes DB locks that are easily reproducible. This seems to be a core Koha issue as it makes the holds cancelling process (and probably others) rather fragile. To reproduce: 1. Clone Rapido ILL: $ mkdir -p ~/git/koha-plugins && cd ~/git/koha-plugins $ git clone https://github.com/bywatersolutions/koha-plugin-rapido-ill.git rapido-ill 2. Start a KTD instance: $ ktd --proxy --name rapido --single-plugin ~/git/koha-plugins/rapido-ill up -d $ ktd --name rapido --wait-ready 200 3. Install the plugin config $ ktd --name rapido --shell k$ cd /kohadevbox/plugins/rapido-ill/scripts k$ perl bootstrap_rapido_testing.pl k$ restart_all 4. Create a hold for a known patron 5. Run this: k$ perl -e 'use Carp::Always; use Koha::Holds; my $hold = Koha::Holds->find(1);$hold->cancel({cancellation_reason => "OVER_365"})' => FAIL: It takes a while! It eventually fails with a lock wait timeout!: ``` C4::Reserves::_FixPriority(): DBI Exception: DBD::mysql::st execute failed: Lock wait timeout exceeded; try restarting transaction at /kohadevbox/koha/Koha/Hold.pm line 933 ``` => FACTS: There's a hold, being cancelled. There is no ILL request on the system. The only thing that is happening is that the plugin hook is being called, and is doing this query: ``` MariaDB [koha_cuyahoga]> SELECT me.* FROM illrequests me JOIN illrequestattributes ON illrequestattributes.illrequest_id = me.illrequest_id WHERE illrequestattributes.type = 'hold_id' AND illrequestattributes.value = '1' AND me.backend = 'RapidoILL'; Empty set (0.001 sec) ``` Moving the plugin hook outside the transaction fixes it. [1] https://github.com/bywatersolutions/koha-plugin-rapido-ill [2] Linked means checking if it has an extended attribute with the hold_id value. No FK checks.