From d72e7ecf428ddb8e7d0355c791da3f500d82416a Mon Sep 17 00:00:00 2001 From: Eric Ihli Date: Tue, 10 Nov 2020 08:43:49 -0800 Subject: [PATCH] Refactor integrant system and add user-limericks --- web/dev/migrations.clj | 2 + web/dev/user.clj | 28 ++--- .../20201110124436-user-limericks.down.sql | 1 + .../20201110124436-user-limericks.up.sql | 5 + web/src/com/darklimericks/db/core.clj | 17 +++ web/src/com/darklimericks/db/limericks.clj | 26 +++++ web/src/com/darklimericks/kv/core.clj | 18 +++ web/src/com/darklimericks/logging.clj | 8 ++ web/src/com/darklimericks/server/core.clj | 12 +- web/src/com/darklimericks/server/db.clj | 7 +- web/src/com/darklimericks/server/handlers.clj | 26 +++-- .../com/darklimericks/server/limericks.clj | 25 +---- web/src/com/darklimericks/server/router.clj | 44 ++++++++ web/src/com/darklimericks/server/system.clj | 105 ------------------ web/src/com/darklimericks/server/views.clj | 10 +- web/src/com/darklimericks/server/worker.clj | 18 +++ 16 files changed, 197 insertions(+), 155 deletions(-) create mode 100644 web/resources/migrations/20201110124436-user-limericks.down.sql create mode 100644 web/resources/migrations/20201110124436-user-limericks.up.sql create mode 100644 web/src/com/darklimericks/db/core.clj create mode 100644 web/src/com/darklimericks/kv/core.clj create mode 100644 web/src/com/darklimericks/logging.clj create mode 100644 web/src/com/darklimericks/server/router.clj create mode 100644 web/src/com/darklimericks/server/worker.clj diff --git a/web/dev/migrations.clj b/web/dev/migrations.clj index 916f8cc..5ad2d51 100644 --- a/web/dev/migrations.clj +++ b/web/dev/migrations.clj @@ -8,6 +8,8 @@ :db {:connection-uri (-> state/config :database.sql/connection :jdbcUrl)}}) (comment + (migratus/migrate config) + (migratus/create config "User Limericks") state/config (:database.sql/connection state/system) (migratus/init config)) diff --git a/web/dev/user.clj b/web/dev/user.clj index a5f6795..bbc0a82 100644 --- a/web/dev/user.clj +++ b/web/dev/user.clj @@ -6,17 +6,14 @@ [taoensso.carmine :as car] [taoensso.carmine.message-queue :as car-mq] [integrant.repl.state :as state] - [migratus.core :as migratus] [com.darklimericks.server.handlers :as handlers] [integrant.core :as ig] [hawk.core :as hawk] [clojure.java.io :as io] [com.darklimericks.util.identicon :as identicon] - [com.darklimericks.linguistics.core :as linguistics] [com.darklimericks.server.limericks :as limericks] [com.darklimericks.db.albums :as db.albums] [com.darklimericks.server.util :as util] - [com.owoga.prhyme.limerick :as limerick] [com.darklimericks.server.system] [reitit.core :as reitit])) @@ -26,7 +23,7 @@ (reitit/routes)) ) -(set-refresh-dirs "src" "dev" "resources") +(set-refresh-dirs "src" "resources") (defn add-project-dep ([lib-name lib-version] @@ -48,22 +45,25 @@ :handler auto-reset-handler}])) (defn init [] - (repl/halt) - (-> "config.edn" - io/resource - slurp - ig/read-string - ig/prep - constantly - repl/set-prep!) - (repl/prep) - (repl/init)) + (let [config (-> "config.edn" + io/resource + slurp + ig/read-string)] + (ig/load-namespaces config) + (-> config + ig/prep + constantly + repl/set-prep!) + (repl/go))) (defn reset [] (repl/halt)) + (comment + ((-> state/system + :app/server)) (init) (auto-reset) (let [db (-> state/system :database.sql/connection) diff --git a/web/resources/migrations/20201110124436-user-limericks.down.sql b/web/resources/migrations/20201110124436-user-limericks.down.sql new file mode 100644 index 0000000..441a8d3 --- /dev/null +++ b/web/resources/migrations/20201110124436-user-limericks.down.sql @@ -0,0 +1 @@ +DROP TABLE session_limerick; diff --git a/web/resources/migrations/20201110124436-user-limericks.up.sql b/web/resources/migrations/20201110124436-user-limericks.up.sql new file mode 100644 index 0000000..539e418 --- /dev/null +++ b/web/resources/migrations/20201110124436-user-limericks.up.sql @@ -0,0 +1,5 @@ +CREATE TABLE session_limerick ( + id SERIAL PRIMARY KEY, + limerick_id INTEGER NOT NULL REFERENCES limerick, + session_id UUID NOT NULL +); diff --git a/web/src/com/darklimericks/db/core.clj b/web/src/com/darklimericks/db/core.clj new file mode 100644 index 0000000..f8bda05 --- /dev/null +++ b/web/src/com/darklimericks/db/core.clj @@ -0,0 +1,17 @@ +(ns com.darklimericks.db.core + (:require [integrant.core :as ig] + [environ.core :refer [env]] + [next.jdbc :as jdbc])) + + + +(defmethod ig/prep-key ::connection [_ _] + {:jdbcUrl (str "jdbc:postgresql://localhost:5432/?user=" + (or (env :postgres-user) + "dev") + "&password=" + (or (env :postgres-password) + "dev"))}) + +(defmethod ig/init-key ::connection [_ db-spec] + (jdbc/get-datasource db-spec)) diff --git a/web/src/com/darklimericks/db/limericks.clj b/web/src/com/darklimericks/db/limericks.clj index 3e06fde..7d7d3a2 100644 --- a/web/src/com/darklimericks/db/limericks.clj +++ b/web/src/com/darklimericks/db/limericks.clj @@ -1,5 +1,6 @@ (ns com.darklimericks.db.limericks (:require [next.jdbc :as jdbc] + [taoensso.timbre :as timbre] [honeysql.core :as honey.sql] [honeysql.helpers :as honey.helpers])) @@ -10,9 +11,34 @@ [[name text album-id]]) honey.sql/format)) +(comment + (insert-limerick-sql "foo" "bar" 1) + ;; => ["INSERT INTO limerick (name, text, album_id) VALUES (?, ?, ?)" "foo" "bar" 1] + (-> (insert-limerick-sql "foo" "bar" 1) + (update 0 #(str % " RETURNING id"))) + ) + (defn insert-limerick [db name text album-id] (jdbc/execute! db (insert-limerick-sql name text album-id))) +(defn insert-user-limerick [db session-id name text album-id] + (timbre/info (format "Saving %s." session-id)) + (jdbc/with-transaction [tx db] + (let [{limerick-id :limerick/id} + (jdbc/execute-one! + tx + (-> (insert-limerick-sql name text album-id) + (update 0 #(str % " RETURNING id"))))] + (timbre/info (format "Saving %s to %s." limerick-id session-id)) + (jdbc/execute! tx (-> (honey.helpers/insert-into :session_limerick) + (honey.helpers/columns :limerick_id :session_id) + (honey.helpers/values [[limerick-id session-id]]) + honey.sql/format))))) + +(comment + (require '[integrant.repl.state :as state]) + ) + (defn limerick-sql [limerick-id] (honey.sql/format (honey.sql/build diff --git a/web/src/com/darklimericks/kv/core.clj b/web/src/com/darklimericks/kv/core.clj new file mode 100644 index 0000000..95897e9 --- /dev/null +++ b/web/src/com/darklimericks/kv/core.clj @@ -0,0 +1,18 @@ +(ns com.darklimericks.kv.core + (:require [taoensso.timbre :as timbre] + [integrant.core :as ig] + [environ.core :refer [env]])) + + +(defmethod ig/prep-key ::connection [_ config] + (let [pass (or (env :redis-pass) "dev")] + (assoc-in + config + [:spec :uri] + (format "redis://localhost:6379/")))) + +;; Point of this? We aren't and maintaining a connection here. +;; I guess carmine does that behind the scenes with it's "pool" +;; option. But it's nice to have all boundary config in one place. +(defmethod ig/init-key ::connection [_ config] + config) diff --git a/web/src/com/darklimericks/logging.clj b/web/src/com/darklimericks/logging.clj new file mode 100644 index 0000000..abc4833 --- /dev/null +++ b/web/src/com/darklimericks/logging.clj @@ -0,0 +1,8 @@ +(ns com.darklimericks.logging + (:require [integrant.core :as ig] + [taoensso.timbre :as timbre])) + +(defmethod ig/init-key ::logging [_ config] + (timbre/merge-config! config)) + +(defmethod ig/halt-key! ::logging [_ _]) diff --git a/web/src/com/darklimericks/server/core.clj b/web/src/com/darklimericks/server/core.clj index 5dde61a..4329db3 100644 --- a/web/src/com/darklimericks/server/core.clj +++ b/web/src/com/darklimericks/server/core.clj @@ -1,14 +1,20 @@ (ns com.darklimericks.server.core (:gen-class) (:require [integrant.core :as ig] - [com.darklimericks.server.system :as system] [reitit.coercion] [reitit.coercion.spec] [taoensso.timbre :as timbre] - [clojure.java.io :as io])) + [clojure.java.io :as io] + [org.httpkit.server :as kit])) +(defmethod ig/init-key ::server [_ {:keys [handler] :as opts}] + (timbre/info (format "Starting server on port %d" (:port opts))) + (kit/run-server handler (dissoc opts :handler))) + +(defmethod ig/halt-key! ::server [_ server] + (timbre/info "Stopping server.") + (server)) -(def a (atom {})) (defn -main [] (try diff --git a/web/src/com/darklimericks/server/db.clj b/web/src/com/darklimericks/server/db.clj index eadae7e..4f03477 100644 --- a/web/src/com/darklimericks/server/db.clj +++ b/web/src/com/darklimericks/server/db.clj @@ -1,6 +1,11 @@ (ns com.darklimericks.server.db (:require [clojure.tools.namespace.repl :as c.t.n.r])) -(c.t.n.r/disable-unload!) +(c.t.n.r/disable-reload!) (defonce db (atom {})) + +(defonce worker (atom nil)) + +(comment + (reset! worker nil)) diff --git a/web/src/com/darklimericks/server/handlers.clj b/web/src/com/darklimericks/server/handlers.clj index d5d78fd..5a2c771 100644 --- a/web/src/com/darklimericks/server/handlers.clj +++ b/web/src/com/darklimericks/server/handlers.clj @@ -2,8 +2,10 @@ (:require [taoensso.timbre :as timbre] [hiccup.core :as hiccup] [reitit.ring :as ring] + [reitit.http :as http] + [reitit.interceptor.sieppari :as sieppari] + [integrant.core :as ig] [clojure.string :as string] - [clojure.core.async :as async] [taoensso.carmine :as car] [taoensso.carmine.message-queue :as car-mq] [com.darklimericks.server.util :as util] @@ -13,6 +15,12 @@ [com.darklimericks.server.views :as views] [com.darklimericks.server.limericks :as limericks])) +(defmethod ig/init-key ::handler [_ {:keys [router]}] + (http/ring-handler + router + (ring/create-default-handler) + {:executor sieppari/executor})) + (defn home-handler [db] (fn [request] @@ -23,7 +31,6 @@ (fn [{:album/keys [id artist_id]}] (vector id (db.artists/artist db artist_id))) recent-albums))] - (timbre/info recent-albums artists-by-album) (timbre/info "home-handler") {:status 200 :headers {"Content-Type" "text/html; charset=utf-8"} @@ -37,9 +44,14 @@ (defn limerick-generation-post-handler [db cache] - (fn [{{:keys [scheme]} :params :as request}] + (fn [{{:keys [scheme]} :params + {:keys [session-id]} :session + :as request}] (let [scheme (limericks/parse-scheme scheme) - mid (car/wcar db (car-mq/enqueue "limericks" scheme))] + mid (car/wcar db (car-mq/enqueue + "limericks" + {:scheme scheme + :session-id session-id}))] {:status 301 :headers {"Content-Type" "text/html; charset=utf-8"} :body (views/wrapper @@ -81,7 +93,7 @@ "%s#%s" (util/route-name->path request - :com.darklimericks.server.system/album + :com.darklimericks.server.router/album {:artist-id (:artist/id artist) :artist-name (util/slug (:artist/name artist)) :album-id (:album/id album) @@ -147,7 +159,7 @@ [:a.washed-yellow.link {:href (util/route-name->path req - :com.darklimericks.server.system/artist + :com.darklimericks.server.router/artist {:artist-id (:artist/id artist) :artist-name (:artist/name artist)})} (:artist/name artist)])] @@ -187,7 +199,7 @@ (format "album: \"%s\""))] (let [album-url (util/route-name->path request - :com.darklimericks.server.system/album + :com.darklimericks.server.router/album {:artist-id (:artist/id artist) :artist-name (util/slug (:artist/name artist)) :album-id (:album/id album) diff --git a/web/src/com/darklimericks/server/limericks.clj b/web/src/com/darklimericks/server/limericks.clj index 1a44587..3273365 100644 --- a/web/src/com/darklimericks/server/limericks.clj +++ b/web/src/com/darklimericks/server/limericks.clj @@ -102,25 +102,9 @@ (map string/capitalize) (string/join " "))) -(defn generate-limerick [db scheme task-id] - (let [scheme (parse-scheme scheme)] - (async/thread - (try - (let [rhyme-id (java.util.UUID/randomUUID) - rhyme (limerick/rhyme-from-scheme - dict/prhyme-dict - darklyrics-markov-2 - scheme)] - (swap! db update-in [:tasks task-id] assoc :status :finished) - (swap! db assoc-in [:limericks rhyme-id] {:text rhyme :task-id task-id}) - rhyme) - (catch Throwable e - (println "Exception" e) - (swap! db update-in [:tasks task-id] assoc :status :failed) - (swap! db assoc-in [:tasks task-id] {:text (.getMessage e)})))))) - -(defn generate-limerick-worker [db scheme] - (let [limerick (limerick/rhyme-from-scheme +(defn generate-limerick-worker [db message] + (let [{:keys [scheme session-id]} message + limerick (limerick/rhyme-from-scheme dict/prhyme-dict darklyrics-markov-2 scheme) @@ -131,8 +115,9 @@ (identicon/generate (-> (:album/name album) string/lower-case (string/replace #" " "-")) 128)) - (db.limericks/insert-limerick + (db.limericks/insert-user-limerick db + session-id (get-limerick-name limerick) (string/join "\n" limerick) album-id))) diff --git a/web/src/com/darklimericks/server/router.clj b/web/src/com/darklimericks/server/router.clj new file mode 100644 index 0000000..c67e0e0 --- /dev/null +++ b/web/src/com/darklimericks/server/router.clj @@ -0,0 +1,44 @@ +(ns com.darklimericks.server.router + (:require [integrant.core :as ig] + [taoensso.timbre :as timbre] + [reitit.http :as http] + [reitit.coercion.spec] + [reitit.http.interceptors.parameters :refer [parameters-interceptor]] + [com.darklimericks.server.handlers :as handlers] + [com.darklimericks.server.interceptors :as interceptors])) + +(defmethod ig/init-key ::router [_ {:keys [db cache]}] + (let [routes [["/" {:name ::home + :get {:handler (handlers/home-handler db)}}] + ["/{letter}.html" + {:name ::artists-by-letter + :handler (handlers/artists-by-letter db)}] + ["/limerick-generation-task" + {:name ::limerick-generation-task + :post {:handler (handlers/limerick-generation-post-handler db cache)} + :get {:handler (handlers/limerick-generation-get-handler db cache)}}] + ["/submit" + {:name ::submit + :get {:handler (handlers/submit-limericks-get-handler db)}}] + ["/limericks" + ["/{artist-name}-{artist-id}/{album-name}-{album-id}" + {:name ::album + :coercion reitit.coercion.spec/coercion + :parameters {:path {:artist-id int? + :album-id int?}} + :get {:handler (handlers/limericks-get-handler db cache)}}] + ["/{artist-name}-{artist-id}" + {:name ::artist + :coercion reitit.coercion.spec/coercion + :parameters {:path {:artist-id int?}} + :get {:handler (handlers/artist-get-handler db)}}]] + ["/assets/*" handlers/resource-handler]]] + (timbre/info "Starting router.") + (http/router + routes + {:data {:interceptors [(interceptors/session-interceptor cache) + interceptors/coerce-request-interceptor + interceptors/logging-interceptor + interceptors/format-interceptor + (parameters-interceptor) + interceptors/keywordize-params-interceptor]}}))) diff --git a/web/src/com/darklimericks/server/system.clj b/web/src/com/darklimericks/server/system.clj index 9ebbc82..37e8363 100644 --- a/web/src/com/darklimericks/server/system.clj +++ b/web/src/com/darklimericks/server/system.clj @@ -1,11 +1,9 @@ (ns com.darklimericks.server.system (:require [integrant.core :as ig] [taoensso.timbre :as timbre] - [org.httpkit.server :as kit] [next.jdbc :as jdbc] [environ.core :refer [env]] [taoensso.carmine.message-queue :as car-mq] - [ring.middleware.session :refer [wrap-session]] [reitit.http :as http] [reitit.ring :as ring] [reitit.coercion.spec] @@ -16,108 +14,5 @@ [com.darklimericks.server.interceptors :as interceptors] [com.darklimericks.server.db :as db])) -(def worker (atom nil)) -(defmethod ig/init-key :worker/limerick-gen [_ {:keys [db kv]}] - (when (nil? @worker) - (reset! - worker - (car-mq/worker - kv - "limericks" - {:handler - (fn [{:keys [message attempt]}] - (timbre/info "Received" message) - (limericks/generate-limerick-worker db message) - {:status :success})})))) -(defmethod ig/halt-key! :worker/limerick-gen [_ worker] - #_(.stop worker)) - -(defmethod ig/prep-key :database.kv/connection [_ config] - (let [pass (or (env :redis-pass) "dev")] - (assoc-in - config - [:spec :uri] - (format "redis://localhost:6379/")))) - -;; Point of this? We aren't and maintaining a connection here. -;; I guess carmine does that behind the scenes with it's "pool" -;; option. But it's nice to have all boundary config in one place. -(defmethod ig/init-key :database.kv/connection [_ config] - config) - -(defmethod ig/init-key :app/session-store [_ {:keys [cache]}] - {}) - -(defmethod ig/prep-key :database.sql/connection [_ _] - {:jdbcUrl (str "jdbc:postgresql://localhost:5432/?user=" - (or (env :postgres-user) - "dev") - "&password=" - (or (env :postgres-password) - "dev"))}) - -(defmethod ig/init-key :database.sql/connection [_ db-spec] - (jdbc/get-datasource db-spec)) - -(defmethod ig/init-key :app/logging [_ config] - (timbre/merge-config! config)) - -(defmethod ig/halt-key! :app/logging [_ _]) - -(defmethod ig/init-key :app/cache [_ _] - (timbre/debug "Initializing cache.") - db/db) - -(defmethod ig/halt-key! :app/db [_ db] - #_(reset! db {})) - -(defmethod ig/init-key :app/router [_ {:keys [db cache]}] - (let [routes [["/" {:name ::home - :get {:handler (handlers/home-handler db)}}] - ["/{letter}.html" - {:name ::artists-by-letter - :handler (handlers/artists-by-letter db)}] - ["/limerick-generation-task" - {:name ::limerick-generation-task - :post {:handler (handlers/limerick-generation-post-handler db cache)} - :get {:handler (handlers/limerick-generation-get-handler db cache)}}] - ["/submit" - {:name ::submit - :get {:handler (handlers/submit-limericks-get-handler db)}}] - ["/limericks" - ["/{artist-name}-{artist-id}/{album-name}-{album-id}" - {:name ::album - :coercion reitit.coercion.spec/coercion - :parameters {:path {:artist-id int? - :album-id int?}} - :get {:handler (handlers/limericks-get-handler db cache)}}] - ["/{artist-name}-{artist-id}" - {:name ::artist - :coercion reitit.coercion.spec/coercion - :parameters {:path {:artist-id int?}} - :get {:handler (handlers/artist-get-handler db)}}]] - ["/assets/*" handlers/resource-handler]]] - (http/router - routes - {:data {:interceptors [(interceptors/session-interceptor cache) - interceptors/coerce-request-interceptor - interceptors/logging-interceptor - interceptors/format-interceptor - (parameters-interceptor) - interceptors/keywordize-params-interceptor]}}))) - -(defmethod ig/init-key :app/handler [_ {:keys [router]}] - (http/ring-handler - router - (ring/create-default-handler) - {:executor sieppari/executor})) - -(defmethod ig/init-key :app/server [_ {:keys [handler] :as opts}] - (timbre/info (format "Starting server on port %d" (:port opts))) - (kit/run-server handler (dissoc opts :handler))) - -(defmethod ig/halt-key! :app/server [_ server] - (timbre/info "Stopping server.") - (server)) diff --git a/web/src/com/darklimericks/server/views.clj b/web/src/com/darklimericks/server/views.clj index 76375f6..2933074 100644 --- a/web/src/com/darklimericks/server/views.clj +++ b/web/src/com/darklimericks/server/views.clj @@ -28,7 +28,7 @@ [:a.washed-yellow.pl1 {:href (util/route-name->path request - :com.darklimericks.server.system/submit)} + :com.darklimericks.server.router/submit)} "SUBMIT LIMERICKS"] [:span.dark-yellow (format @@ -76,7 +76,7 @@ [:a.washed-yellow.pr1 {:href (util/route-name->path request - :com.darklimericks.server.system/submit)} + :com.darklimericks.server.router/submit)} "SUBMIT LIMERICKS"] [:span.dark-yellow (format @@ -114,7 +114,7 @@ [:a.light-yellow.f5 {:href (util/route-name->path request - :com.darklimericks.server.system/artist + :com.darklimericks.server.router/artist {:artist-id (:album/artist_id album) :artist-name (-> album :album/id @@ -126,7 +126,7 @@ [:a.link.washed-yellow.f6 {:href (util/route-name->path request - :com.darklimericks.server.system/album + :com.darklimericks.server.router/album {:artist-id (:album/artist_id album) :artist-name (-> album :album/id @@ -163,7 +163,7 @@ (form/form-to [:post (util/route-name->path request - :com.darklimericks.server.system/limerick-generation-task)] + :com.darklimericks.server.router/limerick-generation-task)] (form/text-field "scheme") (form/submit-button "Generate dark limerick")) [:div diff --git a/web/src/com/darklimericks/server/worker.clj b/web/src/com/darklimericks/server/worker.clj new file mode 100644 index 0000000..02ddca1 --- /dev/null +++ b/web/src/com/darklimericks/server/worker.clj @@ -0,0 +1,18 @@ +(ns com.darklimericks.server.worker + (:require [integrant.core :as ig] + [taoensso.timbre :as timbre] + [taoensso.carmine.message-queue :as car-mq] + [com.darklimericks.server.limericks :as limericks])) + +(defmethod ig/init-key ::limerick-gen [_ {:keys [db kv]}] + (car-mq/worker + kv + "limericks" + {:handler + (fn [{:keys [message attempt]}] + (timbre/info "Received" message) + (limericks/generate-limerick-worker db message) + {:status :success})})) + +(defmethod ig/halt-key! ::limerick-gen [_ w] + (.stop w))