Repository: CSCfi/rems
Pull request #1203 (2019-05-03 11:56:48)

fold rems.api.applications-v2 into rems.db.applications
follow-up for #1201


Patch:
diff --git a/src/clj/rems/api/applications.clj b/src/clj/rems/api/applications.clj
index 54aa24f55..604375679 100644
--- a/src/clj/rems/api/applications.clj
+++ b/src/clj/rems/api/applications.clj
@@ -2,7 +2,6 @@
   (:require [clj-time.core :as time]
             [clojure.string :as str]
             [compojure.api.sweet :refer :all]
-            [rems.api.applications-v2 :as applications-v2]
             [rems.api.schema :refer :all]
             [rems.api.util :as api-util]
             [rems.application.commands :as commands]
@@ -94,7 +93,7 @@
        (not= :application.state/draft (:application/state application))))
 
 (defn- get-potential-todos [user-id]
-  (->> (applications-v2/get-all-applications user-id)
+  (->> (applications/get-all-applications user-id)
        (filter potential-todo?)))
 
 (defn- todo? [application]
@@ -145,7 +144,7 @@
       :summary "Get the current user's own applications"
       :roles #{:logged-in}
       :return [ApplicationOverview]
-      (ok (applications-v2/get-my-applications (getx-user-id))))))
+      (ok (applications/get-my-applications (getx-user-id))))))
 
 (def applications-api
   (context "/applications" []
@@ -155,7 +154,7 @@
       :summary "Get all applications which the current user can see"
       :roles #{:logged-in}
       :return [ApplicationOverview]
-      (ok (applications-v2/get-all-applications (getx-user-id))))
+      (ok (applications/get-all-applications (getx-user-id))))
 
     (GET "/todo" []
       :summary "Get all applications that the current user needs to act on."
@@ -258,7 +257,7 @@
       :path-params [application-id :- (describe s/Num "application id")]
       :responses {200 {:schema Application}
                   404 {:schema s/Str :description "Not found"}}
-      (if-let [app (applications-v2/get-application (getx-user-id) application-id)]
+      (if-let [app (applications/get-application (getx-user-id) application-id)]
         (ok app)
         (api-util/not-found-json-response)))
 
@@ -267,7 +266,7 @@
       :roles #{:logged-in}
       :path-params [application-id :- (describe s/Num "application id")]
       :produces ["application/pdf"]
-      (if-let [app (applications-v2/get-application (getx-user-id) application-id)]
+      (if-let [app (applications/get-application (getx-user-id) application-id)]
         (-> app
             (pdf/application-to-pdf-bytes)
             (ByteArrayInputStream.)
diff --git a/src/clj/rems/api/applications_v2.clj b/src/clj/rems/api/applications_v2.clj
deleted file mode 100644
index 20fd164c6..000000000
--- a/src/clj/rems/api/applications_v2.clj
+++ /dev/null
@@ -1,181 +0,0 @@
-(ns rems.api.applications-v2
-  (:require [clojure.core.cache :as cache]
-            [clojure.set :as set]
-            [clojure.test :refer [deftest is testing]]
-            [medley.core :refer [map-vals]]
-            [mount.core :as mount]
-            [rems.application.events-cache :as events-cache]
-            [rems.application.model :as model]
-            [rems.auth.util :refer [throw-forbidden]]
-            [rems.db.applications :as applications]
-            [rems.db.catalogue :as catalogue]
-            [rems.db.events :as events]
-            [rems.db.form :as form]
-            [rems.db.licenses :as licenses]
-            [rems.db.users :as users]
-            [rems.db.workflow :as workflow]
-            [rems.permissions :as permissions]
-            [rems.scheduler :as scheduler]
-            [rems.util :refer [getx atom?]])
-  (:import [org.joda.time Duration]))
-
-(def ^:private injections
-  {:get-form form/get-form
-   :get-catalogue-item catalogue/get-localized-catalogue-item
-   :get-license licenses/get-license
-   :get-user users/get-user-attributes
-   :get-users-with-role users/get-users-with-role
-   :get-workflow workflow/get-workflow})
-
-;; short-lived cache to speed up pollers which get the application
-;; repeatedly for each event instead of building their own projection
-(mount/defstate application-cache
-  :start (atom (cache/ttl-cache-factory {} :ttl 10000)))
-
-(defn get-unrestricted-application
-  "Returns the full application state without any user permission
-   checks and filtering of sensitive information. Don't expose via APIs."
-  [application-id]
-  (let [events (events/get-application-events application-id)
-        cache-key [application-id (count events)]
-        build-app (fn [_] (model/build-application-view events injections))]
-    (if (empty? events)
-      nil ; application not found
-      ;; TODO: this caching could be removed by refactoring the pollers to build their own projection
-      (if (atom? application-cache) ; guard against not started cache
-        (-> (swap! application-cache cache/through-cache cache-key build-app)
-            (getx cache-key))
-        (build-app nil)))))
-
-(defn get-application
-  "Returns the part of application state which the specified user
-   is allowed to see. Suitable for returning from public APIs as-is."
-  [user-id application-id]
-  (when-let [application (get-unrestricted-application application-id)]
-    (or (model/apply-user-permissions application user-id)
-        (throw-forbidden))))
-
-;;; Listing all applications
-
-(defn- all-applications-view
-  "Projection for the current state of all applications."
-  [applications event]
-  (if-let [app-id (:application/id event)] ; old style events don't have :application/id
-    (update applications app-id model/application-view event)
-    applications))
-
-(defn- exclude-unnecessary-keys-from-overview [application]
-  (dissoc application
-          :application/events
-          :application/form
-          :application/licenses))
-
-(mount/defstate
-  ^{:doc "The cached state will contain the following keys:
-          ::raw-apps
-          - Map from application ID to the pure projected state of an application.
-          ::enriched-apps
-          - Map from application ID to the enriched version of an application.
-            Built from the raw apps by calling `enrich-with-injections`.
-            Since the injected entities (resources, forms etc.) are mutable,
-            it creates a cache invalidation problem here.
-          ::apps-by-user
-          - Map from user ID to a list of applications which the user can see.
-            Built from the enriched apps by calling `apply-user-permissions`.
-          ::roles-by-user
-          - Map from user ID to a set of all application roles which the user has,
-            a union of roles from all applications."}
-  all-applications-cache
-  :start (events-cache/new))
-
-(defn- group-apps-by-user [apps]
-  (->> apps
-       (mapcat (fn [app]
-                 (for [user (keys (::permissions/user-roles app))]
-                   (when-let [app (model/apply-user-permissions app user)]
-                     [user app]))))
-       (reduce (fn [apps-by-user [user app]]
-                 (update apps-by-user user conj app))
-               {})))
-
-(deftest test-group-apps-by-user
-  (let [apps [(-> {:application/id 1}
-                  (permissions/give-role-to-users :foo ["user-1" "user-2"]))
-              (-> {:application/id 2}
-                  (permissions/give-role-to-users :bar ["user-1"]))]]
-    (is (= {"user-1" [{:application/id 1} {:application/id 2}]
-            "user-2" [{:application/id 1}]}
-           (->> (group-apps-by-user apps)
-                (map-vals (fn [apps]
-                            (->> apps
-                                 (map #(select-keys % [:application/id]))
-                                 (sort-by :application/id)))))))))
-
-(defn- group-roles-by-user [apps]
-  (->> apps
-       (mapcat (fn [app] (::permissions/user-roles app)))
-       (reduce (fn [roles-by-user [user roles]]
-                 (update roles-by-user user set/union roles))
-               {})))
-
-(deftest test-group-roles-by-user
-  (let [apps [(-> {:application/id 1}
-                  (permissions/give-role-to-users :foo ["user-1" "user-2"]))
-              (-> {:application/id 2}
-                  (permissions/give-role-to-users :bar ["user-1"]))]]
-    (is (= {"user-1" #{:foo :bar}
-            "user-2" #{:foo}}
-           (group-roles-by-user apps)))))
-
-(defn refresh-all-applications-cache! []
-  (events-cache/refresh!
-   all-applications-cache
-   (fn [state events]
-     ;; Because enrich-with-injections is not idempotent,
-     ;; it's necessary to hold on to the "raw" applications.
-     ;; TODO: consider making enrich-with-injections idempotent (move dissocs to hide-non-public-information and other small refactorings)
-     (let [raw-apps (reduce all-applications-view (::raw-apps state) events)
-           updated-app-ids (distinct (map :application/id events))
-           ;; TODO: batched injections: only one DB query to fetch all catalogue items etc.
-           ;;       - fetch all items in the background as a batch, use plain maps as injections
-           ;;       - change db/get-license and db/get-user-attributes to fetch all rows if ID is not defined
-           cached-injections (map-vals memoize injections)
-           enriched-apps (->> (select-keys raw-apps updated-app-ids)
-                              (map-vals #(model/enrich-with-injections % cached-injections))
-                              (merge (::enriched-apps state)))]
-       {::raw-apps raw-apps
-        ::enriched-apps enriched-apps
-        ::apps-by-user (group-apps-by-user (vals enriched-apps))
-        ::roles-by-user (group-roles-by-user (vals enriched-apps))}))))
-
-(defn get-all-unrestricted-applications []
-  (-> (refresh-all-applications-cache!)
-      ::enriched-apps
-      (vals)))
-
-(defn get-all-applications [user-id]
-  (-> (refresh-all-applications-cache!)
-      (get-in [::apps-by-user user-id])
-      (->> (map exclude-unnecessary-keys-from-overview))))
-
-(defn get-all-application-roles [user-id]
-  (-> (refresh-all-applications-cache!)
-      (get-in [::roles-by-user user-id])
-      (set)))
-
-(defn- my-application? [application]
-  (some #{:applicant :member} (:application/roles application)))
-
-(defn get-my-applications [user-id]
-  (->> (get-all-applications user-id)
-       (filter my-application?)))
-
-(defn reload-cache! []
-  ;; TODO: Here is a small chance that a user will experience a cache miss. Consider rebuilding the cache asynchronously and then `reset!` the cache.
-  (events-cache/empty! all-applications-cache)
-  (refresh-all-applications-cache!))
-
-;; empty the cache occasionally in case some of the injected entities are changed
-(mount/defstate all-applications-cache-reloader
-  :start (scheduler/start! reload-cache! (Duration/standardHours 1))
-  :stop (scheduler/stop! all-applications-cache-reloader))
diff --git a/src/clj/rems/db/applications.clj b/src/clj/rems/db/applications.clj
index cabfb8b1e..5e4cd666e 100644
--- a/src/clj/rems/db/applications.clj
+++ b/src/clj/rems/db/applications.clj
@@ -1,9 +1,14 @@
 (ns rems.db.applications
   "Query functions for forms and applications."
-  (:require [clj-time.core :as time]
+  (:require [clojure.core.cache :as cache]
+            [clj-time.core :as time]
             [clojure.java.jdbc :as jdbc]
+            [clojure.set :as set]
             [clojure.test :refer [deftest is]]
             [conman.core :as conman]
+            [medley.core :refer [map-vals]]
+            [mount.core :as mount]
+            [rems.application.events-cache :as events-cache]
             [rems.application.model :as model]
             [rems.auth.util :refer [throw-forbidden]]
             [rems.db.catalogue :as catalogue]
@@ -18,8 +23,10 @@
             [rems.form-validation :as form-validation]
             [rems.json :as json]
             [rems.permissions :as permissions]
-            [rems.util :refer [secure-token]]
-            [rems.workflow.dynamic :as dynamic]))
+            [rems.scheduler :as scheduler]
+            [rems.util :refer [atom? getx secure-token]]
+            [rems.workflow.dynamic :as dynamic])
+  (:import [org.joda.time Duration]))
 
 ;;; Query functions
 
@@ -164,3 +171,166 @@
              :errors (:errors response)})))
       {:success false
        :errors [{:type :t.actions.errors/invalid-token :token invitation-token}]}))
+
+;;; Fetching applications (for API) (incl. caching)
+
+(def ^:private injections
+  {:get-form form/get-form
+   :get-catalogue-item catalogue/get-localized-catalogue-item
+   :get-license licenses/get-license
+   :get-user users/get-user-attributes
+   :get-users-with-role users/get-users-with-role
+   :get-workflow workflow/get-workflow})
+
+;; short-lived cache to speed up pollers which get the application
+;; repeatedly for each event instead of building their own projection
+(mount/defstate application-cache
+  :start (atom (cache/ttl-cache-factory {} :ttl 10000)))
+
+(defn get-unrestricted-application
+  "Returns the full application state without any user permission
+   checks and filtering of sensitive information. Don't expose via APIs."
+  [application-id]
+  (let [events (events/get-application-events application-id)
+        cache-key [application-id (count events)]
+        build-app (fn [_] (model/build-application-view events injections))]
+    (if (empty? events)
+      nil ; application not found
+      ;; TODO: this caching could be removed by refactoring the pollers to build their own projection
+      (if (atom? application-cache) ; guard against not started cache
+        (-> (swap! application-cache cache/through-cache cache-key build-app)
+            (getx cache-key))
+        (build-app nil)))))
+
+(defn get-application
+  "Returns the part of application state which the specified user
+   is allowed to see. Suitable for returning from public APIs as-is."
+  [user-id application-id]
+  (when-let [application (get-unrestricted-application application-id)]
+    (or (model/apply-user-permissions application user-id)
+        (throw-forbidden))))
+
+;;; Listing all applications
+
+(defn- all-applications-view
+  "Projection for the current state of all applications."
+  [applications event]
+  (if-let [app-id (:application/id event)] ; old style events don't have :application/id
+    (update applications app-id model/application-view event)
+    applications))
+
+(defn- exclude-unnecessary-keys-from-overview [application]
+  (dissoc application
+          :application/events
+          :application/form
+          :application/licenses))
+
+(mount/defstate
+  ^{:doc "The cached state will contain the following keys:
+          ::raw-apps
+          - Map from application ID to the pure projected state of an application.
+          ::enriched-apps
+          - Map from application ID to the enriched version of an application.
+            Built from the raw apps by calling `enrich-with-injections`.
+            Since the injected entities (resources, forms etc.) are mutable,
+            it creates a cache invalidation problem here.
+          ::apps-by-user
+          - Map from user ID to a list of applications which the user can see.
+            Built from the enriched apps by calling `apply-user-permissions`.
+          ::roles-by-user
+          - Map from user ID to a set of all application roles which the user has,
+            a union of roles from all applications."}
+  all-applications-cache
+  :start (events-cache/new))
+
+(defn- group-apps-by-user [apps]
+  (->> apps
+       (mapcat (fn [app]
+                 (for [user (keys (::permissions/user-roles app))]
+                   (when-let [app (model/apply-user-permissions app user)]
+                     [user app]))))
+       (reduce (fn [apps-by-user [user app]]
+                 (update apps-by-user user conj app))
+               {})))
+
+(deftest test-group-apps-by-user
+  (let [apps [(-> {:application/id 1}
+                  (permissions/give-role-to-users :foo ["user-1" "user-2"]))
+              (-> {:application/id 2}
+                  (permissions/give-role-to-users :bar ["user-1"]))]]
+    (is (= {"user-1" [{:application/id 1} {:application/id 2}]
+            "user-2" [{:application/id 1}]}
+           (->> (group-apps-by-user apps)
+                (map-vals (fn [apps]
+                            (->> apps
+                                 (map #(select-keys % [:application/id]))
+                                 (sort-by :application/id)))))))))
+
+(defn- group-roles-by-user [apps]
+  (->> apps
+       (mapcat (fn [app] (::permissions/user-roles app)))
+       (reduce (fn [roles-by-user [user roles]]
+                 (update roles-by-user user set/union roles))
+               {})))
+
+(deftest test-group-roles-by-user
+  (let [apps [(-> {:application/id 1}
+                  (permissions/give-role-to-users :foo ["user-1" "user-2"]))
+              (-> {:application/id 2}
+                  (permissions/give-role-to-users :bar ["user-1"]))]]
+    (is (= {"user-1" #{:foo :bar}
+            "user-2" #{:foo}}
+           (group-roles-by-user apps)))))
+
+(defn refresh-all-applications-cache! []
+  (events-cache/refresh!
+   all-applications-cache
+   (fn [state events]
+     ;; Because enrich-with-injections is not idempotent,
+     ;; it's necessary to hold on to the "raw" applications.
+     ;; TODO: consider making enrich-with-injections idempotent (move dissocs to hide-non-public-information and other small refactorings)
+     (let [raw-apps (reduce all-applications-view (::raw-apps state) events)
+           updated-app-ids (distinct (map :application/id events))
+           ;; TODO: batched injections: only one DB query to fetch all catalogue items etc.
+           ;;       - fetch all items in the background as a batch, use plain maps as injections
+           ;;       - change db/get-license and db/get-user-attributes to fetch all rows if ID is not defined
+           cached-injections (map-vals memoize injections)
+           enriched-apps (->> (select-keys raw-apps updated-app-ids)
+                              (map-vals #(model/enrich-with-injections % cached-injections))
+                              (merge (::enriched-apps state)))]
+       {::raw-apps raw-apps
+        ::enriched-apps enriched-apps
+        ::apps-by-user (group-apps-by-user (vals enriched-apps))
+        ::roles-by-user (group-roles-by-user (vals enriched-apps))}))))
+
+(defn get-all-unrestricted-applications []
+  (-> (refresh-all-applications-cache!)
+      ::enriched-apps
+      (vals)))
+
+(defn get-all-applications [user-id]
+  (-> (refresh-all-applications-cache!)
+      (get-in [::apps-by-user user-id])
+      (->> (map exclude-unnecessary-keys-from-overview))))
+
+(defn get-all-application-roles [user-id]
+  (-> (refresh-all-applications-cache!)
+      (get-in [::roles-by-user user-id])
+      (set)))
+
+(defn- my-application? [application]
+  (some #{:applicant :member} (:application/roles application)))
+
+(defn get-my-applications [user-id]
+  (->> (get-all-applications user-id)
+       (filter my-application?)))
+
+(defn reload-cache! []
+  ;; TODO: Here is a small chance that a user will experience a cache miss. Consider rebuilding the cache asynchronously and then `reset!` the cache.
+  (events-cache/empty! all-applications-cache)
+  (refresh-all-applications-cache!))
+
+;; empty the cache occasionally in case some of the injected entities are changed
+(mount/defstate all-applications-cache-reloader
+  :start (scheduler/start! reload-cache! (Duration/standardHours 1))
+  :stop (scheduler/stop! all-applications-cache-reloader))
diff --git a/src/clj/rems/db/attachments.clj b/src/clj/rems/db/attachments.clj
index 228a45c81..2802db41d 100644
--- a/src/clj/rems/db/attachments.clj
+++ b/src/clj/rems/db/attachments.clj
@@ -1,6 +1,6 @@
 (ns rems.db.attachments
-  (:require [rems.api.applications-v2 :as applications-v2]
-            [rems.application-util :refer [form-fields-editable?]]
+  (:require [rems.application-util :refer [form-fields-editable?]]
+            [rems.db.applications :as applications]
             [rems.auth.util :refer [throw-forbidden]]
             [rems.db.core :as db])
   (:import [java.io ByteArrayOutputStream FileInputStream File ByteArrayInputStream]
@@ -23,7 +23,7 @@
 (defn save-attachment!
   [{:keys [tempfile filename content-type]} user-id application-id item-id]
   (check-attachment-content-type content-type)
-  (let [application (applications-v2/get-application user-id application-id)
+  (let [application (applications/get-application user-id application-id)
         byte-array (with-open [input (FileInputStream. ^File tempfile)
                                buffer (ByteArrayOutputStream.)]
                      (clojure.java.io/copy input buffer)
@@ -39,7 +39,7 @@
                           :data byte-array})))
 
 (defn remove-attachment! [user-id application-id item-id]
-  (let [application (applications-v2/get-application user-id application-id)]
+  (let [application (applications/get-application user-id application-id)]
     (when-not (form-fields-editable? application)
       (throw-forbidden))
     (db/remove-attachment! {:application application-id
@@ -47,7 +47,7 @@
                             :item item-id})))
 
 (defn get-attachment [user-id application-id field-id]
-  (let [application (applications-v2/get-application user-id application-id)
+  (let [application (applications/get-application user-id application-id)
         form-id (get-in application [:application/form :form/id])]
     (when-let [attachment (db/get-attachment {:item field-id
                                               :form form-id
diff --git a/src/clj/rems/middleware.clj b/src/clj/rems/middleware.clj
index d02f4a3e9..7ded3b446 100644
--- a/src/clj/rems/middleware.clj
+++ b/src/clj/rems/middleware.clj
@@ -7,11 +7,11 @@
             [clojure.test :refer [deftest is testing]]
             [clojure.tools.logging :as log]
             [clojure.walk :refer [keywordize-keys]]
-            [rems.api.applications-v2 :as applications-v2]
             [rems.auth.auth :as auth]
             [rems.config :refer [env]]
             [rems.context :as context]
             [rems.db.api-key :as api-key]
+            [rems.db.applications :as applications]
             [rems.db.roles :as roles]
             [rems.env :refer [+defaults+]]
             [rems.layout :refer [error-page]]
@@ -83,7 +83,7 @@
               context/*flash* (:flash request)
               context/*roles* (when context/*user*
                                 (set/union (roles/get-roles (getx-user-id))
-                                           (applications-v2/get-all-application-roles (getx-user-id))))]
+                                           (applications/get-all-application-roles (getx-user-id))))]
       (with-mdc {:roles (str/join " " (sort context/*roles*))}
         (handler request)))))
 
diff --git a/src/clj/rems/poller/email.clj b/src/clj/rems/poller/email.clj
index 91f993f6c..8a28f9087 100644
--- a/src/clj/rems/poller/email.clj
+++ b/src/clj/rems/poller/email.clj
@@ -4,8 +4,8 @@
             [clojure.tools.logging :as log]
             [mount.core :as mount]
             [postal.core :as postal]
-            [rems.api.applications-v2 :as applications-v2]
             [rems.config :refer [env]]
+            [rems.db.applications :as applications]
             [rems.db.events :as events]
             [rems.db.users :as users]
             [rems.poller.common :as common]
@@ -147,7 +147,7 @@
 
 (defn event-to-emails [event]
   (when-let [app-id (:application/id event)]
-    (event-to-emails-impl event (applications-v2/get-unrestricted-application app-id))))
+    (event-to-emails-impl event (applications/get-unrestricted-application app-id))))
 
 ;;; Generic poller infrastructure
 
diff --git a/src/clj/rems/poller/entitlements.clj b/src/clj/rems/poller/entitlements.clj
index 1beb9446b..de38b46c6 100644
--- a/src/clj/rems/poller/entitlements.clj
+++ b/src/clj/rems/poller/entitlements.clj
@@ -3,7 +3,7 @@
    entitlements in the db and optionally POSTs them to a webhook."
   (:require [clojure.test :refer :all]
             [mount.core :as mount]
-            [rems.api.applications-v2 :as applications-v2]
+            [rems.db.applications :as applications]
             [rems.db.entitlements :as entitlements]
             [rems.poller.common :as common]
             [rems.scheduler :as scheduler])
@@ -17,7 +17,7 @@
                      :application.event/member-removed
                      :application.event/closed}
                    (:event/type event))
-    (let [application (applications-v2/get-unrestricted-application (:application/id event))]
+    (let [application (applications/get-unrestricted-application (:application/id event))]
       (entitlements/update-entitlements-for application))))
 
 (defn run []
diff --git a/src/clj/rems/validate.clj b/src/clj/rems/validate.clj
index 0825e988b..52bcd206b 100644
--- a/src/clj/rems/validate.clj
+++ b/src/clj/rems/validate.clj
@@ -2,13 +2,13 @@
   "Validating data in the database."
   (:require [clojure.pprint :refer [pprint]]
             [clojure.tools.logging :as log]
-            [rems.api.applications-v2 :as applications-v2]))
+            [rems.db.applications :as applications]))
 
 (defn validate []
   (log/info "Validating data")
   (try
     ;; will throw an exception if there are non-valid events
-    (applications-v2/get-all-unrestricted-applications)
+    (applications/get-all-unrestricted-applications)
     (log/info "Validations passed")
     (catch Throwable t
       (log/error t "Validations failed" (with-out-str (when-let [data (ex-data t)]


Test patch:
diff --git a/test/clj/rems/db/testing.clj b/test/clj/rems/db/testing.clj
index efec65760..fa1fcdc27 100644
--- a/test/clj/rems/db/testing.clj
+++ b/test/clj/rems/db/testing.clj
@@ -3,8 +3,8 @@
             [conman.core :as conman]
             [luminus-migrations.core :as migrations]
             [mount.core :as mount]
-            [rems.api.applications-v2]
             [rems.config :refer [env]]
+            [rems.db.applications]
             [rems.db.core :as db]
             [rems.db.test-data :as test-data]))
 
@@ -20,8 +20,8 @@
 
 (defn caches-fixture [f]
   ;; no specific teardown. relies on the teardown of test-db-fixture.
-  (mount/start #'rems.api.applications-v2/application-cache
-               #'rems.api.applications-v2/all-applications-cache)
+  (mount/start #'rems.db.applications/application-cache
+               #'rems.db.applications/all-applications-cache)
   (f))
 
 (defn test-data-fixture [f]
diff --git a/test/clj/rems/test_db.clj b/test/clj/rems/test_db.clj
index 81420a6ff..1b5f4b2df 100644
--- a/test/clj/rems/test_db.clj
+++ b/test/clj/rems/test_db.clj
@@ -4,7 +4,6 @@
             [clj-time.core :as time]
             [clojure.string :refer [split-lines]]
             [clojure.test :refer :all]
-            [rems.api.applications-v2 :as applications-v2]
             [rems.auth.ForbiddenException]
             [rems.config]
             [rems.context :as context]
@@ -199,7 +198,7 @@
                                       :application-id app-id
                                       :time (time/now)
                                       :comment ""})))
-    (is (= :application.state/approved (:application/state (applications-v2/get-application uid app-id))))
+    (is (= :application.state/approved (:application/state (applications/get-application uid app-id))))
 
     (entitlements-poller/run)
     (is (= ["resid111" "resid222"] (sort (map :resid (db/get-entitlements {:application app-id}))))
diff --git a/test/clj/rems/test_performance.clj b/test/clj/rems/test_performance.clj
index 0ce018d44..864f108a5 100644
--- a/test/clj/rems/test_performance.clj
+++ b/test/clj/rems/test_performance.clj
@@ -3,8 +3,8 @@
             [criterium.core :as criterium]
             [medley.core :refer [map-vals]]
             [mount.core :as mount]
-            [rems.api.applications-v2 :as applications-v2]
             [rems.api.applications :as applications-api]
+            [rems.db.applications :as applications]
             [rems.db.events :as events])
   (:import [java.util Locale]))
 
@@ -46,17 +46,17 @@
                       :benchmark test-get-application-events}])))
 
 (defn benchmark-get-all-applications []
-  (let [test-get-all-unrestricted-applications #(doall (applications-v2/get-all-unrestricted-applications))
-        test-get-all-applications #(doall (applications-v2/get-all-applications "alice"))
-        test-get-all-application-roles #(doall (applications-v2/get-all-application-roles "developer"))
-        test-get-my-applications #(doall (applications-v2/get-my-applications "alice"))
+  (let [test-get-all-unrestricted-applications #(doall (applications/get-all-unrestricted-applications))
+        test-get-all-applications #(doall (applications/get-all-applications "alice"))
+        test-get-all-application-roles #(doall (applications/get-all-application-roles "developer"))
+        test-get-my-applications #(doall (applications/get-my-applications "alice"))
         ;; developer can view much more applications than alice, so it takes longer to filter reviews from all apps
         test-get-todos #(doall (applications-api/get-todos "developer"))
         no-cache (fn []
-                   (mount/stop #'applications-v2/all-applications-cache))
+                   (mount/stop #'applications/all-applications-cache))
         cached (fn []
-                 (mount/stop #'applications-v2/all-applications-cache)
-                 (mount/start #'applications-v2/all-applications-cache)
+                 (mount/stop #'applications/all-applications-cache)
+                 (mount/start #'applications/all-applications-cache)
                  (test-get-all-unrestricted-applications))]
     (run-benchmarks [{:name "get-all-unrestricted-applications, no cache"
                       :benchmark test-get-all-unrestricted-applications
@@ -76,15 +76,15 @@
                      {:name "get-todos, cached"
                       :benchmark test-get-todos
                       :setup cached}])
-    (println "cache size" (mm/measure applications-v2/all-applications-cache))))
+    (println "cache size" (mm/measure applications/all-applications-cache))))
 
 (defn benchmark-get-application []
-  (let [test-get-application #(applications-v2/get-application "developer" 12)
+  (let [test-get-application #(applications/get-application "developer" 12)
         no-cache (fn []
-                   (mount/stop #'applications-v2/application-cache))
+                   (mount/stop #'applications/application-cache))
         cached (fn []
-                 (mount/stop #'applications-v2/application-cache)
-                 (mount/start #'applications-v2/application-cache)
+                 (mount/stop #'applications/application-cache)
+                 (mount/start #'applications/application-cache)
                  (test-get-application))]
     (run-benchmarks [{:name "get-application, no cache"
                       :benchmark test-get-application
@@ -92,7 +92,7 @@
                      {:name "get-application, cached"
                       :benchmark test-get-application
                       :setup cached}])
-    (println "cache size" (mm/measure applications-v2/application-cache))))
+    (println "cache size" (mm/measure applications/application-cache))))
 
 (comment
   ;; Note: If clj-memory-meter throws InaccessibleObjectException on Java 9+,