Skip to content

Instantly share code, notes, and snippets.

@grierson
Last active February 1, 2019 14:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grierson/4bcdf11cf93d556671f13826dd355308 to your computer and use it in GitHub Desktop.
Save grierson/4bcdf11cf93d556671f13826dd355308 to your computer and use it in GitHub Desktop.
(ns dorsia.core
(:require [ring.adapter.jetty :as jetty]
[ring.util.response :as resp]
[integrant.core :as ig]
[reitit.ring :as ring]))
;; Start Persistence
(defprotocol ReservationRepository
(create [this reservation] "Add reservation")
(read-reservations [this datetime] "Get all reservations"))
(def reservations (atom [{:quantity 3 :name "Alice"}
{:quantity 4 :name "Bob"}]))
(defrecord MemoryRepo []
ReservationRepository
(create [this reservation]
(swap! reservations conj reservation))
(read-reservations [this datetime]
@reservations))
;; End Persistence
;; Start Usecase
(defn try-accept [capacity reservedSeats reservation]
(let [reservedSeats (reduce + (map :quantity reservedSeats))
total (+ reservedSeats (:quantity reservation))]
(when (<= total capacity)
reservation)))
(defn try-accept-comp [reservationRepository capacity reservation]
(let [reservations (read-reservations reservationRepository (:datetime reservation))
result (try-accept capacity reservations reservation)]
(when result
(create reservationRepository reservation))))
;; End Usecase
;; Start Handlers
(defn try-accept-handler [reservationRepository capacity {:keys [query-params]}]
(if-let [response (try-accept-comp reservationRepository capacity query-params)]
(resp/response response)
(resp/bad-request "Could not handle")))
(defn get-requests-handler [reservationRepository {:keys [query-params]}]
(if-let [response (read-reservations reservationRepository (:datetime query-params))]
(resp/response response)
(resp/bad-request "Could not handle")))
;; End Handlers
;; Integrant / Dependency Injectioni
(defmethod ig/init-key :dorsia/reservations.repository/memory [_ _]
(MemoryRepo.))
(defmethod ig/init-key :dorsia/routes [_ routes]
(-> routes
ring/router
ring/ring-handler))
(defmethod ig/init-key :ring.adapter/jetty [_ {:keys [handler port]}]
(jetty/run-jetty handler {:port port
:join? false}))
(defmethod ig/halt-key! :ring.adapter/jetty [_ server]
(.stop server))
(defmethod ig/init-key :handler.reservations/get [_ {:keys [reservationRepository]}]
(fn [request]
(get-requests-handler reservationRepository request)))
(defmethod ig/init-key :handler.reservations/post [_ {:keys [reservationRepository capacity]}]
(fn [request]
(try-accept-handler reservationRepository capacity request)))
;; Integrant / Dependency Injection
(derive :ring.adapter/jetty :ring/adapter)
(derive :dorsia.reservations/repository :dorsia.reservations.repository/memory)
(def config
{:ring.adapter/jetty {:port 8080, :handler (ig/ref :dorsia/routes)}
:dorsia/reservations.repository/memory {}
:dorsia/routes ["/api"
["/reservations" {:get (ig/ref :handler.reservations/get)
:post (ig/ref :handler.reservations/post)}]]
:handler.reservations/get {:reservationRepository (ig/ref :dorsia.reservations/repository}
:handler.reservations/post {:reservationRepository (ig/ref :dorsia.reservations/repository)
:capacity 10}})
(comment
(def system (ig/init config [:dorsia/routes]))
((:dorsia/routes system) {:request-method :get
:uri "/api/reservations"})
((:dorsia/routes system) {:request-method :post
:uri "/api/reservations"
:query-params {:name "Charlie"
:quantity 1}})
(ig/halt! system))
;; Query/Business logic/Command Sandwich Tests
(def database-stub
(reify reservationRepository
{:read-reservations [{:quantity 3
:datetime (t/date-time 1986 10 14 4 3 27 456)}]
:create (throws RuntimeException "Insert not supported"})
(def email-stub
(reify emailService
{:send (throws RuntimeException "Insert not supported"})
(deftest comp-test
(let [capacity 10
request {:quantity 4 :datetime (t/date-time 1986 10 14 4 3 27 456)}
result (try-accept-comp email-stub database-stub capacity request)]
(is (some? result))))
;; Pure business logic Tests
(deftest try-accept
(let [capacity 10
reservedSeats [{:quantity 6 (t/date-time 1986 10 14 4 3 27 456)}]
reservation {:quantity 3 (t/date-time 1986 10 14 4 3 27 456)}
result (try-accept capacity reservedSeats reservation]
(is (some? result))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment