juxt

onetom 2020-02-18T04:26:44.020100Z

im trying to use juxt/clip based on the docs, i was expecting that i will be able to use this in the :post-start expression, since it's receiving an implicit target, but it seems not to be the case:

(clip/start {:components {:a {:start 1}
                            :b {:start 2 
                                :post-start `(prn this (clip/ref :a))}}})
am i doing something wrong? what's the simplest way to get access to that implicit parameter? in other words, how can i explicitly refer to the implicit parameter in the :post-start expression?

dominicm 2020-02-18T08:24:34.026400Z

You should be able to, definitely. Lemme refresh my memory, one sec :)

dominicm 2020-02-18T08:28:58.026600Z

The code for this is in the post start function

dominicm 2020-02-18T08:29:29.026800Z

Oh, is it because you're using backtick? And you're getting a namespaced this?

onetom 2020-02-18T09:02:45.029200Z

ok, so how should this situation look like then?

dominicm 2020-02-18T09:24:26.029400Z

In the exact example above, you could use a single quote instead.

👍 1
onetom 2020-02-18T04:30:35.023700Z

now that im asking, i came up with this:

(clip/start {:components {:a {:start 1}
                            :b {:start 2 
                                :post-start `(prn (clip/ref :b) (clip/ref :a))}}})
while it works, im a bit concerned, because post-start is described as being run before the component is passed in to other components where its clip/refered. im wondering if it just works by accident or not? it would be good if the docs mention such a use-case or have some tests for it at least. what i was trying to achieve with this is to have a datomic seed data transaction, where the seed data (which is the datomic schema for new) is provided as a component too

dominicm 2020-02-18T08:31:31.027Z

I'm surprised this works. I'm using tarjans algorithm which I guess doesn't care about this? I wouldn't expect it to keep working forever if I changed the way the environment works or something.

👍 1
onetom 2020-02-18T07:46:13.026300Z

would it make sense to support something like this:

(with-open [sys (clip/start sys-config)]
  (work-with sys)
  ; exception happens
  ...)
and the system is closed for sure. it feels like it would be a useful construct while developing a system config, which has a webserver in it for example...

dominicm 2020-02-18T08:32:30.027200Z

That's an interesting idea. One problem is that I'd have to return an object so I could extend it to Closeable. One option is a with-system macro? What do you think?

onetom 2020-02-18T08:34:44.027400Z

for now i think i will just make something like this with-system: http://pedestal.io/guides/pedestal-with-component#_testing

onetom 2020-02-18T08:35:34.027600Z

Isn't the PersistentHashMap and object already?

onetom 2020-02-18T08:38:03.027800Z

but with-open is not the most intuitive name anyway, so probably a macro is better. it could be clip/with or clip/let ? and just keep the let-style options, so cursive can recognize it as a let

onetom 2020-02-18T08:40:02.028Z

might even make sense to allow creating multiple systems, so you can test how they interact, without spawning them in separate processes... i remember i did something like this before. created 2 systems but reused the same database in them.

dominicm 2020-02-18T08:53:33.028200Z

I don't own PersistentHashMap, so I shouldn't extend it to an interface I don't own, Closeable

onetom 2020-02-18T08:56:30.028700Z

sure, i was hoping that on a per-instance basis it's possible to sneak in some .close method. after all with-open doesn't care about the object types either, just tries to call .close on them..

onetom 2020-02-18T08:56:48.028900Z

btw, this implementation seems to work at 1st glance:

(defmacro with
  [[bound-var binding-expr] & body]
  `(let [system-config# ~binding-expr
         ~bound-var (clip/start system-config#)]
     (try
       ~@body
       (finally
         (clip/stop system-config# ~bound-var)))))

dominicm 2020-02-18T11:55:16.029600Z

I don't know of any way to do that unfortunately. I'm not sure we should even if we could.

dominicm 2020-02-18T11:55:44.029800Z

That macro looks good! If you wanted multiple bindings to be possible, maybe you could make it recursive?

onetom 2020-02-19T04:33:26.030100Z

i just tried to integrate it into a test suite as a before-each hook and im not sure if it's a good idea to make it recursive, because of that implicit clip/start. that would mean u can only start systems using this with construct, but intuitively i wrote the following code first:

(declare ^:dynamic q)

(use-fixtures
  :each (fn [test-case]
          (sys/with [sys {:components (merge sys/datomic sys/graphql)}
                     {:keys [graphql/schema-fn]} sys
                     schema (schema-fn)]
            (binding [q (fn [query] (gql/execute schema query {} {}))]
              (test-case)))))

onetom 2020-02-19T04:37:16.030300Z

which wouldn't work, even if with would have handled multiple bindings... so currently i have this instead:

(use-fixtures
  :each (fn [test-case]
          (sys/with [sys {:components (merge sys/datomic sys/graphql)}]
            (let [{:keys [graphql/schema-fn]} sys
                  schema (schema-fn)]
              (binding [q (fn [query] (gql/execute schema query {} {}))]
                (test-case))))))
which i think is not too bad... it raises the question though, how would u expose an api for tests, which are specialised for or tied to a specific system instance? it can help immensely to write concise tests, eg:
(deftest query-test
  (expect {:data {:txns [{:id "x" :tags ["tag-1"]}]}}
          (q "{ txns { id tags } }")))

onetom 2020-02-19T07:03:05.030500Z

For the record, before I started using clip, I had a macro, like this:

(defmacro in-tmp-db [& body]
  `(let [db-uri# (str (gensym "datomic:<mem://test>-"))]
     (d/create-database db-uri#)
     (let [~'conn (d/connect db-uri#)
           ~'tx! (fn [&amp; ~'args] (apply d/transact ~'conn ~'args))
           ~'db! (fn [] (d/db ~'conn))
           ~'entity (fn [&amp; ~'args] (apply d/entity (~'db!) ~'args))
           ~'entid (fn [&amp; ~'args] (apply d/entid (~'db!) ~'args))
           ~'pull (fn [&amp; ~'args] (apply d/pull (~'db!) ~'args))]
       (try
         @(~'tx! (datomic/schema))
         ~@body
         (finally
           (d/release ~'conn)
           (d/delete-database db-uri#))))))
so my tests looked something like this:
(deftest some-test
  (expecting "something"
    (in-tmp-db
      (some.datomic/transaction! conn {:entity "map"})
      (expect #{"data-1" "data-2"} (some.datomic/query (db!) [:lookup "ref"])))))

dominicm 2020-02-19T08:34:56.030700Z

I don't understand the question, sorry