Skip to content

Commit ea7e8b6

Browse files
committed
Add section on Existing Applications
1 parent dd91bdd commit ea7e8b6

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

index.adoc

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,6 +1523,93 @@ used in this example for the sake of brevity.
15231523
Now that we have both a server and client, we can `(reset)` the REPL
15241524
and 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

Comments
 (0)