git.fiddlerwoaroof.com
Raw Blame History
(defpackage :slacker.montezuma-store
  (:use :cl :alexandria :serapeum :fw.lu)
  (:export
   #:montezuma-store
   #:search-index
   #:retire-open-indices))
(in-package :slacker.montezuma-store)

(defclass montezuma-store ()
  ((%indexes :reader indexes
	     :initform (make-hash-table :test #'equal :synchronized t))
   (%montezuma-index-path :reader index-path
			  :initarg :index-path))
  (:default-initargs :index-path nil))

(defun retire-open-indices (client)
  (sb-ext:with-locked-hash-table ((indexes client))
    (let ((old-indexes (indexes client)))
      (setf (slot-value client '%indexes) 
	    (make-hash-table :test #'equal :synchronized t))
      (alexandria:maphash-values (lambda (v) (montezuma:close v)) 
				 old-indexes))))

(defun search-index (store index text)
  (let* ((index (ensure-index-for-type store index)))
    (values
     (montezuma:search index
		       (format nil "!text:\";arc\" text:~a" text)
		       :num-docs 3)
     index)))

(defun ensure-index-for-type (store type)
  (sb-ext:with-locked-hash-table ((indexes store))
    (ensure-gethash type (indexes store)
		   (if (index-path store)
		       (make-instance 'montezuma:index
				      :path (ensure-directories-exist
					     (format nil "~a/~a/"
						     (index-path store)
						     type))
				      :create-p nil
				      :create-if-missing-p t)
		       (make-instance 'montezuma:index)))))

(defgeneric combine-child (parent key value)
  (:method (parent k child)
    (setf (gethash k parent) child))
  (:method (parent k (child string))
    (setf (gethash k parent) child))
  (:method (parent k (children list))
    (combine-child parent k (coerce children 'vector)))
  (:method (parent k (children vector))
    (map nil
         (lambda (idx child)
           (combine-child parent
                          (concat k "::" (princ-to-string idx))
                          child))
         (iota (length children))
         children))
  (:method ((parent hash-table) k (child hash-table))
    (do-hash-table (sk sv child)
      (combine-child parent (concat k "::" sk) sv))))

(defun flatten-hash-table (hash-table)
  (let ((new (fw.lu:empty-hash-table-like hash-table)))
    (do-hash-table (k v hash-table new)
      (combine-child new k v))))

(defgeneric store-message (store message)
  (:method ((store montezuma-store) message)
    (let* ((type (gethash "type" message))
           (index (ensure-index-for-type store type)))
      (montezuma:add-document-to-index index
				       (flatten-hash-table message))
      (montezuma:flush index))))

(defmethod slacker:handle-message :before
    (type (event-pump montezuma-store) ts channel message)
  (declare (ignore type ts channel))
  (store-message event-pump message)
  (values))