deps.edn and monorepos VI (Polylith)
This is part of an ongoing series of blog posts about our ever-evolving use of the Clojure CLI,
deps.edn
, and Polylith, with our monorepo at
World Singles Networks.
The Monorepo/Polylith Series
This blog post is part of an ongoing series following our experiences with our Clojure monorepo and our migration to Polylith:
- deps.edn and monorepos
- deps.edn and monorepos II
- deps.edn and monorepos III (Polylith)
- deps.edn and monorepos IV
- deps.edn and monorepos V (Polylith)
- deps.edn and monorepos VI (Polylith) (this post)
- deps.edn and monorepos VII (Polylith)
- deps.edn and monorepos VIII (Polylith)
- deps.edn and monorepos IX (Polylith)
- deps.edn and monorepos X (Polylith)
- deps.edn and monorepos XI (Polylith)
Part VI
A lot of things have changed in the month (and a bit) since my last post in this series!
Our refactoring to Polylith has ramped back up, Polylith itself has had a new alpha release,
tools.build
has continued to evolve nicely, and Java 17 has been released!
Polylith
We have refactored two more applications into bases
and projects
so about a quarter of
our codebase is Polylith-shaped now. The poly deps
matrix no longer looks like a couple
of dozen unrelated components
and now shows bases
that actually depend on them!
The rewriting of our legacy (non-Clojure) code is now all going to Polylith bricks and as we add new features to our dating platform, that is also going into Polylith as new bricks.
I mentioned back in March that we were
switching from clj-http
to httpkit
and that has been completed but it had the side effect that we have lost some telemetry in
New Relic around "web external" activity in our apps because it doesn't recognize httpkit
's
calls. The obvious thing at this point would be to switch to something like
hato
since that wraps Java's built-in HttpClient
functionality but, unfortunately, our legacy (non-Clojure) code still has to run on Java 8
and a lot of our Clojure code is shared between those apps and our "modern" (pure Clojure) apps
that run on more recent Java versions. I've been experimenting with hato
in our test suite
code, since that is not shared with the legacy apps, and I've decided that this is a good
opportunity to leverage the "swappable implementation" feature of Polylith's components
.
We're going to write an http-client
interface (component) and have two implementations:
one using httpkit
and one using hato
and then our legacy apps can use the httpkit
-based
implementation while our other apps can use the hato
-based implementation, with the shared
code written against the common interface. We'll be able to switch projects
over one at a time
if we want and we'll be able to develop against either implementation based on
profiles in Polylith.
As noted above, Polylith has had a new alpha release which includes the work I talked about
in the last post to install poly
as a Clojure CLI "tool" and to run per-project test suite
fixtures, as well as now being able to test individual bricks. Right now, we're running against
a SHA on master so that we can pick up a recent fix for those per-project test suite fixtures
and support for data_readers.clj
.
tools.build
The uber
task in tools.build
has now reached parity with depstar
's functionality so
I have archived depstar
to encourage people to switch over to tools.build
. The log4j2
plugins cache merging from depstar
has been spun out into a separate project that provides a
log4j2 plugins cache conflict handler
for tools.build
(as of v0.4.0).
In addition to switching all of my OSS projects over to tools.build
for JAR building,
I've been able to switch our monorepo at work over to it as well for uberjar building,
and I've abstracted a lot of the common code from various build.clj
files to a new
library -- build-clj -- that lets you
simplify your build.clj
file by providing sane defaults for a lot of the options
that tools.build
offers. That build-clj
library automatically includes the log4j2
conflict handler mentioned above.
I've also created a new, simpler tool for creating new CLI / deps.edn
projects, based
on tools.build
as I hinted at in part IV of this series:
deps-new. In particular, this new tool makes
it much, much easier to write your own project templates since they can be almost entirely
declarative with all the "heavy lifting" done by tools.build
itself.
In part IV, I showed our :build
alias which has now been simplified to this:
:build
{:deps {org.clojure/clojure {:mvn/version "1.11.0-alpha2"}
io.github.seancorfield/build-clj {:git/tag "v0.4.0" :git/sha "54e39ae"
:exclusions [org.slf4j/slf4j-nop]}
;; and local build tools:
worldsingles/build {:local/root "build"}
poly/artifact-uploader-cli {:local/root "bases/artifact-uploader-cli"}
poly/artifact-uploader {:local/root "components/artifact-uploader"}}
:ns-default build}
Gone is the dependency on depstar
, and the tools.build
dependency has been
replaced by my build-clj
wrapper which has simplified our artifact building
code substantially (all my OSS projects also use build-clj
-- see, for example,
next.jdbc
's build.clj
).
Oh, and we're on Clojure 1.11 Alpha 2 in production (as of today).
Java 17
Even though our production systems run on Java 11 (except for our legacy apps), we've been testing locally on Java 14, 15, and 16 so that we can be ready for the new LTS release, Java 17. We've been testing on that for about a week now but we're still blocked from upgrading production by lack of support for Java 17 in New Relic.
They just released version 7.3.0 with support for Java 16 (yesterday!), and they plan to support Java 17 fully in version 7.4.0. See issue 418 for the ongoing work, which is basically complete, but there are still a few issues to shake out before they're fully there.
The timing is pretty good for us really since 7.4.0 will likely be available before we go live on our new virtual server farm at the data center so we expect to roll straight to Java 17, from Java 11, at that point.