3
votes

Regroupement de connexions dans Clojure

Je ne comprends pas l'utilisation des fonctions pool-db et connection dans ce guide de regroupement de connexions .

(def connection (get-pool db-spec))

; usage in code
(jdbc/query connection ["SELECT SUM(1, 2, 3)"])

Pourquoi ne pouvons-nous pas simplement faire?

(defn- get-pool
    "Creates Database connection pool to be used in queries"
    [{:keys [host-port db-name username password]}]
    (let [pool (doto (ComboPooledDataSource.)
                   (.setDriverClass "com.mysql.cj.jdbc.Driver")
                   (.setJdbcUrl (str "jdbc:mysql://"
                                     host-port
                                     "/" db-name))
                   (.setUser username)
                   (.setPassword password)
                   ;; expire excess connections after 30 minutes of inactivity:
                   (.setMaxIdleTimeExcessConnections (* 30 60))
                   ;; expire connections after 3 hours of inactivity:
                   (.setMaxIdleTime (* 3 60 60)))]
        {:datasource pool}))


(def pool-db (delay (get-pool db-spec)))


(defn connection [] @pool-db)

; usage in code
(jdbc/query (connection) ["Select SUM(1, 2, 3)"])


0 commentaires

4 Réponses :


1
votes

Dans votre application, vous souhaitez créer le pool une seule fois et le réutiliser. Pour cette raison, delay est utilisé pour envelopper la méthode (get-pool db-spec) afin que cette méthode ne sera invoquée que la première fois qu'elle est forcée avec deref / @ et mettra en cache le pool et le retournera lors des appels forcés suivants


1 commentaires

Le pool ne sera-t-il pas encore créé une seule fois si nous utilisons (def connection (get-pool db-spec)) . Je pense que cela créera toujours le pool une fois et le stockera en connexion variable. Ne renverra-t-il pas la valeur stockée dans les appels suivants dans ce cas également?



1
votes

La différence est que dans la version retardée, un pool ne sera créé que s'il est appelé (ce qui peut ne pas être le cas si tout était mis en cache), mais la version sans délai instanciera un pool quoi qu'il arrive, c'est-à-dire toujours , même si aucune connexion à une base de données n'est utilisée.

delay ne s'exécute que si deref est appelé et ne fait rien autrement.


0 commentaires

4
votes

Le délai garantit que vous créez le pool de connexions la première fois que vous essayez de l'utiliser, plutôt que lorsque l'espace de noms est chargé.

C'est une bonne idée car la création de votre pool de connexions peut échouer pour l'une des nombreuses raisons, et s'il échoue pendant le chargement de l'espace de noms, vous obtiendrez un comportement étrange - toute définition après l'échec de la création de votre pool de connexions ne le sera pas être évalué, par exemple.

En général, les définitions de var de niveau supérieur doivent être construites pour qu'elles ne puissent pas échouer à l'exécution.

Gardez à l'esprit qu'ils peuvent également être évalués pendant le processus de compilation AOT, comme le note amalloy ci-dessous.


3 commentaires

ITYM, ne peut pas échouer au moment de la compilation?


Je dirais en outre que la raison la plus importante pour laquelle c'est une mauvaise idée est que votre environnement de compilation peut être totalement différent de votre environnement d'exécution, par exemple si vous construisez un uberjar à déployer. Si vous essayez de vous connecter à la base de données de production à partir de votre serveur de compilation / machine de développement, cela échouera et vous ne pourrez pas créer le fichier jar.


Je travaille normalement dans le tbh REPL mais oui - totalement - vous avez raison sur les problèmes de compilation AOT.



0
votes

Je vous suggère d'utiliser une bibliothèque existante pour gérer le regroupement de connexions, quelque chose comme hikari-cp , qui est hautement configurable et fonctionne avec de nombreux implémentations de SQL.


0 commentaires