polylith

2024-09-23T19:25:15.557479Z

Hi all - continuing to experience difficulty leveraging reuse of the same interface across multiple components, only one of which is provided in any given project. For example, I have the following project structure:

bases
  cli
    resources
    src
      tlns
        cli
          core.clj
    deps.edn
components
  do-thing-one
    resources
    src
      tlns
        shared-interface
          core.clj
          interface.clj
    deps.edn
  do-thing-two
    resources
    src
      tlns
        shared-interface
          core.clj
          interface.clj
    deps.edn
  maybe-depended-upon
    resources
    src
      tlns
        maybe-depended-upon
          core.clj
          interface.clj
    deps.edn
projects
  do-thing-one-via-cli
    deps.edn
  do-thing-two-via-cli
    deps.edn
deps.edn
• Component maybe-depended-upon defines an interface tlns.maybe-depended-upon and has no other dependencies internal or external. • Component do-thing-one defines an interface tlns.hared-interface also implemented by component do-thing-two, but has no other dependencies internal or external. • Component do-thing-two defines the same interface tlns.shared-interface, but with a different implementation that internally depends upon the interface tlns.maybe-depended-upon. Crucially, this dependency is not present in the implementation of do-thing-one. • Base cli defines its own dedicated ns tlns.cli which only depends internally upon the interface tlns.shared-interface. • Project do-thing-one-via-cli depends upon base cli and component do-thing-one. • Project do-thing-two-via-cli depends upon base cli and component do-thing-two. • In the root deps.edn, there are separate profiles +dt1 and +dt2 that keep the conflicting dependencies separated, per the documentation. With this setup, however, attempting to run the info command gives me the following error: Error 107: Missing components in the do-thing-one-via-cli project for these interfaces: maybe-depended-upon This is not correct, as only the implementation in project do-thing-two-via-cli actually depends upon maybe-depended-upon; the do-thing-one-via-cli has no such dependencies in its implementation. What is the recommended way to go about having multiple implementations of the same interface that themselves have distinct dependencies per implementation?

Leo E 2025-02-09T14:00:40.559139Z

In 99 out of 100 cases the interfaces will be identical for both differently implemented components. Is there a way to duplicate an identical interface from component to component without copy-pasting it?

seancorfield 2025-02-09T14:03:32.841929Z

Nothing built-in, no.

Leo E 2025-02-09T14:04:29.519179Z

Interfaces commonly has a lot of docstrings in real code and it will be cool not to duplicate whole interface. Maybe any un-standart, but still easy(not potemkin-like) ways exists?

seancorfield 2025-02-09T14:11:48.975589Z

I just copy/paste the file in my editor, as a starting point. Multiple implementations are relatively rare - we had at most three, I think, in a 200 brick project.

seancorfield 2025-02-09T14:13:08.340599Z

And then I tend to edit the docstrings to highlight differences in functionality. And most times there is some difference in the code too...

🔥 1
seancorfield 2024-09-23T19:38:26.431039Z

Have you read through https://cljdoc.org/d/polylith/clj-poly/0.2.21/doc/profile ? Does it make sense, or do you have questions?

2024-09-23T19:46:21.344779Z

@seancorfield Yes, I have, but there must still be something I'm failing utterly to grasp.

2024-09-23T19:46:30.607079Z

Will give it a read again.

seancorfield 2024-09-23T19:47:56.590339Z

Do you have :+default in deps.edn? One of your profiles needs to be the default.

seancorfield 2024-09-23T19:49:07.769819Z

And how exactly are you running info? Are you specifying which profile(s) it should use?

2024-09-23T19:51:20.126389Z

I do, yes. And I get the same error regardless of whether I run info alone, or specifying a profile (either +default or one of the two mentioned)

seancorfield 2024-09-23T19:52:36.475209Z

We have an almost identical setup at work with an i18n component and an i18n-preview component, both with an identical ws.i18n.interface and different impl nses that depend on different components, and our preview project depends on i18n-preview and info works fine for us...

2024-09-23T19:53:06.569949Z

OK, then there's almost certainly something I've screwed up somehow. Will keep hammering at it.

seancorfield 2024-09-23T19:54:41.797899Z

For comparison, here are our profiles from the workspace deps.edn:

:+default {:extra-deps {;; by default, we use the real i18n and web server:
                          poly/i18n        {:local/root "components/i18n"}
                          poly/web-server  {:local/root "components/web-server"}}
             :extra-paths ["components/i18n/test"
                           "components/web-server/test"]}

  :+preview {:extra-deps {;; or the preview i18n and the real web server:
                          poly/i18n        {:local/root "components/i18n-preview"}
                          poly/web-server  {:local/root "components/web-server"}}
             :extra-paths ["components/i18n-preview/test"
                           "components/web-server/test"]}

2024-09-23T19:55:36.566099Z

yup, that is precisely the setup I've got

2024-09-23T19:58:52.751329Z

Do your separate impl nses share the same ns name in each component, or do they differ?

seancorfield 2024-09-23T19:59:24.065049Z

Same ns, but I wouldn't expect that to matter...

2024-09-23T19:59:37.925569Z

Yeah, it didn't in my experiments. Still the same error no matter what I attempt to do

seancorfield 2024-09-23T20:06:19.494889Z

I just deliberately broke my preview i18n component impl into another component -- so there's a dependency on a new i18n-sub component only in i18n-preview which is under that +preview alias -- and info only warns that the preview project is missing that dep (correct), and when I add i18n-sub to just that project then info is happy.

seancorfield 2024-09-23T20:07:45.504429Z

Are you sure your two project deps.edn really have the correct do-thing-<nnn> deps? And none of your bases or components have any components in their deps.edn?

👀 1
2024-09-23T20:11:35.052359Z

I'm going to write up a nonsensitive example to see if I can reproduce and push to public GH.

2024-09-23T20:13:34.758849Z

Everything looks to be correct as asked above.

2024-09-23T20:13:55.026159Z

no bases/components in base/component deps.edn

2024-09-23T20:14:20.418089Z

and the projects are correctly referring to the correct do-thing-<n> deps.

seancorfield 2024-09-23T20:39:53.124239Z

I'll be interested to see how your setup is different to ours, and to the user profile example in the docs...

2024-09-23T20:40:00.302289Z

@seancorfield Here's a repo showing the issue: https://github.com/awebneck/polylith-shared-interface-example

2024-09-23T20:44:46.237049Z

And logs of some executions in the poly console: bare info shows the error

shared-int-example$ info
  stable since: 7be5074

  projects: 3   interfaces: 2
  bases:    1   components: 3

  active profiles: default

  project                 alias  status   dev  dt2
  -------------------------------------   --------
  do-thing-one-via-cli *  dt1     ---     ---  --
  do-thing-two-via-cli *  dt2     ---     ---  --
  development +           dev     s--     s--  --

  interface            brick                   dt1  dt2   dev  dt2
  ------------------------------------------   --------   --------
  maybe-depended-upon  maybe-depended-upon *   ---  stx   st-  --
  shared-interface     do-thing-one *          stx  ---   st-  --
  shared-interface     do-thing-two *          ---  stx   ---  st
  -                    cli *                   stx  stx   st-  --

  Error 107: Missing components in the do-thing-one-via-cli project for these interfaces: maybe-depended-upon
info + does not give the error
shared-int-example$ info +
  stable since: 7be5074

  projects: 3   interfaces: 2
  bases:    1   components: 3

  project                 alias  status   dev  default  dt2
  -------------------------------------   -----------------
  do-thing-one-via-cli *  dt1     ---     ---    --     --
  do-thing-two-via-cli *  dt2     ---     ---    --     --
  development +           dev     s--     s--    --     --

  interface            brick                   dt1  dt2   dev  default  dt2
  ------------------------------------------   --------   -----------------
  maybe-depended-upon  maybe-depended-upon *   ---  stx   st-    --     --
  shared-interface     do-thing-one *          stx  ---   ---    st     --
  shared-interface     do-thing-two *          ---  stx   ---    --     st
  -                    cli *                   stx  stx   st-    --     --
info +default does show the error
shared-int-example$ info +default
  stable since: 7be5074

  projects: 3   interfaces: 2
  bases:    1   components: 3

  active profiles: default

  project                 alias  status   dev  dt2
  -------------------------------------   --------
  do-thing-one-via-cli *  dt1     ---     ---  --
  do-thing-two-via-cli *  dt2     ---     ---  --
  development +           dev     s--     s--  --

  interface            brick                   dt1  dt2   dev  dt2
  ------------------------------------------   --------   --------
  maybe-depended-upon  maybe-depended-upon *   ---  stx   st-  --
  shared-interface     do-thing-one *          stx  ---   st-  --
  shared-interface     do-thing-two *          ---  stx   ---  st
  -                    cli *                   stx  stx   st-  --

  Error 107: Missing components in the do-thing-one-via-cli project for these interfaces: maybe-depended-upon
as does info +dt2 (the other profile)
shared-int-example$ info +dt2
  stable since: 7be5074

  projects: 3   interfaces: 2
  bases:    1   components: 3

  active profiles: dt2

  project                 alias  status   dev  default
  -------------------------------------   ------------
  do-thing-one-via-cli *  dt1     ---     ---    --
  do-thing-two-via-cli *  dt2     ---     ---    --
  development +           dev     s--     s--    --

  interface            brick                   dt1  dt2   dev  default
  ------------------------------------------   --------   ------------
  maybe-depended-upon  maybe-depended-upon *   ---  stx   st-    --
  shared-interface     do-thing-one *          stx  ---   ---    st
  shared-interface     do-thing-two *          ---  stx   st-    --
  -                    cli *                   stx  stx   st-    --

  Error 107: Missing components in the do-thing-one-via-cli project for these interfaces: maybe-depended-upon
test I cannot get to work under any invocation:
shared-int-example$ test
  Error 107: Missing components in the do-thing-one-via-cli project for these interfaces: maybe-depended-upon
shared-int-example$ test +
  Error 107: Missing components in the development project for these interfaces: shared-interface
  Error 107: Missing components in the do-thing-one-via-cli project for these interfaces: maybe-depended-upon
shared-int-example$ test +default
  Error 107: Missing components in the do-thing-one-via-cli project for these interfaces: maybe-depended-upon
shared-int-example$ test +dt2
  Error 107: Missing components in the do-thing-one-via-cli project for these interfaces: maybe-depended-upon

seancorfield 2024-09-23T20:49:17.647959Z

I see the same behavior locally with that repo... but I can't see anything obviously wrong right now...

2024-09-23T20:52:18.015419Z

😞 Welp, thanks for looking just the same - the help is appreciated regardless.

seancorfield 2024-09-23T21:20:26.246249Z

I figured it out @awebneck! You're using an old version of Polylith. Update it to 0.2.21 and it will work (modulo a couple of incorrect names in the files).

seancorfield 2024-09-23T21:21:10.401009Z

That's why I couldn't see anything wrong -- there isn't anything wrong, but you're hitting a bug in Polylith 0.2.19 that was fixed in 0.2.20.

seancorfield 2024-09-23T21:23:52.966359Z

Your maybe-depended-upon component has `def` instead of `defn` in both interface and core. You do-thing-* tests both refer to `.do-thing-*.` in the required ns instead of `.shared-interface.`. But with those two fixes, all the tests pass on 0.2.21.

2024-09-23T21:44:37.933079Z

@seancorfield aw, I knew it was going to be something doofy. Thank you!