branch: externals/calibre
commit 30ec9ca2da204a4d3bcdb8ea182279df864bcea2
Author: Kjartan Óli Ágústsson <[email protected]>
Commit: Kjartan Óli Ágústsson <[email protected]>

    Use queuing to avoid multiple concurrent calls to calibredb
    
    * calibre-exec.el:
    (calibre-exec--process-sentinel): Move from calibre-library.el
    (calibre-exec--commands, calibre-exec--executing,
    calibre-exec--execute, calibre-exec--next-command,
    calibre-exec--queue-commands, calibre-exec--queue-command,
    calibre-exec--start-execution): Create.
    * calibre-library.el (calibre-library-add-books,
    calibre-library-remove-books): Use calibre-exec--queue-command and
    calibre-exec--start-execution instead of direct calls to
    calibre-library--execute.
    (calibre-library--process-sentinel): Move to calibre-exec.el.
    (calibre-library--execute): Remove.
---
 calibre-exec.el    | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 calibre-library.el | 25 +++--------------
 2 files changed, 84 insertions(+), 21 deletions(-)

diff --git a/calibre-exec.el b/calibre-exec.el
new file mode 100644
index 0000000000..aa34a84123
--- /dev/null
+++ b/calibre-exec.el
@@ -0,0 +1,80 @@
+;;; calibre-exec.el --- Execute operations on a Library  -*- lexical-binding: 
t; -*-
+
+;; Copyright (C) 2023  Kjartan Oli Agustsson
+
+;; This file is part of calibre.el.
+
+;; calibre.el is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; calibre.el is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with calibre.el.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;; This file contains the infrastructure to execute operations, such
+;; as adding, modifying, or removing books, on the active library.
+
+;;; Code:
+(eval-when-compile (require 'cl-macs))
+
+(require 'calibre-db)
+
+(defvar calibre-exec--commands nil)
+(defvar calibre-exec--executing nil)
+(defun calibre-exec--process-sentinel (_ event)
+  "Process filter for Calibre library operations.
+EVENT is the process event, see Info node
+`(elisp)Sentinels'"
+  (if (string= event "finished\n")
+      (calibre-library--refresh t)
+    (error "Calibre process failed %S" event))
+  (if calibre-exec--commands
+      (calibre-exec--next-command)
+    (setf calibre-exec--executing nil)))
+
+(cl-defun calibre-exec--execute (args &optional (sentinel 
#'calibre-exec--process-sentinel))
+  "Execute calibredb with arguments ARGS.
+ARGS should be a list of strings to be passed as arguments to
+calibredb.  SENTINEL is a process sentinel to install."
+  (if (not (executable-find calibre-calibredb-executable))
+      (error "Could not find calibredb")
+    (make-process
+     :name "calibre"
+     :command `(,calibre-calibredb-executable "--with-library" 
,(calibre--library) ,@args)
+     :buffer (get-buffer-create "*calibre*")
+     :sentinel sentinel)))
+
+(defun calibre-exec--next-command ()
+  "Execute the next command in Calibre command if any.
+Commands are stored in `calibre-exec--commands'"
+  (when calibre-exec--commands
+    (let ((command (car calibre-exec--commands)))
+      (setf calibre-exec--commands (cdr calibre-exec--commands))
+      (calibre-exec--execute command))))
+
+(defun calibre-exec--queue-commands (commands)
+  "Queue each calibredb command in COMMANDS for execution.
+COMMANDS should be a list of lists that are valid arguments to
+`calibre-exec--execute'."
+  (setf calibre-exec--commands (append commands calibre-exec--commands)))
+
+(defun calibre-exec--queue-command (command)
+  "Queue COMMAND for execution.
+COMMAND should be a valid argument to `calibre-exec--execute'."
+  (calibre-exec--queue-commands (list command)))
+
+(defun calibre-exec--start-execution ()
+  "Start executing any commands queued."
+  (unless calibre-exec--executing
+    (setf calibre-exec--executing t)
+    (calibre-exec--next-command)))
+
+(provide 'calibre-exec)
+;;; calibre-exec.el ends here
diff --git a/calibre-library.el b/calibre-library.el
index 6167dcd11d..a9f5765b91 100644
--- a/calibre-library.el
+++ b/calibre-library.el
@@ -37,7 +37,9 @@
 
 (defun calibre-library-add-books (files)
   "Add FILES to the Calibre library."
-  (calibre-library--execute `("add" "-r" ,@(mapcar #'expand-file-name files))))
+  (calibre-exec--queue-command
+   `("add" "-r" ,@(mapcar #'expand-file-name files)))
+  (calibre-exec--start-execution))
 
 ;;;###autoload
 (defun calibre-dired-add ()
@@ -49,26 +51,7 @@
 (defun calibre-library-remove-books (books)
   "Remove BOOKS from the Calibre library."
   (let ((ids (mapcar #'int-to-string (mapcar #'calibre-book-id books))))
-    (calibre-library--execute `("remove" ,(string-join ids ",")))))
-
-(defun calibre-library--process-sentinel (_ event)
-  "Process filter for Calibre library operations.
-EVENT is the process event, see Info node
-`(elisp)Sentinels'"
-  (if (string= event "finished\n")
-      (if (get-buffer calibre-library-buffer)
-          (calibre-library--refresh t))
-    (error "Calibre process failed %S" event)))
-
-(cl-defun calibre-library--execute (args &optional (sentinel 
#'calibre-library--process-sentinel))
-  "Execute calibredb with arguments ARGS.
-ARGS should be a list of strings.  SENTINEL is a process sentinel to install."
-  (if (not (executable-find calibre-calibredb-executable))
-      (error "Could not find calibredb")
-    (make-process
-     :name "calibre"
-     :command `(,calibre-calibredb-executable "--with-library" 
,(calibre--library) ,@args)
-     :sentinel sentinel)))
+    (calibre-exec--queue-command `("remove" ,(string-join ids ",")))))
 
 (defun calibre-library-mark-remove (&optional _num)
   "Mark a book for removal and move to the next line."

Reply via email to