mirror of
https://github.com/vale981/lack
synced 2025-03-05 09:21:39 -05:00
Bugfix: make it possible to close the DB connection
This commit is contained in:
parent
19b9f1baa3
commit
67f6d4dc9e
1 changed files with 54 additions and 45 deletions
|
@ -19,8 +19,16 @@
|
||||||
:remove-session))
|
:remove-session))
|
||||||
(in-package :lack.middleware.session.store.dbi)
|
(in-package :lack.middleware.session.store.dbi)
|
||||||
|
|
||||||
|
(defmacro with-db-connection (connection store &body body)
|
||||||
|
`(let ((,connection (funcall (dbi-store-connector ,store))))
|
||||||
|
(unwind-protect
|
||||||
|
(progn ,@body)
|
||||||
|
(when (dbi-store-disconnector ,store)
|
||||||
|
(funcall (dbi-store-disconnector ,store) ,connection)))))
|
||||||
|
|
||||||
(defstruct (dbi-store (:include store))
|
(defstruct (dbi-store (:include store))
|
||||||
(connector nil :type function)
|
(connector nil :type function)
|
||||||
|
(disconnector nil)
|
||||||
(serializer (lambda (data)
|
(serializer (lambda (data)
|
||||||
(usb8-array-to-base64-string
|
(usb8-array-to-base64-string
|
||||||
(string-to-utf-8-bytes (prin1-to-string (marshal data))))))
|
(string-to-utf-8-bytes (prin1-to-string (marshal data))))))
|
||||||
|
@ -31,20 +39,20 @@
|
||||||
(table-name "sessions"))
|
(table-name "sessions"))
|
||||||
|
|
||||||
(defmethod fetch-session ((store dbi-store) sid)
|
(defmethod fetch-session ((store dbi-store) sid)
|
||||||
(let* ((conn (funcall (dbi-store-connector store)))
|
(with-db-connection conn store
|
||||||
(query (dbi:prepare conn
|
(let* ((query (dbi:prepare conn
|
||||||
(format nil "SELECT session_data FROM ~A WHERE id = ?"
|
(format nil "SELECT session_data FROM ~A WHERE id = ?"
|
||||||
(dbi-store-table-name store))))
|
(dbi-store-table-name store))))
|
||||||
(result (dbi:fetch (dbi:execute query sid))))
|
(result (dbi:fetch (dbi:execute query sid))))
|
||||||
(if result
|
(if result
|
||||||
(handler-case (funcall (dbi-store-deserializer store) (getf result :|session_data|))
|
(handler-case (funcall (dbi-store-deserializer store) (getf result :|session_data|))
|
||||||
(error (e)
|
(error (e)
|
||||||
(warn "Error (~A) occured while deserializing a session. Ignoring.~2% Data:~% ~A~2% Error:~% ~A"
|
(warn "Error (~A) occured while deserializing a session. Ignoring.~2% Data:~% ~A~2% Error:~% ~A"
|
||||||
(class-name (class-of e))
|
(class-name (class-of e))
|
||||||
(getf result :|session_data|)
|
(getf result :|session_data|)
|
||||||
e)
|
e)
|
||||||
nil))
|
nil))
|
||||||
nil)))
|
nil))))
|
||||||
|
|
||||||
(defun current-timestamp ()
|
(defun current-timestamp ()
|
||||||
(multiple-value-bind (sec min hour date month year)
|
(multiple-value-bind (sec min hour date month year)
|
||||||
|
@ -54,36 +62,37 @@
|
||||||
hour min sec)))
|
hour min sec)))
|
||||||
|
|
||||||
(defmethod store-session ((store dbi-store) sid session)
|
(defmethod store-session ((store dbi-store) sid session)
|
||||||
(let ((conn (funcall (dbi-store-connector store)))
|
(with-db-connection conn store
|
||||||
(serialized-session (funcall (dbi-store-serializer store) session)))
|
(let ((serialized-session (funcall (dbi-store-serializer store) session)))
|
||||||
(dbi:with-transaction conn
|
(dbi:with-transaction conn
|
||||||
(let* ((query (dbi:prepare conn
|
(let* ((query (dbi:prepare conn
|
||||||
(format nil "SELECT session_data FROM ~A WHERE id = ?"
|
(format nil "SELECT session_data FROM ~A WHERE id = ?"
|
||||||
(dbi-store-table-name store))))
|
(dbi-store-table-name store))))
|
||||||
(current-session (getf (dbi:fetch (dbi:execute query sid)) :|session_data|)))
|
(current-session (getf (dbi:fetch (dbi:execute query sid)) :|session_data|)))
|
||||||
(cond
|
(cond
|
||||||
;; Session exists but not changed
|
;; Session exists but not changed
|
||||||
((equal current-session serialized-session))
|
((equal current-session serialized-session))
|
||||||
;; Session exists and is going to be changed
|
;; Session exists and is going to be changed
|
||||||
(current-session
|
(current-session
|
||||||
(dbi:do-sql conn
|
(dbi:do-sql conn
|
||||||
(format nil "UPDATE ~A SET session_data = ?~:[~*~;, updated_at = '~A'~] WHERE id = ?"
|
(format nil "UPDATE ~A SET session_data = ?~:[~*~;, updated_at = '~A'~] WHERE id = ?"
|
||||||
(dbi-store-table-name store)
|
(dbi-store-table-name store)
|
||||||
(dbi-store-record-timestamps store)
|
(dbi-store-record-timestamps store)
|
||||||
(current-timestamp))
|
(current-timestamp))
|
||||||
serialized-session
|
serialized-session
|
||||||
sid))
|
sid))
|
||||||
;; New session
|
;; New session
|
||||||
(t
|
(t
|
||||||
(dbi:do-sql conn (format nil "INSERT INTO ~A (id, session_data~:[~;, created_at, updated_at~]) VALUES (?, ?~:*~:[~*~;, '~A', ~:*'~A'~])"
|
(dbi:do-sql conn (format nil "INSERT INTO ~A (id, session_data~:[~;, created_at, updated_at~]) VALUES (?, ?~:*~:[~*~;, '~A', ~:*'~A'~])"
|
||||||
(dbi-store-table-name store)
|
(dbi-store-table-name store)
|
||||||
(dbi-store-record-timestamps store)
|
(dbi-store-record-timestamps store)
|
||||||
(current-timestamp))
|
(current-timestamp))
|
||||||
sid
|
sid
|
||||||
serialized-session)))))))
|
serialized-session))))))))
|
||||||
|
|
||||||
(defmethod remove-session ((store dbi-store) sid)
|
(defmethod remove-session ((store dbi-store) sid)
|
||||||
(dbi:do-sql (funcall (dbi-store-connector store))
|
(with-db-connection conn store
|
||||||
(format nil "DELETE FROM ~A WHERE id = ?"
|
(dbi:do-sql conn
|
||||||
(dbi-store-table-name store))
|
(format nil "DELETE FROM ~A WHERE id = ?"
|
||||||
sid))
|
(dbi-store-table-name store))
|
||||||
|
sid)))
|
||||||
|
|
Loading…
Add table
Reference in a new issue