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."