branch: externals/el-job
commit 127b68e005dcecb82518c3cdefb09cc0fdaaa1a0
Author: Martin Edström <meedstro...@gmail.com>
Commit: Martin Edström <meedstro...@gmail.com>

    Release version 1.0.4
---
 el-job.el | 63 +++++++++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 45 insertions(+), 18 deletions(-)

diff --git a/el-job.el b/el-job.el
index f360a0e04c..094d64aa8e 100644
--- a/el-job.el
+++ b/el-job.el
@@ -19,7 +19,7 @@
 ;; URL:              https://github.com/meedstrom/el-job
 ;; Created:          2024-10-30
 ;; Keywords:         processes
-;; Package-Version:  1.0.1
+;; Package-Version:  1.0.4
 ;; Package-Requires: ((emacs "28.1") (compat "30"))
 
 ;;; Commentary:
@@ -558,11 +558,13 @@ This puts them to work.  Each successful child will print 
output
 should trigger `el-job--handle-output'."
   (el-job--with job
       ( .ready .busy .input-sets .result-sets .queued-inputs .cores-to-use
-        .past-elapsed .timestamps .finish-times .id .stderr .timeout )
+        .past-elapsed .timestamps .finish-times .id .stderr .timeout 
.poll-timer )
     (cancel-timer .timeout)
     (setf .result-sets nil)
     (setf .finish-times nil)
-    (let ((splits (el-job--split-optimally .queued-inputs .cores-to-use 
.past-elapsed)))
+    (let ((splits (el-job--split-optimally .queued-inputs
+                                           .cores-to-use
+                                           .past-elapsed)))
       (unless (length< splits (1+ (length .ready)))
         (error "Items split in %d lists, but only %d ready processes"
                (length splits) (length .ready)))
@@ -580,13 +582,45 @@ should trigger `el-job--handle-output'."
           (setf (alist-get proc .input-sets) items)
           (with-current-buffer (process-buffer proc)
             (erase-buffer)
-            (remove-hook 'after-change-functions #'el-job--check-done t)
+            ;; (remove-hook 'after-change-functions #'el-job--check-done t)
             (process-send-string proc (prin1-to-string items))
             (process-send-string proc "\n")
-            (add-hook 'after-change-functions #'el-job--check-done nil t)))))
+            ;; (add-hook 'after-change-functions #'el-job--check-done nil t)
+            ))))
     (setf .queued-inputs nil)
     (plist-put .timestamps :work-begun (current-time))
-    (setf .timeout (run-with-timer 30 nil #'el-job--timeout .stderr))))
+    (setf .poll-timer (run-with-timer 0.05 nil #'el-job--poll 1 .busy))
+    ;; (setf .timeout (run-with-timer 30 nil #'el-job--timeout .stderr))
+    ))
+
+(defun el-job--poll (n bufs)
+  (let (busy-bufs)
+    (save-current-buffer
+      (dolist (buf bufs)
+        (if (not (buffer-live-p))
+            ;; May be intentionally done by an `el-job-disable' call,
+            ;; so not necessarily a problem.
+            (el-job--dbg 2 "Process buffer found killed: %s" buf)
+          (set-buffer buf)
+          (if (eq (char-before) ?\n)
+              (el-job--handle-output)
+            (push buf busy-bufs))))
+
+      ;; Eval to see the full series of timer delays:
+      ;; (--map (/ (float it) (ash 1 5)) (-iterate '1+ 1 42))
+      ;; Or the cumulative sums:
+      ;; (-reductions '+ (--map (/ (float it) (ash 1 5)) (-iterate '1+ 1 42)))
+      (if (and busy-bufs (<= n 42))
+          (setf (el-job:poll-timer el-job-here)
+                (run-with-timer
+                 (/ (float n) (ash 1 5)) nil #'el-job--poll (1+ n) busy-bufs))
+        (let ((desc (or (el-job:id el-job-here)
+                        (format "once-off job that calls %S"
+                                (car (last (el-job:spawn-args 
el-job-here)))))))
+          (el-job-disable el-job-here)
+          (if busy-bufs
+              (message "el-job: Timed out, was busy for 30+ seconds: %s" desc)
+            (el-job--dbg 2 "Reaped idle processes for %s" desc)))))))
 
 (defun el-job--timeout (stderr-buf)
   "Disable job corresponding to STDERR-BUF, and print that it timed out.
@@ -636,7 +670,7 @@ more input in the queue."
        (dolist (proc (append (el-job:busy job)
                              (el-job:ready job)))
          (el-job--unhide-buffer (process-buffer proc))
-         (el-job--kill-quietly proc))
+         (delete-process proc))
        (error "In buffer %s: problems reading child output: %S"
               (current-buffer) err)))
     (when results
@@ -678,25 +712,18 @@ more input in the queue."
 
 This does not deregister the job ID.  That means the next launch with
 same ID still has the benchmarks table and possibly queued input."
-  (el-job--with job (.id .timeout .busy .ready .stderr)
-    (cancel-timer .timeout)
+  (el-job--with job (.id .timeout .busy .ready .stderr .poll-timer)
+    (cancel-timer .timeout)  (el-job.timeout job)
+    (cancel-timer .poll-timer)
     (let ((preserve (and .id (> el-job--debug-level 0))))
       (dolist (proc (append .busy .ready))
         (let ((buf (process-buffer proc)))
-          (el-job--kill-quietly proc)
+          (delete-process proc)
           (and (buffer-live-p buf) (not preserve) (kill-buffer buf))))
       (setf .busy nil)
       (setf .ready nil)
       (and (buffer-live-p .stderr) (not preserve) (kill-buffer .stderr)))))
 
-;; TODO Maybe now we can use only `delete-process' since sentinel is always
-;;      ignore.
-(defun el-job--kill-quietly (proc)
-  "Kill PROC while disabling its sentinel and filter."
-  (set-process-filter proc #'ignore)
-  (set-process-sentinel proc #'ignore)
-  (delete-process proc))
-
 (defun el-job--unhide-buffer (buffer)
   "Rename BUFFER to omit initial space, and return the new name."
   (with-current-buffer buffer

Reply via email to