From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by olra.theworths.org (Postfix) with ESMTP id 5E55B431FBC for ; Tue, 23 Feb 2010 08:33:06 -0800 (PST) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org X-Spam-Flag: NO X-Spam-Score: -1.249 X-Spam-Level: X-Spam-Status: No, score=-1.249 tagged_above=-999 required=5 tests=[AWL=-1.350, BAYES_50=0.001, RDNS_DYNAMIC=0.1] autolearn=no Received: from olra.theworths.org ([127.0.0.1]) by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id oqouYxszil63 for ; Tue, 23 Feb 2010 08:33:04 -0800 (PST) Received: from hackervisions.org (67-207-143-141.slicehost.net [67.207.143.141]) by olra.theworths.org (Postfix) with ESMTP id 2E31B431FAE for ; Tue, 23 Feb 2010 08:33:04 -0800 (PST) Received: from john-marshall.sflc.info ([216.27.154.200] helo=wyzanski.hackervisions.org) by hv with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.69) (envelope-from ) id 1Njxh0-00031D-BS; Tue, 23 Feb 2010 11:33:02 -0500 Date: Tue, 23 Feb 2010 11:32:51 -0500 Message-ID: <87vddnlxos.wl%james@hackervisions.org> From: James Vasile To: notmuch@notmuchmail.org X-Mailer: Wanderlust/2.15.6 User-Agent: SEMI/1.14.6 (Maruoka) FLIM/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL/10.7 Emacs/23.1 (i486-pc-linux-gnu) MULE/6.0 (HANACHIRUSATO) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Subject: [PATCH] Calls to notmuch get queued and executed asynchronously. X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Feb 2010 16:33:06 -0000 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 *\"." + (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