Fork me on GitHub
#duct
<
2019-11-06
>
weavejester01:11:30

In theory that should work…

weavejester01:11:34

Ah, I see the problem, @ccann. The :duct.core/requires key wasn’t designed to be used outside of Duct core, so it’s being overwritten. I need to create a proper public key for requirements.

weavejester01:11:19

Try creating a key: :. Since it won’t be automatically removed, you can make it derive from :duct/const to have Integrant ignore it.

weavejester01:11:39

I’ll create a proper requires key that’s designed for public use.

weavejester01:11:58

In the next Duct version. Feel free to add an issue to remind me.

rickmoynihan10:11:08

@weavejester: I think I ran into the same problem as @ccann after our chat yesterday; but I’d tried it in our app rather than a minimal test case. However I’ve now got it failing in a minimal test case; and it seems to fail even with the solution you’re suggesting. Here’s my minimal example:

(require '[duct.core :as duct])

  (derive :example.profile/b-one :duct/profile)
  (derive :example.profile/a-two :duct/profile)

  (derive : :duct/const)

  (duct/prep-config {:example.profile/b-one {:a {:replace-me :init}
                                             :b [:b-one]}

                     :example.profile/a-two {:a {:replace-me :replaced}
                                             :b [:b-two]
                                             :c [:c-two]
                                             : (ig/ref :example.profile/b-one)}}
                    #{:example.profile/b-one :example.profile/a-two})

rickmoynihan10:11:40

The profiles are named b-one a-two to guarantee the sort ordering is the opposite to the dependency order; and I’d like to see the order be [one two] (where two) takes precedence. I expect to see the result contain {:a {replace-me :replaced} rather than {:a replace-me :init} which is what I get.

rickmoynihan10:11:03

complete result output is:

{:a {:replace-me :init},
 :b [:b-two :b-one],
 :c [:c-two],
 : {:key :example.profile/b-one}}

rickmoynihan10:11:19

Did I understand correctly what you meant by derive your own requires key?

rickmoynihan10:11:02

It looks like duct/prep-config doesn’t walk in dependency order. duct/build-config seems to yield the same too.

rickmoynihan10:11:10

hmmm something must be up; possibly with my example… build-config calls ig/init so not sure why it’s not obeying the dependency order.

rickmoynihan10:11:57

the result of ig/prep inside build-config is:

#:example.profile{:b-one
                  {:a {:replace-me :init},
                   :b [:b-one],
                   :duct.core/requires {:key :duct.profile/base}},
                  :a-two
                  {:a {:replace-me :replaced},
                   :b [:b-two],
                   :c [:c-two],
                   : {:key :example.profile/b-one},
                   :duct.core/requires {:key :duct.profile/base}}}

rickmoynihan11:11:40

Ok, I think I see what the problem is. When we call fold-modules we’ve forgotten the dependencies between profiles/modules. So the functions then evaluate in key-comparator order 😞

rickmoynihan11:11:32

We lose that info at ig/init in build-config. So to summarise I think the profiles are initialised in the right order; but aren’t folded/applied to the meta-system in the right order in fold-modules.

weavejester14:11:52

@rickmoynihan The dependencies should be held in the metadata of the system, so when ig/fold is called in fold-modules, the dependency order should be correct. I’ll look into this and try to figure out what’s going wrong, but I won’t have much time until Sunday. Feel free to open an issue to remind me.

rickmoynihan14:11:52

ahh thanks for that James, that’s helpful… I’ll take a look and try and see if I can see what’s going on… I’ll open an issue when I’ve done a bit more digging for sure :thumbsup:

weavejester14:11:55

Oh, and while you’re here, just to get some feedback - do you use any Duct modules, or just profiles and components?

rickmoynihan14:11:28

Yeah we use the following:

:duct.module/logging {}
 :duct.module.web/api {}
 :duct.module.web/site {}

 :app.module.project/inject-all {} 
The final one is the only module we have that is ours at the minute… it essentially injects an identifier/slug for the project into every component.

rickmoynihan14:11:07

Though I don’t think any of the above are configured through the module config… they’re just used to bring in the defaults; and then we override the bits we need but at a component level, rather than module level.

rickmoynihan14:11:34

ataraxy might use the module config… though no I think even with that we strayed out of the easy config, and use the component layer to configure it.

rickmoynihan14:11:09

yeah all ataraxy keys are configured through :duct.router/ataraxy

weavejester14:11:43

Thanks; that’s pretty useful.

rickmoynihan15:11:30

I think with ataraxy we moved away from the module config primarily because it enforced a convention of having handlers in a handler namespace. And we prefer to have a project structured by feature rather than layer. I think we’ve spoken about that before.

rickmoynihan15:11:39

@weavejester Ok I think I see the problem now… Which is I think essentially what you said earlier about :duct.core/requires not being designed to be used outside of duct… however the reason that creating your own : key doesn’t work is because it’s not the requires key that’s special; but anything deriving deriving from :duct/profile gets all of its refs deactivated and made into InertRef’s.

rickmoynihan15:11:38

This happens in the postwalk here:

rickmoynihan15:11:23

I’ll write this up on an issue after I’ve got some (late) lunch.

weavejester15:11:52

Ah, that makes sense.

weavejester15:11:30

Because the refs need to be merged as well, and not resolved right away.

weavejester19:11:31

Thanks for the writeup, @rickmoynihan. I’m interested in your opinions about the possible solution I outlined.

👀 4