 (defn update-resource
   "Given a table name, the name of the primary key, and the original and updated resource,
   update a resource in the DB, returning the property map for the resource."
-  ([table-name primary-key-name original-resource new-resource]
-  (update-resource table-name primary-key-name original-resource new-resource (current-timestamp)))
-
-  ([table-name primary-key-name original-resource new-resource timestamp]
+  ([conn table-name primary-key-name original-resource new-resource]
+  (update-resource conn table-name primary-key-name original-resource new-resource (current-timestamp)))
+
+  ([conn table-name primary-key-name original-resource new-resource timestamp]
   (let [timed-resource (merge new-resource {
           primary-key-name (original-resource primary-key-name)
           :created-at (:created-at original-resource)
           :updated-at timestamp})
-        update (pool/with-pool [conn pool/rethinkdb-pool]
-                 (with-timeout default-timeout
-                   (-> (r/table table-name)
-                       (r/get (original-resource primary-key-name))
-                       (r/replace timed-resource)
-                       (r/run conn))))]
+        update (with-timeout default-timeout
+                 (-> (r/table table-name)
+                     (r/get (original-resource primary-key-name))
+                     (r/replace timed-resource)
+                     (r/run conn)))]
   (if (or (= 1 (:replaced update)) (= 1 (:unchanged update)))
     timed-resource
     (throw (RuntimeException. (str "RethinkDB update failure: " update)))))))
 
 (defn delete-resource
   "Delete the specified resource and return `true`."
-  ([table-name primary-key-value]
-   (let [delete (pool/with-pool [conn pool/rethinkdb-pool]
-                  (with-timeout default-timeout
-                    (-> (r/table table-name)
-                        (r/get primary-key-value)
-                        (r/delete)
-                        (r/run conn))))]
+  ([conn table-name primary-key-value]
+   (let [delete (with-timeout default-timeout
+                  (-> (r/table table-name)
+                      (r/get primary-key-value)
+                      (r/delete)
+                      (r/run conn)))]
     (if (= 1 (:deleted delete))
       true
       (throw (RuntimeException. (str "RethinkDB delete failure: " delete))))))
 
-  ([table-name key-name key-value]
-   (let [delete (pool/with-pool [conn pool/rethinkdb-pool]
-                  (with-timeout default-timeout
-                    (-> (r/table table-name)
-                        (r/get-all [key-value] {:index key-name})
-                        (r/delete)
-                        (r/run conn))))]
+  ([conn table-name key-name key-value]
+   (let [delete (with-timeout default-timeout
+                  (-> (r/table table-name)
+                      (r/get-all [key-value] {:index key-name})
+                      (r/delete)
+                      (r/run conn)))]
      (if (zero? (:errors delete))
       true
       (throw (RuntimeException. (str "RethinkDB delete failure: " delete)))))))


(defn create-resource
  "Create a resource in the DB, returning the property map for the resource."
  [table-name resource timestamp]
  (let [timed-resource (merge resource {
          :created-at timestamp
          :updated-at timestamp})
        insert (pool/with-pool [conn pool/rethinkdb-pool]
                 (with-timeout default-timeout
                   (-> (r/table table-name)
                       (r/insert timed-resource)
                       (r/run conn))))]
  (if (= 1 (:inserted insert))
    timed-resource
    (throw (RuntimeException. (str "RethinkDB insert failure: " insert))))))

(defn read-resource
  "
  Given a table name and a primary key value, retrieve the resource from the database,
  or return nil if it doesn't exist.
  "
  [table-name primary-key-value]
  (pool/with-pool [conn pool/rethinkdb-pool]
    (-> (r/table table-name)
      (r/get primary-key-value)
      (r/run conn))))

(defn read-resources
  "
  Given a table name, and an optional index name and value, and an optional set of fields, retrieve
  the resources from the database.
  "
  ([table-name fields]
  (pool/with-pool [conn pool/rethinkdb-pool]
    (with-timeout default-timeout
      (-> (r/table table-name)
          (r/with-fields fields)
          (r/run conn)))))

  ([table-name index-name index-value]
  (pool/with-pool [conn pool/rethinkdb-pool]
    (with-timeout default-timeout
      (-> (r/table table-name)
          (r/get-all [index-value] {:index index-name})
          (r/run conn)))))

  ([table-name index-name index-value fields]
  (pool/with-pool [conn pool/rethinkdb-pool]
    (with-timeout default-timeout
      (-> (r/table table-name)
          (r/get-all [index-value] {:index index-name})
          (r/pluck fields)
          (r/run conn))))))

(defn read-resources-in-order
  "


(defn delete-all-resources!
  "Use with caution! Failure can result in partial deletes of just some resources. Returns `true` if successful."
  [conn table-name]
  (let [delete (with-timeout default-timeout
                 (-> (r/table table-name)
                     (r/delete)
                     (r/run conn)))]
    (if (pos? (:errors delete))
      (throw (RuntimeException. (str "RethinkDB delete failure: " delete)))
      true)))