[notmuch] [PATCH] Calls to notmuch get queued and executed asynchronously.

James Vasile james at hackervisions.org
Tue Feb 23 08:32:51 PST 2010


Added notmuch-enqueue-asynch to replace calls to
notmuch-call-notmuch-process.  Calls to notmuch are then queued and
executed asynchronously.  If the db is busy and we get an error saying
it was locked, keep trying until the db is no longer busy.  Errors go
in a buffer as per usual.

The only caveat here is that if the db is permanently locked (i.e. the
lock is broken), we just keep on trying forever.  Maybe there should
probably be a maximum number of tries or a timeout, but since 'notmuch
new' can take a long time, it's difficult to come up with a reasonable
limit.
---
 notmuch.el |   57 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index 6482170..7fc63e9 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -302,7 +302,7 @@ pseudoheader summary"
   "Add a tag to the current message."
   (interactive
    (list (notmuch-select-tag-with-completion "Tag to add: ")))
-  (apply 'notmuch-call-notmuch-process
+  (apply 'notmuch-enqueue-asynch
 	 (append (cons "tag"
 		       (mapcar (lambda (s) (concat "+" s)) toadd))
 		 (cons (notmuch-show-get-message-id) nil)))
@@ -315,7 +315,7 @@ pseudoheader summary"
   (let ((tags (notmuch-show-get-tags)))
     (if (intersection tags toremove :test 'string=)
 	(progn
-	  (apply 'notmuch-call-notmuch-process
+	  (apply 'notmuch-enqueue-asynch
 		 (append (cons "tag"
 			       (mapcar (lambda (s) (concat "-" s)) toremove))
 			 (cons (notmuch-show-get-message-id) nil)))
@@ -1374,6 +1374,53 @@ Complete list of currently available key bindings:
   (let ((message-id (notmuch-search-find-thread-id)))
     (notmuch-reply message-id)))
 
+(defun join-string-list (string-list)
+    "Concatenates a list of strings and puts spaces between the
+elements."
+    (mapconcat 'identity string-list " "))
+
+(defvar notmuch-asynch-queue nil)
+(defun notmuch-call-notmuch-process-asynch (&rest args)
+  "Asynchronously invoke \"notmuch\" with the given list of arguments.
+
+Error output from the process will be presented to the user as an
+error and will also appear in a buffer named \"*notmuch <arguments>*\"."
+  (when args
+    (let ((process-connection-type nil)
+	  (buffer-name (format "*notmuch %s*" (join-string-list args))))
+      (when (get-buffer buffer-name)
+	(kill-buffer (get-buffer buffer-name)))
+      (let* ((process-buffer (get-buffer-create buffer-name))
+	     (process (apply 'start-process "notmuch-process" process-buffer
+			     notmuch-command args)))
+	(set-process-sentinel process 'notmuch-call-notmuch-process-asynch-sentinel)))))
+(defun notmuch-enqueue-asynch (&rest args)
+  "Add a call to notmuch to the queue of notmuch calls.
+
+args is a list of arguments to notmuch.  ex: (\"tag\" \"+list\"
+\"to:mylist at example.com\")
+
+Calls to notmuch are queued and called asynchronously."
+  (setq notmuch-asynch-queue (append notmuch-asynch-queue (list args)))
+  (when (= (length notmuch-asynch-queue) 1)
+    (apply 'notmuch-call-notmuch-process-asynch (pop notmuch-asynch-queue))))
+  
+(defun notmuch-call-notmuch-process-asynch-sentinel (process event)
+  "Handle the exit of a notmuch asynch process.
+
+When notmuch is done processing, display the error or kill the
+error buffer.  If the db was busy on the last attempt to execute
+command, try it again."
+  (with-current-buffer (process-buffer process)
+    (goto-char (point-min))
+    (if (= (process-exit-status process) 0)
+	(kill-buffer (buffer-name (process-buffer process)))
+	(if (search-forward "Unable to acquire database write lock" nil t)
+	    (apply 'notmuch-call-notmuch-process-asynch (cdr (process-command process)))
+	    (error (format "%s: %s" (join-string-list (process-command process))
+			   (buffer-string))))))
+  (apply 'notmuch-call-notmuch-process-asynch (pop notmuch-asynch-queue)))
+
 (defun notmuch-call-notmuch-process (&rest args)
   "Synchronously invoke \"notmuch\" with the given list of arguments.
 
@@ -1420,7 +1467,7 @@ The tag is added to messages in the currently selected thread
 which match the current search terms."
   (interactive
    (list (notmuch-select-tag-with-completion "Tag to add: ")))
-  (notmuch-call-notmuch-process "tag" (concat "+" tag) (notmuch-search-find-thread-id))
+  (notmuch-enqueue-asynch "tag" (concat "+" tag) (notmuch-search-find-thread-id))
   (notmuch-search-set-tags (delete-dups (sort (cons tag (notmuch-search-get-tags)) 'string<))))
 
 (defun notmuch-search-remove-tag (tag)
@@ -1430,7 +1477,7 @@ The tag is removed from messages in the currently selected thread
 which match the current search terms."
   (interactive
    (list (notmuch-select-tag-with-completion "Tag to remove: " (notmuch-search-find-thread-id))))
-  (notmuch-call-notmuch-process "tag" (concat "-" tag) (notmuch-search-find-thread-id))
+  (notmuch-enqueue-asynch "tag" (concat "-" tag) (notmuch-search-find-thread-id))
   (notmuch-search-set-tags (delete tag (notmuch-search-get-tags))))
 
 (defun notmuch-search-archive-thread ()
@@ -1511,7 +1558,7 @@ characters as well as `_.+-'.
 	(unless (string-match-p "^[-+][-+_.[:word:]]+$" (car words))
 	  (error "Action must be of the form `+thistag -that_tag'"))
 	(setq words (cdr words))))
-    (apply 'notmuch-call-notmuch-process "tag"
+    (apply 'notmuch-enqueue-asynch "tag"
 	   (append action-split (list notmuch-search-query-string) nil))))
 
 ;;;###autoload
-- 
1.6.3.3



More information about the notmuch mailing list