unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
* [PATCH] Calls to notmuch get queued and executed asynchronously.
@ 2010-02-23 16:32 James Vasile
  2010-02-24 19:28 ` James Vasile
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: James Vasile @ 2010-02-23 16:32 UTC (permalink / raw)
  To: notmuch

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@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

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2012-10-12 16:58 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-02-23 16:32 [PATCH] Calls to notmuch get queued and executed asynchronously James Vasile
2010-02-24 19:28 ` James Vasile
2011-10-21 20:50 ` Daniel Schoepe
2011-12-30 10:52   ` David Edmondson
2011-12-30 19:21     ` Aaron Ecay
2012-01-03 10:58       ` David Edmondson
2012-10-12  2:21 ` Ethan Glasser-Camp
2012-10-12 16:58   ` David Bremner

Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).