-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
import.lisp
80 lines (70 loc) · 2.92 KB
/
import.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
(in-package #:org.shirakumo.radiance.studio)
(defvar *import-jobs* (make-hash-table :test 'eql))
(defun import-job (user)
(gethash (user:id user) *import-jobs*))
(defun (setf import-job) (job user)
(if job
(setf (gethash (user:id user) *import-jobs*) job)
(remhash (user:id user) *import-jobs*)))
(defclass import-job ()
((thread :initform NIL :accessor thread)
(status :initform :created :accessor status)
(user :initarg :user :accessor user)
(start-time :initform (get-universal-time) :accessor start-time)
(results :initform () :accessor results))
(:default-initargs :user (error "USER required.")))
(defmethod run-import :around ((job import-job))
(setf (status job) :running)
(handler-bind ((error (lambda (e) (maybe-invoke-debugger e 'abort-job))))
(restart-case
(prog1 (call-next-method)
(setf (status job) :completed))
(abort-job ()
:report "Abort the import job."
(setf (status job) :aborted)))))
(defmethod start-import ((job import-job))
(when (and (thread job) (bt:thread-alive-p (thread job)))
(error "Job already started."))
(when (and (import-job (user job))
(case (status (import-job (user job)))
((:created :running) T)))
(error "A job for this user is already running."))
(setf (import-job (user job)) job)
(setf (thread job) (bt:make-thread (lambda () (run-import job))
:name (format NIL "~d import job" (user job))))
job)
(defmethod stop-import ((job import-job))
(when (and (thread job) (bt:thread-alive-p (thread job)))
(let ((thread (shiftf (thread job) NIL)))
(loop repeat 100
while (bt:thread-alive-p thread)
do (sleep 0.001)
finally (when (bt:thread-alive-p thread)
(bt:interrupt-thread thread (lambda () (invoke-restart 'abort-job))))))
(setf (import-job (user job)) NIL))
job)
(define-page import-overview "studio/^import$" (:clip "import.ctml")
(check-permitted :import)
(r-clip:process
T :author (user:username (auth:current))
:job (import-job (auth:current))))
(define-api studio/import/status () ()
(check-permitted :import)
(let ((job (import-job (auth:current))))
(api-output (when job
(mktable :status (status job)
:user (user job)
:start-time (start-time job)
:results (mapcar #'upload->table (results job)))))))
(define-api studio/import/stop () ()
(check-permitted :import)
(let ((job (import-job (auth:current))))
(cond (job
(stop-import job)
(if (string= "true" (post/get "browser"))
(redirect (referer))
(api-output T :message "Import job stopped.")))
(T
(if (string= "true" (post/get "browser"))
(redirect (referer))
(api-output NIL :message "No import job active."))))))