@@ -1523,6 +1523,93 @@ used in this example for the sake of brevity.
15231523Now that we have both a server and client, we can `(reset)` the REPL
15241524and check the web application at: <http://localhost:3000>
15251525
1526+ == Existing Applications
1527+
1528+ So far we have worked on the assumption that you are building a Duct
1529+ application from scratch, but what if you have an existing application?
1530+ Can Duct provide any benefit in that case?
1531+
1532+ If you use Integrant, you can use parts of Duct. This section will cover
1533+ common use-cases.
1534+
1535+ === Integrant '`main`' replacement
1536+
1537+ A common pattern for using Integrant have a `-main` function that loads
1538+ and initiates an Integrant configuration. In many cases, you can use
1539+ Duct to replace this with a data-driven approach.
1540+
1541+ For example, suppose you've written an application with a custom server
1542+ and worker queue component. You may have an Integrant configuration file
1543+ that looks like this:
1544+
1545+ .resources/example/app/config.edn
1546+ [,clojure]
1547+ ----
1548+ {:example.app/server
1549+ {:queue #ig/ref :example.app/worker-queue}
1550+
1551+ :example.app/worker-queue
1552+ {:worker-threads 32}}
1553+ ----
1554+
1555+ In order to run this configuration, you have a main function that loads
1556+ in the config file and populates the it with additional values from the
1557+ environment. In the example below, the server port number is pulled from
1558+ the `PORT` environment variable.
1559+
1560+ .src/example/app/main.clj
1561+ [,clojure]
1562+ ----
1563+ (ns example.app.main
1564+ (:require [clojure.java.io :as io]
1565+ [integrant.core :as ig]))
1566+
1567+ (defn -main [& _args]
1568+ (let [port (some-> (System/getenv "PORT")
1569+ (Integer/parseInt)
1570+ (or 3000))
1571+ config (-> (io/resource "example/app/config.edn")
1572+ (slurp)
1573+ (ig/read-string)
1574+ (assoc-in [:example.app/server :port] port))]
1575+ (ig/load-namespaces config)
1576+ (ig/init config)))
1577+ ----
1578+
1579+ Duct can be used to replace all this with a data-driven configuration.
1580+ In your `deps.edn` file, add a Duct alias:
1581+
1582+ .deps.edn
1583+ [,clojure]
1584+ ----
1585+ {:aliases
1586+ {:duct {:extra-deps {org.duct-framework/main {:mvn/version "0.1.11"}}
1587+ :main-opts ["-m" "duct.main"]}
1588+ ;; rest of your deps.edn
1589+ }}
1590+ ----
1591+
1592+ Then move your configuration into `duct.edn` under the `:system` key.
1593+ Use the `:vars` key to define the options you want to pull from the
1594+ environment or from command-line options.
1595+
1596+ .duct.edn
1597+ [,clojure]
1598+ ----
1599+ {:vars
1600+ {port {:env PORT, :type :int, :default 3000}
1601+ :system
1602+ {:example.app/server
1603+ {:port #ig/var port
1604+ :queue #ig/ref :example.app/worker-queue}
1605+
1606+ :example.app/worker-queue
1607+ {:worker-threads 32}}}
1608+ ----
1609+
1610+ To run your application, use `clojure -M:duct`, or the `duct` alias
1611+ defined in the <<Project Setup>> section.
1612+
15261613== Integrations
15271614
15281615=== Docker
0 commit comments