[hunchentoot-devel] Handling Lisp errors.

Victor Kryukov victor.kryukov at gmail.com
Mon Apr 16 00:03:15 UTC 2007


Hello list,

I want to accomplish the following: every time a lisp error happens,
the whole backtrace and some additional information is sent to my mail
account.  The question is, what is the best way to do it with
Hunchentoot? (I do know how to send email messages from lisp with the
help of mel-base).

The second question is: how do you use CLSQL thread-safely with
Hunchentoot / SBCL? SBCL don't provide thread properties, so my first
solution[1] was to create a hash-table and to assign each thread a
connection, to check from every thread whether it already has a
connection, and then to clean that hash-table periodically, closing
connections for dead threads. That worked pretty well, but I was
afraid of exhausting limit of database threads somehow, so I switched
to the second solution.

The second solution[2] is to open new connection every time I need to
save something to database or read something from it, and to close it
right after that. That of course solves connection limit problem
(unless I have very many users simultaneously, which is not expected
in the near term), however it's much slower.

Anybody can share his/her strategy?

Best regards,
Victor.

[1] http://paste.lisp.org/display/39787
(defparameter *database-mutex* (sb-thread:make-mutex :name "database lock"))
(defparameter *threads-connection* (make-hash-table))

(defun setup-connection ()
   (connect '("localhost" "lj" "victor" "victor")
          :database-type :postgresql :if-exists :new))

 (defun db ()
  (handler-case
      (sb-thread:with-mutex (*database-mutex*)
       (or (gethash sb-thread:*current-thread* *threads-connection*)
           (setf (gethash sb-thread:*current-thread* *threads-connection*)
                 (setup-connection))))
    (error () (progn
               (close-old-connections)
               (db)))))

(defun close-old-connections ()
  (maphash #'(lambda (thread connection)
              (unless (sb-thread:thread-alive-p thread)
                (clsql:disconnect :database connection)
                (remhash thread *threads-connection*)))
          *threads-connection*))

 (let ((old-select (symbol-function 'clsql:select)))
    (defun select (&rest args)
     (let ((*default-database* (db)))
       (apply old-select args))))

 (let ((old-insert-records (symbol-function 'insert-records)))
    (defun insert-records (&rest args)
     (apply old-insert-records :database (db) args)))


[2] http://paste.lisp.org/display/39787#1
(defun db ()
  (connect *connection-spec*
           :database-type :postgresql :if-exists :new))

(let ((old-select (symbol-function 'clsql:select)))
   (defun select (&rest args)
     (let ((clsql:*default-database* (db)))
       (prog1
           (apply old-select args)
         (disconnect :database clsql:*default-database*)))))

(let ((old-insert-records (symbol-function 'insert-records)))
   (defun insert-records (&rest args)
     (let ((db (db)))
       (prog1
           (apply old-insert-records :database db args)
         (disconnect :database db)))))



-- 
Yours Sincerely,
Victor Kryukov



More information about the Tbnl-devel mailing list