kit-clj / kit

Lightweight, modular framework for scalable web development in Clojure
https://kit-clj.github.io/
MIT License
463 stars 43 forks source link

how to add multi db connections #95

Closed vinurs closed 1 year ago

vinurs commented 1 year ago

if i have two pgs, then how to support it

yogthos commented 1 year ago

You'd have to add a new component in resources/system.edn, e.g:

:db.sql/connection-otherdb #profile {:dev {:jdbc-url "<url>"},
                              :test {:jdbc-url "<url>"},
                              :prod {:jdbc-url #env JDBC_OTHERDB_URL}}

Then you'd want to create a separate set of queries and migrations for it:

 :db.sql/query-fn {:conn #ig/ref :db.sql/connection-otherdb,
                   :options {},
                   :filename "sql/queries-otherdb.sql"}
 :db.sql/migrations {:store :database,
                     :migration-dir "migrations_other/"
                     :db {:datasource #ig/ref :db.sql/connection-otherdb},
                     :migrate-on-init? true}
vinurs commented 1 year ago

is that :db.sql/query-fn should change to

:db.sql/other-query-fn {:conn #ig/ref :db.sql/connection-otherdb,
                   :options {},
                   :filename "sql/queries-otherdb.sql"}
yogthos commented 1 year ago

oh yeah, you'll need unique keys for query-fn and migrations as well

vinurs commented 1 year ago

i add a new connection

 :db.sql/connection-nis
 #profile {:dev  {:jdbc-url "postgresql://localhost:5432/db_scaffold?user=db_scaffold&password=db_scaffold&useSSL=true"}
           :test {}
           :prod {:jdbc-url   #env JDBC_URL
                  :init-size  1
                  :min-idle   1
                  :max-idle   8
                  :max-active 32}}

 :db.sql/nis-query-fn
 {:conn     #ig/ref :db.sql/connection-nis
  :options  {}
  :filenames ["queries.sql" "queries111.sql"]
  }

then run (go) output errors

clojure.lang.ExceptionInfo: Error on key :db.sql/connection-nis when building system
{:reason :integrant.core/build-threw-exception, :system #:db.sql{:connection #object[com.zaxxer.hikari.HikariDataSource 0x70642809 "HikariDataSource (HikariPool-1)"]}, :function #multifn[init-key 0x6cdf190e], :key :db.sql/connection-nis, :value {:jdbc-url "postgresql://localhost:5432/db_scaffold?user=db_scaffold&password=db_scaffold&useSSL=true"}}
 at integrant.core$build_exception.invokeStatic (core.cljc:285)
    integrant.core$build_exception.invoke (core.cljc:284)
    integrant.core$try_build_action.invokeStatic (core.cljc:296)
    integrant.core$try_build_action.invoke (core.cljc:293)
    integrant.core$build_key.invokeStatic (core.cljc:302)
    integrant.core$build_key.invoke (core.cljc:298)
    clojure.core$partial$fn__5912.invoke (core.clj:2656)
    clojure.core.protocols$fn__8249.invokeStatic (protocols.clj:168)
    clojure.core.protocols/fn (protocols.clj:124)
    clojure.core.protocols$fn__8204$G__8199__8213.invoke (protocols.clj:19)
    clojure.core.protocols$seq_reduce.invokeStatic (protocols.clj:31)
    clojure.core.protocols$fn__8236.invokeStatic (protocols.clj:75)
    clojure.core.protocols/fn (protocols.clj:75)
    clojure.core.protocols$fn__8178$G__8173__8191.invoke (protocols.clj:13)
    clojure.core$reduce.invokeStatic (core.clj:6886)
    clojure.core$reduce.invoke (core.clj:6868)
    integrant.core$build.invokeStatic (core.cljc:325)
    integrant.core$build.invoke (core.cljc:305)
    integrant.core$init.invokeStatic (core.cljc:431)
    integrant.core$init.invoke (core.cljc:423)
    integrant.core$init.invokeStatic (core.cljc:428)
    integrant.core$init.invoke (core.cljc:423)
    integrant.repl$init_system$fn__3879.invoke (repl.clj:37)
    integrant.repl$build_system.invokeStatic (repl.clj:24)
    integrant.repl$build_system.invoke (repl.clj:22)
    integrant.repl$init_system.invokeStatic (repl.clj:34)
    integrant.repl$init_system.invoke (repl.clj:33)
    integrant.repl$init$fn__3891.invoke (repl.clj:54)
    clojure.lang.AFn.applyToHelper (AFn.java:154)
    clojure.lang.AFn.applyTo (AFn.java:144)
    clojure.lang.Var.alterRoot (Var.java:308)
    clojure.core$alter_var_root.invokeStatic (core.clj:5535)
    clojure.core$alter_var_root.doInvoke (core.clj:5530)
    clojure.lang.RestFn.invoke (RestFn.java:425)
    integrant.repl$init.invokeStatic (repl.clj:52)
    integrant.repl$init.invoke (repl.clj:49)
    integrant.repl$go.invokeStatic (repl.clj:61)
    integrant.repl$go.invoke (repl.clj:57)
    integrant.repl$go.invokeStatic (repl.clj:58)
    integrant.repl$go.invoke (repl.clj:57)
    user$eval48963.invokeStatic (NO_SOURCE_FILE:58)
    user$eval48963.invoke (NO_SOURCE_FILE:58)
    clojure.lang.Compiler.eval (Compiler.java:7194)
    clojure.lang.Compiler.eval (Compiler.java:7149)
    clojure.core$eval.invokeStatic (core.clj:3215)
    clojure.core$eval.invoke (core.clj:3211)
    nrepl.middleware.interruptible_eval$evaluate$fn__44464$fn__44465.invoke (interruptible_eval.clj:87)
    clojure.lang.AFn.applyToHelper (AFn.java:152)
    clojure.lang.AFn.applyTo (AFn.java:144)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.core$with_bindings_STAR_.invokeStatic (core.clj:1990)
    clojure.core$with_bindings_STAR_.doInvoke (core.clj:1990)
    clojure.lang.RestFn.invoke (RestFn.java:425)
    nrepl.middleware.interruptible_eval$evaluate$fn__44464.invoke (interruptible_eval.clj:87)
    clojure.main$repl$read_eval_print__9206$fn__9209.invoke (main.clj:437)
    clojure.main$repl$read_eval_print__9206.invoke (main.clj:437)
    clojure.main$repl$fn__9215.invoke (main.clj:458)
    clojure.main$repl.invokeStatic (main.clj:458)
    clojure.main$repl.doInvoke (main.clj:368)
    clojure.lang.RestFn.invoke (RestFn.java:1523)
    nrepl.middleware.interruptible_eval$evaluate.invokeStatic (interruptible_eval.clj:84)
    nrepl.middleware.interruptible_eval$evaluate.invoke (interruptible_eval.clj:56)
    nrepl.middleware.interruptible_eval$interruptible_eval$fn__44497$fn__44501.invoke (interruptible_eval.clj:152)
    clojure.lang.AFn.run (AFn.java:22)
    nrepl.middleware.session$session_exec$main_loop__44567$fn__44571.invoke (session.clj:218)
    nrepl.middleware.session$session_exec$main_loop__44567.invoke (session.clj:217)
    clojure.lang.AFn.run (AFn.java:22)
    java.lang.Thread.run (Thread.java:833)
Caused by: java.lang.IllegalArgumentException: No method in multimethod 'init-key' for dispatch value: :db.sql/connection-nis
 at clojure.lang.MultiFn.getFn (MultiFn.java:156)
    clojure.lang.MultiFn.invoke (MultiFn.java:233)
    integrant.core$try_build_action.invokeStatic (core.cljc:294)
    integrant.core$try_build_action.invoke (core.cljc:293)
    integrant.core$build_key.invokeStatic (core.cljc:302)
    integrant.core$build_key.invoke (core.cljc:298)
    clojure.core$partial$fn__5912.invoke (core.clj:2656)
    clojure.core.protocols$fn__8249.invokeStatic (protocols.clj:168)
    clojure.core.protocols/fn (protocols.clj:124)
    clojure.core.protocols$fn__8204$G__8199__8213.invoke (protocols.clj:19)
    clojure.core.protocols$seq_reduce.invokeStatic (protocols.clj:31)
    clojure.core.protocols$fn__8236.invokeStatic (protocols.clj:75)
    clojure.core.protocols/fn (protocols.clj:75)
    clojure.core.protocols$fn__8178$G__8173__8191.invoke (protocols.clj:13)
    clojure.core$reduce.invokeStatic (core.clj:6886)
    clojure.core$reduce.invoke (core.clj:6868)
    integrant.core$build.invokeStatic (core.cljc:325)
    integrant.core$build.invoke (core.cljc:305)
    integrant.core$init.invokeStatic (core.cljc:431)
    integrant.core$init.invoke (core.cljc:423)
    integrant.core$init.invokeStatic (core.cljc:428)
    integrant.core$init.invoke (core.cljc:423)
    integrant.repl$init_system$fn__3879.invoke (repl.clj:37)
    integrant.repl$build_system.invokeStatic (repl.clj:24)
    integrant.repl$build_system.invoke (repl.clj:22)
    integrant.repl$init_system.invokeStatic (repl.clj:34)
    integrant.repl$init_system.invoke (repl.clj:33)
    integrant.repl$init$fn__3891.invoke (repl.clj:54)
    clojure.lang.AFn.applyToHelper (AFn.java:154)
    clojure.lang.AFn.applyTo (AFn.java:144)
    clojure.lang.Var.alterRoot (Var.java:308)
    clojure.core$alter_var_root.invokeStatic (core.clj:5535)
    clojure.core$alter_var_root.doInvoke (core.clj:5530)
    clojure.lang.RestFn.invoke (RestFn.java:425)
    integrant.repl$init.invokeStatic (repl.clj:52)
    integrant.repl$init.invoke (repl.clj:49)
    integrant.repl$go.invokeStatic (repl.clj:61)
    integrant.repl$go.invoke (repl.clj:57)
    integrant.repl$go.invokeStatic (repl.clj:58)
    integrant.repl$go.invoke (repl.clj:57)
    user$eval48963.invokeStatic (NO_SOURCE_FILE:58)
    user$eval48963.invoke (NO_SOURCE_FILE:58)
    clojure.lang.Compiler.eval (Compiler.java:7194)
    clojure.lang.Compiler.eval (Compiler.java:7149)
    clojure.core$eval.invokeStatic (core.clj:3215)
    clojure.core$eval.invoke (core.clj:3211)
    nrepl.middleware.interruptible_eval$evaluate$fn__44464$fn__44465.invoke (interruptible_eval.clj:87)
    clojure.lang.AFn.applyToHelper (AFn.java:152)
    clojure.lang.AFn.applyTo (AFn.java:144)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.core$with_bindings_STAR_.invokeStatic (core.clj:1990)
    clojure.core$with_bindings_STAR_.doInvoke (core.clj:1990)
    clojure.lang.RestFn.invoke (RestFn.java:425)
    nrepl.middleware.interruptible_eval$evaluate$fn__44464.invoke (interruptible_eval.clj:87)
    clojure.main$repl$read_eval_print__9206$fn__9209.invoke (main.clj:437)
    clojure.main$repl$read_eval_print__9206.invoke (main.clj:437)
    clojure.main$repl$fn__9215.invoke (main.clj:458)
    clojure.main$repl.invokeStatic (main.clj:458)
    clojure.main$repl.doInvoke (main.clj:368)
    clojure.lang.RestFn.invoke (RestFn.java:1523)
    nrepl.middleware.interruptible_eval$evaluate.invokeStatic (interruptible_eval.clj:84)
    nrepl.middleware.interruptible_eval$evaluate.invoke (interruptible_eval.clj:56)
    nrepl.middleware.interruptible_eval$interruptible_eval$fn__44497$fn__44501.invoke (interruptible_eval.clj:152)
    clojure.lang.AFn.run (AFn.java:22)
    nrepl.middleware.session$session_exec$main_loop__44567$fn__44571.invoke (session.clj:218)
    nrepl.middleware.session$session_exec$main_loop__44567.invoke (session.clj:217)
    clojure.lang.AFn.run (AFn.java:22)
    java.lang.Thread.run (Thread.java:833)
yogthos commented 1 year ago

Once you have the config entries you also need the corresponding Integrant multimethods that implement them, hence the error you're seeing:

Caused by: java.lang.IllegalArgumentException: No method in multimethod 'init-key' for dispatch value: :db.sql/connection-nis

here's what the ones provided by default look like https://github.com/kit-clj/kit/blob/master/libs/kit-sql-conman/src/kit/edge/db/sql/conman.clj

it might be worth looking over the official Integrant docs as well https://github.com/weavejester/integrant

vinurs commented 1 year ago

ok, works now, thanks for ur help